From 5a005ef586b9000810156a961b9622c903dce988 Mon Sep 17 00:00:00 2001 From: kramm Date: Sat, 8 Sep 2007 17:59:44 +0000 Subject: [PATCH] removed outdated files --- pdf2swf/HOWTO_pdf2swf | 112 - pdf2swf/pdf2swf.1 | 77 - pdf2swf/ttf2pt1/.cvsignore | 1 - pdf2swf/ttf2pt1/COPYRIGHT | 83 - pdf2swf/ttf2pt1/Makefile.in | 34 - pdf2swf/ttf2pt1/bdf.c | 660 ---- pdf2swf/ttf2pt1/bitmap.c | 2458 ------------ pdf2swf/ttf2pt1/byteorder.h | 24 - pdf2swf/ttf2pt1/ft.c | 653 ---- pdf2swf/ttf2pt1/global.h | 171 - pdf2swf/ttf2pt1/pt1.c | 7372 ------------------------------------ pdf2swf/ttf2pt1/pt1.h | 257 -- pdf2swf/ttf2pt1/runt1asm.c | 61 - pdf2swf/ttf2pt1/t1asm.c | 617 --- pdf2swf/ttf2pt1/ttf.c | 1480 -------- pdf2swf/ttf2pt1/ttf.h | 172 - pdf2swf/ttf2pt1/ttf2pt1.c | 2570 ------------- pdf2swf/ttf2pt1/ttf2pt1.h | 15 - pdf2swf/ttf2pt1/version.h | 7 - pdf2swf/ttf2pt1/win_missing.h | 59 - pdf2swf/xpdf/.cvsignore | 1 - pdf2swf/xpdf/Annot.cc | 315 -- pdf2swf/xpdf/Annot.h | 73 - pdf2swf/xpdf/Array.cc | 73 - pdf2swf/xpdf/Array.h | 58 - pdf2swf/xpdf/BuiltinFont.cc | 65 - pdf2swf/xpdf/BuiltinFont.h | 57 - pdf2swf/xpdf/BuiltinFontTables.cc | 4284 --------------------- pdf2swf/xpdf/BuiltinFontTables.h | 23 - pdf2swf/xpdf/CMap.cc | 408 -- pdf2swf/xpdf/CMap.h | 102 - pdf2swf/xpdf/Catalog.cc | 353 -- pdf2swf/xpdf/Catalog.h | 92 - pdf2swf/xpdf/CharCodeToUnicode.cc | 540 --- pdf2swf/xpdf/CharCodeToUnicode.h | 117 - pdf2swf/xpdf/CharTypes.h | 24 - pdf2swf/xpdf/Decrypt.cc | 411 -- pdf2swf/xpdf/Decrypt.h | 63 - pdf2swf/xpdf/Dict.cc | 95 - pdf2swf/xpdf/Dict.h | 77 - pdf2swf/xpdf/Error.cc | 38 - pdf2swf/xpdf/Error.h | 23 - pdf2swf/xpdf/ErrorCodes.h | 36 - pdf2swf/xpdf/FoFiBase.cc | 156 - pdf2swf/xpdf/FoFiBase.h | 57 - pdf2swf/xpdf/FoFiEncodings.cc | 994 ----- pdf2swf/xpdf/FoFiEncodings.h | 36 - pdf2swf/xpdf/FoFiTrueType.cc | 1753 --------- pdf2swf/xpdf/FoFiTrueType.h | 140 - pdf2swf/xpdf/FoFiType1.cc | 212 -- pdf2swf/xpdf/FoFiType1.h | 59 - pdf2swf/xpdf/FoFiType1C.cc | 2484 ------------ pdf2swf/xpdf/FoFiType1C.h | 232 -- pdf2swf/xpdf/FontEncodingTables.cc | 1824 --------- pdf2swf/xpdf/FontEncodingTables.h | 20 - pdf2swf/xpdf/Function.cc | 1535 -------- pdf2swf/xpdf/Function.h | 225 -- pdf2swf/xpdf/GHash.cc | 380 -- pdf2swf/xpdf/GHash.h | 78 - pdf2swf/xpdf/GList.cc | 97 - pdf2swf/xpdf/GList.h | 96 - pdf2swf/xpdf/GMutex.h | 49 - pdf2swf/xpdf/GString.cc | 319 -- pdf2swf/xpdf/GString.h | 97 - pdf2swf/xpdf/Gfx.cc | 3596 ------------------ pdf2swf/xpdf/Gfx.h | 293 -- pdf2swf/xpdf/GfxFont.cc | 1546 -------- pdf2swf/xpdf/GfxFont.h | 315 -- pdf2swf/xpdf/GfxState.cc | 3961 ------------------- pdf2swf/xpdf/GfxState.h | 1206 ------ pdf2swf/xpdf/GlobalParams.cc | 2057 ---------- pdf2swf/xpdf/GlobalParams.h | 336 -- pdf2swf/xpdf/JArithmeticDecoder.cc | 322 -- pdf2swf/xpdf/JArithmeticDecoder.h | 109 - pdf2swf/xpdf/JBIG2Stream.cc | 3386 ----------------- pdf2swf/xpdf/JBIG2Stream.h | 143 - pdf2swf/xpdf/JPXStream.cc | 2953 --------------- pdf2swf/xpdf/JPXStream.h | 349 -- pdf2swf/xpdf/Lexer.cc | 493 --- pdf2swf/xpdf/Lexer.h | 80 - pdf2swf/xpdf/Link.cc | 905 ----- pdf2swf/xpdf/Link.h | 409 -- pdf2swf/xpdf/Makefile.in | 119 - pdf2swf/xpdf/NameToCharCode.cc | 116 - pdf2swf/xpdf/NameToCharCode.h | 42 - pdf2swf/xpdf/NameToUnicodeTable.h | 1097 ------ pdf2swf/xpdf/Object.cc | 231 -- pdf2swf/xpdf/Object.h | 303 -- pdf2swf/xpdf/Outline.cc | 151 - pdf2swf/xpdf/Outline.h | 76 - pdf2swf/xpdf/OutputDev.cc | 129 - pdf2swf/xpdf/OutputDev.h | 205 - pdf2swf/xpdf/PDFDoc.cc | 431 --- pdf2swf/xpdf/PDFDoc.h | 182 - pdf2swf/xpdf/PDFDocEncoding.cc | 44 - pdf2swf/xpdf/PDFDocEncoding.h | 16 - pdf2swf/xpdf/PSTokenizer.cc | 135 - pdf2swf/xpdf/PSTokenizer.h | 41 - pdf2swf/xpdf/Page.cc | 367 -- pdf2swf/xpdf/Page.h | 175 - pdf2swf/xpdf/Parser.cc | 214 -- pdf2swf/xpdf/Parser.h | 56 - pdf2swf/xpdf/SecurityHandler.cc | 376 -- pdf2swf/xpdf/SecurityHandler.h | 155 - pdf2swf/xpdf/Stream-CCITT.h | 459 --- pdf2swf/xpdf/Stream.cc | 4572 ---------------------- pdf2swf/xpdf/Stream.h | 846 ----- pdf2swf/xpdf/UTF8.h | 56 - pdf2swf/xpdf/UnicodeMap.cc | 293 -- pdf2swf/xpdf/UnicodeMap.h | 123 - pdf2swf/xpdf/UnicodeMapTables.h | 361 -- pdf2swf/xpdf/XRef.cc | 888 ----- pdf2swf/xpdf/XRef.h | 131 - pdf2swf/xpdf/aconf.h | 24 - pdf2swf/xpdf/cmyk.cc | 661 ---- pdf2swf/xpdf/cmyk.h | 4 - pdf2swf/xpdf/config.h | 112 - pdf2swf/xpdf/gfile.cc | 705 ---- pdf2swf/xpdf/gfile.h | 138 - pdf2swf/xpdf/gmem.c | 229 -- pdf2swf/xpdf/gmem.h | 62 - pdf2swf/xpdf/gtypes.h | 29 - 122 files changed, 71867 deletions(-) delete mode 100644 pdf2swf/HOWTO_pdf2swf delete mode 100644 pdf2swf/pdf2swf.1 delete mode 100644 pdf2swf/ttf2pt1/.cvsignore delete mode 100644 pdf2swf/ttf2pt1/COPYRIGHT delete mode 100644 pdf2swf/ttf2pt1/Makefile.in delete mode 100644 pdf2swf/ttf2pt1/bdf.c delete mode 100644 pdf2swf/ttf2pt1/bitmap.c delete mode 100644 pdf2swf/ttf2pt1/byteorder.h delete mode 100644 pdf2swf/ttf2pt1/ft.c delete mode 100644 pdf2swf/ttf2pt1/global.h delete mode 100644 pdf2swf/ttf2pt1/pt1.c delete mode 100644 pdf2swf/ttf2pt1/pt1.h delete mode 100644 pdf2swf/ttf2pt1/runt1asm.c delete mode 100644 pdf2swf/ttf2pt1/t1asm.c delete mode 100644 pdf2swf/ttf2pt1/ttf.c delete mode 100644 pdf2swf/ttf2pt1/ttf.h delete mode 100644 pdf2swf/ttf2pt1/ttf2pt1.c delete mode 100644 pdf2swf/ttf2pt1/ttf2pt1.h delete mode 100644 pdf2swf/ttf2pt1/version.h delete mode 100644 pdf2swf/ttf2pt1/win_missing.h delete mode 100644 pdf2swf/xpdf/.cvsignore delete mode 100644 pdf2swf/xpdf/Annot.cc delete mode 100644 pdf2swf/xpdf/Annot.h delete mode 100644 pdf2swf/xpdf/Array.cc delete mode 100644 pdf2swf/xpdf/Array.h delete mode 100644 pdf2swf/xpdf/BuiltinFont.cc delete mode 100644 pdf2swf/xpdf/BuiltinFont.h delete mode 100644 pdf2swf/xpdf/BuiltinFontTables.cc delete mode 100644 pdf2swf/xpdf/BuiltinFontTables.h delete mode 100644 pdf2swf/xpdf/CMap.cc delete mode 100644 pdf2swf/xpdf/CMap.h delete mode 100644 pdf2swf/xpdf/Catalog.cc delete mode 100644 pdf2swf/xpdf/Catalog.h delete mode 100644 pdf2swf/xpdf/CharCodeToUnicode.cc delete mode 100644 pdf2swf/xpdf/CharCodeToUnicode.h delete mode 100644 pdf2swf/xpdf/CharTypes.h delete mode 100644 pdf2swf/xpdf/Decrypt.cc delete mode 100644 pdf2swf/xpdf/Decrypt.h delete mode 100644 pdf2swf/xpdf/Dict.cc delete mode 100644 pdf2swf/xpdf/Dict.h delete mode 100644 pdf2swf/xpdf/Error.cc delete mode 100644 pdf2swf/xpdf/Error.h delete mode 100644 pdf2swf/xpdf/ErrorCodes.h delete mode 100644 pdf2swf/xpdf/FoFiBase.cc delete mode 100644 pdf2swf/xpdf/FoFiBase.h delete mode 100644 pdf2swf/xpdf/FoFiEncodings.cc delete mode 100644 pdf2swf/xpdf/FoFiEncodings.h delete mode 100644 pdf2swf/xpdf/FoFiTrueType.cc delete mode 100644 pdf2swf/xpdf/FoFiTrueType.h delete mode 100644 pdf2swf/xpdf/FoFiType1.cc delete mode 100644 pdf2swf/xpdf/FoFiType1.h delete mode 100644 pdf2swf/xpdf/FoFiType1C.cc delete mode 100644 pdf2swf/xpdf/FoFiType1C.h delete mode 100644 pdf2swf/xpdf/FontEncodingTables.cc delete mode 100644 pdf2swf/xpdf/FontEncodingTables.h delete mode 100644 pdf2swf/xpdf/Function.cc delete mode 100644 pdf2swf/xpdf/Function.h delete mode 100644 pdf2swf/xpdf/GHash.cc delete mode 100644 pdf2swf/xpdf/GHash.h delete mode 100644 pdf2swf/xpdf/GList.cc delete mode 100644 pdf2swf/xpdf/GList.h delete mode 100644 pdf2swf/xpdf/GMutex.h delete mode 100644 pdf2swf/xpdf/GString.cc delete mode 100644 pdf2swf/xpdf/GString.h delete mode 100644 pdf2swf/xpdf/Gfx.cc delete mode 100644 pdf2swf/xpdf/Gfx.h delete mode 100644 pdf2swf/xpdf/GfxFont.cc delete mode 100644 pdf2swf/xpdf/GfxFont.h delete mode 100644 pdf2swf/xpdf/GfxState.cc delete mode 100644 pdf2swf/xpdf/GfxState.h delete mode 100644 pdf2swf/xpdf/GlobalParams.cc delete mode 100644 pdf2swf/xpdf/GlobalParams.h delete mode 100644 pdf2swf/xpdf/JArithmeticDecoder.cc delete mode 100644 pdf2swf/xpdf/JArithmeticDecoder.h delete mode 100644 pdf2swf/xpdf/JBIG2Stream.cc delete mode 100644 pdf2swf/xpdf/JBIG2Stream.h delete mode 100644 pdf2swf/xpdf/JPXStream.cc delete mode 100644 pdf2swf/xpdf/JPXStream.h delete mode 100644 pdf2swf/xpdf/Lexer.cc delete mode 100644 pdf2swf/xpdf/Lexer.h delete mode 100644 pdf2swf/xpdf/Link.cc delete mode 100644 pdf2swf/xpdf/Link.h delete mode 100644 pdf2swf/xpdf/Makefile.in delete mode 100644 pdf2swf/xpdf/NameToCharCode.cc delete mode 100644 pdf2swf/xpdf/NameToCharCode.h delete mode 100644 pdf2swf/xpdf/NameToUnicodeTable.h delete mode 100644 pdf2swf/xpdf/Object.cc delete mode 100644 pdf2swf/xpdf/Object.h delete mode 100644 pdf2swf/xpdf/Outline.cc delete mode 100644 pdf2swf/xpdf/Outline.h delete mode 100644 pdf2swf/xpdf/OutputDev.cc delete mode 100644 pdf2swf/xpdf/OutputDev.h delete mode 100644 pdf2swf/xpdf/PDFDoc.cc delete mode 100644 pdf2swf/xpdf/PDFDoc.h delete mode 100644 pdf2swf/xpdf/PDFDocEncoding.cc delete mode 100644 pdf2swf/xpdf/PDFDocEncoding.h delete mode 100644 pdf2swf/xpdf/PSTokenizer.cc delete mode 100644 pdf2swf/xpdf/PSTokenizer.h delete mode 100644 pdf2swf/xpdf/Page.cc delete mode 100644 pdf2swf/xpdf/Page.h delete mode 100644 pdf2swf/xpdf/Parser.cc delete mode 100644 pdf2swf/xpdf/Parser.h delete mode 100644 pdf2swf/xpdf/SecurityHandler.cc delete mode 100644 pdf2swf/xpdf/SecurityHandler.h delete mode 100644 pdf2swf/xpdf/Stream-CCITT.h delete mode 100644 pdf2swf/xpdf/Stream.cc delete mode 100644 pdf2swf/xpdf/Stream.h delete mode 100644 pdf2swf/xpdf/UTF8.h delete mode 100644 pdf2swf/xpdf/UnicodeMap.cc delete mode 100644 pdf2swf/xpdf/UnicodeMap.h delete mode 100644 pdf2swf/xpdf/UnicodeMapTables.h delete mode 100644 pdf2swf/xpdf/XRef.cc delete mode 100644 pdf2swf/xpdf/XRef.h delete mode 100644 pdf2swf/xpdf/aconf.h delete mode 100644 pdf2swf/xpdf/cmyk.cc delete mode 100644 pdf2swf/xpdf/cmyk.h delete mode 100644 pdf2swf/xpdf/config.h delete mode 100644 pdf2swf/xpdf/gfile.cc delete mode 100644 pdf2swf/xpdf/gfile.h delete mode 100644 pdf2swf/xpdf/gmem.c delete mode 100644 pdf2swf/xpdf/gmem.h delete mode 100644 pdf2swf/xpdf/gtypes.h diff --git a/pdf2swf/HOWTO_pdf2swf b/pdf2swf/HOWTO_pdf2swf deleted file mode 100644 index e85b895..0000000 --- a/pdf2swf/HOWTO_pdf2swf +++ /dev/null @@ -1,112 +0,0 @@ -Notice - - This documentation is a little outdated. As with swftools-0.2.1 and - above, you can simply do - pdf2swf -bl -o document.swf document.pdf - to link viewer and preloader. - However, the Steps below are still valid for jpeg2swf. - -Step 1: Converting the documents - - Suppose you have an arbitrary pdf file, "document.pdf". - Call: - pdf2swf -o tmp.swf document.pdf - Now, tmp.swf is a Flash Movie generated from document.pdf. Movie means - that there are no navigation elements whatsoever. Just frames which - get displayed one by one, at a rate of approx. 1/2 frames/second. How - to make document browsable is explained below. - (You can do the same things described below with jpeg files. Simply - use - jpeg2swf -o tmp.swf pic1.jpeg pic2.jpeg ... - and read on) - -Step 2: Linking a viewer - - Just take a viewer of your choice (e.g. [1]SimpleViewer.swf ) and put - it in the same directory where you entered the commands above. - Now call: - swfcombine -o flashfile.swf SimpleViewer.swf viewport=tmp.swf - Now, 'flashfile.swf' is "browsable", i.e. there are some buttons in it - for turning pages. - -Step 3: Linking a Preloader - - Depending on the size of your PDFs/SWFs, you may want to have some - kind of loading animation displayed while the browser is busy getting - the actual document. Assuming you have some file like flashfile.swf - above, you furthermore need the file [2]PreLoader.swf and an arbirtary - loading animation of your choice. (To get started, try [3]loading.swf, - or just convert a "Loading" JPEG picture to swf (jpeg2swf -o - loading.swf picture.jpg)) Now use - swfcombine -o flashfile.swf PreLoader.swf loader=loading.swf - movie=flashfile.swf - (Most loaders are smaller than the document they load. They usually - need some centering so they appear in the middle of the page to be - displayed, not in the upper left corner. Replace the above command - with e.g. - swfcombine -o flashfile.swf PreLoader.swf -x 3000 -y 3000 - loader=loading.swf movie=flashfile.swf - and try playing around with the values after -x and -y) - -Step 4: Correcting the size and framerate - - Sometimes, the bounding box of the generated flash file is not - correct. This happens because when linking a viewer or preloader to - the SWFs, the new dimensions are those of the PreLoader and Viewer - templates, and not those of your pdf or jpeg files. To fix this, use - swfcombine --dummy `swfdump -XY tmp.swf` flashfile.swf -o - flashfile.swf - (tmp.swf is your 'original' swf, generated like above) - You may also want to adjust the framerate of the movie to that of the - preloader. (As the preloader is usually the only animated part of e.g. - pdf viewers) - Use: - swfcombine --dummy `swfdump -r loading.swf` flashfile.swf -o - flashfile.swf - -Step 5: Embedding the SWF into a html page - - Usually, one wants to put the generated SWFs on his web page. To do - so, you have to embed the SWF file into html. If you don't know how to - embed SWFs into html pages, it's explained at - [4]http://www.macromedia.com/support/flash/ts/documents/tn4150.html . - Also, you can simply type - swfdump --html flashfile.swf - and insert the output into your html document - -Appendix A: Creating your own Viewers - - If you know about Flash, and you want to substitute SimpleViewer from - above with something more sophisticated, follow these rules: - 1. There has to be some rectangle (Movieclip, whatever... ) in your - Viewer, named "viewport". (This name is used to reference the object - when using swfcombine for merging it with the converted pdfs) - 2. The First frame should contain an actionscript "Stop" instruction. - (Otherwise, the browsing buttons turn pages, but pages get also - automatically turned every few seconds) - 3. Browsing buttons next to the rectangle (which turn pages in the - shown pdf) should trigger some Actionsscript events, like - - SetTarget "viewport" - NextFrame - SetTarget "" - - to set the frame in the to-be-replaced rectangle. (It will be replaced - with a MovieClip, therefore a SetTarget is neccessary) - It's important that the Target Name ist "viewport", not "/viewport", - as the Movie will get inserted into a Movieclip (Sprite). - _________________________________________________________________ - - [5]Back to the SWFTools Project page - -References - - Visible links - 1. http://www.quiss.org/swftools/SimpleViewer.swf - 2. http://www.quiss.org/swftools/PreLoader.swf - 3. http://www.quiss.org/swftools/loading.swf - 4. http://www.macromedia.com/support/flash/ts/documents/tn4150.html - 5. http://www.quiss.org/swftools - - - diff --git a/pdf2swf/pdf2swf.1 b/pdf2swf/pdf2swf.1 deleted file mode 100644 index ed641b8..0000000 --- a/pdf2swf/pdf2swf.1 +++ /dev/null @@ -1,77 +0,0 @@ -.TH pdf2swf "1" "January 2003" "pdf2swf" "swftools" -.SH NAME -pdf2swf - convert PDF files into SWF -.SH Synopsis -.B pdf2swf -[\fIoptions\fR] \fIfile.pdf\fR [-o \fIfile.swf\fR] -.SH DESCRIPTION -This tools converts Acrobat PDF files into Flash SWF Animation -files. -.SH OPTIONS -.TP -\fB\-h\fR, \fB\-\-help\fR -Print short help message and exit -.TP -\fB\-V\fR, \fB\-\-version\fR -Print version info and exit -.TP -\fB\-p\fR, \fB\-\-pages\fR \fIrange\fR -Convert only pages in \fIrange\fR with \fIrange\fR e.g. 1-20 or 1,4,6,9-11 or -3-5,10-12 -.TP -\fB\-v\fR, \fB\-\-verbose\fR -Be verbose. Use more than one -v for greater effect. -.TP -\fB\-z\fR, \fB\-\-zlib\fR -Use Flash 6 (MX) zlib compression. -\fBThe resulting SWF will not be playable in browsers with Flash Plugins 5 and below!\fR -.TP -\fB\-i\fR, \fB\-\-ignore\fR -Allows pdf2swf to change the draw order of the pdf. This may make the generated -SWF files a little bit smaller, but it may also cause the images in the pdf to look funny. -.TP -\fB\-j\fR, \fB\-\-jpegquality\fR \fIquality\fR -Set quality of embedded jpeg pictures to \fIquality\fR. 0 is worst (small), 100 is best (big). (default:85) -.TP -\fB\-s\fR, \fB\-\-set\fR \fIparam=value\fR -Set a SWF encoder specific parameter. See pdf2swf \-\-help for more information. -.TP -\fB\-w\fR, \fB\-\-samewindow\fR -When converting pdf hyperlinks, don't make the links open a new window when clicked on, -but open the page they point to in the window the SWF is displayed. -.TP -\fB\-t\fR, \fB\-\-stop\fR -Insert a stop() command in each page. The resulting SWF file will not turn pages automatically. -.TP -\fB\-T\fR, \fB\-\-flashversion\fR \fInum\fR -Set Flash Version in the SWF header to \fInum\fR. -.TP -\fB\-F\fR, \fB\-\-fontdir\fR \fIdirectory\fR -Add \fIdirectory\fR to the font search path. -.TP -\fB\-b\fR, \fB\-\-defaultviewer\fR -Link a standard viewer to the swf file. Therefore the swf file will be "browseable", i.e. -display some buttons for turning pages. -The viewer swf to be used is determined by a symlink named "default_viewer.swf" in -the swftools data directory. -.TP -\fB\-l\fR, \fB\-\-defaultloader\fR -Link a standard preloader to the swf file which will be displayed while the main swf is -loading. -The loader swf to be used is determined by a symlink named "default_loader.swf" in -the swftools data directory. -.TP -\fB\-B\fR, \fB\-\-viewer\fR \fIfilename\fR -Link viewer \fIfilename\fR to the swf file. See http://www.quiss.org/swftools/pdf2swf_usage.html -for information on how to create your own viewers. -.TP -\fB\-L\fR, \fB\-\-loader\fR \fIfilename\fR -Link preloader \fIfilename\fR to the swf file, where \fIfilename\fR -is an arbitrary swf animation. -.SH BUGS -.PP -dashed lines don't work. - -.SH AUTHOR - -Matthias Kramm diff --git a/pdf2swf/ttf2pt1/.cvsignore b/pdf2swf/ttf2pt1/.cvsignore deleted file mode 100644 index f3c7a7c..0000000 --- a/pdf2swf/ttf2pt1/.cvsignore +++ /dev/null @@ -1 +0,0 @@ -Makefile diff --git a/pdf2swf/ttf2pt1/COPYRIGHT b/pdf2swf/ttf2pt1/COPYRIGHT deleted file mode 100644 index 6e130fb..0000000 --- a/pdf2swf/ttf2pt1/COPYRIGHT +++ /dev/null @@ -1,83 +0,0 @@ -The following copyright notice applies to all the files provided -in this distribution unless explicitly noted otherwise -(the most notable exception being t1asm.c). - - Copyright (c) 1997-2001 by the AUTHORS: - Andrew Weeks - Frank M. Siegert - Mark Heath - Thomas Henlich - Sergey Babkin , - Turgut Uyar - Rihardas Hepas - Szalay Tamas - Johan Vromans - Petr Titera - Lei Wang - Chen Xiangyang - Zvezdan Petkovic - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. All advertising materials mentioning features or use of this software - must display the following acknowledgement: - This product includes software developed by the TTF2PT1 Project - and its contributors. - - THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND - ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - SUCH DAMAGE. - -For the approximate list of the AUTHORS' responsibilities see the -project history. - -Other contributions to the project are: - -Turgut Uyar - The Unicode translation table for the Turkish language. - -Rihardas Hepas - The Unicode translation table for the Baltic languages. - -Szalay Tamas - The Unicode translation table for the Central European languages. - -Johan Vromans - The RPM file. - -Petr Titera - The Unicode map format with names, the forced Unicode option. - -Frank M. Siegert - Port to Windows - -Lei Wang -Chen Xiangyang - Translation maps for Chinese fonts. - -Zvezdan Petkovic - The Unicode translation tables for the Cyrillic alphabet. - -I. Lee Hetherington - The Type1 assembler (from the package 't1utils'), its full copyright - notice: - Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. - Permission is hereby granted to use, modify, and distribute this program - for any purpose provided this copyright notice and the one below remain - intact. - diff --git a/pdf2swf/ttf2pt1/Makefile.in b/pdf2swf/ttf2pt1/Makefile.in deleted file mode 100644 index 430d2ec..0000000 --- a/pdf2swf/ttf2pt1/Makefile.in +++ /dev/null @@ -1,34 +0,0 @@ -top_builddir = ../.. -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -include ../../Makefile.common - -all: libpdf.a - -ttf2pt1_objects = ft.o ttf.o pt1.o ttf2pt1.o t1asm.o bdf.o bitmap.o - -ft.o: ft.c - $(C) -I./ -Wno-parentheses ft.c -o $@ -ttf.o: ttf.c - $(C) -I./ -Wno-parentheses ttf.c -o $@ -pt1.o: pt1.c - $(C) -I./ -Wno-parentheses pt1.c -o $@ -ttf2pt1.o: ttf2pt1.c - $(C) -I./ -Wno-parentheses ttf2pt1.c -o $@ -t1asm.o: t1asm.c - $(C) -I./ -Wno-parentheses t1asm.c -o $@ -bitmap.o: bitmap.c - $(C) -I./ -Wno-parentheses bitmap.c -o $@ -bdf.o: bdf.c - $(C) -I./ -Wno-parentheses bdf.c -o $@ - -libpdf.a: $(ttf2pt1_objects) - $(AR) r ttf2pt1.a $(ttf2pt1_objects) - $(RANLIB) ttf2pt1.a - -install: -uninstall: - -clean: - rm -f *.o *.lo *.a *.la gmon.out - diff --git a/pdf2swf/ttf2pt1/bdf.c b/pdf2swf/ttf2pt1/bdf.c deleted file mode 100644 index cc580ec..0000000 --- a/pdf2swf/ttf2pt1/bdf.c +++ /dev/null @@ -1,660 +0,0 @@ -/* - * The font parser for the BDF files - * - * Copyright (c) 2001 by the TTF2PT1 project - * Copyright (c) 2001 by Sergey Babkin - * - * see COPYRIGHT for the full copyright notice - */ - -#include -#include -#include -#include -#include "pt1.h" -#include "global.h" - -/* prototypes of call entries */ -static void openfont(char *fname, char *arg); -static void closefont( void); -static int getnglyphs ( void); -static int glnames( GLYPH *glyph_list); -static void readglyphs( GLYPH *glyph_list); -static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); -static void fnmetrics( struct font_metrics *fm); -static void glpath( int glyphno, GLYPH *glyph_list); -static void kerning( GLYPH *glyph_list); - -/* globals */ - -/* front-end descriptor */ -struct frontsw bdf_sw = { - /*name*/ "bdf", - /*descr*/ "BDF bitmapped fonts", - /*suffix*/ { "bdf" }, - /*open*/ openfont, - /*close*/ closefont, - /*nglyphs*/ getnglyphs, - /*glnames*/ glnames, - /*glmetrics*/ readglyphs, - /*glenc*/ glenc, - /*fnmetrics*/ fnmetrics, - /*glpath*/ glpath, - /*kerning*/ kerning, -}; - -/* statics */ - -#define MAXLINE 10240 /* maximal line length in the input file */ - -static int lineno; /* line number */ - -#define GETLEN(s) s, (sizeof(s)-1) -#define LENCMP(str, txt) strncmp(str, txt, sizeof(txt)-1) - -static FILE *bdf_file; -static int nglyphs; -static struct font_metrics fmet; - -/* many BDF fonts are of small pixel size, so we better try - * to scale them by an integer to keep the dimensions in - * whole pixels. However if the size is too big and a non- - * integer scaling is needed, we use the standard ttf2pt1's - * scaling abilities. - */ -static int pixel_size; -static int scale; -static int scale_external; - -static char *slant; -static char xlfdname[201]; -static char *spacing; -static char *charset_reg; -static char *charset_enc; -static char *fnwidth; -static int is_unicode = 0; - -/* tempoary storage for returning data to ttf2pt1 later on request */ -static int maxenc = 0; -static int *fontenc; -static GENTRY **glpaths; - -static int got_glyphs = 0; -static GLYPH *glyphs; -static int curgl; - -static int readfile(FILE *f, int (*strfunc)(int len, char *str)); - -/* - * Read the file and parse each string with strfunc(), - * until strfunc() returns !=0 or the end of file happens. - * Returns -1 on EOF or strfunc() returning <0, else 0 - */ - -static int -readfile( - FILE *f, - int (*strfunc)(int len, char *str) -) -{ - static char str[MAXLINE]; /* input line, maybe should be dynamic ? */ - char *s; - int len, c, res; - - len=0; - while(( c=getc(f) )!=EOF) { - if(c=='\n') { - str[len]=0; - - res = strfunc(len, str); - lineno++; - if(res<0) - return -1; - else if(res!=0) - return 0; - - len=0; - } else if(len%d)\n", lineno, MAXLINE-1); - exit(1); - } - } - return -1; /* EOF */ -} - -/* - * Parse the header of the font file. - * Stop after the line CHARS is encountered. Ignore the unknown lines. - */ - -struct line { - char *name; /* property name with trailing space */ - int namelen; /* length of the name string */ - enum { - ALLOW_REPEAT = 0x01, /* this property may be repeated in multiple lines */ - IS_SEEN = 0x02, /* this property has been seen already */ - MUST_SEE = 0x04, /* this property must be seen */ - IS_LAST = 0x08 /* this is the last property to be read */ - } flags; - char *fmt; /* format string for the arguments, NULL means a string arg */ - int nvals; /* number of values to be read by sscanf */ - void *vp[4]; /* pointers to values to be read */ -}; - -static struct line header[] = { - { GETLEN("FONT "), 0, " %200s", 1, {&xlfdname} }, - { GETLEN("SIZE "), MUST_SEE, " %d", 1, {&pixel_size} }, - { GETLEN("FONTBOUNDINGBOX "), MUST_SEE, " %hd %hd %hd %hd", 4, - {&fmet.bbox[2], &fmet.bbox[3], &fmet.bbox[0], &fmet.bbox[1]} }, - { GETLEN("FAMILY_NAME "), MUST_SEE, NULL, 1, {&fmet.name_family} }, - { GETLEN("WEIGHT_NAME "), MUST_SEE, NULL, 1, {&fmet.name_style} }, - { GETLEN("COPYRIGHT "), 0, NULL, 1, {&fmet.name_copyright} }, - { GETLEN("SLANT "), MUST_SEE, NULL, 1, {&slant} }, - { GETLEN("SPACING "), 0, NULL, 1, {&spacing} }, - { GETLEN("SETWIDTH_NAME "), 0, NULL, 1, {&fnwidth} }, - { GETLEN("CHARSET_REGISTRY "), 0, NULL, 1, {&charset_reg} }, - { GETLEN("CHARSET_ENCODING "), 0, NULL, 1, {&charset_enc} }, - { GETLEN("FONT_ASCENT "), 0, " %hd", 1, {&fmet.ascender} }, - { GETLEN("FONT_DESCENT "), 0, " %hd", 1, {&fmet.descender} }, - - /* these 2 must go in this order for post-processing */ - { GETLEN("UNDERLINE_THICKNESS "), 0, " %hd", 1, {&fmet.underline_thickness} }, - { GETLEN("UNDERLINE_POSITION "), 0, " %hd", 1, {&fmet.underline_position} }, - - { GETLEN("CHARS "), MUST_SEE|IS_LAST, " %d", 1, {&nglyphs} }, - { NULL, 0, 0 } /* end mark: name==NULL */ -}; - -static int -handle_header( - int len, - char *str -) -{ - struct line *cl; - char *s, *p; - int c; - -#if 0 - fprintf(stderr, "line: %s\n", str); -#endif - for(cl = header; cl->name != 0; cl++) { - if(strncmp(str, cl->name, cl->namelen)) - continue; -#if 0 - fprintf(stderr, "match: %s\n", cl->name); -#endif - if(cl->flags & IS_SEEN) { - if(cl->flags & ALLOW_REPEAT) - continue; - - fprintf(stderr, "**** input line %d redefines the property %s\n", lineno, cl->name); - exit(1); - } - cl->flags |= IS_SEEN; - if(cl->fmt == 0) { - s = malloc(len - cl->namelen + 1); - if(s == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - *((char **)(cl->vp[0])) = s; - - /* skip until a quote */ - for(p = str+cl->namelen; (c = *p)!=0; p++) { - if(c == '"') { - p++; - break; - } - } - for(; (c = *p)!=0; p++) { - if(c == '"') { - c = *++p; - if(c == '"') - *s++ = c; - else - break; - } else - *s++ = c; - } - *s = 0; /* end of line */ - } else { - c = sscanf(str+cl->namelen, cl->fmt, cl->vp[0], cl->vp[1], cl->vp[2], cl->vp[3]); - if(c != cl->nvals) { - fprintf(stderr, "**** property %s at input line %d must have %d arguments\n", - cl->name, lineno, cl->nvals); - exit(1); - } - } - if(cl->flags & IS_LAST) - return 1; - else - return 0; - } - return 0; -} - -/* - * Parse the description of the glyphs - */ - -static int -handle_glyphs( - int len, - char *str -) -{ - static int inbmap=0; - static char *bmap; - static int xsz, ysz, xoff, yoff; - static int curln; - int i, c; - char *p, *plim, *psz; - - if(!LENCMP(str, "ENDFONT")) { - if(curgl < nglyphs) { - fprintf(stderr, "**** unexpected end of font file after %d glyphs\n", curgl); - exit(1); - } else - return 1; - } - if(curgl >= nglyphs) { - fprintf(stderr, "**** file contains more glyphs than advertised (%d)\n", nglyphs); - exit(1); - } - if(!LENCMP(str, "STARTCHAR")) { - /* sizeof will count \0 instead of ' ' */ - for(i=sizeof("STARTCHAR"); str[i] == ' '; i++) - {} - - glyphs[curgl].name = strdup(str + i); - if(glyphs[curgl].name == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } else if(!LENCMP(str, "ENCODING")) { - if(sscanf(str, "ENCODING %d", &fontenc[curgl])!=1) { - fprintf(stderr,"**** weird ENCODING statement at line %d\n", lineno); - exit(1); - } - if(fontenc[curgl] == -1) /* compatibility format */ - sscanf(str, "ENCODING -1 %d", &fontenc[curgl]); - if(fontenc[curgl] > maxenc) - maxenc = fontenc[curgl]; - } else if(!LENCMP(str, "DWIDTH")) { - if(sscanf(str, "DWIDTH %d %d", &xsz, &ysz)!=2) { - fprintf(stderr,"**** weird DWIDTH statement at line %d\n", lineno); - exit(1); - } - glyphs[curgl].width = xsz*scale; - } else if(!LENCMP(str, "BBX")) { - if(sscanf(str, "BBX %d %d %d %d", &xsz, &ysz, &xoff, &yoff)!=4) { - fprintf(stderr,"**** weird BBX statement at line %d\n", lineno); - exit(1); - } - bmap=malloc(xsz*ysz); - if(bmap==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - glyphs[curgl].lsb = -xoff*scale; - glyphs[curgl].xMin = -xoff*scale; - glyphs[curgl].xMax = (xsz-xoff)*scale; - glyphs[curgl].yMin = -yoff*scale; - glyphs[curgl].yMax = (ysz-xoff)*scale; - } else if(!LENCMP(str, "BITMAP")) { - inbmap=1; - curln=ysz-1; /* the lowest line has index 0 */ - } else if(!LENCMP(str, "ENDCHAR")) { - inbmap=0; - if(bmap) { - glyphs[curgl].lastentry = 0; - glyphs[curgl].path = 0; - glyphs[curgl].entries = 0; - bmp_outline(&glyphs[curgl], scale, bmap, xsz, ysz, xoff, yoff); - free(bmap); - /* remember in a static table or it will be erased */ - glpaths[curgl] = glyphs[curgl].entries; - glyphs[curgl].entries = 0; - - if(glpaths[curgl]) - glyphs[curgl].ttf_pathlen = 1; - else - glyphs[curgl].ttf_pathlen = 0; - } - curgl++; - } else if(inbmap) { - if(curln<0) { - fprintf(stderr,"**** bitmap is longer than %d lines at line %d\n", ysz, lineno); - exit(1); - } - - i=0; - p=&bmap[curln*xsz]; psz=p+xsz; - while(ilsb = 0; - g->width = fmet.bbox[2]; - g->xMin = 0; - g->yMin = 0; - } - g = &glyphs[0]; - g->name = ".notdef"; - g->xMax = fmet.bbox[2]*4/5; - g->yMax = fmet.bbox[3]*4/5; - g->entries = g->path = g->lastentry = 0; - /* make it look as a black square */ - fg_rmoveto(g, 0.0, 0.0); - fg_rlineto(g, 0.0, (double)g->yMax); - fg_rlineto(g, (double)g->xMax, (double)g->yMax); - fg_rlineto(g, (double)g->xMax, 0.0); - fg_rlineto(g, 0.0, 0.0); - g_closepath(g); - glpaths[0] = g->entries; - g->entries = 0; - g->ttf_pathlen = 4; - - g = &glyphs[1]; - g->name = ".null"; - g->xMax = g->yMax = 0; - g->ttf_pathlen = 0; - - if(readfile(bdf_file, handle_glyphs) < 0) { - fprintf(stderr, "**** file does not contain the ENDFONT line\n"); - exit(1); - } - got_glyphs = 1; -} - -/* - * Open font and prepare to return information to the main driver. - * May print error and warning messages. - * Exit on error. - */ - -static void -openfont( - char *fname, - char *arg /* unused now */ -) -{ - struct line *cl; - int i, l; - - if ((bdf_file = fopen(fname, "rb")) == NULL) { - fprintf(stderr, "**** Cannot open file '%s'\n", fname); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Processing file %s\n", fname); - } - - lineno = 1; - - for(cl = header; cl->name != 0; cl++) - cl->flags &= ~IS_SEEN; - if(readfile(bdf_file, handle_header) < 0) { - fprintf(stderr, "**** file does not contain the CHARS definition\n"); - exit(1); - } - for(cl = header; cl->name != 0; cl++) { - if( (cl->flags & MUST_SEE) && !(cl->flags & IS_SEEN) ) { - fprintf(stderr, "**** mandatory property %sis not found in the input line\n", - cl->name); /* cl->name has a space at the end */ - exit(1); - } - - /* set a few defaults */ - if( !(cl->flags & IS_SEEN) ) { - if(cl->vp[0] == &fmet.underline_thickness) { - fmet.underline_thickness = 1; - } else if(cl->vp[0] == &fmet.underline_position) { - fmet.underline_position = fmet.bbox[1] + fmet.underline_thickness - - (pixel_size - fmet.bbox[3]); - } else if(cl->vp[0] == &fmet.ascender) { - fmet.ascender = fmet.bbox[2] + fmet.bbox[0]; - } else if(cl->vp[0] == &fmet.descender) { - fmet.descender = fmet.bbox[0]; - } - } - } - - nglyphs += 2; /* add empty glyph and .notdef */ - - /* postprocessing to compensate for the differences in the metric formats */ - fmet.bbox[2] += fmet.bbox[0]; - fmet.bbox[3] += fmet.bbox[1]; - - scale = 1000/pixel_size; /* XXX ? */ - if(scale*pixel_size < 950) { - scale = 1; - scale_external = 1; - fmet.units_per_em = pixel_size; - } else { - scale_external = 0; - fmet.units_per_em = scale*pixel_size; - - fmet.underline_position *= scale; - fmet.underline_thickness *= scale; - fmet.ascender *= scale; - fmet.descender *= scale; - for(i=0; i<4; i++) - fmet.bbox[i] *= scale; - } - - fmet.italic_angle = 0.0; - if(spacing == 0 /* possibly an old font */ - || toupper(spacing[0]) != 'P') /* or anything non-proportional */ - fmet.is_fixed_pitch = 1; - else - fmet.is_fixed_pitch = 0; - - if(fmet.name_copyright==NULL) - fmet.name_copyright = ""; - - /* create the full name */ - l = strlen(fmet.name_family) - + (fmet.name_style? strlen(fmet.name_style) : 0) - + (fnwidth? strlen(fnwidth) : 0) - + strlen("Oblique") + 1; - - if(( fmet.name_full = malloc(l) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - strcpy(fmet.name_full, fmet.name_family); - if(fnwidth && strcmp(fnwidth, "Normal")) { - strcat(fmet.name_full, fnwidth); - } - if(fmet.name_style && strcmp(fmet.name_style, "Medium")) { - strcat(fmet.name_full, fmet.name_style); - } - switch(toupper(slant[0])) { - case 'O': - strcat(fmet.name_full, "Oblique"); - break; - case 'I': - strcat(fmet.name_full, "Italic"); - break; - } - - fmet.name_ps = fmet.name_full; - fmet.name_version = "1.0"; - - if(charset_reg && charset_enc - && !strcmp(charset_reg, "iso10646") && !strcmp(charset_enc, "1")) - is_unicode = 1; - - if(( fontenc = calloc(nglyphs, sizeof *fontenc) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - for(i=0; i=0 && e 255) - return 2; - else - return 0; -} - -/* - * Get the font metrics - */ -static void -fnmetrics( - struct font_metrics *fm -) -{ - *fm = fmet; -} - -/* - * Get the path of contrours for a glyph. - */ - -static void -glpath( - int glyphno, - GLYPH *glyf_list -) -{ - readglyphs(glyf_list); - glyf_list[glyphno].entries = glpaths[glyphno]; - glpaths[glyphno] = 0; -} - -/* - * Get the kerning data. - */ - -static void -kerning( - GLYPH *glyph_list -) -{ - return; /* no kerning in BDF */ -} diff --git a/pdf2swf/ttf2pt1/bitmap.c b/pdf2swf/ttf2pt1/bitmap.c deleted file mode 100644 index eb5c409..0000000 --- a/pdf2swf/ttf2pt1/bitmap.c +++ /dev/null @@ -1,2458 +0,0 @@ -/* - * Handling of the bitmapped glyphs - * - * Copyright (c) 2001 by the TTF2PT1 project - * Copyright (c) 2001 by Sergey Babkin - * - * see COPYRIGHT for the full copyright notice - */ - -#include -#include -#include -#include "pt1.h" -#include "global.h" - -/* possible values of limits */ -#define L_NONE 0 /* nothing here */ -#define L_ON 1 /* black is on up/right */ -#define L_OFF 2 /* black is on down/left */ - -static int warnedhints = 0; - - -#ifdef USE_AUTOTRACE -#include - -/* - * Produce an autotraced outline from a bitmap. - * scale - factor to scale the sizes - * bmap - array of dots by lines, xsz * ysz - * xoff, yoff - offset of the bitmap's lower left corner - * from the logical position (0,0) - */ - -static void -autotraced_bmp_outline( - GLYPH *g, - int scale, - char *bmap, - int xsz, - int ysz, - int xoff, - int yoff -) -{ - at_bitmap_type atb; - at_splines_type *atsp; - at_fitting_opts_type *atoptsp; - at_spline_list_type *slp; - at_spline_type *sp; - int i, j, k; - double lastx, lasty; - double fscale; - char *xbmap; - - fscale = (double)scale; - - /* provide a white margin around the bitmap */ - xbmap = malloc((ysz+2)*(xsz+2)); - if(xbmap == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - memset(xbmap, 0, xsz+2); /* top margin */ - for(i=0, j=xsz+2; ilength; i++) { - slp = &atsp->data[i]; -#if 0 - fprintf(stderr, "%s: contour %d: %d entries clockwise=%d color=%02X%02X%02X\n", - g->name, i, slp->length, slp->clockwise, slp->color.r, slp->color.g, slp->color.b); -#endif - if(slp->length == 0) - continue; -#if 0 - if(slp->color.r + slp->color.g + slp->color.b == 0) - continue; -#endif - fg_rmoveto(g, fscale*(slp->data[0].v[0].x+xoff), fscale*(slp->data[0].v[0].y+yoff)); - for(j=0; jlength; j++) { -#if 0 - fprintf(stderr, " "); - for(k=0; k<4; k++) - fprintf(stderr, "(%g %g) ", - fscale*(slp->data[j].v[k].x+xoff), - fscale*(ysz-slp->data[j].v[k].y+yoff) - ); - fprintf(stderr, "\n"); -#endif - fg_rrcurveto(g, - fscale*(slp->data[j].v[1].x+xoff), fscale*(slp->data[j].v[1].y+yoff), - fscale*(slp->data[j].v[2].x+xoff), fscale*(slp->data[j].v[2].y+yoff), - fscale*(slp->data[j].v[3].x+xoff), fscale*(slp->data[j].v[3].y+yoff) ); - } - g_closepath(g); - } - - at_splines_free(atsp); - at_fitting_opts_free(atoptsp); - free(xbmap); -} - -#endif /*USE_AUTOTRACE*/ - -/* an extension of gentry for description of the fragments */ -typedef struct gex_frag GEX_FRAG; -struct gex_frag { - /* indexes to len, the exact values and order are important */ -#define GEXFI_NONE -1 -#define GEXFI_CONVEX 0 -#define GEXFI_CONCAVE 1 -#define GEXFI_LINE 2 /* a line with steps varying by +-1 pixel */ -#define GEXFI_EXACTLINE 3 /* a line with exactly the same steps */ -#define GEXFI_COUNT 4 /* maximal index + 1 */ - unsigned short len[GEXFI_COUNT]; /* length of various fragment types starting here */ - unsigned short lenback[GEXFI_COUNT]; /* length back to the start of curve */ - - signed char ixstart; /* index of the frag type that starts here */ - signed char ixcont; /* index of the frag type that continues here */ - - short flags; -#define GEXFF_HLINE 0x0001 /* the exact line is longer in "horizontal" dimension */ -#define GEXFF_EXTR 0x0002 /* this gentry is an extremum in some direction */ -#define GEXFF_CIRC 0x0004 /* the joint at this gentry is for a circular curve */ -#define GEXFF_DRAWCURVE 0x0008 /* vect[] describes a curve to draw */ -#define GEXFF_DRAWLINE 0x0010 /* vect[] describes a line to draw */ -#define GEXFF_SPLIT 0x0020 /* is a result of splitting a line */ -#define GEXFF_SYMNEXT 0x0040 /* this subfrag is symmetric with next one */ -#define GEXFF_DONE 0x0080 /* this subfrag has been vectorized */ -#define GEXFF_LONG 0x0100 /* this gentry is longer than 1 pixel */ - - unsigned short aidx; /* index of gentry in the array representing the contour */ - - unsigned short vectlen; /* number of gentries represented by vect[] */ - - /* coordinates for vectored replacement of this fragment */ - /* (already scaled because it's needed for curve approximation) */ - double vect[4 /*ref.points*/][2 /*X,Y*/]; - - double bbox[2 /*X,Y*/]; /* absolute sizes of bounding box of a subfragment */ - - /* used when splitting the curved frags into subfrags */ - GENTRY *prevsub; /* to gentries describing neighboring subfrags */ - GENTRY *nextsub; - GENTRY *ordersub; /* single-linked list describing the order of calculation */ - - int sublen; /* length of this subfrag */ - /* the symmetry across the subfrags */ - int symaxis; /* the symmetry axis, with next subfrag */ - int symxlen; /* min length of adjacent symmetric frags */ - /* the symmetry within this subfrag (the axis is always diagonal) */ - GENTRY *symge; /* symge->i{x,y}3 is the symmetry point of symge==0 if none */ - -}; -#define X_FRAG(ge) ((GEX_FRAG *)((ge)->ext)) - -/* various interesting tables related to GEX_FRAG */ -static char *gxf_name[GEXFI_COUNT] = {"Convex", "Concave", "Line", "ExLine"}; -static int gxf_cvk[2] = {-1, 1}; /* coefficients of concaveness */ - -/* - * Dump the contents of X_EXT()->len and ->lenback for a contour - */ -static void -gex_dump_contour( - GENTRY *ge, - int clen -) -{ - int i, j; - - for(j = 0; j < GEXFI_COUNT; j++) { - fprintf(stderr, "%-8s", gxf_name[j]); - for(i = 0; i < clen; i++, ge = ge->frwd) - fprintf(stderr, " %2d", X_FRAG(ge)->len[j]); - fprintf(stderr, " %p\n (back) ", ge); - for(i = 0; i < clen; i++, ge = ge->frwd) - fprintf(stderr, " %2d", X_FRAG(ge)->lenback[j]); - fprintf(stderr, "\n"); - } -} - -/* - * Calculate values of X_EXT()->lenback[] for all entries in - * a contour. The contour is identified by: - * ge - any gentry of the contour - * clen - contour length - */ - -static void -gex_calc_lenback( - GENTRY *ge, - int clen -) -{ - int i, j; - int end; - GEX_FRAG *f; - int len[GEXFI_COUNT]; /* length of the most recent fragment */ - int count[GEXFI_COUNT]; /* steps since beginning of the fragment */ - - for(j = 0; j < GEXFI_COUNT; j++) - len[j] = count[j] = 0; - - end = clen; - for(i = 0; i < end; i++, ge = ge->frwd) { - f = X_FRAG(ge); - for(j = 0; j < GEXFI_COUNT; j++) { - if(len[j] != count[j]) { - f->lenback[j] = count[j]++; - } else - f->lenback[j] = 0; - if(f->len[j] != 0) { - len[j] = f->len[j]; - count[j] = 1; /* start with the next gentry */ - /* if the fragment will wrap over the start, process to its end */ - if(i < clen && i + len[j] > end) - end = i + len[j]; - } - } - } - gex_dump_contour(ge, clen); -} - -/* Limit a curve to not exceed the given coordinates - * at its given side - */ - -static void -limcurve( - double curve[4][2 /*X,Y*/], - double lim[2 /*X,Y*/], - int where /* 0 - start, 3 - end */ -) -{ - int other = 3-where; /* the other end */ - int sgn[2 /*X,Y*/]; /* sign for comparison */ - double t, from, to, nt, t2, nt2, tt[4]; - double val[2 /*X,Y*/]; - int i; - - for(i=0; i<2; i++) - sgn[i] = fsign(curve[other][i] - curve[where][i]); - -#if 0 - fprintf(stderr, " limit (%g,%g)-(%g,%g) at %d by (%g,%g), sgn(%d,%d)\n", - curve[0][0], curve[0][1], curve[3][0], curve[3][1], - where, lim[0], lim[1], sgn[0], sgn[1]); -#endif - /* a common special case */ - if( sgn[0]*(curve[where][0] - lim[0]) >= 0. - && sgn[1]*(curve[where][1] - lim[1]) >= 0. ) - return; /* nothing to do */ - - if(other==0) { - from = 0.; - to = 1.; - } else { - from = 1.; - to = 0.; - } -#if 0 - fprintf(stderr, "t="); -#endif - while( fabs(from-to) > 0.00001 ) { - t = 0.5 * (from+to); - t2 = t*t; - nt = 1.-t; - nt2 = nt*nt; - tt[0] = nt2*nt; - tt[1] = 3*nt2*t; - tt[2] = 3*nt*t2; - tt[3] = t*t2; - for(i=0; i<2; i++) - val[i] = curve[0][i]*tt[0] + curve[1][i]*tt[1] - + curve[2][i]*tt[2] + curve[3][i]*tt[3]; -#if 0 - fprintf(stderr, "%g(%g,%g) ", t, val[0], val[1]); -#endif - if(fabs(val[0] - lim[0]) < 0.1 - || fabs(val[1] - lim[1]) < 0.1) - break; - - if(sgn[0] * (val[0] - lim[0]) < 0. - || sgn[1] * (val[1] - lim[1]) < 0.) - to = t; - else - from = t; - } - /* now t is the point of splitting */ -#define SPLIT(pt1, pt2) ( (pt1) + t*((pt2)-(pt1)) ) /* order is important! */ - for(i=0; i<2; i++) { - double v11, v12, v13, v21, v22, v31; /* intermediate points */ - - v11 = SPLIT(curve[0][i], curve[1][i]); - v12 = SPLIT(curve[1][i], curve[2][i]); - v13 = SPLIT(curve[2][i], curve[3][i]); - v21 = SPLIT(v11, v12); - v22 = SPLIT(v12, v13); - v31 = SPLIT(v21, v22); - if(other==0) { - curve[1][i] = v11; - curve[2][i] = v21; - curve[3][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31; - } else { - curve[0][i] = fabs(v31 - lim[i]) < 0.1 ? lim[i] : v31; - curve[1][i] = v22; - curve[2][i] = v13; - } - } -#undef SPLIT -#if 0 - fprintf(stderr, "\n"); -#endif -} - -/* - * Vectorize a subfragment of a curve fragment. All the data has been already - * collected by this time - */ - -static void -dosubfrag( - GLYPH *g, - int fti, /* fragment type index */ - GENTRY *firstge, /* first gentry of fragment */ - GENTRY *ge, /* first gentry of subfragment */ - double fscale -) -{ - GENTRY *gel, *gei; /* last gentry of this subfrag */ - GEX_FRAG *f, *ff, *lf, *pf, *xf; - /* maximal amount of space that can be used at the beginning and the end */ - double fixfront[2], fixend[2]; /* fixed points - used to show direction */ - double mvfront[2], mvend[2]; /* movable points */ - double limfront[2], limend[2]; /* limit of movement for movabel points */ - double sympt; - int outfront, outend; /* the beginning/end is going outwards */ - int symfront, symend; /* a ready symmetric fragment is present at front/end */ - int drnd[2 /*X,Y*/]; /* size of the round part */ - int i, j, a1, a2, ndots; - double avg2, max2; /* squared distances */ - struct dot_dist *dots, *usedots; - - ff = X_FRAG(firstge); - f = X_FRAG(ge); - gel = f->nextsub; - lf = X_FRAG(gel); - if(f->prevsub != 0) - pf = X_FRAG(f->prevsub); - else - pf = 0; - - for(i=0; i<2; i++) - drnd[i] = gel->bkwd->ipoints[i][2] - ge->ipoints[i][2]; - - if(f->prevsub==0 && f->ixcont == GEXFI_NONE) { - /* nothing to join with : may use the whole length */ - for(i = 0; i < 2; i++) - limfront[i] = ge->bkwd->ipoints[i][2]; - } else { - /* limit to a half */ - for(i = 0; i < 2; i++) - limfront[i] = 0.5 * (ge->ipoints[i][2] + ge->bkwd->ipoints[i][2]); - } - if( (ge->ix3 == ge->bkwd->ix3) /* vert */ - ^ (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3)) - ^ (fti == GEXFI_CONCAVE) /* counter-clockwise */ ) { - /* the beginning is not a flat 90-degree end */ - outfront = 1; - for(i = 0; i < 2; i++) - fixfront[i] = ge->frwd->ipoints[i][2]; - } else { - outfront = 0; - for(i = 0; i < 2; i++) - fixfront[i] = ge->ipoints[i][2]; - } - - if(lf->nextsub==0 && lf->ixstart == GEXFI_NONE) { - /* nothing to join with : may use the whole length */ - for(i = 0; i < 2; i++) - limend[i] = gel->ipoints[i][2]; - } else { - /* limit to a half */ - for(i = 0; i < 2; i++) - limend[i] = 0.5 * (gel->ipoints[i][2] + gel->bkwd->ipoints[i][2]); - } - gei = gel->bkwd->bkwd; - if( (gel->ix3 == gel->bkwd->ix3) /* vert */ - ^ (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3)) - ^ (fti == GEXFI_CONVEX) /* clockwise */ ) { - /* the end is not a flat 90-degree end */ - outend = 1; - for(i = 0; i < 2; i++) - fixend[i] = gel->bkwd->bkwd->ipoints[i][2]; - } else { - outend = 0; - for(i = 0; i < 2; i++) - fixend[i] = gel->bkwd->ipoints[i][2]; - } - - for(i = 0; i < 2; i++) { - fixfront[i] *= fscale; - limfront[i] *= fscale; - fixend[i] *= fscale; - limend[i] *= fscale; - } - - fprintf(stderr, " %d out(%d[%d %d %d],%d[%d %d %d]) drnd(%d, %d)\n", - fti, - outfront, - (ge->ix3 == ge->bkwd->ix3), - (isign(ge->bkwd->ix3 - ge->frwd->ix3)==isign(ge->bkwd->iy3 - ge->frwd->iy3)), - (fti == GEXFI_CONCAVE), - outend, - (gel->ix3 == gel->bkwd->ix3), - (isign(gel->ix3 - gei->ix3)==isign(gel->iy3 - gei->iy3)), - (fti == GEXFI_CONVEX), - drnd[0], drnd[1]); - - /* prepare to calculate the distances */ - ndots = f->sublen - 1; - dots = malloc(sizeof(*dots) * ndots); - if(dots == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - for(i = 0, gei = ge; i < ndots; i++, gei = gei->frwd) { - for(a1 = 0; a1 < 2; a1++) - dots[i].p[a1] = fscale * gei->ipoints[a1][2]; - } - - /* see if we can mirror a ready symmetric curve */ - - /* check symmetry with the fragment before this */ - symfront = (pf != 0 && (pf->flags & GEXFF_SYMNEXT) && (pf->flags & GEXFF_DONE) - && ( outend && f->sublen <= pf->sublen - || ( pf->sublen == f->sublen - && (lf->sublen == 0 - || ( abs(limfront[0]-limend[0]) >= abs(pf->vect[0][0]-pf->vect[3][0]) - && abs(limfront[1]-limend[1]) >= abs(pf->vect[0][1]-pf->vect[3][1]) )) - ) - ) - ); - /* check symmetry with the fragment after this */ - symend = ( (f->flags & GEXFF_SYMNEXT) && (lf->flags & GEXFF_DONE) - && ( outfront && f->sublen <= lf->sublen - || ( lf->sublen == f->sublen - && (pf == 0 - || ( abs(limfront[0]-limend[0]) >= abs(lf->vect[0][0]-lf->vect[3][0]) - && abs(limfront[1]-limend[1]) >= abs(lf->vect[0][1]-lf->vect[3][1]) )) - ) - ) - ); - if(symfront || symend) { - /* mirror the symmetric neighbour subfrag */ - if(symfront) { - a1 = (ge->ix3 != ge->bkwd->ix3); /* the symmetry axis */ - a2 = !a1; /* the other axis (goes along the extremum gentry) */ - - /* the symmetry point on a2 */ - sympt = fscale * 0.5 * (ge->ipoints[a2][2] + ge->bkwd->ipoints[a2][2]); - xf = pf; /* the symmetric fragment */ - } else { - a1 = (gel->ix3 != gel->bkwd->ix3); /* the symmetry axis */ - a2 = !a1; /* the other axis (goes along the extremum gentry) */ - - /* the symmetry point on a2 */ - sympt = fscale * 0.5 * (gel->ipoints[a2][2] + gel->bkwd->ipoints[a2][2]); - xf = lf; /* the symmetric fragment */ - } - fprintf(stderr, " sym with %p f=%d(%p) e=%d(%p) a1=%c a2=%c sympt=%g\n", - xf, symfront, pf, symend, lf, - a1 ? 'Y': 'X', a2 ? 'Y': 'X', sympt - ); - for(i=0; i<4; i++) { - f->vect[3-i][a1] = xf->vect[i][a1]; - f->vect[3-i][a2] = sympt - (xf->vect[i][a2]-sympt); - } - if(symfront) { - if(outend || lf->sublen==0) - limcurve(f->vect, limend, 3); - } else { - if(outfront || pf == 0) - limcurve(f->vect, limfront, 0); - } - avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2); - fprintf(stderr, " avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale); - if(max2 <= fscale*fscale) { - f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE); - f->vectlen = f->sublen; - free(dots); - return; - } - } - - if( !outfront && !outend && f->symge != 0) { - /* a special case: try a circle segment as an approximation */ - double lenfront, lenend, len, maxlen; - - /* coefficient for a Bezier approximation of a circle */ -#define CIRCLE_FRAC 0.55 - - a1 = (ge->ix3 == ge->bkwd->ix3); /* get the axis along the front */ - a2 = !a1; /* axis along the end */ - - lenfront = fixfront[a1] - limfront[a1]; - lenend = fixend[a2] - limend[a2]; - if(fabs(lenfront) < fabs(lenend)) - len = fabs(lenfront); - else - len = fabs(lenend); - - /* make it go close to the round shape */ - switch(f->sublen) { - case 2: - maxlen = fscale; - break; - case 4: - case 6: - maxlen = fscale * 2.; - break; - default: - maxlen = fscale * abs(ge->frwd->frwd->ipoints[a1][2] - - ge->ipoints[a1][2]); - break; - } - if(len > maxlen) - len = maxlen; - - mvfront[a1] = fixfront[a1] - fsign(lenfront) * len; - mvfront[a2] = limfront[a2]; - mvend[a2] = fixend[a2] - fsign(lenend) * len; - mvend[a1] = limend[a1]; - - for(i=0; i<2; i++) { - f->vect[0][i] = mvfront[i]; - f->vect[3][i] = mvend[i]; - } - f->vect[1][a1] = mvfront[a1] + CIRCLE_FRAC*(mvend[a1]-mvfront[a1]); - f->vect[1][a2] = mvfront[a2]; - f->vect[2][a1] = mvend[a1]; - f->vect[2][a2] = mvend[a2] + CIRCLE_FRAC*(mvfront[a2]-mvend[a2]); - - avg2 = fdotcurvdist2(f->vect, dots, ndots, &max2); - fprintf(stderr, " avg=%g max=%g fscale=%g\n", sqrt(avg2), sqrt(max2), fscale); - if(max2 <= fscale*fscale) { - f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE); - f->vectlen = f->sublen; - free(dots); - return; - } -#undef CIRCLE_FRAC - } - for(i=0; i<2; i++) { - f->vect[0][i] = limfront[i]; - f->vect[1][i] = fixfront[i]; - f->vect[2][i] = fixend[i]; - f->vect[3][i] = limend[i]; - } - usedots = dots; - if(outfront) { - usedots++; ndots--; - } - if(outend) - ndots--; - if( fcrossrayscv(f->vect, NULL, NULL) == 0) { - fprintf(stderr, "**** Internal error: rays must cross but don't at %p-%p\n", - ge, gel); - fprintf(stderr, " (%g, %g) (%g, %g) (%g, %g) (%g, %g)\n", - limfront[0], limfront[1], - fixfront[0], fixfront[1], - fixend[0], fixend[1], - limend[0], limend[1] - ); - dumppaths(g, NULL, NULL); - exit(1); - } else { - if(ndots != 0) - fapproxcurve(f->vect, usedots, ndots); - f->flags |= (GEXFF_DONE | GEXFF_DRAWCURVE); - f->vectlen = f->sublen; - } - free(dots); -} - -/* - * Produce an outline from a bitmap. - * scale - factor to scale the sizes - * bmap - array of dots by lines, xsz * ysz - * xoff, yoff - offset of the bitmap's lower left corner - * from the logical position (0,0) - */ - -void -bmp_outline( - GLYPH *g, - int scale, - char *bmap, - int xsz, - int ysz, - int xoff, - int yoff -) -{ - char *hlm, *vlm; /* arrays of the limits of outlines */ - char *amp; /* map of ambiguous points */ - int x, y; - char *ip, *op; - double fscale; - - if(xsz==0 || ysz==0) - return; - -#ifdef USE_AUTOTRACE - if(use_autotrace) { - autotraced_bmp_outline(g, scale, bmap, xsz, ysz, xoff, yoff); - return; - } -#endif /*USE_AUTOTRACE*/ - - fscale = (double)scale; - g->flags &= ~GF_FLOAT; /* build it as int first */ - - if(!warnedhints) { - warnedhints = 1; - if(hints && subhints) { - WARNING_2 fprintf(stderr, - "Use of hint substitution on bitmap fonts is not recommended\n"); - } - } - -#if 0 - printbmap(bmap, xsz, ysz, xoff, yoff); -#endif - - /* now find the outlines */ - hlm=calloc( xsz, ysz+1 ); /* horizontal limits */ - vlm=calloc( xsz+1, ysz ); /* vertical limits */ - amp=calloc( xsz, ysz ); /* ambiguous points */ - - if(hlm==0 || vlm==0 || amp==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - /* - * hlm and vlm represent a grid of horisontal and - * vertical lines. Each pixel is surrounded by the grid - * from all the sides. The values of [hv]lm mark the - * parts of grid where the pixel value switches from white - * to black and back. - */ - - /* find the horizontal limits */ - ip=bmap; op=hlm; - /* 1st row */ - for(x=0; x0; y--) - for(x=xsz-1; x>0; x--) { - if(bmap[y*xsz+x]) { - if( !bmap[y*xsz+x-1] && !bmap[y*xsz-xsz+x] && bmap[y*xsz-xsz+x-1] ) - amp[y*xsz+x]=1; - } else { - if( bmap[y*xsz+x-1] && bmap[y*xsz-xsz+x] && !bmap[y*xsz-xsz+x-1] ) - amp[y*xsz+x]=1; - } - } - -#if 0 - printlimits(hlm, vlm, amp, xsz, ysz); -#endif - - /* generate the vectored (stepping) outline */ - - while(1) { - int found = 0; - int outer; /* flag: this is an outer contour */ - int hor, newhor; /* flag: the current contour direction is horizontal */ - int dir; /* previous direction of the coordinate, 1 - L_ON, 0 - L_OFF */ - int startx, starty; /* start of a contour */ - int firstx, firsty; /* start of the current line */ - int newx, newy; /* new coordinates to try */ - char *lm, val; - int maxx, maxy, xor; - - for(y=ysz; !found && y>0; y--) - for(x=0; x L_NONE) - goto foundcontour; - break; /* have no contours left */ - - foundcontour: - ig_rmoveto(g, x+xoff, y+yoff); /* intermediate as int */ - - startx = firstx = x; - starty = firsty = y; - - if(hlm[y*xsz+x] == L_OFF) { - outer = 1; dir = 0; - hlm[y*xsz+x] = -hlm[y*xsz+x]; /* mark as seen */ - hor = 1; x++; - } else { - outer = 0; dir = 0; - hor = 0; y--; - vlm[y*(xsz+1)+x] = -vlm[y*(xsz+1)+x]; /* mark as seen */ - } - - while(x!=startx || y!=starty) { -#if 0 - printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir); -#endif - - /* initialization common for try1 and try2 */ - if(hor) { - lm = vlm; maxx = xsz+1; maxy = ysz; newhor = 0; - } else { - lm = hlm; maxx = xsz; maxy = ysz+1; newhor = 1; - } - xor = (outer ^ hor ^ dir); - - try1: - /* first we try to change axis, to keep the - * contour as long as possible - */ - - newx = x; newy = y; - if(!hor && (!outer ^ dir)) - newx--; - if(hor && (!outer ^ dir)) - newy--; - - if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy) - goto try2; - - if(!xor) - val = L_ON; - else - val = L_OFF; -#if 0 - printf("try 1, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx], - (newhor ? 'h':'v'), newx, newy); -#endif - if( lm[newy*maxx + newx] == val ) - goto gotit; - - try2: - /* try to change the axis anyway */ - - newx = x; newy = y; - if(!hor && (outer ^ dir)) - newx--; - if(hor && (outer ^ dir)) - newy--; - - if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy) - goto try3; - - if(xor) - val = L_ON; - else - val = L_OFF; -#if 0 - printf("try 2, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx], - (newhor ? 'h':'v'), newx, newy); -#endif - if( lm[newy*maxx + newx] == val ) - goto gotit; - - try3: - /* try to continue in the old direction */ - - if(hor) { - lm = hlm; maxx = xsz; maxy = ysz+1; - } else { - lm = vlm; maxx = xsz+1; maxy = ysz; - } - newhor = hor; - newx = x; newy = y; - if(hor && dir) - newx--; - if(!hor && !dir) - newy--; - - if(newx < 0 || newx >= maxx || newy < 0 || newy >= maxy) - goto badtry; - - if(dir) - val = L_ON; - else - val = L_OFF; -#if 0 - printf("try 3, want %d have %d at %c(%d, %d)\n", val, lm[newy*maxx + newx], - (newhor ? 'h':'v'), newx, newy); -#endif - if( lm[newy*maxx + newx] == val ) - goto gotit; - - badtry: - fprintf(stderr, "**** Internal error in the contour detection code at (%d, %d)\n", x, y); - fprintf(stderr, "glyph='%s' outer=%d hor=%d dir=%d\n", g->name, outer, hor, dir); - fflush(stdout); - exit(1); - - gotit: - if(hor != newhor) { /* changed direction, end the previous line */ - ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */ - firstx = x; firsty = y; - } - lm[newy*maxx + newx] = -lm[newy*maxx + newx]; - hor = newhor; - dir = (val == L_ON); - if(newhor) - x -= (dir<<1)-1; - else - y += (dir<<1)-1; - } -#if 0 - printf("trace (%d, %d) outer=%d hor=%d dir=%d\n", x, y, outer, hor, dir); -#endif - ig_rlineto(g, x+xoff, y+yoff); /* intermediate as int */ - g_closepath(g); - } - - - /* try to vectorize the curves and sloped lines in the bitmap */ - if(vectorize) { - GENTRY *ge, *pge, *cge, *loopge; - int i; - int skip; - - dumppaths(g, NULL, NULL); - - /* allocate the extensions */ - for(cge=g->entries; cge!=0; cge=cge->next) { - cge->ext = calloc(1, sizeof(GEX_FRAG) ); - if(cge->ext == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - - for(cge=g->entries; cge!=0; cge=cge->next) { - if(cge->type != GE_MOVE) - continue; - - /* we've found the beginning of a contour */ - { - int d, vert, count, stepmore, delaystop; - int vdir, hdir, fullvdir, fullhdir, len; - int dx, dy, lastdx, lastdy; - int k1, k2, reversal, smooth, good; - int line[2 /*H,V*/], maxlen[2 /*H,V*/], minlen[2 /*H,V*/]; - GENTRY **age; /* array of gentries in a contour */ - int clen; /* contour length, size of ths array */ - int i, j; - GEX_FRAG *f; - - /* we know that all the contours start at the top-left corner, - * so at most it might be before/after the last element of - * the last/first fragment - */ - - ge = cge->next; - pge = ge->bkwd; - if(ge->ix3 == pge->ix3) { /* a vertical line */ - /* we want to start always from a horizontal line because - * then we always start from top and that is quaranteed to be a - * fragment boundary, so move the start point of the contour - */ - pge->prev->next = pge->next; - pge->next->prev = pge->prev; - cge->next = pge; - pge->prev = cge; - pge->next = ge; - ge->prev = pge; - ge = pge; pge = ge->bkwd; - cge->ix3 = pge->ix3; cge->iy3 = pge->iy3; - } - - /* fill the array of gentries */ - clen = 1; - for(ge = cge->next->frwd; ge != cge->next; ge = ge->frwd) - clen++; - age = (GENTRY **)malloc(sizeof(*age) * clen); - ge = cge->next; - count = 0; - do { - age[count] = ge; - X_FRAG(ge)->aidx = count++; - - /* and by the way find the extremums */ - for(i=0; i<2; i++) { - if( isign(ge->frwd->ipoints[i][2] - ge->ipoints[i][2]) - * isign(ge->bkwd->bkwd->ipoints[i][2] - ge->bkwd->ipoints[i][2]) == 1) { - X_FRAG(ge)->flags |= GEXFF_EXTR; - fprintf(stderr, " %s extremum at %p\n", (i?"vert":"hor"), ge); - } - if(abs(ge->ipoints[i][2] - ge->bkwd->ipoints[i][2]) > 1) - X_FRAG(ge)->flags |= GEXFF_LONG; - } - - ge = ge->frwd; - } while(ge != cge->next); - - /* Find the convex and concave fragments, defined as: - * convex (clockwise): dy/dx <= dy0/dx0, - * or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx > 0 - * concave (counter-clockwise): dy/dx >= dy0/dx0, - * or a reversal: dy/dx == - dy0/dx0 && abs(dxthis) == 1 && dy/dx < 0 - * - * Where dx and dy are measured between the end of this gentry - * and the start of the previous one (dx0 and dy0 are the same - * thing calculated for the previous gentry and its previous one), - * dxthis is between the end and begginning of this gentry. - * - * A reversal is a situation when the curve changes its direction - * along the x axis, so it passes through a momentary vertical - * direction. - */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - ge = cge->next; - pge = ge->bkwd; /* the beginning of the fragment */ - count = 1; - lastdx = pge->ix3 - pge->bkwd->bkwd->ix3; - lastdy = pge->iy3 - pge->bkwd->bkwd->iy3; - -#define CHKCURVCONN(ge, msg) do { \ - dx = (ge)->ix3 - (ge)->bkwd->bkwd->ix3; \ - dy = (ge)->iy3 - (ge)->bkwd->bkwd->iy3; \ - if(0 && msg) { \ - fprintf(stderr, " %p: dx=%d dy=%d dx0=%d dy0=%d ", \ - (ge), dx, dy, lastdx, lastdy); \ - } \ - k1 = X_FRAG(ge)->flags; \ - k2 = X_FRAG((ge)->bkwd)->flags; \ - if(0 && msg) { \ - fprintf(stderr, "fl=%c%c%c%c ", \ - (k1 & GEXFF_EXTR) ? 'X' : '-', \ - (k1 & GEXFF_LONG) ? 'L' : '-', \ - (k2 & GEXFF_EXTR) ? 'X' : '-', \ - (k2 & GEXFF_LONG) ? 'L' : '-' \ - ); \ - } \ - if( (k1 & GEXFF_EXTR) && (k2 & GEXFF_LONG) \ - || (k2 & GEXFF_EXTR) && (k1 & GEXFF_LONG) ) { \ - smooth = 0; \ - good = reversal = -1; /* for debugging */ \ - } else { \ - k1 = dy * lastdx; \ - k2 = lastdy * dx; \ - smooth = (abs(dx)==1 || abs(dy)==1); \ - good = (k1 - k2)*gxf_cvk[d] >= 0; \ - if(smooth && !good) { \ - reversal = (k1 == -k2 && abs((ge)->ix3 - (ge)->bkwd->ix3)==1 \ - && dy*dx*gxf_cvk[d] < 0); \ - } else \ - reversal = 0; \ - } \ - if(0 && msg) { \ - fprintf(stderr, "k1=%d k2=%d pge=%p count=%d %s good=%d rev=%d\n", \ - k1, k2, pge, count, gxf_name[d], good, reversal); \ - } \ - } while(0) - - do { - CHKCURVCONN(ge, 1); - - if(smooth && (good || reversal) ) - count++; - else { - /* can't continue */ -#if 0 - if(count >= 4) { /* worth remembering */ - fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); - } -#endif - X_FRAG(pge)->len[d] = count; - if(smooth) { - pge = ge->bkwd; - count = 2; - } else { - pge = ge; - count = 1; - } - } - lastdx = dx; lastdy = dy; - ge = ge->frwd; - } while(ge != cge->next); - - /* see if we can connect the last fragment to the first */ - CHKCURVCONN(ge, 1); - - if(smooth && (good || reversal) ) { - /* -1 to avoid ge->bkwd being counted twice */ - if( X_FRAG(ge->bkwd)->len[d] >= 2 ) - count += X_FRAG(ge->bkwd)->len[d] - 1; - else if(count == clen+1) { - /* we are joining a circular (closed) curve, check whether it - * can be joined at any point or whether it has a discontinuity - * at the point where we join it now - */ - lastdx = dx; lastdy = dy; - CHKCURVCONN(ge->frwd, 0); - - if(smooth && (good || reversal) ) { - /* yes, the curve is truly a circular one and can be - * joined at any point - */ - -#if 0 - fprintf(stderr, " found a circular joint point at %p\n", pge); -#endif - /* make sure that in a circular fragment we start from an extremum */ - while( ! (X_FRAG(pge)->flags & GEXFF_EXTR) ) - pge = pge->frwd; - X_FRAG(pge)->flags |= GEXFF_CIRC; - } - } -#if 0 - fprintf(stderr, " %s joined %p to %p count=%d bk_count=%d\n", gxf_name[d], pge, ge->bkwd, - count, X_FRAG(ge->bkwd)->len[d] ); -#endif - X_FRAG(ge->bkwd)->len[d] = 0; - } - X_FRAG(pge)->len[d] = count; -#if 0 - if(count >= 4) { /* worth remembering */ - fprintf(stderr, " %s last frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); - } -#endif -#undef CHKCURVCONN - - /* do postprocessing */ - ge = cge->next; - do { - f = X_FRAG(ge); - len = f->len[d]; -#if 0 - fprintf(stderr, " %p %s len=%d clen=%d\n", ge, gxf_name[d], len, clen); -#endif - if(len < 3) /* get rid of the fragments that are too short */ - f->len[d] = 0; - else if(len == 3) { - /* _ - * drop the |_| - shaped fragments, leave alone the _| - shaped - * (and even those only if not too short in pixels), - * those left alone are further filtered later - */ - k1 = (ge->ix3 == ge->bkwd->ix3); /* axis of the start */ - if(isign(ge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) - != isign(ge->frwd->ipoints[k1][2] - ge->frwd->frwd->ipoints[k1][2]) - && abs(ge->frwd->frwd->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) > 2) { -#if 0 - fprintf(stderr, " %s frag %p count=%d good shape\n", - gxf_name[d], ge, count); -#endif - } else - f->len[d] = 0; - } else if(len == clen+1) - break; /* a closed fragment, nothing else interesting */ - else { /* only for open fragments */ - GENTRY *gem, *gex, *gei, *ges; - - ges = ge; /* the start entry */ - gem = age[(f->aidx + f->len[d])%clen]; /* entry past the end of the fragment */ - - gei = ge->frwd; - if( (ge->ix3 == ge->bkwd->ix3) /* vert */ - ^ (isign(ge->bkwd->ix3 - gei->ix3)==isign(ge->bkwd->iy3 - gei->iy3)) - ^ !(d == GEXFI_CONVEX) /* counter-clockwise */ ) { - -#if 0 - fprintf(stderr, " %p: %s potential spurious start\n", ge, gxf_name[d]); -#endif - /* the beginning may be a spurious entry */ - - gex = 0; /* the extremum closest to the beginning - to be found */ - for(gei = ge->frwd; gei != gem; gei = gei->frwd) { - if(X_FRAG(gei)->flags & GEXFF_EXTR) { - gex = gei; - break; - } - } - if(gex == 0) - gex = gem->bkwd; - - /* A special case: ignore the spurious ends on small curves that - * either enclose an 1-pixel-wide extremum or are 1-pixel deep. - * Any 5-or-less-pixel-long curve with extremum 2 steps away - * qualifies for that. - */ - - if(len <= 5 && gex == ge->frwd->frwd) { - good = 0; -#if 0 - fprintf(stderr, " E"); -#endif - } else { - good = 1; /* assume that ge is not spurious */ - - /* gei goes backwards, gex goes forwards from the extremum */ - gei = gex; - /* i is the symmetry axis, j is the other axis (X=0 Y=1) */ - i = (gex->ix3 != gex->bkwd->ix3); - j = !i; - for( ; gei!=ge && gex!=gem; gei=gei->bkwd, gex=gex->frwd) { - if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2] - || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2] - != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] - ) { - good = 0; /* no symmetry - must be spurious */ -#if 0 - fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)", - gei, gex, - i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2], - j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2], - gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] ); -#endif - break; - } - } - if(gex == gem) { /* oops, the other side is too short */ - good = 0; -#if 0 - fprintf(stderr, " X"); -#endif - } - if(good && gei == ge) { - if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]) - != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) { - good = 0; /* oops, goes into another direction */ -#if 0 - fprintf(stderr, " D"); -#endif - } - } - } - if(!good) { /* it is spurious, drop it */ -#if 0 - fprintf(stderr, " %p: %s spurious start\n", ge, gxf_name[d]); -#endif - f->len[d] = 0; - ges = ge->frwd; - len--; - X_FRAG(ges)->len[d] = len; - } - } - - gei = gem->bkwd->bkwd->bkwd; - if( (gem->ix3 != gem->bkwd->ix3) /* gem->bkwd is vert */ - ^ (isign(gem->bkwd->ix3 - gei->ix3)==isign(gem->bkwd->iy3 - gei->iy3)) - ^ (d == GEXFI_CONVEX) /* clockwise */ ) { - -#if 0 - fprintf(stderr, " %p: %s potential spurious end\n", gem->bkwd, gxf_name[d]); -#endif - /* the end may be a spurious entry */ - - gex = 0; /* the extremum closest to the end - to be found */ - for(gei = gem->bkwd->bkwd; gei != ges->bkwd; gei = gei->bkwd) { - if(X_FRAG(gei)->flags & GEXFF_EXTR) { - gex = gei; - break; - } - } - if(gex == 0) - gex = ges; - - good = 1; /* assume that gem->bkwd is not spurious */ - /* gei goes backwards, gex goes forwards from the extremum */ - gei = gex; - /* i is the symmetry axis, j is the other axis (X=0 Y=1) */ - i = (gex->ix3 != gex->bkwd->ix3); - j = !i; - for( ; gei!=ges->bkwd && gex!=gem->bkwd; gei=gei->bkwd, gex=gex->frwd) { - if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2] - || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2] - != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] - ) { - good = 0; /* no symmetry - must be spurious */ -#if 0 - fprintf(stderr, " M(%p,%p)(%d %d,%d)(%d %d,%d)", - gei, gex, - i, gei->bkwd->ipoints[i][2], gex->ipoints[i][2], - j, gei->bkwd->ipoints[j][2] - gei->ipoints[j][2], - gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] ); -#endif - break; - } - } - if(gei == ges->bkwd) { /* oops, the other side is too short */ - good = 0; -#if 0 - fprintf(stderr, " X"); -#endif - } - if(good && gex == gem->bkwd) { - if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]) - != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) { - good = 0; /* oops, goes into another direction */ -#if 0 - fprintf(stderr, " D"); -#endif - } - } - if(!good) { /* it is spurious, drop it */ -#if 0 - fprintf(stderr, " %p: %s spurious end\n", gem->bkwd, gxf_name[d]); -#endif - X_FRAG(ges)->len[d] = --len; - } - } - if(len < 4) { - X_FRAG(ges)->len[d] = 0; -#if 0 - fprintf(stderr, " %p: %s frag discarded, too small now\n", ge, gxf_name[d]); -#endif - } - if(ges != ge) { - if(ges == cge->next) - break; /* went around the loop */ - else { - ge = ges->frwd; /* don't look at this fragment twice */ - continue; - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); - } - - /* Find the straight line fragments. - * Even though the lines are sloped, they are called - * "vertical" or "horizontal" according to their longer - * dimension. All the steps in the shother dimension must - * be 1 pixel long, all the steps in the longer dimension - * must be within the difference of 1 pixel. - */ - for(d = GEXFI_LINE; d<= GEXFI_EXACTLINE; d++) { - ge = cge->next; - pge = ge->bkwd; /* the beginning of the fragment */ - count = 1; - delaystop = 0; - do { - int h; - - stepmore = 0; - hdir = isign(ge->ix3 - ge->bkwd->ix3); - vdir = isign(ge->iy3 - ge->bkwd->iy3); - vert = (hdir == 0); - if(count==1) { - /* at this point pge==ge->bkwd */ - /* account for the previous gentry, which was !vert */ - if(!vert) { /* prev was vertical */ - maxlen[0] = minlen[0] = 0; - maxlen[1] = minlen[1] = abs(pge->iy3 - pge->bkwd->iy3); - line[0] = (maxlen[1] == 1); - line[1] = 1; - fullhdir = hdir; - fullvdir = isign(pge->iy3 - pge->bkwd->iy3); - } else { - maxlen[0] = minlen[0] = abs(pge->ix3 - pge->bkwd->ix3); - maxlen[1] = minlen[1] = 0; - line[0] = 1; - line[1] = (maxlen[0] == 1); - fullhdir = isign(pge->ix3 - pge->bkwd->ix3); - fullvdir = vdir; - } - } - h = line[0]; /* remember the prevalent direction */ -#if 0 - fprintf(stderr, " %p: v=%d(%d) h=%d(%d) vl(%d,%d,%d) hl=(%d,%d,%d) %s count=%d ", - ge, vdir, fullvdir, hdir, fullhdir, - line[1], minlen[1], maxlen[1], - line[0], minlen[0], maxlen[0], - gxf_name[d], count); -#endif - if(vert) { - if(vdir != fullvdir) - line[0] = line[1] = 0; - len = abs(ge->iy3 - ge->bkwd->iy3); - } else { - if(hdir != fullhdir) - line[0] = line[1] = 0; - len = abs(ge->ix3 - ge->bkwd->ix3); - } -#if 0 - fprintf(stderr, "len=%d\n", len); -#endif - if(len != 1) /* this is not a continuation in the short dimension */ - line[!vert] = 0; - - /* can it be a continuation in the long dimension ? */ - if( line[vert] ) { - if(maxlen[vert]==0) - maxlen[vert] = minlen[vert] = len; - else if(maxlen[vert]==minlen[vert]) { - if(d == GEXFI_EXACTLINE) { - if(len != maxlen[vert]) - line[vert] = 0; /* it can't */ - } else if(len < maxlen[vert]) { - if(len < minlen[vert]-1) - line[vert] = 0; /* it can't */ - else - minlen[vert] = len; - } else { - if(len > maxlen[vert]+1) - line[vert] = 0; /* it can't */ - else - maxlen[vert] = len; - } - } else if(len < minlen[vert] || len > maxlen[vert]) - line[vert] = 0; /* it can't */ - } - - if(line[0] == 0 && line[1] == 0) { -#if 0 - if(count >= 3) - fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); -#endif - X_FRAG(pge)->len[d] = count; - if(d == GEXFI_EXACTLINE && h) { - X_FRAG(pge)->flags |= GEXFF_HLINE; - } - if(count == 1) - pge = ge; - else { - stepmore = 1; /* may reconsider the 1st gentry */ - pge = ge = ge->bkwd; - count = 1; - } - } else - count++; - - ge = ge->frwd; - if(ge == cge->next && !stepmore) - delaystop = 1; /* consider the first gentry again */ - } while(stepmore || ge != cge->next ^ delaystop); - /* see if there is an unfinished line left */ - if(count != 1) { -#if 0 - if(count >= 3) - fprintf(stderr, " %s frag %p-%p count=%d\n", gxf_name[d], pge, ge->bkwd, count); -#endif - X_FRAG(ge->bkwd->bkwd)->len[d] = 0; - X_FRAG(pge)->len[d] = count; - } - } - - /* do postprocessing of the lines */ -#if 0 - fprintf(stderr, "Line postprocessing\n"); - gex_dump_contour(cge->next, clen); -#endif - - /* the non-exact line frags are related to exact line frags sort - * of like to individual gentries: two kinds of exact frags - * must be interleaved, with one kind having the size of 3 - * and the other kind having the size varying within +-2. - */ - - ge = cge->next; - do { - GEX_FRAG *pf, *lastf1, *lastf2; - int len1, len2, fraglen; - - f = X_FRAG(ge); - - fraglen = f->len[GEXFI_LINE]; - if(fraglen >= 4) { - - vert = 0; /* vert is a pseudo-directon */ - line[0] = line[1] = 1; - maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0; - lastf2 = lastf1 = f; - len2 = len1 = 0; - for(pge = ge, i = 1; i < fraglen; i++, pge=pge->frwd) { - pf = X_FRAG(pge); - len = pf->len[GEXFI_EXACTLINE]; -#if 0 - fprintf(stderr, " pge=%p i=%d of %d ge=%p exLen=%d\n", pge, i, - f->len[GEXFI_LINE], ge, len); -#endif - len1++; len2++; - if(len==0) { - continue; - } - vert = !vert; /* alternate the pseudo-direction */ - if(len > 3) - line[!vert] = 0; - if(maxlen[vert] == 0) - maxlen[vert] = minlen[vert] = len; - else if(maxlen[vert]-2 >= len && minlen[vert]+2 <= len) { - if(len > maxlen[vert]) - maxlen[vert] = len; - else if(len < minlen[vert]) - minlen[vert] = len; - } else - line[vert] = 0; - if(line[0] == 0 && line[1] == 0) { -#if 0 - fprintf(stderr, " Line breaks at %p %c(%d, %d) %c(%d, %d) len=%d fl=%d l2=%d l1=%d\n", - pge, (!vert)?'*':' ', minlen[0], maxlen[0], - vert?'*':' ', minlen[1], maxlen[1], len, fraglen, len2, len1); -#endif - if(lastf2 != lastf1) { - lastf2->len[GEXFI_LINE] = len2-len1; - } - lastf1->len[GEXFI_LINE] = len1+1; - pf->len[GEXFI_LINE] = fraglen+1 - i; - gex_dump_contour(pge, clen); - - /* continue with the line */ - vert = 0; /* vert is a pseudo-directon */ - line[0] = line[1] = 1; - maxlen[0] = minlen[0] = maxlen[1] = minlen[1] = 0; - lastf2 = lastf1 = f; - len2 = len1 = 0; - } else { - lastf1 = pf; - len1 = 0; - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); -#if 0 - gex_dump_contour(cge->next, clen); -#endif - - ge = cge->next; - do { - f = X_FRAG(ge); - - if(f->len[GEXFI_LINE] >= 4) { - len = f->len[GEXFI_EXACTLINE]; - /* if a non-exact line covers precisely two exact lines, - * split it - */ - if(len > 0 && f->len[GEXFI_LINE] > len+1) { - GEX_FRAG *pf; - pge = age[(f->aidx + len - 1)%clen]; /* last gentry of exact line */ - pf = X_FRAG(pge); - if(f->len[GEXFI_LINE] + 1 == len + pf->len[GEXFI_EXACTLINE]) { - f->len[GEXFI_LINE] = len; - f->flags |= GEXFF_SPLIT; - pf->len[GEXFI_LINE] = pf->len[GEXFI_EXACTLINE]; - pf->flags |= GEXFF_SPLIT; - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); - ge = cge->next; - do { - f = X_FRAG(ge); - - /* too small lines are of no interest */ - if( (f->flags & GEXFF_SPLIT)==0 && f->len[GEXFI_LINE] < 4) - f->len[GEXFI_LINE] = 0; - - len = f->len[GEXFI_EXACTLINE]; - /* too small exact lines are of no interest */ - if(len < 3) /* exact lines may be shorter */ - f->len[GEXFI_EXACTLINE] = 0; - /* get rid of inexact additions to the end of the exact lines */ - else if(f->len[GEXFI_LINE] == len+1) - f->len[GEXFI_LINE] = len; - /* same at the beginning */ - else { - int diff = X_FRAG(ge->bkwd)->len[GEXFI_LINE] - len; - - if(diff == 1 || diff == 2) { - X_FRAG(ge->bkwd)->len[GEXFI_LINE] = 0; - f->len[GEXFI_LINE] = len; - } - } - - ge = ge->frwd; - } while(ge != cge->next); -#if 0 - gex_dump_contour(cge->next, clen); -#endif - - gex_calc_lenback(cge->next, clen); /* prepare data */ - - /* resolve conflicts between lines and curves */ - - /* - * the short (3-gentry) curve frags must have one of the ends - * coinciding with another curve frag of the same type - */ - - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - ge = cge->next; - do { - f = X_FRAG(ge); - - if(f->len[d] == 3) { - pge = age[(f->aidx + 2)%clen]; /* last gentry of this frag */ - if(f->lenback[d] == 0 && X_FRAG(pge)->len[d] == 0) { - fprintf(stderr, " discarded small %s at %p-%p\n", gxf_name[d], ge, pge); - f->len[d] = 0; - X_FRAG(ge->frwd)->lenback[d] = 0; - X_FRAG(ge->frwd->frwd)->lenback[d] = 0; - } - } - ge = ge->frwd; - } while(ge != cge->next); - } - - /* - * longer exact lines take priority over curves, shorter lines - * and inexact lines are resolved with convex/concave conflicts - */ - ge = cge->next; - do { - f = X_FRAG(ge); - - len = f->len[GEXFI_EXACTLINE]; - - if(len < 6) { /* line is short */ - ge = ge->frwd; - continue; - } - - fprintf(stderr, " line at %p len=%d\n", ge, f->len[GEXFI_EXACTLINE]); - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - GEX_FRAG *pf; - - /* check if we overlap the end of some fragment */ - if(f->lenback[d]) { - /* chop off the end of conflicting fragment */ - len = f->lenback[d]; - pge = age[(f->aidx + clen - len)%clen]; - pf = X_FRAG(pge); - if(pf->len[d] == clen+1 && pf->flags & GEXFF_CIRC) { - /* the conflicting fragment is self-connected */ - - pf->len[d] = 0; - /* calculate the new value for lenback */ - len = clen+1 - f->len[GEXFI_EXACTLINE]; - for(pge = ge; len > 0; pge = pge->bkwd, len--) - X_FRAG(pge)->lenback[d] = len; - /* now pge points to the last entry of the line, - * which is also the new first entry of the curve - */ - X_FRAG(pge)->len[d] = clen+2 - f->len[GEXFI_EXACTLINE]; - /* clean lenback of gentries covered by the line */ - for(pge = ge->frwd, j = f->len[GEXFI_EXACTLINE]-1; j > 0; pge = pge->frwd, j--) - X_FRAG(pge)->lenback[d] = 0; - fprintf(stderr, " cut %s circular frag to %p-%p\n", - gxf_name[d], pge, ge); - gex_dump_contour(ge, clen); - } else { - /* when we chop off a piece of fragment, we leave the remaining - * piece(s) overlapping with the beginning and possibly the end - * of the line fragment under consideration - */ - fprintf(stderr, " cut %s frag at %p from len=%d to len=%d (end %p)\n", - gxf_name[d], pge, pf->len[d], len+1, ge); - j = pf->len[d] - len - 1; /* how many gentries are chopped off */ - pf->len[d] = len + 1; - i = f->len[GEXFI_EXACTLINE] - 1; - for(pge = ge->frwd; j > 0 && i > 0; j--, i--, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - gex_dump_contour(ge, clen); - - if(j != 0) { - /* the conflicting fragment is split in two by this line - * fragment, fix up its tail - */ - - fprintf(stderr, " end of %s frag len=%d %p-", - gxf_name[d], j+1, pge->bkwd); - X_FRAG(pge->bkwd)->len[d] = j+1; /* the overlapping */ - for(i = 1; j > 0; j--, i++, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = i; - fprintf(stderr, "%p\n", pge->bkwd); - gex_dump_contour(ge, clen); - } - } - } - /* check if we overlap the beginning of some fragments */ - i = f->len[GEXFI_EXACTLINE]-1; /* getntries remaining to consider */ - j = 0; /* gentries remaining in the overlapping fragment */ - for(pge = ge; i > 0; i--, pge = pge->frwd) { - if(j > 0) { - X_FRAG(pge)->lenback[d] = 0; - j--; - } - /* the beginning of one fragment may be the end of another - * fragment, in this case if j-- above results in 0, that will - * cause it to check the same gentry for the beginning - */ - if(j == 0) { - pf = X_FRAG(pge); - j = pf->len[d]; - if(j != 0) { - fprintf(stderr, " removed %s frag at %p len=%d\n", - gxf_name[d], pge, j); - gex_dump_contour(ge, clen); - pf->len[d] = 0; - j--; - } - } - } - /* pge points at the last gentry of the line fragment */ - if(j > 1) { /* we have the tail of a fragment left */ - fprintf(stderr, " end of %s frag len=%d %p-", - gxf_name[d], j, pge); - X_FRAG(pge)->len[d] = j; /* the overlapping */ - for(i = 0; j > 0; j--, i++, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = i; - fprintf(stderr, "%p\n", pge->bkwd); - gex_dump_contour(ge, clen); - } else if(j == 1) { - X_FRAG(pge)->lenback[d] = 0; - } - } - - ge = ge->frwd; - } while(ge != cge->next); - - /* - * The exact lines take priority over curves that coincide - * with them or extend by only one gentry on either side - * (but not both sides). By this time it applies only to the - * small exact lines. - */ - - /* Maybe we should remove only exact coincidences ? */ - - ge = cge->next; - do { - f = X_FRAG(ge); - - len = f->len[GEXFI_EXACTLINE]; - if(len >= 4) { - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - if(f->len[d] == len || f->len[d] == len+1) { - - fprintf(stderr, " removed %s frag at %p len=%d linelen=%d\n", - gxf_name[d], ge, f->len[d], len); - pge = ge->frwd; - for(i = f->len[d]; i > 1; i--, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - f->len[d] = 0; - gex_dump_contour(ge, clen); - } else if(X_FRAG(ge->bkwd)->len[d] == len+1) { - fprintf(stderr, " removed %s frag at %p len=%d next linelen=%d\n", - gxf_name[d], ge->bkwd, X_FRAG(ge->bkwd)->len[d], len); - pge = ge; - for(i = len; i > 0; i--, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - X_FRAG(ge->bkwd)->len[d] = 0; - gex_dump_contour(ge, clen); - } - } - } - - ge = ge->frwd; - } while(ge != cge->next); - - /* - * The lines may cover only whole curves (or otherwise empty space), - * so cut them where they overlap parts of the curves. If 2 or less - * gentries are left in the line, remove the line. - * If a line and a curve fully coincide, remove the line. Otherwise - * remove the curves that are completely covered by the lines. - */ - - ge = cge->next; - do { - f = X_FRAG(ge); - - reconsider_line: - len = f->len[GEXFI_LINE]; - - if(len == 0) { - ge = ge->frwd; - continue; - } - - if(f->len[GEXFI_CONVEX] >= len - || f->len[GEXFI_CONCAVE] >= len) { - line_completely_covered: - fprintf(stderr, " removed covered Line frag at %p len=%d\n", - ge, len); - f->len[GEXFI_LINE] = 0; - for(pge = ge->frwd; len > 1; len--, pge = pge->frwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = 0; - gex_dump_contour(ge, clen); - ge = ge->frwd; - continue; - } - - k1 = 0; /* how much to cut at the front */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - if(f->lenback[d]) { - pge = age[(f->aidx + clen - f->lenback[d])%clen]; - i = X_FRAG(pge)->len[d] - f->lenback[d] - 1; - if(i > k1) - k1 = i; - } - } - - k2 = 0; /* how much to cut at the end */ - pge = age[(f->aidx + len)%clen]; /* gentry after the end */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - i = X_FRAG(pge)->lenback[d] - 1; - if(i > k2) - k2 = i; - } - - if(k1+k2 > 0 && k1+k2 >= len-3) - goto line_completely_covered; - - if(k2 != 0) { /* cut the end */ - len -= k2; - f->len[GEXFI_LINE] = len; - /* pge still points after the end */ - for(i = k2, pge = pge->bkwd; i > 0; i--, pge = pge->bkwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = 0; - } - if(k1 != 0) { /* cut the beginning */ - len -= k1; - f->len[GEXFI_LINE] = 0; - for(i = 1, pge = ge->frwd; i < k1; i++, pge = pge->frwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = 0; - X_FRAG(pge)->len[GEXFI_LINE] = len; - for(i = 0; i < len; i++, pge = pge->frwd) - X_FRAG(pge)->lenback[GEXFI_LINE] = i; - } - if(k1 != 0 || k2 != 0) { - fprintf(stderr, " cut Line frag at %p by (%d,%d) to len=%d\n", - ge, k1, k2, len); - gex_dump_contour(ge, clen); - - goto reconsider_line; /* the line may have to be cut again */ - } - pge = age[(f->aidx + k1)%clen]; /* new beginning */ - good = 1; /* flag: no need do do a debugging dump */ - for(i=1; ifrwd) - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - if(X_FRAG(pge)->len[d]) { - fprintf(stderr, " removed %s frag at %p len=%d covered by line\n", - gxf_name[d], pge, X_FRAG(pge)->len[d], len); - good = 0; - } - X_FRAG(pge)->len[d] = 0; - } - pge = age[(f->aidx + k1 + 1)%clen]; /* next after new beginning */ - for(i=1; ifrwd) - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) - X_FRAG(pge)->lenback[d] = 0; - if(!good) - gex_dump_contour(ge, clen); - - ge = ge->frwd; - } while(ge != cge->next); - - /* Resolve conflicts between curves */ - for(d = GEXFI_CONVEX; d<= GEXFI_CONCAVE; d++) { - dx = (GEXFI_CONVEX + GEXFI_CONCAVE) - d; /* the other type */ - ge = cge->next; - do { - GENTRY *sge; - - f = X_FRAG(ge); - len = f->len[d]; - if(len < 2) { - ge = ge->frwd; - continue; - } - sge = ge; /* the start of fragment */ - - i = f->len[dx]; - if(i != 0) { /* two curved frags starting here */ - /* should be i!=len because otherwise they would be - * covered by an exact line - */ - if(i > len) { - curve_completely_covered: - /* remove the convex frag */ - fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n", - gxf_name[d], ge, len, gxf_name[dx]); - f->len[d] = 0; - for(pge = ge->frwd, j = 1; j < len; j++, pge = pge->frwd) - X_FRAG(pge)->lenback[d] = 0; - gex_dump_contour(ge, clen); - - ge = ge->frwd; /* the frag is gone, nothing more to do */ - continue; - } else { - /* remove the concave frag */ - fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n", - gxf_name[dx], ge, i, gxf_name[d]); - f->len[dx] = 0; - for(pge = ge->frwd, j = 1; j < i; j++, pge = pge->frwd) - X_FRAG(pge)->lenback[dx] = 0; - gex_dump_contour(ge, clen); - } - } - - - k1 = X_FRAG(ge->frwd)->lenback[dx]; - if(k1 != 0) { /* conflict at the front */ - GENTRY *gels, *gele, *gei; - - pge = age[(f->aidx + clen - (k1-1))%clen]; /* first gentry of concave frag */ - k2 = X_FRAG(pge)->len[dx]; /* its length */ - - i = k2 - (k1-1); /* amount of overlap */ - if(i > len) - i = len; - /* i >= 2 by definition */ - if(i >= k2-1) { /* covers the other frag - maybe with 1 gentry showing */ - fprintf(stderr, " removed %s frag at %p len=%d covered by %s\n", - gxf_name[dx], pge, k2, gxf_name[d]); - X_FRAG(pge)->len[dx] = 0; - for(pge = pge->frwd, j = 1; j < k2; j++, pge = pge->frwd) - X_FRAG(pge)->lenback[dx] = 0; - if(i >= len-1) { /* covers our frag too - maybe with 1 gentry showing */ - /* our frag will be removed as well, prepare a line to replace it */ - gels = ge; - gele = age[(f->aidx + i - 1)%clen]; - fprintf(stderr, " new Line frag at %p-%p len=%d\n", gels, gele, i); - X_FRAG(gels)->len[GEXFI_LINE] = i; - for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[GEXFI_LINE] = j; - } else { - gex_dump_contour(ge, clen); - ge = ge->frwd; - continue; - } - } - if(i >= len-1) /* covers our frag - maybe with 1 gentry showing */ - goto curve_completely_covered; - - /* XXX need to do something better for the case when a curve frag - * is actually nothing but an artifact of two other curves of - * the opposite type touching each other, like on the back of "3" - */ - - /* change the overlapping part to a line */ - gels = ge; - gele = age[(f->aidx + i - 1)%clen]; - /* give preference to local extremums */ - if(X_FRAG(gels)->flags & GEXFF_EXTR) { - gels = gels->frwd; - i--; - } - if(X_FRAG(gele)->flags & GEXFF_EXTR) { - gele = gele->bkwd; - i--; - } - if(gels->bkwd == gele) { - /* Oops the line became negative. Probably should - * never happen but I can't think of any formal reasoning - * leading to that, so check just in case. Restore - * the previous state. - */ - gels = gele; gele = gels->frwd; i = 2; - } - - j = X_FRAG(gels)->lenback[dx] + 1; /* new length */ - if(j != k2) { - X_FRAG(pge)->len[dx] = j; - fprintf(stderr, " cut %s frag at %p len=%d to %p len=%d end overlap with %s\n", - gxf_name[dx], pge, k2, gels, j, gxf_name[d]); - for(gei = gels->frwd; j < k2; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[dx] = 0; - } - - if(gele != ge) { - sge = gele; - f->len[d] = 0; - fprintf(stderr, " cut %s frag at %p len=%d ", gxf_name[d], ge, len); - len--; - for(gei = ge->frwd; gei != gele; gei = gei->frwd, len--) - X_FRAG(gei)->lenback[d] = 0; - X_FRAG(gele)->len[d] = len; - X_FRAG(gele)->lenback[d] = 0; - fprintf(stderr, "to %p len=%d start overlap with %s\n", - sge, len, gxf_name[dx]); - for(gei = gei->frwd, j = 1; j < len; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[d] = j; - - } - if(i > 1) { - fprintf(stderr, " new Line frag at %p-%p len=%d\n", gels, gele, i); - X_FRAG(gels)->len[GEXFI_LINE] = i; - for(gei = gels->frwd, j = 1; j < i; gei = gei->frwd, j++) - X_FRAG(gei)->lenback[GEXFI_LINE] = j; - } - gex_dump_contour(ge, clen); - } - - ge = ge->frwd; - } while(ge != cge->next); - } - - /* - * Assert that there are no conflicts any more and - * for each gentry find the fragment types that start - * and continue here. - */ - ge = cge->next; - do { - f = X_FRAG(ge); - dx = GEXFI_NONE; /* type that starts here */ - dy = GEXFI_NONE; /* type that goes through here */ - for(d = GEXFI_CONVEX; d<= GEXFI_LINE; d++) { - if(f->len[d]) { - if(dx >= 0) { - fprintf(stderr, "**** Internal error in vectorization\n"); - fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n", - g->name, ge, gxf_name[dx], gxf_name[d]); - dumppaths(g, cge->next, cge->next->bkwd); - gex_dump_contour(ge, clen); - exit(1); - } - dx = d; - } - if(f->lenback[d]) { - if(dy >= 0) { - fprintf(stderr, "**** Internal error in vectorization\n"); - fprintf(stderr, "CONFLICT in %s at %p between %s and %s\n", - g->name, ge, gxf_name[dy], gxf_name[d]); - dumppaths(g, cge->next, cge->next->bkwd); - gex_dump_contour(ge, clen); - exit(1); - } - dy = d; - } - } - f->ixstart = dx; - f->ixcont = dy; - ge = ge->frwd; - } while(ge != cge->next); - - /* - * make sure that the contour does not start in the - * middle of a fragment - */ - ge = cge->next; /* old start of the contour */ - f = X_FRAG(ge); - if(f->ixstart == GEXFI_NONE && f->ixcont != GEXFI_NONE) { - /* oops, it's mid-fragment, move the start */ - GENTRY *xge; - - xge = ge->bkwd->next; /* entry following the contour */ - - /* find the first gentry of this frag */ - pge = age[(f->aidx + clen - f->lenback[f->ixcont])%clen]; - - ge->prev = ge->bkwd; - ge->bkwd->next = ge; - - cge->next = pge; - pge->prev = cge; - - pge->bkwd->next = xge; - if(xge) - xge->prev = pge->bkwd; - - cge->ix3 = pge->bkwd->ix3; cge->iy3 = pge->bkwd->iy3; - } - - /* vectorize each fragment separately */ - ge = cge->next; - do { - /* data for curves */ - GENTRY *firstge, *lastge, *gef, *gel, *gei, *gex; - GENTRY *ordhd; /* head of the order list */ - GENTRY **ordlast; - int nsub; /* number of subfrags */ - GEX_FRAG *ff, *lf, *xf; - - f = X_FRAG(ge); - switch(f->ixstart) { - case GEXFI_LINE: - len = f->len[GEXFI_LINE]; - pge = age[(f->aidx + len - 1)%clen]; /* last gentry */ - - if(ge->iy3 == ge->bkwd->iy3) { /* frag starts and ends horizontally */ - k1 = 1/*Y*/ ; /* across the direction of start */ - k2 = 0/*X*/ ; /* along the direction of start */ - } else { /* frag starts and ends vertically */ - k1 = 0/*X*/ ; /* across the direction of start */ - k2 = 1/*Y*/ ; /* along the direction of start */ - } - - if(len % 2) { - /* odd number of entries in the frag */ - double halfstep, halfend; - - f->vect[0][k1] = fscale * ge->ipoints[k1][2]; - f->vect[3][k1] = fscale * pge->ipoints[k1][2]; - - halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) - * 0.5 / ((len+1)/2); - if(f->ixcont != GEXFI_NONE) { - halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - if(X_FRAG(pge)->ixstart != GEXFI_NONE) { - halfend = (pge->ipoints[k2][2] - pge->bkwd->ipoints[k2][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep); - f->vect[3][k2] = fscale * (pge->ipoints[k2][2] - halfstep); - } else { - /* even number of entries */ - double halfstep, halfend; - - f->vect[0][k1] = fscale * ge->ipoints[k1][2]; - halfstep = (pge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) - * 0.5 / (len/2); - if(f->ixcont != GEXFI_NONE) { - halfend = (ge->ipoints[k2][2] - ge->bkwd->ipoints[k2][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - f->vect[0][k2] = fscale * (ge->bkwd->ipoints[k2][2] + halfstep); - - halfstep = (pge->ipoints[k1][2] - ge->bkwd->ipoints[k1][2]) - * 0.5 / (len/2); - if(X_FRAG(pge)->ixstart != GEXFI_NONE) { - halfend = (pge->ipoints[k1][2] - pge->bkwd->ipoints[k1][2]) * 0.5; - if(fabs(halfstep) < fabs(halfend)) /* must be at least half gentry away */ - halfstep = halfend; - } - f->vect[3][k1] = fscale * (pge->ipoints[k1][2] - halfstep); - f->vect[3][k2] = fscale * pge->ipoints[k2][2]; - } - f->vectlen = len; - f->flags |= GEXFF_DRAWLINE; - break; - case GEXFI_CONVEX: - case GEXFI_CONCAVE: - len = f->len[f->ixstart]; - firstge = ge; - lastge = age[(f->aidx + len - 1)%clen]; /* last gentry */ - - nsub = 0; - gex = firstge; - xf = X_FRAG(gex); - xf->prevsub = 0; - xf->sublen = 1; - xf->flags &= ~GEXFF_DONE; - for(gei = firstge->frwd; gei != lastge; gei = gei->frwd) { - xf->sublen++; - if(X_FRAG(gei)->flags & GEXFF_EXTR) { - xf->nextsub = gei; - for(i=0; i<2; i++) - xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]); - nsub++; - xf = X_FRAG(gei); - xf->prevsub = gex; - xf->sublen = 1; - xf->flags &= ~GEXFF_DONE; - gex = gei; - } - } - xf->sublen++; - xf->nextsub = gei; - for(i=0; i<2; i++) - xf->bbox[i] = abs(gei->ipoints[i][2] - gex->bkwd->ipoints[i][2]); - nsub++; - ff = xf; /* remember the beginning of the last subfrag */ - xf = X_FRAG(gei); - xf->prevsub = gex; - if(firstge != lastge) { - xf->nextsub = 0; - xf->sublen = 0; - - /* correct the bounding box of the last and first subfrags for - * intersections with other fragments - */ - if(xf->ixstart != GEXFI_NONE) { - /* ff points to the beginning of the last subfrag */ - for(i=0; i<2; i++) - ff->bbox[i] -= 0.5 * abs(lastge->ipoints[i][2] - lastge->bkwd->ipoints[i][2]); - } - ff = X_FRAG(firstge); - if(ff->ixcont != GEXFI_NONE) { - for(i=0; i<2; i++) - ff->bbox[i] -= 0.5 * abs(firstge->ipoints[i][2] - firstge->bkwd->ipoints[i][2]); - } - } - - fprintf(stderr, " %s frag %p%s nsub=%d\n", gxf_name[f->ixstart], - ge, (f->flags&GEXFF_CIRC)?" circular":"", nsub); - - /* find the symmetry between the subfragments */ - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - gex = ff->nextsub; - xf = X_FRAG(gex); - gel = xf->nextsub; - if(gel == 0) { - ff->flags &= ~GEXFF_SYMNEXT; - break; /* not a circular frag */ - } - good = 1; /* assume that we have symmetry */ - /* gei goes backwards, gex goes forwards from the extremum */ - gei = gex; - /* i is the symmetry axis, j is the other axis (X=0 Y=1) */ - ff->symaxis = i = (gex->ix3 != gex->bkwd->ix3); - j = !i; - for( ; gei!=gef && gex!=gel; gei=gei->bkwd, gex=gex->frwd) { - if( gei->bkwd->ipoints[i][2] != gex->ipoints[i][2] - || gei->bkwd->ipoints[j][2] - gei->ipoints[j][2] - != gex->bkwd->ipoints[j][2] - gex->ipoints[j][2] - ) { - good = 0; /* no symmetry */ - break; - } - } - if(good) { - if( isign(gei->bkwd->ipoints[j][2] - gei->ipoints[j][2]) - != isign(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) { - good = 0; /* oops, goes into another direction */ - } - } - if(good) - ff->flags |= GEXFF_SYMNEXT; - else - ff->flags &= ~GEXFF_SYMNEXT; - } - - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - if((ff->flags & GEXFF_SYMNEXT)==0) { - ff->symxlen = 0; - continue; - } - gex = ff->prevsub; - if(gex == 0 || (X_FRAG(gex)->flags & GEXFF_SYMNEXT)==0) { - ff->symxlen = 0; - continue; - } - ff->symxlen = X_FRAG(gex)->sublen; - xf = X_FRAG(ff->nextsub); - if(xf->sublen < ff->symxlen) - ff->symxlen = xf->sublen; - } - - /* find the symmetry inside the subfragments */ - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - - if(ff->sublen % 2) { - /* we must have an even number of gentries for diagonal symmetry */ - ff->symge = 0; - continue; - } - - /* gei goes forwards from the front */ - gei = gef->frwd; - /* gex goes backwards from the back */ - gex = ff->nextsub->bkwd; - - /* i is the direction of gei, j is the direction of gex */ - i = (gei->iy3 != gei->bkwd->iy3); - j = !i; - for( ; gei->bkwd != gex; gei=gei->frwd, gex=gex->bkwd) { - if( abs(gei->bkwd->ipoints[i][2] - gei->ipoints[i][2]) - != abs(gex->bkwd->ipoints[j][2] - gex->ipoints[j][2]) ) - break; /* no symmetry */ - i = j; - j = !j; - } - if(gei->bkwd == gex) - ff->symge = gex; - else - ff->symge = 0; /* no symmetry */ - } - - /* find the order of calculation: - * prefer to start from long fragments that have the longest - * neighbours symmetric with them, with all being equal prefer - * the fragments that have smaller physical size - */ - ordhd = 0; - for(gef = firstge, count=0; count < nsub; gef = ff->nextsub, count++) { - ff = X_FRAG(gef); - - for(ordlast = &ordhd; *ordlast != 0; ordlast = &xf->ordersub) { - xf = X_FRAG(*ordlast); - if(ff->sublen > xf->sublen) - break; - if(ff->sublen < xf->sublen) - continue; - if(ff->symxlen > xf->symxlen) - break; - if(ff->symxlen < xf->symxlen) - continue; - if(ff->bbox[0] < xf->bbox[0] || ff->bbox[1] < xf->bbox[1]) - break; - } - - ff->ordersub = *ordlast; - *ordlast = gef; - } - - /* vectorize the subfragments */ - for(gef = ordhd; gef != 0; gef = ff->ordersub) { - - /* debugging stuff */ - ff = X_FRAG(gef); - fprintf(stderr, " %p-%p bbox[%g,%g] sym=%p %s len=%d xlen=%d\n", - gef, ff->nextsub, ff->bbox[0], ff->bbox[1], ff->symge, - (ff->flags & GEXFF_SYMNEXT) ? "symnext" : "", - ff->sublen, ff->symxlen); - - dosubfrag(g, f->ixstart, firstge, gef, fscale); - } - - break; - } - ge = ge->frwd; - } while(ge != cge->next); - - free(age); - - } - - } - - /* all the fragments are found, extract the vectorization */ - pge = g->entries; - g->entries = g->lastentry = 0; - g->flags |= GF_FLOAT; - loopge = 0; - skip = 0; - - for(ge = pge; ge != 0; ge = ge->next) { - GEX_FRAG *f, *pf; - - switch(ge->type) { - case GE_LINE: - f = X_FRAG(ge); - if(skip == 0) { - if(f->flags & (GEXFF_DRAWLINE|GEXFF_DRAWCURVE)) { - /* draw a line to the start point */ - fg_rlineto(g, f->vect[0][0], f->vect[0][1]); - /* draw the fragment */ - if(f->flags & GEXFF_DRAWCURVE) - fg_rrcurveto(g, - f->vect[1][0], f->vect[1][1], - f->vect[2][0], f->vect[2][1], - f->vect[3][0], f->vect[3][1]); - else - fg_rlineto(g, f->vect[3][0], f->vect[3][1]); - skip = f->vectlen - 2; - } else { - fg_rlineto(g, fscale * ge->ix3, fscale * ge->iy3); - } - } else - skip--; - break; - case GE_MOVE: - fg_rmoveto(g, -1e6, -1e6); /* will be fixed by GE_PATH */ - skip = 0; - /* remember the reference to update it later */ - loopge = g->lastentry; - break; - case GE_PATH: - /* update the first MOVE of this contour */ - if(loopge) { - loopge->fx3 = g->lastentry->fx3; - loopge->fy3 = g->lastentry->fy3; - loopge = 0; - } - g_closepath(g); - break; - } - } - for(ge = pge; ge != 0; ge = cge) { - cge = ge->next; - free(ge->ext); - free(ge); - } - dumppaths(g, NULL, NULL); - - /* end of vectorization logic */ - } else { - /* convert the data to float */ - GENTRY *ge; - double x, y; - - for(ge = g->entries; ge != 0; ge = ge->next) { - ge->flags |= GEF_FLOAT; - if(ge->type != GE_MOVE && ge->type != GE_LINE) - continue; - - x = fscale * ge->ix3; - y = fscale * ge->iy3; - - ge->fx3 = x; - ge->fy3 = y; - } - g->flags |= GF_FLOAT; - } - - free(hlm); free(vlm); free(amp); -} - -#if 0 -/* print out the bitmap */ -printbmap(bmap, xsz, ysz, xoff, yoff) - char *bmap; - int xsz, ysz, xoff, yoff; -{ - int x, y; - - for(y=ysz-1; y>=0; y--) { - putchar( (y%10==0) ? y/10+'0' : ' ' ); - putchar( y%10+'0' ); - for(x=0; x=0; y--) { - for(x=0; x> 8))) -#define ntohl(x) \ - ((ULONG)((((ULONG)(x) & 0x000000ffU) << 24) | \ - (((ULONG)(x) & 0x0000ff00U) << 8) | \ - (((ULONG)(x) & 0x00ff0000U) >> 8) | \ - (((ULONG)(x) & 0xff000000U) >> 24))) -#endif diff --git a/pdf2swf/ttf2pt1/ft.c b/pdf2swf/ttf2pt1/ft.c deleted file mode 100644 index 12f44c6..0000000 --- a/pdf2swf/ttf2pt1/ft.c +++ /dev/null @@ -1,653 +0,0 @@ -/* - * The font parser using the FreeType library version 2. - * - * see COPYRIGHT - * - */ - -#include "../../config.h" -#ifdef USE_FREETYPE - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pt1.h" -#include "global.h" - -/* prototypes of call entries */ -static void openfont(char *fname, char *arg); -static void closefont( void); -static int getnglyphs ( void); -static int glnames( GLYPH *glyph_list); -static void glmetrics( GLYPH *glyph_list); -static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); -static void fnmetrics( struct font_metrics *fm); -static void glpath( int glyphno, GLYPH *glyph_list); -static void kerning( GLYPH *glyph_list); - -/* globals */ - -/* front-end descriptor */ -struct frontsw freetype_sw = { - /*name*/ "ft", - /*descr*/ "based on the FreeType library", - /*suffix*/ { "ttf", "otf", "pfa", "pfb" }, - /*open*/ openfont, - /*close*/ closefont, - /*nglyphs*/ getnglyphs, - /*glnames*/ glnames, - /*glmetrics*/ glmetrics, - /*glenc*/ glenc, - /*fnmetrics*/ fnmetrics, - /*glpath*/ glpath, - /*kerning*/ kerning, -}; - -/* statics */ - -static char * dupcnstring( unsigned char *s, int len); - -static FT_Library library; -static FT_Face face; - -static int enc_type, enc_found; - -/* SFNT functions do not seem to be included by default in FT2beta8 */ -#define ENABLE_SFNT - -/* - * Open font and prepare to return information to the main driver. - * May print error and warning messages. - * Exit on error. - */ - -static void -openfont( - char *fname, - char *arg /* unused now */ -) -{ - FT_Error error; - - if( FT_Init_FreeType( &library ) ) { - fprintf(stderr, "** FreeType initialization failed\n"); - exit(1); - } - - if( error = FT_New_Face( library, fname, 0, &face ) ) { - if ( error == FT_Err_Unknown_File_Format ) - fprintf(stderr, "**** %s has format unknown to FreeType\n", fname); - else - fprintf(stderr, "**** Cannot access %s ****\n", fname); - exit(1); - } - - if(FT_HAS_FIXED_SIZES(face)) { - WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); - } - if(FT_HAS_MULTIPLE_MASTERS(face)) { - WARNING_1 fprintf(stderr, "Font contains multiple masters, using default\n"); - } - - if(ISDBG(FT)) fprintf(stderr," %d units per EM\n", face->units_per_EM); - - enc_found = 0; -} - -/* - * Close font. - * Exit on error. - */ - -static void -closefont( - void -) -{ - if( FT_Done_Face(face) ) { - WARNING_1 fprintf(stderr, "Errors when closing the font file, ignored\n"); - } - if( FT_Done_FreeType(library) ) { - WARNING_1 fprintf(stderr, "Errors when stopping FreeType, ignored\n"); - } -} - -/* - * Get the number of glyphs in font. - */ - -static int -getnglyphs ( - void -) -{ - if(ISDBG(FT)) fprintf(stderr, "%d glyphs in font\n", face->num_glyphs); - return (int)face->num_glyphs; -} - -/* - * Get the names of the glyphs. - * Returns 0 if the names were assigned, non-zero if the font - * provides no glyph names. - */ - -static int -glnames( - GLYPH *glyph_list -) -{ -#define MAX_NAMELEN 1024 - unsigned char bf[1024]; - int i; - - if( ! FT_HAS_GLYPH_NAMES(face) ) { - WARNING_1 fprintf(stderr, "Font has no glyph names\n"); - return 1; - } - - for(i=0; i < face->num_glyphs; i++) { - if( FT_Get_Glyph_Name(face, i, bf, MAX_NAMELEN) || bf[0]==0 ) { - sprintf(bf, "_g_%d", i); - WARNING_2 fprintf(stderr, - "Glyph No. %d has no postscript name, becomes %s\n", i, bf); - } - glyph_list[i].name = strdup(bf); - if(ISDBG(FT)) fprintf(stderr, "%d has name %s\n", i, bf); - if (glyph_list[i].name == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - return 0; -} - -/* - * Get the metrics of the glyphs. - */ - -static void -glmetrics( - GLYPH *glyph_list -) -{ - GLYPH *g; - int i; - FT_Glyph_Metrics *met; - FT_BBox bbox; - FT_Glyph gly; - - for(i=0; i < face->num_glyphs; i++) { - g = &(glyph_list[i]); - - if( FT_Load_Glyph(face, i, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE) ) { - fprintf(stderr, "Can't load glyph %s, skipped\n", g->name); - continue; - } - - met = &face->glyph->metrics; - - if(FT_HAS_HORIZONTAL(face)) { - g->width = met->horiAdvance; - g->lsb = met->horiBearingX; - } else { - WARNING_2 fprintf(stderr, "Glyph %s has no horizontal metrics, guessed them\n", g->name); - g->width = met->width; - g->lsb = 0; - } - - if( FT_Get_Glyph(face->glyph, &gly) ) { - fprintf(stderr, "Can't access glyph %s bbox, skipped\n", g->name); - continue; - } - - FT_Glyph_Get_CBox(gly, ft_glyph_bbox_unscaled, &bbox); - g->xMin = bbox.xMin; - g->yMin = bbox.yMin; - g->xMax = bbox.xMax; - g->yMax = bbox.yMax; - - g->ttf_pathlen = face->glyph->outline.n_points; - } -} - -/* - * Get the original encoding of the font. - * Returns 1 for if the original encoding is Unicode, 2 if the - * original encoding is other 16-bit, 0 if 8-bit. - */ - -static int -glenc( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - int i, e; - unsigned code; - - if(ISDBG(FT)) - for(e=0; e < face->num_charmaps; e++) { - fprintf(stderr, "found encoding pid=%d eid=%d\n", - face->charmaps[e]->platform_id, - face->charmaps[e]->encoding_id); - } - - if(enc_found) - goto populate_map; - - enc_type = 0; - - /* first check for an explicit PID/EID */ - - if(force_pid != -1) { - for(e=0; e < face->num_charmaps; e++) { - if(face->charmaps[e]->platform_id == force_pid - && face->charmaps[e]->encoding_id == force_eid) { - WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", - force_pid, force_eid); - if( FT_Set_Charmap(face, face->charmaps[e]) ) { - fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); - exit(1); - } - enc_type = 1; - goto populate_map; - } - } - fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", - force_pid, force_eid); - exit(1); - } - - /* next check for a direct Adobe mapping */ - - if(!forcemap) { - for(e=0; e < face->num_charmaps; e++) { - if(face->charmaps[e]->encoding == ft_encoding_adobe_custom) { - WARNING_1 fputs("Found Adobe Custom Encoding\n", stderr); - if( FT_Set_Charmap(face, face->charmaps[e]) ) { - fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); - exit(1); - } - goto populate_map; - } - } - } - - for(e=0; e < face->num_charmaps; e++) { - if(face->charmaps[e]->platform_id == 3) { - switch(face->charmaps[e]->encoding_id) { - case 0: - WARNING_1 fputs("Found Symbol Encoding\n", stderr); - break; - case 1: - WARNING_1 fputs("Found Unicode Encoding\n", stderr); - enc_type = 1; - break; - default: - WARNING_1 { - fprintf(stderr, - "****MS Encoding ID %d not supported****\n", - face->charmaps[e]->encoding_id); - fputs("Treating it like Symbol encoding\n", stderr); - } - break; - } - break; - } - } - if(e >= face->num_charmaps) { - WARNING_1 fputs("No Microsoft encoding, using first encoding available\n", stderr); - e = 0; - } - - if( !face->charmaps || FT_Set_Charmap(face, face->charmaps[e]) ) { - fprintf(stderr, "**** Cannot set charmap in FreeType ****\n"); - } - -populate_map: - enc_found = 1; - for(i=0; i=' ' && c!=127) - *out++ = c; - else if(!warned) { - warned=1; - WARNING_1 fprintf(stderr, "Some font name strings are in Unicode, may not show properly\n"); - } - } - *out = 0; - return res; -} - -/* - * Get the font metrics - */ -static void -fnmetrics( - struct font_metrics *fm -) -{ - char *str; - static char *fieldstocheck[3]; -#ifdef ENABLE_SFNT - FT_SfntName sn; -#endif /* ENABLE_SFNT */ - int i; - - fm->italic_angle = 0.0; /* FreeType hides the angle */ - fm->underline_position = face->underline_position; - fm->underline_thickness = face->underline_thickness; - fm->is_fixed_pitch = FT_IS_FIXED_WIDTH(face); - - fm->ascender = face->ascender; - fm->descender = face->descender; - - fm->units_per_em = face->units_per_EM; - - fm->bbox[0] = face->bbox.xMin; - fm->bbox[1] = face->bbox.yMin; - fm->bbox[2] = face->bbox.xMax; - fm->bbox[3] = face->bbox.yMax; - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_COPYRIGHT, &sn) ) -#endif /* ENABLE_SFNT */ - fm->name_copyright = ""; -#ifdef ENABLE_SFNT - else - fm->name_copyright = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - - fm->name_family = face->family_name; - - fm->name_style = face->style_name; - if(fm->name_style == NULL) - fm->name_style = ""; - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_FULL_NAME, &sn) ) -#endif /* ENABLE_SFNT */ - { - int len; - - if(!fm->name_family) - fm->name_family = ""; - if(!fm->name_style) - fm->name_style= ""; - len = strlen(fm->name_family) + strlen(fm->name_style) + 2; - if(( fm->name_full = malloc(len) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - strcpy(fm->name_full, fm->name_family); - if(strlen(fm->name_style) != 0) { - strcat(fm->name_full, " "); - strcat(fm->name_full, fm->name_style); - } - } -#ifdef ENABLE_SFNT - else - fm->name_full = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_VERSION_STRING, &sn) ) -#endif /* ENABLE_SFNT */ - fm->name_version = "1.0"; -#ifdef ENABLE_SFNT - else - fm->name_version = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - -#ifdef ENABLE_SFNT - if( FT_Get_Sfnt_Name(face, TT_NAME_ID_PS_NAME , &sn) ) { -#endif /* ENABLE_SFNT */ - if(( fm->name_ps = strdup(fm->name_full) )==NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } -#ifdef ENABLE_SFNT - } else - fm->name_ps = dupcnstring(sn.string, sn.string_len); -#endif /* ENABLE_SFNT */ - for(i=0; fm->name_ps[i]!=0; i++) - if(fm->name_ps[i] == ' ') - fm->name_ps[i] = '_'; /* no spaces in the Postscript name */ - - /* guess the boldness from the font names */ - fm->force_bold=0; - - fieldstocheck[0] = fm->name_style; - fieldstocheck[1] = fm->name_full; - fieldstocheck[2] = fm->name_ps; - - for(i=0; !fm->force_bold && iforce_bold=1; - break; - } - } - } -} - -/* - * Functions to decompose the outlines - */ - -static GLYPH *curg; -static double lastx, lasty; - -static int -outl_moveto( - FT_Vector *to, - void *unused -) -{ - double tox, toy; - - tox = fscale((double)to->x); toy = fscale((double)to->y); - - /* FreeType does not do explicit closepath() */ - if(curg->lastentry) { - g_closepath(curg); - } - fg_rmoveto(curg, tox, toy); - lastx = tox; lasty = toy; - - return 0; -} - -static int -outl_lineto( - FT_Vector *to, - void *unused -) -{ - double tox, toy; - - tox = fscale((double)to->x); toy = fscale((double)to->y); - - fg_rlineto(curg, tox, toy); - lastx = tox; lasty = toy; - - return 0; -} - -static int -outl_conicto( - FT_Vector *control1, - FT_Vector *to, - void *unused -) -{ - double c1x, c1y, tox, toy; - - c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); - tox = fscale((double)to->x); toy = fscale((double)to->y); - - fg_rrcurveto(curg, - (lastx + 2.0 * c1x) / 3.0, (lasty + 2.0 * c1y) / 3.0, - (2.0 * c1x + tox) / 3.0, (2.0 * c1y + toy) / 3.0, - tox, toy ); - lastx = tox; lasty = toy; - - return 0; -} - -static int -outl_cubicto( - FT_Vector *control1, - FT_Vector *control2, - FT_Vector *to, - void *unused -) -{ - double c1x, c1y, c2x, c2y, tox, toy; - - c1x = fscale((double)control1->x); c1y = fscale((double)control1->y); - c2x = fscale((double)control2->x); c2y = fscale((double)control2->y); - tox = fscale((double)to->x); toy = fscale((double)to->y); - - fg_rrcurveto(curg, c1x, c1y, c2x, c2y, tox, toy); - lastx = tox; lasty = toy; - - return 0; -} - -static FT_Outline_Funcs ft_outl_funcs = { - outl_moveto, - outl_lineto, - outl_conicto, - outl_cubicto, - 0, - 0 -}; - -/* - * Get the path of contrours for a glyph. - */ - -static void -glpath( - int glyphno, - GLYPH *glyf_list -) -{ - FT_Outline *ol; - - curg = &glyf_list[glyphno]; - - if( FT_Load_Glyph(face, glyphno, FT_LOAD_NO_BITMAP|FT_LOAD_NO_SCALE|FT_LOAD_NO_HINTING) - || face->glyph->format != ft_glyph_format_outline ) { - fprintf(stderr, "Can't load glyph %s, skipped\n", curg->name); - return; - } - - ol = &face->glyph->outline; - lastx = 0.0; lasty = 0.0; - - if( FT_Outline_Decompose(ol, &ft_outl_funcs, NULL) ) { - fprintf(stderr, "Can't decompose outline of glyph %s, skipped\n", curg->name); - return; - } - - /* FreeType does not do explicit closepath() */ - if(curg->lastentry) { - g_closepath(curg); - } - - if(ol->flags & ft_outline_reverse_fill) { - assertpath(curg->entries, __FILE__, __LINE__, curg->name); - reversepaths(curg); - } -} - -/* - * Get the kerning data. - */ - -static void -kerning( - GLYPH *glyph_list -) -{ - int i, j, n; - int nglyphs = face->num_glyphs; - FT_Vector k; - GLYPH *gl; - - if( nglyphs == 0 || !FT_HAS_KERNING(face) ) { - WARNING_1 fputs("No Kerning data\n", stderr); - return; - } - - for(i=0; i= 1) -#define WARNING_2 if(warnlevel >= 2) -#define WARNING_3 if(warnlevel >= 3) -#define WARNING_4 if(warnlevel >= 4) - -/* - * Bitmap control macros - */ - -#define BITMAP_BYTES(size) (((size)+7)>>3) -#define DEF_BITMAP(name, size) unsigned char name[BITMAP_BYTES(size)] -#define SET_BITMAP(name, bit) ( name[(bit)>>3] |= (1<<((bit)&7)) ) -#define CLR_BITMAP(name, bit) ( name[(bit)>>3] &= ~(1<<((bit)&7)) ) -#define IS_BITMAP(name, bit) ( name[(bit)>>3] & (1<<((bit)&7)) ) - -/* debugging */ - -/* debug flags */ -#define DEBUG_UNICODE 0x00000001 /* unicode to 8-bit code conversion */ -#define DEBUG_MAINSTEMS 0x00000002 /* glyph-wide main stem generation */ -#define DEBUG_SUBSTEMS 0x00000004 /* substituted stem generation */ -#define DEBUG_STEMS (DEBUG_MAINSTEMS|DEBUG_SUBSTEMS) -#define DEBUG_REVERSAL 0x00000008 /* reversal of the paths */ -#define DEBUG_FIXCVDIR 0x00000010 /* fixcvdir() */ -#define DEBUG_STEMOVERLAP 0x00000020 /* stemoverlap() */ -#define DEBUG_BLUESTEMS 0x00000040 /* markbluestems() */ -#define DEBUG_STRAIGHTEN 0x00000080 /* markbluestems() */ -#define DEBUG_EXTMAP 0x00000100 /* parsing of external map */ -#define DEBUG_TOINT 0x00000200 /* conversion of path to integer */ -#define DEBUG_BUILDG 0x00000400 /* building of glyph path */ -#define DEBUG_QUAD 0x00000800 /* splitting curves by quadrants */ -#define DEBUG_SQEQ 0x00001000 /* square equation solver */ -#define DEBUG_COMPOSITE 0x00002000 /* handling of composite glyphs */ -#define DEBUG_FCONCISE 0x00004000 /* normalization of curves */ -#define DEBUG_FT 0x00008000 /* FreeType front-end */ -#define DEBUG_DISABLED 0x80000000 /* special flag: temporary disable debugging */ - -/* at what we want to look now */ -#ifndef DEBUG -# define DEBUG (0) -#endif - -/* uncomment the next line if debugging data is wanted for one glyph only */ -/* #define DBG_GLYPH "_517" /* */ - -#if DEBUG==0 -# define ISDBG(name) (0) -# define ENABLEDBG(condition) (0) -# define DISABLEDBG(condition) (0) -#else - extern int debug; /* collection of the flags */ -/* this ISDBG will only work on ANSI C, not K&R */ -# define ISDBG(name) ( (debug & DEBUG_DISABLED) ? 0 : (debug & (DEBUG_##name)) ) -# define ENABLEDBG(condition) ( (condition) ? (debug&=~DEBUG_DISABLED) : 0 ) -# define DISABLEDBG(condition) ( (condition) ? (debug|=DEBUG_DISABLED) : 0 ) -#endif - -#ifdef DBG_GLYPH -# define DBG_TO_GLYPH(g) DISABLEDBG( strcmp( (g)->name, DBG_GLYPH ) ) -# define DBG_FROM_GLYPH(g) ENABLEDBG(1) -#else -# define DBG_TO_GLYPH(g) (0) -# define DBG_FROM_GLYPH(g) (0) -#endif - -/* prototypes */ -int iscale( int val); -double fscale( double val); -int unicode_rev_lookup( int unival); -void bmp_outline( GLYPH *g, int scale, char *bmap, - int xsz, int ysz, int xoff, int yoff); -int isign( int x); -int fsign( double x); - -/* global metrics for a font */ - -struct font_metrics { - /* post */ - double italic_angle; - short underline_position; - short underline_thickness; - short is_fixed_pitch; - - /* hhea */ - short ascender; - short descender; - - /* head */ - unsigned short units_per_em; - short bbox[4]; - - /* name */ - char *name_copyright; - char *name_family; - char *name_style; - char *name_full; - char *name_version; - char *name_ps; - - /* other */ - int force_bold; -}; - -/* size of the encoding table - glyphs beyond 255 are actually unnumbered */ - -#define ENCTABSZ 1024 - -/* switch table structure for front-ends */ - -#define MAXSUFFIX 10 - -struct frontsw { - char *name; /* name of the front end */ - char *descr; /* description of the front end */ - char *suffix[MAXSUFFIX]; /* possible file name suffixes */ - - void (*open)(char *fname, char *arg); /* open font file */ - void (*close)(void); /* close font file */ - int (*nglyphs)(void); /* get the number of glyphs */ - int (*glnames)(GLYPH *glyphs); /* get the names of glyphs */ - void (*glmetrics)(GLYPH *glyphs); /* get the metrics of glyphs */ - int (*glenc)(GLYPH *glyphs, int *enc, int *unimap); /* get the encoding */ - void (*fnmetrics)(struct font_metrics *fm); /* get the font metrics */ - void (*glpath)(int glyphno, GLYPH *glyphs); /* get the glyph path */ - void (*kerning)(GLYPH *glyph_list); /* extract the kerning data */ -}; diff --git a/pdf2swf/ttf2pt1/pt1.c b/pdf2swf/ttf2pt1/pt1.c deleted file mode 100644 index 3f2bc08..0000000 --- a/pdf2swf/ttf2pt1/pt1.c +++ /dev/null @@ -1,7372 +0,0 @@ -/* - * see COPYRIGHT - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -# include -# include -#else -# include "win_missing.h" -#endif - -#include "ttf.h" -#include "pt1.h" -#include "global.h" - -/* big and small values for comparisons */ -#define FBIGVAL (1e20) -#define FEPS (100000./FBIGVAL) - -/* names of the axes */ -#define X 0 -#define Y 1 - -/* the GENTRY extension structure used in fforceconcise() */ - -struct gex_con { - double d[2 /*X, Y*/]; /* sizes of curve */ - double sin2; /* squared sinus of the angle to the next gentry */ - double len2; /* squared distance between the endpoints */ - -/* number of reference dots taken from each curve */ -#define NREFDOTS 3 - - double dots[NREFDOTS][2]; /* reference dots */ - - int flags; /* flags for gentry and tits joint to the next gentry */ -/* a vertical or horizontal line may be in 2 quadrants at once */ -#define GEXF_QUL 0x00000001 /* in up-left quadrant */ -#define GEXF_QUR 0x00000002 /* in up-right quadrant */ -#define GEXF_QDR 0x00000004 /* in down-right quadrant */ -#define GEXF_QDL 0x00000008 /* in down-left quadrant */ -#define GEXF_QMASK 0x0000000F /* quadrant mask */ - -/* if a line is nearly vertical or horizontal, we remember that idealized quartant too */ -#define GEXF_QTO_IDEAL(f) (((f)&0xF)<<4) -#define GEXF_QFROM_IDEAL(f) (((f)&0xF0)>>4) -#define GEXF_IDQ_L 0x00000090 /* left */ -#define GEXF_IDQ_R 0x00000060 /* right */ -#define GEXF_IDQ_U 0x00000030 /* up */ -#define GEXF_IDQ_D 0x000000C0 /* down */ - -/* possibly can be joined with conditions: - * (in order of increasing preference, the numeric order is important) - */ -#define GEXF_JLINE 0x00000100 /* into one line */ -#define GEXF_JIGN 0x00000200 /* if one entry's tangent angle is ignored */ -#define GEXF_JID 0x00000400 /* if one entry is idealized to hor/vert */ -#define GEXF_JFLAT 0x00000800 /* if one entry is flattened */ -#define GEXF_JGOOD 0x00001000 /* perfectly, no additional maodifications */ - -#define GEXF_JMASK 0x00001F00 /* the mask of all above */ -#define GEXF_JCVMASK 0x00001E00 /* the mask of all above except JLINE */ - -/* which entry needs to be modified for conditional joining */ -#define GEXF_JIGN1 0x00002000 -#define GEXF_JIGN2 0x00004000 -#define GEXF_JIGNDIR(dir) (GEXF_JIGN1<<(dir)) -#define GEXF_JID1 0x00008000 -#define GEXF_JID2 0x00010000 -#define GEXF_JIDDIR(dir) (GEXF_JID1<<(dir)) -#define GEXF_JFLAT1 0x00020000 -#define GEXF_JFLAT2 0x00040000 -#define GEXF_JFLATDIR(dir) (GEXF_JFLAT1<<(dir)) - -#define GEXF_VERT 0x00100000 /* is nearly vertical */ -#define GEXF_HOR 0x00200000 /* is nearly horizontal */ -#define GEXF_FLAT 0x00400000 /* is nearly flat */ - -#define GEXF_VDOTS 0x01000000 /* the dots are valid */ - - signed char isd[2 /*X,Y*/]; /* signs of the sizes */ -}; -typedef struct gex_con GEX_CON; - -/* convenience macros */ -#define X_CON(ge) ((GEX_CON *)((ge)->ext)) -#define X_CON_D(ge) (X_CON(ge)->d) -#define X_CON_DX(ge) (X_CON(ge)->d[0]) -#define X_CON_DY(ge) (X_CON(ge)->d[1]) -#define X_CON_ISD(ge) (X_CON(ge)->isd) -#define X_CON_ISDX(ge) (X_CON(ge)->isd[0]) -#define X_CON_ISDY(ge) (X_CON(ge)->isd[1]) -#define X_CON_SIN2(ge) (X_CON(ge)->sin2) -#define X_CON_LEN2(ge) (X_CON(ge)->len2) -#define X_CON_F(ge) (X_CON(ge)->flags) - -/* performance statistics about guessing the concise curves */ -static int ggoodcv=0, ggoodcvdots=0, gbadcv=0, gbadcvdots=0; - -int stdhw, stdvw; /* dominant stems widths */ -int stemsnaph[12], stemsnapv[12]; /* most typical stem width */ - -int bluevalues[14]; -int nblues; -int otherblues[10]; -int notherb; -int bbox[4]; /* the FontBBox array */ -double italic_angle; - -GLYPH *glyph_list; -int encoding[ENCTABSZ]; /* inverse of glyph[].char_no */ -int kerning_pairs = 0; - -/* prototypes */ -static void fixcvdir( GENTRY * ge, int dir); -static void fixcvends( GENTRY * ge); -static int fgetcvdir( GENTRY * ge); -static int igetcvdir( GENTRY * ge); -static int fiszigzag( GENTRY *ge); -static int iiszigzag( GENTRY *ge); -static GENTRY * freethisge( GENTRY *ge); -static void addgeafter( GENTRY *oge, GENTRY *nge ); -static GENTRY * newgentry( int flags); -static void debugstems( char *name, STEM * hstems, int nhs, STEM * vstems, int nvs); -static int addbluestems( STEM *s, int n); -static void sortstems( STEM * s, int n); -static int stemoverlap( STEM * s1, STEM * s2); -static int steminblue( STEM *s); -static void markbluestems( STEM *s, int nold); -static int joinmainstems( STEM * s, int nold, int useblues); -static void joinsubstems( STEM * s, short *pairs, int nold, int useblues); -static void fixendpath( GENTRY *ge); -static void fdelsmall( GLYPH *g, double minlen); -static void alloc_gex_con( GENTRY *ge); -static double fjointsin2( GENTRY *ge1, GENTRY *ge2); -static double fcvarea( GENTRY *ge); -static double fcvval( GENTRY *ge, int axis, double t); -static void fsampledots( GENTRY *ge, double dots[][2], int ndots); -static void fnormalizege( GENTRY *ge); -static void fanalyzege( GENTRY *ge); -static void fanalyzejoint( GENTRY *ge); -static void fconcisecontour( GLYPH *g, GENTRY *ge); -static double fclosegap( GENTRY *from, GENTRY *to, int axis, - double gap, double *ret); - -int -isign( - int x -) -{ - if (x > 0) - return 1; - else if (x < 0) - return -1; - else - return 0; -} - -int -fsign( - double x -) -{ - if (x > 0.0) - return 1; - else if (x < 0.0) - return -1; - else - return 0; -} - -static GENTRY * -newgentry( - int flags -) -{ - GENTRY *ge; - - ge = calloc(1, sizeof(GENTRY)); - - if (ge == 0) { - fprintf(stderr, "***** Memory allocation error *****\n"); - exit(255); - } - ge->stemid = -1; - ge->flags = flags; - /* the rest is set to 0 by calloc() */ - return ge; -} - -/* - * Routines to print out Postscript functions with optimization - */ - -void -rmoveto( - int dx, - int dy -) -{ - if (optimize && dx == 0) - fprintf(pfa_file, "%d vmoveto\n", dy); - else if (optimize && dy == 0) - fprintf(pfa_file, "%d hmoveto\n", dx); - else - fprintf(pfa_file, "%d %d rmoveto\n", dx, dy); -} - -void -rlineto( - int dx, - int dy -) -{ - if (optimize && dx == 0 && dy == 0) /* for special pathologic - * case */ - return; - else if (optimize && dx == 0) - fprintf(pfa_file, "%d vlineto\n", dy); - else if (optimize && dy == 0) - fprintf(pfa_file, "%d hlineto\n", dx); - else - fprintf(pfa_file, "%d %d rlineto\n", dx, dy); -} - -void -rrcurveto( - int dx1, - int dy1, - int dx2, - int dy2, - int dx3, - int dy3 -) -{ - /* first two ifs are for crazy cases that occur surprisingly often */ - if (optimize && dx1 == 0 && dx2 == 0 && dx3 == 0) - rlineto(0, dy1 + dy2 + dy3); - else if (optimize && dy1 == 0 && dy2 == 0 && dy3 == 0) - rlineto(dx1 + dx2 + dx3, 0); - else if (optimize && dy1 == 0 && dx3 == 0) - fprintf(pfa_file, "%d %d %d %d hvcurveto\n", - dx1, dx2, dy2, dy3); - else if (optimize && dx1 == 0 && dy3 == 0) - fprintf(pfa_file, "%d %d %d %d vhcurveto\n", - dy1, dx2, dy2, dx3); - else - fprintf(pfa_file, "%d %d %d %d %d %d rrcurveto\n", - dx1, dy1, dx2, dy2, dx3, dy3); -} - -void -closepath(void) -{ - fprintf(pfa_file, "closepath\n"); -} - -/* - * Many of the path processing routines exist (or will exist) in - * both floating-point and integer version. Fimally most of the - * processing will go in floating point and the integer processing - * will become legacy. - * The names of floating routines start with f, names of integer - * routines start with i, and those old routines existing in one - * version only have no such prefix at all. - */ - -/* -** Routine that checks integrity of the path, for debugging -*/ - -void -assertpath( - GENTRY * from, - char *file, - int line, - char *name -) -{ - GENTRY *first, *pe, *ge; - int isfloat; - - if(from==0) - return; - isfloat = (from->flags & GEF_FLOAT); - pe = from->prev; - for (ge = from; ge != 0; pe = ge, ge = ge->next) { - if( (ge->flags & GEF_FLOAT) ^ isfloat ) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "float flag changes from %s to %s at 0x%p (type %c, prev type %c)\n", - (isfloat ? "TRUE" : "FALSE"), (isfloat ? "FALSE" : "TRUE"), ge, ge->type, pe->type); - abort(); - } - if (pe != ge->prev) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "unidirectional chain 0x%x -next-> 0x%x -prev-> 0x%x \n", - pe, ge, ge->prev); - abort(); - } - - switch(ge->type) { - case GE_MOVE: - break; - case GE_PATH: - if (ge->prev == 0) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "empty path at 0x%x \n", ge); - abort(); - } - break; - case GE_LINE: - case GE_CURVE: - if(ge->frwd->bkwd != ge) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "unidirectional chain 0x%x -frwd-> 0x%x -bkwd-> 0x%x \n", - ge, ge->frwd, ge->frwd->bkwd); - abort(); - } - if(ge->prev->type == GE_MOVE) { - first = ge; - if(ge->bkwd->next->type != GE_PATH) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "broken first backlink 0x%x -bkwd-> 0x%x -next-> 0x%x \n", - ge, ge->bkwd, ge->bkwd->next); - abort(); - } - } - if(ge->next->type == GE_PATH) { - if(ge->frwd != first) { - fprintf(stderr, "**! assertpath: called from %s line %d (%s) ****\n", file, line, name); - fprintf(stderr, "broken loop 0x%x -...-> 0x%x -frwd-> 0x%x \n", - first, ge, ge->frwd); - abort(); - } - } - break; - } - - } -} - -void -assertisfloat( - GLYPH *g, - char *msg -) -{ - if( !(g->flags & GF_FLOAT) ) { - fprintf(stderr, "**! Glyph %s is not float: %s\n", g->name, msg); - abort(); - } - if(g->lastentry) { - if( !(g->lastentry->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! Glyphs %s last entry is int: %s\n", g->name, msg); - abort(); - } - } -} - -void -assertisint( - GLYPH *g, - char *msg -) -{ - if( (g->flags & GF_FLOAT) ) { - fprintf(stderr, "**! Glyph %s is not int: %s\n", g->name, msg); - abort(); - } - if(g->lastentry) { - if( (g->lastentry->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! Glyphs %s last entry is float: %s\n", g->name, msg); - abort(); - } - } -} - - -/* - * Routines to save the generated data about glyph - */ - -void -fg_rmoveto( - GLYPH * g, - double x, - double y) -{ - GENTRY *oge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: f rmoveto(%g, %g)\n", g->name, x, y); - - assertisfloat(g, "adding float MOVE"); - - if ((oge = g->lastentry) != 0) { - if (oge->type == GE_MOVE) { /* just eat up the first move */ - oge->fx3 = x; - oge->fy3 = y; - } else if (oge->type == GE_LINE || oge->type == GE_CURVE) { - fprintf(stderr, "Glyph %s: MOVE in middle of path\n", g->name); - } else { - GENTRY *nge; - - nge = newgentry(GEF_FLOAT); - nge->type = GE_MOVE; - nge->fx3 = x; - nge->fy3 = y; - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } - } else { - GENTRY *nge; - - nge = newgentry(GEF_FLOAT); - nge->type = GE_MOVE; - nge->fx3 = x; - nge->fy3 = y; - nge->bkwd = (GENTRY*)&g->entries; - g->entries = g->lastentry = nge; - } - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -void -ig_rmoveto( - GLYPH * g, - int x, - int y) -{ - GENTRY *oge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: i rmoveto(%d, %d)\n", g->name, x, y); - - assertisint(g, "adding int MOVE"); - - if ((oge = g->lastentry) != 0) { - if (oge->type == GE_MOVE) { /* just eat up the first move */ - oge->ix3 = x; - oge->iy3 = y; - } else if (oge->type == GE_LINE || oge->type == GE_CURVE) { - fprintf(stderr, "Glyph %s: MOVE in middle of path, ignored\n", g->name); - } else { - GENTRY *nge; - - nge = newgentry(0); - nge->type = GE_MOVE; - nge->ix3 = x; - nge->iy3 = y; - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } - } else { - GENTRY *nge; - - nge = newgentry(0); - nge->type = GE_MOVE; - nge->ix3 = x; - nge->iy3 = y; - nge->bkwd = (GENTRY*)&g->entries; - g->entries = g->lastentry = nge; - } - -} - -void -fg_rlineto( - GLYPH * g, - double x, - double y) -{ - GENTRY *oge, *nge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: f rlineto(%g, %g)\n", g->name, x, y); - - assertisfloat(g, "adding float LINE"); - - nge = newgentry(GEF_FLOAT); - nge->type = GE_LINE; - nge->fx3 = x; - nge->fy3 = y; - - if ((oge = g->lastentry) != 0) { - if (x == oge->fx3 && y == oge->fy3) { /* empty line */ - /* ignore it or we will get in troubles later */ - free(nge); - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name); - free(nge); - } - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -void -ig_rlineto( - GLYPH * g, - int x, - int y) -{ - GENTRY *oge, *nge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: i rlineto(%d, %d)\n", g->name, x, y); - - assertisint(g, "adding int LINE"); - - nge = newgentry(0); - nge->type = GE_LINE; - nge->ix3 = x; - nge->iy3 = y; - - if ((oge = g->lastentry) != 0) { - if (x == oge->ix3 && y == oge->iy3) { /* empty line */ - /* ignore it or we will get in troubles later */ - free(nge); - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: LINE outside of path\n", g->name); - free(nge); - } - -} - -void -fg_rrcurveto( - GLYPH * g, - double x1, - double y1, - double x2, - double y2, - double x3, - double y3) -{ - GENTRY *oge, *nge; - - oge = g->lastentry; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: f rrcurveto(%g, %g, %g, %g, %g, %g)\n" - ,g->name, x1, y1, x2, y2, x3, y3); - - assertisfloat(g, "adding float CURVE"); - - if (oge && oge->fx3 == x1 && x1 == x2 && x2 == x3) /* check if it's - * actually a line */ - fg_rlineto(g, x1, y3); - else if (oge && oge->fy3 == y1 && y1 == y2 && y2 == y3) - fg_rlineto(g, x3, y1); - else { - nge = newgentry(GEF_FLOAT); - nge->type = GE_CURVE; - nge->fx1 = x1; - nge->fy1 = y1; - nge->fx2 = x2; - nge->fy2 = y2; - nge->fx3 = x3; - nge->fy3 = y3; - - if (oge != 0) { - if (x3 == oge->fx3 && y3 == oge->fy3) { - free(nge); /* consider this curve empty */ - /* ignore it or we will get in troubles later */ - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name); - free(nge); - } - } - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -void -ig_rrcurveto( - GLYPH * g, - int x1, - int y1, - int x2, - int y2, - int x3, - int y3) -{ - GENTRY *oge, *nge; - - oge = g->lastentry; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: i rrcurveto(%d, %d, %d, %d, %d, %d)\n" - ,g->name, x1, y1, x2, y2, x3, y3); - - assertisint(g, "adding int CURVE"); - - if (oge && oge->ix3 == x1 && x1 == x2 && x2 == x3) /* check if it's - * actually a line */ - ig_rlineto(g, x1, y3); - else if (oge && oge->iy3 == y1 && y1 == y2 && y2 == y3) - ig_rlineto(g, x3, y1); - else { - nge = newgentry(0); - nge->type = GE_CURVE; - nge->ix1 = x1; - nge->iy1 = y1; - nge->ix2 = x2; - nge->iy2 = y2; - nge->ix3 = x3; - nge->iy3 = y3; - - if (oge != 0) { - if (x3 == oge->ix3 && y3 == oge->iy3) { - free(nge); /* consider this curve empty */ - /* ignore it or we will get in troubles later */ - return; - } - if (g->path == 0) { - g->path = nge; - nge->bkwd = nge->frwd = nge; - } else { - oge->frwd = nge; - nge->bkwd = oge; - g->path->bkwd = nge; - nge->frwd = g->path; - } - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - } else { - WARNING_1 fprintf(stderr, "Glyph %s: CURVE outside of path\n", g->name); - free(nge); - } - } -} - -void -g_closepath( - GLYPH * g -) -{ - GENTRY *oge, *nge; - - if (ISDBG(BUILDG)) - fprintf(stderr, "%s: closepath\n", g->name); - - oge = g->lastentry; - - if (g->path == 0) { - WARNING_1 fprintf(stderr, "Warning: **** closepath on empty path in glyph \"%s\" ****\n", - g->name); - if (oge == 0) { - WARNING_1 fprintf(stderr, "No previois entry\n"); - } else { - WARNING_1 fprintf(stderr, "Previous entry type: %c\n", oge->type); - if (oge->type == GE_MOVE) { - g->lastentry = oge->prev; - if (oge->prev == 0) - g->entries = 0; - else - g->lastentry->next = 0; - free(oge); - } - } - return; - } - - nge = newgentry(oge->flags & GEF_FLOAT); /* keep the same type */ - nge->type = GE_PATH; - - g->path = 0; - - oge->next = nge; - nge->prev = oge; - g->lastentry = nge; - - if (0 && ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); -} - -/* - * * SB * Routines to smooth and fix the glyphs - */ - -/* -** we don't want to see the curves with coinciding middle and -** outer points -*/ - -static void -fixcvends( - GENTRY * ge -) -{ - int dx, dy; - int x0, y0, x1, y1, x2, y2, x3, y3; - - if (ge->type != GE_CURVE) - return; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! fixcvends(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - x0 = ge->prev->ix3; - y0 = ge->prev->iy3; - x1 = ge->ix1; - y1 = ge->iy1; - x2 = ge->ix2; - y2 = ge->iy2; - x3 = ge->ix3; - y3 = ge->iy3; - - - /* look at the start of the curve */ - if (x1 == x0 && y1 == y0) { - dx = x2 - x1; - dy = y2 - y1; - - if (dx == 0 && dy == 0 - || x2 == x3 && y2 == y3) { - /* Oops, we actually have a straight line */ - /* - * if it's small, we hope that it will get optimized - * later - */ - if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) { - ge->ix1 = x3; - ge->iy1 = y3; - ge->ix2 = x0; - ge->iy2 = y0; - } else {/* just make it a line */ - ge->type = GE_LINE; - } - } else { - if (abs(dx) < 4 && abs(dy) < 4) { /* consider it very - * small */ - ge->ix1 = x2; - ge->iy1 = y2; - } else if (abs(dx) < 8 && abs(dy) < 8) { /* consider it small */ - ge->ix1 += dx / 2; - ge->iy1 += dy / 2; - } else { - ge->ix1 += dx / 4; - ge->iy1 += dy / 4; - } - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) { - if (abs(x3 - x0) * abs(ge->iy1 - y0) > abs(y3 - y0) * abs(ge->ix1 - x0)) - ge->ix1 += isign(dx); - } else { - if (abs(x3 - x0) * abs(ge->iy1 - y0) < abs(y3 - y0) * abs(ge->ix1 - x0)) - ge->iy1 += isign(dy); - } - - ge->ix2 += (x3 - x2) / 8; - ge->iy2 += (y3 - y2) / 8; - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(y3 - y2) < abs(y3 - y0) * abs(x3 - x2)) { - if (abs(x3 - x0) * abs(y3 - ge->iy2) > abs(y3 - y0) * abs(x3 - ge->ix2)) - ge->iy1 -= isign(y3 - y2); - } else { - if (abs(x3 - x0) * abs(y3 - ge->iy2) < abs(y3 - y0) * abs(x3 - ge->ix2)) - ge->ix1 -= isign(x3 - x2); - } - - } - } else if (x2 == x3 && y2 == y3) { - dx = x1 - x2; - dy = y1 - y2; - - if (dx == 0 && dy == 0) { - /* Oops, we actually have a straight line */ - /* - * if it's small, we hope that it will get optimized - * later - */ - if (abs(x3 - x0) <= 2 || abs(y3 - y0) <= 2) { - ge->ix1 = x3; - ge->iy1 = y3; - ge->ix2 = x0; - ge->iy2 = y0; - } else {/* just make it a line */ - ge->type = GE_LINE; - } - } else { - if (abs(dx) < 4 && abs(dy) < 4) { /* consider it very - * small */ - ge->ix2 = x1; - ge->iy2 = y1; - } else if (abs(dx) < 8 && abs(dy) < 8) { /* consider it small */ - ge->ix2 += dx / 2; - ge->iy2 += dy / 2; - } else { - ge->ix2 += dx / 4; - ge->iy2 += dy / 4; - } - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(dy) < abs(y3 - y0) * abs(dx)) { - if (abs(x3 - x0) * abs(ge->iy2 - y3) > abs(y3 - y0) * abs(ge->ix2 - x3)) - ge->ix2 += isign(dx); - } else { - if (abs(x3 - x0) * abs(ge->iy2 - y3) < abs(y3 - y0) * abs(ge->ix2 - x3)) - ge->iy2 += isign(dy); - } - - ge->ix1 += (x0 - x1) / 8; - ge->iy1 += (y0 - y1) / 8; - /* make sure that it's still on the same side */ - if (abs(x3 - x0) * abs(y0 - y1) < abs(y3 - y0) * abs(x0 - x1)) { - if (abs(x3 - x0) * abs(y0 - ge->iy1) > abs(y3 - y0) * abs(x0 - ge->ix1)) - ge->iy1 -= isign(y0 - y1); - } else { - if (abs(x3 - x0) * abs(y0 - ge->iy1) < abs(y3 - y0) * abs(x0 - ge->ix1)) - ge->ix1 -= isign(x0 - x1); - } - - } - } -} - -/* -** After transformations we want to make sure that the resulting -** curve is going in the same quadrant as the original one, -** because rounding errors introduced during transformations -** may make the result completeley wrong. -** -** `dir' argument describes the direction of the original curve, -** it is the superposition of two values for the front and -** rear ends of curve: -** -** >EQUAL - goes over the line connecting the ends -** =EQUAL - coincides with the line connecting the ends -** flags & GEF_FLOAT) { - fprintf(stderr, "**! fixcvdir(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - fdir = (dir & CVDIR_FRONT) - CVDIR_FEQUAL; - if ((dir & CVDIR_REAR) == CVDIR_RSAME) - rdir = fdir; /* we need only isign, exact value doesn't matter */ - else - rdir = (dir & CVDIR_REAR) - CVDIR_REQUAL; - - fixcvends(ge); - - c = isign(ge->ix3 - ge->prev->ix3); /* note the direction of - * curve */ - d = isign(ge->iy3 - ge->prev->iy3); - - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - - changed = 1; - while (changed) { - if (ISDBG(FIXCVDIR)) { - /* for debugging */ - fprintf(stderr, "fixcvdir %d %d (%d %d %d %d %d %d) %f %f %f\n", - fdir, rdir, - ge->ix1 - ge->prev->ix3, - ge->iy1 - ge->prev->iy3, - ge->ix2 - ge->ix1, - ge->iy2 - ge->iy1, - ge->ix3 - ge->ix2, - ge->iy3 - ge->iy2, - kk1, kk, kk2); - } - changed = 0; - - if (fdir > 0) { - if (kk1 > kk) { /* the front end has problems */ - if (c * (ge->ix1 - ge->prev->ix3) > 0) { - ge->ix1 -= c; - changed = 1; - } if (d * (ge->iy2 - ge->iy1) > 0) { - ge->iy1 += d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } else if (fdir < 0) { - if (kk1 < kk) { /* the front end has problems */ - if (c * (ge->ix2 - ge->ix1) > 0) { - ge->ix1 += c; - changed = 1; - } if (d * (ge->iy1 - ge->prev->iy3) > 0) { - ge->iy1 -= d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - kk1 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } - if (rdir > 0) { - if (kk2 < kk) { /* the rear end has problems */ - if (c * (ge->ix2 - ge->ix1) > 0) { - ge->ix2 -= c; - changed = 1; - } if (d * (ge->iy3 - ge->iy2) > 0) { - ge->iy2 += d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } else if (rdir < 0) { - if (kk2 > kk) { /* the rear end has problems */ - if (c * (ge->ix3 - ge->ix2) > 0) { - ge->ix2 += c; - changed = 1; - } if (d * (ge->iy2 - ge->iy1) > 0) { - ge->iy2 -= d; - changed = 1; - } - /* recalculate the coefficients */ - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - kk = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - kk2 = fabs(a == 0 ? (b == 0 ? 1. : 100000.) : ((double) b / (double) a)); - } - } - } - fixcvends(ge); -} - -/* Get the directions of ends of curve for further usage */ - -/* expects that the previous element is also float */ - -static int -fgetcvdir( - GENTRY * ge -) -{ - double a, b; - double k, k1, k2; - int dir = 0; - - if( !(ge->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! fgetcvdir(0x%x) on int entry, ABORT\n", ge); - abort(); /* dump core */ - } - - a = fabs(ge->fy3 - ge->prev->fy3); - b = fabs(ge->fx3 - ge->prev->fx3); - k = a < FEPS ? (b < FEPS ? 1. : 100000.) : ( b / a); - - a = fabs(ge->fy1 - ge->prev->fy3); - b = fabs(ge->fx1 - ge->prev->fx3); - if(a < FEPS) { - if(b < FEPS) { - a = fabs(ge->fy2 - ge->prev->fy3); - b = fabs(ge->fx2 - ge->prev->fx3); - k1 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a); - } else - k1 = FBIGVAL; - } else - k1 = b / a; - - a = fabs(ge->fy3 - ge->fy2); - b = fabs(ge->fx3 - ge->fx2); - if(a < FEPS) { - if(b < FEPS) { - a = fabs(ge->fy3 - ge->fy1); - b = fabs(ge->fx3 - ge->fx1); - k2 = a < FEPS ? (b < FEPS ? k : 100000.) : ( b / a); - } else - k2 = FBIGVAL; - } else - k2 = b / a; - - if(fabs(k1-k) < 0.0001) - dir |= CVDIR_FEQUAL; - else if (k1 < k) - dir |= CVDIR_FUP; - else - dir |= CVDIR_FDOWN; - - if(fabs(k2-k) < 0.0001) - dir |= CVDIR_REQUAL; - else if (k2 > k) - dir |= CVDIR_RUP; - else - dir |= CVDIR_RDOWN; - - return dir; -} - - -/* expects that the previous element is also int */ - -static int -igetcvdir( - GENTRY * ge -) -{ - int a, b; - double k, k1, k2; - int dir = 0; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! igetcvdir(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - a = ge->iy3 - ge->prev->iy3; - b = ge->ix3 - ge->prev->ix3; - k = (a == 0) ? (b == 0 ? 1. : 100000.) : fabs((double) b / (double) a); - - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - if(a == 0) { - if(b == 0) { - a = ge->iy2 - ge->prev->iy3; - b = ge->ix2 - ge->prev->ix3; - k1 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a); - } else - k1 = FBIGVAL; - } else - k1 = fabs((double) b / (double) a); - - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - if(a == 0) { - if(b == 0) { - a = ge->iy3 - ge->iy1; - b = ge->ix3 - ge->ix1; - k2 = (a == 0) ? (b == 0 ? k : 100000.) : fabs((double) b / (double) a); - } else - k2 = FBIGVAL; - } else - k2 = fabs((double) b / (double) a); - - if(fabs(k1-k) < 0.0001) - dir |= CVDIR_FEQUAL; - else if (k1 < k) - dir |= CVDIR_FUP; - else - dir |= CVDIR_FDOWN; - - if(fabs(k2-k) < 0.0001) - dir |= CVDIR_REQUAL; - else if (k2 > k) - dir |= CVDIR_RUP; - else - dir |= CVDIR_RDOWN; - - return dir; -} - -#if 0 -/* a function just to test the work of fixcvdir() */ -static void -testfixcvdir( - GLYPH * g -) -{ - GENTRY *ge; - int dir; - - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_CURVE) { - dir = igetcvdir(ge); - fixcvdir(ge, dir); - } - } -} -#endif - -static int -iround( - double val -) -{ - return (int) (val > 0 ? val + 0.5 : val - 0.5); -} - -/* for debugging - dump the glyph - * mark with a star the entries from start to end inclusive - * (start == NULL means don't mark any, end == NULL means to the last) - */ - -void -dumppaths( - GLYPH *g, - GENTRY *start, - GENTRY *end -) -{ - GENTRY *ge; - int i; - char mark=' '; - - fprintf(stderr, "Glyph %s:\n", g->name); - - /* now do the conversion */ - for(ge = g->entries; ge != 0; ge = ge->next) { - if(ge == start) - mark = '*'; - fprintf(stderr, " %c %8x", mark, ge); - switch(ge->type) { - case GE_MOVE: - case GE_LINE: - if(ge->flags & GEF_FLOAT) - fprintf(stderr," %c float (%g, %g)\n", ge->type, ge->fx3, ge->fy3); - else - fprintf(stderr," %c int (%d, %d)\n", ge->type, ge->ix3, ge->iy3); - break; - case GE_CURVE: - if(ge->flags & GEF_FLOAT) { - fprintf(stderr," C float "); - for(i=0; i<3; i++) - fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]); - fprintf(stderr,"\n"); - } else { - fprintf(stderr," C int "); - for(i=0; i<3; i++) - fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]); - fprintf(stderr,"\n"); - } - break; - default: - fprintf(stderr, " %c\n", ge->type); - break; - } - if(ge == end) - mark = ' '; - } -} - -/* - * Routine that converts all entries in the path from float to int - */ - -void -pathtoint( - GLYPH *g -) -{ - GENTRY *ge; - int x[3], y[3]; - int i; - - - if(ISDBG(TOINT)) - fprintf(stderr, "TOINT: glyph %s\n", g->name); - assertisfloat(g, "converting path to int\n"); - - fdelsmall(g, 1.0); /* get rid of sub-pixel contours */ - assertpath(g->entries, __FILE__, __LINE__, g->name); - - /* 1st pass, collect the directions of the curves: have - * to do that in advance, while everyting is float - */ - for(ge = g->entries; ge != 0; ge = ge->next) { - if( !(ge->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! glyphs %s has int entry, found in conversion to int\n", - g->name); - exit(1); - } - if(ge->type == GE_CURVE) { - ge->dir = fgetcvdir(ge); - } - } - - /* now do the conversion */ - for(ge = g->entries; ge != 0; ge = ge->next) { - switch(ge->type) { - case GE_MOVE: - case GE_LINE: - if(ISDBG(TOINT)) - fprintf(stderr," %c float x=%g y=%g\n", ge->type, ge->fx3, ge->fy3); - x[0] = iround(ge->fx3); - y[0] = iround(ge->fy3); - for(i=0; i<3; i++) { /* put some valid values everywhere, for convenience */ - ge->ixn[i] = x[0]; - ge->iyn[i] = y[0]; - } - if(ISDBG(TOINT)) - fprintf(stderr," int x=%d y=%d\n", ge->ix3, ge->iy3); - break; - case GE_CURVE: - if(ISDBG(TOINT)) - fprintf(stderr," %c float ", ge->type); - - for(i=0; i<3; i++) { - if(ISDBG(TOINT)) - fprintf(stderr,"(%g, %g) ", ge->fxn[i], ge->fyn[i]); - x[i] = iround(ge->fxn[i]); - y[i] = iround(ge->fyn[i]); - } - - if(ISDBG(TOINT)) - fprintf(stderr,"\n int "); - - for(i=0; i<3; i++) { - ge->ixn[i] = x[i]; - ge->iyn[i] = y[i]; - if(ISDBG(TOINT)) - fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]); - } - ge->flags &= ~GEF_FLOAT; /* for fixcvdir */ - fixcvdir(ge, ge->dir); - - if(ISDBG(TOINT)) { - fprintf(stderr,"\n fixed "); - for(i=0; i<3; i++) - fprintf(stderr,"(%d, %d) ", ge->ixn[i], ge->iyn[i]); - fprintf(stderr,"\n"); - } - - break; - } - ge->flags &= ~GEF_FLOAT; - } - g->flags &= ~GF_FLOAT; -} - - -/* check whether we can fix up the curve to change its size by (dx,dy) */ -/* 0 means NO, 1 means YES */ - -/* for float: if scaling would be under 10% */ - -int -fcheckcv( - GENTRY * ge, - double dx, - double dy -) -{ - if( !(ge->flags & GEF_FLOAT) ) { - fprintf(stderr, "**! fcheckcv(0x%x) on int entry, ABORT\n", ge); - abort(); /* dump core */ - } - - if (ge->type != GE_CURVE) - return 0; - - if( fabs(ge->fx3 - ge->prev->fx3) < fabs(dx) * 10 ) - return 0; - - if( fabs(ge->fy3 - ge->prev->fy3) < fabs(dy) * 10 ) - return 0; - - return 1; -} - -/* for int: if won't create new zigzags at the ends */ - -int -icheckcv( - GENTRY * ge, - int dx, - int dy -) -{ - int xdep, ydep; - - if(ge->flags & GEF_FLOAT) { - fprintf(stderr, "**! icheckcv(0x%x) on floating entry, ABORT\n", ge); - abort(); /* dump core */ - } - - if (ge->type != GE_CURVE) - return 0; - - xdep = ge->ix3 - ge->prev->ix3; - ydep = ge->iy3 - ge->prev->iy3; - - if (ge->type == GE_CURVE - && (xdep * (xdep + dx)) > 0 - && (ydep * (ydep + dy)) > 0) { - return 1; - } else - return 0; -} - -/* float connect the ends of open contours */ - -void -fclosepaths( - GLYPH * g -) -{ - GENTRY *ge, *fge, *xge, *nge; - int i; - - assertisfloat(g, "fclosepaths float\n"); - - for (xge = g->entries; xge != 0; xge = xge->next) { - if( xge->type != GE_PATH ) - continue; - - ge = xge->prev; - if(ge == 0 || ge->type != GE_LINE && ge->type!= GE_CURVE) { - fprintf(stderr, "**! Glyph %s got empty path\n", - g->name); - exit(1); - } - - fge = ge->frwd; - if (fge->prev == 0 || fge->prev->type != GE_MOVE) { - fprintf(stderr, "**! Glyph %s got strange beginning of path\n", - g->name); - exit(1); - } - fge = fge->prev; - if (fge->fx3 != ge->fx3 || fge->fy3 != ge->fy3) { - /* we have to fix this open path */ - - WARNING_4 fprintf(stderr, "Glyph %s got path open by dx=%g dy=%g\n", - g->name, fge->fx3 - ge->fx3, fge->fy3 - ge->fy3); - - - /* add a new line */ - nge = newgentry(GEF_FLOAT); - (*nge) = (*ge); - nge->fx3 = fge->fx3; - nge->fy3 = fge->fy3; - nge->type = GE_LINE; - - addgeafter(ge, nge); - - if (fabs(ge->fx3 - fge->fx3) <= 2 && fabs(ge->fy3 - fge->fy3) <= 2) { - /* - * small change, try to get rid of the new entry - */ - - double df[2]; - - for(i=0; i<2; i++) { - df[i] = ge->fpoints[i][2] - fge->fpoints[i][2]; - df[i] = fclosegap(nge, nge, i, df[i], NULL); - } - - if(df[0] == 0. && df[1] == 0.) { - /* closed gap successfully, remove the added entry */ - freethisge(nge); - } - } - } - } -} - -void -smoothjoints( - GLYPH * g -) -{ - GENTRY *ge, *ne; - int dx1, dy1, dx2, dy2, k; - int dir; - - return; /* this stuff seems to create problems */ - - assertisint(g, "smoothjoints int"); - - if (g->entries == 0) /* nothing to do */ - return; - - for (ge = g->entries->next; ge != 0; ge = ge->next) { - ne = ge->frwd; - - /* - * although there should be no one-line path * and any path - * must end with CLOSEPATH, * nobody can say for sure - */ - - if (ge == ne || ne == 0) - continue; - - /* now handle various joints */ - - if (ge->type == GE_LINE && ne->type == GE_LINE) { - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - dx2 = ne->ix3 - ge->ix3; - dy2 = ne->iy3 - ge->iy3; - - /* check whether they have the same direction */ - /* and the same slope */ - /* then we can join them into one line */ - - if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0 && dx1 * dy2 == dy1 * dx2) { - /* extend the previous line */ - ge->ix3 = ne->ix3; - ge->iy3 = ne->iy3; - - /* and get rid of the next line */ - freethisge(ne); - } - } else if (ge->type == GE_LINE && ne->type == GE_CURVE) { - fixcvends(ne); - - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - dx2 = ne->ix1 - ge->ix3; - dy2 = ne->iy1 - ge->iy3; - - /* if the line is nearly horizontal and we can fix it */ - if (dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0 - && icheckcv(ne, 0, -dy1) - && abs(dy1) <= 4) { - dir = igetcvdir(ne); - ge->iy3 -= dy1; - ne->iy1 -= dy1; - fixcvdir(ne, dir); - if (ge->next != ne) - ne->prev->iy3 -= dy1; - dy1 = 0; - } else if (dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0 - && icheckcv(ne, -dx1, 0) - && abs(dx1) <= 4) { - /* the same but vertical */ - dir = igetcvdir(ne); - ge->ix3 -= dx1; - ne->ix1 -= dx1; - fixcvdir(ne, dir); - if (ge->next != ne) - ne->prev->ix3 -= dx1; - dx1 = 0; - } - /* - * if line is horizontal and curve begins nearly - * horizontally - */ - if (dy1 == 0 && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0) { - dir = igetcvdir(ne); - ne->iy1 -= dy2; - fixcvdir(ne, dir); - dy2 = 0; - } else if (dx1 == 0 && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0) { - /* the same but vertical */ - dir = igetcvdir(ne); - ne->ix1 -= dx2; - fixcvdir(ne, dir); - dx2 = 0; - } - } else if (ge->type == GE_CURVE && ne->type == GE_LINE) { - fixcvends(ge); - - dx1 = ge->ix3 - ge->ix2; - dy1 = ge->iy3 - ge->iy2; - dx2 = ne->ix3 - ge->ix3; - dy2 = ne->iy3 - ge->iy3; - - /* if the line is nearly horizontal and we can fix it */ - if (dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0 - && icheckcv(ge, 0, dy2) - && abs(dy2) <= 4) { - dir = igetcvdir(ge); - ge->iy3 += dy2; - ge->iy2 += dy2; - fixcvdir(ge, dir); - if (ge->next != ne) - ne->prev->iy3 += dy2; - dy2 = 0; - } else if (dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0 - && icheckcv(ge, dx2, 0) - && abs(dx2) <= 4) { - /* the same but vertical */ - dir = igetcvdir(ge); - ge->ix3 += dx2; - ge->ix2 += dx2; - fixcvdir(ge, dir); - if (ge->next != ne) - ne->prev->ix3 += dx2; - dx2 = 0; - } - /* - * if line is horizontal and curve ends nearly - * horizontally - */ - if (dy2 == 0 && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0) { - dir = igetcvdir(ge); - ge->iy2 += dy1; - fixcvdir(ge, dir); - dy1 = 0; - } else if (dx2 == 0 && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0) { - /* the same but vertical */ - dir = igetcvdir(ge); - ge->ix2 += dx1; - fixcvdir(ge, dir); - dx1 = 0; - } - } else if (ge->type == GE_CURVE && ne->type == GE_CURVE) { - fixcvends(ge); - fixcvends(ne); - - dx1 = ge->ix3 - ge->ix2; - dy1 = ge->iy3 - ge->iy2; - dx2 = ne->ix1 - ge->ix3; - dy2 = ne->iy1 - ge->iy3; - - /* - * check if we have a rather smooth joint at extremal - * point - */ - /* left or right extremal point */ - if (abs(dx1) <= 4 && abs(dx2) <= 4 - && dy1 != 0 && 5 * abs(dx1) / abs(dy1) == 0 - && dy2 != 0 && 5 * abs(dx2) / abs(dy2) == 0 - && (ge->iy3 < ge->prev->iy3 && ne->iy3 < ge->iy3 - || ge->iy3 > ge->prev->iy3 && ne->iy3 > ge->iy3) - && (ge->ix3 - ge->prev->ix3) * (ne->ix3 - ge->ix3) < 0 - ) { - dir = igetcvdir(ge); - ge->ix2 += dx1; - dx1 = 0; - fixcvdir(ge, dir); - dir = igetcvdir(ne); - ne->ix1 -= dx2; - dx2 = 0; - fixcvdir(ne, dir); - } - /* top or down extremal point */ - else if (abs(dy1) <= 4 && abs(dy2) <= 4 - && dx1 != 0 && 5 * abs(dy1) / abs(dx1) == 0 - && dx2 != 0 && 5 * abs(dy2) / abs(dx2) == 0 - && (ge->ix3 < ge->prev->ix3 && ne->ix3 < ge->ix3 - || ge->ix3 > ge->prev->ix3 && ne->ix3 > ge->ix3) - && (ge->iy3 - ge->prev->iy3) * (ne->iy3 - ge->iy3) < 0 - ) { - dir = igetcvdir(ge); - ge->iy2 += dy1; - dy1 = 0; - fixcvdir(ge, dir); - dir = igetcvdir(ne); - ne->iy1 -= dy2; - dy2 = 0; - fixcvdir(ne, dir); - } - /* or may be we just have a smooth junction */ - else if (dx1 * dx2 >= 0 && dy1 * dy2 >= 0 - && 10 * abs(k = abs(dx1 * dy2) - abs(dy1 * dx2)) < (abs(dx1 * dy2) + abs(dy1 * dx2))) { - int tries[6][4]; - int results[6]; - int i, b; - - /* build array of changes we are going to try */ - /* uninitalized entries are 0 */ - if (k > 0) { - static int t1[6][4] = { - {0, 0, 0, 0}, - {-1, 0, 1, 0}, - {-1, 0, 0, 1}, - {0, -1, 1, 0}, - {0, -1, 0, 1}, - {-1, -1, 1, 1}}; - memcpy(tries, t1, sizeof tries); - } else { - static int t1[6][4] = { - {0, 0, 0, 0}, - {1, 0, -1, 0}, - {1, 0, 0, -1}, - {0, 1, -1, 0}, - {0, 1, 0, -1}, - {1, 1, -1, -1}}; - memcpy(tries, t1, sizeof tries); - } - - /* now try the changes */ - results[0] = abs(k); - for (i = 1; i < 6; i++) { - results[i] = abs((abs(dx1) + tries[i][0]) * (abs(dy2) + tries[i][1]) - - (abs(dy1) + tries[i][2]) * (abs(dx2) + tries[i][3])); - } - - /* and find the best try */ - k = abs(k); - b = 0; - for (i = 1; i < 6; i++) - if (results[i] < k) { - k = results[i]; - b = i; - } - /* and finally apply it */ - if (dx1 < 0) - tries[b][0] = -tries[b][0]; - if (dy2 < 0) - tries[b][1] = -tries[b][1]; - if (dy1 < 0) - tries[b][2] = -tries[b][2]; - if (dx2 < 0) - tries[b][3] = -tries[b][3]; - - dir = igetcvdir(ge); - ge->ix2 -= tries[b][0]; - ge->iy2 -= tries[b][2]; - fixcvdir(ge, dir); - dir = igetcvdir(ne); - ne->ix1 += tries[b][3]; - ne->iy1 += tries[b][1]; - fixcvdir(ne, dir); - } - } - } -} - -/* debugging: print out stems of a glyph */ -static void -debugstems( - char *name, - STEM * hstems, - int nhs, - STEM * vstems, - int nvs -) -{ - int i; - - fprintf(pfa_file, "%% %s\n", name); - fprintf(pfa_file, "%% %d horizontal stems:\n", nhs); - for (i = 0; i < nhs; i++) - fprintf(pfa_file, "%% %3d %d (%d...%d) %c %c%c%c%c\n", i, hstems[i].value, - hstems[i].from, hstems[i].to, - ((hstems[i].flags & ST_UP) ? 'U' : 'D'), - ((hstems[i].flags & ST_END) ? 'E' : '-'), - ((hstems[i].flags & ST_FLAT) ? 'F' : '-'), - ((hstems[i].flags & ST_ZONE) ? 'Z' : ' '), - ((hstems[i].flags & ST_TOPZONE) ? 'T' : ' ')); - fprintf(pfa_file, "%% %d vertical stems:\n", nvs); - for (i = 0; i < nvs; i++) - fprintf(pfa_file, "%% %3d %d (%d...%d) %c %c%c\n", i, vstems[i].value, - vstems[i].from, vstems[i].to, - ((vstems[i].flags & ST_UP) ? 'U' : 'D'), - ((vstems[i].flags & ST_END) ? 'E' : '-'), - ((vstems[i].flags & ST_FLAT) ? 'F' : '-')); -} - -/* add pseudo-stems for the limits of the Blue zones to the stem array */ -static int -addbluestems( - STEM *s, - int n -) -{ - int i; - - for(i=0; i - (s[j].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT) - ) - continue; - } else { - if( - (s[i].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT) - < - (s[j].flags & (ST_ZONE|ST_FLAT|ST_END) ^ ST_FLAT) - ) - continue; - } - } - } - x = s[j]; - s[j] = s[i]; - s[i] = x; - } -} - -/* check whether two stem borders overlap */ - -static int -stemoverlap( - STEM * s1, - STEM * s2 -) -{ - int result; - - if (s1->from <= s2->from && s1->to >= s2->from - || s2->from <= s1->from && s2->to >= s1->from) - result = 1; - else - result = 0; - - if (ISDBG(STEMOVERLAP)) - fprintf(pfa_file, "%% overlap %d(%d..%d)x%d(%d..%d)=%d\n", - s1->value, s1->from, s1->to, s2->value, s2->from, s2->to, result); - return result; -} - -/* - * check if the stem [border] is in an appropriate blue zone - * (currently not used) - */ - -static int -steminblue( - STEM *s -) -{ - int i, val; - - val=s->value; - if(s->flags & ST_UP) { - /* painted size up, look at lower zones */ - if(nblues>=2 && val>=bluevalues[0] && val<=bluevalues[1] ) - return 1; - for(i=0; i=otherblues[i] && val<=otherblues[i+1] ) - return 1; - } - } else { - /* painted side down, look at upper zones */ - for(i=2; i=bluevalues[i] && val<=bluevalues[i+1] ) - return 1; - } - } - - return 0; -} - -/* mark the outermost stem [borders] in the blue zones */ - -static void -markbluestems( - STEM *s, - int nold -) -{ - int i, j, a, b, c; - /* - * traverse the list of Blue Values, mark the lowest upper - * stem in each bottom zone and the topmost lower stem in - * each top zone with ST_BLUE - */ - - /* top zones */ - for(i=2; i=0; j--) { - if( s[j].flags & (ST_ZONE|ST_UP|ST_END) ) - continue; - c=s[j].value; - if(c=0 && s[j].value==c - && (s[j].flags & (ST_UP|ST_ZONE))==0 ; j--) - s[j].flags |= ST_BLUE; - break; - } - } - } - /* baseline */ - if(nblues>=2) { - a=bluevalues[0]; b=bluevalues[1]; - for(j=0; jb) /* too high */ - break; - if(c>=a) { /* found the lowest stem border */ - /* mark all the stems with the same value */ - if(ISDBG(BLUESTEMS)) - fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value); - /* include ST_END values */ - while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 ) - j--; - s[j].flags |= ST_BLUE; - for(j++; jb) /* too high */ - break; - if(c>=a) { /* found the lowest stem border */ - /* mark all the stems with the same value */ - if(ISDBG(BLUESTEMS)) - fprintf(pfa_file, "%% found U BLUE at %d\n", s[j].value); - /* include ST_END values */ - while( s[j-1].value==c && (s[j-1].flags & ST_ZONE)==0 ) - j--; - s[j].flags |= ST_BLUE; - for(j++; j=b) { /* have no free space */ - for(j=nold; j>=b; j--) /* make free space */ - s[j]=s[j-1]; - b++; - nold++; - } - s[nnew]=s[a]; - s[nnew].flags &= ~(ST_UP|ST_BLUE); - nnew++; - i=b-1; - } else { - s[nnew++]=s[c]; - i=c; /* skip up to this point */ - } - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d U BLUE\n", - s[nnew-2].value, s[nnew-1].value); - } else { - if (nstack >= MAX_STACK) { - WARNING_1 fprintf(stderr, "Warning: **** converter's stem stack overflow ****\n"); - nstack = 0; - } - stack[nstack++] = s[i]; - } - } else if(s[i].flags & ST_BLUE) { - /* again, we just HAVE to use this value */ - if (readystem) - nnew += 2; - readystem=0; - - /* remember the list of Blue zone stems with the same value */ - for(a=i, i++; i= 0; i--) { - if( (stack[i].flags & ST_UP)==0 ) { - if( (stack[i].flags & (ST_ZONE|ST_TOPZONE))==ST_ZONE ) - break; - else - continue; - } - for(j=a; j=0; j-=2) { - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% ?stem %d...%d -- %d\n", - s[j].value, s[j+1].value, stack[c].value); - if(s[j+1].value < stack[c].value) /* no conflict */ - break; - if(s[j].flags & ST_BLUE) { - /* oops, we don't want to spoil other blue zones */ - stack[c].value=s[j+1].value+1; - break; - } - if( (s[j].flags|s[j+1].flags) & ST_END ) { - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% -stem %d...%d p=1\n", - s[j].value, s[j+1].value); - continue; /* pri==1, silently discard it */ - } - /* we want to discard no nore than 2 stems of pri>=2 */ - if( ++readystem > 2 ) { - /* change our stem to not conflict */ - stack[c].value=s[j+1].value+1; - break; - } else { - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% -stem %d...%d p>=2\n", - s[j].value, s[j+1].value); - continue; - } - } - nnew=j+2; - /* add this stem */ - if(nnew>=b-1) { /* have no free space */ - for(j=nold; j>=b-1; j--) /* make free space */ - s[j]=s[j-1]; - b++; - nold++; - } - s[nnew++]=stack[c]; - s[nnew++]=s[b-1]; - /* clean up the stack */ - nstack=sbottom=0; - readystem=0; - /* set the next position to search */ - i=b-1; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d D BLUE\n", - s[nnew-2].value, s[nnew-1].value); - } else if (nstack > 0) { - - /* - * check whether our stem overlaps with anything in - * stack - */ - for (j = nstack - 1; j >= sbottom; j--) { - if (s[i].value <= stack[j].value) - break; - if (stack[j].flags & ST_ZONE) - continue; - - if ((s[i].flags & ST_END) - || (stack[j].flags & ST_END)) - pri = 1; - else if ((s[i].flags & ST_FLAT) - || (stack[j].flags & ST_FLAT)) - pri = 3; - else - pri = 2; - - if (pri < readystem && s[nnew + 1].value >= stack[j].value - || !stemoverlap(&stack[j], &s[i])) - continue; - - if (readystem > 1 && s[nnew + 1].value < stack[j].value) { - nnew += 2; - readystem = 0; - nlps = 0; - } - /* - * width of the previous stem (if it's - * present) - */ - w1 = s[nnew + 1].value - s[nnew].value; - - /* width of this stem */ - w2 = s[i].value - stack[j].value; - - if (readystem == 0) { - /* nothing yet, just add a new stem */ - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - readystem = pri; - if (pri == 1) - nlps = 1; - else if (pri == 2) - sbottom = j; - else { - sbottom = j + 1; - while (sbottom < nstack - && stack[sbottom].value <= stack[j].value) - sbottom++; - } - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } else if (pri == 1) { - if (stack[j].value > s[nnew + 1].value) { - /* - * doesn't overlap with the - * previous one - */ - nnew += 2; - nlps++; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } else if (w2 < w1) { - /* is narrower */ - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d %d->%d\n", - stack[j].value, s[i].value, pri, nlps, w1, w2); - } - } else if (pri == 2) { - if (readystem == 2) { - /* choose the narrower stem */ - if (w1 > w2) { - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - sbottom = j; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - /* else readystem==1 */ - } else if (stack[j].value > s[nnew + 1].value) { - /* - * value doesn't overlap with - * the previous one - */ - nnew += 2; - nlps = 0; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - sbottom = j; - readystem = pri; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } else if (nlps == 1 - || stack[j].value > s[nnew - 1].value) { - /* - * we can replace the top - * stem - */ - nlps = 0; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - readystem = pri; - sbottom = j; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - } else if (readystem == 3) { /* that means also - * pri==3 */ - /* choose the narrower stem */ - if (w1 > w2) { - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - sbottom = j + 1; - while (sbottom < nstack - && stack[sbottom].value <= stack[j].value) - sbottom++; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% /stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - } else if (pri == 3) { - /* - * we can replace as many stems as - * neccessary - */ - nnew += 2; - while (nnew > 0 && s[nnew - 1].value >= stack[j].value) { - nnew -= 2; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% -stem %d..%d\n", - s[nnew].value, s[nnew + 1].value); - } - nlps = 0; - s[nnew] = stack[j]; - s[nnew + 1] = s[i]; - readystem = pri; - sbottom = j + 1; - while (sbottom < nstack - && stack[sbottom].value <= stack[j].value) - sbottom++; - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% +stem %d...%d p=%d n=%d\n", - stack[j].value, s[i].value, pri, nlps); - } - } - } - } - if (readystem) - nnew += 2; - - /* change the 1-pixel-wide stems to 20-pixel-wide stems if possible - * the constant 20 is recommended in the Type1 manual - */ - if(useblues) { - for(i=0; ii+2 && s[i+2].value0 && s[i-1].value>s[i].value-22) - s[i].value=s[i-1].value+2; /* compensate for fuzziness */ - else - s[i].value-=20; - } - } - } - /* make sure that no stem it stretched between - * a top zone and a bottom zone - */ - if(useblues) { - for(i=0; i=s[i].value && c<=s[i+1].value && c=2) { - c=bluevalues[1]; - if( c>=s[i].value && c<=s[i+1].value && c>b ) - b=c; - } - for(j=1; j=s[i].value && c<=s[i+1].value && c>b ) - b=c; - } - if( a!=10000 && b!= -10000 ) { /* it is stretched */ - /* split the stem into 2 ghost stems */ - for(j=nnew+1; j>i+1; j--) /* make free space */ - s[j]=s[j-2]; - nnew+=2; - - if(s[i].value+22 >= a) - s[i+1].value=a-2; /* leave space for fuzziness */ - else - s[i+1].value=s[i].value+20; - - if(s[i+3].value-22 <= b) - s[i+2].value=b+2; /* leave space for fuzziness */ - else - s[i+2].value=s[i+3].value-20; - - i+=2; - } - } - } - /* look for triple stems */ - for (i = 0; i < nnew; i += 2) { - if (nnew - i >= 6) { - a = s[i].value + s[i + 1].value; - b = s[i + 2].value + s[i + 3].value; - c = s[i + 4].value + s[i + 5].value; - - w1 = s[i + 1].value - s[i].value; - w2 = s[i + 3].value - s[i + 2].value; - w3 = s[i + 5].value - s[i + 4].value; - - fw = w3 - w1; /* fuzz in width */ - fd = ((c - b) - (b - a)); /* fuzz in distance - * (doubled) */ - - /* we are able to handle some fuzz */ - /* - * it doesn't hurt if the declared stem is a bit - * narrower than actual unless it's an edge in - * a blue zone - */ - if (abs(abs(fd) - abs(fw)) * 5 < w2 - && abs(fw) * 20 < (w1 + w3)) { /* width dirrerence <10% */ - - if(useblues) { /* check that we don't disturb any blue stems */ - j=c; k=a; - if (fw > 0) { - if (fd > 0) { - if( s[i+5].flags & ST_BLUE ) - continue; - j -= fw; - } else { - if( s[i+4].flags & ST_BLUE ) - continue; - j += fw; - } - } else if(fw < 0) { - if (fd > 0) { - if( s[i+1].flags & ST_BLUE ) - continue; - k -= fw; - } else { - if( s[i].flags & ST_BLUE ) - continue; - k += fw; - } - } - pri = ((j - b) - (b - k)); - - if (pri > 0) { - if( s[i+2].flags & ST_BLUE ) - continue; - } else if(pri < 0) { - if( s[i+3].flags & ST_BLUE ) - continue; - } - } - - /* - * first fix up the width of 1st and 3rd - * stems - */ - if (fw > 0) { - if (fd > 0) { - s[i + 5].value -= fw; - c -= fw; - } else { - s[i + 4].value += fw; - c += fw; - } - } else { - if (fd > 0) { - s[i + 1].value -= fw; - a -= fw; - } else { - s[i].value += fw; - a += fw; - } - } - fd = ((c - b) - (b - a)); - - if (fd > 0) { - s[i + 2].value += abs(fd) / 2; - } else { - s[i + 3].value -= abs(fd) / 2; - } - - s[i].flags |= ST_3; - i += 4; - } - } - } - - return (nnew & ~1); /* number of lines must be always even */ -} - -/* - * these macros and function allow to set the base stem, - * check that it's not empty and subtract another stem - * from the base stem (possibly dividing it into multiple parts) - */ - -/* pairs for pieces of the base stem */ -static short xbstem[MAX_STEMS*2]; -/* index of the last point */ -static int xblast= -1; - -#define setbasestem(from, to) \ - (xbstem[0]=from, xbstem[1]=to, xblast=1) -#define isbaseempty() (xblast<=0) - -/* returns 1 if was overlapping, 0 otherwise */ -static int -subfrombase( - int from, - int to -) -{ - int a, b; - int i, j; - - if(isbaseempty()) - return 0; - - /* handle the simple case simply */ - if(from > xbstem[xblast] || to < xbstem[0]) - return 0; - - /* the binary search may be more efficient */ - /* but for now the linear search is OK */ - for(b=1; from > xbstem[b]; b+=2) {} /* result: from <= xbstem[b] */ - for(a=xblast-1; to < xbstem[a]; a-=2) {} /* result: to >= xbstem[a] */ - - /* now the interesting examples are: - * (it was hard for me to understand, so I looked at the examples) - * 1 - * a|-----| |-----|b |-----| |-----| - * f|-----|t - * 2 - * a|-----|b |-----| |-----| |-----| - * f|--|t - * 3 - * a|-----|b |-----| |-----| |-----| - * f|-----|t - * 4 - * |-----|b a|-----| |-----| |-----| - * f|------------|t - * 5 - * |-----| |-----|b |-----| a|-----| - * f|-----------------------------|t - * 6 - * |-----|b |-----| |-----| a|-----| - * f|--------------------------------------------------|t - * 7 - * |-----|b |-----| a|-----| |-----| - * f|--------------------------|t - */ - - if(a < b-1) /* hits a gap - example 1 */ - return 0; - - /* now the subtraction itself */ - - if(a==b-1 && from > xbstem[a] && to < xbstem[b]) { - /* overlaps with only one subrange and splits it - example 2 */ - j=xblast; i=(xblast+=2); - while(j>=b) - xbstem[i--]=xbstem[j--]; - xbstem[b]=from-1; - xbstem[b+1]=to+1; - return 1; - /* becomes - * 2a - * a|b || |-----| |-----| |-----| - * f|--|t - */ - } - - if(xbstem[b-1] < from) { - /* cuts the back of this subrange - examples 3, 4, 7 */ - xbstem[b] = from-1; - b+=2; - /* becomes - * 3a - * a|----| |-----|b |-----| |-----| - * f|-----|t - * 4a - * |---| a|-----|b |-----| |-----| - * f|------------|t - * 7a - * |---| |-----|b a|-----| |-----| - * f|--------------------------|t - */ - } - - if(xbstem[a+1] > to) { - /* cuts the front of this subrange - examples 4a, 5, 7a */ - xbstem[a] = to+1; - a-=2; - /* becomes - * 4b - * a|---| |---|b |-----| |-----| - * f|------------|t - * 5b - * |-----| |-----|b a|-----| || - * f|-----------------------------|t - * 7b - * |---| a|-----|b || |-----| - * f|--------------------------|t - */ - } - - if(a < b-1) /* now after modification it hits a gap - examples 3a, 4b */ - return 1; /* because we have removed something */ - - /* now remove the subranges completely covered by the new stem */ - /* examples 5b, 6, 7b */ - i=b-1; j=a+2; - /* positioned as: - * 5b i j - * |-----| |-----|b a|-----| || - * f|-----------------------------|t - * 6 i xblast j - * |-----|b |-----| |-----| a|-----| - * f|--------------------------------------------------|t - * 7b i j - * |---| a|-----|b || |-----| - * f|--------------------------|t - */ - while(j <= xblast) - xbstem[i++]=xbstem[j++]; - xblast=i-1; - return 1; -} - -/* for debugging */ -static void -printbasestem(void) -{ - int i; - - printf("( "); - for(i=0; i lastpri - && ( lastpri==1 || s[j].value-v<20 || (s[x].value-v)*2 >= s[j].value-v ) ) { - lastpri=pri; - x=j; - } - } - } else { - for(j=i-1; j>=0; j--) { - if(mx[i][j]==0) - continue; - - if( (f | s[j].flags) & ST_END ) - pri=1; - else if( (f | s[j].flags) & ST_FLAT ) - pri=3; - else - pri=2; - - if(lastpri==0 - || pri > lastpri - && ( lastpri==1 || v-s[j].value<20 || (v-s[x].value)*2 >= v-s[j].value ) ) { - lastpri=pri; - x=j; - } - } - } - if(x== -1 && mx[i][i]) - pairs[i]=i; /* a special case */ - else - pairs[i]=x; - } - - if(ISDBG(SUBSTEMS)) { - for(i=0; i0) - fprintf(pfa_file, "%% %d...%d (%d x %d)\n", s[i].value, s[j].value, i, j); - } - } -} - -/* - * Make all the stems originating at the same value get the - * same width. Without this the rasterizer may move the dots - * randomly up or down by one pixel, and that looks bad. - * The prioritisation is the same as in findstemat(). - */ -static void -uniformstems( - STEM * s, - short *pairs, - int ns -) -{ - int i, j, from, to, val, dir; - int pri, prevpri[2], wd, prevwd[2], prevbest[2]; - - for(from=0; from prevpri[dir] || wd= 0) { - if(ISDBG(SUBSTEMS)) { - fprintf(stderr, "at %d (%s %d) pair %d->%d(%d)\n", i, - (dir ? "UP":"DOWN"), s[i].value, pairs[i], prevbest[dir], - s[prevbest[dir]].value); - } - pairs[i] = prevbest[dir]; - } - } - } -} - -/* - * Find the best stem in the array at the specified (value, origin), - * related to the entry ge. - * Returns its index in the array sp, -1 means "none". - * prevbest is the result for the other end of the line, we must - * find something better than it or leave it as it is. - */ -static int -findstemat( - int value, - int origin, - GENTRY *ge, - STEM *sp, - short *pairs, - int ns, - int prevbest /* -1 means "none" */ -) -{ - int i, min, max; - int v, si; - int pri, prevpri; /* priority, 0 = has ST_END, 1 = no ST_END */ - int wd, prevwd; /* stem width */ - - si= -1; /* nothing yet */ - - /* stems are ordered by value, binary search */ - min=0; max=ns; /* min <= i < max */ - while( min < max ) { - i=(min+max)/2; - v=sp[i].value; - if(vvalue) - max=i; - else { - si=i; /* temporary value */ - break; - } - } - - if( si < 0 ) /* found nothing this time */ - return prevbest; - - /* find the priority of the prevbest */ - /* we expect that prevbest has a pair */ - if(prevbest>=0) { - i=pairs[prevbest]; - prevpri=1; - if( (sp[prevbest].flags | sp[i].flags) & ST_END ) - prevpri=0; - prevwd=abs(sp[i].value-value); - } - - /* stems are not ordered by origin, so now do the linear search */ - - while( si>0 && sp[si-1].value==value ) /* find the first one */ - si--; - - for(; siprevpri - || pri==prevpri && prevwd==0 || wd!=0 && wdprev->ix3; - y=ge->prev->iy3; - - if(*nextvsi == -2) - si[SI_VP]=findstemat(x, y, ge, vs, vpairs, nvs, -1); - else { - si[SI_VP]= *nextvsi; *nextvsi= -2; - } - if(*nexthsi == -2) - si[SI_HP]=findstemat(y, x, ge, hs, hpairs, nhs, -1); - else { - si[SI_HP]= *nexthsi; *nexthsi= -2; - } - - /* - * For the horizontal lines we make sure that both - * ends of the line have the same horizontal stem, - * and the same thing for vertical lines and stems. - * In both cases we enforce the stem for the next entry. - * Otherwise unpleasant effects may arise. - */ - - if(ge->type==GE_LINE) { - if(ge->ix3==x) { /* vertical line */ - *nextvsi=si[SI_VP]=findstemat(x, ge->iy3, ge->frwd, vs, vpairs, nvs, si[SI_VP]); - } else if(ge->iy3==y) { /* horizontal line */ - *nexthsi=si[SI_HP]=findstemat(y, ge->ix3, ge->frwd, hs, hpairs, nhs, si[SI_HP]); - } - } - - if(si[SI_VP]+si[SI_HP] == -2) /* no stems, leave it alone */ - return 0; - - /* build the array of relevant bounds */ - nr=0; - for(i=0; i< sizeof(si) / sizeof(si[0]); i++) { - STEM *sp; - short *pairs; - int step; - int f; - int nzones, firstzone, binzone, einzone; - int btype, etype; - - if(si[i] < 0) - continue; - - if(i r[nr].high) { - j=r[nr].low; r[nr].low=r[nr].high; r[nr].high=j; - step= -1; - } else { - step=1; - } - - /* handle the interaction with Blue Zones */ - - if(i>=SI_HP) { /* only for horizontal stems */ - if(si[i]==pairs[si[i]]) { - /* special case, the outermost stem in the - * Blue Zone without a pair, simulate it to 20-pixel - */ - if(sp[ si[i] ].flags & ST_UP) { - r[nr].high+=20; - for(j=si[i]+1; j sp[j].value-2) - r[nr].high=sp[j].value-2; - break; - } - } else { - r[nr].low-=20; - for(j=si[i]-1; j>=0; j--) - if( (sp[j].flags & (ST_ZONE|ST_TOPZONE)) - == (ST_ZONE) ) { - if(r[nr].low < sp[j].value+2) - r[nr].low=sp[j].value+2; - break; - } - } - } - - /* check that the stem borders don't end up in - * different Blue Zones */ - f=sp[ si[i] ].flags; - nzones=0; einzone=binzone=0; - for(j=si[i]; j!=pairs[ si[i] ]; j+=step) { - if( (sp[j].flags & ST_ZONE)==0 ) - continue; - /* if see a zone border going in the same direction */ - if( ((f ^ sp[j].flags) & ST_UP)==0 ) { - if( ++nzones == 1 ) { - firstzone=sp[j].value; /* remember the first one */ - etype=sp[j].flags & ST_TOPZONE; - } - einzone=1; - - } else { /* the opposite direction */ - if(nzones==0) { /* beginning is in a blue zone */ - binzone=1; - btype=sp[j].flags & ST_TOPZONE; - } - einzone=0; - } - } - - /* beginning and end are in Blue Zones of different types */ - if( binzone && einzone && (btype ^ etype)!=0 ) { - if( sp[si[i]].flags & ST_UP ) { - if(firstzone > r[nr].low+22) - r[nr].high=r[nr].low+20; - else - r[nr].high=firstzone-2; - } else { - if(firstzone < r[nr].high-22) - r[nr].low=r[nr].high-20; - else - r[nr].low=firstzone+2; - } - } - } - - if(ISDBG(SUBSTEMS)) - fprintf(pfa_file, "%% at(%d,%d)[%d,%d] %d..%d %c (%d x %d)\n", x, y, i, nr, - r[nr].low, r[nr].high, r[nr].isvert ? 'v' : 'h', - si[i], pairs[si[i]]); - - nr++; - } - - /* now try to find a group */ - conflict=0; /* no conflicts found yet */ - for(j=0; j= lb ) { - if( r[j].low == lb && r[j].high == hb ) /* coincides */ - r[j].already=1; - else - conflict=1; - } - - if(conflict) - break; - } - - if(conflict) { /* nope, check all the groups */ - for(j=0; j= lb ) { - if( r[j].low == lb && r[j].high == hb ) /* coincides */ - r[j].already=1; - else - conflict=1; - } - - if(conflict) - i=egp[grp]-1; /* fast forward to the next group */ - } - } - - /* do we have any empty group ? */ - if(conflict && grp < NSTEMGRP-1) { - grp++; conflict=0; - for(j=0; j 0) { - for(i=egp[NSTEMGRP-1]-1; i>=egp[grp]; i--) - s[i+rexpand]=s[i]; - for(i=0; istemid = gssentry_lastgrp = grp; - return 0; -} - -/* - * Create the groups of substituted stems from the list. - * Each group will be represented by a subroutine in the Subs - * array. - */ - -static void -groupsubstems( - GLYPH *g, - STEM *hs, /* horizontal stems, sorted by value */ - short *hpairs, - int nhs, - STEM *vs, /* vertical stems, sorted by value */ - short *vpairs, - int nvs -) -{ - GENTRY *ge; - int i, j; - - /* temporary storage */ - STEMBOUNDS s[MAX_STEMS*2]; - /* indexes in there, pointing past the end each stem group */ - short egp[NSTEMGRP]; - - int nextvsi, nexthsi; /* -2 means "check by yourself" */ - - for(i=0; ientries; ge != 0; ge = ge->next) { - if(ge->type!=GE_LINE && ge->type!=GE_CURVE) { - nextvsi=nexthsi= -2; /* next path is independent */ - continue; - } - - if( gssentry(ge, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) { - WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n", - g->name, NSTEMGRP); - /* it's better to have no substituted hints at all than have only part */ - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid= -1; - g->nsg=0; /* just to be safe, already is 0 by initialization */ - return; - } - - /* - * handle the last vert/horiz line of the path specially, - * correct the hint for the first entry of the path - */ - if(ge->frwd != ge->next && (nextvsi != -2 || nexthsi != -2) ) { - if( gssentry(ge->frwd, hs, hpairs, nhs, vs, vpairs, nvs, s, egp, &nextvsi, &nexthsi) ) { - WARNING_2 fprintf(stderr, "*** glyph %s requires over %d hint subroutines, ignored them\n", - g->name, NSTEMGRP); - /* it's better to have no substituted hints at all than have only part */ - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid= -1; - g->nsg=0; /* just to be safe, already is 0 by initialization */ - return; - } - } - - } - - /* find the index of the first empty group - same as the number of groups */ - if(egp[0]>0) { - for(i=1; insg=i; - } else - g->nsg=0; - - if(ISDBG(SUBSTEMS)) { - fprintf(pfa_file, "%% %d substem groups (%d %d %d)\n", g->nsg, - g->nsg>1 ? egp[g->nsg-2] : -1, - g->nsg>0 ? egp[g->nsg-1] : -1, - g->nsgnsg] : -1 ); - j=0; - for(i=0; insg; i++) { - fprintf(pfa_file, "%% grp %3d: ", i); - for(; jnsg==1) { /* it would be the same as the main stems */ - /* so erase it */ - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid= -1; - g->nsg=0; - } - - if(g->nsg>0) { - if( (g->nsbs=malloc(g->nsg * sizeof (egp[0]))) == 0 ) { - fprintf(stderr, "**** not enough memory for substituted hints ****\n"); - exit(255); - } - memmove(g->nsbs, egp, g->nsg * sizeof(short)); - if( (g->sbstems=malloc(egp[g->nsg-1] * sizeof (s[0]))) == 0 ) { - fprintf(stderr, "**** not enough memory for substituted hints ****\n"); - exit(255); - } - memmove(g->sbstems, s, egp[g->nsg-1] * sizeof(s[0])); - } -} - -void -buildstems( - GLYPH * g -) -{ - STEM hs[MAX_STEMS], vs[MAX_STEMS]; /* temporary working - * storage */ - short hs_pairs[MAX_STEMS], vs_pairs[MAX_STEMS]; /* best pairs for these stems */ - STEM *sp; - GENTRY *ge, *nge, *pge; - int nx, ny; - int ovalue; - int totals, grp, lastgrp; - - assertisint(g, "buildstems int"); - - g->nhs = g->nvs = 0; - memset(hs, 0, sizeof hs); - memset(vs, 0, sizeof vs); - - /* first search the whole character for possible stem points */ - - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_CURVE) { - - /* - * SURPRISE! - * We consider the stems bound by the - * H/V ends of the curves as flat ones. - * - * But we don't include the point on the - * other end into the range. - */ - - /* first check the beginning of curve */ - /* if it is horizontal, add a hstem */ - if (ge->iy1 == ge->prev->iy3) { - hs[g->nhs].value = ge->iy1; - - if (ge->ix1 < ge->prev->ix3) - hs[g->nhs].flags = ST_FLAT | ST_UP; - else - hs[g->nhs].flags = ST_FLAT; - - hs[g->nhs].origin = ge->prev->ix3; - hs[g->nhs].ge = ge; - - if (ge->ix1 < ge->prev->ix3) { - hs[g->nhs].from = ge->ix1+1; - hs[g->nhs].to = ge->prev->ix3; - if(hs[g->nhs].from > hs[g->nhs].to) - hs[g->nhs].from--; - } else { - hs[g->nhs].from = ge->prev->ix3; - hs[g->nhs].to = ge->ix1-1; - if(hs[g->nhs].from > hs[g->nhs].to) - hs[g->nhs].to++; - } - if (ge->ix1 != ge->prev->ix3) - g->nhs++; - } - /* if it is vertical, add a vstem */ - else if (ge->ix1 == ge->prev->ix3) { - vs[g->nvs].value = ge->ix1; - - if (ge->iy1 > ge->prev->iy3) - vs[g->nvs].flags = ST_FLAT | ST_UP; - else - vs[g->nvs].flags = ST_FLAT; - - vs[g->nvs].origin = ge->prev->iy3; - vs[g->nvs].ge = ge; - - if (ge->iy1 < ge->prev->iy3) { - vs[g->nvs].from = ge->iy1+1; - vs[g->nvs].to = ge->prev->iy3; - if(vs[g->nvs].from > vs[g->nvs].to) - vs[g->nvs].from--; - } else { - vs[g->nvs].from = ge->prev->iy3; - vs[g->nvs].to = ge->iy1-1; - if(vs[g->nvs].from > vs[g->nvs].to) - vs[g->nvs].to++; - } - - if (ge->iy1 != ge->prev->iy3) - g->nvs++; - } - /* then check the end of curve */ - /* if it is horizontal, add a hstem */ - if (ge->iy3 == ge->iy2) { - hs[g->nhs].value = ge->iy3; - - if (ge->ix3 < ge->ix2) - hs[g->nhs].flags = ST_FLAT | ST_UP; - else - hs[g->nhs].flags = ST_FLAT; - - hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if (ge->ix3 < ge->ix2) { - hs[g->nhs].from = ge->ix3; - hs[g->nhs].to = ge->ix2-1; - if( hs[g->nhs].from > hs[g->nhs].to ) - hs[g->nhs].to++; - } else { - hs[g->nhs].from = ge->ix2+1; - hs[g->nhs].to = ge->ix3; - if( hs[g->nhs].from > hs[g->nhs].to ) - hs[g->nhs].from--; - } - - if (ge->ix3 != ge->ix2) - g->nhs++; - } - /* if it is vertical, add a vstem */ - else if (ge->ix3 == ge->ix2) { - vs[g->nvs].value = ge->ix3; - - if (ge->iy3 > ge->iy2) - vs[g->nvs].flags = ST_FLAT | ST_UP; - else - vs[g->nvs].flags = ST_FLAT; - - vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if (ge->iy3 < ge->iy2) { - vs[g->nvs].from = ge->iy3; - vs[g->nvs].to = ge->iy2-1; - if( vs[g->nvs].from > vs[g->nvs].to ) - vs[g->nvs].to++; - } else { - vs[g->nvs].from = ge->iy2+1; - vs[g->nvs].to = ge->iy3; - if( vs[g->nvs].from > vs[g->nvs].to ) - vs[g->nvs].from--; - } - - if (ge->iy3 != ge->iy2) - g->nvs++; - } else { - - /* - * check the end of curve for a not smooth - * local extremum - */ - nge = ge->frwd; - - if (nge == 0) - continue; - else if (nge->type == GE_LINE) { - nx = nge->ix3; - ny = nge->iy3; - } else if (nge->type == GE_CURVE) { - nx = nge->ix1; - ny = nge->iy1; - } else - continue; - - /* check for vertical extremums */ - if (ge->iy3 > ge->iy2 && ge->iy3 > ny - || ge->iy3 < ge->iy2 && ge->iy3 < ny) { - hs[g->nhs].value = ge->iy3; - hs[g->nhs].from - = hs[g->nhs].to - = hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if (ge->ix3 < ge->ix2 - || nx < ge->ix3) - hs[g->nhs].flags = ST_UP; - else - hs[g->nhs].flags = 0; - - if (ge->ix3 != ge->ix2 || nx != ge->ix3) - g->nhs++; - } - /* - * the same point may be both horizontal and - * vertical extremum - */ - /* check for horizontal extremums */ - if (ge->ix3 > ge->ix2 && ge->ix3 > nx - || ge->ix3 < ge->ix2 && ge->ix3 < nx) { - vs[g->nvs].value = ge->ix3; - vs[g->nvs].from - = vs[g->nvs].to - = vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if (ge->iy3 > ge->iy2 - || ny > ge->iy3) - vs[g->nvs].flags = ST_UP; - else - vs[g->nvs].flags = 0; - - if (ge->iy3 != ge->iy2 || ny != ge->iy3) - g->nvs++; - } - } - - } else if (ge->type == GE_LINE) { - nge = ge->frwd; - - /* if it is horizontal, add a hstem */ - /* and the ends as vstems if they brace the line */ - if (ge->iy3 == ge->prev->iy3 - && ge->ix3 != ge->prev->ix3) { - hs[g->nhs].value = ge->iy3; - if (ge->ix3 < ge->prev->ix3) { - hs[g->nhs].flags = ST_FLAT | ST_UP; - hs[g->nhs].from = ge->ix3; - hs[g->nhs].to = ge->prev->ix3; - } else { - hs[g->nhs].flags = ST_FLAT; - hs[g->nhs].from = ge->prev->ix3; - hs[g->nhs].to = ge->ix3; - } - hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - pge = ge->bkwd; - - /* add beginning as vstem */ - vs[g->nvs].value = pge->ix3; - vs[g->nvs].origin - = vs[g->nvs].from - = vs[g->nvs].to = pge->iy3; - vs[g->nvs].ge = ge; - - if(pge->type==GE_CURVE) - ovalue=pge->iy2; - else - ovalue=pge->prev->iy3; - - if (pge->iy3 > ovalue) - vs[g->nvs].flags = ST_UP | ST_END; - else if (pge->iy3 < ovalue) - vs[g->nvs].flags = ST_END; - else - vs[g->nvs].flags = 0; - - if( vs[g->nvs].flags != 0 ) - g->nvs++; - - /* add end as vstem */ - vs[g->nvs].value = ge->ix3; - vs[g->nvs].origin - = vs[g->nvs].from - = vs[g->nvs].to = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if(nge->type==GE_CURVE) - ovalue=nge->iy1; - else - ovalue=nge->iy3; - - if (ovalue > ge->iy3) - vs[g->nvs].flags = ST_UP | ST_END; - else if (ovalue < ge->iy3) - vs[g->nvs].flags = ST_END; - else - vs[g->nvs].flags = 0; - - if( vs[g->nvs].flags != 0 ) - g->nvs++; - - g->nhs++; - } - /* if it is vertical, add a vstem */ - /* and the ends as hstems if they brace the line */ - else if (ge->ix3 == ge->prev->ix3 - && ge->iy3 != ge->prev->iy3) { - vs[g->nvs].value = ge->ix3; - if (ge->iy3 > ge->prev->iy3) { - vs[g->nvs].flags = ST_FLAT | ST_UP; - vs[g->nvs].from = ge->prev->iy3; - vs[g->nvs].to = ge->iy3; - } else { - vs[g->nvs].flags = ST_FLAT; - vs[g->nvs].from = ge->iy3; - vs[g->nvs].to = ge->prev->iy3; - } - vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - pge = ge->bkwd; - - /* add beginning as hstem */ - hs[g->nhs].value = pge->iy3; - hs[g->nhs].origin - = hs[g->nhs].from - = hs[g->nhs].to = pge->ix3; - hs[g->nhs].ge = ge; - - if(pge->type==GE_CURVE) - ovalue=pge->ix2; - else - ovalue=pge->prev->ix3; - - if (pge->ix3 < ovalue) - hs[g->nhs].flags = ST_UP | ST_END; - else if (pge->ix3 > ovalue) - hs[g->nhs].flags = ST_END; - else - hs[g->nhs].flags = 0; - - if( hs[g->nhs].flags != 0 ) - g->nhs++; - - /* add end as hstem */ - hs[g->nhs].value = ge->iy3; - hs[g->nhs].origin - = hs[g->nhs].from - = hs[g->nhs].to = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if(nge->type==GE_CURVE) - ovalue=nge->ix1; - else - ovalue=nge->ix3; - - if (ovalue < ge->ix3) - hs[g->nhs].flags = ST_UP | ST_END; - else if (ovalue > ge->ix3) - hs[g->nhs].flags = ST_END; - else - hs[g->nhs].flags = 0; - - if( hs[g->nhs].flags != 0 ) - g->nhs++; - - g->nvs++; - } - /* - * check the end of line for a not smooth local - * extremum - */ - nge = ge->frwd; - - if (nge == 0) - continue; - else if (nge->type == GE_LINE) { - nx = nge->ix3; - ny = nge->iy3; - } else if (nge->type == GE_CURVE) { - nx = nge->ix1; - ny = nge->iy1; - } else - continue; - - /* check for vertical extremums */ - if (ge->iy3 > ge->prev->iy3 && ge->iy3 > ny - || ge->iy3 < ge->prev->iy3 && ge->iy3 < ny) { - hs[g->nhs].value = ge->iy3; - hs[g->nhs].from - = hs[g->nhs].to - = hs[g->nhs].origin = ge->ix3; - hs[g->nhs].ge = ge->frwd; - - if (ge->ix3 < ge->prev->ix3 - || nx < ge->ix3) - hs[g->nhs].flags = ST_UP; - else - hs[g->nhs].flags = 0; - - if (ge->ix3 != ge->prev->ix3 || nx != ge->ix3) - g->nhs++; - } - /* - * the same point may be both horizontal and vertical - * extremum - */ - /* check for horizontal extremums */ - if (ge->ix3 > ge->prev->ix3 && ge->ix3 > nx - || ge->ix3 < ge->prev->ix3 && ge->ix3 < nx) { - vs[g->nvs].value = ge->ix3; - vs[g->nvs].from - = vs[g->nvs].to - = vs[g->nvs].origin = ge->iy3; - vs[g->nvs].ge = ge->frwd; - - if (ge->iy3 > ge->prev->iy3 - || ny > ge->iy3) - vs[g->nvs].flags = ST_UP; - else - vs[g->nvs].flags = 0; - - if (ge->iy3 != ge->prev->iy3 || ny != ge->iy3) - g->nvs++; - } - } - } - - g->nhs=addbluestems(hs, g->nhs); - sortstems(hs, g->nhs); - sortstems(vs, g->nvs); - - if (ISDBG(STEMS)) - debugstems(g->name, hs, g->nhs, vs, g->nvs); - - /* find the stems interacting with the Blue Zones */ - markbluestems(hs, g->nhs); - - if(subhints) { - if (ISDBG(SUBSTEMS)) - fprintf(pfa_file, "%% %s: joining subst horizontal stems\n", g->name); - joinsubstems(hs, hs_pairs, g->nhs, 1); - uniformstems(hs, hs_pairs, g->nhs); - - if (ISDBG(SUBSTEMS)) - fprintf(pfa_file, "%% %s: joining subst vertical stems\n", g->name); - joinsubstems(vs, vs_pairs, g->nvs, 0); - - groupsubstems(g, hs, hs_pairs, g->nhs, vs, vs_pairs, g->nvs); - } - - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% %s: joining main horizontal stems\n", g->name); - g->nhs = joinmainstems(hs, g->nhs, 1); - if (ISDBG(MAINSTEMS)) - fprintf(pfa_file, "%% %s: joining main vertical stems\n", g->name); - g->nvs = joinmainstems(vs, g->nvs, 0); - - if (ISDBG(MAINSTEMS)) - debugstems(g->name, hs, g->nhs, vs, g->nvs); - - if(g->nhs > 0) { - if ((sp = malloc(sizeof(STEM) * g->nhs)) == 0) { - fprintf(stderr, "**** not enough memory for hints ****\n"); - exit(255); - } - g->hstems = sp; - memcpy(sp, hs, sizeof(STEM) * g->nhs); - } else - g->hstems = 0; - - if(g->nvs > 0) { - if ((sp = malloc(sizeof(STEM) * g->nvs)) == 0) { - fprintf(stderr, "**** not enough memory for hints ****\n"); - exit(255); - } - g->vstems = sp; - memcpy(sp, vs, sizeof(STEM) * g->nvs); - } else - g->vstems = 0; - - /* now check that the stems won't overflow the interpreter's stem stack: - * some interpreters (like X11) push the stems on each change into - * stack and pop them only after the whole glyphs is completed. - */ - - totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */ - lastgrp = -1; - - for (ge = g->entries; ge != 0; ge = ge->next) { - grp=ge->stemid; - if(grp >= 0 && grp != lastgrp) { - if(grp==0) - totals += g->nsbs[0]; - else - totals += g->nsbs[grp] - g->nsbs[grp-1]; - - lastgrp = grp; - } - } - - /* be on the safe side, check for >= , not > */ - if(totals >= max_stemdepth) { /* oops, too deep */ - WARNING_2 { - fprintf(stderr, "Warning: glyph %s needs hint stack depth %d\n", g->name, totals); - fprintf(stderr, " (limit %d): removed the substituted hints from it\n", max_stemdepth); - } - if(g->nsg > 0) { - for (ge = g->entries; ge != 0; ge = ge->next) - ge->stemid = -1; - free(g->sbstems); g->sbstems = 0; - free(g->nsbs); g->nsbs = 0; - g->nsg = 0; - } - } - - /* now check if there are too many main stems */ - totals = (g->nhs+g->nvs) / 2; /* we count whole stems, not halves */ - if(totals >= max_stemdepth) { - /* even worse, too much of non-substituted stems */ - WARNING_2 { - fprintf(stderr, "Warning: glyph %s has %d main hints\n", g->name, totals); - fprintf(stderr, " (limit %d): removed the hints from it\n", max_stemdepth); - } - if(g->vstems) { - free(g->vstems); g->vstems = 0; g->nvs = 0; - } - if(g->hstems) { - free(g->hstems); g->hstems = 0; g->nhs = 0; - } - } -} - -/* convert weird curves that are close to lines into lines. -*/ - -void -fstraighten( - GLYPH * g -) -{ - GENTRY *ge, *pge, *nge, *ige; - double df; - int dir; - double iln, oln; - int svdir, i, o; - - for (ige = g->entries; ige != 0; ige = ige->next) { - if (ige->type != GE_CURVE) - continue; - - ge = ige; - pge = ge->bkwd; - nge = ge->frwd; - - df = 0.; - - /* look for vertical then horizontal */ - for(i=0; i<2; i++) { - o = !i; /* other axis */ - - iln = fabs(ge->fpoints[i][2] - pge->fpoints[i][2]); - oln = fabs(ge->fpoints[o][2] - pge->fpoints[o][2]); - /* - * if current curve is almost a vertical line, and it - * doesn't begin or end horizontally (and the prev/next - * line doesn't join smoothly ?) - */ - if( oln < 1. - || ge->fpoints[o][2] == ge->fpoints[o][1] - || ge->fpoints[o][0] == pge->fpoints[o][2] - || iln > 2. - || iln > 1. && iln/oln > 0.1 ) - continue; - - - if(ISDBG(STRAIGHTEN)) - fprintf(stderr,"** straighten almost %s\n", (i? "horizontal":"vertical")); - - df = ge->fpoints[i][2] - pge->fpoints[i][2]; - dir = fsign(ge->fpoints[o][2] - pge->fpoints[o][2]); - ge->type = GE_LINE; - - /* - * suck in all the sequence of such almost lines - * going in the same direction but not deviating - * too far from vertical - */ - iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]); - oln = nge->fpoints[o][2] - ge->fpoints[o][2]; - - while (fabs(df) <= 5 && nge->type == GE_CURVE - && dir == fsign(oln) /* that also gives oln != 0 */ - && iln <= 2. - && ( iln <= 1. || iln/fabs(oln) <= 0.1 ) ) { - ge->fx3 = nge->fx3; - ge->fy3 = nge->fy3; - - if(ISDBG(STRAIGHTEN)) - fprintf(stderr,"** straighten collapsing %s\n", (i? "horizontal":"vertical")); - freethisge(nge); - fixendpath(ge); - pge = ge->bkwd; - nge = ge->frwd; - - df = ge->fpoints[i][2] - pge->fpoints[i][2]; - - iln = fabs(nge->fpoints[i][2] - ge->fpoints[i][2]); - oln = nge->fpoints[o][2] - ge->fpoints[o][2]; - } - - /* now check what do we have as previous/next line */ - - if(ge != pge) { - if( pge->type == GE_LINE && pge->fpoints[i][2] == pge->prev->fpoints[i][2] - && fabs(pge->fpoints[o][2] != pge->prev->fpoints[o][2]) ) { - if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with previous 0x%x 0x%x\n", pge, ge); - /* join the previous line with current */ - pge->fx3 = ge->fx3; - pge->fy3 = ge->fy3; - - ige = freethisge(ge)->prev; /* keep the iterator valid */ - ge = pge; - fixendpath(ge); - pge = ge->bkwd; - } - } - - if(ge != nge) { - if (nge->type == GE_LINE && nge->fpoints[i][2] == ge->fpoints[i][2] - && fabs(nge->fpoints[o][2] != ge->fpoints[o][2]) ) { - if(ISDBG(STRAIGHTEN)) fprintf(stderr,"** straighten join with next 0x%x 0x%x\n", ge, nge); - /* join the next line with current */ - ge->fx3 = nge->fx3; - ge->fy3 = nge->fy3; - - freethisge(nge); - fixendpath(ge); - pge = ge->bkwd; - nge = ge->frwd; - - } - } - - if(ge != pge) { - /* try to align the lines if neccessary */ - if(df != 0.) - fclosegap(ge, ge, i, df, NULL); - } else { - /* contour consists of only one line, get rid of it */ - ige = freethisge(ge); /* keep the iterator valid */ - if(ige == 0) /* this was the last contour */ - return; - ige = ige->prev; - } - - break; /* don't bother looking at the other axis */ - } - } -} - -/* solve a square equation, - * returns the number of solutions found, the solutions - * are stored in res which should point to array of two doubles. - * min and max limit the area for solutions - */ - -static int -fsqequation( - double a, - double b, - double c, - double *res, - double min, - double max -) -{ - double D; - int n; - - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq(%g,%g,%g) [%g;%g]\n", a, b, c, min, max); - - if(fabs(a) < 0.000001) { /* if a linear equation */ - n=0; - if(fabs(b) < 0.000001) /* not an equation at all */ - return 0; - res[0] = -c/b; - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: linear t=%g\n", res[0]); - if(res[0] >= min && res[0] <= max) - n++; - return n; - } - - D = b*b - 4.0*a*c; - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: D=%g\n", D); - if(D<0) - return 0; - - D = sqrt(D); - - n=0; - res[0] = (-b+D) / (2*a); - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t1=%g\n", res[0]); - if(res[0] >= min && res[0] <= max) - n++; - - res[n] = (-b-D) / (2*a); - if(ISDBG(SQEQ)) fprintf(stderr, "sqeq: t2=%g\n", res[n]); - if(res[n] >= min && res[n] <= max) - n++; - - /* return 2nd solution only if it's different enough */ - if(n==2 && fabs(res[0]-res[1])<0.000001) - n=1; - - return n; -} - -/* check that the curves don't cross quadrant boundary */ -/* (float) */ - -/* - Here we make sure that the curve does not continue past - horizontal or vertical extremums. The horizontal points are - explained, vertical points are by analogy. - - The horizontal points are where the derivative - dy/dx is equal to 0. But the Bezier curves are defined by - parametric formulas - x=fx(t) - y=fy(t) - so finding this derivative is complicated. - Also even if we find some point (x,y) splitting at this point - is far not obvious. Fortunately we can use dy/dt = 0 instead, - this gets to a rather simple square equation and splitting - at a known value of t is simple. - - The formulas are: - - y = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3 - y = (-A+3*B-3*C+D)*t^3 + (3*A-6*B+3*C)*t^2 + (-3*A+3*B)*t + A - dy/dt = 3*(-A+3*B-3*C+D)*t^2 + 2*(3*A-6*B+3*C)*t + (-3*A+3*B) - */ - -void -ffixquadrants( - GLYPH *g -) -{ - GENTRY *ge, *nge; - int i, j, np, oldnp; - double sp[5]; /* split points, last one empty */ - char dir[5]; /* for debugging, direction by which split happened */ - double a, b, *pts; /* points of a curve */ - - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type != GE_CURVE) - continue; - - doagain: - np = 0; /* no split points yet */ - if(ISDBG(QUAD)) { - fprintf(stderr, "%s: trying 0x%x (%g %g) (%g %g) (%g %g) (%g %g)\n ", g->name, - ge, ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2, - ge->fx3, ge->fy3); - } - for(i=0; i<2; i++) { /* first for x then for y */ - /* find the cooridnates of control points */ - a = ge->prev->fpoints[i][2]; - pts = &ge->fpoints[i][0]; - - oldnp = np; - np += fsqequation( - 3.0*(-a + 3.0*pts[0] - 3.0*pts[1] + pts[2]), - 6.0*(a - 2.0*pts[0] + pts[1]), - 3.0*(-a + pts[0]), - &sp[np], - 0.0, 1.0); /* XXX range is [0;1] */ - - if(np == oldnp) - continue; - - if(ISDBG(QUAD)) - fprintf(stderr, "%s: 0x%x: %d pts(%c): ", - g->name, ge, np-oldnp, i? 'y':'x'); - - /* remove points that are too close to the ends - * because hor/vert ends are permitted, also - * if the split point is VERY close to the ends - * but not exactly then just flatten it and check again. - */ - for(j = oldnp; jfpoints[i][0] != ge->prev->fpoints[i][2]) { - ge->fpoints[i][0] = ge->prev->fpoints[i][2]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened at front\n"); - goto doagain; - } - if( ge->fpoints[i][1] != ge->fpoints[i][0] - && fsign(ge->fpoints[i][2] - ge->fpoints[i][1]) - != fsign(ge->fpoints[i][1] - ge->fpoints[i][0]) ) { - ge->fpoints[i][1] = ge->fpoints[i][0]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at front\n"); - goto doagain; - } - sp[j] = sp[j+1]; np--; j--; - if(ISDBG(QUAD)) fprintf(stderr, "(front flat) "); - } else if(sp[j] > 0.97) { /* rear end of curve */ - if(ge->fpoints[i][1] != ge->fpoints[i][2]) { - ge->fpoints[i][1] = ge->fpoints[i][2]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened at rear\n"); - goto doagain; - } - if( ge->fpoints[i][0] != ge->fpoints[i][1] - && fsign(ge->prev->fpoints[i][2] - ge->fpoints[i][0]) - != fsign(ge->fpoints[i][0] - ge->fpoints[i][1]) ) { - ge->fpoints[i][0] = ge->fpoints[i][1]; - if(ISDBG(QUAD)) fprintf(stderr, "flattened zigzag at rear\n"); - goto doagain; - } - sp[j] = sp[j+1]; np--; j--; - if(ISDBG(QUAD)) fprintf(stderr, "(rear flat) "); - } - } - if(ISDBG(QUAD)) fprintf(stderr, "\n"); - } - - if(np==0) /* no split points, leave it alone */ - continue; - - if(ISDBG(QUAD)) { - fprintf(stderr, "%s: splitting 0x%x (%g %g) (%g %g) (%g %g) (%g %g) at %d points\n ", g->name, - ge, ge->prev->fx3, ge->prev->fy3, ge->fx1, ge->fy1, ge->fx2, ge->fy2, - ge->fx3, ge->fy3, np); - for(i=0; i sp[j]) { - a = sp[i]; sp[i] = sp[j]; sp[j] = a; - } - - /* now finally do the split on each point */ - for(j=0; jfpoints[i][0]; /* get the middle points */ - b = ge->fpoints[i][1]; - - /* calculate new internal points */ - c = SPLIT(a, b); - - ge->fpoints[i][0] = SPLIT(ge->prev->fpoints[i][2], a); - ge->fpoints[i][1] = SPLIT(ge->fpoints[i][0], c); - - nge->fpoints[i][1] = SPLIT(b, nge->fpoints[i][2]); - nge->fpoints[i][0] = SPLIT(c, nge->fpoints[i][1]); - - ge->fpoints[i][2] = SPLIT(ge->fpoints[i][1], - + nge->fpoints[i][0]); - } -#undef SPLIT - - addgeafter(ge, nge); - - /* go to the next part, adjust remaining points */ - ge = nge; - for(i=j+1; itype != GE_CURVE) - return 0; - - a = ge->iy2 - ge->iy1; - b = ge->ix2 - ge->ix1; - if(a == 0) { - if(b == 0) { - return 0; - } else - k = FBIGVAL; - } else - k = fabs((double) b / (double) a); - - a = ge->iy1 - ge->prev->iy3; - b = ge->ix1 - ge->prev->ix3; - if(a == 0) { - if(b == 0) { - return 0; - } else - k1 = FBIGVAL; - } else - k1 = fabs((double) b / (double) a); - - a = ge->iy3 - ge->iy2; - b = ge->ix3 - ge->ix2; - if(a == 0) { - if(b == 0) { - return 0; - } else - k2 = FBIGVAL; - } else - k2 = fabs((double) b / (double) a); - - /* if the curve is not a zigzag */ - if (k1+0.0001 >= k && k2 <= k+0.0001 || k1 <= k+0.0001 && k2+0.0001 >= k) - return 0; - else - return 1; -} - -/* check if a curve is a zigzag - floating */ - -static int -fiszigzag( - GENTRY *ge -) -{ - double k, k1, k2; - double a, b; - - if (ge->type != GE_CURVE) - return 0; - - a = fabs(ge->fy2 - ge->fy1); - b = fabs(ge->fx2 - ge->fx1); - if(a < FEPS) { - if(b < FEPS) { - return 0; - } else - k = FBIGVAL; - } else - k = b / a; - - a = fabs(ge->fy1 - ge->prev->fy3); - b = fabs(ge->fx1 - ge->prev->fx3); - if(a < FEPS) { - if(b < FEPS) { - return 0; - } else - k1 = FBIGVAL; - } else - k1 = b / a; - - a = fabs(ge->fy3 - ge->fy2); - b = fabs(ge->fx3 - ge->fx2); - if(a < FEPS) { - if(b < FEPS) { - return 0; - } else - k2 = FBIGVAL; - } else - k2 = b / a; - - /* if the curve is not a zigzag */ - if (k1+0.0001 >= k && k2 <= k+0.0001 || k1 <= k+0.0001 && k2+0.0001 >= k) - return 0; - else - return 1; -} - -/* split the zigzag-like curves into two parts */ - -void -fsplitzigzags( - GLYPH * g -) -{ - GENTRY *ge, *nge; - double a, b, c, d; - - assertisfloat(g, "splitting zigzags"); - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type != GE_CURVE) - continue; - - /* if the curve is not a zigzag */ - if ( !fiszigzag(ge) ) { - continue; - } - - if(ISDBG(FCONCISE)) { - double maxsc1, maxsc2; - fprintf(stderr, "split a zigzag "); - fnormalizege(ge); - if( fcrossraysge(ge, ge, &maxsc1, &maxsc2, NULL) ) { - fprintf(stderr, "sc1=%g sc2=%g\n", maxsc1, maxsc2); - } else { - fprintf(stderr, "(rays don't cross)\n"); - } - } - /* split the curve by t=0.5 */ - nge = newgentry(GEF_FLOAT); - (*nge) = (*ge); - nge->type = GE_CURVE; - - a = ge->prev->fx3; - b = ge->fx1; - c = ge->fx2; - d = ge->fx3; - nge->fx3 = d; - nge->fx2 = (c + d) / 2.; - nge->fx1 = (b + 2. * c + d) / 4.; - ge->fx3 = (a + b * 3. + c * 3. + d) / 8.; - ge->fx2 = (a + 2. * b + c) / 4.; - ge->fx1 = (a + b) / 2.; - - a = ge->prev->fy3; - b = ge->fy1; - c = ge->fy2; - d = ge->fy3; - nge->fy3 = d; - nge->fy2 = (c + d) / 2.; - nge->fy1 = (b + 2. * c + d) / 4.; - ge->fy3 = (a + b * 3. + c * 3. + d) / 8.; - ge->fy2 = (a + 2. * b + c) / 4.; - ge->fy1 = (a + b) / 2.; - - addgeafter(ge, nge); - - if(ISDBG(FCONCISE)) { - dumppaths(g, ge, nge); - } - } -} - -/* free this GENTRY, returns what was ge->next - * (ge must be of type GE_LINE or GE_CURVE) - * works on both float and int entries - */ - -static GENTRY * -freethisge( - GENTRY *ge -) -{ - GENTRY *xge; - - if (ge->bkwd != ge->prev) { - /* at beginning of the contour */ - - xge = ge->bkwd; - if(xge == ge) { /* was the only line in contour */ - /* remove the contour completely */ - /* prev is GE_MOVE, next is GE_PATH, remove them all */ - - /* may be the first contour, then ->bkwd points to ge->entries */ - if(ge->prev->prev == 0) - *(GENTRY **)(ge->prev->bkwd) = ge->next->next; - else - ge->prev->prev->next = ge->next->next; - - if(ge->next->next) { - ge->next->next->prev = ge->prev->prev; - ge->next->next->bkwd = ge->prev->bkwd; - } - - xge = ge->next->next; - free(ge->prev); free(ge->next); free(ge); - return xge; - } - - /* move the start point of the contour */ - if(ge->flags & GEF_FLOAT) { - ge->prev->fx3 = xge->fx3; - ge->prev->fy3 = xge->fy3; - } else { - ge->prev->ix3 = xge->ix3; - ge->prev->iy3 = xge->iy3; - } - } else if(ge->frwd != ge->next) { - /* at end of the contour */ - - xge = ge->frwd->prev; - /* move the start point of the contour */ - if(ge->flags & GEF_FLOAT) { - xge->fx3 = ge->bkwd->fx3; - xge->fy3 = ge->bkwd->fy3; - } else { - xge->ix3 = ge->bkwd->ix3; - xge->iy3 = ge->bkwd->iy3; - } - } - - ge->prev->next = ge->next; - ge->next->prev = ge->prev; - ge->bkwd->frwd = ge->frwd; - ge->frwd->bkwd = ge->bkwd; - - xge = ge->next; - free(ge); - return xge; -} - -/* inserts a new gentry (LINE or CURVE) after another (MOVE - * or LINE or CURVE) - * corrects the first GE_MOVE if neccessary - */ - -static void -addgeafter( - GENTRY *oge, /* after this */ - GENTRY *nge /* insert this */ -) -{ - if(oge->type == GE_MOVE) { - /* insert before next */ - if(oge->next->type == GE_PATH) { - /* first and only GENTRY in path */ - nge->frwd = nge->bkwd = nge; - } else { - nge->frwd = oge->next; - nge->bkwd = oge->next->bkwd; - oge->next->bkwd->frwd = nge; - oge->next->bkwd = nge; - } - } else { - nge->frwd = oge->frwd; - nge->bkwd = oge; - oge->frwd->bkwd = nge; - oge->frwd = nge; - } - - nge->next = oge->next; - nge->prev = oge; - oge->next->prev = nge; - oge->next = nge; - - if(nge->frwd->prev->type == GE_MOVE) { - /* fix up the GE_MOVE entry */ - if(nge->flags & GEF_FLOAT) { - nge->frwd->prev->fx3 = nge->fx3; - nge->frwd->prev->fy3 = nge->fy3; - } else { - nge->frwd->prev->ix3 = nge->ix3; - nge->frwd->prev->iy3 = nge->iy3; - } - } -} - -/* - * Check if this GENTRY happens to be at the end of path - * and fix the first MOVETO accordingly - * handles both int and float - */ - -static void -fixendpath( - GENTRY *ge -) -{ - GENTRY *mge; - - mge = ge->frwd->prev; - if(mge->type == GE_MOVE) { - if(ge->flags & GEF_FLOAT) { - mge->fx3 = ge->fx3; - mge->fy3 = ge->fy3; - } else { - mge->ix3 = ge->ix3; - mge->iy3 = ge->iy3; - } - } -} - -/* - * This function adjusts the rest of path (the part from...to is NOT changed) - * to cover the specified gap by the specified axis (0 - X, 1 - Y). - * Gap is counted in direction (end_of_to - beginning_of_from). - * Returns by how much the gap was not closed (0.0 if it was fully closed). - * Ret contains by how much the first and last points of [from...to] - * were moved to bring them in consistence to the rest of the path. - * If ret==NULL then this info is not returned. - */ - -static double -fclosegap( - GENTRY *from, - GENTRY *to, - int axis, - double gap, - double *ret -) -{ -#define TIMESLARGER 10. /* how many times larger must be a curve to not change too much */ - double rm[2]; - double oldpos[2]; - double times, limit, df, dx; - int j, k; - GENTRY *xge, *pge, *nge, *bge[2]; - - /* remember the old points to calculate ret */ - oldpos[0] = from->prev->fpoints[axis][2]; - oldpos[1] = to->fpoints[axis][2]; - - rm[0] = rm[1] = gap / 2. ; - - bge[0] = from; /* this is convenient for iterations */ - bge[1] = to; - - /* first try to modify large curves but if have none then settle for small */ - for(times = (TIMESLARGER-1); times > 0.1; times /= 2. ) { - - if(rm[0]+rm[1] == 0.) - break; - - /* iterate in both directions, backwards then forwards */ - for(j = 0; j<2; j++) { - - if(rm[j] == 0.) /* if this direction is exhausted */ - continue; - - limit = fabs(rm[j]) * (1.+times); - - for(xge = bge[j]->cntr[j]; xge != bge[!j]; xge = xge->cntr[j]) { - dx = xge->fpoints[axis][2] - xge->prev->fpoints[axis][2]; - df = fabs(dx) - limit; - if( df <= FEPS ) /* curve is too small to change */ - continue; - - if( df >= fabs(rm[j]) ) - df = rm[j]; - else - df *= fsign(rm[j]); /* we may cover this part of rm */ - - rm[j] -= df; - limit = fabs(rm[j]) * (1.+times); - - if(xge->type == GE_CURVE) { /* correct internal points */ - double scale = ((dx+df) / dx) - 1.; - double base; - - if(j) - base = xge->fpoints[axis][2]; - else - base = xge->prev->fpoints[axis][2]; - - for(k = 0; k<2; k++) - xge->fpoints[axis][k] += scale * - (xge->fpoints[axis][k] - base); - } - - /* move all the intermediate lines */ - if(j) { - df = -df; /* absolute direction */ - pge = bge[1]->bkwd; - nge = xge->bkwd; - } else { - xge->fpoints[axis][2] += df; - pge = bge[0]; - nge = xge->frwd; - } - while(nge != pge) { - if(nge->type == GE_CURVE) { - nge->fpoints[axis][0] +=df; - nge->fpoints[axis][1] +=df; - } - nge->fpoints[axis][2] += df; - if(nge->next != nge->frwd) { /* last entry of contour */ - nge->frwd->prev->fpoints[axis][2] += df; - } - nge = nge->cntr[!j]; - } - - if(rm[j] == 0.) - break; - } - } - } - - /* find the difference */ - oldpos[0] -= from->prev->fpoints[axis][2]; - oldpos[1] -= to->fpoints[axis][2]; - - if(ret) { - ret[0] = oldpos[0] - from->prev->fpoints[axis][2]; - ret[1] = oldpos[1] - to->fpoints[axis][2]; - } - -#if 0 - if( rm[0]+rm[1] != gap - oldpos[1] + oldpos[0]) { - fprintf(stderr, "** gap=%g rm[0]=%g rm[1]=%g o[0]=%g o[1]=%g rg=%g og=%g\n", - gap, rm[0], rm[1], oldpos[0], oldpos[1], rm[0]+rm[1], - gap - oldpos[1] + oldpos[0]); - } -#endif - - return rm[0]+rm[1]; -#undef TIMESLARGER -} - -/* remove the lines or curves smaller or equal to the size limit */ - -static void -fdelsmall( - GLYPH *g, - double minlen -) -{ - GENTRY *ge, *nge, *pge, *xge, *next; - int i, k; - double dx, dy, d2, d2m; - double minlen2; -#define TIMESLARGER 10. /* how much larger must be a curve to not change too much */ - - minlen2 = minlen*minlen; - - for (ge = g->entries; ge != 0; ge = next) { - next = ge->next; - - if (ge->type != GE_CURVE && ge->type != GE_LINE) - continue; - - d2m = 0; - for(i= (ge->type==GE_CURVE? 0: 2); i<3; i++) { - dx = ge->fxn[i] - ge->prev->fx3; - dy = ge->fyn[i] - ge->prev->fy3; - d2 = dx*dx + dy*dy; - if(d2m < d2) - d2m = d2; - } - - if( d2m > minlen2 ) { /* line is not too small */ - /* XXX add more normalization here */ - continue; - } - - /* if the line is too small */ - - /* check forwards if we have a whole sequence of them */ - nge = ge; - for(xge = ge->frwd; xge != ge; xge = xge->frwd) { - d2m = 0; - for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) { - dx = xge->fxn[i] - xge->prev->fx3; - dy = xge->fyn[i] - xge->prev->fy3; - d2 = dx*dx + dy*dy; - if(d2m < d2) - d2m = d2; - } - if( d2m > minlen2 ) /* line is not too small */ - break; - nge = xge; - if(next == nge) /* move the next step past this sequence */ - next = next->next; - } - - /* check backwards if we have a whole sequence of them */ - pge = ge; - for(xge = ge->bkwd; xge != ge; xge = xge->bkwd) { - d2m = 0; - for(i= (xge->type==GE_CURVE? 0: 2); i<3; i++) { - dx = xge->fxn[i] - xge->prev->fx3; - dy = xge->fyn[i] - xge->prev->fy3; - d2 = dx*dx + dy*dy; - if(d2m < d2) - d2m = d2; - } - if( d2m > minlen2 ) /* line is not too small */ - break; - pge = xge; - } - - /* now we have a sequence of small fragments in pge...nge (inclusive) */ - - if(ISDBG(FCONCISE)) { - fprintf(stderr, "glyph %s has very small fragments(%x..%x..%x)\n", - g->name, pge, ge, nge); - dumppaths(g, pge, nge); - } - - /* reduce whole sequence to one part and remember the middle point */ - if(pge != nge) { - while(1) { - xge = pge->frwd; - if(xge == nge) { - pge->fx1 = pge->fx2 = pge->fx3; - pge->fx3 = nge->fx3; - pge->fy1 = pge->fy2 = pge->fy3; - pge->fy3 = nge->fy3; - pge->type = GE_CURVE; - freethisge(nge); - break; - } - if(xge == nge->bkwd) { - pge->fx1 = pge->fx2 = (pge->fx3+xge->fx3)/2.; - pge->fx3 = nge->fx3; - pge->fy1 = pge->fy2 = (pge->fy3+xge->fy3)/2.; - pge->fy3 = nge->fy3; - pge->type = GE_CURVE; - freethisge(nge); - freethisge(xge); - break; - } - freethisge(pge); pge = xge; - xge = nge->bkwd; freethisge(nge); nge = xge; - } - } - ge = pge; - - /* check if the whole sequence is small */ - dx = ge->fx3 - ge->prev->fx3; - dy = ge->fy3 - ge->prev->fy3; - d2 = dx*dx + dy*dy; - - if( d2 > minlen2 ) { /* no, it is not */ - double b, d; - - WARNING_3 fprintf(stderr, "glyph %s had a sequence of fragments < %g points each, reduced to one curve\n", - g->name, minlen); - - /* check that we did not create a monstrosity spanning quadrants */ - if(fsign(ge->fx1 - ge->prev->fx1) * fsign(ge->fx3 - ge->fx1) < 0 - || fsign(ge->fy1 - ge->prev->fy1) * fsign(ge->fy3 - ge->fy1) < 0 ) { - /* yes, we did; are both parts of this thing big enough ? */ - dx = ge->fx1 - ge->prev->fx3; - dy = ge->fy1 - ge->prev->fy3; - d2 = dx*dx + dy*dy; - - dx = ge->fx3 - ge->fx1; - dy = ge->fy3 - ge->fy1; - d2m = dx*dx + dy*dy; - - if(d2 > minlen2 && d2m > minlen2) { /* make two straights */ - nge = newgentry(GEF_FLOAT); - *nge = *ge; - - for(i=0; i<2; i++) { - ge->fpoints[i][2] = ge->fpoints[i][0]; - b = nge->fpoints[i][0]; - d = nge->fpoints[i][2] - b; - nge->fpoints[i][0] = b + 0.1*d; - nge->fpoints[i][1] = b + 0.9*d; - } - } - for(i=0; i<2; i++) { /* make one straight or first of two straights */ - b = ge->prev->fpoints[i][2]; - d = ge->fpoints[i][2] - b; - ge->fpoints[i][0] = b + 0.1*d; - ge->fpoints[i][1] = b + 0.9*d; - } - } - continue; - } - - if(ge->frwd == ge) { /* points to itself, just remove the path completely */ - WARNING_3 fprintf(stderr, "glyph %s had a path made of fragments < %g points each, removed\n", - g->name, minlen); - - next = freethisge(ge); - continue; - } - - /* now close the gap by x and y */ - for(i=0; i<2; i++) { - double gap; - - gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2]; - if( fclosegap(ge, ge, i, gap, NULL) != 0.0 ) { - double scale, base; - - /* not good, as the last resort just scale the next line */ - gap = ge->fpoints[i][2] - ge->prev->fpoints[i][2]; - - if(ISDBG(FCONCISE)) - fprintf(stderr, " last resort on %c: closing next by %g\n", - (i==0 ? 'x' : 'y'), gap); - - nge = ge->frwd; - base = nge->fpoints[i][2]; - dx = ge->fpoints[i][2] - base; - if(fabs(dx) < FEPS) - continue; - - scale = ((dx-gap) / dx); - - if(nge->type == GE_CURVE) - for(k = 0; k<2; k++) - nge->fpoints[i][k] = base + - scale * (nge->fpoints[i][k] - base); - - ge->fpoints[i][2] -= gap; - } - } - - /* OK, the gap is closed - remove this useless GENTRY */ - freethisge(ge); - } -#undef TIMESLARGER -} - -/* find the point where two rays continuing vectors cross - * returns 1 if they cross, 0 if they don't - * If they cross optionally (if the pointers are not NULL) returns - * the maximal scales for both vectors and also optionally the point - * where the rays cross (twice). - * Expects that the curves are normalized. - * - * For convenience there are 2 front-end functions taking - * arguments in different formats - */ - -struct ray { - double x1, y1, x2, y2; - int isvert; - double k, b; /* lines are represented as y = k*x + b */ - double *maxp; -}; -static struct ray ray[3]; - -/* the back-end doing the actual work - * the rays are defined in the static array ray[] - */ - -static int -fcrossraysxx( - double crossdot[2][2] -) -{ - double x, y, max; - int i; - - for(i=0; i<2; i++) { - if(ray[i].x1 == ray[i].x2) - ray[i].isvert = 1; - else { - ray[i].isvert = 0; - ray[i].k = (ray[i].y2 - ray[i].y1) / (ray[i].x2 - ray[i].x1); - ray[i].b = ray[i].y2 - ray[i].k * ray[i].x2; - } - } - - if(ray[0].isvert && ray[1].isvert) { - if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: both vertical\n"); - return 0; /* both vertical, don't cross */ - } - - if(ray[1].isvert) { - ray[2] = ray[0]; /* exchange them */ - ray[0] = ray[1]; - ray[1] = ray[2]; - } - - if(ray[0].isvert) { - x = ray[0].x1; - } else { - if( fabs(ray[0].k - ray[1].k) < FEPS) { - if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: parallel lines, k = %g, %g\n", - ray[0].k, ray[1].k); - return 0; /* parallel lines */ - } - x = (ray[1].b - ray[0].b) / (ray[0].k - ray[1].k) ; - } - y = ray[1].k * x + ray[1].b; - - for(i=0; i<2; i++) { - if(ray[i].isvert) - max = (y - ray[i].y1) / (ray[i].y2 - ray[i].y1); - else - max = (x - ray[i].x1) / (ray[i].x2 - ray[i].x1); - /* check if wrong sides of rays cross */ - if( max < 0 ) { - if(ISDBG(FCONCISE)) fprintf(stderr, "crossrays: %c scale=%g @(%g,%g) (%g,%g)<-(%g,%g)\n", - (i?'Y':'X'), max, x, y, ray[i].x2, ray[i].y2, ray[i].x1, ray[i].y1); - return 0; - } - if(ray[i].maxp) - *ray[i].maxp = max; - } - if(crossdot != 0) { - crossdot[0][0] = crossdot[1][0] = x; - crossdot[0][1] = crossdot[1][1] = y; - } - return 1; -} - -/* the front-end getting the arguments from 4 dots defining - * a curve in the same format as for fapproxcurve(): - * rays are defined as beginning and end of the curve, - * the crossdot is inserted as the two middle dots of the curve - */ - -int -fcrossrayscv( - double curve[4][2 /*X,Y*/], - double *max1, - double *max2 -) -{ - ray[0].x1 = curve[0][X]; - ray[0].y1 = curve[0][Y]; - ray[0].x2 = curve[1][X]; - ray[0].y2 = curve[1][Y]; - ray[0].maxp = max1; - - ray[1].x1 = curve[2][X]; - ray[1].y1 = curve[2][Y]; - ray[1].x2 = curve[3][X]; - ray[1].y2 = curve[3][Y]; - ray[1].maxp = max2; - - return fcrossraysxx(&curve[1]); -} - -/* the front-end getting the arguments from gentries: - * rays are defined as beginning of curve1 and end of curve 2 - */ - -int -fcrossraysge( - GENTRY *ge1, - GENTRY *ge2, - double *max1, - double *max2, - double crossdot[2][2] -) -{ - ray[0].x1 = ge1->prev->fx3; - ray[0].y1 = ge1->prev->fy3; - ray[0].x2 = ge1->fpoints[X][ge1->ftg]; - ray[0].y2 = ge1->fpoints[Y][ge1->ftg]; - ray[0].maxp = max1; - - ray[1].x1 = ge2->fx3; - ray[1].y1 = ge2->fy3; - if(ge2->rtg < 0) { - ray[1].x2 = ge2->prev->fx3; - ray[1].y2 = ge2->prev->fy3; - } else { - ray[1].x2 = ge2->fpoints[X][ge2->rtg]; - ray[1].y2 = ge2->fpoints[Y][ge2->rtg]; - } - ray[1].maxp = max2; - - return fcrossraysxx(crossdot); -} - -/* debugging printout functions */ - -#if defined(DEBUG_DOTSEG) || defined(DEBUG_DOTCURVE) || defined(DEBUG_APPROXCV) - -/* for debugging */ -static -printdot( - double dot[2] -) -{ - fprintf(stderr, "(%g,%g)", dot[0], dot[1]); -} - -static -printseg( - double seg[2][2] -) -{ - putc('[', stderr); - printdot(seg[0]); - putc(' ', stderr); - printdot(seg[1]); - putc(']', stderr); -} - -#endif /* DEBUG_* */ - -/* - * Find squared distance from a dot to a line segment - */ - -double -fdotsegdist2( - double seg[2][2 /*X,Y*/], - double dot[2 /*X,Y*/] -) -{ -#define x1 seg[0][X] -#define y1 seg[0][Y] -#define x2 seg[1][X] -#define y2 seg[1][Y] -#define xdot dot[X] -#define ydot dot[Y] - - double dx, dy; /* segment dimensions */ - double kline, bline; /* segment line formula is y=k*x+b */ - double kperp, bperp; /* perpendicular from the dot to the line */ - double xcross, ycross; /* where the perpendicular crosses the segment */ - -/* handle the situation where the nearest point of the segment is its end */ -#define HANDLE_LIMITS(less12, lesscr1, lesscr2) \ - if( less12 ) { \ - if( lesscr1 ) { \ - xcross = x1; \ - ycross = y1; \ - } else if( !(lesscr2) ) { \ - xcross = x2; \ - ycross = y2; \ - } \ - } else { \ - if( !(lesscr1) ) { \ - xcross = x1; \ - ycross = y1; \ - } else if( lesscr2 ) { \ - xcross = x2; \ - ycross = y2; \ - } \ - } \ - /* end of macro */ - - - dx = x2 - x1; - dy = y2 - y1; - - if(fabs(dx) < FEPS) { - /* special case - vertical line */ -#ifdef DEBUG_DOTSEG - printf("vertical line!\n"); -#endif - xcross = x1; - ycross = ydot; - HANDLE_LIMITS( y1 < y2, ycross < y1, ycross < y2); - } else if(fabs(dy) < FEPS) { - /* special case - horizontal line */ -#ifdef DEBUG_DOTSEG - printf("horizontal line!\n"); -#endif - xcross = xdot; - ycross = y1; - HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2) - } else { - kline = dy/dx; - bline = y1 - x1*kline; - kperp = -1./kline; - bperp = ydot - xdot*kperp; - - xcross = (bline-bperp) / (kperp-kline); - ycross = kline*xcross + bline; - - HANDLE_LIMITS( x1 < x2, xcross < x1, xcross < x2) - } -#ifdef DEBUG_DOTSEG - printf("crossover at (%g,%g)\n", xcross, ycross); -#endif - - dx = xdot-xcross; - dy = ydot-ycross; - return dx*dx+dy*dy; -#undef x1 -#undef y1 -#undef x2 -#undef y2 -#undef xdot -#undef ydot -#undef HANDLE_LIMITS -} - -/* find the weighted quadratic average for the distance of a set - * of dots from the curve; also fills out the individual distances - * for each dot; if maxp!=NULL then returns the maximal squared - * distance in there - */ - -double -fdotcurvdist2( - double curve[4][2 /*X,Y*/ ], - struct dot_dist *dots, - int ndots, /* number of entries in dots */ - double *maxp -) -{ - /* a curve is approximated by this many straight segments */ -#define NAPSECT 16 - /* a curve is divided into this many sections with equal weight each */ -#define NWSECT 4 - /* table of coefficients for finding the dots on the curve */ - /* tt[0] is left unused */ - static double tt[NAPSECT][4]; - static int havett = 0; /* flag: tt is initialized */ - /* dots on the curve */ - double cvd[NAPSECT+1][2 /*X,Y*/]; - /* sums by sections */ - double sum[NWSECT]; - /* counts by sections */ - double count[NWSECT]; - int d, i, j; - int id1, id2; - double dist1, dist2, dist3, dx, dy, x, y; - double max = 0.; - - if(!havett) { - double t, nt, t2, nt2, step; - - havett++; - step = 1. / NAPSECT; - t = 0; - for(i=1; iid1+1; i--) { - dx = x - cvd[i][X]; - dy = y - cvd[i][Y]; - dist3 = dx*dx + dy*dy; -#ifdef DEBUG_DOTCURVE - printf(" dot %d ",i); printdot(cvd[i]); printf(" dist=%g\n", sqrt(dist3)); -#endif - if(dist3 < dist2) { - dist2 = dist3; - id2 = i; - } else - break; - } - - /* now find which of the local minimums is smaller */ - if(dist2 < dist1) { - id1 = id2; - } - } - - /* the nearest segment must include the nearest dot */ - if(id1==0) { - dots[d].seg = 0; - dots[d].dist2 = fdotsegdist2(&cvd[0], dots[d].p); - } else if(id1==NAPSECT) { - dots[d].seg = NAPSECT-1; - dots[d].dist2 = fdotsegdist2(&cvd[NAPSECT-1], dots[d].p); - } else { - dist1 = fdotsegdist2(&cvd[id1], dots[d].p); - dist2 = fdotsegdist2(&cvd[id1-1], dots[d].p); - if(dist2 < dist1) { - dots[d].seg = id1-1; - dots[d].dist2 = dist2; - } else { - dots[d].seg = id1; - dots[d].dist2 = dist1; - } - } - - i = dots[d].seg % NWSECT; - sum[i] += dots[d].dist2; - if(dots[d].dist2 > max) - max = dots[d].dist2; - count[i]++; -#ifdef DEBUG_DOTCURVE - printf(" best seg %d sect %d dist=%g\n", dots[d].seg, i, sqrt(dots[d].dist2)); -#endif - } - - /* calculate the weighted average */ - id1=0; - dist1=0.; - for(i=0; irtg < 0) { - d[1][X] = ge1->fx3 - ge1->prev->fx3; - d[1][Y] = ge1->fy3 - ge1->prev->fy3; - } else { - d[1][X] = ge1->fx3 - ge1->fpoints[X][ge1->rtg]; - d[1][Y] = ge1->fy3 - ge1->fpoints[Y][ge1->rtg]; - } - d[2][X] = ge2->fpoints[X][ge2->ftg] - ge2->prev->fx3; - d[2][Y] = ge2->fpoints[Y][ge2->ftg] - ge2->prev->fy3; - - len1 = sqrt( d[1][X]*d[1][X] + d[1][Y]*d[1][Y] ); - len2 = sqrt( d[2][X]*d[2][X] + d[2][Y]*d[2][Y] ); - /* scale the 2nd segment to the length of 1 - * and to make sure that the 1st segment is longer scale it to - * the length of 2 and extend to the same distance backwards - */ - scale1 = 2./len1; - scale2 = 1./len2; - - for(axis=0; axis <2; axis++) { - d[0][axis] = -( d[1][axis] *= scale1 ); - d[2][axis] *= scale2; - } - return fdotsegdist2(d, d[2]); -} - -#if 0 -/* find the area covered by the curve - * (limited by the projections to the X axis) - */ - -static double -fcvarea( - GENTRY *ge -) -{ - double Ly, My, Ny, Py, Qx, Rx, Sx; - double area; - - /* y = Ly*t^3 + My*t^2 + Ny*t + Py */ - Ly = -ge->prev->fy3 + 3*(ge->fy1 - ge->fy2) + ge->fy3; - My = 3*ge->prev->fy3 - 6*ge->fy1 + 3*ge->fy2; - Ny = 3*(-ge->prev->fy3 + ge->fy1); - Py = ge->prev->fy3; - - /* dx/dt = Qx*t^2 + Rx*t + Sx */ - Qx = 3*(-ge->prev->fx3 + 3*(ge->fx1 - ge->fx2) + ge->fx3); - Rx = 6*(ge->prev->fx3 - 2*ge->fx1 + ge->fx2); - Sx = 3*(-ge->prev->fx3 + ge->fx1); - - /* area is integral[from 0 to 1]( y(t) * dx(t)/dt *dt) */ - area = 1./6.*(Ly*Qx) + 1./5.*(Ly*Rx + My*Qx) - + 1./4.*(Ly*Sx + My*Rx + Ny*Qx) + 1./3.*(My*Sx + Ny*Rx + Py*Qx) - + 1./2.*(Ny*Sx + Py*Rx) + Py*Sx; - - return area; -} -#endif - -/* find the value of point on the curve at the given parameter t, - * along the given axis (0 - X, 1 - Y). - */ - -static double -fcvval( - GENTRY *ge, - int axis, - double t -) -{ - double t2, mt, mt2; - - /* val = A*(1-t)^3 + 3*B*(1-t)^2*t + 3*C*(1-t)*t^2 + D*t^3 */ - t2 = t*t; - mt = 1-t; - mt2 = mt*mt; - - return ge->prev->fpoints[axis][2]*mt2*mt - + 3*(ge->fpoints[axis][0]*mt2*t + ge->fpoints[axis][1]*mt*t2) - + ge->fpoints[axis][2]*t*t2; -} - -/* - * Find ndots equally spaced dots on a curve or line and fill - * their coordinates into the dots array - */ - -static void -fsampledots( - GENTRY *ge, - double dots[][2], /* the dots to fill */ - int ndots -) -{ - int i, axis; - double t, nf, dx, d[2]; - - nf = ndots+1; - if(ge->type == GE_CURVE) { - for(i=0; ifx3 - ge->prev->fx3; - d[1] = ge->fy3 - ge->prev->fy3; - for(i=0; iprev->fpoints[axis][2] - + t*d[axis]; - } - } -} - -/* - * Allocate a structure gex_con - */ - -static void -alloc_gex_con( - GENTRY *ge -) -{ - ge->ext = (void*)calloc(1, sizeof(GEX_CON)); - if(ge->ext == 0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } -} - -/* - * Normalize a gentry for fforceconcise() : find the points that - * can be used to calculate the tangents. - */ - -static void -fnormalizege( - GENTRY *ge -) -{ - int midsame, frontsame, rearsame; - - if(ge->type == GE_LINE) { - ge->ftg = 2; - ge->rtg = -1; - } else { /* assume it's a curve */ - midsame = (fabs(ge->fx1-ge->fx2)fy1-ge->fy2)fx1-ge->prev->fx3)fy1-ge->prev->fy3)fx3-ge->fx2)fy3-ge->fy2)ftg = 2; - ge->rtg = -1; - } else { - if(frontsame) { - ge->ftg = 1; - } else { - ge->ftg = 0; - } - if(rearsame) { - ge->rtg = 0; - } else { - ge->rtg = 1; - } - } - } -} - -/* various definition for the processing of outlines */ - -/* maximal average quadratic distance from the original curve - * (in dots) to consider the joined curve good - */ -#define CVEPS 1.5 -#define CVEPS2 (CVEPS*CVEPS) -/* squared sinus of the maximal angle that we consider a smooth joint */ -#define SMOOTHSIN2 0.25 /* 0.25==sin(30 degrees)^2 */ -/* squared line length that we consider small */ -#define SMALL_LINE2 (15.*15.) -/* how many times a curve must be bigger than a line to join, squared */ -#define TIMES_LINE2 (3.*3.) - -/* - * Normalize and analyse a gentry for fforceconcise() and fill out the gex_con - * structure - */ - -static void -fanalyzege( - GENTRY *ge -) -{ - int i, ix, iy; - double avsd2, dots[3][2 /*X,Y*/]; - GEX_CON *gex; - - gex = X_CON(ge); - memset(gex, 0, sizeof *gex); - - gex->len2 = 0; - for(i=0; i<2; i++) { - avsd2 = gex->d[i] = ge->fpoints[i][2] - ge->prev->fpoints[i][2]; - gex->len2 += avsd2*avsd2; - } - gex->sin2 = fjointsin2(ge, ge->frwd); - if(ge->type == GE_CURVE) { - ge->dir = fgetcvdir(ge); - for(i=0; i<2; i++) { - dots[0][i] = ge->prev->fpoints[i][2]; - dots[1][i] = ge->fpoints[i][2]; - dots[2][i] = fcvval(ge, i, 0.5); - } - avsd2 = fdotsegdist2(dots, dots[2]); - if(avsd2 <= CVEPS2) { - gex->flags |= GEXF_FLAT; - } - } else { - ge->dir = CVDIR_FEQUAL|CVDIR_REQUAL; - gex->flags |= GEXF_FLAT; - } - if(gex->flags & GEXF_FLAT) { - if( fabs(gex->d[X]) > FEPS && fabs(gex->d[Y]) < 5. - && fabs(gex->d[Y] / gex->d[X]) < 0.2) - gex->flags |= GEXF_HOR; - else if( fabs(gex->d[Y]) > FEPS && fabs(gex->d[X]) < 5. - && fabs(gex->d[X] / gex->d[Y]) < 0.2) - gex->flags |= GEXF_VERT; - } - ix = gex->isd[X] = fsign(gex->d[X]); - iy = gex->isd[Y] = fsign(gex->d[Y]); - if(ix <= 0) { - if(iy <= 0) - gex->flags |= GEXF_QDL; - if(iy >= 0) - gex->flags |= GEXF_QUL; - if(gex->flags & GEXF_HOR) - gex->flags |= GEXF_IDQ_L; - } - if(ix >= 0) { - if(iy <= 0) - gex->flags |= GEXF_QDR; - if(iy >= 0) - gex->flags |= GEXF_QUR; - if(gex->flags & GEXF_HOR) - gex->flags |= GEXF_IDQ_R; - } - if(gex->flags & GEXF_VERT) { - if(iy <= 0) { - gex->flags |= GEXF_IDQ_U; - } else { /* supposedly there is no 0-sized entry */ - gex->flags |= GEXF_IDQ_D; - } - } -} - -/* - * Analyse a joint between this and following gentry for fforceconcise() - * and fill out the corresponding parts of the gex_con structure - * Bothe entries must be analyzed first. - */ - -static void -fanalyzejoint( - GENTRY *ge -) -{ - GENTRY *nge = ge->frwd; - GENTRY tge; - GEX_CON *gex, *ngex; - double avsd2, dots[3][2 /*X,Y*/]; - int i; - - gex = X_CON(ge); ngex = X_CON(nge); - - /* look if they can be joined honestly */ - - /* if any is flat, they should join smoothly */ - if( (gex->flags & GEXF_FLAT || ngex->flags & GEXF_FLAT) - && gex->sin2 > SMOOTHSIN2) - goto try_flatboth; - - if(ge->type == GE_LINE) { - if(nge->type == GE_LINE) { - if(gex->len2 > SMALL_LINE2 || ngex->len2 > SMALL_LINE2) - goto try_flatboth; - } else { - if(gex->len2*TIMES_LINE2 > ngex->len2) - goto try_flatboth; - } - } else if(nge->type == GE_LINE) { - if(ngex->len2*TIMES_LINE2 > gex->len2) - goto try_flatboth; - } - - /* if curve changes direction */ - if( gex->isd[X]*ngex->isd[X]<0 || gex->isd[Y]*ngex->isd[Y]<0) - goto try_idealone; - - /* if would create a zigzag */ - if( ((ge->dir&CVDIR_FRONT)-CVDIR_FEQUAL) * ((nge->dir&CVDIR_REAR)-CVDIR_REQUAL) < 0 ) - goto try_flatone; - - if( fcrossraysge(ge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JGOOD; - -try_flatone: - /* look if they can be joined by flatting out one of the entries */ - - /* at this point we know that the general direction of the - * gentries is OK - */ - - if( gex->flags & GEXF_FLAT ) { - tge = *ge; - tge.fx1 = tge.fx3; - tge.fy1 = tge.fy3; - fnormalizege(&tge); - if( fcrossraysge(&tge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JFLAT|GEXF_JFLAT1; - } - if( ngex->flags & GEXF_FLAT ) { - tge = *nge; - tge.fx2 = ge->fx3; - tge.fy2 = ge->fy3; - fnormalizege(&tge); - if( fcrossraysge(ge, &tge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JFLAT|GEXF_JFLAT2; - } - -try_idealone: - /* look if one of the entries can be brought to an idealized - * horizontal or vertical position and then joined - */ - if( gex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) { - tge = *ge; - tge.fx1 = tge.fx3; - tge.fy1 = ge->prev->fy3; /* force horizontal */ - fnormalizege(&tge); - if( fcrossraysge(&tge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID1; - } else if( gex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) { - tge = *ge; - tge.fx1 = ge->prev->fx3; /* force vertical */ - tge.fy1 = tge.fy3; - fnormalizege(&tge); - if( fcrossraysge(&tge, nge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID1; - } - if( ngex->flags & GEXF_HOR && gex->isd[X]*ngex->isd[X]>=0 ) { - tge = *nge; - tge.fx2 = ge->fx3; - tge.fy2 = nge->fy3; /* force horizontal */ - fnormalizege(&tge); - if( fcrossraysge(ge, &tge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID2; - } else if( ngex->flags & GEXF_VERT && gex->isd[Y]*ngex->isd[Y]>=0 ) { - tge = *nge; - tge.fx2 = nge->fx3; /* force vertical */ - tge.fy2 = ge->fy3; - fnormalizege(&tge); - if( fcrossraysge(ge, &tge, NULL, NULL, NULL) ) - gex->flags |= GEXF_JID|GEXF_JID2; - } - -try_flatboth: - /* look if we can change them to one line */ - if(gex->flags & GEXF_FLAT && ngex->flags & GEXF_FLAT) { - for(i=0; i<2; i++) { - dots[0][i] = ge->prev->fpoints[i][2]; - dots[1][i] = nge->fpoints[i][2]; - dots[2][i] = ge->fpoints[i][2]; - } - if( fdotsegdist2(dots, dots[2]) <= CVEPS2) - gex->flags |= GEXF_JLINE; - } -} - -/* - * Force conciseness of one contour in the glyph, - * the contour is indicated by one entry from it. - */ - -static void -fconcisecontour( - GLYPH *g, - GENTRY *startge -) -{ -/* initial maximal number of dots to be used as reference */ -#define MAXDOTS ((NREFDOTS+1)*12) - - GENTRY *ge, *pge, *nge, *ige; - GEX_CON *gex, *pgex, *ngex, *nngex; - GENTRY tpge, tnge; - int quad, qq, i, j, ndots, maxdots; - int found[2]; - int joinmask, pflag, nflag; - struct dot_dist *dots; - double avsd2, maxd2, eps2; - double apcv[4][2]; - - if(startge == 0) { - fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n", - __FILE__, __LINE__); - fprintf(stderr, "Strange contour in glyph %s\n", g->name); - dumppaths(g, NULL, NULL); - return; - } - - if(startge->type != GE_CURVE && startge->type != GE_LINE) - return; /* probably a degenerate contour */ - - if(ISDBG(FCONCISE)) - fprintf(stderr, "processing contour 0x%p of glyph %s\n", startge, g->name); - - maxdots = MAXDOTS; - dots = (struct dot_dist *)malloc(sizeof(*dots)*maxdots); - if(dots == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - ge = startge; - joinmask = GEXF_JGOOD; - while(1) { - restart: - gex = X_CON(ge); - if((gex->flags & GEXF_JMASK) > ((joinmask<<1)-1)) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "found higher flag (%x>%x) at 0x%p\n", - gex->flags & GEXF_JMASK, ((joinmask<<1)-1), ge); - joinmask <<= 1; - startge = ge; /* have to redo the pass */ - continue; - } - if(( gex->flags & joinmask )==0) - goto next; - - /* if we happen to be in the middle of a string of - * joinable entries, find its beginning - */ - if( gex->flags & (GEXF_JCVMASK^GEXF_JID) ) - quad = gex->flags & X_CON_F(ge->frwd) & GEXF_QMASK; - else if( gex->flags & GEXF_JID2 ) - quad = gex->flags & GEXF_QFROM_IDEAL(X_CON_F(ge->frwd)) & GEXF_QMASK; - else /* must be GEXF_JID1 */ - quad = GEXF_QFROM_IDEAL(gex->flags) & X_CON_F(ge->frwd) & GEXF_QMASK; - - pge = ge; - pgex = X_CON(pge->bkwd); - - if(ISDBG(FCONCISE)) - fprintf(stderr, "ge %p prev -> 0x%p ", ge, pge); - - while(pgex->flags & GEXF_JCVMASK) { - if( !(pgex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID2)) ) - qq = GEXF_QFROM_IDEAL(pgex->flags); - else - qq = pgex->flags & GEXF_QMASK; - - if(ISDBG(FCONCISE)) - fprintf(stderr, "(%x?%x)", quad, qq); - - if( !(quad & qq) ) { - if( !(X_CON_F(pge) & (GEXF_JCVMASK^GEXF_JID)) - && pgex->flags & (GEXF_JCVMASK^GEXF_JID) ) { - /* the previos entry is definitely a better match */ - if(pge == ge) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "\nprev is a better match at %p\n", pge); - startge = ge; - goto next; - } else - pge = pge->frwd; - } - break; - } - - quad &= qq; - pge = pge->bkwd; - pgex = X_CON(pge->bkwd); - if(ISDBG(FCONCISE)) - fprintf(stderr, "0x%p ", pge); - } - - /* collect as many entries for joining as possible */ - nge = ge->frwd; - ngex = X_CON(nge); - nngex = X_CON(nge->frwd); - - if(ISDBG(FCONCISE)) - fprintf(stderr, ": 0x%x\nnext -> 0x%p ", pge, nge); - - while(ngex->flags & GEXF_JCVMASK) { - if( !(ngex->flags & ((GEXF_JCVMASK^GEXF_JID)|GEXF_JID1)) ) - qq = GEXF_QFROM_IDEAL(nngex->flags); - else - qq = nngex->flags & GEXF_QMASK; - - if(ISDBG(FCONCISE)) - fprintf(stderr, "(%x?%x)", quad, qq); - if( !(quad & qq) ) { - if( !(X_CON_F(nge->bkwd) & (GEXF_JCVMASK^GEXF_JID)) - && ngex->flags & (GEXF_JCVMASK^GEXF_JID) ) { - /* the next-next entry is definitely a better match */ - if(nge == ge->frwd) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "\nnext %x is a better match than %x at %p (jmask %x)\n", - ngex->flags & GEXF_JCVMASK, gex->flags & GEXF_JCVMASK, nge, joinmask); - goto next; - } else - nge = nge->bkwd; - } - break; - } - - quad &= qq; - nge = nge->frwd; - ngex = nngex; - nngex = X_CON(nge->frwd); - if(ISDBG(FCONCISE)) - fprintf(stderr, "0x%p ", nge); - } - - if(ISDBG(FCONCISE)) - fprintf(stderr, ": 0x%x\n", nge); - - /* XXX add splitting of last entries if neccessary */ - - /* make sure that all the reference dots are valid */ - for(ige = pge; ige != nge->frwd; ige = ige->frwd) { - nngex = X_CON(ige); - if( !(nngex->flags & GEXF_VDOTS) ) { - fsampledots(ige, nngex->dots, NREFDOTS); - nngex->flags |= GEXF_VDOTS; - } - } - - /* do the actual joining */ - while(1) { - pgex = X_CON(pge); - ngex = X_CON(nge->bkwd); - /* now the segments to be joined are pge...nge */ - - ndots = 0; - for(ige = pge; ige != nge->frwd; ige = ige->frwd) { - if(maxdots < ndots+(NREFDOTS+1)) { - maxdots += MAXDOTS; - dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots); - if(dots == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - nngex = X_CON(ige); - for(i=0; idots[i][j]; - ndots++; - } - for(j=0; j<2; j++) - dots[ndots].p[j] = ige->fpoints[j][2]; - ndots++; - } - ndots--; /* the last point is not interesting */ - - tpge = *pge; - pflag = pgex->flags; - if(pflag & (GEXF_JGOOD|GEXF_JFLAT2|GEXF_JID2)) { - /* nothing */ - } else if(pflag & GEXF_JFLAT) { - tpge.fx1 = tpge.fx3; - tpge.fy1 = tpge.fy3; - } else if(pflag & GEXF_JID) { - if(pflag & GEXF_HOR) - tpge.fy1 = tpge.bkwd->fy3; - else - tpge.fx1 = tpge.bkwd->fx3; - } - - tnge = *nge; - nflag = ngex->flags; - if(nflag & (GEXF_JGOOD|GEXF_JFLAT1|GEXF_JID) - && !(nflag & GEXF_JID2)) { - /* nothing */ - } else if(nflag & GEXF_JFLAT) { - tnge.fx2 = tnge.bkwd->fx3; - tnge.fy2 = tnge.bkwd->fy3; - } else if(nflag & GEXF_JID) { - if(X_CON_F(nge) & GEXF_HOR) - tnge.fy2 = tnge.fy3; - else - tnge.fx2 = tnge.fx3; - } - - fnormalizege(&tpge); - fnormalizege(&tnge); - if( fcrossraysge(&tpge, &tnge, NULL, NULL, &apcv[1]) ) { - apcv[0][X] = tpge.bkwd->fx3; - apcv[0][Y] = tpge.bkwd->fy3; - /* apcv[1] and apcv[2] were filled by fcrossraysge() */ - apcv[3][X] = tnge.fx3; - apcv[3][Y] = tnge.fy3; - - /* calculate the precision depending on the smaller dimension of the curve */ - maxd2 = apcv[3][X]-apcv[0][X]; - maxd2 *= maxd2; - eps2 = apcv[3][Y]-apcv[0][Y]; - eps2 *= eps2; - if(maxd2 < eps2) - eps2 = maxd2; - eps2 *= (CVEPS2*4.) / (400.*400.); - if(eps2 < CVEPS2) - eps2 = CVEPS2; - else if(eps2 > CVEPS2*4.) - eps2 = CVEPS2*4.; - - fapproxcurve(apcv, dots, ndots); - - avsd2 = fdotcurvdist2(apcv, dots, ndots, &maxd2); - if(ISDBG(FCONCISE)) - fprintf(stderr, "avsd = %g, maxd = %g, ", sqrt(avsd2), sqrt(maxd2)); - if(avsd2 <= eps2 && maxd2 <= eps2*2.) { - /* we've guessed a curve that is close enough */ - ggoodcv++; ggoodcvdots += ndots; - - if(ISDBG(FCONCISE)) { - fprintf(stderr, "in %s joined %p-%p to ", g->name, pge, nge); - for(i=0; i<4; i++) { - fprintf(stderr, " (%g, %g)", apcv[i][X], apcv[i][Y]); - } - fprintf(stderr, " from\n"); - dumppaths(g, pge, nge); - } - for(i=0; i<3; i++) { - pge->fxn[i] = apcv[i+1][X]; - pge->fyn[i] = apcv[i+1][Y]; - } - pge->type = GE_CURVE; - ge = pge; - for(ige = pge->frwd; ; ige = pge->frwd) { - if(ige == pge) { - fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n", - __FILE__, __LINE__); - free(dots); - return; - } - if(startge == ige) - startge = pge; - free(ige->ext); - freethisge(ige); - if(ige == nge) - break; - } - fnormalizege(ge); - if(ISDBG(FCONCISE)) { - fprintf(stderr, "normalized "); - for(i=0; i<3; i++) { - fprintf(stderr, " (%g, %g)", ge->fpoints[X][i], ge->fpoints[Y][i]); - } - fprintf(stderr, "\n"); - } - fanalyzege(ge); - fanalyzejoint(ge); - fanalyzege(ge->bkwd); - fanalyzejoint(ge->bkwd); - - /* the results of this join will have to be reconsidered */ - startge = ge = ge->frwd; - goto restart; - } else { - gbadcv++; gbadcvdots += ndots; - } - } - - /* if we're down to 2 entries then the join has failed */ - if(pge->frwd == nge) { - pgex->flags &= ~joinmask; - if(ISDBG(FCONCISE)) - fprintf(stderr, "no match\n"); - goto next; - } - - /* reduce the number of entries by dropping one at some end, - * should never drop the original ge from the range - */ - - if(nge->bkwd == ge - || pge != ge && (pgex->flags & GEXF_JCVMASK) <= (ngex->flags & GEXF_JCVMASK) ) { - pge = pge->frwd; - } else { - nge = nge->bkwd; - } - if(ISDBG(FCONCISE)) - fprintf(stderr, "next try: %p to %p\n", pge, nge); - } - -next: - ge = ge->frwd; - if(ge == startge) { - joinmask = (joinmask >> 1) & GEXF_JCVMASK; - if(joinmask == 0) - break; - } - } - - /* join flat segments into lines */ - /* here ge==startge */ - while(1) { - gex = X_CON(ge); - if( !(gex->flags & GEXF_JLINE) ) - goto next2; - - ndots = 0; - dots[ndots].p[X] = ge->fx3; - dots[ndots].p[Y] = ge->fy3; - ndots++; - - pge = ge->bkwd; - nge = ge->frwd; - - if(ISDBG(FCONCISE)) - fprintf(stderr, "joining LINE from %p-%p\n", ge, nge); - - while(pge!=nge) { - pgex = X_CON(pge); - ngex = X_CON(nge); - if(ISDBG(FCONCISE)) - fprintf(stderr, "(p=%p/%x n=0x%x/%x) ", pge, pgex->flags & GEXF_JLINE, - nge, ngex->flags & GEXF_JLINE); - if( !((pgex->flags | ngex->flags) & GEXF_JLINE) ) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "(end p=%p n=%p) ", pge, nge); - break; - } - - if(maxdots < ndots+2) { - maxdots += MAXDOTS; - dots = (struct dot_dist *)realloc((void *)dots, sizeof(*dots)*maxdots); - if(dots == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - } - if( pgex->flags & GEXF_JLINE ) { - for(i=0; i<2; i++) { - apcv[0][i] = pge->bkwd->fpoints[i][2]; - apcv[1][i] = nge->fpoints[i][2]; - dots[ndots].p[i] = pge->fpoints[i][2]; - } - ndots++; - for(i=0; i CVEPS2) - break; - } - if(iflags &= ~GEXF_JLINE; - } else { - pge = pge->bkwd; - if(pge == nge) { - if(ISDBG(FCONCISE)) - fprintf(stderr, "intersected at prev %p ", pge); - break; /* oops, tried to self-intersect */ - } - } - } else if(ISDBG(FCONCISE)) - fprintf(stderr, "(p=%p) ", pge); - - if( ngex->flags & GEXF_JLINE ) { - for(i=0; i<2; i++) { - apcv[0][i] = pge->fpoints[i][2]; /* pge points before the 1st segment */ - apcv[1][i] = nge->frwd->fpoints[i][2]; - dots[ndots].p[i] = nge->fpoints[i][2]; - } - ndots++; - for(i=0; i CVEPS2) - break; - } - if(ifrwd); - ndots--; - ngex->flags &= ~GEXF_JLINE; - } else { - nge = nge->frwd; - } - } else if(ISDBG(FCONCISE)) - fprintf(stderr, "(n=%p) ", nge); - } - - pge = pge->frwd; /* now the limits are pge...nge inclusive */ - if(pge == nge) /* a deeply perversive contour */ - break; - - if(ISDBG(FCONCISE)) { - fprintf(stderr, "\nin %s joined LINE %p-%p from\n", g->name, pge, nge); - dumppaths(g, pge, nge); - } - pge->type = GE_LINE; - for(i=0; i<2; i++) { - pge->fpoints[i][2] = nge->fpoints[i][2]; - } - fnormalizege(pge); - X_CON_F(pge) &= ~GEXF_JLINE; - - ge = pge; - for(ige = pge->frwd; ; ige = pge->frwd) { - if(ige == pge) { - fprintf(stderr, "WARNING: assertion in %s line %d, please report it to the ttf2pt1 project\n", - __FILE__, __LINE__); - free(dots); - return; - } - if(startge == ige) - startge = pge; - free(ige->ext); - freethisge(ige); - if(ige == nge) - break; - } -next2: - ge = ge->frwd; - if(ge == startge) - break; - } - - free(dots); -} - -/* force conciseness: substitute 2 or more curves going in the -** same quadrant with one curve -** in floating point -*/ - -void -fforceconcise( - GLYPH * g -) -{ - - GENTRY *ge, *nge, *endge, *xge; - - assertisfloat(g, "enforcing conciseness"); - - fdelsmall(g, 0.05); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - if(ISDBG(FCONCISE)) - dumppaths(g, NULL, NULL); - - /* collect more information about each gentry and their joints */ - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) - fnormalizege(ge); - - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) { - alloc_gex_con(ge); - fanalyzege(ge); - } - - /* see what we can do about joining */ - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) - fanalyzejoint(ge); - - /* now do the joining */ - for (ge = g->entries; ge != 0; ge = ge->next) - if(ge->type == GE_MOVE) - fconcisecontour(g, ge->next); - - for (ge = g->entries; ge != 0; ge = ge->next) - if (ge->type == GE_CURVE || ge->type == GE_LINE) - free(ge->ext); -} - -void -print_glyph( - int glyphno -) -{ - GLYPH *g; - GENTRY *ge; - int x = 0, y = 0; - int i; - int grp, lastgrp= -1; - - if(ISDBG(FCONCISE) && glyphno == 0) { - fprintf(stderr, "Guessed curves: bad %d/%d good %d/%d\n", - gbadcv, gbadcvdots, ggoodcv, ggoodcvdots); - } - - g = &glyph_list[glyphno]; - - fprintf(pfa_file, "/%s { \n", g->name); - - /* consider widths >MAXLEGALWIDTH as bugs */ - if( g->scaledwidth <= MAXLEGALWIDTH ) { - fprintf(pfa_file, "0 %d hsbw\n", g->scaledwidth); - } else { - fprintf(pfa_file, "0 1000 hsbw\n"); - WARNING_2 fprintf(stderr, "glyph %s: width %d seems to be buggy, set to 1000\n", - g->name, g->scaledwidth); - } - -#if 0 - fprintf(pfa_file, "%% contours: "); - for (i = 0; i < g->ncontours; i++) - fprintf(pfa_file, "%s(%d,%d) ", (g->contours[i].direction == DIR_OUTER ? "out" : "in"), - g->contours[i].xofmin, g->contours[i].ymin); - fprintf(pfa_file, "\n"); - - if (g->rymin < 5000) - fprintf(pfa_file, "%d lower%s\n", g->rymin, (g->flatymin ? "flat" : "curve")); - if (g->rymax > -5000) - fprintf(pfa_file, "%d upper%s\n", g->rymax, (g->flatymax ? "flat" : "curve")); -#endif - - if (g->hstems) - for (i = 0; i < g->nhs; i += 2) { - if (g->hstems[i].flags & ST_3) { - fprintf(pfa_file, "%d %d %d %d %d %d hstem3\n", - g->hstems[i].value, - g->hstems[i + 1].value - g->hstems[i].value, - g->hstems[i + 2].value, - g->hstems[i + 3].value - g->hstems[i + 2].value, - g->hstems[i + 4].value, - g->hstems[i + 5].value - g->hstems[i + 4].value - ); - i += 4; - } else { - fprintf(pfa_file, "%d %d hstem\n", g->hstems[i].value, - g->hstems[i + 1].value - g->hstems[i].value); - } - } - - if (g->vstems) - for (i = 0; i < g->nvs; i += 2) { - if (g->vstems[i].flags & ST_3) { - fprintf(pfa_file, "%d %d %d %d %d %d vstem3\n", - g->vstems[i].value, - g->vstems[i + 1].value - g->vstems[i].value, - g->vstems[i + 2].value, - g->vstems[i + 3].value - g->vstems[i + 2].value, - g->vstems[i + 4].value, - g->vstems[i + 5].value - g->vstems[i + 4].value - ); - i += 4; - } else { - fprintf(pfa_file, "%d %d vstem\n", g->vstems[i].value, - g->vstems[i + 1].value - g->vstems[i].value); - } - } - - for (ge = g->entries; ge != 0; ge = ge->next) { - if(g->nsg>0) { - grp=ge->stemid; - if(grp >= 0 && grp != lastgrp) { - fprintf(pfa_file, "%d 4 callsubr\n", grp+g->firstsubr); - lastgrp=grp; - } - } - - switch (ge->type) { - case GE_MOVE: - if (absolute) - fprintf(pfa_file, "%d %d amoveto\n", ge->ix3, ge->iy3); - else - rmoveto(ge->ix3 - x, ge->iy3 - y); - if (0) - fprintf(stderr, "Glyph %s: print moveto(%d, %d)\n", - g->name, ge->ix3, ge->iy3); - x = ge->ix3; - y = ge->iy3; - break; - case GE_LINE: - if (absolute) - fprintf(pfa_file, "%d %d alineto\n", ge->ix3, ge->iy3); - else - rlineto(ge->ix3 - x, ge->iy3 - y); - x = ge->ix3; - y = ge->iy3; - break; - case GE_CURVE: - if (absolute) - fprintf(pfa_file, "%d %d %d %d %d %d arcurveto\n", - ge->ix1, ge->iy1, ge->ix2, ge->iy2, ge->ix3, ge->iy3); - else - rrcurveto(ge->ix1 - x, ge->iy1 - y, - ge->ix2 - ge->ix1, ge->iy2 - ge->iy1, - ge->ix3 - ge->ix2, ge->iy3 - ge->iy2); - x = ge->ix3; - y = ge->iy3; - break; - case GE_PATH: - closepath(); - break; - default: - WARNING_1 fprintf(stderr, "**** Glyph %s: unknown entry type '%c'\n", - g->name, ge->type); - break; - } - } - - fprintf(pfa_file, "endchar } ND\n"); -} - -/* print the subroutines for this glyph, returns the number of them */ -int -print_glyph_subs( - int glyphno, - int startid /* start numbering subroutines from this id */ -) -{ - GLYPH *g; - int i, grp; - - g = &glyph_list[glyphno]; - - if(!hints || !subhints || g->nsg<1) - return 0; - - g->firstsubr=startid; - -#if 0 - fprintf(pfa_file, "%% %s %d\n", g->name, g->nsg); -#endif - for(grp=0; grpnsg; grp++) { - fprintf(pfa_file, "dup %d {\n", startid++); - for(i= (grp==0)? 0 : g->nsbs[grp-1]; insbs[grp]; i++) - fprintf(pfa_file, "\t%d %d %cstem\n", g->sbstems[i].low, - g->sbstems[i].high-g->sbstems[i].low, - g->sbstems[i].isvert ? 'v' : 'h'); - fprintf(pfa_file, "\treturn\n\t} NP\n"); - } - - return g->nsg; -} - -void -print_glyph_metrics( - int code, - int glyphno -) -{ - GLYPH *g; - - g = &glyph_list[glyphno]; - - if(transform) - fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n", - code, g->scaledwidth, g->name, - iscale(g->xMin), iscale(g->yMin), iscale(g->xMax), iscale(g->yMax)); - else - fprintf(afm_file, "C %d ; WX %d ; N %s ; B %d %d %d %d ;\n", - code, g->scaledwidth, g->name, - g->xMin, g->yMin, g->xMax, g->yMax); -} - -/* - SB: - An important note about the BlueValues. - - The Adobe documentation says that the maximal width of a Blue zone - is connected to the value of BlueScale, which is by default 0.039625. - The BlueScale value defines, at which point size the overshoot - suppression be disabled. - - The formula for it that is given in the manual is: - - BlueScale=point_size/240, for a 300dpi device - - that makes us wonder what is this 240 standing for. Incidentally - 240=72*1000/300, where 72 is the relation between inches and points, - 1000 is the size of the glyph matrix, and 300dpi is the resolution of - the output device. Knowing that we can recalculate the formula for - the font size in pixels rather than points: - - BlueScale=pixel_size/1000 - - That looks a lot simpler than the original formula, does not it ? - And the limitation about the maximal width of zone also looks - a lot simpler after the transformation: - - max_width < 1000/pixel_size - - that ensures that even at the maximal pixel size when the overshoot - suppression is disabled the zone width will be less than one pixel. - This is important, failure to comply to this limit will result in - really ugly fonts (been there, done that). But knowing the formula - for the pixel width, we see that in fact we can use the maximal width - of 24, not 23 as specified in the manual. - -*/ - -#define MAXBLUEWIDTH (24) - -/* - * Find the indexes of the most frequent values - * in the hystogram, sort them in ascending order, and save which one - * was the best one (if asked). - * Returns the number of values found (may be less than maximal because - * we ignore the zero values) - */ - -#define MAXHYST (2000) /* size of the hystogram */ -#define HYSTBASE 500 - -static int -besthyst( - int *hyst, /* the hystogram */ - int base, /* the base point of the hystogram */ - int *best, /* the array for indexes of best values */ - int nbest, /* its allocated size */ - int width, /* minimal difference between indexes */ - int *bestindp /* returned top point */ -) -{ - unsigned char hused[MAXHYST / 8 + 1]; - int i, max, j, w, last = 0; - int nf = 0; - - width--; - - memset(hused, 0 , sizeof hused); - - max = 1; - for (i = 0; i < nbest && max != 0; i++) { - best[i] = 0; - max = 0; - for (j = 1; j < MAXHYST - 1; j++) { - w = hyst[j]; - - if (w > max && (hused[j>>3] & (1 << (j & 0x07))) == 0) { - best[i] = j; - max = w; - } - } - if (max != 0) { - if (max < last/2) { - /* do not pick the too low values */ - break; - } - for (j = best[i] - width; j <= best[i] + width; j++) { - if (j >= 0 && j < MAXHYST) - hused[j >> 3] |= (1 << (j & 0x07)); - } - last = max; - best[i] -= base; - nf = i + 1; - } - } - - if (bestindp) - *bestindp = best[0]; - - /* sort the indexes in ascending order */ - for (i = 0; i < nf; i++) { - for (j = i + 1; j < nf; j++) - if (best[j] < best[i]) { - w = best[i]; - best[i] = best[j]; - best[j] = w; - } - } - - return nf; -} - -/* - * Find the next best Blue zone in the hystogram. - * Return the weight of the found zone. - */ - -static int -bestblue( - short *zhyst, /* the zones hystogram */ - short *physt, /* the points hystogram */ - short *ozhyst, /* the other zones hystogram */ - int *bluetab /* where to put the found zone */ -) -{ - int i, j, w, max, ind, first, last; - - /* find the highest point in the zones hystogram */ - /* if we have a plateau, take its center */ - /* if we have multiple peaks, take the first one */ - - max = -1; - first = last = -10; - for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) { - w = zhyst[i]; - if (w > max) { - first = last = i; - max = w; - } else if (w == max) { - if (last == i - 1) - last = i; - } - } - ind = (first + last) / 2; - - if (max == 0) /* no zones left */ - return 0; - - /* now we reuse `first' and `last' as inclusive borders of the zone */ - first = ind; - last = ind + (MAXBLUEWIDTH - 1); - - /* our maximal width is far too big, so we try to make it narrower */ - w = max; - j = (w & 1); /* a pseudo-random bit */ - while (1) { - while (physt[first] == 0) - first++; - while (physt[last] == 0) - last--; - if (last - first < (MAXBLUEWIDTH * 2 / 3) || (max - w) * 10 > max) - break; - - if (physt[first] < physt[last] - || physt[first] == physt[last] && j) { - if (physt[first] * 20 > w) /* if weight is >5%, - * stop */ - break; - w -= physt[first]; - first++; - j = 0; - } else { - if (physt[last] * 20 > w) /* if weight is >5%, - * stop */ - break; - w -= physt[last]; - last--; - j = 1; - } - } - - /* save our zone */ - bluetab[0] = first - HYSTBASE; - bluetab[1] = last - HYSTBASE; - - /* invalidate all the zones overlapping with this one */ - /* the constant of 2 is determined by the default value of BlueFuzz */ - for (i = first - (MAXBLUEWIDTH - 1) - 2; i <= last + 2; i++) - if (i >= 0 && i < MAXHYST) { - zhyst[i] = 0; - ozhyst[i] = 0; - } - return w; -} - -/* - * Try to find the Blue Values, bounding box and italic angle - */ - -void -findblues(void) -{ - /* hystograms for upper and lower zones */ - short hystl[MAXHYST]; - short hystu[MAXHYST]; - short zuhyst[MAXHYST]; - short zlhyst[MAXHYST]; - int nchars; - int i, j, k, w, max; - GENTRY *ge; - GLYPH *g; - double ang; - - /* find the lowest and highest points of glyphs */ - /* and by the way build the values for FontBBox */ - /* and build the hystogram for the ItalicAngle */ - - /* re-use hystl for the hystogram of italic angle */ - - bbox[0] = bbox[1] = 5000; - bbox[2] = bbox[3] = -5000; - - for (i = 0; i < MAXHYST; i++) - hystl[i] = 0; - - nchars = 0; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if (g->flags & GF_USED) { - nchars++; - - g->rymin = 5000; - g->rymax = -5000; - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_LINE) { - - j = ge->iy3 - ge->prev->iy3; - k = ge->ix3 - ge->prev->ix3; - if (j > 0) - ang = atan2(-k, j) * 180.0 / M_PI; - else - ang = atan2(k, -j) * 180.0 / M_PI; - - k /= 100; - j /= 100; - if (ang > -45.0 && ang < 45.0) { - /* - * be careful to not overflow - * the counter - */ - hystl[HYSTBASE + (int) (ang * 10.0)] += (k * k + j * j) / 4; - } - if (ge->iy3 == ge->prev->iy3) { - if (ge->iy3 <= g->rymin) { - g->rymin = ge->iy3; - g->flatymin = 1; - } - if (ge->iy3 >= g->rymax) { - g->rymax = ge->iy3; - g->flatymax = 1; - } - } else { - if (ge->iy3 < g->rymin) { - g->rymin = ge->iy3; - g->flatymin = 0; - } - if (ge->iy3 > g->rymax) { - g->rymax = ge->iy3; - g->flatymax = 0; - } - } - } else if (ge->type == GE_CURVE) { - if (ge->iy3 < g->rymin) { - g->rymin = ge->iy3; - g->flatymin = 0; - } - if (ge->iy3 > g->rymax) { - g->rymax = ge->iy3; - g->flatymax = 0; - } - } - if (ge->type == GE_LINE || ge->type == GE_CURVE) { - if (ge->ix3 < bbox[0]) - bbox[0] = ge->ix3; - if (ge->ix3 > bbox[2]) - bbox[2] = ge->ix3; - if (ge->iy3 < bbox[1]) - bbox[1] = ge->iy3; - if (ge->iy3 > bbox[3]) - bbox[3] = ge->iy3; - } - } - } - } - - /* get the most popular angle */ - max = 0; - w = 0; - for (i = 0; i < MAXHYST; i++) { - if (hystl[i] > w) { - w = hystl[i]; - max = i; - } - } - ang = (double) (max - HYSTBASE) / 10.0; - WARNING_2 fprintf(stderr, "Guessed italic angle: %f\n", ang); - if (italic_angle == 0.0) - italic_angle = ang; - - /* build the hystogram of the lower points */ - for (i = 0; i < MAXHYST; i++) - hystl[i] = 0; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if ((g->flags & GF_USED) - && g->rymin + HYSTBASE >= 0 && g->rymin < MAXHYST - HYSTBASE) { - hystl[g->rymin + HYSTBASE]++; - } - } - - /* build the hystogram of the upper points */ - for (i = 0; i < MAXHYST; i++) - hystu[i] = 0; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if ((g->flags & GF_USED) - && g->rymax + HYSTBASE >= 0 && g->rymax < MAXHYST - HYSTBASE) { - hystu[g->rymax + HYSTBASE]++; - } - } - - /* build the hystogram of all the possible lower zones with max width */ - for (i = 0; i < MAXHYST; i++) - zlhyst[i] = 0; - - for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) { - for (j = 0; j < MAXBLUEWIDTH; j++) - zlhyst[i] += hystl[i + j]; - } - - /* build the hystogram of all the possible upper zones with max width */ - for (i = 0; i < MAXHYST; i++) - zuhyst[i] = 0; - - for (i = 0; i <= MAXHYST - MAXBLUEWIDTH; i++) { - for (j = 0; j < MAXBLUEWIDTH; j++) - zuhyst[i] += hystu[i + j]; - } - - /* find the baseline */ - w = bestblue(zlhyst, hystl, zuhyst, &bluevalues[0]); - if (0) - fprintf(stderr, "BaselineBlue zone %d%% %d...%d\n", w * 100 / nchars, - bluevalues[0], bluevalues[1]); - - if (w == 0) /* no baseline, something weird */ - return; - - /* find the upper zones */ - for (nblues = 2; nblues < 14; nblues += 2) { - w = bestblue(zuhyst, hystu, zlhyst, &bluevalues[nblues]); - - if (0) - fprintf(stderr, "Blue zone %d%% %d...%d\n", w * 100 / nchars, - bluevalues[nblues], bluevalues[nblues+1]); - - if (w * 20 < nchars) - break; /* don't save this zone */ - } - - /* find the lower zones */ - for (notherb = 0; notherb < 10; notherb += 2) { - w = bestblue(zlhyst, hystl, zuhyst, &otherblues[notherb]); - - if (0) - fprintf(stderr, "OtherBlue zone %d%% %d...%d\n", w * 100 / nchars, - otherblues[notherb], otherblues[notherb+1]); - - - if (w * 20 < nchars) - break; /* don't save this zone */ - } - -} - -/* - * Find the actual width of the glyph and modify the - * description to reflect it. Not guaranteed to do - * any good, may make character spacing too wide. - */ - -void -docorrectwidth(void) -{ - int i; - GENTRY *ge; - GLYPH *g; - int xmin, xmax; - int maxwidth, minsp; - - /* enforce this minimal spacing, - * we limit the amount of the enforced spacing to avoid - * spacing the bold wonts too widely - */ - minsp = (stdhw>60 || stdhw<10)? 60 : stdhw; - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - g->oldwidth=g->scaledwidth; /* save the old width, will need for AFM */ - - if (correctwidth && g->flags & GF_USED) { - xmin = 5000; - xmax = -5000; - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type != GE_LINE && ge->type != GE_CURVE) - continue; - - if (ge->ix3 <= xmin) { - xmin = ge->ix3; - } - if (ge->ix3 >= xmax) { - xmax = ge->ix3; - } - } - - maxwidth=xmax+minsp; - if( g->scaledwidth < maxwidth ) { - g->scaledwidth = maxwidth; - WARNING_3 fprintf(stderr, "glyph %s: extended from %d to %d\n", - g->name, g->oldwidth, g->scaledwidth ); - } - } - } - -} - -/* - * Try to find the typical stem widths - */ - -void -stemstatistics(void) -{ -#define MINDIST 10 /* minimal distance between the widths */ - int hyst[MAXHYST+MINDIST*2]; - int best[12]; - int i, j, k, w; - int nchars; - int ns; - STEM *s; - GLYPH *g; - - /* start with typical stem width */ - - nchars=0; - - /* build the hystogram of horizontal stem widths */ - memset(hyst, 0, sizeof hyst); - - for (i = 0, g = glyph_list; i < numglyphs; i++, g++) { - if (g->flags & GF_USED) { - nchars++; - s = g->hstems; - for (j = 0; j < g->nhs; j += 2) { - if ((s[j].flags | s[j + 1].flags) & ST_END) - continue; - w = s[j + 1].value - s[j].value+1; - if(w==20) /* split stems should not be counted */ - continue; - if (w > 0 && w < MAXHYST - 1) { - /* - * handle some fuzz present in - * converted fonts - */ - hyst[w+MINDIST] += MINDIST-1; - for(k=1; kflags & GF_USED) { - s = g->vstems; - for (j = 0; j < g->nvs; j += 2) { - if ((s[j].flags | s[j + 1].flags) & ST_END) - continue; - w = s[j + 1].value - s[j].value+1; - if (w > 0 && w < MAXHYST - 1) { - /* - * handle some fuzz present in - * converted fonts - */ - hyst[w+MINDIST] += MINDIST-1; - for(k=1; knext) { - if(ge->type == GE_LINE || ge->type == GE_CURVE) { - if (ISDBG(REVERSAL)) - fprintf(stderr, "reverse path 0x%x <- 0x%x, 0x%x\n", ge, ge->prev, ge->bkwd); - - /* cut out the path itself */ - pge = ge->prev; /* GE_MOVE */ - if (pge == 0) { - fprintf(stderr, "**! No MOVE before line !!! Fatal. ****\n"); - exit(1); - } - nge = ge->bkwd->next; /* GE_PATH */ - pge->next = nge; - nge->prev = pge; - ge->bkwd->next = 0; /* mark end of chain */ - - /* remember the starting point */ - if(ge->flags & GEF_FLOAT) { - flast[0] = pge->fx3; - flast[1] = pge->fy3; - } else { - ilast[0] = pge->ix3; - ilast[1] = pge->iy3; - } - - /* then reinsert them in backwards order */ - for(cur = ge; cur != 0; cur = next ) { - next = cur->next; /* or addgeafter() will screw it up */ - if(cur->flags & GEF_FLOAT) { - for(i=0; i<2; i++) { - /* reverse the direction of path element */ - f = cur->fpoints[i][0]; - cur->fpoints[i][0] = cur->fpoints[i][1]; - cur->fpoints[i][1] = f; - f = flast[i]; - flast[i] = cur->fpoints[i][2]; - cur->fpoints[i][2] = f; - } - } else { - for(i=0; i<2; i++) { - /* reverse the direction of path element */ - n = cur->ipoints[i][0]; - cur->ipoints[i][0] = cur->ipoints[i][1]; - cur->ipoints[i][1] = n; - n = ilast[i]; - ilast[i] = cur->ipoints[i][2]; - cur->ipoints[i][2] = n; - } - } - addgeafter(pge, cur); - } - - /* restore the starting point */ - if(ge->flags & GEF_FLOAT) { - pge->fx3 = flast[0]; - pge->fy3 = flast[1]; - } else { - pge->ix3 = ilast[0]; - pge->iy3 = ilast[1]; - } - - ge = nge; - } - - } -} - -void -reversepaths( - GLYPH * g -) -{ - reversepathsfromto(g->entries, NULL); -} - -/* add a kerning pair information, scales the value */ - -void -addkernpair( - unsigned id1, - unsigned id2, - int unscval -) -{ - static unsigned char *bits = 0; - static int lastid; - GLYPH *g = &glyph_list[id1]; - int i, n; - struct kern *p; - - if(unscval == 0 || id1 >= numglyphs || id2 >= numglyphs) - return; - - if( (glyph_list[id1].flags & GF_USED)==0 - || (glyph_list[id2].flags & GF_USED)==0 ) - return; - - if(bits == 0) { - bits = calloc( BITMAP_BYTES(numglyphs), 1); - if (bits == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - lastid = id1; - } - - if(lastid != id1) { - /* refill the bitmap cache */ - memset(bits, 0,BITMAP_BYTES(numglyphs)); - p = g->kern; - for(i=g->kerncount; i>0; i--) { - n = (p++)->id; - SET_BITMAP(bits, n); - } - lastid = id1; - } - - if(IS_BITMAP(bits, id2)) - return; /* duplicate */ - - if(g->kerncount <= g->kernalloc) { - g->kernalloc += 8; - p = realloc(g->kern, sizeof(struct kern) * g->kernalloc); - if(p == 0) { - fprintf (stderr, "** realloc failed, kerning data will be incomplete\n"); - } - g->kern = p; - } - - SET_BITMAP(bits, id2); - p = &g->kern[g->kerncount]; - p->id = id2; - p->val = iscale(unscval) - (g->scaledwidth - g->oldwidth); - g->kerncount++; - kerning_pairs++; -} - -/* print out the kerning information */ - -void -print_kerning( - FILE *afm_file -) -{ - int i, j, n; - GLYPH *g; - struct kern *p; - - if( kerning_pairs == 0 ) - return; - - fprintf(afm_file, "StartKernData\n"); - fprintf(afm_file, "StartKernPairs %hd\n", kerning_pairs); - - for(i=0; iflags & GF_USED) ==0) - continue; - p = g->kern; - for(j=g->kerncount; j>0; j--, p++) { - fprintf(afm_file, "KPX %s %s %d\n", g->name, - glyph_list[ p->id ].name, p->val ); - } - } - - fprintf(afm_file, "EndKernPairs\n"); - fprintf(afm_file, "EndKernData\n"); -} - - -#if 0 - -/* -** This function is commented out because the information -** collected by it is not used anywhere else yet. Now -** it only collects the directions of contours. And the -** direction of contours gets fixed already in draw_glyf(). -** -*********************************************** -** -** Here we expect that the paths are already closed. -** We also expect that the contours do not intersect -** and that curves doesn't cross any border of quadrant. -** -** Find which contours go inside which and what is -** their proper direction. Then fix the direction -** to make it right. -** -*/ - -#define MAXCONT 1000 - -void -fixcontours( - GLYPH * g -) -{ - CONTOUR cont[MAXCONT]; - short ymax[MAXCONT]; /* the highest point */ - short xofmax[MAXCONT]; /* X-coordinate of any point - * at ymax */ - short ymin[MAXCONT]; /* the lowest point */ - short xofmin[MAXCONT]; /* X-coordinate of any point - * at ymin */ - short count[MAXCONT]; /* count of lines */ - char dir[MAXCONT]; /* in which direction they must go */ - GENTRY *start[MAXCONT], *minptr[MAXCONT], *maxptr[MAXCONT]; - int ncont; - int i; - int dx1, dy1, dx2, dy2; - GENTRY *ge, *nge; - - /* find the contours and their most upper/lower points */ - ncont = 0; - ymax[0] = -5000; - ymin[0] = 5000; - for (ge = g->entries; ge != 0; ge = ge->next) { - if (ge->type == GE_LINE || ge->type == GE_CURVE) { - if (ge->iy3 > ymax[ncont]) { - ymax[ncont] = ge->iy3; - xofmax[ncont] = ge->ix3; - maxptr[ncont] = ge; - } - if (ge->iy3 < ymin[ncont]) { - ymin[ncont] = ge->iy3; - xofmin[ncont] = ge->ix3; - minptr[ncont] = ge; - } - } - if (ge->frwd != ge->next) { - start[ncont++] = ge->frwd; - ymax[ncont] = -5000; - ymin[ncont] = 5000; - } - } - - /* determine the directions of contours */ - for (i = 0; i < ncont; i++) { - ge = minptr[i]; - nge = ge->frwd; - - if (ge->type == GE_CURVE) { - dx1 = ge->ix3 - ge->ix2; - dy1 = ge->iy3 - ge->iy2; - - if (dx1 == 0 && dy1 == 0) { /* a pathological case */ - dx1 = ge->ix3 - ge->ix1; - dy1 = ge->iy3 - ge->iy1; - } - if (dx1 == 0 && dy1 == 0) { /* a more pathological - * case */ - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - } - } else { - dx1 = ge->ix3 - ge->prev->ix3; - dy1 = ge->iy3 - ge->prev->iy3; - } - if (nge->type == GE_CURVE) { - dx2 = ge->ix3 - nge->ix1; - dy2 = ge->iy3 - nge->iy1; - if (dx1 == 0 && dy1 == 0) { /* a pathological case */ - dx2 = ge->ix3 - nge->ix2; - dy2 = ge->iy3 - nge->iy2; - } - if (dx1 == 0 && dy1 == 0) { /* a more pathological - * case */ - dx2 = ge->ix3 - nge->ix3; - dy2 = ge->iy3 - nge->iy3; - } - } else { - dx2 = ge->ix3 - nge->ix3; - dy2 = ge->iy3 - nge->iy3; - } - - /* compare angles */ - cont[i].direction = DIR_INNER; - if (dy1 == 0) { - if (dx1 < 0) - cont[i].direction = DIR_OUTER; - } else if (dy2 == 0) { - if (dx2 > 0) - cont[i].direction = DIR_OUTER; - } else if (dx2 * dy1 < dx1 * dy2) - cont[i].direction = DIR_OUTER; - - cont[i].ymin = ymin[i]; - cont[i].xofmin = xofmin[i]; - } - - /* save the information that may be needed further */ - g->ncontours = ncont; - if (ncont > 0) { - g->contours = malloc(sizeof(CONTOUR) * ncont); - if (g->contours == 0) { - fprintf(stderr, "***** Memory allocation error *****\n"); - exit(255); - } - memcpy(g->contours, cont, sizeof(CONTOUR) * ncont); - } -} - -#endif - -/* - * - */ - diff --git a/pdf2swf/ttf2pt1/pt1.h b/pdf2swf/ttf2pt1/pt1.h deleted file mode 100644 index 4f65f88..0000000 --- a/pdf2swf/ttf2pt1/pt1.h +++ /dev/null @@ -1,257 +0,0 @@ -/* - * see COPYRIGHT - */ - - -/* glyph entry, one drawing command */ -typedef struct gentry { - /* this list links all GENTRYs of a GLYPH sequentially */ - struct gentry *next; /* double linked list */ - struct gentry *prev; - - /* this list links all GENTRYs of one contour - - * of types GE_LINE and GE_CURVE only - * bkwd is also reused: in the very first entry (normally - * of type GE_MOVE) it points to g->entries - */ - struct gentry *cntr[2]; /* double-linked circular list */ -/* convenience handles */ -#define bkwd cntr[0] -#define frwd cntr[1] - - /* various extended structures used at some stage of transformation */ - void *ext; - - union { - struct { - int val[2][3]; /* integer values */ - } i; - struct { - double val[2][3]; /* floating values */ - } f; - } points; /* absolute values, NOT deltas */ -/* convenience handles */ -#define ipoints points.i.val -#define fpoints points.f.val -#define ixn ipoints[0] -#define iyn ipoints[1] -#define fxn fpoints[0] -#define fyn fpoints[1] -#define ix1 ixn[0] -#define ix2 ixn[1] -#define ix3 ixn[2] -#define iy1 iyn[0] -#define iy2 iyn[1] -#define iy3 iyn[2] -#define fx1 fxn[0] -#define fx2 fxn[1] -#define fx3 fxn[2] -#define fy1 fyn[0] -#define fy2 fyn[1] -#define fy3 fyn[2] - - char flags; -#define GEF_FLOAT 0x02 /* entry contains floating point data */ -#define GEF_LINE 0x04 /* entry looks like a line even if it's a curve */ - - unsigned char dir; /* used to temporarily store the values for - * the directions of the ends of curves */ -/* front end */ -#define CVDIR_FUP 0x02 /* goes over the line connecting the ends */ -#define CVDIR_FEQUAL 0x01 /* coincides with the line connecting the - * ends */ -#define CVDIR_FDOWN 0x00 /* goes under the line connecting the ends */ -#define CVDIR_FRONT 0x0F /* mask of all front directions */ -/* rear end */ -#define CVDIR_RSAME 0x30 /* is the same as for the front end */ -#define CVDIR_RUP 0x20 /* goes over the line connecting the ends */ -#define CVDIR_REQUAL 0x10 /* coincides with the line connecting the - * ends */ -#define CVDIR_RDOWN 0x00 /* goes under the line connecting the ends */ -#define CVDIR_REAR 0xF0 /* mask of all rear directions */ - - signed char stemid; /* connection to the substituted stem group */ - char type; -#define GE_HSBW 'B' -#define GE_MOVE 'M' -#define GE_LINE 'L' -#define GE_CURVE 'C' -#define GE_PATH 'P' - - /* indexes of the points to be used for calculation of the tangents */ - signed char ftg; /* front tangent */ - signed char rtg; /* rear tangent, -1 means "idx 2 of the previous entry" */ -} GENTRY; - -/* stem structure, describes one [hv]stem */ -/* acually, it describes one border of a stem */ -/* the whole stem is a pair of these structures */ - -typedef struct stem { - short value; /* value of X or Y coordinate */ - short origin; /* point of origin for curve stems */ - GENTRY *ge; /* entry that has (value, origin) as its first dot */ - /* also for all the stems the couple (value, origin) - * is used to determine whether a stem is relevant for a - * line, it's considered revelant if this tuple is - * equal to any of the ends of the line. - * ge is also used to resolve ambiguity if there is more than - * one line going through certain pointi, it is used to - * distinguish these lines. - */ - - short from, to; /* values of other coordinate between - * which this stem is valid */ - - short flags; - /* ordering of ST_END, ST_FLAT, ST_ZONE is IMPORTANT for sorting */ -#define ST_END 0x01 /* end of line, lowest priority */ -#define ST_FLAT 0x02 /* stem is defined by a flat line, not a - * curve */ -#define ST_ZONE 0x04 /* pseudo-stem, the limit of a blue zone */ -#define ST_UP 0x08 /* the black area is to up or right from - * value */ -#define ST_3 0x20 /* first stem of [hv]stem3 */ -#define ST_BLUE 0x40 /* stem is in blue zone */ -#define ST_TOPZONE 0x80 /* 1 - top zone, 0 - bottom zone */ -#define ST_VERT 0x100 /* vertical stem (used in substitutions) */ -} STEM; - -#define MAX_STEMS 2000 /* we can't have more stems than path - * elements (or hope so) */ -#define NSTEMGRP 50 /* maximal number of the substituted stem groups */ - -/* structure for economical representation of the - * substituted stems - */ - -typedef struct stembounds { - short low; /* low bound */ - short high; /* high bound */ - char isvert; /* 1 - vertical, 0 - horizontal */ - char already; /* temp. flag: is aleready included */ -} STEMBOUNDS; - -struct kern { - unsigned id; /* ID of the second glyph */ - int val; /* kerning value */ -}; - -typedef struct contour { - short ymin, xofmin; - short inside; /* inside which contour */ - char direction; -#define DIR_OUTER 1 -#define DIR_INNER 0 -} CONTOUR; - -typedef struct glyph { - int char_no;/* Encoding of glyph */ - int orig_code;/* code of glyph in the font's original encoding */ - char *name; /* Postscript name of glyph */ - int xMin, yMin, xMax, yMax; /* values from TTF dictionary */ - int lsb; /* left sidebearing */ - int ttf_pathlen; /* total length of TTF paths */ - short width; - short flags; -#define GF_USED 0x0001 /* whether is this glyph used in T1 font */ -#define GF_FLOAT 0x0002 /* thys glyph contains floating point entries */ - - GENTRY *entries;/* doube linked list of entries */ - GENTRY *lastentry; /* the last inserted entry */ - GENTRY *path; /* beggining of the last path */ - int oldwidth; /* actually also scaled */ - int scaledwidth; -#define MAXLEGALWIDTH 10000 - - struct kern *kern; /* kerning data */ - int kerncount; /* number of kerning pairs */ - int kernalloc; /* for how many pairs we have space */ - - STEM *hstems; /* global horiz. and vert. stems */ - STEM *vstems; - int nhs, nvs; /* numbers of stems */ - - STEMBOUNDS *sbstems; /* substituted stems for all the groups */ - short *nsbs; /* indexes of the group ends in the common array */ - int nsg; /* actual number of the stem groups */ - int firstsubr; /* first substistuted stems subroutine number */ - - CONTOUR *contours; /* it is not used now */ - int ncontours; - - int rymin, rymax; /* real values */ - /* do we have flat surfaces on top/bottom */ - char flatymin, flatymax; - -} GLYPH; - -/* description of a dot for calculation of its distance to a curve */ - -struct dot_dist { - double p[2 /*X,Y*/]; /* coordinates of a dot */ - double dist2; /* squared distance from the dot to the curve */ - short seg; /* the closest segment of the curve */ -}; - -extern int stdhw, stdvw; /* dominant stems widths */ -extern int stemsnaph[12], stemsnapv[12]; /* most typical stem width */ - -extern int bluevalues[14]; -extern int nblues; -extern int otherblues[10]; -extern int notherb; -extern int bbox[4]; /* the FontBBox array */ -extern double italic_angle; - -extern GLYPH *glyph_list; -extern int encoding[]; /* inverse of glyph[].char_no */ - -/* prototypes of functions */ -void rmoveto( int dx, int dy); -void rlineto( int dx, int dy); -void rrcurveto( int dx1, int dy1, int dx2, int dy2, int dx3, int dy3); -void assertpath( GENTRY * from, char *file, int line, char *name); - -void fg_rmoveto( GLYPH * g, double x, double y); -void ig_rmoveto( GLYPH * g, int x, int y); -void fg_rlineto( GLYPH * g, double x, double y); -void ig_rlineto( GLYPH * g, int x, int y); -void fg_rrcurveto( GLYPH * g, double x1, double y1, - double x2, double y2, double x3, double y3); -void ig_rrcurveto( GLYPH * g, int x1, int y1, - int x2, int y2, int x3, int y3); -void g_closepath( GLYPH * g); - -void pathtoint( GLYPH *g); -void ffixquadrants( GLYPH *g); -void flattencurves( GLYPH * g); -int checkcv( GENTRY * ge, int dx, int dy); -void iclosepaths( GLYPH * g); -void fclosepaths( GLYPH * g); -void smoothjoints( GLYPH * g); -void buildstems( GLYPH * g); -void fstraighten( GLYPH * g); -void istraighten( GLYPH * g, int zigonly); -void isplitzigzags( GLYPH * g); -void fsplitzigzags( GLYPH * g); -void fforceconcise( GLYPH * g); -void iforceconcise( GLYPH * g); -void reversepathsfromto( GENTRY * from, GENTRY * to); -void reversepaths( GLYPH * g); -void dumppaths( GLYPH * g, GENTRY *start, GENTRY *end); -void print_glyph( int glyphno); -int print_glyph_subs( int glyphno, int startid); -void print_glyph_metrics( int code, int glyphno); -void findblues(void); -void stemstatistics(void); -void docorrectwidth(void); -void addkernpair( unsigned id1, unsigned id2, int unscval); -void print_kerning( FILE *afm_file); - -int fcrossrayscv( double curve[4][2], double *max1, double *max2); -int fcrossraysge( GENTRY *ge1, GENTRY *ge2, double *max1, double *max2, - double crossdot[2][2]); -double fdotsegdist2( double seg[2][2], double dot[2]); -double fdotcurvdist2( double curve[4][2], struct dot_dist *dots, int ndots, double *maxp); -void fapproxcurve( double cv[4][2], struct dot_dist *dots, int ndots); diff --git a/pdf2swf/ttf2pt1/runt1asm.c b/pdf2swf/ttf2pt1/runt1asm.c deleted file mode 100644 index 58c4cad..0000000 --- a/pdf2swf/ttf2pt1/runt1asm.c +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Wrap-around code to either compile in t1asm or call it externally - * - * Copyright (C) 2000 by Sergey Babkin - * Copyright (C) 2000 by The TTF2PT1 Project - * - * See COPYRIGHT for full license - */ - -#ifdef EXTERNAL_T1ASM - -#include -#include - -FILE *ifp; -FILE *ofp; - -int -runt1asm( - int pfbflag -) -{ - char *cmd; - int id, od; - int error; - - /* first make a copy in case some of then is already stdin/stdout */ - if(( id = dup(fileno(ifp)) )<0) { - perror("** Re-opening input file for t1asm"); - exit(1); - } - if(( od = dup(fileno(ofp)) )<0) { - perror("** Re-opening output file for t1asm"); - exit(1); - } - fclose(ifp); fclose(ofp); - close(0); - if(( dup(id) )!=0) { - perror("** Re-directing input file for t1asm"); - exit(1); - } - close(1); - if(( dup(od) )!=1) { - perror("** Re-directing output file for t1asm"); - exit(1); - } - close(id); close(od); - - if(pfbflag) - error = execlp("t1asm", "t1asm", "-b", NULL); - else - error = execlp("t1asm", "t1asm", NULL); - - perror("** Calling t1asm"); - - exit(1); -} - -#else -# include "t1asm.c" -#endif diff --git a/pdf2swf/ttf2pt1/t1asm.c b/pdf2swf/ttf2pt1/t1asm.c deleted file mode 100644 index 1fa21d7..0000000 --- a/pdf2swf/ttf2pt1/t1asm.c +++ /dev/null @@ -1,617 +0,0 @@ -/* t1asm - * - * This program `assembles' Adobe Type-1 font programs in pseudo-PostScript - * form into either PFB or PFA format. The human readable/editable input is - * charstring- and eexec-encrypted as specified in the `Adobe Type 1 Font - * Format' version 1.1 (the `black book'). There is a companion program, - * t1disasm, which `disassembles' PFB and PFA files into a pseudo-PostScript - * file. - * - * Copyright (c) 1992 by I. Lee Hetherington, all rights reserved. - * - * Permission is hereby granted to use, modify, and distribute this program - * for any purpose provided this copyright notice and the one below remain - * intact. - * - * I. Lee Hetherington (ilh@lcs.mit.edu) - * - * Revision 1.2 92/05/22 11:54:45 ilh - * Fixed bug where integers larger than 32000 could not be encoded in - * charstrings. Now integer range is correct for four-byte - * twos-complement integers: -(1<<31) <= i <= (1<<31)-1. Bug detected by - * Piet Tutelaers (rcpt@urc.tue.nl). - * - * Revision 1.1 92/05/22 11:48:46 ilh - * initial version - * - * Ported to Microsoft C/C++ Compiler and MS-DOS operating system by - * Kai-Uwe Herbing (herbing@netmbx.netmbx.de) on June 12, 1992. Code - * specific to the MS-DOS version is encapsulated with #ifdef _MSDOS - * ... #endif, where _MSDOS is an identifier, which is automatically - * defined, if you compile with the Microsoft C/C++ Compiler. - * - */ - -#ifndef lint -static char copyright[] = - "@(#) Copyright (c) 1992 by I. Lee Hetherington, all rights reserved."; -#ifdef _MSDOS -static char portnotice[] = - "@(#) Ported to MS-DOS by Kai-Uwe Herbing (herbing@netmbx.netmbx.de)."; -#endif -#endif - -/* Note: this is ANSI C. */ - -#ifdef _MSDOS - #include - #include - #include -#endif -#include -#include -#include -#include -#include - -#ifdef WIN32 -# ifdef STANDALONE -# define WINDOWS_FUNCTIONS -# include "win_missing.h" -# endif -#endif - -/* int32 must be at least 32-bit and uint16 must be at least 16-bit */ -#if INT_MAX >= 0x7FFFFFFFUL -typedef int int32; -#else -typedef long int32; -#endif -#if USHRT_MAX >= 0xFFFFUL -typedef unsigned short uint16; -#else -typedef unsigned int uint16; -#endif - -#define LINESIZE 256 - -#define MAXBLOCKLEN ((1L<<17)-6) -#define MINBLOCKLEN ((1L<<8)-6) - -#define MARKER 128 -#define ASCII 1 -#define BINARY 2 -#define DONE 3 - -typedef unsigned char byte; - -/* must be visible from outside */ -FILE *ifp; -FILE *ofp; - -/* flags */ -static int pfb = 0; -static int active = 0; -static int start_charstring = 0; -static int in_eexec = 0; - -static char line[LINESIZE]; - -/* lenIV and charstring start command */ -static int lenIV = 4; -static char cs_start[10]; - -/* for charstring buffering */ -static byte charstring_buf[65535]; -static byte *charstring_bp; - -/* for PFB block buffering */ -static byte blockbuf[MAXBLOCKLEN]; -static int32 blocklen = MAXBLOCKLEN; -static int32 blockpos = -1; -static int blocktyp = ASCII; - -/* decryption stuff */ -static uint16 er, cr; -static uint16 c1 = 52845, c2 = 22719; - -/* table of charstring commands */ -static struct command { - char *name; - int one, two; -} command_table[] = { - { "callothersubr", 12, 16 }, - { "callsubr", 10, -1 }, - { "closepath", 9, -1 }, - { "div", 12, 12 }, - { "dotsection", 12, 0 }, - { "endchar", 14, -1 }, - { "hlineto", 6, -1 }, - { "hmoveto", 22, -1 }, - { "hsbw", 13, -1 }, - { "hstem", 1, -1 }, - { "hstem3", 12, 2 }, - { "hvcurveto", 31, -1 }, - { "pop", 12, 17 }, - { "return", 11, -1 }, - { "rlineto", 5, -1 }, - { "rmoveto", 21, -1 }, - { "rrcurveto", 8, -1 }, - { "sbw", 12, 7 }, - { "seac", 12, 6 }, - { "setcurrentpoint", 12, 33 }, - { "vhcurveto", 30, -1 }, - { "vlineto", 7, -1 }, - { "vmoveto", 4, -1 }, - { "vstem", 3, -1 }, - { "vstem3", 12, 1 }, -}; /* alphabetical */ - -/* Two separate encryption functions because eexec and charstring encryption - must proceed in parallel. */ - -static byte eencrypt(byte plain) -{ - byte cipher; - - cipher = (byte) (plain ^ (er >> 8)); - er = (uint16) ((cipher + er) * c1 + c2); - return cipher; -} - -static byte cencrypt(byte plain) -{ - byte cipher; - - cipher = (byte) (plain ^ (cr >> 8)); - cr = (uint16) ((cipher + cr) * c1 + c2); - return cipher; -} - -/* This function flushes a buffered PFB block. */ - -static void output_block() -{ - int32 i; - - /* output four-byte block length */ - fputc((int) (blockpos & 0xff), ofp); - fputc((int) ((blockpos >> 8) & 0xff), ofp); - fputc((int) ((blockpos >> 16) & 0xff), ofp); - fputc((int) ((blockpos >> 24) & 0xff), ofp); - - /* output block data */ - for (i = 0; i < blockpos; i++) - fputc(blockbuf[i], ofp); - - /* mark block buffer empty and uninitialized */ - blockpos = -1; -} - -/* This function outputs a single byte. If output is in PFB format then output - is buffered through blockbuf[]. If output is in PFA format, then output - will be hexadecimal if in_eexec is set, ASCII otherwise. */ - -static void output_byte(byte b) -{ - static char *hexchar = "0123456789ABCDEF"; - static int hexcol = 0; - - if (pfb) { - /* PFB */ - if (blockpos < 0) { - fputc(MARKER, ofp); - fputc(blocktyp, ofp); - blockpos = 0; - } - blockbuf[blockpos++] = b; - if (blockpos == blocklen) - output_block(); - } else { - /* PFA */ - if (in_eexec) { - /* trim hexadecimal lines to 64 columns */ - if (hexcol >= 64) { - fputc('\n', ofp); - hexcol = 0; - } - fputc(hexchar[(b >> 4) & 0xf], ofp); - fputc(hexchar[b & 0xf], ofp); - hexcol += 2; - } else { - fputc(b, ofp); - } - } -} - -/* This function outputs a byte through possible eexec encryption. */ - -static void eexec_byte(byte b) -{ - if (in_eexec) - output_byte(eencrypt(b)); - else - output_byte(b); -} - -/* This function outputs a null-terminated string through possible eexec - encryption. */ - -static void eexec_string(char *string) -{ - while (*string) - eexec_byte((byte) *string++); -} - -/* This function gets ready for the eexec-encrypted data. If output is in - PFB format then flush current ASCII block and get ready for binary block. - We start encryption with four random (zero) bytes. */ - -static void eexec_start() -{ - eexec_string(line); - if (pfb) { - output_block(); - blocktyp = BINARY; - } - - in_eexec = 1; - er = 55665; - eexec_byte(0); - eexec_byte(0); - eexec_byte(0); - eexec_byte(0); -} - -/* This function wraps-up the eexec-encrypted data. - If output is in PFB format then this entails flushing binary block and - starting an ASCII block. */ - -static void eexec_end() -{ - int i, j; - - if (pfb) { - output_block(); - blocktyp = ASCII; - } else { - fputc('\n', ofp); - } - in_eexec = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 64; j++) - eexec_byte('0'); - eexec_byte('\n'); - } -#if 0 - eexec_string("cleartomark\n"); -#endif -} - -/* This function writes ASCII trailer. - If output is in PFB format then this entails flushing binary block and - starting an ASCII block. */ - -static void file_end() -{ - if (pfb) { - output_block(); - fputc(MARKER, ofp); - fputc(DONE, ofp); - } -} -/* This function returns an input line of characters. A line is terminated by - length (including terminating null) greater than LINESIZE, a newline \n, or - when active (looking for charstrings) by '{'. When terminated by a newline - the newline is put into line[]. When terminated by '{', the '{' is not put - into line[], and the flag start_charstring is set to 1. */ - -static void t1asm_getline() -{ - int c; - char *p = line; - int comment = 0; - - start_charstring = 0; - while (p < line + LINESIZE) { - c = fgetc(ifp); - if (c == EOF) - break; - if (c == '%') - comment = 1; - if (active && !comment && c == '{') { - start_charstring = 1; - break; - } - *p++ = (char) c; - if (c == '\n') - break; - } - *p = '\0'; -} - -/* This function is used by the binary search, bsearch(), for command names in - the command table. */ - -static int command_compare(const void *key, const void *item) -{ - return strcmp((char *) key, ((struct command *) item)->name); -} - -/* This function returns 1 if the string is an integer and 0 otherwise. */ - -static int is_integer(char *string) -{ - if (isdigit(string[0]) || string[0] == '-' || string[0] == '+') { - while (*++string && isdigit(*string)) - ; /* deliberately empty */ - if (!*string) - return 1; - } - return 0; -} - -/* This function initializes charstring encryption. Note that this is called - at the beginning of every charstring. */ - -static void charstring_start() -{ - int i; - - charstring_bp = charstring_buf; - cr = 4330; - for (i = 0; i < lenIV; i++) - *charstring_bp++ = cencrypt((byte) 0); -} - -/* This function encrypts and buffers a single byte of charstring data. */ - -static void charstring_byte(int v) -{ - byte b = (byte) (v & 0xff); - - if (charstring_bp - charstring_buf > sizeof(charstring_buf)) { - fprintf(stderr, "error: charstring_buf full (%d bytes)\n", - sizeof(charstring_buf)); - exit(1); - } - *charstring_bp++ = cencrypt(b); -} - -/* This function outputs buffered, encrypted charstring data through possible - eexec encryption. */ - -static void charstring_end() -{ - byte *bp; - - sprintf(line, "%d ", charstring_bp - charstring_buf); - eexec_string(line); - sprintf(line, "%s ", cs_start); - eexec_string(line); - for (bp = charstring_buf; bp < charstring_bp; bp++) - eexec_byte(*bp); -} - -/* This function generates the charstring representation of an integer. */ - -static void charstring_int(int num) -{ - int x; - - if (num >= -107 && num <= 107) { - charstring_byte(num + 139); - } else if (num >= 108 && num <= 1131) { - x = num - 108; - charstring_byte(x / 256 + 247); - charstring_byte(x % 256); - } else if (num >= -1131 && num <= -108) { - x = abs(num) - 108; - charstring_byte(x / 256 + 251); - charstring_byte(x % 256); - } else if (num >= (-2147483647-1) && num <= 2147483647) { - charstring_byte(255); - charstring_byte(num >> 24); - charstring_byte(num >> 16); - charstring_byte(num >> 8); - charstring_byte(num); - } else { - fprintf(stderr, - "error: cannot format the integer %d, too large\n", num); - exit(1); - } -} - -/* This function parses an entire charstring into integers and commands, - outputting bytes through the charstring buffer. */ - -static void parse_charstring() -{ - struct command *cp; - - charstring_start(); - while (fscanf(ifp, "%s", line) == 1) { - //char*bracket; - if (line[0] == '%') { - /* eat comment to end of line */ - while (fgetc(ifp) != '\n' && !feof(ifp)) - ; /* deliberately empty */ - continue; - } - if (line[0] == '}') - break; - //if(bracket=strchr(line, '}')) { - // *bracket = 0; - //} - if (is_integer(line)) { - charstring_int(atoi(line)); - } else { - cp = (struct command *) - bsearch((void *) line, (void *) command_table, - sizeof(command_table) / sizeof(struct command), - sizeof(struct command), - command_compare); - if (cp) { - charstring_byte(cp->one); - if (cp->two >= 0) - charstring_byte(cp->two); - } else { - fprintf(stderr, "error: cannot use `%s' in charstring\n",line); - exit(1); - } - } - //if(bracket) { - // //line ended with } - // break; - //} - } - charstring_end(); -} - -static void usage() -{ - fprintf(stderr, - "usage: t1asm [-b] [-l block-length] [input [output]]\n"); - fprintf(stderr, - "\n-b means output in PFB format, otherwise PFA format.\n"); - fprintf(stderr, - "The block length applies to the length of blocks in the\n"); - fprintf(stderr, - "PFB output file; the default is to use the largest possible.\n"); - exit(1); -} - -static void print_banner() -{ - static char rcs_revision[] = ""; /* removed RCS */ - static char revision[20]; - - if (sscanf(rcs_revision, "$Revision: %19s", revision) != 1) - revision[0] = '\0'; - fprintf(stderr, "This is t1asm %s.\n", revision); -} - -#ifdef STANDALONE -int main(int argc, char **argv) -{ - char *p, *q, *r; - int c; - - extern char *optarg; - extern int optind; - - ifp = stdin; - ofp = stdout; - - print_banner(); - - /* interpret command line arguments using getopt */ - while ((c = getopt(argc, argv, "bl:")) != -1) - switch (c) { - case 'b': - pfb = 1; - break; - case 'l': - blocklen = atoi(optarg); - if (blocklen < MINBLOCKLEN) { - blocklen = MINBLOCKLEN; - fprintf(stderr, - "warning: using minimum block length of %d\n", - blocklen); - } else if (blocklen > MAXBLOCKLEN) { - blocklen = MAXBLOCKLEN; - fprintf(stderr, - "warning: using maximum block length of %d\n", - blocklen); - } - break; - default: - usage(); - break; - } - if (argc - optind > 2) - usage(); - - /* possibly open input & output files */ - if (argc - optind >= 1) { - ifp = fopen(argv[optind], "rb"); - if (!ifp) { - fprintf(stderr, "error: cannot open %s for reading\n", argv[1]); - exit(1); - } - } - if (argc - optind >= 2) { - ofp = fopen(argv[optind + 1], "wb"); - if (!ofp) { - fprintf(stderr, "error: cannot open %s for writing\n", argv[2]); - exit(1); - } - } - -#else -int runt1asm(int pfbflag) -{ - char *p, *q, *r; - - /* need to reset this. (For some reason, if ttf2pt1.c fork()s, it doesn't - matter whether we reset this or not, triggering a bug which only appears - on Win32 */ - active = 0; - - pfb = pfbflag; -#endif - - #ifdef _MSDOS - /* If we are processing a PFB (binary) output */ - /* file, we must set its file mode to binary. */ - if (pfb) - _setmode(_fileno(ofp), _O_BINARY); - #endif - - /* Finally, we loop until no more input. Some special things to look for - are the `currentfile eexec' line, the beginning of the `/Subrs' - definition, the definition of `/lenIV', and the definition of the - charstring start command which has `...string currentfile...' in it. */ - - while (!feof(ifp) && !ferror(ifp)) { - t1asm_getline(); - if (strcmp(line, "currentfile eexec\n") == 0) { - eexec_start(); - continue; - } else if (strstr(line, "/Subrs") && isspace(line[6])) { - active = 1; - } else if ((p = strstr(line, "/lenIV"))) { - sscanf(p, "%*s %d", &lenIV); - } else if ((p = strstr(line, "string currentfile"))) { - /* locate the name of the charstring start command */ - *p = '\0'; /* damage line[] */ - q = strrchr(line, '/'); - if (q) { - r = cs_start; - ++q; - while (!isspace(*q) && *q != '{') - *r++ = *q++; - *r = '\0'; - } - *p = 's'; /* repair line[] */ - } - /* output line data */ - eexec_string(line); - if ((p = strstr(line, "currentfile closefile"))) { - eexec_end(); - } - if (start_charstring) { - if (!cs_start[0]) { - fprintf(stderr, "error: couldn't find charstring start command\n"); - exit(1); - } - parse_charstring(); - } - } - file_end(); - - fclose(ifp); - fclose(ofp); - - return 0; -} diff --git a/pdf2swf/ttf2pt1/ttf.c b/pdf2swf/ttf2pt1/ttf.c deleted file mode 100644 index b8db0e8..0000000 --- a/pdf2swf/ttf2pt1/ttf.c +++ /dev/null @@ -1,1480 +0,0 @@ -/* - * True Type Font to Adobe Type 1 font converter - * By Mark Heath - * Based on ttf2pfa by Andrew Weeks - * With help from Frank M. Siegert - * - * see COPYRIGHT - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifndef WIN32 -# include -# include -#else -# include "windows.h" -#endif - -#include "ttf.h" -#include "pt1.h" -#include "global.h" - -/* prototypes of call entries */ -static void openfont(char *fname, char *arg); -static void closefont( void); -static int getnglyphs ( void); -static int glnames( GLYPH *glyph_list); -static void glmetrics( GLYPH *glyph_list); -static int glenc( GLYPH *glyph_list, int *encoding, int *unimap); -static void fnmetrics( struct font_metrics *fm); -static void glpath( int glyphno, GLYPH *glyph_list); -static void kerning( GLYPH *glyph_list); - -/* globals */ - -/* front-end descriptor */ -struct frontsw ttf_sw = { - /*name*/ "ttf", - /*descr*/ "built-in TTF support", - /*suffix*/ { "ttf" }, - /*open*/ openfont, - /*close*/ closefont, - /*nglyphs*/ getnglyphs, - /*glnames*/ glnames, - /*glmetrics*/ glmetrics, - /*glenc*/ glenc, - /*fnmetrics*/ fnmetrics, - /*glpath*/ glpath, - /*kerning*/ kerning, -}; - -/* statics */ - -static FILE *ttf_file; -static int ttf_nglyphs, long_offsets; - -static TTF_DIRECTORY *directory; -static TTF_DIR_ENTRY *dir_entry; -static char *filebuffer; -static char *filebuffer_end; -static TTF_NAME *name_table = NULL; -static TTF_NAME_REC *name_record; -static TTF_HEAD *head_table = NULL; -static TTF_HHEA *hhea_table = NULL; -static TTF_KERN *kern_table = NULL; -static TTF_CMAP *cmap_table = NULL; -static LONGHORMETRIC *hmtx_table = NULL; -static TTF_GLYF *glyf_table; -static BYTE *glyf_start = NULL; -static TTF_MAXP *maxp_table = NULL; -static TTF_POST_HEAD *post_table = NULL; -static union { - USHORT *sp; - ULONG *lp; -} loca_table; -#define short_loca_table loca_table.sp -#define long_loca_table loca_table.lp - -static short cmap_n_segs; -static USHORT *cmap_seg_start, *cmap_seg_end; -static short *cmap_idDelta, *cmap_idRangeOffset; -static TTF_CMAP_FMT0 *encoding0; -static int enc_type; - -static char name_buffer[2000]; -static char *name_fields[8]; - -static int enc_found_ms, enc_found_mac; - -static char *mac_glyph_names[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", - "mu", "partialdiff", "summation", "product", - "pi", "integral", "ordfeminine", "ordmasculine", - "Omega", "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", "macron", - "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" -}; - -/* other prototypes */ -static void draw_composite_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, - double *matrix, int level); -static void draw_simple_glyf( GLYPH *g, GLYPH *glyph_list, int glyphno, - double *matrix); -static double f2dot14( short x); - -/* get the TTF description table address and length for this index */ - -static void -get_glyf_table( - int glyphno, - TTF_GLYF **tab, - int *len -) -{ - if(tab!=NULL) { - if (long_offsets) { - *tab = (TTF_GLYF *) (glyf_start + ntohl(long_loca_table[glyphno])); - } else { - *tab = (TTF_GLYF *) (glyf_start + (ntohs(short_loca_table[glyphno]) << 1)); - } - } - if(len!=NULL) { - if (long_offsets) { - *len = ntohl(long_loca_table[glyphno + 1]) - ntohl(long_loca_table[glyphno]); - } else { - *len = (ntohs(short_loca_table[glyphno + 1]) - ntohs(short_loca_table[glyphno])) << 1; - } - } -} - -static void -handle_name(void) -{ - int j, k, lang, len, platform; - char *p, *string_area; - char *nbp = name_buffer; - int found3 = 0; - - string_area = (char *) name_table + ntohs(name_table->offset); - name_record = &(name_table->nameRecords); - - for (j = 0; j < 8; j++) { - name_fields[j] = ""; - } - - for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) { - - platform = ntohs(name_record->platformID); - - if (platform == 3) { - - found3 = 1; - lang = ntohs(name_record->languageID) & 0xff; - len = ntohs(name_record->stringLength); - if (lang == 0 || lang == 9) { - k = ntohs(name_record->nameID); - if (k < 8) { - name_fields[k] = nbp; - - p = string_area + ntohs(name_record->stringOffset); - for (k = 0; k < len; k++) { - if (p[k] != '\0') { - if (p[k] == '(') { - *nbp = '['; - } else if (p[k] == ')') { - *nbp = ']'; - } else { - *nbp = p[k]; - } - nbp++; - } - } - *nbp = '\0'; - nbp++; - } - } - } - name_record++; - } - - string_area = (char *) name_table + ntohs(name_table->offset); - name_record = &(name_table->nameRecords); - - if (!found3) { - for (j = 0; j < ntohs(name_table->numberOfNameRecords); j++) { - - platform = ntohs(name_record->platformID); - - if (platform == 1) { - - found3 = 1; - lang = ntohs(name_record->languageID) & 0xff; - len = ntohs(name_record->stringLength); - if (lang == 0 || lang == 9) { - k = ntohs(name_record->nameID); - if (k < 8) { - name_fields[k] = nbp; - - p = string_area + ntohs(name_record->stringOffset); - for (k = 0; k < len; k++) { - if (p[k] != '\0') { - if (p[k] == '(') { - *nbp = '['; - } else if (p[k] == ')') { - *nbp = ']'; - } else { - *nbp = p[k]; - } - nbp++; - } - } - *nbp = '\0'; - nbp++; - } - } - } - name_record++; - } - } - if (!found3) { - fprintf(stderr, "**** Cannot decode font name fields ****\n"); - exit(1); - } - if (name_fields[4][0] == 0) { /* Full Name empty, use Family Name */ - name_fields[4] = name_fields[1]; - } - if (name_fields[6][0] == 0) { /* Font Name empty, use Full Name */ - name_fields[6] = name_fields[4]; - if (name_fields[6][0] == 0) { /* oops, empty again */ - WARNING_1 fprintf(stderr, "Font name is unknown, setting to \"Unknown\"\n"); - name_fields[6] = "Unknown"; - } - } - p = name_fields[6]; - /* must not start with a digit */ - if(isdigit(*p)) - *p+= 'A'-'0'; /* change to a letter */ - while (*p != '\0') { - if (!isalnum(*p) || *p=='_') { - *p = '-'; - } - p++; - } -} - -static void -handle_head(void) -{ - long_offsets = ntohs(head_table->indexToLocFormat); - if (long_offsets != 0 && long_offsets != 1) { - fprintf(stderr, "**** indexToLocFormat wrong ****\n"); - exit(1); - } -} - -/* limit the recursion level to avoid cycles */ -#define MAX_COMPOSITE_LEVEL 20 - -static void -draw_composite_glyf( - GLYPH *g, - GLYPH *glyph_list, - int glyphno, - double *orgmatrix, - int level -) -{ - int len; - short ncontours; - USHORT flagbyte, glyphindex; - double arg1, arg2; - BYTE *ptr; - char *bptr; - SHORT *sptr; - double matrix[6], newmatrix[6]; - - get_glyf_table(glyphno, &glyf_table, &len); - - if(len<=0) /* nothing to do */ - return; - - ncontours = ntohs(glyf_table->numberOfContours); - if (ncontours >= 0) { /* simple case */ - draw_simple_glyf(g, glyph_list, glyphno, orgmatrix); - return; - } - - if(ISDBG(COMPOSITE) && level ==0) - fprintf(stderr, "* %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", g->name, - orgmatrix[0], orgmatrix[1], orgmatrix[2], orgmatrix[3], - orgmatrix[4], orgmatrix[5]); - - /* complex case */ - if(level >= MAX_COMPOSITE_LEVEL) { - WARNING_1 fprintf(stderr, - "*** Glyph %s: stopped (possibly infinite) recursion at depth %d\n", - g->name, level); - return; - } - - ptr = ((BYTE *) glyf_table + sizeof(TTF_GLYF)); - sptr = (SHORT *) ptr; - do { - flagbyte = ntohs(*sptr); - sptr++; - glyphindex = ntohs(*sptr); - sptr++; - - if (flagbyte & ARG_1_AND_2_ARE_WORDS) { - arg1 = (short)ntohs(*sptr); - sptr++; - arg2 = (short)ntohs(*sptr); - sptr++; - } else { - bptr = (char *) sptr; - arg1 = (signed char) bptr[0]; - arg2 = (signed char) bptr[1]; - sptr++; - } - matrix[1] = matrix[2] = 0.0; - - if (flagbyte & WE_HAVE_A_SCALE) { - matrix[0] = matrix[3] = f2dot14(*sptr); - sptr++; - } else if (flagbyte & WE_HAVE_AN_X_AND_Y_SCALE) { - matrix[0] = f2dot14(*sptr); - sptr++; - matrix[3] = f2dot14(*sptr); - sptr++; - } else if (flagbyte & WE_HAVE_A_TWO_BY_TWO) { - matrix[0] = f2dot14(*sptr); - sptr++; - matrix[2] = f2dot14(*sptr); - sptr++; - matrix[1] = f2dot14(*sptr); - sptr++; - matrix[3] = f2dot14(*sptr); - sptr++; - } else { - matrix[0] = matrix[3] = 1.0; - } - - /* - * See * - * http://fonts.apple.com/TTRefMan/RM06/Chap6g - * lyf.html * matrix[0,1,2,3,4,5]=a,b,c,d,m,n - */ - - if (fabs(matrix[0]) > fabs(matrix[1])) - matrix[4] = fabs(matrix[0]); - else - matrix[4] = fabs(matrix[1]); - if (fabs(fabs(matrix[0]) - fabs(matrix[2])) <= 33. / 65536.) - matrix[4] *= 2.0; - - if (fabs(matrix[2]) > fabs(matrix[3])) - matrix[5] = fabs(matrix[2]); - else - matrix[5] = fabs(matrix[3]); - if (fabs(fabs(matrix[2]) - fabs(matrix[3])) <= 33. / 65536.) - matrix[5] *= 2.0; - - /* - * fprintf (stderr,"Matrix Opp %hd - * %hd\n",arg1,arg2); - */ -#if 0 - fprintf(stderr, "Matrix: %f %f %f %f %f %f\n", - matrix[0], matrix[1], matrix[2], matrix[3], - matrix[4], matrix[5]); - fprintf(stderr, "Offset: %f %f (%s)\n", - arg1, arg2, - ((flagbyte & ARGS_ARE_XY_VALUES) ? "XY" : "index")); -#endif - - if (flagbyte & ARGS_ARE_XY_VALUES) { - matrix[4] *= arg1; - matrix[5] *= arg2; - } else { - WARNING_1 fprintf(stderr, - "*** Glyph %s: reusing scale from another glyph is unsupported\n", - g->name); - /* - * must extract values from a glyph - * but it seems to be too much pain - * and it's not clear now that it - * would be really used in any - * interesting font - */ - } - - /* at this point arg1,arg2 contain what logically should be matrix[4,5] */ - - /* combine matrices */ - - newmatrix[0] = orgmatrix[0]*matrix[0] + orgmatrix[2]*matrix[1]; - newmatrix[1] = orgmatrix[0]*matrix[2] + orgmatrix[2]*matrix[3]; - - newmatrix[2] = orgmatrix[1]*matrix[0] + orgmatrix[3]*matrix[1]; - newmatrix[3] = orgmatrix[1]*matrix[2] + orgmatrix[3]*matrix[3]; - - newmatrix[4] = orgmatrix[0]*matrix[4] + orgmatrix[2]*matrix[5] + orgmatrix[4]; - newmatrix[5] = orgmatrix[1]*matrix[4] + orgmatrix[3]*matrix[5] + orgmatrix[5]; - - if(ISDBG(COMPOSITE)) { - fprintf(stderr, "%*c+-> %2d %s [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", - level+1, ' ', level, glyph_list[glyphindex].name, - matrix[0], matrix[1], matrix[2], matrix[3], - matrix[4], matrix[5]); - fprintf(stderr, "%*c = [ %.2f %.2f %.2f %.2f %.2f %.2f ]\n", - level+1, ' ', - newmatrix[0], newmatrix[1], newmatrix[2], newmatrix[3], - newmatrix[4], newmatrix[5]); - } - draw_composite_glyf(g, glyph_list, glyphindex, newmatrix, level+1); - - } while (flagbyte & MORE_COMPONENTS); -} - -static void -draw_simple_glyf( - GLYPH *g, - GLYPH *glyph_list, - int glyphno, - double *matrix -) -{ - int i, j, k, k1, len, first, cs, ce; - /* We assume that hsbw always sets to(0, 0) */ - double xlast = 0, ylast = 0; - int finished, nguide, contour_start, contour_end; - short ncontours, n_inst, last_point; - USHORT *contour_end_pt; - BYTE *ptr; -#define GLYFSZ 2000 - short xabs[GLYFSZ], yabs[GLYFSZ], xrel[GLYFSZ], yrel[GLYFSZ]; - double xcoord[GLYFSZ], ycoord[GLYFSZ]; - BYTE flags[GLYFSZ]; - double tx, ty; - int needreverse = 0; /* transformation may require - * that */ - GENTRY *lge; - - lge = g->lastentry; - - get_glyf_table(glyphno, &glyf_table, &len); - - if (len <= 0) { - WARNING_1 fprintf(stderr, - "**** Composite glyph %s refers to non-existent glyph %s, ignored\n", - g->name, - glyph_list[glyphno].name); - return; - } - ncontours = ntohs(glyf_table->numberOfContours); - if (ncontours < 0) { - WARNING_1 fprintf(stderr, - "**** Composite glyph %s refers to composite glyph %s, ignored\n", - g->name, - glyph_list[glyphno].name); - return; - } - contour_end_pt = (USHORT *) ((char *) glyf_table + sizeof(TTF_GLYF)); - - last_point = ntohs(contour_end_pt[ncontours - 1]); - n_inst = ntohs(contour_end_pt[ncontours]); - - ptr = ((BYTE *) contour_end_pt) + (ncontours << 1) + n_inst + 2; - j = k = 0; - while (k <= last_point) { - flags[k] = ptr[j]; - - if (ptr[j] & REPEAT) { - for (k1 = 0; k1 < ptr[j + 1]; k1++) { - k++; - flags[k] = ptr[j]; - } - j++; - } - j++; - k++; - } - - for (k = 0; k <= last_point; k++) { - if (flags[k] & XSHORT) { - if (flags[k] & XSAME) { - xrel[k] = ptr[j]; - } else { - xrel[k] = -ptr[j]; - } - j++; - } else if (flags[k] & XSAME) { - xrel[k] = 0.0; - } else { - xrel[k] = (short)( ptr[j] * 256 + ptr[j + 1] ); - j += 2; - } - if (k == 0) { - xabs[k] = xrel[k]; - } else { - xabs[k] = xrel[k] + xabs[k - 1]; - } - - } - - for (k = 0; k <= last_point; k++) { - if (flags[k] & YSHORT) { - if (flags[k] & YSAME) { - yrel[k] = ptr[j]; - } else { - yrel[k] = -ptr[j]; - } - j++; - } else if (flags[k] & YSAME) { - yrel[k] = 0; - } else { - yrel[k] = ptr[j] * 256 + ptr[j + 1]; - j += 2; - } - if (k == 0) { - yabs[k] = yrel[k]; - } else { - yabs[k] = yrel[k] + yabs[k - 1]; - } - } - - if (matrix) { - for (i = 0; i <= last_point; i++) { - tx = xabs[i]; - ty = yabs[i]; - xcoord[i] = fscale(matrix[0] * tx + matrix[2] * ty + matrix[4]); - ycoord[i] = fscale(matrix[1] * tx + matrix[3] * ty + matrix[5]); - } - } else { - for (i = 0; i <= last_point; i++) { - xcoord[i] = fscale(xabs[i]); - ycoord[i] = fscale(yabs[i]); - } - } - - i = j = 0; - first = 1; - - while (i <= ntohs(contour_end_pt[ncontours - 1])) { - contour_end = ntohs(contour_end_pt[j]); - - if (first) { - fg_rmoveto(g, xcoord[i], ycoord[i]); - xlast = xcoord[i]; - ylast = ycoord[i]; - contour_start = i; - first = 0; - } else if (flags[i] & ONOROFF) { - fg_rlineto(g, xcoord[i], ycoord[i]); - xlast = xcoord[i]; - ylast = ycoord[i]; - } else { - cs = i - 1; - finished = nguide = 0; - while (!finished) { - if (i == contour_end + 1) { - ce = contour_start; - finished = 1; - } else if (flags[i] & ONOROFF) { - ce = i; - finished = 1; - } else { - i++; - nguide++; - } - } - - switch (nguide) { - case 0: - fg_rlineto(g, xcoord[ce], ycoord[ce]); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - break; - - case 1: - fg_rrcurveto(g, - (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, - (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, - (2.0 * xcoord[cs + 1] + xcoord[ce]) / 3.0, - (2.0 * ycoord[cs + 1] + ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - - break; - - case 2: - fg_rrcurveto(g, - (-xcoord[cs] + 4.0 * xcoord[cs + 1]) / 3.0, - (-ycoord[cs] + 4.0 * ycoord[cs + 1]) / 3.0, - (4.0 * xcoord[cs + 2] - xcoord[ce]) / 3.0, - (4.0 * ycoord[cs + 2] - ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - break; - - case 3: - fg_rrcurveto(g, - (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, - (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, - (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0, - (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0, - (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0, - (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0 - ); - - fg_rrcurveto(g, - (xcoord[cs + 1] + 5.0 * xcoord[cs + 2]) / 6.0, - (ycoord[cs + 1] + 5.0 * ycoord[cs + 2]) / 6.0, - (5.0 * xcoord[cs + 2] + xcoord[cs + 3]) / 6.0, - (5.0 * ycoord[cs + 2] + ycoord[cs + 3]) / 6.0, - (xcoord[cs + 3] + xcoord[cs + 2]) / 2.0, - (ycoord[cs + 3] + ycoord[cs + 2]) / 2.0 - ); - - fg_rrcurveto(g, - (xcoord[cs + 2] + 5.0 * xcoord[cs + 3]) / 6.0, - (ycoord[cs + 2] + 5.0 * ycoord[cs + 3]) / 6.0, - (2.0 * xcoord[cs + 3] + xcoord[ce]) / 3.0, - (2.0 * ycoord[cs + 3] + ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - ylast = ycoord[ce]; - xlast = xcoord[ce]; - - break; - - default: - k1 = cs + nguide; - fg_rrcurveto(g, - (xcoord[cs] + 2.0 * xcoord[cs + 1]) / 3.0, - (ycoord[cs] + 2.0 * ycoord[cs + 1]) / 3.0, - (5.0 * xcoord[cs + 1] + xcoord[cs + 2]) / 6.0, - (5.0 * ycoord[cs + 1] + ycoord[cs + 2]) / 6.0, - (xcoord[cs + 1] + xcoord[cs + 2]) / 2.0, - (ycoord[cs + 1] + ycoord[cs + 2]) / 2.0 - ); - - for (k = cs + 2; k <= k1 - 1; k++) { - fg_rrcurveto(g, - (xcoord[k - 1] + 5.0 * xcoord[k]) / 6.0, - (ycoord[k - 1] + 5.0 * ycoord[k]) / 6.0, - (5.0 * xcoord[k] + xcoord[k + 1]) / 6.0, - (5.0 * ycoord[k] + ycoord[k + 1]) / 6.0, - (xcoord[k] + xcoord[k + 1]) / 2.0, - (ycoord[k] + ycoord[k + 1]) / 2.0 - ); - - } - - fg_rrcurveto(g, - (xcoord[k1 - 1] + 5.0 * xcoord[k1]) / 6.0, - (ycoord[k1 - 1] + 5.0 * ycoord[k1]) / 6.0, - (2.0 * xcoord[k1] + xcoord[ce]) / 3.0, - (2.0 * ycoord[k1] + ycoord[ce]) / 3.0, - xcoord[ce], - ycoord[ce] - ); - xlast = xcoord[ce]; - ylast = ycoord[ce]; - - break; - } - } - if (i >= contour_end) { - g_closepath(g); - first = 1; - i = contour_end + 1; - j++; - } else { - i++; - } - } - - if (matrix) { - /* guess whether do we need to reverse the results */ - - double x[3], y[3]; - int max = 0, from, to; - - /* transform a triangle going in proper direction */ - /* - * the origin of triangle is in (0,0) so we know it in - * advance - */ - - x[0] = y[0] = 0; - x[1] = matrix[0] * 0 + matrix[2] * 300; - y[1] = matrix[1] * 0 + matrix[3] * 300; - x[2] = matrix[0] * 300 + matrix[2] * 0; - y[2] = matrix[1] * 300 + matrix[3] * 0; - - /* then find the topmost point */ - for (i = 0; i < 3; i++) - if (y[i] > y[max]) - max = i; - from = (max + 3 - 1) % 3; - to = (max + 1) % 3; - - needreverse = 0; - - /* special cases for horizontal lines */ - if (y[max] == y[from]) { - if (x[max] < y[from]) - needreverse = 1; - } else if (y[to] == y[from]) { - if (x[to] < x[max]) - needreverse = 1; - } else { /* generic case */ - if ((x[to] - x[max]) * (y[max] - y[from]) - > (x[max] - x[from]) * (y[to] - y[max])) - needreverse = 1; - } - - if (needreverse) { - if (lge) { - assertpath(lge->next, __FILE__, __LINE__, g->name); - reversepathsfromto(lge->next, NULL); - } else { - assertpath(g->entries, __FILE__, __LINE__, g->name); - reversepaths(g); - } - } - } -} - -static double -f2dot14( - short x -) -{ - short y = ntohs(x); - return (y >> 14) + ((y & 0x3fff) / 16384.0); -} - - -/* check that the pointer points within the file */ -/* returns 0 if pointer is good, 1 if bad */ -static int -badpointer( - void *ptr -) -{ - return (ptr < (void *)filebuffer || ptr >= (void *)filebuffer_end); -} - -/* - * Externally accessible methods - */ - -/* - * Open font and prepare to return information to the main driver. - * May print error and warning messages. - * Exit on error. - */ - -static void -openfont( - char *fname, - char *arg /* unused now */ -) -{ - int i, j; - struct stat statbuf; - static struct { - void **tbpp; /* pointer to pointer to the table */ - char name[5]; /* table name */ - char optional; /* flag: table may be missing */ - } tables[] = { - { (void **)&name_table, "name", 0 }, - { (void **)&head_table, "head", 0 }, - { (void **)&hhea_table, "hhea", 0 }, - { (void **)&post_table, "post", 0 }, - { (void **)&glyf_start, "glyf", 0 }, - { (void **)&cmap_table, "cmap", 0 }, - { (void **)&kern_table, "kern", 1 }, - { (void **)&maxp_table, "maxp", 0 }, - { (void **)&hmtx_table, "hmtx", 0 }, - { (void **)&long_loca_table, "loca", 0 }, - { NULL, "", 0 } /* end of table */ - }; - - if (stat(fname, &statbuf) == -1) { - fprintf(stderr, "**** Cannot access %s ****\n", fname); - exit(1); - } - if ((filebuffer = malloc(statbuf.st_size)) == NULL) { - fprintf(stderr, "**** Cannot malloc space for file ****\n"); - exit(1); - } - - filebuffer_end = filebuffer + statbuf.st_size; - - if ((ttf_file = fopen(fname, "rb")) == NULL) { - fprintf(stderr, "**** Cannot open file '%s'\n", fname); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Processing file %s\n", fname); - } - - if (fread(filebuffer, 1, statbuf.st_size, ttf_file) != statbuf.st_size) { - fprintf(stderr, "**** Could not read whole file \n"); - exit(1); - } - fclose(ttf_file); - - directory = (TTF_DIRECTORY *) filebuffer; - - if (ntohl(directory->sfntVersion) != 0x00010000) { - fprintf(stderr, - "**** Unknown File Version number [%x], or not a TrueType file\n", - directory->sfntVersion); - exit(1); - } - - /* clear the tables */ - for(j=0; tables[j].tbpp != NULL; j++) - *(tables[j].tbpp) = NULL; - - dir_entry = &(directory->list); - - for (i = 0; i < ntohs(directory->numTables); i++) { - - for(j=0; tables[j].tbpp != NULL; j++) - if (memcmp(dir_entry->tag, tables[j].name, 4) == 0) { - *(tables[j].tbpp) = (void *) (filebuffer + ntohl(dir_entry->offset)); - break; - } - - if (memcmp(dir_entry->tag, "EBDT", 4) == 0 || - memcmp(dir_entry->tag, "EBLC", 4) == 0 || - memcmp(dir_entry->tag, "EBSC", 4) == 0) { - WARNING_1 fprintf(stderr, "Font contains bitmaps\n"); - } - dir_entry++; - } - - for(j=0; tables[j].tbpp != NULL; j++) - if(!tables[j].optional && badpointer( *(tables[j].tbpp) )) { - fprintf(stderr, "**** File contains no required table '%s'\n", tables[j].name); - exit(1); - } - - handle_name(); - - handle_head(); - - ttf_nglyphs = ntohs(maxp_table->numGlyphs); - - enc_found_ms = enc_found_mac = 0; -} - -/* - * Close font. - * Exit on error. - */ - -static void -closefont( - void -) -{ - return; /* empty operation */ -} - -/* - * Get the number of glyphs in font. - */ - -static int -getnglyphs ( - void -) -{ - return ttf_nglyphs; -} - -/* - * Get the names of the glyphs. - * Returns 0 if the names were assigned, non-zero if the font - * provides no glyph names. - */ - -static int -glnames( - GLYPH *glyph_list -) -{ - int i, len, n, npost; - unsigned int format; - USHORT *name_index; - char *ptr, *p; - char **ps_name_ptr = (char **) malloc(ttf_nglyphs * sizeof(char *)); - int n_ps_names; - int ps_fmt_3 = 0; - - format = ntohl(post_table->formatType); - - if (format == 0x00010000) { - for (i = 0; i < 258 && i < ttf_nglyphs; i++) { - glyph_list[i].name = mac_glyph_names[i]; - } - } else if (format == 0x00020000) { - npost = ntohs(post_table->numGlyphs); - if (ttf_nglyphs != npost) { - /* This is an error in the font, but we can now cope */ - WARNING_1 fprintf(stderr, "**** Postscript table size mismatch %d/%d ****\n", - npost, ttf_nglyphs); - } - n_ps_names = 0; - name_index = &(post_table->glyphNameIndex); - - /* This checks the integrity of the post table */ - for (i=0; i n_ps_names + 257) { - n_ps_names = n - 257; - } - } - - ptr = (char *) post_table + 34 + (ttf_nglyphs << 1); - i = 0; - while (*ptr > 0 && i < n_ps_names) { - len = *ptr; - /* previously the program wrote nulls into the table. If the table - was corrupt, this could put zeroes anywhere, leading to obscure bugs, - so now I malloc space for the names. Yes it is much less efficient */ - - if ((p = malloc(len+1)) == NULL) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - - ps_name_ptr[i] = p; - strncpy(p, ptr+1, len); - p[len] = '\0'; - i ++; - ptr += len + 1; - } - - if (i != n_ps_names) - { - WARNING_2 fprintf (stderr, "** Postscript Name mismatch %d != %d **\n", - i, n_ps_names); - n_ps_names = i; - } - - /* - * for (i=0; inumGlyphs); - for (i = 0; i < ttf_nglyphs; i++) { - glyph_list[i].name = mac_glyph_names[i + ptr[i]]; - } - } else { - fprintf(stderr, - "**** Postscript table in wrong format %x ****\n", - format); - exit(1); - } - - return ps_fmt_3; -} - -/* - * Get the metrics of the glyphs. - */ - -static void -glmetrics( - GLYPH *glyph_list -) -{ - int i; - int n_hmetrics = ntohs(hhea_table->numberOfHMetrics); - GLYPH *g; - LONGHORMETRIC *hmtx_entry = hmtx_table; - FWORD *lsblist; - - for (i = 0; i < n_hmetrics; i++) { - g = &(glyph_list[i]); - g->width = ntohs(hmtx_entry->advanceWidth); - g->lsb = ntohs(hmtx_entry->lsb); - hmtx_entry++; - } - - lsblist = (FWORD *) hmtx_entry; - hmtx_entry--; - - for (i = n_hmetrics; i < ttf_nglyphs; i++) { - g = &(glyph_list[i]); - g->width = ntohs(hmtx_entry->advanceWidth); - g->lsb = ntohs(lsblist[i - n_hmetrics]); - } - - for (i = 0; i < ttf_nglyphs; i++) { - g = &(glyph_list[i]); - get_glyf_table(i, &glyf_table, &g->ttf_pathlen); - - g->xMin = (short)ntohs(glyf_table->xMin); - g->xMax = (short)ntohs(glyf_table->xMax); - g->yMin = (short)ntohs(glyf_table->yMin); - g->yMax = (short)ntohs(glyf_table->yMax); - } - -} - - -static void -handle_ms_encoding( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - int j, k, kk, set_ok; - USHORT start, end, ro; - short delta, n; - - for (j = 0; j < cmap_n_segs - 1; j++) { - start = ntohs(cmap_seg_start[j]); - end = ntohs(cmap_seg_end[j]); - delta = ntohs(cmap_idDelta[j]); - ro = ntohs(cmap_idRangeOffset[j]); - - for (k = start; k <= end; k++) { - if (ro == 0) { - n = k + delta; - } else { - n = ntohs(*((ro >> 1) + (k - start) + - &(cmap_idRangeOffset[j]))); - if (delta != 0) - { - /* Not exactly sure how to deal with this circumstance, - I suspect it never occurs */ - n += delta; - fprintf (stderr, - "rangeoffset and delta both non-zero - %d/%d", - ro, delta); - } - } - if(n<0 || n>=ttf_nglyphs) { - WARNING_1 fprintf(stderr, "Font contains a broken glyph code mapping, ignored\n"); - continue; - } - if (glyph_list[n].orig_code != -1) { -#if 0 - if (strcmp(glyph_list[n].name, ".notdef") != 0) { - WARNING_2 fprintf(stderr, - "Glyph %s has >= two encodings (A), %4.4x & %4.4x\n", - glyph_list[n].name, - glyph_list[n].orig_code, - k); - } -#endif - set_ok = 0; - } else { - set_ok = 1; - } - if (enc_type==1 || forcemap) { - kk = unicode_rev_lookup(k); - if(ISDBG(UNICODE)) - fprintf(stderr, "Unicode %s - 0x%04x\n",glyph_list[n].name,k); - if (set_ok) { - glyph_list[n].orig_code = k; - /* glyph_list[n].char_no = kk; */ - } - if (kk >= 0 && kk < ENCTABSZ && encoding[kk] == -1) - encoding[kk] = n; - } else { - if ((k & 0xff00) == 0xf000) { - if( encoding[k & 0x00ff] == -1 ) { - encoding[k & 0x00ff] = n; - if (set_ok) { - /* glyph_list[n].char_no = k & 0x00ff; */ - glyph_list[n].orig_code = k; - } - } - } else { - if (set_ok) { - /* glyph_list[n].char_no = k; */ - glyph_list[n].orig_code = k; - } - WARNING_2 fprintf(stderr, - "Glyph %s has non-symbol encoding %4.4x\n", - glyph_list[n].name, - k & 0xffff); - /* - * just use the code - * as it is - */ - if ((k & ~0xff) == 0 && encoding[k] == -1 ) - encoding[k] = n; - } - } - } - } -} - -static void -handle_mac_encoding( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - short n; - int j, size; - - size = ntohs(encoding0->length) - 6; - for (j = 0; j < size; j++) { - n = encoding0->glyphIdArray[j]; - if (glyph_list[n].char_no != -1) { - WARNING_2 fprintf(stderr, - "Glyph %s has >= two encodings (B), %4.4x & %4.4x\n", - glyph_list[n].name, - glyph_list[n].char_no, - j); - } else { - if (j < ENCTABSZ) { - if(encoding[j] == -1) { - glyph_list[n].char_no = j; - encoding[j] = n; - } - } - } - } -} - -/* - * Get the original encoding of the font. - * Returns 1 for if the original encoding is Unicode, 2 if the - * original encoding is other 16-bit, 0 if 8-bit. - */ - -static int -glenc( - GLYPH *glyph_list, - int *encoding, - int *unimap -) -{ - int num_tables = ntohs(cmap_table->numberOfEncodingTables); - BYTE *ptr; - int i, format, offset, seg_c2, found; - int platform, encoding_id; - TTF_CMAP_ENTRY *table_entry; - TTF_CMAP_FMT4 *encoding4; - - if(enc_found_ms) { - handle_ms_encoding(glyph_list, encoding, unimap); - return enc_type; - } else if(enc_found_mac) { - handle_mac_encoding(glyph_list, encoding, unimap); - return 0; - } - - if(force_pid != -1 && force_pid != 3) { - fputs("*** Only platform ID == 3 is supported\n", stderr); - exit(1); - } - - enc_type = 0; - found = 0; - - for (i = 0; i < num_tables && !found; i++) { - table_entry = &(cmap_table->encodingTable[i]); - offset = ntohl(table_entry->offset); - encoding4 = (TTF_CMAP_FMT4 *) ((BYTE *) cmap_table + offset); - format = ntohs(encoding4->format); - platform = ntohs(table_entry->platformID); - encoding_id = ntohs(table_entry->encodingID); - - if (platform == 3 && format == 4) { - if(force_pid == 3) { - if(encoding_id != force_eid) - continue; - WARNING_1 fprintf(stderr, "Found Encoding PID=%d/EID=%d\n", - force_pid, force_eid); - enc_type = 1; - } else { - switch (encoding_id) { - case 0: - WARNING_1 fputs("Found Symbol Encoding\n", stderr); - break; - case 1: - WARNING_1 fputs("Found Unicode Encoding\n", stderr); - enc_type = 1; - break; - default: - WARNING_1 { - fprintf(stderr, - "****MS Encoding ID %d not supported****\n", - encoding_id); - fputs("Treating it like Symbol encoding\n", stderr); - } - break; - } - } - - found = 1; - seg_c2 = ntohs(encoding4->segCountX2); - cmap_n_segs = seg_c2 >> 1; - ptr = (BYTE *) encoding4 + 14; - cmap_seg_end = (USHORT *) ptr; - cmap_seg_start = (USHORT *) (ptr + seg_c2 + 2); - cmap_idDelta = (short *) (ptr + (seg_c2 * 2) + 2); - cmap_idRangeOffset = (short *) (ptr + (seg_c2 * 3) + 2); - enc_found_ms = 1; - - handle_ms_encoding(glyph_list, encoding, unimap); - } - } - - if (!found) { - if(force_pid != -1) { - fprintf(stderr, "*** TTF encoding table PID=%d/EID=%d not found\n", - force_pid, force_eid); - exit(1); - } - - WARNING_1 fputs("No Microsoft encoding, looking for MAC encoding\n", stderr); - for (i = 0; i < num_tables && !found; i++) { - table_entry = &(cmap_table->encodingTable[i]); - offset = ntohl(table_entry->offset); - encoding0 = (TTF_CMAP_FMT0 *) ((BYTE *) cmap_table + offset); - format = ntohs(encoding0->format); - platform = ntohs(table_entry->platformID); - encoding_id = ntohs(table_entry->encodingID); - - if (format == 0) { - found = 1; - enc_found_mac = 1; - - handle_mac_encoding(glyph_list, encoding, unimap); - } - } - } - if (!found) { - fprintf(stderr, "**** No Recognised Encoding Table ****\n"); - exit(1); - } - - return enc_type; -} - -/* - * Get the font metrics - */ -static void -fnmetrics( - struct font_metrics *fm -) -{ - char *str; - static int fieldstocheck[]= {2,4,6}; - int i, j, len; - - fm->italic_angle = (short) (ntohs(post_table->italicAngle.upper)) + - ((short) ntohs(post_table->italicAngle.lower) / 65536.0); - fm->underline_position = (short) ntohs(post_table->underlinePosition); - fm->underline_thickness = (short) ntohs(post_table->underlineThickness); - fm->is_fixed_pitch = ntohl(post_table->isFixedPitch); - - fm->ascender = (short)ntohs(hhea_table->ascender); - fm->descender = (short)ntohs(hhea_table->descender); - - fm->units_per_em = ntohs(head_table->unitsPerEm); - - fm->bbox[0] = (short) ntohs(head_table->xMin); - fm->bbox[1] = (short) ntohs(head_table->yMin); - fm->bbox[2] = (short) ntohs(head_table->xMax); - fm->bbox[3] = (short) ntohs(head_table->yMax); - - fm->name_copyright = name_fields[0]; - fm->name_family = name_fields[1]; - fm->name_style = name_fields[2]; - fm->name_full = name_fields[4]; - fm->name_version = name_fields[5]; - fm->name_ps = name_fields[6]; - - /* guess the boldness from the font names */ - fm->force_bold=0; - - for(i=0; !fm->force_bold && i= len || !islower(str[j+4])) - ) { - fm->force_bold=1; - break; - } - } - } -} - -/* - * Get the path of contrours for a glyph. - */ - -static void -glpath( - int glyphno, - GLYPH *glyf_list -) -{ - double matrix[6]; - GLYPH *g; - - g = &glyph_list[glyphno]; - - matrix[0] = matrix[3] = 1.0; - matrix[1] = matrix[2] = matrix[4] = matrix[5] = 0.0; - draw_composite_glyf(g, glyf_list, glyphno, matrix, 0 /*level*/); -} - -/* - * Get the kerning data. - */ - -static void -kerning( - GLYPH *glyph_list -) -{ - TTF_KERN_SUB *subtable; - TTF_KERN_ENTRY *kern_entry; - int i, j; - int ntables; - int npairs; - char *ptr; - - if(kern_table == NULL) { - WARNING_1 fputs("No Kerning data\n", stderr); - return; - } - if(badpointer(kern_table)) { - fputs("**** Defective Kerning table, ignored\n", stderr); - return; - } - - ntables = ntohs(kern_table->nTables); - ptr = (char *) kern_table + 4; - - for (i = 0; i < ntables; i++) { - subtable = (TTF_KERN_SUB *) ptr; - if ((ntohs(subtable->coverage) & 0xff00) == 0) { - npairs = (short) ntohs(subtable->nPairs); - kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB)); - - kern_entry = (TTF_KERN_ENTRY *) (ptr + sizeof(TTF_KERN_SUB)); - for (j = 0; j < npairs; j++) { - if( kern_entry->value != 0) - addkernpair(ntohs(kern_entry->left), - ntohs(kern_entry->right), (short)ntohs(kern_entry->value)); - kern_entry++; - } - } - ptr += subtable->length; - } -} - diff --git a/pdf2swf/ttf2pt1/ttf.h b/pdf2swf/ttf2pt1/ttf.h deleted file mode 100644 index 9f5c502..0000000 --- a/pdf2swf/ttf2pt1/ttf.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * see COPYRIGHT - */ - -/* these definitions are mostly taken from Microsoft's True Type - documentation. -*/ - -#define BYTE unsigned char -#define CHAR signed char -#define USHORT unsigned short -#define SHORT signed short -#define ULONG unsigned int -#define LONG signed int -#define FWORD SHORT -#define UFWORD USHORT - -#define ONOROFF 0x01 -#define XSHORT 0x02 -#define YSHORT 0x04 -#define REPEAT 0x08 -#define XSAME 0x10 -#define YSAME 0x20 - -#define ARG_1_AND_2_ARE_WORDS 0x0001 -#define ARGS_ARE_XY_VALUES 0x0002 -#define XY_BOUND_TO_GRID 0x0004 -#define WE_HAVE_A_SCALE 0x0008 -#define MORE_COMPONENTS 0x0020 -#define WE_HAVE_AN_X_AND_Y_SCALE 0x0040 -#define WE_HAVE_A_TWO_BY_TWO 0x0080 -#define WE_HAVE_INSTRUCTIONS 0x0100 -#define USE_MY_METRICS 0x0200 - -typedef struct short_2 { - SHORT upper; - USHORT lower; -} TTF2PT1_FIXED ; - -typedef struct longhormetric { - UFWORD advanceWidth; - FWORD lsb; -} LONGHORMETRIC; - -typedef struct ttf_hhea { - BYTE version[4]; - SHORT ascender, descender, lineGap; - USHORT advnaceWidthMax; - SHORT minLSB, minRSB, xMaxExtent; - SHORT caretSlopeRise, caretSlopeRun; - SHORT reserved[5]; - SHORT metricDataFormat; - USHORT numberOfHMetrics; -} TTF_HHEA; - -typedef struct ttf_dir_entry { - char tag[4]; - ULONG checksum; - ULONG offset; - ULONG length; -} TTF_DIR_ENTRY ; - -typedef struct ttf_directory { - ULONG sfntVersion; - USHORT numTables; - USHORT searchRange; - USHORT entrySelector; - USHORT rangeShift; - TTF_DIR_ENTRY list; -} TTF_DIRECTORY ; - -typedef struct ttf_name_rec { - USHORT platformID; - USHORT encodingID; - USHORT languageID; - USHORT nameID; - USHORT stringLength; - USHORT stringOffset; -} TTF_NAME_REC; - -typedef struct ttf_name { - USHORT format; - USHORT numberOfNameRecords; - USHORT offset; - TTF_NAME_REC nameRecords; -} TTF_NAME ; - -typedef struct ttf_head { - ULONG version; - ULONG fontRevision; - ULONG checksumAdjust; - ULONG magicNo; - USHORT flags; - USHORT unitsPerEm; - BYTE created[8]; - BYTE modified[8]; - FWORD xMin, yMin, xMax, yMax; - USHORT macStyle, lowestRecPPEM; - SHORT fontDirection, indexToLocFormat, glyphDataFormat; -} TTF_HEAD ; - -typedef struct ttf_kern { - USHORT version, nTables; -} TTF_KERN ; - -typedef struct ttf_kern_sub { - USHORT version, length, coverage; - USHORT nPairs, searchRange, entrySelector, rangeShift; -} TTF_KERN_SUB; - -typedef struct ttf_kern_entry { - USHORT left, right; - FWORD value; -} TTF_KERN_ENTRY; - -typedef struct ttf_cmap_fmt0 { - USHORT format; - USHORT length; - USHORT version; - BYTE glyphIdArray[256]; -} TTF_CMAP_FMT0; - -typedef struct ttf_cmap_fmt4 { - USHORT format; - USHORT length; - USHORT version; - USHORT segCountX2; - USHORT searchRange; - USHORT entrySelector; - USHORT rangeShift; -} TTF_CMAP_FMT4; - -typedef struct ttf_cmap_entry { - USHORT platformID; - USHORT encodingID; - ULONG offset; -} TTF_CMAP_ENTRY; - -typedef struct ttf_cmap { - USHORT version; - USHORT numberOfEncodingTables; - TTF_CMAP_ENTRY encodingTable[1]; -} TTF_CMAP ; - -typedef struct ttf_glyf { - SHORT numberOfContours; - FWORD xMin, yMin, xMax, yMax; -} TTF_GLYF ; - -typedef struct ttf_maxp { - ULONG version; - USHORT numGlyphs, maxPoints, maxContours; - USHORT maxCompositePoints, maxCompositeContours; - USHORT maxZones, maxTwilightPoints, maxStorage; - USHORT maxFunctionDefs, maxInstructionsDefs; - USHORT maxSizeOfInstructions, maxComponentElements; - USHORT maxComponentDepth; -} TTF_MAXP ; - -typedef struct ttf_post_head { - ULONG formatType; - TTF2PT1_FIXED italicAngle; - FWORD underlinePosition; - FWORD underlineThickness; - ULONG isFixedPitch; - ULONG minMemType42; - ULONG maxMemType42; - ULONG minMemType1; - ULONG maxMemType1; - USHORT numGlyphs; - USHORT glyphNameIndex; -} TTF_POST_HEAD ; diff --git a/pdf2swf/ttf2pt1/ttf2pt1.c b/pdf2swf/ttf2pt1/ttf2pt1.c deleted file mode 100644 index 0b03b23..0000000 --- a/pdf2swf/ttf2pt1/ttf2pt1.c +++ /dev/null @@ -1,2570 +0,0 @@ -/* - * True Type Font to Adobe Type 1 font converter - * By Mark Heath - * Based on ttf2pfa by Andrew Weeks - * With help from Frank M. Siegert - * - * see COPYRIGHT for full copyright notice - * -*********************************************************************** - * - * Sergey Babkin , - * - * Added post-processing of resulting outline to correct the errors - * both introduced during conversion and present in the original font, - * autogeneration of hints (has yet to be improved though) and BlueValues, - * scaling to 1000x1000 matrix, option to print the result on STDOUT, - * support of Unicode to CP1251 conversion, optimization of the - * resulting font code by space (that improves the speed too). Excluded - * the glyphs that are unaccessible through the encoding table from - * the output file. Added the built-in Type1 assembler (taken from - * the `t1utils' package). - * -*********************************************************************** - * - * Thomas Henlich - * - * Added generation of .afm file (font metrics) - * Read encoding information from encoding description file - * Fixed bug in error message about unknown language ('-l' option) - * Added `:' after %%!PS-AdobeFont-1.0 - * changed unused entries in ISOLatin1Encoding[] from .notdef to c127,c128... - * -*********************************************************************** - * - * Thomas Henlich - * - * Added generation of .afm file (font metrics) - * -*********************************************************************** - * - * Bug Fixes: -************************************************************************ - * - * Sun, 21 Jun 1998 Thomas Henlich - * 1. "width" should be "short int" because otherwise: - * characters with negative widths (e.g. -4) become *very* wide (65532) - * 2. the number of /CharStrings is numglyphs and not numglyphs+1 - * -*********************************************************************** - * - * - * - * The resultant font file produced by this program still needs to be ran - * through t1asm (from the t1utils archive) to produce a completely valid - * font. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../../config.h" - -#ifdef _GNU_SOURCE -#include -#endif - -#ifndef WIN32 -# include -# include -# define BITBUCKET "/dev/null" -# include -#else -# define WINDOWS_FUNCTIONS /* ask to define functions - in one file only */ -# include "win_missing.h" -# define BITBUCKET "NUL" -#endif - -#include "pt1.h" -#include "global.h" -#include "version.h" - -/* globals */ - -/* table of front-ends */ - -extern struct frontsw ttf_sw; -extern struct frontsw bdf_sw; -#if defined(USE_FREETYPE) - extern struct frontsw freetype_sw; -#endif - -struct frontsw *frontswtab[] = { - &bdf_sw, -#if defined(USE_FREETYPE) && defined(PREFER_FREETYPE) - &freetype_sw, -#endif - &ttf_sw, -#if defined(USE_FREETYPE) && !defined(PREFER_FREETYPE) - &freetype_sw, -#endif - NULL /* end of table */ -}; - -#ifdef WIN32 -#define NOPIPES -#else -#undef NOPIPES -#endif - -struct frontsw *cursw=0; /* the active front end */ -char *front_arg=""; /* optional argument */ - -/* options */ -int encode = 0; /* encode the resulting file */ -int pfbflag = 0; /* produce compressed file */ -int wantafm=0; /* want to see .afm instead of .t1a on stdout */ -int correctvsize=0; /* try to correct the vertical size of characters */ -int wantuid = 0; /* user wants UniqueID entry in the font */ -int allglyphs = 0; /* convert all glyphs, not only 256 of them */ -int warnlevel = 3; /* the level of permitted warnings */ -int forcemap = 0; /* do mapping even on non-Unicode fonts */ -/* options - maximal limits */ -int max_stemdepth = 128; /* maximal depth of stem stack in interpreter (128 - limit from X11) */ -/* options - debugging */ -int absolute = 0; /* print out in absolute values */ -int reverse = 1; /* reverse font to Type1 path directions */ -/* options - suboptions of Outline Processing, defaults are set in table */ -int optimize; /* enables space optimization */ -int smooth; /* enable smoothing of outlines */ -int transform; /* enables transformation to 1000x1000 matrix */ -int hints; /* enables autogeneration of hints */ -int subhints; /* enables autogeneration of substituted hints */ -int trybold; /* try to guess whether the font is bold */ -int correctwidth; /* try to correct the character width */ -int vectorize; /* vectorize the bitmaps */ -int use_autotrace; /* use the autotrace library on bitmap */ -/* options - suboptions of File Generation, defaults are set in table */ -int gen_pfa; /* generate the font file */ -int gen_afm; /* generate the metrics file */ -int gen_dvienc; /* generate the dvips encoding file */ - -/* not quite options to select a particular source encoding */ -int force_pid = -1; /* specific platform id */ -int force_eid = -1; /* specific encoding id */ - -/* structure to define the sub-option lists controlled by the - * case: uppercase enables them, lowercase disables - */ -struct subo_case { - char disbl; /* character to disable - enforced lowercase */ - char enbl; /* character to enable - auto-set as toupper(disbl) */ - int *valp; /* pointer to the actual variable containing value */ - int dflt; /* default value */ - char *descr; /* description */ -}; - -int debug = DEBUG; /* debugging flag */ - -FILE *null_file, *pfa_file, *afm_file, *dvienc_file; -int numglyphs; -struct font_metrics fontm; - -/* non-globals */ -static char *strUID = 0; /* user-supplied UniqueID */ -static unsigned long numUID; /* auto-generated UniqueID */ - -static int ps_fmt_3 = 0; -static double scale_factor, original_scale_factor; - -static char *glyph_rename[ENCTABSZ]; - -/* the names assigned if the original font - * does not specify any - */ - -static char *Fmt3Encoding[256] = { - "c0", "c1", "c2", "c3", - "c4", "c5", "c6", "c7", - "c8", "c9", "c10", "c11", - "c12", "CR", "c14", "c15", - "c16", "c17", "c18", "c19", - "c20", "c21", "c22", "c23", - "c24", "c25", "c26", "c27", - "c28", "c29", "c30", "c31", - "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", "c127", - "c128", "c129", "quotesinglbase", "florin", - "quotedblbase", "ellipsis", "dagger", "daggerdbl", - "circumflex", "perthousand", "Scaron", "guilsinglleft", - "OE", "c141", "c142", "c143", - "c144", "quoteleft", "quoteright", "quotedblleft", - "quotedblright", "bullet", "endash", "emdash", - "tilde", "trademark", "scaron", "guilsinglright", - "oe", "c157", "c158", "Ydieresis", - "nbspace", "exclamdown", "cent", "sterling", - "currency", "yen", "brokenbar", "section", - "dieresis", "copyright", "ordfeminine", "guillemotleft", - "logicalnot", "sfthyphen", "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" -}; - -#ifdef notdef /* { */ -/* This table is not used anywhere in the code - * so it's ifdef-ed out by default but left in - * the source code for reference purposes (and - * possibly for future use) - */ - -static char *ISOLatin1Encoding[256] = { - ".null", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "CR", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".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", - "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", "c127", - "c128", "c129", "quotesinglbase", "florin", - "quotedblbase", "ellipsis", "dagger", "daggerdbl", - "circumflex", "perthousand", "Scaron", "guilsinglleft", - "OE", "c141", "c142", "c143", - "c144", "quoteleft", "quoteright", "quotedblleft", - "quotedblright", "bullet", "endash", "emdash", - "tilde", "trademark", "scaron", "guilsinglright", - "oe", "c157", "c158", "Ydieresis", - "nbspace", "exclamdown", "cent", "sterling", - "currency", "yen", "brokenbar", "section", - "dieresis", "copyright", "ordfeminine", "guillemotleft", - "logicalnot", "sfthyphen", "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" -}; - -#endif /* } notdef */ - -static char *adobe_StandardEncoding[256] = { - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".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", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "exclamdown", "cent", "sterling", - "fraction", "yen", "florin", "section", - "currency", "quotesingle", "quotedblleft", "guillemotleft", - "guilsinglleft", "guilsinglright", "fi", "fl", - ".notdef", "endash", "dagger", "daggerdbl", - "periodcentered", ".notdef", "paragraph", "bullet", - "quotesinglbase", "quotedblbase", "quotedblright", "guillemotright", - "ellipsis", "perthousand", ".notdef", "questiondown", - ".notdef", "grave", "acute", "circumflex", - "tilde", "macron", "breve", "dotaccent", - "dieresis", ".notdef", "ring", "cedilla", - ".notdef", "hungarumlaut", "ogonek", "caron", - "emdash", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "AE", ".notdef", "ordfeminine", - ".notdef", ".notdef", ".notdef", ".notdef", - "Lslash", "Oslash", "OE", "ordmasculine", - ".notdef", ".notdef", ".notdef", ".notdef", - ".notdef", "ae", ".notdef", ".notdef", - ".notdef", "dotlessi", ".notdef", ".notdef", - "lslash", "oslash", "oe", "germandbls", - ".notdef", ".notdef", ".notdef", ".notdef" -}; - -/* - * Decription of the supported conversions from Unicode - * - * SB - * Yes, I know that the compiled-in conversion is stupid but - * it is simple to implement and allows not to worry about the - * filesystem context. After all, the source is always available - * and adding another language to it is easy. - * - * The language name is expected to be the same as the subdirectory name - * in the `encodings' directory (for possible future extensions). - * The primary use of the aliases is for guessing based on the current - * locale. - */ - -#define MAXUNIALIAS 10 -#define MAXUNITABLES 3 - -/* the character used as the language argument separator */ -#define LANG_ARG_SEP '+' - - -/* - * Types of language-related routines. Arguments are: - * name is the glyph name - * arg is the user-specified language-dependent argument - * which can for example select the subfont plane for Eastern fonts. - * If none is supplied by user then an empty string ("") is passed. - * If no language is specified by user and auto-guessing happens - * then NULL is passed. - * when shows if the conversion by name was called before conversion by - * map or after (it's called twice) - */ - -/* type of the Unicode map initialization routine */ -typedef void uni_init_t(char *arg); - -/* type of Unicode converter-by-name function - * it's called for each glyph twice: one time for each glyph - * before doing conversion by map and one time after - */ -typedef int uni_conv_t(char *name, char *arg, int when); -#define UNICONV_BYNAME_BEFORE 0 -#define UNICONV_BYNAME_AFTER 1 - -struct uni_language { - uni_init_t *init[MAXUNITABLES]; /* map initialization routines */ - uni_conv_t *convbyname; /* the name-based conversion function */ - char *name; /* the language name */ - char *descr; /* description */ - char *alias[MAXUNIALIAS]; /* aliases of the language name */ - int sample_upper; /* code of some uppercase character for correctvsize() */ -}; - -/* the converter routines have an option of adding this suffix to the font name */ -static char *uni_font_name_suffix = ""; /* empty by default */ -/* this buffer may be used to store the suffix */ -#define UNI_MAX_SUFFIX_LEN 100 -static char uni_suffix_buf[UNI_MAX_SUFFIX_LEN+1]; - -/* - * Prototypes of the conversion routines - */ - -static uni_init_t unicode_latin1; -static uni_init_t unicode_latin2; -static uni_init_t unicode_latin4; -static uni_init_t unicode_latin5; -static uni_init_t unicode_cyrillic; -static uni_init_t unicode_adobestd; -static uni_init_t unicode_plane; -static uni_conv_t unicode_adobestd_byname; - -static uni_init_t unicode_init_user; - -/* - * The order of descriptions is important: if we can't guess the - * language we just call all the conversion routines in order until - * we find one that understands this glyph. - */ -static struct uni_language uni_lang[]= { - /* pseudo-language for all the languages using Latin1 */ - { - { unicode_latin1 }, - 0, /* no name-based mapping */ - "latin1", - "works for most of the Western languages", - { "en_", "de_", "fr_", "nl_", "no_", "da_", "it_" }, - 'A' - }, - { /* by Szalay Tamas */ - { unicode_latin2 }, - 0, /* no name-based mapping */ - "latin2", - "works for Central European languages", - { "hu_","pl_","cz_","si_","sk_" }, - 'A' - }, - { /* by Rièardas Èepas */ - { unicode_latin4 }, - 0, /* no name-based mapping */ - "latin4", - "works for Baltic languages", - { "lt_", "lv_" }, /* doubt about ee_ */ - 'A' - }, - { /* by Turgut Uyar */ - { unicode_latin5 }, - 0, /* no name-based mapping */ - "latin5", - "for Turkish", - { "tr_" }, - 'A' - }, - { /* by Zvezdan Petkovic */ - { unicode_cyrillic, unicode_latin1 }, - 0, /* no name-based mapping */ - "cyrillic", - "in Windows encoding", - { "bg_", "be_", "mk_", "ru_", "sr_", "su_", "uk_" }, - 'A' - }, - { - { unicode_cyrillic, unicode_latin1 }, - 0, /* no name-based mapping */ - "russian", - "obsolete, use cyrillic instead", - { 0 }, - 'A' - }, - { - { unicode_cyrillic, unicode_latin1 }, - 0, /* no name-based mapping */ - "bulgarian", - "obsolete, use cyrillic instead", - { 0 }, - 'A' - }, - { - { unicode_adobestd }, - unicode_adobestd_byname, - "adobestd", - "Adobe Standard, expected by TeX", - { NULL }, - 'A' - }, - { - { unicode_plane }, - 0, /* no name-based mapping */ - "plane", - "one plane of Unicode or other multi-byte encoding as is", - { NULL }, - 0 /* no easy way to predict the capital letters */ - }, -}; - -static struct uni_language uni_lang_user = { - { unicode_init_user }, - 0, /* no name-based mapping */ - 0, /* no name */ - 0, /* no description */ - { 0 }, - 0 /* no sample */ -}; - -static struct uni_language *uni_lang_selected=0; /* 0 means "unknown, try all" */ -static int uni_sample='A'; /* sample of an uppercase character */ -static char *uni_lang_arg=""; /* user-supplied language-dependent argument */ - -extern int runt1asm(int); - -/* - * user-defined loadable maps - */ - - -/* The idea begind buckets is to avoid comparing every code with all ENCTABSZ codes in table. - * All the 16-bit unicode space is divided between a number of equal-sized buckets. - * Initially all the buckets are marked with 0. Then if any code in the bucket is - * used it's marked with 1. Later during translation we check the code's bucket first - * and it it's 0 then return failure right away. This may be useful for - * Chinese fonts with many thousands of glyphs. - */ - -#define BUCKET_ID_BITS 11 -#define MARK_UNI_BUCKET(unicode) SET_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS)) -#define IS_UNI_BUCKET(unicode) IS_BITMAP(uni_user_buckets, (unicode)>>(16-BUCKET_ID_BITS)) - -static DEF_BITMAP(uni_user_buckets, 1< UNI_MAX_SUFFIX_LEN-1) - arg = NULL; - else { - sprintf(uni_suffix_buf, "-%s", arg); - uni_font_name_suffix = uni_suffix_buf; - } - } - - /* now read in the encoding description file, if requested */ - if ((unicode_map_file = fopen(path, "rb")) == NULL) { - fprintf(stderr, "**** Cannot access map file '%s' ****\n", path); - exit(1); - } - - sawplane = 0; - if(arg==NULL) - enabled = found = 1; - else - enabled = found = 0; - - lineno=0; curpos=0; - while (fgets (buffer, UNIBFSZ, unicode_map_file) != NULL) { - char name[UNIBFSZ]; - - lineno++; - - if(sscanf(buffer, "plane %s", name)==1) { - sawplane = 1; - if(arg == 0) { - fprintf(stderr, "**** map file '%s' requires plane name\n", path); - fprintf(stderr, "for example:\n"); - fprintf(stderr, " ttf2pt1 -L %s%c[pid=N,eid=N,]%s ...\n", - path, LANG_ARG_SEP, name); - fprintf(stderr, "to select plane '%s'\n", name); - exit(1); - } - if( !strcmp(arg, name) ) { - enabled = found = 1; - curpos = 0; - } else { - enabled = 0; - if(found) /* no need to read further */ - break; - } - continue; - } - - if(sscanf(buffer, "id %d %d", pid, eid)==2) { - if( !overid /* only if the user has not overriden */ - && (enabled || !sawplane) ) { - force_pid = pid; force_eid = eid; - forcemap = 1; - } - continue; - } - - if( !enabled ) - continue; /* skip to the next plane */ - - if( sscanf(buffer, "at %i", &curpos) == 1 ) { - if(curpos > 255) { - fprintf(stderr, "**** map file '%s' line %d: code over 255\n", path, lineno); - exit(1); - } - if(ISDBG(EXTMAP)) fprintf(stderr, "=== at 0x%x\n", curpos); - continue; - } - - /* try the format of Roman Czyborra's files */ - if ( sscanf (buffer, " =%x U+%4x", &code, &unicode) == 2 - /* try the format of Linux locale charmap file */ - || sscanf (buffer, " <%*s /x%x ", &code, &unicode) == 2 ) { - if (code < ENCTABSZ) { - if(code >= enctabsz) enctabsz=code+1; - unicode_map[code] = unicode; - glyph_rename[code] = NULL; - } - } - /* try the format with glyph renaming */ - else if (sscanf (buffer, " !%x U+%4x %128s", &code, - &unicode, name) == 3) { - if (code < ENCTABSZ) { - if(code >= enctabsz) enctabsz=code+1; - unicode_map[code] = unicode; - glyph_rename[code] = strdup(name); - } - } - /* try the compact sequence format */ - else if( (n=sscanf(buffer, " %i%n", &unicode, &cnt)) == 1 ) { - p = buffer; - do { - if(curpos > 255) { - fprintf(stderr, "**** map file '%s' line %d: code over 255 for unicode 0x%x\n", - path, lineno, unicode); - exit(1); - } - if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%d -> 0x%x\n", curpos, unicode); - unicode_map[curpos++] = unicode; - p += cnt; - if( sscanf(p, " %[,-]%n", &next,&cnt) == 1 ) { - if(ISDBG(EXTMAP)) fprintf(stderr, "=== next: '%c'\n", next); - p += cnt; - if( next == '-' ) { /* range */ - if ( sscanf(p, " %i%n", &unicode2, &cnt) != 1 ) { - fprintf(stderr, "**** map file '%s' line %d: missing end of range\n", path, lineno); - exit(1); - } - p += cnt; - if(ISDBG(EXTMAP)) fprintf(stderr, "=== range 0x%x to 0x%x\n", unicode, unicode2); - for(unicode++; unicode <= unicode2; unicode++) { - if(curpos > 255) { - fprintf(stderr, "**** map file '%s' line %d: code over 255 in unicode range ...-0x%x\n", - path, lineno, unicode2); - exit(1); - } - if(ISDBG(EXTMAP)) fprintf(stderr, "=== 0x%x -> 0x%x\n", curpos, unicode); - unicode_map[curpos++] = unicode; - } - } - } - } while ( sscanf(p, " %i%n", &unicode, &cnt) == 1 ); - } - - } - - fclose (unicode_map_file); - - if( !found ) { - fprintf(stderr, "**** map file '%s' has no plane '%s'\n", path, arg); - exit(1); - } - - if(unicode_map['A'] == 'A') - uni_sample = 'A'; /* seems to be compatible with Latin */ - else - uni_sample = 0; /* don't make any assumptions */ -} - -/* - * by Zvezdan Petkovic - */ -static void -unicode_cyrillic( - char *arg -) -{ - int i; - static unsigned int cyrillic_unicode_map[] = { - 0x0402, 0x0403, 0x201a, 0x0453, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x20ac, 0x2030, 0x0409, 0x2039, 0x040a, 0x040c, 0x040b, 0x040f, /* 88 */ - 0x0452, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, 0x0459, 0x203a, 0x045a, 0x045c, 0x045b, 0x045f, /* 98 */ - 0x00a0, 0x040e, 0x045e, 0x0408, 0x00a4, 0x0490, 0x00a6, 0x00a7, /* A0 */ - 0x0401, 0x00a9, 0x0404, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x0407, /* A8 */ - 0x00b0, 0x00b1, 0x0406, 0x0456, 0x0491, 0x00b5, 0x00b6, 0x00b7, /* B0 */ - 0x0451, 0x2116, 0x0454, 0x00bb, 0x0458, 0x0405, 0x0455, 0x0457, /* B8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0xBF; i++) - unicode_map[i] = cyrillic_unicode_map[i-0x80]; - - for(i=0xC0; i<=0xFF; i++) - unicode_map[i] = i+0x350; - -} - -static void -unicode_latin1( - char *arg -) -{ - int i; - static unsigned int latin1_unicode_map[] = { - 0x20ac, -1, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x017d, 0x008f, /* 88 */ - 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x017e, 0x0178, /* 98 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0x9F; i++) - unicode_map[i] = latin1_unicode_map[i-0x80]; - - for(i=0xA0; i<=0xFF; i++) - unicode_map[i] = i; -} - -static void -unicode_adobestd( - char *arg -) -{ - int i; - static unsigned int adobestd_unicode_map[] = { - -1, 0x00a1, 0x00a2, 0x00a3, 0x2215, 0x00a5, 0x0192, 0x00a7, /* A0 */ - 0x00a4, 0x0027, 0x201c, 0x00ab, 0x2039, 0x203a, 0xfb01, 0xfb02, /* A8 */ - -1, 0x2013, 0x2020, 0x2021, 0x2219, -1, 0x00b6, 0x2022, /* B0 */ - 0x201a, 0x201e, 0x201d, 0x00bb, 0x2026, 0x2030, -1, 0x00bf, /* B8 */ - -1, 0x0060, 0x00b4, 0x02c6, 0x02dc, 0x02c9, 0x02d8, 0x02d9, /* C0 */ - 0x00a8, -1, 0x02da, 0x00b8, -1, 0x02dd, 0x02db, 0x02c7, /* C8 */ - 0x2014, -1, -1, -1, -1, -1, -1, -1, /* D0 */ - -1, -1, -1, -1, -1, -1, -1, -1, /* D8 */ - -1, 0x00c6, -1, 0x00aa, -1, -1, -1, -1, /* E0 */ - 0x0141, 0x00d8, 0x0152, 0x00ba, -1, -1, -1, -1, /* E8 */ - -1, 0x00e6, -1, -1, -1, 0x0131, -1, -1, /* F0 */ - 0x0142, 0x00f8, 0x0153, 0x00df, -1, -1, -1, -1, /* F8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - unicode_map[0x27] = 0x2019; - unicode_map[0x60] = -1; - - /* 0x80 to 0x9F is a hole */ - - for(i=0xA0; i<=0xFF; i++) - unicode_map[i] = adobestd_unicode_map[i-0xA0]; -} - -/* - * Not all of the Adobe glyphs are in the Unicode - * standard maps, so the font creators have - * different ideas about their codes. Because - * of this we try to map based on the glyph - * names instead of Unicode codes. If there are - * no glyph names (ps_fmt_3!=0) we fall back - * to the code-based scheme. - */ - -static int -unicode_adobestd_byname( - char *name, - char *arg, - int where -) -{ - int i; - - /* names always take precedence over codes */ - if(where == UNICONV_BYNAME_AFTER) - return -1; - - for(i=32; i<256; i++) { - if(!strcmp(name, adobe_StandardEncoding[i])) - return i; - } - return -1; - -} - -static void -unicode_latin2( - char *arg -) -{ - int i; - static unsigned int latin2_unicode_map[] = { - 0x00a0, 0x0104, 0x02d8, 0x0141, 0x00a4, 0x013d, 0x015a, 0x00a7, /* A0 */ - 0x00a8, 0x0160, 0x015e, 0x0164, 0x0179, 0x00ad, 0x017d, 0x017b, /* A8 */ - 0x00b0, 0x0105, 0x02db, 0x0142, 0x00b4, 0x013e, 0x015b, 0x02c7, /* B0 */ - 0x00b8, 0x0161, 0x015f, 0x0165, 0x017a, 0x02dd, 0x017e, 0x017c, /* B8 */ - 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7, /* C0 */ - 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e, /* C8 */ - 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7, /* D0 */ - 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df, /* D8 */ - 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7, /* E0 */ - 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f, /* E8 */ - 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7, /* F0 */ - 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9, /* F8 */ - }; - - for(i=0; i<=0x7E; i++) - unicode_map[i] = i; - - /* 7F-9F are unused */ - - for(i=0xA0; i<=0xFF; i++) - unicode_map[i] = latin2_unicode_map[i-0xA0]; -} - -static void -unicode_latin4( - char *arg -) -{ - int i; - static unsigned int latin4_unicode_map[] = { - 0x0080, 0x0081, 0x201a, 0x0192, -1, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x02c6, 0x2030, -1, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */ - 0x201e, 0x201c, 0x2019, -1, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, -1, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */ - 0x00a0, 0x0104, 0x0138, 0x0156, 0x00a4, 0x0128, 0x013b, 0x00a7, /* A0 */ - 0x00a8, 0x0160, 0x0112, 0x0122, 0x0166, 0x00ad, 0x017d, 0x00af, /* A8 */ - 0x00b0, 0x0105, 0x02db, 0x0157, 0x00b4, 0x0129, 0x013c, 0x02c7, /* B0 */ - 0x00b8, 0x0161, 0x0113, 0x0123, 0x0167, 0x014a, 0x017e, 0x014b, /* B8 */ - 0x0100, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x012e, /* C0 */ - 0x010c, 0x00c9, 0x0118, 0x00cb, 0x0116, 0x00cd, 0x00ce, 0x012a, /* C8 */ - 0x0110, 0x0145, 0x014c, 0x0136, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */ - 0x00d8, 0x0172, 0x00da, 0x00db, 0x00dc, 0x0168, 0x016a, 0x00df, /* D8 */ - 0x0101, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x012f, /* E0 */ - 0x010d, 0x00e9, 0x0119, 0x00eb, 0x0117, 0x00ed, 0x00ee, 0x012b, /* E8 */ - 0x0111, 0x0146, 0x014d, 0x0137, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */ - 0x00f8, 0x0173, 0x00fa, 0x00fb, 0x00fc, 0x0169, 0x016b, 0x02d9, /* F8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0xFF; i++) - unicode_map[i] = latin4_unicode_map[i-0x80]; - -#if 0 /* for documentation purposes only */ - case 0x201e: return 0x90; /* these two quotes are a hack only */ - case 0x201c: return 0x91; /* these two quotes are a hack only */ - case 0x00A0: return 0xA0; /* NO-BREAK SPACE */ - case 0x0104: return 0xA1; /* LATIN CAPITAL LETTER A WITH OGONEK */ - case 0x0138: return 0xA2; /* LATIN SMALL LETTER KRA */ - case 0x0156: return 0xA3; /* LATIN CAPITAL LETTER R WITH CEDILLA */ - case 0x00A4: return 0xA4; /* CURRENCY SIGN */ - case 0x0128: return 0xA5; /* LATIN CAPITAL LETTER I WITH TILDE */ - case 0x013B: return 0xA6; /* LATIN CAPITAL LETTER L WITH CEDILLA */ - case 0x00A7: return 0xA7; /* SECTION SIGN */ - case 0x00A8: return 0xA8; /* DIAERESIS */ - case 0x0160: return 0xA9; /* LATIN CAPITAL LETTER S WITH CARON */ - case 0x0112: return 0xAA; /* LATIN CAPITAL LETTER E WITH MACRON */ - case 0x0122: return 0xAB; /* LATIN CAPITAL LETTER G WITH CEDILLA */ - case 0x0166: return 0xAC; /* LATIN CAPITAL LETTER T WITH STROKE */ - case 0x00AD: return 0xAD; /* SOFT HYPHEN */ - case 0x017D: return 0xAE; /* LATIN CAPITAL LETTER Z WITH CARON */ - case 0x00AF: return 0xAF; /* MACRON */ - case 0x00B0: return 0xB0; /* DEGREE SIGN */ - case 0x0105: return 0xB1; /* LATIN SMALL LETTER A WITH OGONEK */ - case 0x02DB: return 0xB2; /* OGONEK */ - case 0x0157: return 0xB3; /* LATIN SMALL LETTER R WITH CEDILLA */ - case 0x00B4: return 0xB4; /* ACUTE ACCENT */ - case 0x0129: return 0xB5; /* LATIN SMALL LETTER I WITH TILDE */ - case 0x013C: return 0xB6; /* LATIN SMALL LETTER L WITH CEDILLA */ - case 0x02C7: return 0xB7; /* CARON */ - case 0x00B8: return 0xB8; /* CEDILLA */ - case 0x0161: return 0xB9; /* LATIN SMALL LETTER S WITH CARON */ - case 0x0113: return 0xBA; /* LATIN SMALL LETTER E WITH MACRON */ - case 0x0123: return 0xBB; /* LATIN SMALL LETTER G WITH CEDILLA */ - case 0x0167: return 0xBC; /* LATIN SMALL LETTER T WITH STROKE */ - case 0x014A: return 0xBD; /* LATIN CAPITAL LETTER ENG */ - case 0x017E: return 0xBE; /* LATIN SMALL LETTER Z WITH CARON */ - case 0x014B: return 0xBF; /* LATIN SMALL LETTER ENG */ - case 0x0100: return 0xC0; /* LATIN CAPITAL LETTER A WITH MACRON */ - case 0x00C1: return 0xC1; /* LATIN CAPITAL LETTER A WITH ACUTE */ - case 0x00C2: return 0xC2; /* LATIN CAPITAL LETTER A WITH CIRCUMFLEX */ - case 0x00C3: return 0xC3; /* LATIN CAPITAL LETTER A WITH TILDE */ - case 0x00C4: return 0xC4; /* LATIN CAPITAL LETTER A WITH DIAERESIS */ - case 0x00C5: return 0xC5; /* LATIN CAPITAL LETTER A WITH RING ABOVE */ - case 0x00C6: return 0xC6; /* LATIN CAPITAL LIGATURE AE */ - case 0x012E: return 0xC7; /* LATIN CAPITAL LETTER I WITH OGONEK */ - case 0x010C: return 0xC8; /* LATIN CAPITAL LETTER C WITH CARON */ - case 0x00C9: return 0xC9; /* LATIN CAPITAL LETTER E WITH ACUTE */ - case 0x0118: return 0xCA; /* LATIN CAPITAL LETTER E WITH OGONEK */ - case 0x00CB: return 0xCB; /* LATIN CAPITAL LETTER E WITH DIAERESIS */ - case 0x0116: return 0xCC; /* LATIN CAPITAL LETTER E WITH DOT ABOVE */ - case 0x00CD: return 0xCD; /* LATIN CAPITAL LETTER I WITH ACUTE */ - case 0x00CE: return 0xCE; /* LATIN CAPITAL LETTER I WITH CIRCUMFLEX */ - case 0x012A: return 0xCF; /* LATIN CAPITAL LETTER I WITH MACRON */ - case 0x0110: return 0xD0; /* LATIN CAPITAL LETTER D WITH STROKE */ - case 0x0145: return 0xD1; /* LATIN CAPITAL LETTER N WITH CEDILLA */ - case 0x014C: return 0xD2; /* LATIN CAPITAL LETTER O WITH MACRON */ - case 0x0136: return 0xD3; /* LATIN CAPITAL LETTER K WITH CEDILLA */ - case 0x00D4: return 0xD4; /* LATIN CAPITAL LETTER O WITH CIRCUMFLEX */ - case 0x00D5: return 0xD5; /* LATIN CAPITAL LETTER O WITH TILDE */ - case 0x00D6: return 0xD6; /* LATIN CAPITAL LETTER O WITH DIAERESIS */ - case 0x00D7: return 0xD7; /* MULTIPLICATION SIGN */ - case 0x00D8: return 0xD8; /* LATIN CAPITAL LETTER O WITH STROKE */ - case 0x0172: return 0xD9; /* LATIN CAPITAL LETTER U WITH OGONEK */ - case 0x00DA: return 0xDA; /* LATIN CAPITAL LETTER U WITH ACUTE */ - case 0x00DB: return 0xDB; /* LATIN CAPITAL LETTER U WITH CIRCUMFLEX */ - case 0x00DC: return 0xDC; /* LATIN CAPITAL LETTER U WITH DIAERESIS */ - case 0x0168: return 0xDD; /* LATIN CAPITAL LETTER U WITH TILDE */ - case 0x016A: return 0xDE; /* LATIN CAPITAL LETTER U WITH MACRON */ - case 0x00DF: return 0xDF; /* LATIN SMALL LETTER SHARP S */ - case 0x0101: return 0xE0; /* LATIN SMALL LETTER A WITH MACRON */ - case 0x00E1: return 0xE1; /* LATIN SMALL LETTER A WITH ACUTE */ - case 0x00E2: return 0xE2; /* LATIN SMALL LETTER A WITH CIRCUMFLEX */ - case 0x00E3: return 0xE3; /* LATIN SMALL LETTER A WITH TILDE */ - case 0x00E4: return 0xE4; /* LATIN SMALL LETTER A WITH DIAERESIS */ - case 0x00E5: return 0xE5; /* LATIN SMALL LETTER A WITH RING ABOVE */ - case 0x00E6: return 0xE6; /* LATIN SMALL LIGATURE AE */ - case 0x012F: return 0xE7; /* LATIN SMALL LETTER I WITH OGONEK */ - case 0x010D: return 0xE8; /* LATIN SMALL LETTER C WITH CARON */ - case 0x00E9: return 0xE9; /* LATIN SMALL LETTER E WITH ACUTE */ - case 0x0119: return 0xEA; /* LATIN SMALL LETTER E WITH OGONEK */ - case 0x00EB: return 0xEB; /* LATIN SMALL LETTER E WITH DIAERESIS */ - case 0x0117: return 0xEC; /* LATIN SMALL LETTER E WITH DOT ABOVE */ - case 0x00ED: return 0xED; /* LATIN SMALL LETTER I WITH ACUTE */ - case 0x00EE: return 0xEE; /* LATIN SMALL LETTER I WITH CIRCUMFLEX */ - case 0x012B: return 0xEF; /* LATIN SMALL LETTER I WITH MACRON */ - case 0x0111: return 0xF0; /* LATIN SMALL LETTER D WITH STROKE */ - case 0x0146: return 0xF1; /* LATIN SMALL LETTER N WITH CEDILLA */ - case 0x014D: return 0xF2; /* LATIN SMALL LETTER O WITH MACRON */ - case 0x0137: return 0xF3; /* LATIN SMALL LETTER K WITH CEDILLA */ - case 0x00F4: return 0xF4; /* LATIN SMALL LETTER O WITH CIRCUMFLEX */ - case 0x00F5: return 0xF5; /* LATIN SMALL LETTER O WITH TILDE */ - case 0x00F6: return 0xF6; /* LATIN SMALL LETTER O WITH DIAERESIS */ - case 0x00F7: return 0xF7; /* DIVISION SIGN */ - case 0x00F8: return 0xF8; /* LATIN SMALL LETTER O WITH STROKE */ - case 0x0173: return 0xF9; /* LATIN SMALL LETTER U WITH OGONEK */ - case 0x00FA: return 0xFA; /* LATIN SMALL LETTER U WITH ACUTE */ - case 0x00FB: return 0xFB; /* LATIN SMALL LETTER U WITH CIRCUMFLEX */ - case 0x00FC: return 0xFC; /* LATIN SMALL LETTER U WITH DIAERESIS */ - case 0x0169: return 0xFD; /* LATIN SMALL LETTER U WITH TILDE */ - case 0x016B: return 0xFE; /* LATIN SMALL LETTER U WITH MACRON */ - case 0x02D9: return 0xFF; /* DOT ABOVE */ -#endif -} - -static void -unicode_latin5( - char *arg -) -{ - int i; - static unsigned int latin5_unicode_map1[] = { - 0x0080, 0x0081, 0x201a, 0x0192, 0x201e, 0x2026, 0x2020, 0x2021, /* 80 */ - 0x02c6, 0x2030, 0x0160, 0x2039, 0x0152, 0x008d, 0x008e, 0x008f, /* 88 */ - 0x0090, 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014, /* 90 */ - 0x02dc, 0x2122, 0x0161, 0x203a, 0x0153, 0x009d, 0x009e, 0x0178, /* 98 */ - }; - static unsigned int latin5_unicode_map2[] = { - 0x011e, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7, /* D0 */ - 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x0130, 0x015e, 0x00df, /* D8 */ - 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7, /* E0 direct */ - 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef, /* E8 direct */ - 0x011f, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7, /* F0 */ - 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x0131, 0x015f, 0x00ff, /* F8 */ - }; - - for(i=0; i<=0x7F; i++) - unicode_map[i] = i; - - for(i=0x80; i<=0x9F; i++) - unicode_map[i] = latin5_unicode_map1[i-0x80]; - - for(i=0xA0; i<=0xCF; i++) - unicode_map[i] = i; - - for(i=0xD0; i<=0xFF; i++) - unicode_map[i] = latin5_unicode_map2[i-0xD0]; -} - -/* a way to select one 256-character plane from Unicode - * or other multi-byte encoding - */ - -static void -unicode_plane( - char *arg -) -{ - static unsigned plane; - int nchars; - int c1, c2, i; - - if(uni_lang_selected == 0) - return; /* don't participate in auto-guessing */ - - plane = 0; force_pid = force_eid = -1; - - c1 = sscanf(arg, "pid=%d,eid=%d%n", &force_pid, &force_eid, &nchars); - if(c1 == 2) { - arg += nchars; - if(*arg == ',') - arg++; - } - if(arg[0] == '0' && (arg[1]=='x' || arg[1]=='X') ) { - arg += 2; - c2 = sscanf(arg, "%x", &plane); - } else { - c2 = sscanf(arg, "%d", &plane); - } - - if( (c1!=2 && c1!=0) || (c1==0 && c2==0) ) { - fprintf(stderr, "**** option -l plane expects one of the following formats:\n"); - fprintf(stderr, " -l plane+0xNN - select hexadecimal number of plane of Unicode\n"); - fprintf(stderr, " -l plane+NN - select decimal number of plane of Unicode\n"); - fprintf(stderr, " -l plane+pid=N,eid=N - select plane 0 of specified encoding\n"); - fprintf(stderr, " -l plane+pid=N,eid=N,0xNN - select hex plane of TTF encoding with this PID/EID\n"); - fprintf(stderr, " -l plane+pid=N,eid=N,NN - select decimal plane of TTF encoding with this PID/EID\n"); - exit(1); - } - - if(c2!=0) { - if(strlen(arg) > sizeof(uni_suffix_buf)-2) { - fprintf(stderr, "**** plane number is too large\n"); - } - - sprintf(uni_suffix_buf, "-%s", arg); - uni_font_name_suffix = uni_suffix_buf; - } else { - uni_font_name_suffix = ""; - } - - plane <<= 8; - for(i=0; i<=0xFF; i++) - unicode_map[i] = plane | i; -} - -/* look up the 8-bit code by unicode */ - -int -unicode_rev_lookup( - int unival -) -{ - int res; - - if( ! IS_UNI_BUCKET(unival) ) - return -1; - - for (res = 0; res < enctabsz; res++) - if (unicode_map[res] == unival) - return res; - return -1; -} - -/* mark the buckets for quick lookup */ - -static void -unicode_prepare_buckets( - void -) -{ - int i; - - memset(uni_user_buckets, 0, sizeof uni_user_buckets); - for(i=0; i 126) { - sprintf(res+i, "\\x%02X", c); - i+=4; - } else { - res[i++] = c; - } - } - if(*s != 0) { - res[i++] = '.'; - res[i++] = '.'; - res[i++] = '.'; - } - res[i++] = 0; - return res; -} - -/* - * Scale the values according to the scale_factor - */ - -double -fscale( - double val -) -{ - return scale_factor * val; -} - -int -iscale( - int val -) -{ - return (int) (val > 0 ? scale_factor * val + 0.5 - : scale_factor * val - 0.5); -} - -/* - * Try to force fixed width of characters - */ - -static void -alignwidths(void) -{ - int i; - int n = 0, avg, max = 0, min = 3000, sum = 0, x; - - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - x = glyph_list[i].width; - - if (x != 0) { - if (x < min) - min = x; - if (x > max) - max = x; - - sum += x; - n++; - } - } - } - - if (n == 0) - return; - - avg = sum / n; - - WARNING_3 fprintf(stderr, "widths: max=%d avg=%d min=%d\n", max, avg, min); - - /* if less than 5% variation from average */ - /* force fixed width */ - if (20 * (avg - min) < avg && 20 * (max - avg) < avg) { - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) - glyph_list[i].width = avg; - } - fontm.is_fixed_pitch = 1; - } -} - -static void -convert_glyf( - int glyphno -) -{ - GLYPH *g; - int ncurves; - - g = &glyph_list[glyphno]; - - - g->scaledwidth = iscale(g->width); - - g->entries = 0; - g->lastentry = 0; - g->path = 0; - if (g->ttf_pathlen != 0) { - cursw->glpath(glyphno, glyph_list); - g->lastentry = 0; - - if(ISDBG(BUILDG)) - dumppaths(g, NULL, NULL); - - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fclosepaths(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - /* float processing */ - if(smooth) { - ffixquadrants(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fsplitzigzags(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fforceconcise(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - - fstraighten(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - } - - pathtoint(g); - /* all processing past this point expects integer path */ - assertpath(g->entries, __FILE__, __LINE__, g->name); - -#if 0 - fixcontours(g); - testfixcvdir(g); -#endif - - /* int processing */ - if (smooth) { - smoothjoints(g); - assertpath(g->entries, __FILE__, __LINE__, g->name); - } - - ncurves = 0; - { - GENTRY *ge; - for(ge = g->entries; ge; ge = ge->next) - ncurves++; - } - if (ncurves > 200) { - WARNING_3 fprintf(stderr, - "** Glyph %s is too long, may display incorrectly\n", - g->name); - } - } else { - /* for buildstems */ - g->flags &= ~GF_FLOAT; - } -} - -static void -handle_gnames(void) -{ - int i, n, found, c, type; - - /* get the names from the font file */ - ps_fmt_3 = cursw->glnames(glyph_list); - - /* check for names with wrong characters */ - for (n = 0; n < numglyphs; n++) { - int c; - for (i = 0; (c = glyph_list[n].name[i]) != 0; i++) { - if (!(isalnum(c) || c == '.' || c == '_' || c == '-') - || i==0 && isdigit(c)) { /* must not start with a digit */ - WARNING_3 fprintf(stderr, "Glyph %d %s (%s), ", - n, isdigit(c) ? "name starts with a digit" : - "has bad characters in name", - nametoprint(glyph_list[n].name)); - glyph_list[n].name = malloc(16); - sprintf(glyph_list[n].name, "_b_%d", n); - WARNING_3 fprintf(stderr, "changing to %s\n", glyph_list[n].name); - break; - } - } - } - - if( !ps_fmt_3 ) { - /* check for duplicate names */ - for (n = 0; n < numglyphs; n++) { - found = 0; - for (i = 0; i < n && !found; i++) { - if (strcmp(glyph_list[i].name, glyph_list[n].name) == 0) { - if (( glyph_list[n].name = malloc(16) )==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - sprintf(glyph_list[n].name, "_d_%d", n); - - /* if the font has no names in it (what the native parser - * recognises as ps_fmt_3), FreeType returns all the - * names as .notdef, so don't complain in this case - */ - if(strcmp(glyph_list[i].name, ".notdef")) { - WARNING_3 fprintf(stderr, - "Glyph %d has the same name as %d: (%s), changing to %s\n", - n, i, - glyph_list[i].name, - glyph_list[n].name); - } - found = 1; - } - } - } - - } - - /* start the encoding stuff */ - for (i = 0; i < ENCTABSZ; i++) { - encoding[i] = -1; - } - - /* do the 1st round of encoding by name */ - if(!ps_fmt_3 && uni_lang_selected && uni_lang_selected->convbyname) { - for (n = 0; n < numglyphs; n++) { - c = uni_lang_selected->convbyname(glyph_list[n].name, - uni_lang_arg, UNICONV_BYNAME_BEFORE); - if(c>=0 && cinit[i]; i++) { - for (n = 0; n < ENCTABSZ; n++) - unicode_map[n] = -1; - uni_lang_selected->init[i](uni_lang_arg); - unicode_prepare_buckets(); - type = cursw->glenc(glyph_list, encoding, unicode_map); - if( type == 0 ) - /* if we have an 8-bit encoding we don't need more tries */ - break; - } - } else { - /* language is unknown, try the first table of each */ - for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) { - if(uni_lang[i].init[0] == NULL) - continue; - for (n = 0; n < ENCTABSZ; n++) - unicode_map[n] = -1; - uni_lang[i].init[0](uni_lang_arg); - unicode_prepare_buckets(); - type = cursw->glenc(glyph_list, encoding, unicode_map); - if( type == 0 ) - /* if we have an 8-bit encoding we don't need more tries */ - break; - } - } - - if (ps_fmt_3) { - /* get rid of the old names, they are all "UNKNOWN" anyawy */ - for (i = 0; i < numglyphs; i++) { - glyph_list[i].name = 0; - } - if(type == 0) { - /* 8-bit - give 8859/1 names to the first 256 glyphs */ - for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */ - if (encoding[i] > 0) { - glyph_list[encoding[i]].name = Fmt3Encoding[i]; - } - } - } else if(type == 1) { - /* Unicode - give 8859/1 names to the first 256 glyphs of Unicode */ - for (n = 0; n < 256; n++) { /* here 256, not ENCTABSZ */ - i = unicode_rev_lookup(n); - if (i>=0 && encoding[i] > 0) { - glyph_list[encoding[i]].name = Fmt3Encoding[i]; - } - } - } /* for other types of encodings just give generated names */ - /* assign unique names to the rest of the glyphs */ - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].name == 0) { - if (( glyph_list[i].name = malloc(16) )==0) { - fprintf (stderr, "****malloc failed %s line %d\n", __FILE__, __LINE__); - exit(255); - } - sprintf(glyph_list[i].name, "_d_%d", i); - } - } - } - - /* do the 2nd round of encoding by name */ - if(uni_lang_selected && uni_lang_selected->convbyname) { - for (n = 0; n < numglyphs; n++) { - c = uni_lang_selected->convbyname(glyph_list[n].name, - uni_lang_arg, UNICONV_BYNAME_AFTER); - if(c>=0 && c 0) - glyph_list[0].name = ".notdef"; - if(numglyphs > 1) - glyph_list[1].name = ".null"; - - for (i = 0; i < ENCTABSZ; i++) { - if ((encoding[i] != 0) && glyph_rename[i]) { - glyph_list[encoding[i]].name = glyph_rename[i]; - } - } - -} - -static void -usage(void) -{ - -#ifdef _GNU_SOURCE -# define fplop(txt) fputs(txt, stderr); -#else -# define fplop(txt) -#endif - - fputs("Use:\n", stderr); - fputs("ttf2pt1 [-] [-l language | -L file] []\n", stderr); - fputs(" or\n", stderr); - fputs("ttf2pt1 [-] [-l language | -L file] -\n", stderr); - fputs(" or\n", stderr); - fputs("ttf2pt1 [-] [-l language | -L file] - | t1asm > \n", stderr); - - fplop("\n"); - fplop("This build supports both short and long option names,\n"); - fplop("the long options are listed before corresponding short ones\n"); - - fplop(" --all-glyphs\n"); - fputs(" -a - include all glyphs, even those not in the encoding table\n", stderr); - fplop(" --pfb\n"); - fputs(" -b - produce a compressed .pfb file\n", stderr); - fplop(" --debug dbg_suboptions\n"); - fputs(" -d dbg_suboptions - debugging options, run ttf2pt1 -d? for help\n", stderr); - fplop(" --encode\n"); - fputs(" -e - produce a fully encoded .pfa file\n", stderr); - fplop(" --force-unicode\n"); - fputs(" -F - force use of Unicode encoding even if other MS encoding detected\n", stderr); - fplop(" --generate suboptions\n"); - fputs(" -G suboptions - control the file generation, run ttf2pt1 -G? for help\n", stderr); - fplop(" --language language\n"); - fputs(" -l language - convert Unicode to specified language, run ttf2pt1 -l? for list\n", stderr); - fplop(" --language-map file\n"); - fputs(" -L file - convert Unicode according to encoding description file\n", stderr); - fplop(" --limit =\n"); - fputs(" -m = - set maximal limit of given type to value, types:\n", stderr); - fputs(" h - maximal hint stack depth in the PostScript interpreter\n", stderr); - fplop(" --processing suboptions\n"); - fputs(" -O suboptions - control outline processing, run ttf2pt1 -O? for help\n", stderr); - fplop(" --parser name\n"); - fputs(" -p name - use specific front-end parser, run ttf2pt1 -p? for list\n", stderr); - fplop(" --uid id\n"); - fputs(" -u id - use this UniqueID, -u A means autogeneration\n", stderr); - fplop(" --vertical-autoscale size\n"); - fputs(" -v size - scale the font to make uppercase letters >size/1000 high\n", stderr); - fplop(" --version\n"); - fputs(" -V - print ttf2pt1 version number\n", stderr); - fplop(" --warning number\n"); - fputs(" -W number - set the level of permitted warnings (0 - disable)\n", stderr); - fputs("Obsolete options (will be removed in future releases):\n", stderr); - fplop(" --afm\n"); - fputs(" -A - write the .afm file to STDOUT instead of the font, now -GA\n", stderr); - fputs(" -f - don't try to guess the value of the ForceBold hint, now -Ob\n", stderr); - fputs(" -h - disable autogeneration of hints, now -Oh\n", stderr); - fputs(" -H - disable hint substitution, now -Ou\n", stderr); - fputs(" -o - disable outline optimization, now -Oo\n", stderr); - fputs(" -s - disable outline smoothing, now -Os\n", stderr); - fputs(" -t - disable auto-scaling to 1000x1000 standard matrix, now -Ot\n", stderr); - fputs(" -w - correct the glyph widths (use only for buggy fonts), now -OW\n", stderr); - fputs("With no , write to with suffix replaced.\n", stderr); - fputs("The last '-' means 'use STDOUT'.\n", stderr); - -#undef fplop - -} - -static void -printversion(void) -{ - fprintf(stderr, "ttf2pt1 %s\n", TTF2PT1_VERSION); -} - -/* initialize a table of suboptions */ -static void -init_subo_tbl( - struct subo_case *tbl -) -{ - int i; - - for(i=0; tbl[i].disbl != 0; i++) { - tbl[i].disbl = tolower(tbl[i].disbl); - tbl[i].enbl = toupper(tbl[i].disbl); - *(tbl[i].valp) = tbl[i].dflt; - } -} - -/* print the default value of the suboptions */ -static void -print_subo_dflt( - FILE *f, - struct subo_case *tbl -) -{ - int i; - - for(i=0; tbl[i].disbl != 0; i++) { - if(tbl[i].dflt) - putc(tbl[i].enbl, f); - else - putc(tbl[i].disbl, f); - } -} - -/* print the usage message for the suboptions */ -static void -print_subo_usage( - FILE *f, - struct subo_case *tbl -) -{ - int i; - - fprintf(f,"The lowercase suboptions disable features, corresponding\n"); - fprintf(f,"uppercase suboptions enable them. The supported suboptions,\n"); - fprintf(f,"their default states and the features they control are:\n"); - for(i=0; tbl[i].disbl != 0; i++) { - fprintf(f," %c/%c - [%s] %s\n", tbl[i].disbl, tbl[i].enbl, - tbl[i].dflt ? "enabled" : "disabled", tbl[i].descr); - } -} - -/* find and set the entry according to suboption, - * return the found entry (or if not found return NULL) - */ -struct subo_case * -set_subo( - struct subo_case *tbl, - int subopt -) -{ - int i; - - for(i=0; tbl[i].disbl != 0; i++) { - if(subopt == tbl[i].disbl) { - *(tbl[i].valp) = 0; - return &tbl[i]; - } else if(subopt == tbl[i].enbl) { - *(tbl[i].valp) = 1; - return &tbl[i]; - } - } - return NULL; -} - - -int -ttf2pt1_main( - int argc, - char **argv -) -{ - int i, j; - time_t now; - char filename[4096]; - int c,nchars,nmetrics; - int ws; - int forcebold= -1; /* -1 means "don't know" */ - char *lang; - int oc; - int subid; - char *cmdline; -#ifdef _GNU_SOURCE -# define ttf2pt1_getopt(a, b, c, d, e) getopt_long(a, b, c, d, e) - static struct option longopts[] = { - { "afm", 0, NULL, 'A' }, - { "all-glyphs", 0, NULL, 'a' }, - { "pfb", 0, NULL, 'b' }, - { "debug", 1, NULL, 'd' }, - { "encode", 0, NULL, 'e' }, - { "force-unicode", 0, NULL, 'F' }, - { "generate", 1, NULL, 'G' }, - { "language", 1, NULL, 'l' }, - { "language-map", 1, NULL, 'L' }, - { "limit", 1, NULL, 'm' }, - { "processing", 1, NULL, 'O' }, - { "parser", 1, NULL, 'p' }, - { "uid", 1, NULL, 'u' }, - { "vertical-autoscale", 1, NULL, 'v' }, - { "version", 0, NULL, 'V' }, - { "warning", 1, NULL, 'W' }, - { NULL, 0, NULL, 0 } - }; -#else -# define ttf2pt1_getopt(a, b, c, d, e) getopt(a, b, c) -#endif - /* table of Outline Processing (may think also as Optimization) options */ - static struct subo_case opotbl[] = { - { 'b', 0/*auto-set*/, &trybold, 1, "guessing of the ForceBold hint" }, - { 'h', 0/*auto-set*/, &hints, 1, "autogeneration of hints" }, - { 'u', 0/*auto-set*/, &subhints, 1, "hint substitution technique" }, - { 'o', 0/*auto-set*/, &optimize, 1, "space optimization of font files" }, - { 's', 0/*auto-set*/, &smooth, 1, "smoothing and repair of outlines" }, - { 't', 0/*auto-set*/, &transform, 1, "auto-scaling to the standard matrix 1000x1000" }, - { 'w', 0/*auto-set*/, &correctwidth, 0, "correct the glyph widths (use only for buggy fonts)" }, - { 'v', 0/*auto-set*/, &vectorize, 0, "vectorize (trace) the bitmaps" }, -#ifdef USE_AUTOTRACE - { 'z', 0/*auto-set*/, &use_autotrace, 0, "use the autotrace library on bitmaps (works badly)" }, -#endif /*USE_AUTOTRACE*/ - { 0, 0, 0, 0, 0} /* terminator */ - }; - /* table of the File Generation options */ - static struct subo_case fgotbl[] = { - { 'f', 0/*auto-set*/, &gen_pfa, 1, "generate the font file (.t1a, .pfa or .pfb)" }, - { 'a', 0/*auto-set*/, &gen_afm, 1, "generate the Adobe metrics file (.afm)" }, - { 'e', 0/*auto-set*/, &gen_dvienc, 0, "generate the dvips encoding file (.enc)" }, - { 0, 0, 0, 0, 0} /* terminator */ - }; - int *genlast = NULL; - - - init_subo_tbl(opotbl); /* initialize sub-options of -O */ - init_subo_tbl(fgotbl); /* initialize sub-options of -G */ - - /* save the command line for the record - * (we don't bother about escaping the shell special characters) - */ - - j = 0; - for(i=1; ivalp) ) - genlast = s->valp; - } - break; - } - case 'h': - fputs("Warning: option -h is obsolete, use -Oh instead\n", stderr); - hints = 0; - break; - case 'H': - fputs("Warning: meaning of option -H has been changed to its opposite\n", stderr); - fputs("Warning: option -H is obsolete, use -Ou instead\n", stderr); - subhints = 0; - break; - case 'f': - fputs("Warning: option -f is obsolete, use -Ob instead\n", stderr); - trybold = 0; - break; - case 'w': - fputs("Warning: option -w is obsolete, use -OW instead\n", stderr); - correctwidth = 1; - break; - case 'u': - if(wantuid) { - fprintf(stderr, "**** UniqueID may be specified only once ****\n"); - exit(1); - } - wantuid = 1; - if(optarg[0]=='A' && optarg[1]==0) - strUID=0; /* will be generated automatically */ - else { - strUID=optarg; - for(i=0; optarg[i]!=0; i++) - if( !isdigit(optarg[i]) ) { - fprintf(stderr, "**** UniqueID must be numeric or A for automatic ****\n"); - exit(1); - } - } - break; - case 'v': - correctvsize = atoi(optarg); - if(correctvsize <= 0 && correctvsize > 1000) { - fprintf(stderr, "**** wrong vsize '%d', ignored ****\n", correctvsize); - correctvsize=0; - } - break; - case 'p': - if(cursw!=0) { - fprintf(stderr, "**** only one front-end parser be used ****\n"); - exit(1); - } - - { /* separate parser from parser-specific argument */ - char *p = strchr(optarg, LANG_ARG_SEP); - if(p != 0) { - *p = 0; - front_arg = p+1; - } else - front_arg = ""; - } - for(i=0; frontswtab[i] != NULL; i++) - if( !strcmp(frontswtab[i]->name, optarg) ) { - cursw = frontswtab[i]; - break; - } - - if(cursw==0) { - if (strcmp(optarg, "?")) - fprintf(stderr, "**** unknown front-end parser '%s' ****\n", optarg); - fputs("the following front-ends are supported now:\n", stderr); - for(i=0; frontswtab[i] != NULL; i++) { - fprintf(stderr," %s (%s)\n file suffixes: ", - frontswtab[i]->name, - frontswtab[i]->descr ? frontswtab[i]->descr : "no description" - ); - for(j=0; jsuffix[j]) - fprintf(stderr, "%s ", frontswtab[i]->suffix[j]); - fprintf(stderr, "\n"); - } - exit(1); - } - break; - case 'l': - if(uni_lang_selected!=0) { - fprintf(stderr, "**** only one language option may be used ****\n"); - exit(1); - } - - { /* separate language from language-specific argument */ - char *p = strchr(optarg, LANG_ARG_SEP); - if(p != 0) { - *p = 0; - uni_lang_arg = p+1; - } else - uni_lang_arg = ""; - } - for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) - if( !strcmp(uni_lang[i].name, optarg) ) { - uni_lang_selected = &uni_lang[i]; - uni_sample = uni_lang[i].sample_upper; - break; - } - - if(uni_lang_selected==0) { - if (strcmp(optarg, "?")) - fprintf(stderr, "**** unknown language '%s' ****\n", optarg); - fputs(" the following languages are supported now:\n", stderr); - for(i=0; i < sizeof uni_lang/(sizeof uni_lang[0]); i++) - fprintf(stderr," %s (%s)\n", - uni_lang[i].name, - uni_lang[i].descr ? uni_lang[i].descr : "no description" - ); - exit(1); - } - break; - case 'L': - if(uni_lang_selected!=0) { - fprintf(stderr, "**** only one language option may be used ****\n"); - exit(1); - } - uni_lang_selected = &uni_lang_user; - uni_lang_arg = optarg; - break; - case 'V': - printversion(); - exit(0); - break; - default: - usage(); - exit(1); - break; - } - } - - argc-=optind-1; /* the rest of code counts from argv[0] */ - argv+=optind-1; - - if (absolute && encode) { - fprintf(stderr, "**** options -a and -e are incompatible ****\n"); - exit(1); - } - if ((argc != 2) && (argc != 3)) { - usage(); - exit(1); - } - /* try to guess the language by the locale used */ - if(uni_lang_selected==0 && (lang=getenv("LANG"))!=0 ) { - for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) { - if( !strncmp(uni_lang[i].name, lang, strlen(uni_lang[i].name)) ) { - uni_lang_selected = &uni_lang[i]; - goto got_a_language; - } - } - /* no full name ? try aliases */ - for(i=0; i < sizeof uni_lang/sizeof(struct uni_language); i++) { - for(c=0; csuffix[j] - && !strcmp(p, frontswtab[i]->suffix[j]) ) { - cursw = frontswtab[i]; - WARNING_1 fprintf(stderr, "Auto-detected front-end parser '%s'\n", - cursw->name); - WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n"); - break; - } - } - free(s); - } - - if(cursw==0) { - cursw = frontswtab[0]; - WARNING_1 fprintf(stderr, "Can't detect front-end parser, using '%s' by default\n", - cursw->name); - WARNING_1 fprintf(stderr, " (use ttf2pt1 -p? to get the full list of available front-ends)\n"); - } - } - - /* open the input file */ - cursw->open(argv[1], front_arg); - - /* Get base name of output file (if not specified) - * by removing (known) suffixes - */ - if (argc == 2) { - char *p; - argv[2] = strdup (argv[1]); - p = strrchr(argv[2], '.'); - if (p != NULL) - for (j = 0; (j < MAXSUFFIX) && (cursw->suffix[j]); j++) - if (!strcmp(p+1, cursw->suffix[j])) { - *p = '\0'; - break; - } - } - - if ((null_file = fopen(BITBUCKET, "wb")) == NULL) { - fprintf(stderr, "**** Cannot open %s ****\n", - BITBUCKET); - exit(1); - } - if (argv[2][0] == '-' && argv[2][1] == 0) { -#ifdef NOPIPES - if(encode) { - fprintf(stderr, "**** can't write encoded file to stdout ***\n"); - exit(1); - } -#endif /* NOPIPES */ - pfa_file = afm_file = dvienc_file = null_file; - - if(wantafm || genlast == &gen_afm) { /* print .afm instead of .pfa */ - afm_file=stdout; - } else if(genlast == &gen_dvienc) { /* print .enc instead of .pfa */ - dvienc_file=stdout; - } else { - pfa_file=stdout; - } - } else { -#ifndef NOPIPES - snprintf(filename, sizeof filename, "%s.%s", argv[2], encode ? (pfbflag ? "pfb" : "pfa") : "t1a" ); -#else /* NOPIPES */ - snprintf(filename, sizeof filename, "%s.t1a", argv[2]); -#endif /* NOPIPES */ - if(gen_pfa) { - if ((pfa_file = fopen(filename, "wb+")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } else { - WARNING_2 fprintf(stderr, "Creating file %s\n", filename); - } - } else - pfa_file = null_file; - - if(gen_afm) { - snprintf(filename, sizeof filename, "%s.afm", argv[2]) ; - if ((afm_file = fopen(filename, "w+")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } - } else - afm_file = null_file; - - if(gen_dvienc) { - snprintf(filename, sizeof filename, "%s.enc", argv[2]) ; - if ((dvienc_file = fopen(filename, "w+")) == NULL) { - fprintf(stderr, "**** Cannot create %s ****\n", filename); - exit(1); - } - } else - dvienc_file = null_file; - } - - /* - * Now check whether we want a fully encoded .pfa file - */ -#ifndef NOPIPES - if (encode && pfa_file != null_file) { - int p[2]; - extern FILE *ifp, *ofp; /* from t1asm.c */ - - ifp=stdin; //? - ofp=stdout; //? - - if (pipe(p) < 0) { - perror("**** Cannot create pipe ****\n"); - exit(1); - } - ofp = pfa_file; - ifp = fdopen(p[0], "rb"); - if (ifp == NULL) { - perror("**** Cannot use pipe for reading ****\n"); - exit(1); - } - pfa_file = fdopen(p[1], "wb"); - if (pfa_file == NULL) { - perror("**** Cannot use pipe for writing ****\n"); - exit(1); - } - switch (fork()) { - case -1: - perror("**** Cannot fork the assembler process ****\n"); - exit(1); - case 0: /* child */ - fclose(pfa_file); - exit(runt1asm(pfbflag)); - default: /* parent */ - fclose(ifp); fclose(ofp); - } - } -#endif /* NOPIPES */ - - numglyphs = cursw->nglyphs(); - - WARNING_3 fprintf(stderr, "numglyphs = %d\n", numglyphs); - - glyph_list = (GLYPH *) calloc(numglyphs, sizeof(GLYPH)); - - /* initialize non-0 fields */ - for (i = 0; i < numglyphs; i++) { - GLYPH *g; - - g = &glyph_list[i]; - g->char_no = -1; - g->orig_code = -1; - g->name = "UNKNOWN"; - g->flags = GF_FLOAT; /* we start with float representation */ - } - - handle_gnames(); - - cursw->glmetrics(glyph_list); - cursw->fnmetrics(&fontm); - - original_scale_factor = 1000.0 / (double) fontm.units_per_em; - - if(transform == 0) - scale_factor = 1.0; /* don't transform */ - else - scale_factor = original_scale_factor; - - if(correctvsize && uni_sample!=0) { /* only for known languages */ - /* try to adjust the scale factor to make a typical - * uppercase character of hight at least (correctvsize), this - * may improve the appearance of the font but also - * make it weird, use with caution - */ - int ysz; - - ysz = iscale(glyph_list[encoding[uni_sample]].yMax); - if( ysz 45.0 || italic_angle < -45.0) - italic_angle = 0.0; /* consider buggy */ - - if (hints) { - findblues(); - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - DBG_TO_GLYPH(&glyph_list[i]); - buildstems(&glyph_list[i]); - assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name); - DBG_FROM_GLYPH(&glyph_list[i]); - } - } - stemstatistics(); - } else { - for(i=0; i<4; i++) - bbox[i] = iscale(fontm.bbox[i]); - } - /* don't touch the width of fixed width fonts */ - if( fontm.is_fixed_pitch ) - correctwidth=0; - docorrectwidth(); /* checks correctwidth inside */ - if (reverse) - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - DBG_TO_GLYPH(&glyph_list[i]); - reversepaths(&glyph_list[i]); - assertpath(glyph_list[i].entries, __FILE__, __LINE__, glyph_list[i].name); - DBG_FROM_GLYPH(&glyph_list[i]); - } - } - - -#if 0 - /* - ** It seems to bring troubles. The problem is that some - ** styles of the font may be recognized as fixed-width - ** while other styles of the same font as proportional. - ** So it's better to be commented out yet. - */ - if (tryfixed) - alignwidths(); -#endif - - if(trybold) { - forcebold = fontm.force_bold; - } - - fprintf(pfa_file, "%%!PS-AdobeFont-1.0: %s %s\n", fontm.name_ps, fontm.name_copyright); - time(&now); - fprintf(pfa_file, "%%%%CreationDate: %s", ctime(&now)); - fprintf(pfa_file, "%% Converted by ttf2pt1 %s/%s\n", TTF2PT1_VERSION, cursw->name); - fprintf(pfa_file, "%% Args: %s\n", cmdline); - fprintf(pfa_file, "%%%%EndComments\n"); - fprintf(pfa_file, "12 dict begin\n/FontInfo 9 dict dup begin\n"); - - WARNING_3 fprintf(stderr, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); - - - fprintf(pfa_file, "/version (%s) readonly def\n", fontm.name_version); - - fprintf(pfa_file, "/Notice (%s) readonly def\n", fontm.name_copyright); - - fprintf(pfa_file, "/FullName (%s) readonly def\n", fontm.name_full); - fprintf(pfa_file, "/FamilyName (%s) readonly def\n", fontm.name_family); - - if(wantuid) { - if(strUID) - fprintf(pfa_file, "/UniqueID %s def\n", strUID); - else { - numUID=0; - for(i=0; fontm.name_full[i]!=0; i++) { - numUID *= 37; /* magic number, good for hash */ - numUID += fontm.name_full[i]-' '; - /* if the name is long the first chars - * may be lost forever, so re-insert - * them thus making kind of CRC - */ - numUID += (numUID>>24) & 0xFF; - } - /* the range for private UIDs is 4 000 000 - 4 999 999 */ - fprintf(pfa_file, "/UniqueID %lu def\n", numUID%1000000+4000000); - } - } - - fprintf(pfa_file, "/Weight (%s) readonly def\n", fontm.name_style); - - fprintf(pfa_file, "/ItalicAngle %f def\n", italic_angle); - fprintf(pfa_file, "/isFixedPitch %s def\n", - fontm.is_fixed_pitch ? "true" : "false"); - - /* we don't print out the unused glyphs */ - nchars = 0; - for (i = 0; i < numglyphs; i++) { - if (glyph_list[i].flags & GF_USED) { - nchars++; - } - } - - fprintf(afm_file, "StartFontMetrics 4.1\n"); - fprintf(afm_file, "FontName %s%s\n", fontm.name_ps, uni_font_name_suffix); - fprintf(afm_file, "FullName %s\n", fontm.name_full); - fprintf(afm_file, "Notice %s\n", fontm.name_copyright); - fprintf(afm_file, "EncodingScheme FontSpecific\n"); - fprintf(afm_file, "FamilyName %s\n", fontm.name_family); - fprintf(afm_file, "Weight %s\n", fontm.name_style); - fprintf(afm_file, "Version %s\n", fontm.name_version); - fprintf(afm_file, "Characters %d\n", nchars); - fprintf(afm_file, "ItalicAngle %.1f\n", italic_angle); - - fprintf(afm_file, "Ascender %d\n", iscale(fontm.ascender)); - fprintf(afm_file, "Descender %d\n", iscale(fontm.descender)); - - fprintf(pfa_file, "/UnderlinePosition %d def\n", - iscale(fontm.underline_position)); - - fprintf(pfa_file, "/UnderlineThickness %hd def\nend readonly def\n", - iscale(fontm.underline_thickness)); - - fprintf(afm_file, "UnderlineThickness %d\n", - iscale(fontm.underline_thickness)); - - fprintf(afm_file, "UnderlinePosition %d\n", - iscale(fontm.underline_position)); - - fprintf(afm_file, "IsFixedPitch %s\n", - fontm.is_fixed_pitch ? "true" : "false"); - fprintf(afm_file, "FontBBox %d %d %d %d\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - - fprintf(pfa_file, "/FontName /%s%s def\n", fontm.name_ps, uni_font_name_suffix); - fprintf(pfa_file, "/PaintType 0 def\n/StrokeWidth 0 def\n"); - /* I'm not sure if these are fixed */ - fprintf(pfa_file, "/FontType 1 def\n"); - - if (transform) { - fprintf(pfa_file, "/FontMatrix [0.001 0 0 0.001 0 0] def\n"); - } else { - fprintf(pfa_file, "/FontMatrix [%9.7f 0 0 %9.7f 0 0] def\n", - original_scale_factor / 1000.0, original_scale_factor / 1000.0); - } - - fprintf(pfa_file, "/FontBBox {%d %d %d %d} readonly def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - - fprintf(pfa_file, "/Encoding 256 array\n"); - /* determine number of elements for metrics table */ - nmetrics = 256; - for (i = 0; i < numglyphs; i++) { - if( glyph_list[i].flags & GF_USED - && glyph_list[i].char_no == -1 ) { - nmetrics++; - } - } - fprintf(afm_file, "StartCharMetrics %d\n", nmetrics); - - fprintf(dvienc_file, "/%s%sEncoding [\n", - fontm.name_ps, uni_font_name_suffix); - - for (i = 0; i < 256; i++) { /* here 256, not ENCTABSZ */ - fprintf(pfa_file, - "dup %d /%s put\n", i, glyph_list[encoding[i]].name); - if( glyph_list[encoding[i]].flags & GF_USED ) { - print_glyph_metrics(i, encoding[i]); - } - if (encoding[i]) - fprintf (dvienc_file, "/index0x%04X\n", encoding[i]); - else - fprintf (dvienc_file, "/.notdef\n"); - } - - /* print the metrics for glyphs not in encoding table */ - for(i=0; ikerning(glyph_list); - print_kerning(afm_file); - } - - fprintf(afm_file, "EndFontMetrics\n"); - if(afm_file != null_file) - fclose(afm_file); - - fprintf(dvienc_file, "] def\n"); - if(dvienc_file != null_file) - fclose(dvienc_file); - - WARNING_1 fprintf(stderr, "Finished - font files created\n"); - - cursw->close(); - -#ifndef NOPIPES - while (wait(&ws) > 0) { - } -#else - if (encode && pfa_file != null_file) { - extern FILE *ifp, *ofp; /* from t1asm.c */ - - snprintf(filename, sizeof filename, "%s.%s", argv[2], pfbflag ? "pfb" : "pfa" ); - - if ((ofp = fopen(filename, "wb+")) == NULL) { - exit(1); - } else { - WARNING_2 fprintf(stderr, "Creating file %s\n", filename); - } - - snprintf(filename, sizeof filename, "%s.t1a", argv[2]); - - if ((ifp = fopen(filename, "rb")) == NULL) { - exit(1); - } else { - WARNING_2 fprintf(stderr, "Converting file %s\n", filename); - } - - runt1asm(pfbflag); - - WARNING_2 fprintf(stderr, "Removing file %s\n", filename); - if(unlink(filename) < 0) - WARNING_1 fprintf(stderr, "Unable to remove file %s\n", filename); - } -#endif /* NOPIPES */ - - fclose(null_file); - return 0; -} diff --git a/pdf2swf/ttf2pt1/ttf2pt1.h b/pdf2swf/ttf2pt1/ttf2pt1.h deleted file mode 100644 index 6e244da..0000000 --- a/pdf2swf/ttf2pt1/ttf2pt1.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef __ttf2pt1_included__ -#define __ttf2pt1_included__ -#ifdef __cplusplus -extern "C" { -#endif -int -ttf2pt1_main( - int argc, - char **argv -); -#ifdef __cplusplus -} -#endif -#endif - diff --git a/pdf2swf/ttf2pt1/version.h b/pdf2swf/ttf2pt1/version.h deleted file mode 100644 index a376d23..0000000 --- a/pdf2swf/ttf2pt1/version.h +++ /dev/null @@ -1,7 +0,0 @@ -/* - * see COPYRIGHT - */ - - -/* version number */ -#define TTF2PT1_VERSION "3.4.3" diff --git a/pdf2swf/ttf2pt1/win_missing.h b/pdf2swf/ttf2pt1/win_missing.h deleted file mode 100644 index c494099..0000000 --- a/pdf2swf/ttf2pt1/win_missing.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Implementation of things missing in Windows - */ - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#undef ntohs -#undef ntohl -#undef htonl - -#ifdef WINDOWS_FUNCTIONS -/* byte order */ - -char *optarg; -int optind=1; - -char getopt(int argc, char **argv, char *args) { - int n,nlen=strlen(args),nLen=0; - char nCmd; - - if (argv[optind] && *argv[optind]=='-') { - nCmd=*((argv[optind]+1)); - - for (n=0;n - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "gmem.h" -#include "Object.h" -#include "Catalog.h" -#include "Gfx.h" -#include "Lexer.h" -#include "Annot.h" - -//------------------------------------------------------------------------ -// Annot -//------------------------------------------------------------------------ - -Annot::Annot(XRef *xrefA, Dict *acroForm, Dict *dict) { - Object apObj, asObj, obj1, obj2; - GBool regen, isTextField; - double t; - - ok = gFalse; - xref = xrefA; - appearBuf = NULL; - - if (dict->lookup("Rect", &obj1)->isArray() && - obj1.arrayGetLength() == 4) { - //~ should check object types here - obj1.arrayGet(0, &obj2); - xMin = obj2.getNum(); - obj2.free(); - obj1.arrayGet(1, &obj2); - yMin = obj2.getNum(); - obj2.free(); - obj1.arrayGet(2, &obj2); - xMax = obj2.getNum(); - obj2.free(); - obj1.arrayGet(3, &obj2); - yMax = obj2.getNum(); - obj2.free(); - if (xMin > xMax) { - t = xMin; xMin = xMax; xMax = t; - } - if (yMin > yMax) { - t = yMin; yMin = yMax; yMax = t; - } - } else { - //~ this should return an error - xMin = yMin = 0; - xMax = yMax = 1; - } - obj1.free(); - - // check if field apperances need to be regenerated - regen = gFalse; - if (acroForm) { - acroForm->lookup("NeedAppearances", &obj1); - if (obj1.isBool() && obj1.getBool()) { - regen = gTrue; - } - obj1.free(); - } - - // check for a text-type field - isTextField = dict->lookup("FT", &obj1)->isName("Tx"); - obj1.free(); - -#if 0 //~ appearance stream generation is not finished yet - if (regen && isTextField) { - generateAppearance(acroForm, dict); - } else { -#endif - if (dict->lookup("AP", &apObj)->isDict()) { - if (dict->lookup("AS", &asObj)->isName()) { - if (apObj.dictLookup("N", &obj1)->isDict()) { - if (obj1.dictLookupNF(asObj.getName(), &obj2)->isRef()) { - obj2.copy(&appearance); - ok = gTrue; - } else { - obj2.free(); - if (obj1.dictLookupNF("Off", &obj2)->isRef()) { - obj2.copy(&appearance); - ok = gTrue; - } - } - obj2.free(); - } - obj1.free(); - } else { - if (apObj.dictLookupNF("N", &obj1)->isRef()) { - obj1.copy(&appearance); - ok = gTrue; - } - obj1.free(); - } - asObj.free(); - } - apObj.free(); -#if 0 //~ appearance stream generation is not finished yet - } -#endif -} - -Annot::~Annot() { - appearance.free(); - if (appearBuf) { - delete appearBuf; - } -} - -void Annot::generateAppearance(Dict *acroForm, Dict *dict) { - MemStream *appearStream; - Object daObj, vObj, drObj, appearDict, obj1, obj2; - GString *daStr, *daStr1, *vStr, *s; - char buf[256]; - double fontSize; - int c; - int i0, i1; - - //~ DA can be inherited - if (dict->lookup("DA", &daObj)->isString()) { - daStr = daObj.getString(); - - // look for a font size - //~ may want to parse the DS entry in place of this (if it exists) - daStr1 = NULL; - fontSize = 10; - for (i1 = daStr->getLength() - 2; i1 >= 0; --i1) { - if (daStr->getChar(i1) == 'T' && daStr->getChar(i1+1) == 'f') { - for (--i1; i1 >= 0 && Lexer::isSpace(daStr->getChar(i1)); --i1) ; - for (i0 = i1; i0 >= 0 && !Lexer::isSpace(daStr->getChar(i0)); --i0) ; - if (i0 >= 0) { - ++i0; - ++i1; - s = new GString(daStr, i0, i1 - i0); - fontSize = atof(s->getCString()); - delete s; - - // autosize the font - if (fontSize == 0) { - fontSize = 0.67 * (yMax - yMin); - daStr1 = new GString(daStr, 0, i0); - sprintf(buf, "%.2f", fontSize); - daStr1->append(buf); - daStr1->append(daStr->getCString() + i1, - daStr->getLength() - i1); - } - } - break; - } - } - - // build the appearance stream contents - appearBuf = new GString(); - appearBuf->append("/Tx BMC\n"); - appearBuf->append("q BT\n"); - appearBuf->append(daStr1 ? daStr1 : daStr)->append("\n"); - if (dict->lookup("V", &vObj)->isString()) { - //~ handle quadding -- this requires finding the font and using - //~ the encoding and char widths - sprintf(buf, "1 0 0 1 %.2f %.2f Tm\n", 2.0, yMax - yMin - fontSize); - appearBuf->append(buf); - sprintf(buf, "%g TL\n", fontSize); - appearBuf->append(buf); - vStr = vObj.getString(); - i0 = 0; - while (i0 < vStr->getLength()) { - for (i1 = i0; - i1 < vStr->getLength() && - vStr->getChar(i1) != '\n' && vStr->getChar(i1) != '\r'; - ++i1) ; - if (i0 > 0) { - appearBuf->append("T*\n"); - } - appearBuf->append('('); - for (; i0 < i1; ++i0) { - c = vStr->getChar(i0); - if (c == '(' || c == ')' || c == '\\') { - appearBuf->append('\\'); - appearBuf->append(c); - } else if (c < 0x20 || c >= 0x80) { - sprintf(buf, "\\%03o", c); - appearBuf->append(buf); - } else { - appearBuf->append(c); - } - } - appearBuf->append(") Tj\n"); - if (i1 + 1 < vStr->getLength() && - vStr->getChar(i1) == '\r' && vStr->getChar(i1 + 1) == '\n') { - i0 = i1 + 2; - } else { - i0 = i1 + 1; - } - } - } - vObj.free(); - appearBuf->append("ET Q\n"); - appearBuf->append("EMC\n"); - - // build the appearance stream dictionary - appearDict.initDict(xref); - appearDict.dictAdd(copyString("Length"), - obj1.initInt(appearBuf->getLength())); - appearDict.dictAdd(copyString("Subtype"), obj1.initName("Form")); - obj1.initArray(xref); - 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); - - // find the resource dictionary - dict->lookup("DR", &drObj); - if (!drObj.isDict()) { - dict->lookup("Parent", &obj1); - while (obj1.isDict()) { - drObj.free(); - obj1.dictLookup("DR", &drObj); - if (drObj.isDict()) { - break; - } - obj1.dictLookup("Parent", &obj2); - obj1.free(); - obj1 = obj2; - } - obj1.free(); - if (!drObj.isDict()) { - if (acroForm) { - drObj.free(); - acroForm->lookup("DR", &drObj); - } - } - } - if (drObj.isDict()) { - appearDict.dictAdd(copyString("Resources"), drObj.copy(&obj1)); - } - drObj.free(); - - // build the appearance stream - appearStream = new MemStream(appearBuf->getCString(), 0, - appearBuf->getLength(), &appearDict); - appearance.initStream(appearStream); - ok = gTrue; - - if (daStr1) { - delete daStr1; - } - } - daObj.free(); -} - -void Annot::draw(Gfx *gfx) { - Object obj; - - if (appearance.fetch(xref, &obj)->isStream()) { - gfx->doAnnot(&obj, xMin, yMin, xMax, yMax); - } - obj.free(); -} - -//------------------------------------------------------------------------ -// Annots -//------------------------------------------------------------------------ - -Annots::Annots(XRef *xref, Catalog *catalog, Object *annotsObj) { - Dict *acroForm; - Annot *annot; - Object obj1; - int size; - int i; - - annots = NULL; - size = 0; - nAnnots = 0; - - acroForm = catalog->getAcroForm()->isDict() ? - catalog->getAcroForm()->getDict() : NULL; - if (annotsObj->isArray()) { - for (i = 0; i < annotsObj->arrayGetLength(); ++i) { - if (annotsObj->arrayGet(i, &obj1)->isDict()) { - annot = new Annot(xref, acroForm, obj1.getDict()); - if (annot->isOk()) { - if (nAnnots >= size) { - size += 16; - annots = (Annot **)greallocn(annots, size, sizeof(Annot *)); - } - annots[nAnnots++] = annot; - } else { - delete annot; - } - } - obj1.free(); - } - } -} - -Annots::~Annots() { - int i; - - for (i = 0; i < nAnnots; ++i) { - delete annots[i]; - } - gfree(annots); -} diff --git a/pdf2swf/xpdf/Annot.h b/pdf2swf/xpdf/Annot.h deleted file mode 100644 index e5fd841..0000000 --- a/pdf2swf/xpdf/Annot.h +++ /dev/null @@ -1,73 +0,0 @@ -//======================================================================== -// -// Annot.h -// -// Copyright 2000-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ANNOT_H -#define ANNOT_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -class XRef; -class Catalog; -class Gfx; - -//------------------------------------------------------------------------ -// Annot -//------------------------------------------------------------------------ - -class Annot { -public: - - Annot(XRef *xrefA, Dict *acroForm, Dict *dict); - ~Annot(); - GBool isOk() { return ok; } - - void draw(Gfx *gfx); - - // Get appearance object. - Object *getAppearance(Object *obj) { return appearance.fetch(xref, obj); } - -private: - - void generateAppearance(Dict *acroForm, Dict *dict); - - XRef *xref; // the xref table for this PDF file - Object appearance; // a reference to the Form XObject stream - // for the normal appearance - GString *appearBuf; - double xMin, yMin, // annotation rectangle - xMax, yMax; - GBool ok; -}; - -//------------------------------------------------------------------------ -// Annots -//------------------------------------------------------------------------ - -class Annots { -public: - - // Extract non-link annotations from array of annotations. - Annots(XRef *xref, Catalog *catalog, Object *annotsObj); - - ~Annots(); - - // Iterate through list of annotations. - int getNumAnnots() { return nAnnots; } - Annot *getAnnot(int i) { return annots[i]; } - -private: - - Annot **annots; - int nAnnots; -}; - -#endif diff --git a/pdf2swf/xpdf/Array.cc b/pdf2swf/xpdf/Array.cc deleted file mode 100644 index 10ded14..0000000 --- a/pdf2swf/xpdf/Array.cc +++ /dev/null @@ -1,73 +0,0 @@ -//======================================================================== -// -// Array.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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) { - if (i < 0 || i >= length) { -#ifdef DEBUG_MEM - abort(); -#else - return obj->initNull(); -#endif - } - return elems[i].fetch(xref, obj); -} - -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/pdf2swf/xpdf/Array.h b/pdf2swf/xpdf/Array.h deleted file mode 100644 index 20ae05f..0000000 --- a/pdf2swf/xpdf/Array.h +++ /dev/null @@ -1,58 +0,0 @@ -//======================================================================== -// -// Array.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ARRAY_H -#define ARRAY_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -class XRef; - -//------------------------------------------------------------------------ -// Array -//------------------------------------------------------------------------ - -class Array { -public: - - // Constructor. - Array(XRef *xrefA); - - // Destructor. - ~Array(); - - // Reference counting. - int incRef() { return ++ref; } - int decRef() { return --ref; } - - // Get number of elements. - int getLength() { return length; } - - // Add an element. - void add(Object *elem); - - // Accessors. - Object *get(int i, Object *obj); - Object *getNF(int i, Object *obj); - -private: - - XRef *xref; // the xref table for this PDF file - Object *elems; // array of elements - int size; // size of array - int length; // number of elements in array - int ref; // reference count -}; - -#endif diff --git a/pdf2swf/xpdf/BuiltinFont.cc b/pdf2swf/xpdf/BuiltinFont.cc deleted file mode 100644 index ce98957..0000000 --- a/pdf2swf/xpdf/BuiltinFont.cc +++ /dev/null @@ -1,65 +0,0 @@ -//======================================================================== -// -// BuiltinFont.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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(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; - } - } - return gFalse; -} - -int BuiltinFontWidths::hash(char *name) { - 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/pdf2swf/xpdf/BuiltinFont.h b/pdf2swf/xpdf/BuiltinFont.h deleted file mode 100644 index 903ed19..0000000 --- a/pdf2swf/xpdf/BuiltinFont.h +++ /dev/null @@ -1,57 +0,0 @@ -//======================================================================== -// -// BuiltinFont.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef BUILTINFONT_H -#define BUILTINFONT_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -struct BuiltinFont; -class BuiltinFontWidths; - -//------------------------------------------------------------------------ - -struct BuiltinFont { - char *name; - char **defaultBaseEnc; - short ascent; - short descent; - short bbox[4]; - BuiltinFontWidths *widths; -}; - -//------------------------------------------------------------------------ - -struct BuiltinFontWidth { - char *name; - Gushort width; - BuiltinFontWidth *next; -}; - -class BuiltinFontWidths { -public: - - BuiltinFontWidths(BuiltinFontWidth *widths, int sizeA); - ~BuiltinFontWidths(); - GBool getWidth(char *name, Gushort *width); - -private: - - int hash(char *name); - - BuiltinFontWidth **tab; - int size; -}; - -#endif diff --git a/pdf2swf/xpdf/BuiltinFontTables.cc b/pdf2swf/xpdf/BuiltinFontTables.cc deleted file mode 100644 index 9c36238..0000000 --- a/pdf2swf/xpdf/BuiltinFontTables.cc +++ /dev/null @@ -1,4284 +0,0 @@ -//======================================================================== -// -// BuiltinFontTables.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include -#include -#include "FontEncodingTables.h" -#include "BuiltinFontTables.h" - -static BuiltinFontWidth courierWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "L", 600, NULL }, - { "backslash", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "equal", 600, NULL }, - { "question", 600, NULL }, - { "X", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "hyphen", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "five", 600, NULL }, - { "nine", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "zero", 600, NULL }, - { "multiply", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Racute", 600, NULL }, - { "Ograve", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "scedilla", 600, NULL }, - { "Oacute", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "ampersand", 600, NULL }, - { "Iacute", 600, NULL }, - { "lacute", 600, NULL }, - { "igrave", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "iacute", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "seven", 600, NULL }, - { "Amacron", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "braceright", 600, NULL }, - { "icircumflex", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth courierBoldWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "backslash", 600, NULL }, - { "L", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "X", 600, NULL }, - { "question", 600, NULL }, - { "equal", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "hyphen", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "nine", 600, NULL }, - { "five", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "multiply", 600, NULL }, - { "zero", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Ograve", 600, NULL }, - { "Racute", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "Oacute", 600, NULL }, - { "scedilla", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "Iacute", 600, NULL }, - { "ampersand", 600, NULL }, - { "igrave", 600, NULL }, - { "lacute", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "iacute", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "Amacron", 600, NULL }, - { "seven", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "icircumflex", 600, NULL }, - { "braceright", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth courierBoldObliqueWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "backslash", 600, NULL }, - { "L", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "X", 600, NULL }, - { "question", 600, NULL }, - { "equal", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "hyphen", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "nine", 600, NULL }, - { "five", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "multiply", 600, NULL }, - { "zero", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Ograve", 600, NULL }, - { "Racute", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "Oacute", 600, NULL }, - { "scedilla", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "Iacute", 600, NULL }, - { "ampersand", 600, NULL }, - { "igrave", 600, NULL }, - { "lacute", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "iacute", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "Amacron", 600, NULL }, - { "seven", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "icircumflex", 600, NULL }, - { "braceright", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth courierObliqueWidthsTab[] = { - { "Ntilde", 600, NULL }, - { "rcaron", 600, NULL }, - { "kcommaaccent", 600, NULL }, - { "Ncommaaccent", 600, NULL }, - { "Zacute", 600, NULL }, - { "comma", 600, NULL }, - { "cedilla", 600, NULL }, - { "plusminus", 600, NULL }, - { "circumflex", 600, NULL }, - { "dotaccent", 600, NULL }, - { "edotaccent", 600, NULL }, - { "asciitilde", 600, NULL }, - { "colon", 600, NULL }, - { "onehalf", 600, NULL }, - { "dollar", 600, NULL }, - { "Lcaron", 600, NULL }, - { "ntilde", 600, NULL }, - { "Aogonek", 600, NULL }, - { "ncommaaccent", 600, NULL }, - { "minus", 600, NULL }, - { "Iogonek", 600, NULL }, - { "zacute", 600, NULL }, - { "yen", 600, NULL }, - { "space", 600, NULL }, - { "Omacron", 600, NULL }, - { "questiondown", 600, NULL }, - { "emdash", 600, NULL }, - { "Agrave", 600, NULL }, - { "three", 600, NULL }, - { "numbersign", 600, NULL }, - { "lcaron", 600, NULL }, - { "A", 600, NULL }, - { "B", 600, NULL }, - { "C", 600, NULL }, - { "aogonek", 600, NULL }, - { "D", 600, NULL }, - { "E", 600, NULL }, - { "onequarter", 600, NULL }, - { "F", 600, NULL }, - { "G", 600, NULL }, - { "H", 600, NULL }, - { "I", 600, NULL }, - { "J", 600, NULL }, - { "K", 600, NULL }, - { "iogonek", 600, NULL }, - { "backslash", 600, NULL }, - { "L", 600, NULL }, - { "periodcentered", 600, NULL }, - { "M", 600, NULL }, - { "N", 600, NULL }, - { "omacron", 600, NULL }, - { "Tcommaaccent", 600, NULL }, - { "O", 600, NULL }, - { "P", 600, NULL }, - { "Q", 600, NULL }, - { "Uhungarumlaut", 600, NULL }, - { "R", 600, NULL }, - { "Aacute", 600, NULL }, - { "caron", 600, NULL }, - { "S", 600, NULL }, - { "T", 600, NULL }, - { "U", 600, NULL }, - { "agrave", 600, NULL }, - { "V", 600, NULL }, - { "W", 600, NULL }, - { "X", 600, NULL }, - { "question", 600, NULL }, - { "equal", 600, NULL }, - { "Y", 600, NULL }, - { "Z", 600, NULL }, - { "four", 600, NULL }, - { "a", 600, NULL }, - { "Gcommaaccent", 600, NULL }, - { "b", 600, NULL }, - { "c", 600, NULL }, - { "d", 600, NULL }, - { "e", 600, NULL }, - { "f", 600, NULL }, - { "g", 600, NULL }, - { "bullet", 600, NULL }, - { "h", 600, NULL }, - { "i", 600, NULL }, - { "Oslash", 600, NULL }, - { "dagger", 600, NULL }, - { "j", 600, NULL }, - { "k", 600, NULL }, - { "l", 600, NULL }, - { "m", 600, NULL }, - { "n", 600, NULL }, - { "tcommaaccent", 600, NULL }, - { "o", 600, NULL }, - { "ordfeminine", 600, NULL }, - { "ring", 600, NULL }, - { "p", 600, NULL }, - { "q", 600, NULL }, - { "uhungarumlaut", 600, NULL }, - { "r", 600, NULL }, - { "twosuperior", 600, NULL }, - { "aacute", 600, NULL }, - { "s", 600, NULL }, - { "OE", 600, NULL }, - { "t", 600, NULL }, - { "divide", 600, NULL }, - { "u", 600, NULL }, - { "Ccaron", 600, NULL }, - { "v", 600, NULL }, - { "w", 600, NULL }, - { "x", 600, NULL }, - { "y", 600, NULL }, - { "z", 600, NULL }, - { "Gbreve", 600, NULL }, - { "commaaccent", 600, NULL }, - { "hungarumlaut", 600, NULL }, - { "Idotaccent", 600, NULL }, - { "Nacute", 600, NULL }, - { "quotedbl", 600, NULL }, - { "gcommaaccent", 600, NULL }, - { "mu", 600, NULL }, - { "greaterequal", 600, NULL }, - { "Scaron", 600, NULL }, - { "Lslash", 600, NULL }, - { "semicolon", 600, NULL }, - { "oslash", 600, NULL }, - { "lessequal", 600, NULL }, - { "lozenge", 600, NULL }, - { "parenright", 600, NULL }, - { "ccaron", 600, NULL }, - { "Ecircumflex", 600, NULL }, - { "gbreve", 600, NULL }, - { "trademark", 600, NULL }, - { "daggerdbl", 600, NULL }, - { "nacute", 600, NULL }, - { "macron", 600, NULL }, - { "Otilde", 600, NULL }, - { "Emacron", 600, NULL }, - { "ellipsis", 600, NULL }, - { "scaron", 600, NULL }, - { "AE", 600, NULL }, - { "Ucircumflex", 600, NULL }, - { "lslash", 600, NULL }, - { "quotedblleft", 600, NULL }, - { "guilsinglright", 600, NULL }, - { "hyphen", 600, NULL }, - { "quotesingle", 600, NULL }, - { "eight", 600, NULL }, - { "exclamdown", 600, NULL }, - { "endash", 600, NULL }, - { "oe", 600, NULL }, - { "Abreve", 600, NULL }, - { "Umacron", 600, NULL }, - { "ecircumflex", 600, NULL }, - { "Adieresis", 600, NULL }, - { "copyright", 600, NULL }, - { "Egrave", 600, NULL }, - { "slash", 600, NULL }, - { "Edieresis", 600, NULL }, - { "otilde", 600, NULL }, - { "Idieresis", 600, NULL }, - { "parenleft", 600, NULL }, - { "one", 600, NULL }, - { "emacron", 600, NULL }, - { "Odieresis", 600, NULL }, - { "ucircumflex", 600, NULL }, - { "bracketleft", 600, NULL }, - { "Ugrave", 600, NULL }, - { "quoteright", 600, NULL }, - { "Udieresis", 600, NULL }, - { "perthousand", 600, NULL }, - { "Ydieresis", 600, NULL }, - { "umacron", 600, NULL }, - { "abreve", 600, NULL }, - { "Eacute", 600, NULL }, - { "adieresis", 600, NULL }, - { "egrave", 600, NULL }, - { "edieresis", 600, NULL }, - { "idieresis", 600, NULL }, - { "Eth", 600, NULL }, - { "ae", 600, NULL }, - { "asterisk", 600, NULL }, - { "odieresis", 600, NULL }, - { "Uacute", 600, NULL }, - { "ugrave", 600, NULL }, - { "nine", 600, NULL }, - { "five", 600, NULL }, - { "udieresis", 600, NULL }, - { "Zcaron", 600, NULL }, - { "Scommaaccent", 600, NULL }, - { "threequarters", 600, NULL }, - { "guillemotright", 600, NULL }, - { "Ccedilla", 600, NULL }, - { "ydieresis", 600, NULL }, - { "tilde", 600, NULL }, - { "at", 600, NULL }, - { "eacute", 600, NULL }, - { "underscore", 600, NULL }, - { "Euro", 600, NULL }, - { "Dcroat", 600, NULL }, - { "multiply", 600, NULL }, - { "zero", 600, NULL }, - { "eth", 600, NULL }, - { "Scedilla", 600, NULL }, - { "Ograve", 600, NULL }, - { "Racute", 600, NULL }, - { "partialdiff", 600, NULL }, - { "uacute", 600, NULL }, - { "braceleft", 600, NULL }, - { "Thorn", 600, NULL }, - { "zcaron", 600, NULL }, - { "scommaaccent", 600, NULL }, - { "ccedilla", 600, NULL }, - { "Dcaron", 600, NULL }, - { "dcroat", 600, NULL }, - { "Ocircumflex", 600, NULL }, - { "Oacute", 600, NULL }, - { "scedilla", 600, NULL }, - { "ogonek", 600, NULL }, - { "ograve", 600, NULL }, - { "racute", 600, NULL }, - { "Tcaron", 600, NULL }, - { "Eogonek", 600, NULL }, - { "thorn", 600, NULL }, - { "degree", 600, NULL }, - { "registered", 600, NULL }, - { "radical", 600, NULL }, - { "Aring", 600, NULL }, - { "percent", 600, NULL }, - { "six", 600, NULL }, - { "paragraph", 600, NULL }, - { "dcaron", 600, NULL }, - { "Uogonek", 600, NULL }, - { "two", 600, NULL }, - { "summation", 600, NULL }, - { "Igrave", 600, NULL }, - { "Lacute", 600, NULL }, - { "ocircumflex", 600, NULL }, - { "oacute", 600, NULL }, - { "Uring", 600, NULL }, - { "Lcommaaccent", 600, NULL }, - { "tcaron", 600, NULL }, - { "eogonek", 600, NULL }, - { "Delta", 600, NULL }, - { "Ohungarumlaut", 600, NULL }, - { "asciicircum", 600, NULL }, - { "aring", 600, NULL }, - { "grave", 600, NULL }, - { "uogonek", 600, NULL }, - { "bracketright", 600, NULL }, - { "Iacute", 600, NULL }, - { "ampersand", 600, NULL }, - { "igrave", 600, NULL }, - { "lacute", 600, NULL }, - { "Ncaron", 600, NULL }, - { "plus", 600, NULL }, - { "uring", 600, NULL }, - { "quotesinglbase", 600, NULL }, - { "lcommaaccent", 600, NULL }, - { "Yacute", 600, NULL }, - { "ohungarumlaut", 600, NULL }, - { "threesuperior", 600, NULL }, - { "acute", 600, NULL }, - { "section", 600, NULL }, - { "dieresis", 600, NULL }, - { "iacute", 600, NULL }, - { "quotedblbase", 600, NULL }, - { "ncaron", 600, NULL }, - { "florin", 600, NULL }, - { "yacute", 600, NULL }, - { "Rcommaaccent", 600, NULL }, - { "fi", 600, NULL }, - { "fl", 600, NULL }, - { "Acircumflex", 600, NULL }, - { "Cacute", 600, NULL }, - { "Icircumflex", 600, NULL }, - { "guillemotleft", 600, NULL }, - { "germandbls", 600, NULL }, - { "Amacron", 600, NULL }, - { "seven", 600, NULL }, - { "Sacute", 600, NULL }, - { "ordmasculine", 600, NULL }, - { "dotlessi", 600, NULL }, - { "sterling", 600, NULL }, - { "notequal", 600, NULL }, - { "Imacron", 600, NULL }, - { "rcommaaccent", 600, NULL }, - { "Zdotaccent", 600, NULL }, - { "acircumflex", 600, NULL }, - { "cacute", 600, NULL }, - { "Ecaron", 600, NULL }, - { "icircumflex", 600, NULL }, - { "braceright", 600, NULL }, - { "quotedblright", 600, NULL }, - { "amacron", 600, NULL }, - { "sacute", 600, NULL }, - { "imacron", 600, NULL }, - { "cent", 600, NULL }, - { "currency", 600, NULL }, - { "logicalnot", 600, NULL }, - { "zdotaccent", 600, NULL }, - { "Atilde", 600, NULL }, - { "breve", 600, NULL }, - { "bar", 600, NULL }, - { "fraction", 600, NULL }, - { "less", 600, NULL }, - { "ecaron", 600, NULL }, - { "guilsinglleft", 600, NULL }, - { "exclam", 600, NULL }, - { "period", 600, NULL }, - { "Rcaron", 600, NULL }, - { "Kcommaaccent", 600, NULL }, - { "greater", 600, NULL }, - { "atilde", 600, NULL }, - { "brokenbar", 600, NULL }, - { "quoteleft", 600, NULL }, - { "Edotaccent", 600, NULL }, - { "onesuperior", 600, NULL } -}; - -static BuiltinFontWidth helveticaWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 333, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 278, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 556, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 667, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 667, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 299, NULL }, - { "A", 667, NULL }, - { "B", 667, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 500, NULL }, - { "K", 667, NULL }, - { "iogonek", 222, NULL }, - { "backslash", 278, NULL }, - { "L", 556, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 556, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 667, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 556, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 556, NULL }, - { "c", 500, NULL }, - { "d", 556, NULL }, - { "e", 556, NULL }, - { "f", 278, NULL }, - { "g", 556, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 222, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 222, NULL }, - { "k", 500, NULL }, - { "l", 222, NULL }, - { "m", 833, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 556, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 556, NULL }, - { "q", 556, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 333, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 500, NULL }, - { "OE", 1000, NULL }, - { "t", 278, NULL }, - { "divide", 584, NULL }, - { "u", 556, NULL }, - { "Ccaron", 722, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 355, NULL }, - { "gcommaaccent", 556, NULL }, - { "mu", 556, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 556, NULL }, - { "semicolon", 278, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 500, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 556, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 500, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 222, NULL }, - { "quotedblleft", 333, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 191, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 667, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 667, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 556, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 278, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 222, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 556, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 556, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 1015, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 556, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 334, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 500, NULL }, - { "ccedilla", 500, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 556, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 500, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 556, NULL }, - { "racute", 333, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 556, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 453, NULL }, - { "Aring", 667, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 537, NULL }, - { "dcaron", 643, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 556, NULL }, - { "ocircumflex", 556, NULL }, - { "oacute", 556, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 556, NULL }, - { "tcaron", 317, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 469, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 278, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 667, NULL }, - { "igrave", 278, NULL }, - { "lacute", 222, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 222, NULL }, - { "lcommaaccent", 222, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 556, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 333, NULL }, - { "ncaron", 556, NULL }, - { "florin", 556, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 500, NULL }, - { "fl", 500, NULL }, - { "Acircumflex", 667, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 667, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 333, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 500, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 334, NULL }, - { "quotedblright", 333, NULL }, - { "amacron", 556, NULL }, - { "sacute", 500, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 667, NULL }, - { "breve", 333, NULL }, - { "bar", 260, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 278, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 260, NULL }, - { "quoteleft", 222, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth helveticaBoldWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 556, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 333, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 611, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 611, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 400, NULL }, - { "A", 722, NULL }, - { "B", 722, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 556, NULL }, - { "K", 722, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 611, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 611, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 611, NULL }, - { "c", 556, NULL }, - { "d", 611, NULL }, - { "e", 556, NULL }, - { "f", 333, NULL }, - { "g", 611, NULL }, - { "bullet", 350, NULL }, - { "h", 611, NULL }, - { "i", 278, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 278, NULL }, - { "k", 556, NULL }, - { "l", 278, NULL }, - { "m", 889, NULL }, - { "n", 611, NULL }, - { "tcommaaccent", 333, NULL }, - { "o", 611, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 611, NULL }, - { "q", 611, NULL }, - { "uhungarumlaut", 611, NULL }, - { "r", 389, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 556, NULL }, - { "OE", 1000, NULL }, - { "t", 333, NULL }, - { "divide", 584, NULL }, - { "u", 611, NULL }, - { "Ccaron", 722, NULL }, - { "v", 556, NULL }, - { "w", 778, NULL }, - { "x", 556, NULL }, - { "y", 556, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 474, NULL }, - { "gcommaaccent", 611, NULL }, - { "mu", 611, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 556, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 611, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 611, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 556, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 238, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 611, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 611, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 278, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 611, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 611, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 611, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 611, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 556, NULL }, - { "tilde", 333, NULL }, - { "dbldaggerumlaut", 556, NULL }, - { "at", 975, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 611, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 611, NULL }, - { "braceleft", 389, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 556, NULL }, - { "ccedilla", 556, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 611, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 556, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 611, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 611, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 549, NULL }, - { "Aring", 722, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 556, NULL }, - { "dcaron", 743, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 611, NULL }, - { "oacute", 611, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 389, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 584, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 611, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 722, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 611, NULL }, - { "quotesinglbase", 278, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 611, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 611, NULL }, - { "florin", 556, NULL }, - { "yacute", 556, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 611, NULL }, - { "fl", 611, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 722, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 556, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 389, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 556, NULL }, - { "sacute", 556, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 280, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 722, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 280, NULL }, - { "quoteleft", 278, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth helveticaBoldObliqueWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 556, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 333, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 611, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 611, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 400, NULL }, - { "A", 722, NULL }, - { "B", 722, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 556, NULL }, - { "K", 722, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 611, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 611, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 611, NULL }, - { "c", 556, NULL }, - { "d", 611, NULL }, - { "e", 556, NULL }, - { "f", 333, NULL }, - { "g", 611, NULL }, - { "bullet", 350, NULL }, - { "h", 611, NULL }, - { "i", 278, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 278, NULL }, - { "k", 556, NULL }, - { "l", 278, NULL }, - { "m", 889, NULL }, - { "n", 611, NULL }, - { "tcommaaccent", 333, NULL }, - { "o", 611, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 611, NULL }, - { "q", 611, NULL }, - { "uhungarumlaut", 611, NULL }, - { "r", 389, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 556, NULL }, - { "OE", 1000, NULL }, - { "t", 333, NULL }, - { "divide", 584, NULL }, - { "u", 611, NULL }, - { "Ccaron", 722, NULL }, - { "v", 556, NULL }, - { "w", 778, NULL }, - { "x", 556, NULL }, - { "y", 556, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 474, NULL }, - { "gcommaaccent", 611, NULL }, - { "mu", 611, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 556, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 611, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 611, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 556, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 238, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 611, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 611, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 278, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 611, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 611, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 611, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 611, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 556, NULL }, - { "tilde", 333, NULL }, - { "at", 975, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 611, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 611, NULL }, - { "braceleft", 389, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 556, NULL }, - { "ccedilla", 556, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 611, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 556, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 611, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 611, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 549, NULL }, - { "Aring", 722, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 556, NULL }, - { "dcaron", 743, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 611, NULL }, - { "oacute", 611, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 389, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 584, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 611, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 722, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 611, NULL }, - { "quotesinglbase", 278, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 611, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 611, NULL }, - { "florin", 556, NULL }, - { "yacute", 556, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 611, NULL }, - { "fl", 611, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 722, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 556, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 389, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 556, NULL }, - { "sacute", 556, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 280, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 722, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 280, NULL }, - { "quoteleft", 278, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth helveticaObliqueWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 333, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 278, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 584, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 556, NULL }, - { "asciitilde", 584, NULL }, - { "colon", 278, NULL }, - { "onehalf", 834, NULL }, - { "dollar", 556, NULL }, - { "Lcaron", 556, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 667, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 584, NULL }, - { "Iogonek", 278, NULL }, - { "zacute", 500, NULL }, - { "yen", 556, NULL }, - { "space", 278, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 611, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 667, NULL }, - { "three", 556, NULL }, - { "numbersign", 556, NULL }, - { "lcaron", 299, NULL }, - { "A", 667, NULL }, - { "B", 667, NULL }, - { "C", 722, NULL }, - { "aogonek", 556, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 834, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 722, NULL }, - { "I", 278, NULL }, - { "J", 500, NULL }, - { "K", 667, NULL }, - { "iogonek", 222, NULL }, - { "backslash", 278, NULL }, - { "L", 556, NULL }, - { "periodcentered", 278, NULL }, - { "M", 833, NULL }, - { "N", 722, NULL }, - { "omacron", 556, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 778, NULL }, - { "P", 667, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 667, NULL }, - { "caron", 333, NULL }, - { "S", 667, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 556, NULL }, - { "V", 667, NULL }, - { "W", 944, NULL }, - { "X", 667, NULL }, - { "question", 556, NULL }, - { "equal", 584, NULL }, - { "Y", 667, NULL }, - { "Z", 611, NULL }, - { "four", 556, NULL }, - { "a", 556, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 556, NULL }, - { "c", 500, NULL }, - { "d", 556, NULL }, - { "e", 556, NULL }, - { "f", 278, NULL }, - { "g", 556, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 222, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 556, NULL }, - { "j", 222, NULL }, - { "k", 500, NULL }, - { "l", 222, NULL }, - { "m", 833, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 556, NULL }, - { "ordfeminine", 370, NULL }, - { "ring", 333, NULL }, - { "p", 556, NULL }, - { "q", 556, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 333, NULL }, - { "twosuperior", 333, NULL }, - { "aacute", 556, NULL }, - { "s", 500, NULL }, - { "OE", 1000, NULL }, - { "t", 278, NULL }, - { "divide", 584, NULL }, - { "u", 556, NULL }, - { "Ccaron", 722, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 500, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 278, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 355, NULL }, - { "gcommaaccent", 556, NULL }, - { "mu", 556, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 667, NULL }, - { "Lslash", 556, NULL }, - { "semicolon", 278, NULL }, - { "oslash", 611, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 500, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 556, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 556, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 500, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 222, NULL }, - { "quotedblleft", 333, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 191, NULL }, - { "eight", 556, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 556, NULL }, - { "oe", 944, NULL }, - { "Abreve", 667, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 556, NULL }, - { "Adieresis", 667, NULL }, - { "copyright", 737, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 556, NULL }, - { "Idieresis", 278, NULL }, - { "parenleft", 333, NULL }, - { "one", 556, NULL }, - { "emacron", 556, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 278, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 222, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 667, NULL }, - { "umacron", 556, NULL }, - { "abreve", 556, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 556, NULL }, - { "egrave", 556, NULL }, - { "edieresis", 556, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 889, NULL }, - { "asterisk", 389, NULL }, - { "odieresis", 556, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 556, NULL }, - { "five", 556, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 667, NULL }, - { "threequarters", 834, NULL }, - { "guillemotright", 556, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 1015, NULL }, - { "eacute", 556, NULL }, - { "underscore", 556, NULL }, - { "Euro", 556, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 584, NULL }, - { "zero", 556, NULL }, - { "eth", 556, NULL }, - { "Scedilla", 667, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 334, NULL }, - { "Thorn", 667, NULL }, - { "zcaron", 500, NULL }, - { "scommaaccent", 500, NULL }, - { "ccedilla", 500, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 556, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 500, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 556, NULL }, - { "racute", 333, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 556, NULL }, - { "degree", 400, NULL }, - { "registered", 737, NULL }, - { "radical", 453, NULL }, - { "Aring", 667, NULL }, - { "percent", 889, NULL }, - { "six", 556, NULL }, - { "paragraph", 537, NULL }, - { "dcaron", 643, NULL }, - { "Uogonek", 722, NULL }, - { "two", 556, NULL }, - { "summation", 600, NULL }, - { "Igrave", 278, NULL }, - { "Lacute", 556, NULL }, - { "ocircumflex", 556, NULL }, - { "oacute", 556, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 556, NULL }, - { "tcaron", 317, NULL }, - { "eogonek", 556, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 469, NULL }, - { "aring", 556, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 278, NULL }, - { "Iacute", 278, NULL }, - { "ampersand", 667, NULL }, - { "igrave", 278, NULL }, - { "lacute", 222, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 584, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 222, NULL }, - { "lcommaaccent", 222, NULL }, - { "Yacute", 667, NULL }, - { "ohungarumlaut", 556, NULL }, - { "threesuperior", 333, NULL }, - { "acute", 333, NULL }, - { "section", 556, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 333, NULL }, - { "ncaron", 556, NULL }, - { "florin", 556, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 500, NULL }, - { "fl", 500, NULL }, - { "Acircumflex", 667, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 278, NULL }, - { "guillemotleft", 556, NULL }, - { "germandbls", 611, NULL }, - { "Amacron", 667, NULL }, - { "seven", 556, NULL }, - { "Sacute", 667, NULL }, - { "ordmasculine", 365, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 556, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 278, NULL }, - { "rcommaaccent", 333, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 556, NULL }, - { "cacute", 500, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 334, NULL }, - { "quotedblright", 333, NULL }, - { "amacron", 556, NULL }, - { "sacute", 500, NULL }, - { "imacron", 278, NULL }, - { "cent", 556, NULL }, - { "currency", 556, NULL }, - { "logicalnot", 584, NULL }, - { "zdotaccent", 500, NULL }, - { "Atilde", 667, NULL }, - { "breve", 333, NULL }, - { "bar", 260, NULL }, - { "fraction", 167, NULL }, - { "less", 584, NULL }, - { "ecaron", 556, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 278, NULL }, - { "period", 278, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 584, NULL }, - { "atilde", 556, NULL }, - { "brokenbar", 260, NULL }, - { "quoteleft", 222, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 333, NULL } -}; - -static BuiltinFontWidth symbolWidthsTab[] = { - { "bracketleftex", 384, NULL }, - { "alpha", 631, NULL }, - { "union", 768, NULL }, - { "infinity", 713, NULL }, - { "comma", 250, NULL }, - { "copyrightsans", 790, NULL }, - { "plusminus", 549, NULL }, - { "arrowup", 603, NULL }, - { "apple", 790, NULL }, - { "parenleftbt", 384, NULL }, - { "notelement", 713, NULL }, - { "colon", 278, NULL }, - { "beta", 549, NULL }, - { "braceleftbt", 494, NULL }, - { "Lambda", 686, NULL }, - { "Phi", 763, NULL }, - { "minus", 549, NULL }, - { "space", 250, NULL }, - { "Sigma", 592, NULL }, - { "approxequal", 549, NULL }, - { "minute", 247, NULL }, - { "circleplus", 768, NULL }, - { "Omicron", 722, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lambda", 549, NULL }, - { "phi", 521, NULL }, - { "aleph", 823, NULL }, - { "Tau", 611, NULL }, - { "spade", 753, NULL }, - { "logicaland", 603, NULL }, - { "sigma", 603, NULL }, - { "propersuperset", 713, NULL }, - { "omicron", 549, NULL }, - { "question", 444, NULL }, - { "equal", 549, NULL }, - { "Epsilon", 611, NULL }, - { "emptyset", 823, NULL }, - { "diamond", 753, NULL }, - { "four", 500, NULL }, - { "Mu", 889, NULL }, - { "parenlefttp", 384, NULL }, - { "club", 753, NULL }, - { "bullet", 460, NULL }, - { "Omega", 768, NULL }, - { "tau", 439, NULL }, - { "Upsilon", 690, NULL }, - { "bracelefttp", 494, NULL }, - { "heart", 753, NULL }, - { "divide", 549, NULL }, - { "epsilon", 439, NULL }, - { "logicalor", 603, NULL }, - { "parenleftex", 384, NULL }, - { "greaterequal", 549, NULL }, - { "mu", 576, NULL }, - { "Nu", 722, NULL }, - { "therefore", 863, NULL }, - { "notsubset", 713, NULL }, - { "omega", 686, NULL }, - { "semicolon", 278, NULL }, - { "element", 713, NULL }, - { "upsilon", 576, NULL }, - { "existential", 549, NULL }, - { "integralbt", 686, NULL }, - { "lessequal", 549, NULL }, - { "phi1", 603, NULL }, - { "lozenge", 494, NULL }, - { "trademarkserif", 890, NULL }, - { "parenright", 333, NULL }, - { "reflexsuperset", 713, NULL }, - { "sigma1", 439, NULL }, - { "nu", 521, NULL }, - { "Gamma", 603, NULL }, - { "angleright", 329, NULL }, - { "ellipsis", 1000, NULL }, - { "Rho", 556, NULL }, - { "parenrightbt", 384, NULL }, - { "radicalex", 500, NULL }, - { "eight", 500, NULL }, - { "angleleft", 329, NULL }, - { "arrowdbldown", 603, NULL }, - { "congruent", 549, NULL }, - { "Theta", 741, NULL }, - { "intersection", 768, NULL }, - { "Pi", 768, NULL }, - { "slash", 278, NULL }, - { "registerserif", 790, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "gamma", 411, NULL }, - { "bracketleft", 333, NULL }, - { "rho", 549, NULL }, - { "circlemultiply", 768, NULL }, - { "Chi", 722, NULL }, - { "theta", 521, NULL }, - { "pi", 549, NULL }, - { "integraltp", 686, NULL }, - { "Eta", 722, NULL }, - { "product", 823, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "propersubset", 713, NULL }, - { "bracketrightbt", 384, NULL }, - { "trademarksans", 786, NULL }, - { "dotmath", 250, NULL }, - { "integralex", 686, NULL }, - { "chi", 549, NULL }, - { "parenrighttp", 384, NULL }, - { "eta", 603, NULL }, - { "underscore", 500, NULL }, - { "Euro", 750, NULL }, - { "multiply", 549, NULL }, - { "zero", 500, NULL }, - { "partialdiff", 494, NULL }, - { "angle", 768, NULL }, - { "arrowdblleft", 987, NULL }, - { "braceleft", 480, NULL }, - { "parenrightex", 384, NULL }, - { "Rfraktur", 795, NULL }, - { "Zeta", 611, NULL }, - { "braceex", 494, NULL }, - { "arrowdblup", 603, NULL }, - { "arrowdown", 603, NULL }, - { "Ifraktur", 686, NULL }, - { "degree", 400, NULL }, - { "Iota", 333, NULL }, - { "perpendicular", 658, NULL }, - { "radical", 549, NULL }, - { "asteriskmath", 500, NULL }, - { "percent", 833, NULL }, - { "zeta", 494, NULL }, - { "six", 500, NULL }, - { "two", 500, NULL }, - { "weierstrass", 987, NULL }, - { "summation", 713, NULL }, - { "bracketrighttp", 384, NULL }, - { "carriagereturn", 658, NULL }, - { "suchthat", 439, NULL }, - { "arrowvertex", 603, NULL }, - { "Delta", 612, NULL }, - { "iota", 329, NULL }, - { "arrowhorizex", 1000, NULL }, - { "bracketrightex", 384, NULL }, - { "bracketright", 333, NULL }, - { "ampersand", 778, NULL }, - { "plus", 549, NULL }, - { "proportional", 713, NULL }, - { "delta", 494, NULL }, - { "copyrightserif", 790, NULL }, - { "bracerightmid", 494, NULL }, - { "arrowleft", 987, NULL }, - { "second", 411, NULL }, - { "arrowdblboth", 1042, NULL }, - { "florin", 500, NULL }, - { "Psi", 795, NULL }, - { "bracerightbt", 494, NULL }, - { "bracketleftbt", 384, NULL }, - { "seven", 500, NULL }, - { "braceleftmid", 494, NULL }, - { "notequal", 549, NULL }, - { "psi", 686, NULL }, - { "equivalence", 549, NULL }, - { "universal", 713, NULL }, - { "arrowdblright", 987, NULL }, - { "braceright", 480, NULL }, - { "reflexsubset", 713, NULL }, - { "Xi", 645, NULL }, - { "theta1", 631, NULL }, - { "logicalnot", 713, NULL }, - { "Kappa", 722, NULL }, - { "similar", 549, NULL }, - { "bar", 200, NULL }, - { "fraction", 167, NULL }, - { "less", 549, NULL }, - { "registersans", 790, NULL }, - { "omega1", 713, NULL }, - { "exclam", 333, NULL }, - { "Upsilon1", 620, NULL }, - { "bracerighttp", 494, NULL }, - { "xi", 493, NULL }, - { "period", 250, NULL }, - { "Alpha", 722, NULL }, - { "arrowright", 987, NULL }, - { "greater", 549, NULL }, - { "bracketlefttp", 384, NULL }, - { "kappa", 549, NULL }, - { "gradient", 713, NULL }, - { "integral", 274, NULL }, - { "arrowboth", 1042, NULL }, - { "Beta", 667, NULL } -}; - -static BuiltinFontWidth timesBoldWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 444, NULL }, - { "kcommaaccent", 556, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 667, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 570, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 520, NULL }, - { "colon", 333, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 667, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 570, NULL }, - { "Iogonek", 389, NULL }, - { "zacute", 444, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 778, NULL }, - { "questiondown", 500, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 394, NULL }, - { "A", 722, NULL }, - { "B", 667, NULL }, - { "C", 722, NULL }, - { "aogonek", 500, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 750, NULL }, - { "F", 611, NULL }, - { "G", 778, NULL }, - { "H", 778, NULL }, - { "I", 389, NULL }, - { "J", 500, NULL }, - { "K", 778, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 667, NULL }, - { "periodcentered", 250, NULL }, - { "M", 944, NULL }, - { "N", 722, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 667, NULL }, - { "O", 778, NULL }, - { "P", 611, NULL }, - { "Q", 778, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 722, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 556, NULL }, - { "T", 667, NULL }, - { "U", 722, NULL }, - { "agrave", 500, NULL }, - { "V", 722, NULL }, - { "W", 1000, NULL }, - { "X", 722, NULL }, - { "question", 500, NULL }, - { "equal", 570, NULL }, - { "Y", 722, NULL }, - { "Z", 667, NULL }, - { "four", 500, NULL }, - { "a", 500, NULL }, - { "Gcommaaccent", 778, NULL }, - { "b", 556, NULL }, - { "c", 444, NULL }, - { "d", 556, NULL }, - { "e", 444, NULL }, - { "f", 333, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 278, NULL }, - { "Oslash", 778, NULL }, - { "dagger", 500, NULL }, - { "j", 333, NULL }, - { "k", 556, NULL }, - { "l", 278, NULL }, - { "m", 833, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 333, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 300, NULL }, - { "ring", 333, NULL }, - { "p", 556, NULL }, - { "q", 556, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 444, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 500, NULL }, - { "s", 389, NULL }, - { "OE", 1000, NULL }, - { "t", 333, NULL }, - { "divide", 570, NULL }, - { "u", 556, NULL }, - { "Ccaron", 722, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 444, NULL }, - { "Gbreve", 778, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 389, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 555, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 556, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 556, NULL }, - { "Lslash", 667, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 778, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 389, NULL }, - { "AE", 1000, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 278, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 500, NULL }, - { "oe", 722, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 747, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 389, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 778, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 722, NULL }, - { "umacron", 556, NULL }, - { "abreve", 500, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 500, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 722, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 667, NULL }, - { "Scommaaccent", 556, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 722, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 930, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 570, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 556, NULL }, - { "Ograve", 778, NULL }, - { "Racute", 722, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 394, NULL }, - { "Thorn", 611, NULL }, - { "zcaron", 444, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 556, NULL }, - { "Ocircumflex", 778, NULL }, - { "Oacute", 778, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 444, NULL }, - { "Tcaron", 667, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 556, NULL }, - { "degree", 400, NULL }, - { "registered", 747, NULL }, - { "radical", 549, NULL }, - { "Aring", 722, NULL }, - { "percent", 1000, NULL }, - { "six", 500, NULL }, - { "paragraph", 540, NULL }, - { "dcaron", 672, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 389, NULL }, - { "Lacute", 667, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 667, NULL }, - { "tcaron", 416, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 778, NULL }, - { "asciicircum", 581, NULL }, - { "aring", 500, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 389, NULL }, - { "ampersand", 833, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 570, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 722, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 556, NULL }, - { "florin", 500, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 722, NULL }, - { "fi", 556, NULL }, - { "fl", 556, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 722, NULL }, - { "Icircumflex", 389, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 556, NULL }, - { "Amacron", 722, NULL }, - { "seven", 500, NULL }, - { "Sacute", 556, NULL }, - { "ordmasculine", 330, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 389, NULL }, - { "rcommaaccent", 444, NULL }, - { "Zdotaccent", 667, NULL }, - { "acircumflex", 500, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 394, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 500, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 570, NULL }, - { "zdotaccent", 444, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 220, NULL }, - { "fraction", 167, NULL }, - { "less", 570, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 250, NULL }, - { "Rcaron", 722, NULL }, - { "Kcommaaccent", 778, NULL }, - { "greater", 570, NULL }, - { "atilde", 500, NULL }, - { "brokenbar", 220, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth timesBoldItalicWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 570, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 570, NULL }, - { "colon", 333, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 556, NULL }, - { "Aogonek", 667, NULL }, - { "ncommaaccent", 556, NULL }, - { "minus", 606, NULL }, - { "Iogonek", 389, NULL }, - { "zacute", 389, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 722, NULL }, - { "questiondown", 500, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 667, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 382, NULL }, - { "A", 667, NULL }, - { "B", 667, NULL }, - { "C", 667, NULL }, - { "aogonek", 500, NULL }, - { "D", 722, NULL }, - { "E", 667, NULL }, - { "onequarter", 750, NULL }, - { "F", 667, NULL }, - { "G", 722, NULL }, - { "H", 778, NULL }, - { "I", 389, NULL }, - { "J", 500, NULL }, - { "K", 667, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 250, NULL }, - { "M", 889, NULL }, - { "N", 722, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 722, NULL }, - { "P", 611, NULL }, - { "Q", 722, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 667, NULL }, - { "Aacute", 667, NULL }, - { "caron", 333, NULL }, - { "S", 556, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 500, NULL }, - { "V", 667, NULL }, - { "W", 889, NULL }, - { "X", 667, NULL }, - { "question", 500, NULL }, - { "equal", 570, NULL }, - { "Y", 611, NULL }, - { "Z", 611, NULL }, - { "four", 500, NULL }, - { "a", 500, NULL }, - { "Gcommaaccent", 722, NULL }, - { "b", 500, NULL }, - { "c", 444, NULL }, - { "d", 500, NULL }, - { "e", 444, NULL }, - { "f", 333, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 556, NULL }, - { "i", 278, NULL }, - { "Oslash", 722, NULL }, - { "dagger", 500, NULL }, - { "j", 278, NULL }, - { "k", 500, NULL }, - { "l", 278, NULL }, - { "m", 778, NULL }, - { "n", 556, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 266, NULL }, - { "ring", 333, NULL }, - { "p", 500, NULL }, - { "q", 500, NULL }, - { "uhungarumlaut", 556, NULL }, - { "r", 389, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 500, NULL }, - { "s", 389, NULL }, - { "OE", 944, NULL }, - { "t", 278, NULL }, - { "divide", 570, NULL }, - { "u", 556, NULL }, - { "Ccaron", 667, NULL }, - { "v", 444, NULL }, - { "w", 667, NULL }, - { "x", 500, NULL }, - { "y", 444, NULL }, - { "z", 389, NULL }, - { "Gbreve", 722, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 389, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 555, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 576, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 556, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 494, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 667, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 1000, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 556, NULL }, - { "macron", 333, NULL }, - { "Otilde", 722, NULL }, - { "Emacron", 667, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 389, NULL }, - { "AE", 944, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 500, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 278, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 389, NULL }, - { "endash", 500, NULL }, - { "oe", 722, NULL }, - { "Abreve", 667, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 667, NULL }, - { "copyright", 747, NULL }, - { "Egrave", 667, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 667, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 389, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 722, NULL }, - { "ucircumflex", 556, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 611, NULL }, - { "umacron", 556, NULL }, - { "abreve", 500, NULL }, - { "Eacute", 667, NULL }, - { "adieresis", 500, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 722, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 556, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 556, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 556, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 667, NULL }, - { "ydieresis", 444, NULL }, - { "tilde", 333, NULL }, - { "at", 832, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 570, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 556, NULL }, - { "Ograve", 722, NULL }, - { "Racute", 667, NULL }, - { "partialdiff", 494, NULL }, - { "uacute", 556, NULL }, - { "braceleft", 348, NULL }, - { "Thorn", 611, NULL }, - { "zcaron", 389, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 500, NULL }, - { "Ocircumflex", 722, NULL }, - { "Oacute", 722, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 667, NULL }, - { "thorn", 500, NULL }, - { "degree", 400, NULL }, - { "registered", 747, NULL }, - { "radical", 549, NULL }, - { "Aring", 667, NULL }, - { "percent", 833, NULL }, - { "six", 500, NULL }, - { "paragraph", 500, NULL }, - { "dcaron", 608, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 389, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 366, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 722, NULL }, - { "asciicircum", 570, NULL }, - { "aring", 500, NULL }, - { "grave", 333, NULL }, - { "uogonek", 556, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 389, NULL }, - { "ampersand", 778, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 570, NULL }, - { "uring", 556, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 611, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 500, NULL }, - { "ncaron", 556, NULL }, - { "florin", 500, NULL }, - { "yacute", 444, NULL }, - { "Rcommaaccent", 667, NULL }, - { "fi", 556, NULL }, - { "fl", 556, NULL }, - { "Acircumflex", 667, NULL }, - { "Cacute", 667, NULL }, - { "Icircumflex", 389, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 500, NULL }, - { "Amacron", 667, NULL }, - { "seven", 500, NULL }, - { "Sacute", 556, NULL }, - { "ordmasculine", 300, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 389, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 500, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 667, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 348, NULL }, - { "quotedblright", 500, NULL }, - { "amacron", 500, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 606, NULL }, - { "zdotaccent", 389, NULL }, - { "Atilde", 667, NULL }, - { "breve", 333, NULL }, - { "bar", 220, NULL }, - { "fraction", 167, NULL }, - { "less", 570, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 389, NULL }, - { "period", 250, NULL }, - { "Rcaron", 667, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 570, NULL }, - { "atilde", 500, NULL }, - { "brokenbar", 220, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 667, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth timesItalicWidthsTab[] = { - { "Ntilde", 667, NULL }, - { "rcaron", 389, NULL }, - { "kcommaaccent", 444, NULL }, - { "Ncommaaccent", 667, NULL }, - { "Zacute", 556, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 675, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 541, NULL }, - { "colon", 333, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 500, NULL }, - { "Aogonek", 611, NULL }, - { "ncommaaccent", 500, NULL }, - { "minus", 675, NULL }, - { "Iogonek", 333, NULL }, - { "zacute", 389, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 722, NULL }, - { "questiondown", 500, NULL }, - { "emdash", 889, NULL }, - { "Agrave", 611, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 300, NULL }, - { "A", 611, NULL }, - { "B", 611, NULL }, - { "C", 667, NULL }, - { "aogonek", 500, NULL }, - { "D", 722, NULL }, - { "E", 611, NULL }, - { "onequarter", 750, NULL }, - { "F", 611, NULL }, - { "G", 722, NULL }, - { "H", 722, NULL }, - { "I", 333, NULL }, - { "J", 444, NULL }, - { "K", 667, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 556, NULL }, - { "periodcentered", 250, NULL }, - { "M", 833, NULL }, - { "N", 667, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 556, NULL }, - { "O", 722, NULL }, - { "P", 611, NULL }, - { "Q", 722, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 611, NULL }, - { "Aacute", 611, NULL }, - { "caron", 333, NULL }, - { "S", 500, NULL }, - { "T", 556, NULL }, - { "U", 722, NULL }, - { "agrave", 500, NULL }, - { "V", 611, NULL }, - { "W", 833, NULL }, - { "X", 611, NULL }, - { "question", 500, NULL }, - { "equal", 675, NULL }, - { "Y", 556, NULL }, - { "Z", 556, NULL }, - { "four", 500, NULL }, - { "a", 500, NULL }, - { "Gcommaaccent", 722, NULL }, - { "b", 500, NULL }, - { "c", 444, NULL }, - { "d", 500, NULL }, - { "e", 444, NULL }, - { "f", 278, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 500, NULL }, - { "i", 278, NULL }, - { "Oslash", 722, NULL }, - { "dagger", 500, NULL }, - { "j", 278, NULL }, - { "k", 444, NULL }, - { "l", 278, NULL }, - { "m", 722, NULL }, - { "n", 500, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 276, NULL }, - { "ring", 333, NULL }, - { "p", 500, NULL }, - { "q", 500, NULL }, - { "uhungarumlaut", 500, NULL }, - { "r", 389, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 500, NULL }, - { "s", 389, NULL }, - { "OE", 944, NULL }, - { "t", 278, NULL }, - { "divide", 675, NULL }, - { "u", 500, NULL }, - { "Ccaron", 667, NULL }, - { "v", 444, NULL }, - { "w", 667, NULL }, - { "x", 444, NULL }, - { "y", 444, NULL }, - { "z", 389, NULL }, - { "Gbreve", 722, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 333, NULL }, - { "Nacute", 667, NULL }, - { "quotedbl", 420, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 500, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 500, NULL }, - { "Lslash", 556, NULL }, - { "semicolon", 333, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 611, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 980, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 500, NULL }, - { "macron", 333, NULL }, - { "Otilde", 722, NULL }, - { "Emacron", 611, NULL }, - { "ellipsis", 889, NULL }, - { "scaron", 389, NULL }, - { "AE", 889, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 556, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 214, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 389, NULL }, - { "endash", 500, NULL }, - { "oe", 667, NULL }, - { "Abreve", 611, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 611, NULL }, - { "copyright", 760, NULL }, - { "Egrave", 611, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 611, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 333, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 722, NULL }, - { "ucircumflex", 500, NULL }, - { "bracketleft", 389, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 556, NULL }, - { "umacron", 500, NULL }, - { "abreve", 500, NULL }, - { "Eacute", 611, NULL }, - { "adieresis", 500, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 667, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 500, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 500, NULL }, - { "Zcaron", 556, NULL }, - { "Scommaaccent", 500, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 667, NULL }, - { "ydieresis", 444, NULL }, - { "tilde", 333, NULL }, - { "at", 920, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 675, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 500, NULL }, - { "Ograve", 722, NULL }, - { "Racute", 611, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 500, NULL }, - { "braceleft", 400, NULL }, - { "Thorn", 611, NULL }, - { "zcaron", 389, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 500, NULL }, - { "Ocircumflex", 722, NULL }, - { "Oacute", 722, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 389, NULL }, - { "Tcaron", 556, NULL }, - { "Eogonek", 611, NULL }, - { "thorn", 500, NULL }, - { "degree", 400, NULL }, - { "registered", 760, NULL }, - { "radical", 453, NULL }, - { "Aring", 611, NULL }, - { "percent", 833, NULL }, - { "six", 500, NULL }, - { "paragraph", 523, NULL }, - { "dcaron", 544, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 333, NULL }, - { "Lacute", 556, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 556, NULL }, - { "tcaron", 300, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 722, NULL }, - { "asciicircum", 422, NULL }, - { "aring", 500, NULL }, - { "grave", 333, NULL }, - { "uogonek", 500, NULL }, - { "bracketright", 389, NULL }, - { "Iacute", 333, NULL }, - { "ampersand", 778, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 667, NULL }, - { "plus", 675, NULL }, - { "uring", 500, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 556, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 556, NULL }, - { "ncaron", 500, NULL }, - { "florin", 500, NULL }, - { "yacute", 444, NULL }, - { "Rcommaaccent", 611, NULL }, - { "fi", 500, NULL }, - { "fl", 500, NULL }, - { "Acircumflex", 611, NULL }, - { "Cacute", 667, NULL }, - { "Icircumflex", 333, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 500, NULL }, - { "Amacron", 611, NULL }, - { "seven", 500, NULL }, - { "Sacute", 500, NULL }, - { "ordmasculine", 310, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 333, NULL }, - { "rcommaaccent", 389, NULL }, - { "Zdotaccent", 556, NULL }, - { "acircumflex", 500, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 611, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 400, NULL }, - { "quotedblright", 556, NULL }, - { "amacron", 500, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 675, NULL }, - { "zdotaccent", 389, NULL }, - { "Atilde", 611, NULL }, - { "breve", 333, NULL }, - { "bar", 275, NULL }, - { "fraction", 167, NULL }, - { "less", 675, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 250, NULL }, - { "Rcaron", 611, NULL }, - { "Kcommaaccent", 667, NULL }, - { "greater", 675, NULL }, - { "atilde", 500, NULL }, - { "brokenbar", 275, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 611, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth timesRomanWidthsTab[] = { - { "Ntilde", 722, NULL }, - { "rcaron", 333, NULL }, - { "kcommaaccent", 500, NULL }, - { "Ncommaaccent", 722, NULL }, - { "Zacute", 611, NULL }, - { "comma", 250, NULL }, - { "cedilla", 333, NULL }, - { "plusminus", 564, NULL }, - { "circumflex", 333, NULL }, - { "dotaccent", 333, NULL }, - { "edotaccent", 444, NULL }, - { "asciitilde", 541, NULL }, - { "colon", 278, NULL }, - { "onehalf", 750, NULL }, - { "dollar", 500, NULL }, - { "Lcaron", 611, NULL }, - { "ntilde", 500, NULL }, - { "Aogonek", 722, NULL }, - { "ncommaaccent", 500, NULL }, - { "minus", 564, NULL }, - { "Iogonek", 333, NULL }, - { "zacute", 444, NULL }, - { "yen", 500, NULL }, - { "space", 250, NULL }, - { "Omacron", 722, NULL }, - { "questiondown", 444, NULL }, - { "emdash", 1000, NULL }, - { "Agrave", 722, NULL }, - { "three", 500, NULL }, - { "numbersign", 500, NULL }, - { "lcaron", 344, NULL }, - { "A", 722, NULL }, - { "B", 667, NULL }, - { "C", 667, NULL }, - { "aogonek", 444, NULL }, - { "D", 722, NULL }, - { "E", 611, NULL }, - { "onequarter", 750, NULL }, - { "F", 556, NULL }, - { "G", 722, NULL }, - { "H", 722, NULL }, - { "I", 333, NULL }, - { "J", 389, NULL }, - { "K", 722, NULL }, - { "iogonek", 278, NULL }, - { "backslash", 278, NULL }, - { "L", 611, NULL }, - { "periodcentered", 250, NULL }, - { "M", 889, NULL }, - { "N", 722, NULL }, - { "omacron", 500, NULL }, - { "Tcommaaccent", 611, NULL }, - { "O", 722, NULL }, - { "P", 556, NULL }, - { "Q", 722, NULL }, - { "Uhungarumlaut", 722, NULL }, - { "R", 667, NULL }, - { "Aacute", 722, NULL }, - { "caron", 333, NULL }, - { "S", 556, NULL }, - { "T", 611, NULL }, - { "U", 722, NULL }, - { "agrave", 444, NULL }, - { "V", 722, NULL }, - { "W", 944, NULL }, - { "X", 722, NULL }, - { "question", 444, NULL }, - { "equal", 564, NULL }, - { "Y", 722, NULL }, - { "Z", 611, NULL }, - { "four", 500, NULL }, - { "a", 444, NULL }, - { "Gcommaaccent", 722, NULL }, - { "b", 500, NULL }, - { "c", 444, NULL }, - { "d", 500, NULL }, - { "e", 444, NULL }, - { "f", 333, NULL }, - { "g", 500, NULL }, - { "bullet", 350, NULL }, - { "h", 500, NULL }, - { "i", 278, NULL }, - { "Oslash", 722, NULL }, - { "dagger", 500, NULL }, - { "j", 278, NULL }, - { "k", 500, NULL }, - { "l", 278, NULL }, - { "m", 778, NULL }, - { "n", 500, NULL }, - { "tcommaaccent", 278, NULL }, - { "o", 500, NULL }, - { "ordfeminine", 276, NULL }, - { "ring", 333, NULL }, - { "p", 500, NULL }, - { "q", 500, NULL }, - { "uhungarumlaut", 500, NULL }, - { "r", 333, NULL }, - { "twosuperior", 300, NULL }, - { "aacute", 444, NULL }, - { "s", 389, NULL }, - { "OE", 889, NULL }, - { "t", 278, NULL }, - { "divide", 564, NULL }, - { "u", 500, NULL }, - { "Ccaron", 667, NULL }, - { "v", 500, NULL }, - { "w", 722, NULL }, - { "x", 500, NULL }, - { "y", 500, NULL }, - { "z", 444, NULL }, - { "Gbreve", 722, NULL }, - { "commaaccent", 250, NULL }, - { "hungarumlaut", 333, NULL }, - { "Idotaccent", 333, NULL }, - { "Nacute", 722, NULL }, - { "quotedbl", 408, NULL }, - { "gcommaaccent", 500, NULL }, - { "mu", 500, NULL }, - { "greaterequal", 549, NULL }, - { "Scaron", 556, NULL }, - { "Lslash", 611, NULL }, - { "semicolon", 278, NULL }, - { "oslash", 500, NULL }, - { "lessequal", 549, NULL }, - { "lozenge", 471, NULL }, - { "parenright", 333, NULL }, - { "ccaron", 444, NULL }, - { "Ecircumflex", 611, NULL }, - { "gbreve", 500, NULL }, - { "trademark", 980, NULL }, - { "daggerdbl", 500, NULL }, - { "nacute", 500, NULL }, - { "macron", 333, NULL }, - { "Otilde", 722, NULL }, - { "Emacron", 611, NULL }, - { "ellipsis", 1000, NULL }, - { "scaron", 389, NULL }, - { "AE", 889, NULL }, - { "Ucircumflex", 722, NULL }, - { "lslash", 278, NULL }, - { "quotedblleft", 444, NULL }, - { "guilsinglright", 333, NULL }, - { "hyphen", 333, NULL }, - { "quotesingle", 180, NULL }, - { "eight", 500, NULL }, - { "exclamdown", 333, NULL }, - { "endash", 500, NULL }, - { "oe", 722, NULL }, - { "Abreve", 722, NULL }, - { "Umacron", 722, NULL }, - { "ecircumflex", 444, NULL }, - { "Adieresis", 722, NULL }, - { "copyright", 760, NULL }, - { "Egrave", 611, NULL }, - { "slash", 278, NULL }, - { "Edieresis", 611, NULL }, - { "otilde", 500, NULL }, - { "Idieresis", 333, NULL }, - { "parenleft", 333, NULL }, - { "one", 500, NULL }, - { "emacron", 444, NULL }, - { "Odieresis", 722, NULL }, - { "ucircumflex", 500, NULL }, - { "bracketleft", 333, NULL }, - { "Ugrave", 722, NULL }, - { "quoteright", 333, NULL }, - { "Udieresis", 722, NULL }, - { "perthousand", 1000, NULL }, - { "Ydieresis", 722, NULL }, - { "umacron", 500, NULL }, - { "abreve", 444, NULL }, - { "Eacute", 611, NULL }, - { "adieresis", 444, NULL }, - { "egrave", 444, NULL }, - { "edieresis", 444, NULL }, - { "idieresis", 278, NULL }, - { "Eth", 722, NULL }, - { "ae", 667, NULL }, - { "asterisk", 500, NULL }, - { "odieresis", 500, NULL }, - { "Uacute", 722, NULL }, - { "ugrave", 500, NULL }, - { "nine", 500, NULL }, - { "five", 500, NULL }, - { "udieresis", 500, NULL }, - { "Zcaron", 611, NULL }, - { "Scommaaccent", 556, NULL }, - { "threequarters", 750, NULL }, - { "guillemotright", 500, NULL }, - { "Ccedilla", 667, NULL }, - { "ydieresis", 500, NULL }, - { "tilde", 333, NULL }, - { "at", 921, NULL }, - { "eacute", 444, NULL }, - { "underscore", 500, NULL }, - { "Euro", 500, NULL }, - { "Dcroat", 722, NULL }, - { "multiply", 564, NULL }, - { "zero", 500, NULL }, - { "eth", 500, NULL }, - { "Scedilla", 556, NULL }, - { "Ograve", 722, NULL }, - { "Racute", 667, NULL }, - { "partialdiff", 476, NULL }, - { "uacute", 500, NULL }, - { "braceleft", 480, NULL }, - { "Thorn", 556, NULL }, - { "zcaron", 444, NULL }, - { "scommaaccent", 389, NULL }, - { "ccedilla", 444, NULL }, - { "Dcaron", 722, NULL }, - { "dcroat", 500, NULL }, - { "Ocircumflex", 722, NULL }, - { "Oacute", 722, NULL }, - { "scedilla", 389, NULL }, - { "ogonek", 333, NULL }, - { "ograve", 500, NULL }, - { "racute", 333, NULL }, - { "Tcaron", 611, NULL }, - { "Eogonek", 611, NULL }, - { "thorn", 500, NULL }, - { "degree", 400, NULL }, - { "registered", 760, NULL }, - { "radical", 453, NULL }, - { "Aring", 722, NULL }, - { "percent", 833, NULL }, - { "six", 500, NULL }, - { "paragraph", 453, NULL }, - { "dcaron", 588, NULL }, - { "Uogonek", 722, NULL }, - { "two", 500, NULL }, - { "summation", 600, NULL }, - { "Igrave", 333, NULL }, - { "Lacute", 611, NULL }, - { "ocircumflex", 500, NULL }, - { "oacute", 500, NULL }, - { "Uring", 722, NULL }, - { "Lcommaaccent", 611, NULL }, - { "tcaron", 326, NULL }, - { "eogonek", 444, NULL }, - { "Delta", 612, NULL }, - { "Ohungarumlaut", 722, NULL }, - { "asciicircum", 469, NULL }, - { "aring", 444, NULL }, - { "grave", 333, NULL }, - { "uogonek", 500, NULL }, - { "bracketright", 333, NULL }, - { "Iacute", 333, NULL }, - { "ampersand", 778, NULL }, - { "igrave", 278, NULL }, - { "lacute", 278, NULL }, - { "Ncaron", 722, NULL }, - { "plus", 564, NULL }, - { "uring", 500, NULL }, - { "quotesinglbase", 333, NULL }, - { "lcommaaccent", 278, NULL }, - { "Yacute", 722, NULL }, - { "ohungarumlaut", 500, NULL }, - { "threesuperior", 300, NULL }, - { "acute", 333, NULL }, - { "section", 500, NULL }, - { "dieresis", 333, NULL }, - { "iacute", 278, NULL }, - { "quotedblbase", 444, NULL }, - { "ncaron", 500, NULL }, - { "florin", 500, NULL }, - { "yacute", 500, NULL }, - { "Rcommaaccent", 667, NULL }, - { "fi", 556, NULL }, - { "fl", 556, NULL }, - { "Acircumflex", 722, NULL }, - { "Cacute", 667, NULL }, - { "Icircumflex", 333, NULL }, - { "guillemotleft", 500, NULL }, - { "germandbls", 500, NULL }, - { "Amacron", 722, NULL }, - { "seven", 500, NULL }, - { "Sacute", 556, NULL }, - { "ordmasculine", 310, NULL }, - { "dotlessi", 278, NULL }, - { "sterling", 500, NULL }, - { "notequal", 549, NULL }, - { "Imacron", 333, NULL }, - { "rcommaaccent", 333, NULL }, - { "Zdotaccent", 611, NULL }, - { "acircumflex", 444, NULL }, - { "cacute", 444, NULL }, - { "Ecaron", 611, NULL }, - { "icircumflex", 278, NULL }, - { "braceright", 480, NULL }, - { "quotedblright", 444, NULL }, - { "amacron", 444, NULL }, - { "sacute", 389, NULL }, - { "imacron", 278, NULL }, - { "cent", 500, NULL }, - { "currency", 500, NULL }, - { "logicalnot", 564, NULL }, - { "zdotaccent", 444, NULL }, - { "Atilde", 722, NULL }, - { "breve", 333, NULL }, - { "bar", 200, NULL }, - { "fraction", 167, NULL }, - { "less", 564, NULL }, - { "ecaron", 444, NULL }, - { "guilsinglleft", 333, NULL }, - { "exclam", 333, NULL }, - { "period", 250, NULL }, - { "Rcaron", 667, NULL }, - { "Kcommaaccent", 722, NULL }, - { "greater", 564, NULL }, - { "atilde", 444, NULL }, - { "brokenbar", 200, NULL }, - { "quoteleft", 333, NULL }, - { "Edotaccent", 611, NULL }, - { "onesuperior", 300, NULL } -}; - -static BuiltinFontWidth zapfDingbatsWidthsTab[] = { - { "a81", 438, NULL }, - { "a82", 138, NULL }, - { "a83", 277, NULL }, - { "a84", 415, NULL }, - { "a85", 509, NULL }, - { "a86", 410, NULL }, - { "a87", 234, NULL }, - { "a88", 234, NULL }, - { "a89", 390, NULL }, - { "a140", 788, NULL }, - { "a141", 788, NULL }, - { "a142", 788, NULL }, - { "a143", 788, NULL }, - { "a144", 788, NULL }, - { "a145", 788, NULL }, - { "a146", 788, NULL }, - { "a147", 788, NULL }, - { "a148", 788, NULL }, - { "a149", 788, NULL }, - { "a90", 390, NULL }, - { "a91", 276, NULL }, - { "a92", 276, NULL }, - { "space", 278, NULL }, - { "a93", 317, NULL }, - { "a94", 317, NULL }, - { "a95", 334, NULL }, - { "a96", 334, NULL }, - { "a97", 392, NULL }, - { "a98", 392, NULL }, - { "a99", 668, NULL }, - { "a150", 788, NULL }, - { "a151", 788, NULL }, - { "a152", 788, NULL }, - { "a153", 788, NULL }, - { "a154", 788, NULL }, - { "a155", 788, NULL }, - { "a156", 788, NULL }, - { "a157", 788, NULL }, - { "a158", 788, NULL }, - { "a159", 788, NULL }, - { "a160", 894, NULL }, - { "a161", 838, NULL }, - { "a162", 924, NULL }, - { "a163", 1016, NULL }, - { "a164", 458, NULL }, - { "a165", 924, NULL }, - { "a166", 918, NULL }, - { "a167", 927, NULL }, - { "a168", 928, NULL }, - { "a169", 928, NULL }, - { "a170", 834, NULL }, - { "a171", 873, NULL }, - { "a172", 828, NULL }, - { "a173", 924, NULL }, - { "a174", 917, NULL }, - { "a175", 930, NULL }, - { "a176", 931, NULL }, - { "a177", 463, NULL }, - { "a178", 883, NULL }, - { "a179", 836, NULL }, - { "a180", 867, NULL }, - { "a181", 696, NULL }, - { "a182", 874, NULL }, - { "a183", 760, NULL }, - { "a184", 946, NULL }, - { "a185", 865, NULL }, - { "a186", 967, NULL }, - { "a187", 831, NULL }, - { "a188", 873, NULL }, - { "a189", 927, NULL }, - { "a1", 974, NULL }, - { "a2", 961, NULL }, - { "a3", 980, NULL }, - { "a4", 719, NULL }, - { "a5", 789, NULL }, - { "a6", 494, NULL }, - { "a7", 552, NULL }, - { "a8", 537, NULL }, - { "a9", 577, NULL }, - { "a190", 970, NULL }, - { "a191", 918, NULL }, - { "a192", 748, NULL }, - { "a193", 836, NULL }, - { "a194", 771, NULL }, - { "a195", 888, NULL }, - { "a196", 748, NULL }, - { "a197", 771, NULL }, - { "a198", 888, NULL }, - { "a199", 867, NULL }, - { "a10", 692, NULL }, - { "a11", 960, NULL }, - { "a12", 939, NULL }, - { "a13", 549, NULL }, - { "a14", 855, NULL }, - { "a15", 911, NULL }, - { "a16", 933, NULL }, - { "a17", 945, NULL }, - { "a18", 974, NULL }, - { "a19", 755, NULL }, - { "a20", 846, NULL }, - { "a21", 762, NULL }, - { "a22", 761, NULL }, - { "a23", 571, NULL }, - { "a24", 677, NULL }, - { "a25", 763, NULL }, - { "a26", 760, NULL }, - { "a27", 759, NULL }, - { "a28", 754, NULL }, - { "a29", 786, NULL }, - { "a30", 788, NULL }, - { "a31", 788, NULL }, - { "a32", 790, NULL }, - { "a33", 793, NULL }, - { "a34", 794, NULL }, - { "a35", 816, NULL }, - { "a36", 823, NULL }, - { "a37", 789, NULL }, - { "a38", 841, NULL }, - { "a39", 823, NULL }, - { "a40", 833, NULL }, - { "a41", 816, NULL }, - { "a42", 831, NULL }, - { "a43", 923, NULL }, - { "a44", 744, NULL }, - { "a45", 723, NULL }, - { "a46", 749, NULL }, - { "a47", 790, NULL }, - { "a48", 792, NULL }, - { "a49", 695, NULL }, - { "a100", 668, NULL }, - { "a101", 732, NULL }, - { "a102", 544, NULL }, - { "a103", 544, NULL }, - { "a104", 910, NULL }, - { "a105", 911, NULL }, - { "a106", 667, NULL }, - { "a107", 760, NULL }, - { "a108", 760, NULL }, - { "a109", 626, NULL }, - { "a50", 776, NULL }, - { "a51", 768, NULL }, - { "a52", 792, NULL }, - { "a53", 759, NULL }, - { "a54", 707, NULL }, - { "a55", 708, NULL }, - { "a56", 682, NULL }, - { "a57", 701, NULL }, - { "a58", 826, NULL }, - { "a59", 815, NULL }, - { "a110", 694, NULL }, - { "a111", 595, NULL }, - { "a112", 776, NULL }, - { "a117", 690, NULL }, - { "a118", 791, NULL }, - { "a119", 790, NULL }, - { "a60", 789, NULL }, - { "a61", 789, NULL }, - { "a62", 707, NULL }, - { "a63", 687, NULL }, - { "a64", 696, NULL }, - { "a65", 689, NULL }, - { "a66", 786, NULL }, - { "a67", 787, NULL }, - { "a68", 713, NULL }, - { "a69", 791, NULL }, - { "a200", 696, NULL }, - { "a201", 874, NULL }, - { "a120", 788, NULL }, - { "a121", 788, NULL }, - { "a202", 974, NULL }, - { "a122", 788, NULL }, - { "a203", 762, NULL }, - { "a123", 788, NULL }, - { "a204", 759, NULL }, - { "a124", 788, NULL }, - { "a205", 509, NULL }, - { "a125", 788, NULL }, - { "a206", 410, NULL }, - { "a126", 788, NULL }, - { "a127", 788, NULL }, - { "a128", 788, NULL }, - { "a129", 788, NULL }, - { "a70", 785, NULL }, - { "a71", 791, NULL }, - { "a72", 873, NULL }, - { "a73", 761, NULL }, - { "a74", 762, NULL }, - { "a75", 759, NULL }, - { "a76", 892, NULL }, - { "a77", 892, NULL }, - { "a78", 788, NULL }, - { "a79", 784, NULL }, - { "a130", 788, NULL }, - { "a131", 788, NULL }, - { "a132", 788, NULL }, - { "a133", 788, NULL }, - { "a134", 788, NULL }, - { "a135", 788, NULL }, - { "a136", 788, NULL }, - { "a137", 788, NULL }, - { "a138", 788, NULL }, - { "a139", 788, NULL } -}; - -BuiltinFont builtinFonts[] = { - { "Courier", standardEncoding, 629, -157, { -23, -250, 715, 805}, NULL }, - { "Courier-Bold", standardEncoding, 629, -157, {-113, -250, 749, 801}, NULL }, - { "Courier-BoldOblique", standardEncoding, 629, -157, { -57, -250, 869, 801}, NULL }, - { "Courier-Oblique", standardEncoding, 629, -157, { -27, -250, 849, 805}, NULL }, - { "Helvetica", standardEncoding, 718, -207, {-166, -225, 1000, 931}, NULL }, - { "Helvetica-Bold", standardEncoding, 718, -207, {-170, -228, 1003, 962}, NULL }, - { "Helvetica-BoldOblique", standardEncoding, 718, -207, {-174, -228, 1114, 962}, NULL }, - { "Helvetica-Oblique", standardEncoding, 718, -207, {-170, -225, 1116, 931}, NULL }, - { "Symbol", symbolEncoding, 1010, -293, {-180, -293, 1090, 1010}, NULL }, - { "Times-Bold", standardEncoding, 683, -217, {-168, -218, 1000, 935}, NULL }, - { "Times-BoldItalic", standardEncoding, 683, -217, {-200, -218, 996, 921}, NULL }, - { "Times-Italic", standardEncoding, 683, -217, {-169, -217, 1010, 883}, NULL }, - { "Times-Roman", standardEncoding, 683, -217, {-168, -218, 1000, 898}, NULL }, - { "ZapfDingbats", zapfDingbatsEncoding, 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/pdf2swf/xpdf/BuiltinFontTables.h b/pdf2swf/xpdf/BuiltinFontTables.h deleted file mode 100644 index eb45549..0000000 --- a/pdf2swf/xpdf/BuiltinFontTables.h +++ /dev/null @@ -1,23 +0,0 @@ -//======================================================================== -// -// 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/pdf2swf/xpdf/CMap.cc b/pdf2swf/xpdf/CMap.cc deleted file mode 100644 index 303cf09..0000000 --- a/pdf2swf/xpdf/CMap.cc +++ /dev/null @@ -1,408 +0,0 @@ -//======================================================================== -// -// CMap.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#include "gmem.h" -#include "gfile.h" -#include "GString.h" -#include "Error.h" -#include "GlobalParams.h" -#include "PSTokenizer.h" -#include "CMap.h" - -//------------------------------------------------------------------------ - -struct CMapVectorEntry { - GBool isVector; - union { - CMapVectorEntry *vector; - CID cid; - }; -}; - -//------------------------------------------------------------------------ - -static int getCharFromFile(void *data) { - return fgetc((FILE *)data); -} - -//------------------------------------------------------------------------ - -CMap *CMap::parse(CMapCache *cache, GString *collectionA, - GString *cMapNameA) { - FILE *f; - CMap *cmap; - PSTokenizer *pst; - char tok1[256], tok2[256], tok3[256]; - int n1, n2, n3; - Guint start, end, code; - - 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(-1, "Couldn't find '%s' CMap file for '%s' collection", - cMapNameA->getCString(), collectionA->getCString()); - return NULL; - } - - cmap = new CMap(collectionA->copy(), cMapNameA->copy()); - - pst = new PSTokenizer(&getCharFromFile, f); - pst->getToken(tok1, sizeof(tok1), &n1); - while (pst->getToken(tok2, sizeof(tok2), &n2)) { - if (!strcmp(tok2, "usecmap")) { - if (tok1[0] == '/') { - cmap->useCMap(cache, tok1 + 1); - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok1, "/WMode")) { - cmap->wMode = atoi(tok2); - pst->getToken(tok1, sizeof(tok1), &n1); - } else if (!strcmp(tok2, "begincodespacerange")) { - while (pst->getToken(tok1, sizeof(tok1), &n1)) { - if (!strcmp(tok1, "endcodespacerange")) { - break; - } - if (!pst->getToken(tok2, sizeof(tok2), &n2) || - !strcmp(tok2, "endcodespacerange")) { - error(-1, "Illegal entry in codespacerange block in CMap"); - break; - } - if (tok1[0] == '<' && tok2[0] == '<' && - n1 == n2 && n1 >= 4 && (n1 & 1) == 0) { - tok1[n1 - 1] = tok2[n1 - 1] = '\0'; - sscanf(tok1 + 1, "%x", &start); - sscanf(tok2 + 1, "%x", &end); - n1 = (n1 - 2) / 2; - cmap->addCodeSpace(cmap->vector, start, end, n1); - } - } - 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(-1, "Illegal entry in cidchar block in CMap"); - break; - } - if (!(tok1[0] == '<' && tok1[n1 - 1] == '>' && - n1 >= 4 && (n1 & 1) == 0)) { - error(-1, "Illegal entry in cidchar block in CMap"); - continue; - } - tok1[n1 - 1] = '\0'; - if (sscanf(tok1 + 1, "%x", &code) != 1) { - error(-1, "Illegal entry in cidchar block in CMap"); - continue; - } - n1 = (n1 - 2) / 2; - cmap->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(-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; - cmap->addCIDs(start, end, n1, (CID)atoi(tok3)); - } - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else { - strcpy(tok1, tok2); - } - } - delete pst; - - fclose(f); - - return cmap; -} - -CMap::CMap(GString *collectionA, GString *cMapNameA) { - int i; - - collection = collectionA; - cMapName = cMapNameA; - wMode = 0; - vector = (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); - for (i = 0; i < 256; ++i) { - vector[i].isVector = gFalse; - vector[i].cid = 0; - } - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -CMap::CMap(GString *collectionA, GString *cMapNameA, int wModeA) { - collection = collectionA; - cMapName = cMapNameA; - wMode = wModeA; - vector = NULL; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -void CMap::useCMap(CMapCache *cache, char *useName) { - GString *useNameStr; - CMap *subCMap; - - useNameStr = new GString(useName); - subCMap = cache->getCMap(collection, useNameStr); - delete useNameStr; - if (!subCMap) { - return; - } - 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(-1, "Collision in usecmap"); - } else { - dest[i].cid = src[i].cid; - } - } - } -} - -void CMap::addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end, - Guint nBytes) { - Guint start2, end2; - int startByte, endByte, i, j; - - if (nBytes > 1) { - startByte = (start >> (8 * (nBytes - 1))) & 0xff; - endByte = (end >> (8 * (nBytes - 1))) & 0xff; - start2 = start & ((1 << (8 * (nBytes - 1))) - 1); - end2 = end & ((1 << (8 * (nBytes - 1))) - 1); - for (i = startByte; i <= endByte; ++i) { - if (!vec[i].isVector) { - vec[i].isVector = gTrue; - vec[i].vector = - (CMapVectorEntry *)gmallocn(256, sizeof(CMapVectorEntry)); - for (j = 0; j < 256; ++j) { - vec[i].vector[j].isVector = gFalse; - vec[i].vector[j].cid = 0; - } - } - addCodeSpace(vec[i].vector, start2, end2, nBytes - 1); - } - } -} - -void CMap::addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID) { - CMapVectorEntry *vec; - CID cid; - int byte; - Guint i; - - vec = vector; - for (i = nBytes - 1; i >= 1; --i) { - byte = (start >> (8 * i)) & 0xff; - if (!vec[byte].isVector) { - error(-1, "Invalid CID (%0*x - %0*x) in CMap", - 2*nBytes, start, 2*nBytes, end); - return; - } - vec = vec[byte].vector; - } - cid = firstCID; - for (byte = (int)(start & 0xff); byte <= (int)(end & 0xff); ++byte) { - if (vec[byte].isVector) { - error(-1, "Invalid CID (%0*x - %0*x) in CMap", - 2*nBytes, start, 2*nBytes, end); - } else { - vec[byte].cid = cid; - } - ++cid; - } -} - -CMap::~CMap() { - delete collection; - delete cMapName; - if (vector) { - freeCMapVector(vector); - } -#if MULTITHREADED - gDestroyMutex(&mutex); -#endif -} - -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 - gLockMutex(&mutex); -#endif - ++refCnt; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif -} - -void CMap::decRefCnt() { - GBool done; - -#if MULTITHREADED - gLockMutex(&mutex); -#endif - done = --refCnt == 0; -#if MULTITHREADED - gUnlockMutex(&mutex); -#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, int *nUsed) { - CMapVectorEntry *vec; - int n, i; - - if (!(vec = vector)) { - // identity CMap - *nUsed = 2; - if (len < 2) { - return 0; - } - return ((s[0] & 0xff) << 8) + (s[1] & 0xff); - } - n = 0; - while (1) { - if (n >= len) { - *nUsed = n; - return 0; - } - i = s[n++] & 0xff; - if (!vec[i].isVector) { - *nUsed = n; - return vec[i].cid; - } - vec = vec[i].vector; - } -} - -//------------------------------------------------------------------------ - -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/pdf2swf/xpdf/CMap.h b/pdf2swf/xpdf/CMap.h deleted file mode 100644 index c321a57..0000000 --- a/pdf2swf/xpdf/CMap.h +++ /dev/null @@ -1,102 +0,0 @@ -//======================================================================== -// -// CMap.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CMAP_H -#define CMAP_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -class GString; -struct CMapVectorEntry; -class CMapCache; - -//------------------------------------------------------------------------ - -class CMap { -public: - - // Create the CMap specified by and . Sets - // the initial reference count to 1. Returns NULL on failure. - static CMap *parse(CMapCache *cache, GString *collectionA, - GString *cMapNameA); - - ~CMap(); - - void incRefCnt(); - void decRefCnt(); - - // Return collection name (-). - GString *getCollection() { return collection; } - - // Return true if this CMap matches the specified , and - // . - GBool match(GString *collectionA, GString *cMapNameA); - - // Return the CID corresponding to the character code starting at - // , which contains bytes. Sets * to the number of - // bytes used by the char code. - CID getCID(char *s, int len, int *nUsed); - - // Return the writing mode (0=horizontal, 1=vertical). - int getWMode() { return wMode; } - -private: - - CMap(GString *collectionA, GString *cMapNameA); - CMap(GString *collectionA, GString *cMapNameA, int wModeA); - void useCMap(CMapCache *cache, char *useName); - void copyVector(CMapVectorEntry *dest, CMapVectorEntry *src); - void addCodeSpace(CMapVectorEntry *vec, Guint start, Guint end, - Guint nBytes); - void addCIDs(Guint start, Guint end, Guint nBytes, CID firstCID); - void freeCMapVector(CMapVectorEntry *vec); - - GString *collection; - GString *cMapName; - int wMode; // writing mode (0=horizontal, 1=vertical) - CMapVectorEntry *vector; // vector for first byte (NULL for - // identity CMap) - int refCnt; -#if MULTITHREADED - GMutex mutex; -#endif -}; - -//------------------------------------------------------------------------ - -#define cMapCacheSize 4 - -class CMapCache { -public: - - CMapCache(); - ~CMapCache(); - - // Get the CMap for the specified character collection. - // Increments its reference count; there will be one reference for - // the cache plus one for the caller of this function. Returns NULL - // on failure. - CMap *getCMap(GString *collection, GString *cMapName); - -private: - - CMap *cache[cMapCacheSize]; -}; - -#endif diff --git a/pdf2swf/xpdf/Catalog.cc b/pdf2swf/xpdf/Catalog.cc deleted file mode 100644 index fd235d6..0000000 --- a/pdf2swf/xpdf/Catalog.cc +++ /dev/null @@ -1,353 +0,0 @@ -//======================================================================== -// -// Catalog.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "gmem.h" -#include "Object.h" -#include "XRef.h" -#include "Array.h" -#include "Dict.h" -#include "Page.h" -#include "Error.h" -#include "Link.h" -#include "Catalog.h" - -//------------------------------------------------------------------------ -// Catalog -//------------------------------------------------------------------------ - -Catalog::Catalog(XRef *xrefA) { - Object catDict, pagesDict; - Object obj, obj2; - int numPages0; - int i; - - ok = gTrue; - xref = xrefA; - pages = NULL; - pageRefs = NULL; - numPages = pagesSize = 0; - baseURI = NULL; - - xref->getCatalog(&catDict); - if (!catDict.isDict()) { - error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName()); - goto err1; - } - - // read page tree - catDict.dictLookup("Pages", &pagesDict); - // This should really be isDict("Pages"), but I've seen at least one - // PDF file where the /Type entry is missing. - if (!pagesDict.isDict()) { - error(-1, "Top-level pages object is wrong type (%s)", - pagesDict.getTypeName()); - goto err2; - } - pagesDict.dictLookup("Count", &obj); - // some PDF files actually use real numbers here ("/Count 9.0") - if (!obj.isNum()) { - error(-1, "Page count in top-level pages object is wrong type (%s)", - obj.getTypeName()); - goto err3; - } - pagesSize = numPages0 = (int)obj.getNum(); - obj.free(); - pages = (Page **)gmallocn(pagesSize, sizeof(Page *)); - pageRefs = (Ref *)gmallocn(pagesSize, sizeof(Ref)); - for (i = 0; i < pagesSize; ++i) { - pages[i] = NULL; - pageRefs[i].num = -1; - pageRefs[i].gen = -1; - } - numPages = readPageTree(pagesDict.getDict(), NULL, 0); - if (numPages != numPages0) { - error(-1, "Page count in top-level pages object is incorrect"); - } - pagesDict.free(); - - // 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(); - - // 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); - - catDict.free(); - return; - - err3: - obj.free(); - err2: - pagesDict.free(); - err1: - catDict.free(); - dests.initNull(); - nameTree.initNull(); - ok = gFalse; -} - -Catalog::~Catalog() { - int i; - - if (pages) { - for (i = 0; i < pagesSize; ++i) { - if (pages[i]) { - delete pages[i]; - } - } - gfree(pages); - gfree(pageRefs); - } - dests.free(); - nameTree.free(); - if (baseURI) { - delete baseURI; - } - metadata.free(); - structTreeRoot.free(); - outline.free(); - acroForm.free(); -} - -GString *Catalog::readMetadata() { - GString *s; - Dict *dict; - Object obj; - int c; - - if (!metadata.isStream()) { - return NULL; - } - dict = metadata.streamGetDict(); - if (!dict->lookup("Subtype", &obj)->isName("XML")) { - error(-1, "Unknown Metadata type: '%s'", - obj.isName() ? obj.getName() : "???"); - } - obj.free(); - s = new GString(); - metadata.streamReset(); - while ((c = metadata.streamGetChar()) != EOF) { - s->append(c); - } - metadata.streamClose(); - return s; -} - -int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) { - Object kids; - Object kid; - Object kidRef; - PageAttrs *attrs1, *attrs2; - Page *page; - int i, j; - - attrs1 = new PageAttrs(attrs, pagesDict); - pagesDict->lookup("Kids", &kids); - if (!kids.isArray()) { - error(-1, "Kids object (page %d) is wrong type (%s)", - start+1, kids.getTypeName()); - goto err1; - } - for (i = 0; i < kids.arrayGetLength(); ++i) { - kids.arrayGet(i, &kid); - if (kid.isDict("Page")) { - attrs2 = new PageAttrs(attrs1, kid.getDict()); - page = new Page(xref, start+1, kid.getDict(), attrs2); - if (!page->isOk()) { - ++start; - goto err3; - } - if (start >= pagesSize) { - pagesSize += 32; - pages = (Page **)greallocn(pages, pagesSize, sizeof(Page *)); - pageRefs = (Ref *)greallocn(pageRefs, pagesSize, sizeof(Ref)); - for (j = pagesSize - 32; j < pagesSize; ++j) { - pages[j] = NULL; - pageRefs[j].num = -1; - pageRefs[j].gen = -1; - } - } - pages[start] = page; - kids.arrayGetNF(i, &kidRef); - if (kidRef.isRef()) { - pageRefs[start].num = kidRef.getRefNum(); - pageRefs[start].gen = kidRef.getRefGen(); - } - kidRef.free(); - ++start; - // This should really be isDict("Pages"), but I've seen at least one - // PDF file where the /Type entry is missing. - } else if (kid.isDict()) { - if ((start = readPageTree(kid.getDict(), attrs1, start)) - < 0) - goto err2; - } else { - error(-1, "Kid object (page %d) is wrong type (%s)", - start+1, kid.getTypeName()); - } - kid.free(); - } - delete attrs1; - kids.free(); - return start; - - err3: - delete page; - err2: - kid.free(); - err1: - kids.free(); - delete attrs1; - ok = gFalse; - return -1; -} - -int Catalog::findPage(int num, int gen) { - int i; - - for (i = 0; i < numPages; ++i) { - if (pageRefs[i].num == num && pageRefs[i].gen == gen) - return i + 1; - } - 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(-1, "Bad named destination value"); - obj2.free(); - } else { - error(-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; -} diff --git a/pdf2swf/xpdf/Catalog.h b/pdf2swf/xpdf/Catalog.h deleted file mode 100644 index c38f109..0000000 --- a/pdf2swf/xpdf/Catalog.h +++ /dev/null @@ -1,92 +0,0 @@ -//======================================================================== -// -// Catalog.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CATALOG_H -#define CATALOG_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -class XRef; -class Object; -class Page; -class PageAttrs; -struct Ref; -class LinkDest; - -//------------------------------------------------------------------------ -// Catalog -//------------------------------------------------------------------------ - -class Catalog { -public: - - // Constructor. - Catalog(XRef *xrefA); - - // Destructor. - ~Catalog(); - - // Is catalog valid? - GBool isOk() { return ok; } - - // Get number of pages. - int getNumPages() { return numPages; } - - // Get a page. - Page *getPage(int i) { return pages[i-1]; } - - // Get the reference for a page object. - Ref *getPageRef(int i) { return &pageRefs[i-1]; } - - // Return base URI, or NULL if none. - GString *getBaseURI() { return baseURI; } - - // Return the contents of the metadata stream, or NULL if there is - // no metadata. - GString *readMetadata(); - - // Return the structure tree root object. - Object *getStructTreeRoot() { return &structTreeRoot; } - - // Find a page, given its object ID. Returns page number, or 0 if - // not found. - int findPage(int num, int gen); - - // Find a named destination. Returns the link destination, or - // NULL if is not a destination. - LinkDest *findDest(GString *name); - - Object *getOutline() { return &outline; } - - Object *getAcroForm() { return &acroForm; } - -private: - - XRef *xref; // the xref table for this PDF file - Page **pages; // array of pages - Ref *pageRefs; // object ID for each page - int numPages; // number of pages - int pagesSize; // size of pages array - 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 ok; // true if catalog is valid - - int readPageTree(Dict *pages, PageAttrs *attrs, int start); - Object *findDestInTree(Object *tree, GString *name, Object *obj); -}; - -#endif diff --git a/pdf2swf/xpdf/CharCodeToUnicode.cc b/pdf2swf/xpdf/CharCodeToUnicode.cc deleted file mode 100644 index 3702a16..0000000 --- a/pdf2swf/xpdf/CharCodeToUnicode.cc +++ /dev/null @@ -1,540 +0,0 @@ -//======================================================================== -// -// CharCodeToUnicode.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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; -}; - -//------------------------------------------------------------------------ - -static int getCharFromString(void *data) { - char *p; - int c; - - p = *(char **)data; - if (*p) { - c = *p++; - *(char **)data = p; - } else { - c = EOF; - } - return c; -} - -static int getCharFromFile(void *data) { - return fgetc((FILE *)data); -} - -//------------------------------------------------------------------------ - -CharCodeToUnicode *CharCodeToUnicode::parseCIDToUnicode(GString *fileName, - GString *collection) { - FILE *f; - Unicode *mapA; - CharCode size, mapLenA; - char buf[64]; - Unicode u; - CharCodeToUnicode *ctu; - - if (!(f = fopen(fileName->getCString(), "r"))) { - error(-1, "Couldn't open cidToUnicode file '%s'", - fileName->getCString()); - 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(-1, "Bad line (%d) in cidToUnicode file '%s'", - (int)(mapLenA + 1), fileName->getCString()); - 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 = fopen(fileName->getCString(), "r"))) { - error(-1, "Couldn't open unicodeToUnicode file '%s'", - fileName->getCString()); - 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")) || - sscanf(tok, "%x", &u0) != 1) { - error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", - line, fileName->getCString()); - continue; - } - n = 0; - while (n < maxUnicodeString) { - if (!(tok = strtok(NULL, " \t\r\n"))) { - break; - } - if (sscanf(tok, "%x", &uBuf[n]) != 1) { - error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", - line, fileName->getCString()); - break; - } - ++n; - } - if (n < 1) { - error(-1, "Bad line (%d) in unicodeToUnicode file '%s'", - line, fileName->getCString()); - 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::parseCMap(GString *buf, int nBits) { - CharCodeToUnicode *ctu; - char *p; - - ctu = new CharCodeToUnicode(NULL); - p = buf->getCString(); - ctu->parseCMap1(&getCharFromString, &p, nBits); - return ctu; -} - -void CharCodeToUnicode::mergeCMap(GString *buf, int nBits) { - char *p; - - p = buf->getCString(); - parseCMap1(&getCharFromString, &p, nBits); -} - -void CharCodeToUnicode::parseCMap1(int (*getCharFunc)(void *), void *data, - int nBits) { - PSTokenizer *pst; - char tok1[256], tok2[256], tok3[256]; - int nDigits, n1, n2, n3; - CharCode i; - CharCode code1, code2; - GString *name; - FILE *f; - - nDigits = nBits / 4; - 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))) { - parseCMap1(&getCharFromFile, f, nBits); - fclose(f); - } else { - error(-1, "Couldn't find ToUnicode CMap file for '%s'", - name->getCString()); - } - 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(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - break; - } - if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && - tok2[0] == '<' && tok2[n2 - 1] == '>')) { - error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - continue; - } - tok1[n1 - 1] = tok2[n2 - 1] = '\0'; - if (sscanf(tok1 + 1, "%x", &code1) != 1) { - error(-1, "Illegal entry in bfchar block in ToUnicode CMap"); - continue; - } - addMapping(code1, tok2 + 1, n2 - 2, 0); - } - 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(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - break; - } - if (!(n1 == 2 + nDigits && tok1[0] == '<' && tok1[n1 - 1] == '>' && - n2 == 2 + nDigits && tok2[0] == '<' && tok2[n2 - 1] == '>')) { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - continue; - } - tok1[n1 - 1] = tok2[n2 - 1] = '\0'; - if (sscanf(tok1 + 1, "%x", &code1) != 1 || - sscanf(tok2 + 1, "%x", &code2) != 1) { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - continue; - } - if (!strcmp(tok3, "[")) { - i = 0; - while (pst->getToken(tok1, sizeof(tok1), &n1) && - code1 + i <= code2) { - if (!strcmp(tok1, "]")) { - break; - } - if (tok1[0] == '<' && tok1[n1 - 1] == '>') { - tok1[n1 - 1] = '\0'; - addMapping(code1 + i, tok1 + 1, n1 - 2, 0); - } else { - error(-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); - } - - } else { - error(-1, "Illegal entry in bfrange block in ToUnicode CMap"); - } - } - pst->getToken(tok1, sizeof(tok1), &n1); - } else { - strcpy(tok1, tok2); - } - } - delete pst; -} - -void CharCodeToUnicode::addMapping(CharCode code, char *uStr, int n, - int offset) { - CharCode oldLen, i; - Unicode u; - char uHex[5]; - int j; - - if (code >= mapLen) { - oldLen = mapLen; - mapLen = (code + 256) & ~255; - map = (Unicode *)greallocn(map, mapLen, sizeof(Unicode)); - for (i = oldLen; i < mapLen; ++i) { - map[i] = 0; - } - } - if (n <= 4) { - if (sscanf(uStr, "%x", &u) != 1) { - error(-1, "Illegal entry in ToUnicode CMap"); - return; - } - map[code] = u + offset; - } else { - if (sMapLen >= sMapSize) { - sMapSize = sMapSize + 16; - sMap = (CharCodeToUnicodeString *) - greallocn(sMap, sMapSize, sizeof(CharCodeToUnicodeString)); - } - map[code] = 0; - sMap[sMapLen].c = code; - sMap[sMapLen].len = n / 4; - for (j = 0; j < sMap[sMapLen].len && j < maxUnicodeString; ++j) { - strncpy(uHex, uStr + j*4, 4); - uHex[4] = '\0'; - if (sscanf(uHex, "%x", &sMap[sMapLen].u[j]) != 1) { - error(-1, "Illegal entry in ToUnicode CMap"); - } - } - sMap[sMapLen].u[sMap[sMapLen].len - 1] += offset; - ++sMapLen; - } -} - -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; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -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; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -CharCodeToUnicode::~CharCodeToUnicode() { - if (tag) { - delete tag; - } - gfree(map); - if (sMap) { - gfree(sMap); - } -#if MULTITHREADED - gDestroyMutex(&mutex); -#endif -} - -void CharCodeToUnicode::incRefCnt() { -#if MULTITHREADED - gLockMutex(&mutex); -#endif - ++refCnt; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif -} - -void CharCodeToUnicode::decRefCnt() { - GBool done; - -#if MULTITHREADED - gLockMutex(&mutex); -#endif - done = --refCnt == 0; -#if MULTITHREADED - gUnlockMutex(&mutex); -#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 (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 (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/pdf2swf/xpdf/CharCodeToUnicode.h b/pdf2swf/xpdf/CharCodeToUnicode.h deleted file mode 100644 index 04852ae..0000000 --- a/pdf2swf/xpdf/CharCodeToUnicode.h +++ /dev/null @@ -1,117 +0,0 @@ -//======================================================================== -// -// CharCodeToUnicode.h -// -// Mapping from character codes to Unicode. -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CHARCODETOUNICODE_H -#define CHARCODETOUNICODE_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -struct CharCodeToUnicodeString; - -//------------------------------------------------------------------------ - -class CharCodeToUnicode { -public: - - // Read the CID-to-Unicode mapping for from the file - // specified by . Sets the initial reference count to 1. - // Returns NULL on failure. - static CharCodeToUnicode *parseCIDToUnicode(GString *fileName, - GString *collection); - - // Create a Unicode-to-Unicode mapping from the file specified by - // . Sets the initial reference count to 1. Returns NULL - // on failure. - static CharCodeToUnicode *parseUnicodeToUnicode(GString *fileName); - - // Create the CharCode-to-Unicode mapping for an 8-bit font. - // is an array of 256 Unicode indexes. Sets the initial - // reference count to 1. - static CharCodeToUnicode *make8BitToUnicode(Unicode *toUnicode); - - // Parse a ToUnicode CMap for an 8- or 16-bit font. - static CharCodeToUnicode *parseCMap(GString *buf, int nBits); - - // Parse a ToUnicode CMap for an 8- or 16-bit font, merging it into - // . - void mergeCMap(GString *buf, int nBits); - - ~CharCodeToUnicode(); - - void incRefCnt(); - void decRefCnt(); - - // Return true if this mapping matches the specified . - GBool match(GString *tagA); - - // Set the mapping for . - void setMapping(CharCode c, Unicode *u, int len); - - // Map a CharCode to Unicode. - int mapToUnicode(CharCode c, Unicode *u, int size); - - // Return the mapping's length, i.e., one more than the max char - // code supported by the mapping. - CharCode getLength() { return mapLen; } - -private: - - void parseCMap1(int (*getCharFunc)(void *), void *data, int nBits); - void addMapping(CharCode code, char *uStr, int n, int offset); - 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; - int refCnt; -#if MULTITHREADED - GMutex mutex; -#endif -}; - -//------------------------------------------------------------------------ - -class CharCodeToUnicodeCache { -public: - - CharCodeToUnicodeCache(int sizeA); - ~CharCodeToUnicodeCache(); - - // Get the CharCodeToUnicode object for . Increments its - // reference count; there will be one reference for the cache plus - // one for the caller of this function. Returns NULL on failure. - CharCodeToUnicode *getCharCodeToUnicode(GString *tag); - - // Insert into the cache, in the most-recently-used position. - void add(CharCodeToUnicode *ctu); - -private: - - CharCodeToUnicode **cache; - int size; -}; - -#endif diff --git a/pdf2swf/xpdf/CharTypes.h b/pdf2swf/xpdf/CharTypes.h deleted file mode 100644 index d0df630..0000000 --- a/pdf2swf/xpdf/CharTypes.h +++ /dev/null @@ -1,24 +0,0 @@ -//======================================================================== -// -// 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/pdf2swf/xpdf/Decrypt.cc b/pdf2swf/xpdf/Decrypt.cc deleted file mode 100644 index 91eb452..0000000 --- a/pdf2swf/xpdf/Decrypt.cc +++ /dev/null @@ -1,411 +0,0 @@ -//======================================================================== -// -// Decrypt.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "gmem.h" -#include "Decrypt.h" - -static void rc4InitKey(Guchar *key, int keyLen, Guchar *state); -static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c); -static void md5(Guchar *msg, int msgLen, Guchar *digest); - -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 -//------------------------------------------------------------------------ - -Decrypt::Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen) { - int i; - - // construct object key - for (i = 0; i < keyLength; ++i) { - objKey[i] = fileKey[i]; - } - objKey[keyLength] = objNum & 0xff; - objKey[keyLength + 1] = (objNum >> 8) & 0xff; - objKey[keyLength + 2] = (objNum >> 16) & 0xff; - objKey[keyLength + 3] = objGen & 0xff; - objKey[keyLength + 4] = (objGen >> 8) & 0xff; - md5(objKey, keyLength + 5, objKey); - - // set up for decryption - x = y = 0; - if ((objKeyLength = keyLength + 5) > 16) { - objKeyLength = 16; - } - rc4InitKey(objKey, objKeyLength, state); -} - -void Decrypt::reset() { - x = y = 0; - rc4InitKey(objKey, objKeyLength, state); -} - -Guchar Decrypt::decryptByte(Guchar c) { - return rc4DecryptByte(state, &x, &y, c); -} - -GBool Decrypt::makeFileKey(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *ownerPassword, GString *userPassword, - Guchar *fileKey, GBool encryptMetadata, - GBool *ownerPasswordOk) { - Guchar test[32], test2[32]; - GString *userPassword2; - Guchar fState[256]; - Guchar tmpKey[16]; - Guchar fx, fy; - int len, i, j; - - // try using the supplied owner password to generate the user password - *ownerPasswordOk = gFalse; - if (ownerPassword) { - len = ownerPassword->getLength(); - if (len < 32) { - 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, 16, 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] = 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); -} - -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] = permissions & 0xff; - buf[65] = (permissions >> 8) & 0xff; - buf[66] = (permissions >> 16) & 0xff; - buf[67] = (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] = 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; -} - -//------------------------------------------------------------------------ -// RC4-compatible decryption -//------------------------------------------------------------------------ - -static void rc4InitKey(Guchar *key, int keyLen, Guchar *state) { - Guchar index1, index2; - Guchar t; - int i; - - for (i = 0; i < 256; ++i) - state[i] = i; - index1 = index2 = 0; - for (i = 0; i < 256; ++i) { - index2 = (key[index1] + state[i] + index2) % 256; - t = state[i]; - state[i] = state[index2]; - state[index2] = t; - index1 = (index1 + 1) % keyLen; - } -} - -static Guchar rc4DecryptByte(Guchar *state, Guchar *x, Guchar *y, Guchar c) { - Guchar x1, y1, tx, ty; - - x1 = *x = (*x + 1) % 256; - y1 = *y = (state[*x] + *y) % 256; - tx = state[x1]; - ty = state[y1]; - state[x1] = ty; - state[y1] = tx; - return c ^ state[(tx + ty) % 256]; -} - -//------------------------------------------------------------------------ -// 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, Gulong 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, Gulong 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, Gulong 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, Gulong s, Gulong Ti) { - return b + rotateLeft((a + (c ^ (b | ~d)) + Xk + Ti), s); -} - -static void md5(Guchar *msg, int msgLen, Guchar *digest) { - Gulong x[16]; - Gulong a, b, c, d, aa, bb, cc, dd; - int n64; - int i, j, k; - - // compute number of 64-byte blocks - // (length + pad byte (0x80) + 8 bytes for length) - n64 = (msgLen + 1 + 8 + 63) / 64; - - // initialize a, b, c, d - a = 0x67452301; - b = 0xefcdab89; - c = 0x98badcfe; - d = 0x10325476; - - // loop through blocks - k = 0; - for (i = 0; i < n64; ++i) { - - // grab a 64-byte block - for (j = 0; j < 16 && k < msgLen - 3; ++j, k += 4) - x[j] = (((((msg[k+3] << 8) + msg[k+2]) << 8) + msg[k+1]) << 8) + msg[k]; - if (i == n64 - 1) { - if (k == msgLen - 3) - x[j] = 0x80000000 + (((msg[k+2] << 8) + msg[k+1]) << 8) + msg[k]; - else if (k == msgLen - 2) - x[j] = 0x800000 + (msg[k+1] << 8) + msg[k]; - else if (k == msgLen - 1) - x[j] = 0x8000 + msg[k]; - else - x[j] = 0x80; - ++j; - while (j < 16) - x[j++] = 0; - x[14] = msgLen << 3; - } - - // save a, b, c, d - aa = a; - bb = b; - cc = c; - dd = d; - - // round 1 - a = md5Round1(a, b, c, d, x[0], 7, 0xd76aa478); - d = md5Round1(d, a, b, c, x[1], 12, 0xe8c7b756); - c = md5Round1(c, d, a, b, x[2], 17, 0x242070db); - b = md5Round1(b, c, d, a, x[3], 22, 0xc1bdceee); - a = md5Round1(a, b, c, d, x[4], 7, 0xf57c0faf); - d = md5Round1(d, a, b, c, x[5], 12, 0x4787c62a); - c = md5Round1(c, d, a, b, x[6], 17, 0xa8304613); - b = md5Round1(b, c, d, a, x[7], 22, 0xfd469501); - a = md5Round1(a, b, c, d, x[8], 7, 0x698098d8); - d = md5Round1(d, a, b, c, x[9], 12, 0x8b44f7af); - c = md5Round1(c, d, a, b, x[10], 17, 0xffff5bb1); - b = md5Round1(b, c, d, a, x[11], 22, 0x895cd7be); - a = md5Round1(a, b, c, d, x[12], 7, 0x6b901122); - d = md5Round1(d, a, b, c, x[13], 12, 0xfd987193); - c = md5Round1(c, d, a, b, x[14], 17, 0xa679438e); - b = md5Round1(b, c, d, a, x[15], 22, 0x49b40821); - - // round 2 - a = md5Round2(a, b, c, d, x[1], 5, 0xf61e2562); - d = md5Round2(d, a, b, c, x[6], 9, 0xc040b340); - c = md5Round2(c, d, a, b, x[11], 14, 0x265e5a51); - b = md5Round2(b, c, d, a, x[0], 20, 0xe9b6c7aa); - a = md5Round2(a, b, c, d, x[5], 5, 0xd62f105d); - d = md5Round2(d, a, b, c, x[10], 9, 0x02441453); - c = md5Round2(c, d, a, b, x[15], 14, 0xd8a1e681); - b = md5Round2(b, c, d, a, x[4], 20, 0xe7d3fbc8); - a = md5Round2(a, b, c, d, x[9], 5, 0x21e1cde6); - d = md5Round2(d, a, b, c, x[14], 9, 0xc33707d6); - c = md5Round2(c, d, a, b, x[3], 14, 0xf4d50d87); - b = md5Round2(b, c, d, a, x[8], 20, 0x455a14ed); - a = md5Round2(a, b, c, d, x[13], 5, 0xa9e3e905); - d = md5Round2(d, a, b, c, x[2], 9, 0xfcefa3f8); - c = md5Round2(c, d, a, b, x[7], 14, 0x676f02d9); - b = md5Round2(b, c, d, a, x[12], 20, 0x8d2a4c8a); - - // round 3 - a = md5Round3(a, b, c, d, x[5], 4, 0xfffa3942); - d = md5Round3(d, a, b, c, x[8], 11, 0x8771f681); - c = md5Round3(c, d, a, b, x[11], 16, 0x6d9d6122); - b = md5Round3(b, c, d, a, x[14], 23, 0xfde5380c); - a = md5Round3(a, b, c, d, x[1], 4, 0xa4beea44); - d = md5Round3(d, a, b, c, x[4], 11, 0x4bdecfa9); - c = md5Round3(c, d, a, b, x[7], 16, 0xf6bb4b60); - b = md5Round3(b, c, d, a, x[10], 23, 0xbebfbc70); - a = md5Round3(a, b, c, d, x[13], 4, 0x289b7ec6); - d = md5Round3(d, a, b, c, x[0], 11, 0xeaa127fa); - c = md5Round3(c, d, a, b, x[3], 16, 0xd4ef3085); - b = md5Round3(b, c, d, a, x[6], 23, 0x04881d05); - a = md5Round3(a, b, c, d, x[9], 4, 0xd9d4d039); - d = md5Round3(d, a, b, c, x[12], 11, 0xe6db99e5); - c = md5Round3(c, d, a, b, x[15], 16, 0x1fa27cf8); - b = md5Round3(b, c, d, a, x[2], 23, 0xc4ac5665); - - // round 4 - a = md5Round4(a, b, c, d, x[0], 6, 0xf4292244); - d = md5Round4(d, a, b, c, x[7], 10, 0x432aff97); - c = md5Round4(c, d, a, b, x[14], 15, 0xab9423a7); - b = md5Round4(b, c, d, a, x[5], 21, 0xfc93a039); - a = md5Round4(a, b, c, d, x[12], 6, 0x655b59c3); - d = md5Round4(d, a, b, c, x[3], 10, 0x8f0ccc92); - c = md5Round4(c, d, a, b, x[10], 15, 0xffeff47d); - b = md5Round4(b, c, d, a, x[1], 21, 0x85845dd1); - a = md5Round4(a, b, c, d, x[8], 6, 0x6fa87e4f); - d = md5Round4(d, a, b, c, x[15], 10, 0xfe2ce6e0); - c = md5Round4(c, d, a, b, x[6], 15, 0xa3014314); - b = md5Round4(b, c, d, a, x[13], 21, 0x4e0811a1); - a = md5Round4(a, b, c, d, x[4], 6, 0xf7537e82); - d = md5Round4(d, a, b, c, x[11], 10, 0xbd3af235); - c = md5Round4(c, d, a, b, x[2], 15, 0x2ad7d2bb); - b = md5Round4(b, c, d, a, x[9], 21, 0xeb86d391); - - // increment a, b, c, d - a += aa; - b += bb; - c += cc; - d += dd; - } - - // break digest into bytes - digest[0] = (Guchar)(a & 0xff); - digest[1] = (Guchar)((a >>= 8) & 0xff); - digest[2] = (Guchar)((a >>= 8) & 0xff); - digest[3] = (Guchar)((a >>= 8) & 0xff); - digest[4] = (Guchar)(b & 0xff); - digest[5] = (Guchar)((b >>= 8) & 0xff); - digest[6] = (Guchar)((b >>= 8) & 0xff); - digest[7] = (Guchar)((b >>= 8) & 0xff); - digest[8] = (Guchar)(c & 0xff); - digest[9] = (Guchar)((c >>= 8) & 0xff); - digest[10] = (Guchar)((c >>= 8) & 0xff); - digest[11] = (Guchar)((c >>= 8) & 0xff); - digest[12] = (Guchar)(d & 0xff); - digest[13] = (Guchar)((d >>= 8) & 0xff); - digest[14] = (Guchar)((d >>= 8) & 0xff); - digest[15] = (Guchar)((d >>= 8) & 0xff); -} diff --git a/pdf2swf/xpdf/Decrypt.h b/pdf2swf/xpdf/Decrypt.h deleted file mode 100644 index 2beba58..0000000 --- a/pdf2swf/xpdf/Decrypt.h +++ /dev/null @@ -1,63 +0,0 @@ -//======================================================================== -// -// Decrypt.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef DECRYPT_H -#define DECRYPT_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "GString.h" - -//------------------------------------------------------------------------ -// Decrypt -//------------------------------------------------------------------------ - -class Decrypt { -public: - - // Initialize the decryptor object. - Decrypt(Guchar *fileKey, int keyLength, int objNum, int objGen); - - // Reset decryption. - void reset(); - - // Decrypt one byte. - Guchar decryptByte(Guchar c); - - // Generate a file key. The buffer must have space for at - // least 16 bytes. Checks and then - // and returns true if either is correct. Sets if - // the owner password was correct. Either or both of the passwords - // may be NULL, which is treated as an empty string. - static GBool makeFileKey(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *ownerPassword, GString *userPassword, - Guchar *fileKey, GBool encryptMetadata, - GBool *ownerPasswordOk); - -private: - - static GBool makeFileKey2(int encVersion, int encRevision, int keyLength, - GString *ownerKey, GString *userKey, - int permissions, GString *fileID, - GString *userPassword, Guchar *fileKey, - GBool encryptMetadata); - - int objKeyLength; - Guchar objKey[21]; - Guchar state[256]; - Guchar x, y; -}; - -#endif diff --git a/pdf2swf/xpdf/Dict.cc b/pdf2swf/xpdf/Dict.cc deleted file mode 100644 index dd1517f..0000000 --- a/pdf2swf/xpdf/Dict.cc +++ /dev/null @@ -1,95 +0,0 @@ -//======================================================================== -// -// Dict.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.h" -#include "Object.h" -#include "XRef.h" -#include "Dict.h" - -//------------------------------------------------------------------------ -// Dict -//------------------------------------------------------------------------ - -Dict::Dict(XRef *xrefA) { - xref = xrefA; - entries = NULL; - size = length = 0; - ref = 1; -} - -Dict::~Dict() { - int i; - - for (i = 0; i < length; ++i) { - gfree(entries[i].key); - entries[i].val.free(); - } - gfree(entries); -} - -void Dict::add(char *key, Object *val) { - if (length == size) { - if (length == 0) { - size = 8; - } else { - size *= 2; - } - entries = (DictEntry *)greallocn(entries, size, sizeof(DictEntry)); - } - entries[length].key = key; - entries[length].val = *val; - ++length; -} - -inline DictEntry *Dict::find(char *key) { - int i; - - for (i = 0; i < length; ++i) { - if (!strcmp(key, entries[i].key)) - return &entries[i]; - } - return NULL; -} - -GBool Dict::is(char *type) { - DictEntry *e; - - return (e = find("Type")) && e->val.isName(type); -} - -Object *Dict::lookup(char *key, Object *obj) { - DictEntry *e; - - return (e = find(key)) ? e->val.fetch(xref, obj) : obj->initNull(); -} - -Object *Dict::lookupNF(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/pdf2swf/xpdf/Dict.h b/pdf2swf/xpdf/Dict.h deleted file mode 100644 index 08f55ec..0000000 --- a/pdf2swf/xpdf/Dict.h +++ /dev/null @@ -1,77 +0,0 @@ -//======================================================================== -// -// Dict.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef DICT_H -#define DICT_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -//------------------------------------------------------------------------ -// Dict -//------------------------------------------------------------------------ - -struct DictEntry { - char *key; - Object val; -}; - -class Dict { -public: - - // Constructor. - Dict(XRef *xrefA); - - // Destructor. - ~Dict(); - - // Reference counting. - int incRef() { return ++ref; } - int decRef() { return --ref; } - - // 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(char *type); - - // Look up an entry and return the value. Returns a null object - // if is not in the dictionary. - Object *lookup(char *key, Object *obj); - Object *lookupNF(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 - int size; // size of array - int length; // number of entries in dictionary - int ref; // reference count - - DictEntry *find(char *key); -}; - -#endif diff --git a/pdf2swf/xpdf/Error.cc b/pdf2swf/xpdf/Error.cc deleted file mode 100644 index c03f75f..0000000 --- a/pdf2swf/xpdf/Error.cc +++ /dev/null @@ -1,38 +0,0 @@ -//======================================================================== -// -// Error.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include "GlobalParams.h" -#include "Error.h" - -void CDECL error(int pos, char *msg, ...) { - va_list args; - - // NB: this can be called before the globalParams object is created - if (globalParams && globalParams->getErrQuiet()) { - return; - } - if (pos >= 0) { - fprintf(stderr, "Error (%d): ", pos); - } else { - fprintf(stderr, "Error: "); - } - va_start(args, msg); - vfprintf(stderr, msg, args); - va_end(args); - fprintf(stderr, "\n"); - fflush(stderr); -} diff --git a/pdf2swf/xpdf/Error.h b/pdf2swf/xpdf/Error.h deleted file mode 100644 index 0ce55e9..0000000 --- a/pdf2swf/xpdf/Error.h +++ /dev/null @@ -1,23 +0,0 @@ -//======================================================================== -// -// Error.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef ERROR_H -#define ERROR_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include -#include "config.h" - -extern void CDECL error(int pos, char *msg, ...); - -#endif diff --git a/pdf2swf/xpdf/ErrorCodes.h b/pdf2swf/xpdf/ErrorCodes.h deleted file mode 100644 index b28528d..0000000 --- a/pdf2swf/xpdf/ErrorCodes.h +++ /dev/null @@ -1,36 +0,0 @@ -//======================================================================== -// -// 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/pdf2swf/xpdf/FoFiBase.cc b/pdf2swf/xpdf/FoFiBase.cc deleted file mode 100644 index 28d0b8c..0000000 --- a/pdf2swf/xpdf/FoFiBase.cc +++ /dev/null @@ -1,156 +0,0 @@ -//======================================================================== -// -// FoFiBase.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "gmem.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); - 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+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+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+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+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::getUVarBE(int pos, int size, GBool *ok) { - Guint x; - int i; - - if (pos < 0 || 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 && - pos + size >= pos && - pos + size <= len; -} diff --git a/pdf2swf/xpdf/FoFiBase.h b/pdf2swf/xpdf/FoFiBase.h deleted file mode 100644 index b78840b..0000000 --- a/pdf2swf/xpdf/FoFiBase.h +++ /dev/null @@ -1,57 +0,0 @@ -//======================================================================== -// -// FoFiBase.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFIBASE_H -#define FOFIBASE_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ - -typedef void (*FoFiOutputFunc)(void *stream, 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 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/pdf2swf/xpdf/FoFiEncodings.cc b/pdf2swf/xpdf/FoFiEncodings.cc deleted file mode 100644 index 37a17f5..0000000 --- a/pdf2swf/xpdf/FoFiEncodings.cc +++ /dev/null @@ -1,994 +0,0 @@ -//======================================================================== -// -// FoFiEncodings.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "FoFiEncodings.h" - -//------------------------------------------------------------------------ -// Type 1 and 1C font data -//------------------------------------------------------------------------ - -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 -}; - -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 -//------------------------------------------------------------------------ - -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/pdf2swf/xpdf/FoFiEncodings.h b/pdf2swf/xpdf/FoFiEncodings.h deleted file mode 100644 index 50e285d..0000000 --- a/pdf2swf/xpdf/FoFiEncodings.h +++ /dev/null @@ -1,36 +0,0 @@ -//======================================================================== -// -// FoFiEncodings.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFIENCODINGS_H -#define FOFIENCODINGS_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ -// Type 1 and 1C font data -//------------------------------------------------------------------------ - -extern char *fofiType1StandardEncoding[256]; -extern char *fofiType1ExpertEncoding[256]; - -//------------------------------------------------------------------------ -// Type 1C font data -//------------------------------------------------------------------------ - -extern char *fofiType1CStdStrings[391]; -extern Gushort fofiType1CISOAdobeCharset[229]; -extern Gushort fofiType1CExpertCharset[166]; -extern Gushort fofiType1CExpertSubsetCharset[87]; - -#endif diff --git a/pdf2swf/xpdf/FoFiTrueType.cc b/pdf2swf/xpdf/FoFiTrueType.cc deleted file mode 100644 index 46b61ec..0000000 --- a/pdf2swf/xpdf/FoFiTrueType.cc +++ /dev/null @@ -1,1753 +0,0 @@ -//======================================================================== -// -// FoFiTrueType.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gtypes.h" -#include "gmem.h" -#include "GString.h" -#include "GHash.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 locaTag 0x6c6f6361 -#define nameTag 0x6e616d65 -#define postTag 0x706f7374 - -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; -} - -//------------------------------------------------------------------------ - -struct T42Table { - 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 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) { - FoFiTrueType *ff; - - ff = new FoFiTrueType(fileA, lenA, gFalse); - if (!ff->parsedOk) { - delete ff; - return NULL; - } - return ff; -} - -FoFiTrueType *FoFiTrueType::load(char *fileName) { - FoFiTrueType *ff; - char *fileA; - int lenA; - - if (!(fileA = FoFiBase::readFile(fileName, &lenA))) { - return NULL; - } - ff = new FoFiTrueType(fileA, lenA, gTrue); - if (!ff->parsedOk) { - delete ff; - return NULL; - } - return ff; -} - -FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA): - FoFiBase(fileA, lenA, freeFileDataA) -{ - tables = NULL; - nTables = 0; - cmaps = NULL; - nCmaps = 0; - nameToGID = NULL; - parsedOk = gFalse; - - parse(); -} - -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; -} - -Gushort FoFiTrueType::mapCodeToGID(int i, int c) { - Gushort 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(cmaps[i].offset + 6 + 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); -} - -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::convertToType42(char *psName, char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[512]; - GBool ok; - - // write the header - ok = gTrue; - sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0); - (*outputFunc)(outputStream, buf, strlen(buf)); - - // begin the font dictionary - (*outputFunc)(outputStream, "10 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, 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); - sprintf(buf, "/FontBBox [%d %d %d %d] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - (*outputFunc)(outputStream, buf, strlen(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); - - // end the dictionary and define the font - (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); -} - -void FoFiTrueType::convertToCIDType2(char *psName, - Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[512]; - Gushort cid; - GBool ok; - int i, j, k; - - // write the header - ok = gTrue; - sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0); - (*outputFunc)(outputStream, buf, strlen(buf)); - - // begin the font dictionary - (*outputFunc)(outputStream, "20 dict begin\n", 14); - (*outputFunc)(outputStream, "/CIDFontName /", 14); - (*outputFunc)(outputStream, psName, 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) { - sprintf(buf, "/CIDCount %d def\n", nCIDs); - (*outputFunc)(outputStream, buf, strlen(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]; - sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff); - (*outputFunc)(outputStream, buf, strlen(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]; - sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "\n", 1); - } - (*outputFunc)(outputStream, "> def\n", 6); - } - } else { - // direct mapping - just fill the string(s) with s[i]=i - sprintf(buf, "/CIDCount %d def\n", nGlyphs); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (nGlyphs > 32767) { - (*outputFunc)(outputStream, "/CIDMap [\n", 10); - for (i = 0; i < nGlyphs; i += 32767) { - j = nGlyphs - i < 32767 ? nGlyphs - i : 32767; - sprintf(buf, " %d string 0 1 %d {\n", 2 * j, j - 1); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, " 1 index exch dup 2 mul 1 add exch %d add" - " 255 and put\n", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, " } for\n", 8); - } - (*outputFunc)(outputStream, "] def\n", 6); - } else { - sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, " 0 1 %d {\n", nGlyphs - 1); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*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); - sprintf(buf, "/FontBBox [%d %d %d %d] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - (*outputFunc)(outputStream, buf, strlen(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); - - // end the dictionary and define the font - (*outputFunc)(outputStream, - "CIDFontName currentdict end /CIDFont defineresource pop\n", - 56); -} - -void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[512]; - GString *sfntsName; - int n, i, j; - - // write the Type 42 sfnts array - sfntsName = (new GString(psName))->append("_sfnts"); - cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics); - delete sfntsName; - - // write the descendant Type 42 fonts - n = cidMap ? nCIDs : nGlyphs; - for (i = 0; i < n; i += 256) { - (*outputFunc)(outputStream, "10 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x def\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 42 def\n", 17); - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - sprintf(buf, "/FontBBox [%d %d %d %d] def\n", - bbox[0], bbox[1], bbox[2], bbox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/PaintType 0 def\n", 17); - (*outputFunc)(outputStream, "/sfnts ", 7); - (*outputFunc)(outputStream, psName, strlen(psName)); - (*outputFunc)(outputStream, "_sfnts def\n", 11); - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - for (j = 0; j < 256 && i+j < n; ++j) { - sprintf(buf, "dup %d /c%02x put\n", j, j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "readonly def\n", 13); - (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32); - (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); - for (j = 0; j < 256 && i+j < n; ++j) { - sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*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, 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) { - sprintf(buf, "%d\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "/FDepVector [\n", 14); - for (i = 0; i < n; i += 256) { - (*outputFunc)(outputStream, "/", 1); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x findfont\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); -} - -void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc, - void *outputStream, char *name, - Gushort *codeToGID) { - // this substitute cmap table maps char codes 0000-ffff directly to - // glyphs 0000-ffff - static char cmapTab[36] = { - 0, 0, // table version number - 0, 1, // number of encoding tables - 0, 1, // platform ID - 0, 0, // encoding ID - 0, 0, 0, 12, // 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 - 0, 0, // startCount[0] - 0, 0, // idDelta[0] - 0, 0 // pad to a mulitple of four bytes - }; - 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 - }; - GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen; - int nZeroLengthTables; - TrueTypeLoca *locaTable; - TrueTypeTable *newTables; - char *newNameTab, *newCmapTab; - int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next; - Guint locaChecksum, glyfChecksum, fileChecksum; - char *tableDir; - char locaBuf[4], checksumBuf[4]; - GBool ok; - Guint t; - int pos, i, j, k, n; - - // check for missing tables - missingCmap = (cmapIdx = seekTable("cmap")) < 0; - missingName = seekTable("name") < 0; - missingPost = seekTable("post") < 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; - 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 (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) { - unsortedLoca = gTrue; - } - locaTable[i].idx = i; - } - - // check for zero-length tables - nZeroLengthTables = 0; - for (i = 0; i < nTables; ++i) { - if (tables[i].len == 0) { - ++nZeroLengthTables; - } - } - - // check for an incorrect cmap table length - badCmapLen = gFalse; - cmapLen = 0; // make gcc happy - if (!missingCmap) { - cmapLen = cmaps[0].offset + cmaps[0].len; - for (i = 1; i < nCmaps; ++i) { - if (cmaps[i].offset + cmaps[i].len > cmapLen) { - cmapLen = cmaps[i].offset + cmaps[i].len; - } - } - cmapLen -= tables[cmapIdx].offset; - if (cmapLen > tables[cmapIdx].len) { - badCmapLen = gTrue; - } - } - - // if nothing is broken, just write the TTF file as is - if (!missingCmap && !missingName && !missingPost && !unsortedLoca && - !badCmapLen && nZeroLengthTables == 0 && !name && !codeToGID) { - (*outputFunc)(outputStream, (char *)file, len); - goto done1; - } - - // 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) { - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaOffset); - for (i = 0; i < nGlyphs; ++i) { - locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset; - } - locaTable[nGlyphs].len = 0; - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaIdx); - 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 = 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] = i + 1; - newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length - newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff); - newNameTab[6 + i*12 + 10] = next >> 8; // string offset - newNameTab[6 + i*12 + 11] = 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) { - 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) { - newCmapTab[44 + 2*i] = codeToGID[i] >> 8; - newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff; - } - } else { - newCmapLen = 0; - newCmapTab = NULL; - } - - // 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 + - (missingCmap ? 1 : 0) + (missingName ? 1 : 0) + - (missingPost ? 1 : 0); - newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable)); - j = 0; - for (i = 0; i < nTables; ++i) { - if (tables[i].len > 0) { - newTables[j] = tables[i]; - newTables[j].origOffset = tables[i].offset; - if (checkRegion(tables[i].offset, newTables[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); - } - } - if (newTables[j].tag == cmapTag && codeToGID) { - newTables[j].len = newCmapLen; - newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab, - newCmapLen); - } 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); - } - ++j; - } - } - if (missingCmap) { - newTables[j].tag = cmapTag; - 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; - } - qsort(newTables, nNewTables, sizeof(TrueTypeTable), - &cmpTrueTypeTableTag); - 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] = fileChecksum >> 24; - checksumBuf[1] = fileChecksum >> 16; - checksumBuf[2] = fileChecksum >> 8; - checksumBuf[3] = 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 && 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 == 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(newCmapTab); - gfree(newNameTab); - gfree(tableDir); - gfree(newTables); - done1: - gfree(locaTable); -} - -void FoFiTrueType::cvtEncoding(char **encoding, - FoFiOutputFunc outputFunc, - void *outputStream) { - char *name; - char buf[64]; - int i; - - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - if (encoding) { - for (i = 0; i < 256; ++i) { - if (!(name = encoding[i])) { - name = ".notdef"; - } - sprintf(buf, "dup %d /", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, name, strlen(name)); - (*outputFunc)(outputStream, " put\n", 5); - } - } else { - for (i = 0; i < 256; ++i) { - sprintf(buf, "dup %d /c%02x put\n", i, i); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - (*outputFunc)(outputStream, "readonly def\n", 13); -} - -void FoFiTrueType::cvtCharStrings(char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, - void *outputStream) { - char *name; - char buf[64], buf2[16]; - int i, k; - - // always define '.notdef' - (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32); - (*outputFunc)(outputStream, "/.notdef 0 def\n", 15); - - // if there's no 'cmap' table, punt - if (nCmaps == 0) { - goto err; - } - - // 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 { - sprintf(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, strlen(name)); - sprintf(buf, " %d def\n", k); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - } - - err: - (*outputFunc)(outputStream, "end readonly def\n", 17); -} - -void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc, - void *outputStream, GString *name, - GBool needVerticalMetrics) { - Guchar headData[54]; - TrueTypeLoca *locaTable; - Guchar *locaData; - TrueTypeTable newTables[nT42Tables]; - Guchar tableDir[12 + nT42Tables*16]; - GBool ok; - Guint checksum; - int nNewTables; - int 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; - - // read the original 'loca' table, pad entries out to 4 bytes, and - // sort it into proper order -- some (non-compliant) fonts have - // out-of-order loca tables; in order to correctly handle the case - // where (compliant) fonts have empty entries in the middle of the - // table, cmpTrueTypeLocaPos uses offset as its primary sort key, - // and idx as its secondary key (ensuring that adjacent entries with - // the same pos value remain in the same order) - locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca)); - i = seekTable("loca"); - pos = tables[i].offset; - 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); - } - } - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaOffset); - for (i = 0; i < nGlyphs; ++i) { - locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset; - } - locaTable[nGlyphs].len = 0; - qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca), - &cmpTrueTypeLocaIdx); - pos = 0; - for (i = 0; i <= nGlyphs; ++i) { - locaTable[i].newOffset = pos; - pos += locaTable[i].len; - if (pos & 3) { - pos += 4 - (pos & 3); - } - } - - // 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) { - 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] = advance / 256; // max advance height - vheaTab[11] = advance % 256; - length = sizeof(vheaTab); - checksum = computeTableChecksum(vheaTab, length); - } else if (needVerticalMetrics && i == t42VmtxTable) { - length = 4 + (nGlyphs - 1) * 4; - vmtxTab = (Guchar *)gmalloc(length); - vmtxTab[0] = advance / 256; - vmtxTab[1] = 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] = 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 > 0 && - 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); - gfree(vmtxTab); - } - } - } - } - - // end the sfnts array - (*outputFunc)(outputStream, "] def\n", 6); - - gfree(locaData); - gfree(locaTable); -} - -void FoFiTrueType::dumpString(Guchar *s, int length, - FoFiOutputFunc outputFunc, - void *outputStream) { - char buf[64]; - int pad, i, j; - - (*outputFunc)(outputStream, "<", 1); - for (i = 0; i < length; i += 32) { - for (j = 0; j < 32 && i+j < length; ++j) { - sprintf(buf, "%02X", s[i+j] & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - 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() { - Guint topTag; - int pos, i, j; - - parsedOk = gTrue; - - // look for a collection (TTC) - topTag = getU32BE(0, &parsedOk); - if (!parsedOk) { - return; - } - if (topTag == ttcfTag) { - pos = getU32BE(12, &parsedOk); - if (!parsedOk) { - return; - } - } else { - pos = 0; - } - - // read the table directory - nTables = getU16BE(pos + 4, &parsedOk); - if (!parsedOk) { - return; - } - tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable)); - pos += 12; - for (i = 0; i < nTables; ++i) { - tables[i].tag = getU32BE(pos, &parsedOk); - tables[i].checksum = getU32BE(pos + 4, &parsedOk); - tables[i].offset = (int)getU32BE(pos + 8, &parsedOk); - tables[i].len = (int)getU32BE(pos + 12, &parsedOk); - if (tables[i].offset + tables[i].len < tables[i].offset || - tables[i].offset + tables[i].len > len) { - parsedOk = gFalse; - } - pos += 16; - } - if (!parsedOk) { - return; - } - - // check for tables that are required by both the TrueType spec and - // the Type 42 spec - if (seekTable("head") < 0 || - seekTable("hhea") < 0 || - seekTable("loca") < 0 || - seekTable("maxp") < 0 || - seekTable("glyf") < 0 || - seekTable("hmtx") < 0) { - parsedOk = gFalse; - return; - } - - // read the cmaps - if ((i = seekTable("cmap")) >= 0) { - pos = tables[i].offset + 2; - nCmaps = getU16BE(pos, &parsedOk); - pos += 2; - if (!parsedOk) { - return; - } - cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap)); - for (j = 0; j < nCmaps; ++j) { - cmaps[j].platform = getU16BE(pos, &parsedOk); - cmaps[j].encoding = getU16BE(pos + 2, &parsedOk); - cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk); - pos += 8; - cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk); - cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk); - } - if (!parsedOk) { - return; - } - } else { - nCmaps = 0; - } - - // 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 and entries are - // in bounds) - i = seekTable("loca"); - if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) { - parsedOk = gFalse; - return; - } - for (j = 0; j <= nGlyphs; ++j) { - if (locaFmt) { - pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk); - } else { - pos = getU16BE(tables[i].offset + j*2, &parsedOk); - } - if (pos < 0 || pos > len) { - parsedOk = gFalse; - } - } - if (!parsedOk) { - return; - } - - // read the post table - readPostTable(); -} - -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; - } - if (n > nGlyphs) { - n = nGlyphs; - } - stringIdx = 0; - stringPos = tablePos + 34 + 2*n; - for (i = 0; i < n; ++i) { - 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) { - goto err; - } - } - m = getU8(stringPos, &ok); - if (!ok || !checkRegion(stringPos + 1, m)) { - goto err; - } - 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) { - goto err; - } - 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(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/pdf2swf/xpdf/FoFiTrueType.h b/pdf2swf/xpdf/FoFiTrueType.h deleted file mode 100644 index f7b09d6..0000000 --- a/pdf2swf/xpdf/FoFiTrueType.h +++ /dev/null @@ -1,140 +0,0 @@ -//======================================================================== -// -// FoFiTrueType.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFITRUETYPE_H -#define FOFITRUETYPE_H - -#include - -#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. - static FoFiTrueType *make(char *fileA, int lenA); - - // Create a FoFiTrueType object from a file on disk. - static FoFiTrueType *load(char *fileName); - - virtual ~FoFiTrueType(); - - // Return the number of cmaps defined by this font. - int getNumCmaps(); - - // Return the platform ID of the th cmap. - int getCmapPlatform(int i); - - // Return the encoding ID of the th cmap. - int getCmapEncoding(int i); - - // Return the index of the cmap for , . Returns - // -1 if there is no corresponding cmap. - int findCmap(int platform, int encoding); - - // Return the GID corresponding to according to the th cmap. - Gushort mapCodeToGID(int i, int c); - - // Returns the GID corresponding to according to the post - // table. Returns 0 if there is no mapping for or if the - // font does not have a post table. - int mapNameToGID(char *name); - - // 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(); - - // Convert to a Type 42 font, suitable for embedding in a PostScript - // file. will be used as the PostScript font name (so we - // don't need to depend on the 'name' table in the font). The - // array specifies the mapping from char codes to names. - // If is NULL, the encoding is unknown or undefined. The - // array specifies the mapping from char codes to GIDs. - void convertToType42(char *psName, char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 2 CIDFont, suitable for embedding in a - // PostScript file. will be used as the PostScript font - // name (so we don't need to depend on the 'name' table in the - // font). The array maps CIDs to GIDs; it has - // entries. - void convertToCIDType2(char *psName, Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 0 (but non-CID) composite font, suitable for - // embedding in a PostScript file. will be used as the - // PostScript font name (so we don't need to depend on the 'name' - // table in the font). The array maps CIDs to GIDs; it has - // entries. - void convertToType0(char *psName, Gushort *cidMap, int nCIDs, - GBool needVerticalMetrics, - FoFiOutputFunc outputFunc, void *outputStream); - - // Write a clean TTF file, filling in missing tables and correcting - // various other errors. If is non-NULL, the font is renamed - // to . If is non-NULL, the font is re-encoded, - // using a Windows Unicode cmap. If is NULL and the font is - // complete and correct, it will be written unmodified. - void writeTTF(FoFiOutputFunc outputFunc, void *outputStream, - char *name = NULL, Gushort *codeToGID = NULL); - -private: - - FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA); - void cvtEncoding(char **encoding, - FoFiOutputFunc outputFunc, - void *outputStream); - void cvtCharStrings(char **encoding, - Gushort *codeToGID, - FoFiOutputFunc outputFunc, - void *outputStream); - void cvtSfnts(FoFiOutputFunc outputFunc, - void *outputStream, GString *name, - GBool needVerticalMetrics); - void dumpString(Guchar *s, int length, - FoFiOutputFunc outputFunc, - void *outputStream); - Guint computeTableChecksum(Guchar *data, int length); - void parse(); - void readPostTable(); - int seekTable(char *tag); - - TrueTypeTable *tables; - int nTables; - TrueTypeCmap *cmaps; - int nCmaps; - int nGlyphs; - int locaFmt; - int bbox[4]; - GHash *nameToGID; - - GBool parsedOk; -}; - -#endif diff --git a/pdf2swf/xpdf/FoFiType1.cc b/pdf2swf/xpdf/FoFiType1.cc deleted file mode 100644 index a8a69fd..0000000 --- a/pdf2swf/xpdf/FoFiType1.cc +++ /dev/null @@ -1,212 +0,0 @@ -//======================================================================== -// -// FoFiType1.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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; - parsed = gFalse; -} - -FoFiType1::~FoFiType1() { - int i; - - if (name) { - gfree(name); - } - if (encoding && encoding != 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::writeEncoded(char **newEncoding, - FoFiOutputFunc outputFunc, void *outputStream) { - char buf[512]; - char *line; - int i; - - // copy everything up to the encoding - for (line = (char *)file; - line && 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, 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]) { - sprintf(buf, "dup %d /%s put\n", i, newEncoding[i]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - } - (*outputFunc)(outputStream, "readonly def\n", 13); - - // copy everything after the encoding - if (!strncmp(line, "/Encoding StandardEncoding def", 30)) { - line = getNextLine(line); - } else { - for (line = getNextLine(line); - line && strncmp(line, "readonly def", 12); - line = getNextLine(line)) ; - if (line) { - line = getNextLine(line); - } - } - if (line) { - (*outputFunc)(outputStream, line, ((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, i, j; - - for (i = 1, line = (char *)file; - i <= 100 && line && (!name || !encoding); - ++i) { - - // get font name - if (!name && !strncmp(line, "/FontName", 9)) { - strncpy(buf, line, 255); - buf[255] = '\0'; - if ((p = strchr(buf+9, '/')) && - (p = strtok(p+1, " \t\n\r"))) { - name = copyString(p); - } - line = getNextLine(line); - - // get encoding - } else if (!encoding && - !strncmp(line, "/Encoding StandardEncoding def", 30)) { - encoding = fofiType1StandardEncoding; - } else if (!encoding && - !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 = line1 - line) > 255) { - n = 255; - } - strncpy(buf, line, n); - buf[n] = '\0'; - for (p = buf; *p == ' ' || *p == '\t'; ++p) ; - if (!strncmp(p, "dup", 3)) { - for (p += 3; *p == ' ' || *p == '\t'; ++p) ; - for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ; - if (*p2) { - c = *p2; - *p2 = '\0'; - if ((code = atoi(p)) < 256) { - *p2 = c; - for (p = p2; *p == ' ' || *p == '\t'; ++p) ; - if (*p == '/') { - ++p; - for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ; - *p2 = '\0'; - encoding[code] = copyString(p); - } - } - } - } else { - p = strtok(buf, " \t\n\r"); - if (p) - { - if (!strcmp(p, "def")) break; - if (!strcmp(p, "readonly")) break; - // the spec does not says this but i'm mantaining old xpdf behaviour that accepts "foo def" as end of the encoding array - p = strtok(buf, " \t\n\r"); - if (p && !strcmp(p, "def")) break; - } - } - } - //~ check for getinterval/putinterval junk - - } else { - line = getNextLine(line); - } - } - - parsed = gTrue; -} diff --git a/pdf2swf/xpdf/FoFiType1.h b/pdf2swf/xpdf/FoFiType1.h deleted file mode 100644 index 843352b..0000000 --- a/pdf2swf/xpdf/FoFiType1.h +++ /dev/null @@ -1,59 +0,0 @@ -//======================================================================== -// -// FoFiType1.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFITYPE1_H -#define FOFITYPE1_H - -#include - -#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(); - - // Write a version of the Type 1 font file with a new encoding. - void writeEncoded(char **newEncoding, - FoFiOutputFunc outputFunc, void *outputStream); - -private: - - FoFiType1(char *fileA, int lenA, GBool freeFileDataA); - - char *getNextLine(char *line); - void parse(); - - char *name; - char **encoding; - GBool parsed; -}; - -#endif diff --git a/pdf2swf/xpdf/FoFiType1C.cc b/pdf2swf/xpdf/FoFiType1C.cc deleted file mode 100644 index a173e7c..0000000 --- a/pdf2swf/xpdf/FoFiType1C.cc +++ /dev/null @@ -1,2484 +0,0 @@ -//======================================================================== -// -// FoFiType1C.cc -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include "gmem.h" -#include "GString.h" -#include "FoFiEncodings.h" -#include "FoFiType1C.h" - -//------------------------------------------------------------------------ - -static char hexChars[17] = "0123456789ABCDEF"; - -//------------------------------------------------------------------------ -// 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 != fofiType1StandardEncoding && - encoding != 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; -} - -Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) { - Gushort *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 = (Gushort *)gmallocn(n, sizeof(Gushort)); - memset(map, 0, n * sizeof(Gushort)); - for (i = 0; i < nGlyphs; ++i) { - map[charset[i]] = i; - } - *nCIDs = n; - return map; -} - -void FoFiType1C::convertToType1(char **newEncoding, GBool ascii, - FoFiOutputFunc outputFunc, - void *outputStream) { - Type1CEexecBuf eb; - Type1CIndex subrIdx; - Type1CIndexVal val; - char buf[512]; - char **enc; - GBool ok; - int i; - - // write header and font dictionary, up to encoding - ok = gTrue; - (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17); - (*outputFunc)(outputStream, name->getCString(), name->getLength()); - if (topDict.versionSID != 0) { - getString(topDict.versionSID, buf, &ok); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*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 (", 10); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.noticeSID != 0) { - getString(topDict.noticeSID, buf, &ok); - (*outputFunc)(outputStream, "/Notice (", 9); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.copyrightSID != 0) { - getString(topDict.copyrightSID, buf, &ok); - (*outputFunc)(outputStream, "/Copyright (", 12); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.fullNameSID != 0) { - getString(topDict.fullNameSID, buf, &ok); - (*outputFunc)(outputStream, "/FullName (", 11); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.familyNameSID != 0) { - getString(topDict.familyNameSID, buf, &ok); - (*outputFunc)(outputStream, "/FamilyName (", 13); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.weightSID != 0) { - getString(topDict.weightSID, buf, &ok); - (*outputFunc)(outputStream, "/Weight (", 9); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") readonly def\n", 15); - } - if (topDict.isFixedPitch) { - (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23); - } else { - (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24); - } - sprintf(buf, "/ItalicAngle %g def\n", topDict.italicAngle); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/UnderlinePosition %g def\n", topDict.underlinePosition); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/UnderlineThickness %g def\n", topDict.underlineThickness); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "end readonly def\n", 17); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, name->getCString(), name->getLength()); - (*outputFunc)(outputStream, " def\n", 5); - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 1 def\n", 16); - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n", - topDict.fontMatrix[0], topDict.fontMatrix[1], topDict.fontMatrix[2], - topDict.fontMatrix[3], topDict.fontMatrix[4], topDict.fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n", - topDict.fontBBox[0], topDict.fontBBox[1], - topDict.fontBBox[2], topDict.fontBBox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (topDict.uniqueID != 0) { - sprintf(buf, "/UniqueID %d def\n", topDict.uniqueID); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - - // write the encoding - (*outputFunc)(outputStream, "/Encoding ", 10); - if (!newEncoding && encoding == fofiType1StandardEncoding) { - (*outputFunc)(outputStream, "StandardEncoding def\n", 21); - } else { - (*outputFunc)(outputStream, "256 array\n", 10); - (*outputFunc)(outputStream, - "0 1 255 {1 index exch /.notdef put} for\n", 40); - enc = newEncoding ? newEncoding : encoding; - if(!enc) { - fprintf(stderr, "convertToType1: Warning: No Encoding\n"); - } - for (i = 0; i < 256; ++i) { - if (enc && enc[i]) { - sprintf(buf, "dup %d /%s put\n", i, enc[i]); - (*outputFunc)(outputStream, buf, strlen(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 ["); - for (i = 0; i < privateDicts[0].nBlueValues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].blueValues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nOtherBlues) { - eexecWrite(&eb, "/OtherBlues ["); - for (i = 0; i < privateDicts[0].nOtherBlues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].otherBlues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nFamilyBlues) { - eexecWrite(&eb, "/FamilyBlues ["); - for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", privateDicts[0].familyBlues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nFamilyOtherBlues) { - eexecWrite(&eb, "/FamilyOtherBlues ["); - for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) { - sprintf(buf, "%s%d", i > 0 ? " " : "", - privateDicts[0].familyOtherBlues[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].blueScale != 0.039625) { - sprintf(buf, "/BlueScale %g def\n", privateDicts[0].blueScale); - eexecWrite(&eb, buf); - } - if (privateDicts[0].blueShift != 7) { - sprintf(buf, "/BlueShift %d def\n", privateDicts[0].blueShift); - eexecWrite(&eb, buf); - } - if (privateDicts[0].blueFuzz != 1) { - sprintf(buf, "/BlueFuzz %d def\n", privateDicts[0].blueFuzz); - eexecWrite(&eb, buf); - } - if (privateDicts[0].hasStdHW) { - sprintf(buf, "/StdHW [%g] def\n", privateDicts[0].stdHW); - eexecWrite(&eb, buf); - } - if (privateDicts[0].hasStdVW) { - sprintf(buf, "/StdVW [%g] def\n", privateDicts[0].stdVW); - eexecWrite(&eb, buf); - } - if (privateDicts[0].nStemSnapH) { - eexecWrite(&eb, "/StemSnapH ["); - for (i = 0; i < privateDicts[0].nStemSnapH; ++i) { - sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapH[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].nStemSnapV) { - eexecWrite(&eb, "/StemSnapV ["); - for (i = 0; i < privateDicts[0].nStemSnapV; ++i) { - sprintf(buf, "%s%g", i > 0 ? " " : "", privateDicts[0].stemSnapV[i]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[0].hasForceBold) { - sprintf(buf, "/ForceBold %s def\n", - privateDicts[0].forceBold ? "true" : "false"); - eexecWrite(&eb, buf); - } - if (privateDicts[0].forceBoldThreshold != 0) { - sprintf(buf, "/ForceBoldThreshold %g def\n", - privateDicts[0].forceBoldThreshold); - eexecWrite(&eb, buf); - } - if (privateDicts[0].languageGroup != 0) { - sprintf(buf, "/LanguageGroup %d def\n", privateDicts[0].languageGroup); - eexecWrite(&eb, buf); - } - if (privateDicts[0].expansionFactor != 0.06) { - sprintf(buf, "/ExpansionFactor %g def\n", privateDicts[0].expansionFactor); - eexecWrite(&eb, buf); - } - - // set up subroutines - ok = gTrue; - getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok); - if (!ok) { - subrIdx.pos = -1; - } - - // write the CharStrings - sprintf(buf, "2 index /CharStrings %d dict dup begin\n", nGlyphs); - eexecWrite(&eb, buf); - for (i = 0; i < nGlyphs; ++i) { - ok = gTrue; - getIndexVal(&charStringsIdx, i, &val, &ok); - if (ok) { - getString(charset[i], buf, &ok); - if (ok) { - eexecCvtGlyph(&eb, buf, 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, - FoFiOutputFunc outputFunc, - void *outputStream) { - int *cidMap; - GString *charStrings; - int *charStringOffsets; - Type1CIndex subrIdx; - Type1CIndexVal val; - int nCIDs, gdBytes; - char buf[512], buf2[512]; - GBool ok; - int gid, offset, n, i, j, k; - - // compute the CID count and build the CID-to-GID mapping - nCIDs = 0; - for (i = 0; i < nGlyphs; ++i) { - if (charset[i] >= nCIDs) { - nCIDs = charset[i] + 1; - } - } - cidMap = (int *)gmallocn(nCIDs, sizeof(int)); - for (i = 0; i < nCIDs; ++i) { - cidMap[i] = -1; - } - for (i = 0; i < nGlyphs; ++i) { - cidMap[charset[i]] = i; - } - - // build the charstrings - 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[gid]].subrsOffset, &subrIdx, &ok); - if (!ok) { - subrIdx.pos = -1; - } - cvtGlyph(val.pos, val.len, charStrings, - &subrIdx, &privateDicts[fdSelect[gid]], gTrue); - } - } - } - 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, 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, buf, &ok); - if (ok) { - (*outputFunc)(outputStream, " /Registry (", 13); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") def\n", 6); - } - ok = gTrue; - getString(topDict.orderingSID, buf, &ok); - if (ok) { - (*outputFunc)(outputStream, " /Ordering (", 13); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, ") def\n", 6); - } - } else { - (*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24); - (*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27); - } - sprintf(buf, " /Supplement %d def\n", topDict.supplement); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "end def\n", 8); - if (topDict.hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - topDict.fontMatrix[0], topDict.fontMatrix[1], - topDict.fontMatrix[2], topDict.fontMatrix[3], - topDict.fontMatrix[4], topDict.fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else if (privateDicts[0].hasFontMatrix) { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } else { - (*outputFunc)(outputStream, - "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38); - } - sprintf(buf, "/FontBBox [%g %g %g %g] def\n", - topDict.fontBBox[0], topDict.fontBBox[1], - topDict.fontBBox[2], topDict.fontBBox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27); - (*outputFunc)(outputStream, " /FSType 8 def\n", 16); - (*outputFunc)(outputStream, "end def\n", 8); - - // CIDFont-specific entries - sprintf(buf, "/CIDCount %d def\n", nCIDs); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15); - sprintf(buf, "/GDBytes %d def\n", gdBytes); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20); - if (topDict.paintType != 0) { - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - - // FDArray entry - sprintf(buf, "/FDArray %d array\n", nFDs); - (*outputFunc)(outputStream, buf, strlen(buf)); - for (i = 0; i < nFDs; ++i) { - sprintf(buf, "dup %d 10 dict begin\n", i); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 1 def\n", 16); - if (privateDicts[i].hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - privateDicts[i].fontMatrix[0], - privateDicts[i].fontMatrix[1], - privateDicts[i].fontMatrix[2], - privateDicts[i].fontMatrix[3], - privateDicts[i].fontMatrix[4], - privateDicts[i].fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23); - if (privateDicts[i].nBlueValues) { - (*outputFunc)(outputStream, "/BlueValues [", 13); - for (j = 0; j < privateDicts[i].nBlueValues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].blueValues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nOtherBlues) { - (*outputFunc)(outputStream, "/OtherBlues [", 13); - for (j = 0; j < privateDicts[i].nOtherBlues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].otherBlues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nFamilyBlues) { - (*outputFunc)(outputStream, "/FamilyBlues [", 14); - for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", privateDicts[i].familyBlues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nFamilyOtherBlues) { - (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19); - for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) { - sprintf(buf, "%s%d", j > 0 ? " " : "", - privateDicts[i].familyOtherBlues[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].blueScale != 0.039625) { - sprintf(buf, "/BlueScale %g def\n", privateDicts[i].blueScale); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].blueShift != 7) { - sprintf(buf, "/BlueShift %d def\n", privateDicts[i].blueShift); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].blueFuzz != 1) { - sprintf(buf, "/BlueFuzz %d def\n", privateDicts[i].blueFuzz); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].hasStdHW) { - sprintf(buf, "/StdHW [%g] def\n", privateDicts[i].stdHW); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].hasStdVW) { - sprintf(buf, "/StdVW [%g] def\n", privateDicts[i].stdVW); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].nStemSnapH) { - (*outputFunc)(outputStream, "/StemSnapH [", 12); - for (j = 0; j < privateDicts[i].nStemSnapH; ++j) { - sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapH[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].nStemSnapV) { - (*outputFunc)(outputStream, "/StemSnapV [", 12); - for (j = 0; j < privateDicts[i].nStemSnapV; ++j) { - sprintf(buf, "%s%g", j > 0 ? " " : "", privateDicts[i].stemSnapV[j]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - } - if (privateDicts[i].hasForceBold) { - sprintf(buf, "/ForceBold %s def\n", - privateDicts[i].forceBold ? "true" : "false"); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].forceBoldThreshold != 0) { - sprintf(buf, "/ForceBoldThreshold %g def\n", - privateDicts[i].forceBoldThreshold); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].languageGroup != 0) { - sprintf(buf, "/LanguageGroup %d def\n", privateDicts[i].languageGroup); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (privateDicts[i].expansionFactor != 0.06) { - sprintf(buf, "/ExpansionFactor %g def\n", - privateDicts[i].expansionFactor); - (*outputFunc)(outputStream, buf, strlen(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); - sprintf(buf, "(Hex) %d StartData\n", - offset + charStrings->getLength()); - (*outputFunc)(outputStream, buf, strlen(buf)); - - // write the charstring offset (CIDMap) table - for (i = 0; i <= nCIDs; i += 6) { - for (j = 0; j < 6 && i+j <= nCIDs; ++j) { - if (i+j < nCIDs && cidMap[i+j] >= 0) { - buf[0] = (char)fdSelect[cidMap[i+j]]; - } else { - buf[0] = (char)0; - } - n = offset + charStringOffsets[i+j]; - for (k = gdBytes; k >= 1; --k) { - buf[k] = (char)(n & 0xff); - n >>= 8; - } - for (k = 0; k <= gdBytes; ++k) { - sprintf(buf2, "%02x", buf[k] & 0xff); - (*outputFunc)(outputStream, buf2, 2); - } - } - (*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) { - sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (i + 32 >= n) { - (*outputFunc)(outputStream, ">", 1); - } - (*outputFunc)(outputStream, "\n", 1); - } - - gfree(charStringOffsets); - delete charStrings; - gfree(cidMap); -} - -void FoFiType1C::convertToType0(char *psName, - FoFiOutputFunc outputFunc, - void *outputStream) { - int *cidMap; - Type1CIndex subrIdx; - Type1CIndexVal val; - int nCIDs; - char buf[512]; - Type1CEexecBuf eb; - GBool ok; - int fd, i, j, k; - - // compute the CID count and build the CID-to-GID mapping - nCIDs = 0; - for (i = 0; i < nGlyphs; ++i) { - if (charset[i] >= nCIDs) { - nCIDs = charset[i] + 1; - } - } - cidMap = (int *)gmallocn(nCIDs, sizeof(int)); - for (i = 0; i < nCIDs; ++i) { - cidMap[i] = -1; - } - for (i = 0; i < nGlyphs; ++i) { - cidMap[charset[i]] = i; - } - - // write the descendant Type 1 fonts - 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 - fd = 0; - for (j = 0; j < 256 && i+j < nCIDs; ++j) { - if (cidMap[i+j] >= 0) { - fd = fdSelect[cidMap[i+j]]; - break; - } - } - - // font dictionary (unencrypted section) - (*outputFunc)(outputStream, "16 dict begin\n", 14); - (*outputFunc)(outputStream, "/FontName /", 11); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x def\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - (*outputFunc)(outputStream, "/FontType 1 def\n", 16); - if (privateDicts[fd].hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - privateDicts[fd].fontMatrix[0], - privateDicts[fd].fontMatrix[1], - privateDicts[fd].fontMatrix[2], - privateDicts[fd].fontMatrix[3], - privateDicts[fd].fontMatrix[4], - privateDicts[fd].fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else if (topDict.hasFontMatrix) { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } else { - (*outputFunc)(outputStream, - "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38); - } - sprintf(buf, "/FontBBox [%g %g %g %g] def\n", - topDict.fontBBox[0], topDict.fontBBox[1], - topDict.fontBBox[2], topDict.fontBBox[3]); - (*outputFunc)(outputStream, buf, strlen(buf)); - sprintf(buf, "/PaintType %d def\n", topDict.paintType); - (*outputFunc)(outputStream, buf, strlen(buf)); - if (topDict.paintType != 0) { - sprintf(buf, "/StrokeWidth %g def\n", topDict.strokeWidth); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "/Encoding 256 array\n", 20); - for (j = 0; j < 256 && i+j < nCIDs; ++j) { - sprintf(buf, "dup %d /c%02x put\n", j, j); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - if (j < 256) { - sprintf(buf, "%d 1 255 { 1 index exch /.notdef put } for\n", j); - (*outputFunc)(outputStream, buf, strlen(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) { - sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].blueValues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nOtherBlues) { - eexecWrite(&eb, "/OtherBlues ["); - for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", privateDicts[fd].otherBlues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nFamilyBlues) { - eexecWrite(&eb, "/FamilyBlues ["); - for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", - privateDicts[fd].familyBlues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nFamilyOtherBlues) { - eexecWrite(&eb, "/FamilyOtherBlues ["); - for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) { - sprintf(buf, "%s%d", k > 0 ? " " : "", - privateDicts[fd].familyOtherBlues[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].blueScale != 0.039625) { - sprintf(buf, "/BlueScale %g def\n", privateDicts[fd].blueScale); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].blueShift != 7) { - sprintf(buf, "/BlueShift %d def\n", privateDicts[fd].blueShift); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].blueFuzz != 1) { - sprintf(buf, "/BlueFuzz %d def\n", privateDicts[fd].blueFuzz); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].hasStdHW) { - sprintf(buf, "/StdHW [%g] def\n", privateDicts[fd].stdHW); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].hasStdVW) { - sprintf(buf, "/StdVW [%g] def\n", privateDicts[fd].stdVW); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].nStemSnapH) { - eexecWrite(&eb, "/StemSnapH ["); - for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) { - sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].nStemSnapV) { - eexecWrite(&eb, "/StemSnapV ["); - for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) { - sprintf(buf, "%s%g", k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]); - eexecWrite(&eb, buf); - } - eexecWrite(&eb, "] def\n"); - } - if (privateDicts[fd].hasForceBold) { - sprintf(buf, "/ForceBold %s def\n", - privateDicts[fd].forceBold ? "true" : "false"); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].forceBoldThreshold != 0) { - sprintf(buf, "/ForceBoldThreshold %g def\n", - privateDicts[fd].forceBoldThreshold); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].languageGroup != 0) { - sprintf(buf, "/LanguageGroup %d def\n", privateDicts[fd].languageGroup); - eexecWrite(&eb, buf); - } - if (privateDicts[fd].expansionFactor != 0.06) { - sprintf(buf, "/ExpansionFactor %g def\n", - privateDicts[fd].expansionFactor); - eexecWrite(&eb, buf); - } - - // set up the subroutines - ok = gTrue; - getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok); - if (!ok) { - subrIdx.pos = -1; - } - - // start the CharStrings - sprintf(buf, "2 index /CharStrings 256 dict dup begin\n"); - eexecWrite(&eb, buf); - - // 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) { - sprintf(buf, "c%02x", j); - eexecCvtGlyph(&eb, buf, val.pos, val.len, - &subrIdx, &privateDicts[fd]); - } - } - } - 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, strlen(psName)); - (*outputFunc)(outputStream, " def\n", 5); - (*outputFunc)(outputStream, "/FontType 0 def\n", 16); - if (topDict.hasFontMatrix) { - sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n", - topDict.fontMatrix[0], topDict.fontMatrix[1], - topDict.fontMatrix[2], topDict.fontMatrix[3], - topDict.fontMatrix[4], topDict.fontMatrix[5]); - (*outputFunc)(outputStream, buf, strlen(buf)); - } else { - (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30); - } - (*outputFunc)(outputStream, "/FMapType 2 def\n", 16); - (*outputFunc)(outputStream, "/Encoding [\n", 12); - for (i = 0; i < nCIDs; i += 256) { - sprintf(buf, "%d\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "/FDepVector [\n", 14); - for (i = 0; i < nCIDs; i += 256) { - (*outputFunc)(outputStream, "/", 1); - (*outputFunc)(outputStream, psName, strlen(psName)); - sprintf(buf, "_%02x findfont\n", i >> 8); - (*outputFunc)(outputStream, buf, strlen(buf)); - } - (*outputFunc)(outputStream, "] def\n", 6); - (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40); - - gfree(cidMap); -} - -void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName, - int offset, int nBytes, - Type1CIndex *subrIdx, - Type1CPrivateDict *pDict) { - char buf[512]; - GString *charBuf; - - // generate the charstring - charBuf = new GString(); - cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue); - - sprintf(buf, "/%s %d RD ", glyphName, charBuf->getLength()); - eexecWrite(eb, buf); - 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) { - Type1CIndexVal val; - GBool ok, dFP; - double d, dx, dy; - Gushort r2; - Guchar byte; - int pos, subrBias, start, i, k; - - 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; - } - - pos = offset; - while (pos < offset + nBytes) { - ok = gTrue; - pos = getOp(pos, gTrue, &ok); - if (!ok) { - break; - } - if (!ops[nOps - 1].isNum) { - --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; - dFP = gFalse; - for (k = 0; k < nOps; k += 2) { - // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints - if (ops[k+1].num < 0) { - d += ops[k].num + ops[k+1].num; - dFP |= ops[k].isFP | ops[k+1].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf); - } else { - d += ops[k].num; - dFP |= ops[k].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - d += ops[k+1].num; - dFP |= ops[k+1].isFP; - } - 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; - dFP = gFalse; - for (k = 0; k < nOps; k += 2) { - // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints - if (ops[k+1].num < 0) { - d += ops[k].num + ops[k+1].num; - dFP |= ops[k].isFP | ops[k+1].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf); - } else { - d += ops[k].num; - dFP |= ops[k].isFP; - cvtNum(d, dFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - d += ops[k+1].num; - dFP |= ops[k+1].isFP; - } - 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].num, ops[0].isFP, 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 < nOps; k += 2) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, 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].num, ops[k].isFP, 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].num, ops[k].isFP, 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].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+5].num, ops[k+5].isFP, 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 + (int)ops[nOps - 1].num; - --nOps; - ok = gTrue; - getIndexVal(subrIdx, k, &val, &ok); - if (ok) { - cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse); - } - } 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(0, gFalse, charBuf); - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, 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].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, 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].num, ops[0].isFP, 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 - 2; k += 6) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf); - charBuf->append((char)8); - } - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k].isFP, 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 - 6; k += 2) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k].isFP, charBuf); - charBuf->append((char)5); - } - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+5].num, ops[k+5].isFP, 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) { - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - charBuf->append((char)8); - k = 5; - } else { - k = 0; - } - for (; k < nOps; k += 4) { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, 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) { - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - k = 5; - } else { - k = 0; - } - for (; k < nOps; k += 4) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x001d: // callgsubr - if (nOps >= 1) { - k = gsubrBias + (int)ops[nOps - 1].num; - --nOps; - ok = gTrue; - getIndexVal(&gsubrIdx, k, &val, &ok); - if (ok) { - cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse); - } - } 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 < nOps && k != nOps-5; k += 4) { - if (k % 8 == 0) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)30); - } else { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)31); - } - } - if (k == nOps-5) { - if (k % 8 == 0) { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - } else { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, 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 < nOps && k != nOps-5; k += 4) { - if (k % 8 == 0) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)31); - } else { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - charBuf->append((char)30); - } - } - if (k == nOps-5) { - if (k % 8 == 0) { - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - } else { - cvtNum(0, gFalse, charBuf); - cvtNum(ops[k].num, ops[k].isFP, charBuf); - cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf); - cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf); - cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf); - cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf); - } - charBuf->append((char)8); - } - nOps = 0; - openPath = gTrue; - break; - case 0x0c00: // dotsection (should be Type 1 only?) - // ignored - nOps = 0; - break; - case 0x0c03: // and - case 0x0c04: // or - case 0x0c05: // not - case 0x0c08: // store - case 0x0c09: // abs - case 0x0c0a: // add - case 0x0c0b: // sub - case 0x0c0c: // div - 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) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - cvtNum(-ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x0c23: // flex - if (nOps != 13) { - //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - charBuf->append((char)8); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(ops[7].num, ops[7].isFP, charBuf); - cvtNum(ops[8].num, ops[8].isFP, charBuf); - cvtNum(ops[9].num, ops[9].isFP, charBuf); - cvtNum(ops[10].num, ops[10].isFP, charBuf); - cvtNum(ops[11].num, ops[11].isFP, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x0c24: // hflex1 - if (nOps != 9) { - //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - charBuf->append((char)8); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - cvtNum(0, gFalse, charBuf); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(ops[7].num, ops[7].isFP, charBuf); - cvtNum(ops[8].num, ops[8].isFP, charBuf); - cvtNum(-(ops[1].num + ops[3].num + ops[7].num), - ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf); - charBuf->append((char)8); - nOps = 0; - openPath = gTrue; - break; - case 0x0c25: // flex1 - if (nOps != 11) { - //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps); - } - cvtNum(ops[0].num, ops[0].isFP, charBuf); - cvtNum(ops[1].num, ops[1].isFP, charBuf); - cvtNum(ops[2].num, ops[2].isFP, charBuf); - cvtNum(ops[3].num, ops[3].isFP, charBuf); - cvtNum(ops[4].num, ops[4].isFP, charBuf); - cvtNum(ops[5].num, ops[5].isFP, charBuf); - charBuf->append((char)8); - cvtNum(ops[6].num, ops[6].isFP, charBuf); - cvtNum(ops[7].num, ops[7].isFP, charBuf); - cvtNum(ops[8].num, ops[8].isFP, charBuf); - cvtNum(ops[9].num, ops[9].isFP, charBuf); - dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num; - dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num; - if (fabs(dx) > fabs(dy)) { - cvtNum(ops[10].num, ops[10].isFP, charBuf); - cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP | - ops[7].isFP | ops[9].isFP, charBuf); - } else { - cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP | - ops[6].isFP | ops[8].isFP, charBuf); - cvtNum(ops[10].num, ops[10].isFP, charBuf); - } - charBuf->append((char)8); - 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 = charBuf->getChar(i) ^ (r2 >> 8); - charBuf->setChar(i, byte); - r2 = (byte + r2) * 52845 + 22719; - } - } -} - -void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *charBuf, - Type1CPrivateDict *pDict) { - double w; - GBool wFP; - int i; - - if (useOp) { - w = pDict->nominalWidthX + ops[0].num; - wFP = pDict->nominalWidthXFP | ops[0].isFP; - for (i = 1; i < nOps; ++i) { - ops[i-1] = ops[i]; - } - --nOps; - } else { - w = pDict->defaultWidthX; - wFP = pDict->defaultWidthXFP; - } - cvtNum(0, gFalse, charBuf); - cvtNum(w, wFP, charBuf); - charBuf->append((char)13); -} - -void FoFiType1C::cvtNum(double x, GBool isFP, GString *charBuf) { - Guchar buf[12]; - int y, n; - - n = 0; - if (isFP) { - if (x >= -32768 && x < 32768) { - y = (int)(x * 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"); - } - } else { - y = (int)x; - 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; - } - } - charBuf->append((char *)buf, n); -} - -void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) { - Guchar *p; - Guchar x; - - for (p = (Guchar *)s; *p; ++p) { - x = *p ^ (eb->r1 >> 8); - eb->r1 = (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] ^ (eb->r1 >> 8); - eb->r1 = (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); - } - } -} - -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 { - 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].isNum) { - --nOps; // drop the operator - if (topDict.firstOp < 0) { - topDict.firstOp = ops[nOps].op; - } - switch (ops[nOps].op) { - case 0x0000: topDict.versionSID = (int)ops[0].num; break; - case 0x0001: topDict.noticeSID = (int)ops[0].num; break; - case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break; - case 0x0002: topDict.fullNameSID = (int)ops[0].num; break; - case 0x0003: topDict.familyNameSID = (int)ops[0].num; break; - case 0x0004: topDict.weightSID = (int)ops[0].num; break; - case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break; - case 0x0c02: topDict.italicAngle = ops[0].num; break; - case 0x0c03: topDict.underlinePosition = ops[0].num; break; - case 0x0c04: topDict.underlineThickness = ops[0].num; break; - case 0x0c05: topDict.paintType = (int)ops[0].num; break; - case 0x0c06: topDict.charstringType = (int)ops[0].num; break; - case 0x0c07: topDict.fontMatrix[0] = ops[0].num; - topDict.fontMatrix[1] = ops[1].num; - topDict.fontMatrix[2] = ops[2].num; - topDict.fontMatrix[3] = ops[3].num; - topDict.fontMatrix[4] = ops[4].num; - topDict.fontMatrix[5] = ops[5].num; - topDict.hasFontMatrix = gTrue; break; - case 0x000d: topDict.uniqueID = (int)ops[0].num; break; - case 0x0005: topDict.fontBBox[0] = ops[0].num; - topDict.fontBBox[1] = ops[1].num; - topDict.fontBBox[2] = ops[2].num; - topDict.fontBBox[3] = ops[3].num; break; - case 0x0c08: topDict.strokeWidth = ops[0].num; break; - case 0x000f: topDict.charsetOffset = (int)ops[0].num; break; - case 0x0010: topDict.encodingOffset = (int)ops[0].num; break; - case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break; - case 0x0012: topDict.privateSize = (int)ops[0].num; - topDict.privateOffset = (int)ops[1].num; break; - case 0x0c1e: topDict.registrySID = (int)ops[0].num; - topDict.orderingSID = (int)ops[1].num; - topDict.supplement = (int)ops[2].num; break; - case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break; - case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; 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; - pSize = pOffset = 0; - pos = offset; - nOps = 0; - while (pos < offset + length) { - pos = getOp(pos, gFalse, &parsedOk); - if (!parsedOk) { - return; - } - if (!ops[nOps - 1].isNum) { - if (ops[nOps - 1].op == 0x0012) { - if (nOps < 3) { - parsedOk = gFalse; - return; - } - pSize = (int)ops[0].num; - pOffset = (int)ops[1].num; - break; - } else if (ops[nOps - 1].op == 0x0c07) { - fontMatrix[0] = ops[0].num; - fontMatrix[1] = ops[1].num; - fontMatrix[2] = ops[2].num; - fontMatrix[3] = ops[3].num; - fontMatrix[4] = ops[4].num; - fontMatrix[5] = ops[5].num; - 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->defaultWidthXFP = gFalse; - pDict->nominalWidthX = 0; - pDict->nominalWidthXFP = gFalse; - - // 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].isNum) { - --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].num; - break; - case 0x0c0a: - pDict->blueShift = (int)ops[0].num; - break; - case 0x0c0b: - pDict->blueFuzz = (int)ops[0].num; - break; - case 0x000a: - pDict->stdHW = ops[0].num; - pDict->hasStdHW = gTrue; - break; - case 0x000b: - pDict->stdVW = ops[0].num; - 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].num != 0; - pDict->hasForceBold = gTrue; - break; - case 0x0c0f: - pDict->forceBoldThreshold = ops[0].num; - break; - case 0x0c11: - pDict->languageGroup = (int)ops[0].num; - break; - case 0x0c12: - pDict->expansionFactor = ops[0].num; - break; - case 0x0c13: - pDict->initialRandomSeed = (int)ops[0].num; - break; - case 0x0013: - pDict->subrsOffset = offset + (int)ops[0].num; - break; - case 0x0014: - pDict->defaultWidthX = ops[0].num; - pDict->defaultWidthXFP = ops[0].isFP; - break; - case 0x0015: - pDict->nominalWidthX = ops[0].num; - pDict->nominalWidthXFP = ops[0].isFP; - break; - } - nOps = 0; - } - } -} - -void FoFiType1C::readFDSelect() { - int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j; - - fdSelect = (Guchar *)gmalloc(nGlyphs); - if (topDict.fdSelectOffset == 0) { - for (i = 0; i < nGlyphs; ++i) { - fdSelect[i] = 0; - } - } else { - pos = topDict.fdSelectOffset; - fdSelectFmt = getU8(pos++, &parsedOk); - if (!parsedOk) { - return; - } - if (fdSelectFmt == 0) { - if (!checkRegion(pos, nGlyphs)) { - parsedOk = gFalse; - return; - } - memcpy(fdSelect, file + pos, nGlyphs); - } 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) { - //~ error(-1, "Bad FDSelect table in CID font"); - parsedOk = gFalse; - return; - } - for (j = gid0; j < gid1; ++j) { - fdSelect[j] = fd; - } - gid0 = gid1; - } - } else { - //~ error(-1, "Unknown FDSelect table format in CID font"); - for (i = 0; i < nGlyphs; ++i) { - fdSelect[i] = 0; - } - } - } -} - -void FoFiType1C::buildEncoding() { - char buf[256]; - int nCodes, nRanges, encFormat; - int pos, c, sid, nLeft, nSups, i, j; - - if (topDict.encodingOffset == 0) { - encoding = fofiType1StandardEncoding; - - } else if (topDict.encodingOffset == 1) { - encoding = 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; - } else if (topDict.charsetOffset == 1) { - charset = fofiType1CExpertCharset; - } else if (topDict.charsetOffset == 2) { - charset = fofiType1CExpertSubsetCharset; - } 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); - op.isNum = gTrue; - op.isFP = gFalse; - - if (b0 == 28) { - x = getU8(pos++, ok); - x = (x << 8) | getU8(pos++, ok); - if (x & 0x8000) { - x |= ~0xffff; - } - op.num = 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.num = 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.num = atof(buf); - op.isFP = gTrue; - - } else if (b0 >= 32 && b0 <= 246) { - op.num = b0 - 139; - - } else if (b0 >= 247 && b0 <= 250) { - op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108; - - } else if (b0 >= 251 && b0 <= 254) { - op.num = -((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.num = (double)x / 65536.0; - op.isFP = gTrue; - - } else if (b0 == 12) { - op.isNum = gFalse; - op.op = 0x0c00 + getU8(pos++, ok); - - } else { - op.isNum = gFalse; - 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 += (int)ops[i].num; - 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].num; - 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) { - *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 < 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/pdf2swf/xpdf/FoFiType1C.h b/pdf2swf/xpdf/FoFiType1C.h deleted file mode 100644 index 62649ed..0000000 --- a/pdf2swf/xpdf/FoFiType1C.h +++ /dev/null @@ -1,232 +0,0 @@ -//======================================================================== -// -// FoFiType1C.h -// -// Copyright 1999-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FOFITYPE1C_H -#define FOFITYPE1C_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "FoFiBase.h" - -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 defaultWidthXFP; - double nominalWidthX; - GBool nominalWidthXFP; -}; - -struct Type1COp { - GBool isNum; // true -> number, false -> operator - GBool isFP; // true -> floating point number, false -> int - union { - double num; // if num is true - int op; // if num is false - }; -}; - -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(); - - // Return the mapping from CIDs to GIDs, and return the number of - // CIDs in *. This is only useful for CID fonts. - Gushort *getCIDToGIDMap(int *nCIDs); - - // Convert to a Type 1 font, suitable for embedding in a PostScript - // file. This is only useful with 8-bit fonts. If is - // not NULL, it will be used in place of the encoding in the Type 1C - // font. If is true the eexec section will be hex-encoded, - // otherwise it will be left as binary data. - void convertToType1(char **newEncoding, GBool ascii, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 0 CIDFont, suitable for embedding in a - // PostScript file. will be used as the PostScript font - // name. - void convertToCIDType0(char *psName, - FoFiOutputFunc outputFunc, void *outputStream); - - // Convert to a Type 0 (but non-CID) composite font, suitable for - // embedding in a PostScript file. will be used as the - // PostScript font name. - void convertToType0(char *psName, - FoFiOutputFunc outputFunc, void *outputStream); - -private: - - FoFiType1C(char *fileA, int lenA, GBool freeFileDataA); - void eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName, - int offset, int nBytes, - Type1CIndex *subrIdx, - Type1CPrivateDict *pDict); - void cvtGlyph(int offset, int nBytes, GString *charBuf, - Type1CIndex *subrIdx, Type1CPrivateDict *pDict, - GBool top); - void cvtGlyphWidth(GBool useOp, GString *charBuf, - Type1CPrivateDict *pDict); - void cvtNum(double x, GBool isFP, GString *charBuf); - void eexecWrite(Type1CEexecBuf *eb, char *s); - void eexecWriteCharstring(Type1CEexecBuf *eb, Guchar *s, int n); - 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/pdf2swf/xpdf/FontEncodingTables.cc b/pdf2swf/xpdf/FontEncodingTables.cc deleted file mode 100644 index f3b9280..0000000 --- a/pdf2swf/xpdf/FontEncodingTables.cc +++ /dev/null @@ -1,1824 +0,0 @@ -//======================================================================== -// -// FontEncodingTables.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include -#include -#include "FontEncodingTables.h" - -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" -}; - -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 -}; - -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" -}; - -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 -}; - -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" -}; - -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 -}; - -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/pdf2swf/xpdf/FontEncodingTables.h b/pdf2swf/xpdf/FontEncodingTables.h deleted file mode 100644 index 8b0a1e7..0000000 --- a/pdf2swf/xpdf/FontEncodingTables.h +++ /dev/null @@ -1,20 +0,0 @@ -//======================================================================== -// -// FontEncodingTables.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FONTENCODINGTABLES_H -#define FONTENCODINGTABLES_H - -extern char *macRomanEncoding[]; -extern char *macExpertEncoding[]; -extern char *winAnsiEncoding[]; -extern char *standardEncoding[]; -extern char *expertEncoding[]; -extern char *symbolEncoding[]; -extern char *zapfDingbatsEncoding[]; - -#endif diff --git a/pdf2swf/xpdf/Function.cc b/pdf2swf/xpdf/Function.cc deleted file mode 100644 index f699641..0000000 --- a/pdf2swf/xpdf/Function.cc +++ /dev/null @@ -1,1535 +0,0 @@ -//======================================================================== -// -// Function.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#include "gmem.h" -#include "Object.h" -#include "Dict.h" -#include "Stream.h" -#include "Error.h" -#include "Function.h" - -//------------------------------------------------------------------------ -// Function -//------------------------------------------------------------------------ - -Function::Function() { -} - -Function::~Function() { -} - -Function *Function::parse(Object *funcObj) { - Function *func; - Dict *dict; - int funcType; - Object obj1; - - if (funcObj->isStream()) { - dict = funcObj->streamGetDict(); - } else if (funcObj->isDict()) { - dict = funcObj->getDict(); - } else if (funcObj->isName("Identity")) { - return new IdentityFunction(); - } else { - error(-1, "Expected function dictionary or stream"); - return NULL; - } - - if (!dict->lookup("FunctionType", &obj1)->isInt()) { - error(-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); - } else if (funcType == 4) { - func = new PostScriptFunction(funcObj, dict); - } else { - error(-1, "Unimplemented function type (%d)", funcType); - return NULL; - } - if (!func->isOk()) { - delete func; - return NULL; - } - - return func; -} - -GBool Function::init(Dict *dict) { - Object obj1, obj2; - int i; - - //----- Domain - if (!dict->lookup("Domain", &obj1)->isArray()) { - error(-1, "Function is missing domain"); - goto err2; - } - m = obj1.arrayGetLength() / 2; - if (m > funcMaxInputs) { - error(-1, "Functions with more than %d inputs are unsupported", - funcMaxInputs); - goto err2; - } - for (i = 0; i < m; ++i) { - obj1.arrayGet(2*i, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function domain array"); - goto err1; - } - domain[i][0] = obj2.getNum(); - obj2.free(); - obj1.arrayGet(2*i+1, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function domain array"); - 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(-1, "Functions with more than %d outputs are unsupported", - funcMaxOutputs); - goto err2; - } - for (i = 0; i < n; ++i) { - obj1.arrayGet(2*i, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function range array"); - goto err1; - } - range[i][0] = obj2.getNum(); - obj2.free(); - obj1.arrayGet(2*i+1, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function range array"); - 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 i; - - // fill these in with arbitrary values just in case they get used - // somewhere - m = funcMaxInputs; - n = funcMaxOutputs; - for (i = 0; i < funcMaxInputs; ++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 < funcMaxOutputs; ++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; - int s; - int i; - - samples = NULL; - ok = gFalse; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (!hasRange) { - error(-1, "Type 0 function is missing range"); - goto err1; - } - - //----- get the stream - if (!funcObj->isStream()) { - error(-1, "Type 0 function isn't a stream"); - goto err1; - } - str = funcObj->getStream(); - - //----- Size - if (!dict->lookup("Size", &obj1)->isArray() || - obj1.arrayGetLength() != m) { - error(-1, "Function has missing or invalid size array"); - goto err2; - } - for (i = 0; i < m; ++i) { - obj1.arrayGet(i, &obj2); - if (!obj2.isInt()) { - error(-1, "Illegal value in function size array"); - goto err3; - } - sampleSize[i] = obj2.getInt(); - obj2.free(); - } - obj1.free(); - idxMul[0] = n; - for (i = 1; i < m; ++i) { - idxMul[i] = idxMul[i-1] * sampleSize[i-1]; - } - - //----- BitsPerSample - if (!dict->lookup("BitsPerSample", &obj1)->isInt()) { - error(-1, "Function has missing or invalid BitsPerSample"); - goto err2; - } - sampleBits = obj1.getInt(); - sampleMul = 1.0 / (double)((1 << 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(-1, "Illegal value in function encode array"); - goto err3; - } - encode[i][0] = obj2.getNum(); - obj2.free(); - obj1.arrayGet(2*i+1, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function encode array"); - 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(-1, "Illegal value in function decode array"); - goto err3; - } - decode[i][0] = obj2.getNum(); - obj2.free(); - obj1.arrayGet(2*i+1, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function decode array"); - 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) - nSamples *= sampleSize[i]; - samples = (double *)gmallocn(nSamples, sizeof(double)); - buf = 0; - bits = 0; - bitMask = (1 << sampleBits) - 1; - 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(); - - ok = gTrue; - return; - - err3: - obj2.free(); - err2: - obj1.free(); - err1: - return; -} - -SampledFunction::~SampledFunction() { - if (samples) { - gfree(samples); - } -} - -SampledFunction::SampledFunction(SampledFunction *func) { - memcpy(this, func, sizeof(SampledFunction)); - samples = (double *)gmallocn(nSamples, sizeof(double)); - memcpy(samples, func->samples, nSamples * sizeof(double)); -} - -void SampledFunction::transform(double *in, double *out) { - double x; - int e[funcMaxInputs][2]; - double efrac0[funcMaxInputs]; - double efrac1[funcMaxInputs]; - double s[1 << funcMaxInputs]; - int i, j, k, idx, t; - - // map input values into sample array - for (i = 0; i < m; ++i) { - x = (in[i] - domain[i][0]) * inputMul[i] + encode[i][0]; - if (x < 0) { - x = 0; - } else if (x > sampleSize[i] - 1) { - x = sampleSize[i] - 1; - } - e[i][0] = (int)x; - if ((e[i][1] = e[i][0] + 1) >= sampleSize[i]) { - // this happens if in[i] = domain[i][1] - e[i][1] = e[i][0]; - } - efrac1[i] = x - e[i][0]; - efrac0[i] = 1 - efrac1[i]; - } - - // for each output, do m-linear interpolation - for (i = 0; i < n; ++i) { - - // pull 2^m values out of the sample array - for (j = 0; j < (1<>= 1) { - idx += idxMul[k] * (e[k][t & 1]); - } - s[j] = samples[idx]; - } - - // do m sets of interpolations - for (j = 0, t = (1<>= 1) { - for (k = 0; k < t; k += 2) { - s[k >> 1] = efrac0[j] * s[k] + efrac1[j] * s[k+1]; - } - } - - // map output value to range - out[i] = s[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]; - } - } -} - -//------------------------------------------------------------------------ -// 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(-1, "Exponential function with more than one input"); - goto err1; - } - - //----- C0 - if (dict->lookup("C0", &obj1)->isArray()) { - if (hasRange && obj1.arrayGetLength() != n) { - error(-1, "Function's C0 array is wrong length"); - goto err2; - } - n = obj1.arrayGetLength(); - for (i = 0; i < n; ++i) { - obj1.arrayGet(i, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function C0 array"); - goto err3; - } - c0[i] = obj2.getNum(); - obj2.free(); - } - } else { - if (hasRange && n != 1) { - error(-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(-1, "Function's C1 array is wrong length"); - goto err2; - } - for (i = 0; i < n; ++i) { - obj1.arrayGet(i, &obj2); - if (!obj2.isNum()) { - error(-1, "Illegal value in function C1 array"); - goto err3; - } - c1[i] = obj2.getNum(); - obj2.free(); - } - } else { - if (n != 1) { - error(-1, "Function's C1 array is wrong length"); - goto err2; - } - c1[0] = 1; - } - obj1.free(); - - //----- N (exponent) - if (!dict->lookup("N", &obj1)->isNum()) { - error(-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(this, 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) { - Object obj1, obj2; - int i; - - ok = gFalse; - funcs = NULL; - bounds = NULL; - encode = NULL; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (m != 1) { - error(-1, "Stitching function with more than one input"); - goto err1; - } - - //----- Functions - if (!dict->lookup("Functions", &obj1)->isArray()) { - error(-1, "Missing 'Functions' entry in stitching function"); - 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)); - for (i = 0; i < k; ++i) { - funcs[i] = NULL; - } - for (i = 0; i < k; ++i) { - if (!(funcs[i] = Function::parse(obj1.arrayGet(i, &obj2)))) { - goto err2; - } - if (i > 0 && (funcs[i]->getInputSize() != 1 || - funcs[i]->getOutputSize() != funcs[0]->getOutputSize())) { - error(-1, "Incompatible subfunctions in stitching function"); - goto err2; - } - obj2.free(); - } - obj1.free(); - - //----- Bounds - if (!dict->lookup("Bounds", &obj1)->isArray() || - obj1.arrayGetLength() != k - 1) { - error(-1, "Missing or invalid 'Bounds' entry in stitching function"); - goto err1; - } - bounds[0] = domain[0][0]; - for (i = 1; i < k; ++i) { - if (!obj1.arrayGet(i - 1, &obj2)->isNum()) { - error(-1, "Invalid type in 'Bounds' array in stitching function"); - 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(-1, "Missing or invalid 'Encode' entry in stitching function"); - goto err1; - } - for (i = 0; i < 2 * k; ++i) { - if (!obj1.arrayGet(i, &obj2)->isNum()) { - error(-1, "Invalid type in 'Encode' array in stitching function"); - goto err2; - } - encode[i] = obj2.getNum(); - obj2.free(); - } - obj1.free(); - - ok = gTrue; - return; - - err2: - obj2.free(); - err1: - obj1.free(); -} - -StitchingFunction::StitchingFunction(StitchingFunction *func) { - int i; - - k = func->k; - 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)); - 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); -} - -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]) / (bounds[i+1] - bounds[i])) * - (encode[2*i+1] - encode[2*i]); - funcs[i]->transform(&x, out); -} - -//------------------------------------------------------------------------ -// PostScriptFunction -//------------------------------------------------------------------------ - -enum PSOp { - psOpAbs, - psOpAdd, - psOpAnd, - psOpAtan, - psOpBitshift, - psOpCeiling, - psOpCopy, - psOpCos, - psOpCvi, - psOpCvr, - psOpDiv, - psOpDup, - psOpEq, - psOpExch, - psOpExp, - psOpFalse, - psOpFloor, - psOpGe, - psOpGt, - psOpIdiv, - psOpIndex, - psOpLe, - psOpLn, - psOpLog, - psOpLt, - psOpMod, - psOpMul, - psOpNe, - psOpNeg, - psOpNot, - psOpOr, - psOpPop, - psOpRoll, - psOpRound, - psOpSin, - psOpSqrt, - psOpSub, - psOpTrue, - psOpTruncate, - psOpXor, - psOpIf, - psOpIfelse, - psOpReturn -}; - -// Note: 'if' and 'ifelse' are parsed separately. -// The rest are listed here in alphabetical order. -// The index in this table is equivalent to the entry in PSOp. -char *psOpNames[] = { - "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" -}; - -#define nPSOps (sizeof(psOpNames) / sizeof(char *)) - -enum PSObjectType { - psBool, - psInt, - psReal, - psOperator, - psBlock -}; - -// In the code array, 'if'/'ifelse' operators take up three slots -// plus space for the code in the subclause(s). -// -// +---------------------------------+ -// | psOperator: psOpIf / psOpIfelse | -// +---------------------------------+ -// | psBlock: ptr= | -// +---------------------------------+ -// | psBlock: ptr= | -// +---------------------------------+ -// | if clause | -// | ... | -// | psOperator: psOpReturn | -// +---------------------------------+ -// | else clause | -// | ... | -// | psOperator: psOpReturn | -// +---------------------------------+ -// | ... | -// -// For 'if', pointer is present in the code stream but unused. - -struct PSObject { - PSObjectType type; - union { - GBool booln; // boolean (stack only) - int intg; // integer (stack and code) - double real; // real (stack and code) - PSOp op; // operator (code only) - int blk; // if/ifelse block pointer (code only) - }; -}; - -#define psStackSize 100 - -class PSStack { -public: - - PSStack() { sp = psStackSize; } - void pushBool(GBool booln); - void pushInt(int intg); - void pushReal(double real); - GBool popBool(); - int popInt(); - double popNum(); - GBool empty() { return sp == psStackSize; } - GBool topIsInt() { return sp < psStackSize && stack[sp].type == psInt; } - GBool topTwoAreInts() - { return sp < psStackSize - 1 && - stack[sp].type == psInt && - stack[sp+1].type == psInt; } - GBool topIsReal() { return sp < psStackSize && stack[sp].type == psReal; } - GBool topTwoAreNums() - { return sp < psStackSize - 1 && - (stack[sp].type == psInt || stack[sp].type == psReal) && - (stack[sp+1].type == psInt || stack[sp+1].type == psReal); } - void copy(int n); - void roll(int n, int j); - void index(int i); - void pop(); - -private: - - GBool checkOverflow(int n = 1); - GBool checkUnderflow(); - GBool checkType(PSObjectType t1, PSObjectType t2); - - PSObject stack[psStackSize]; - int sp; -}; - -GBool PSStack::checkOverflow(int n) { - if (sp - n < 0) { - error(-1, "Stack overflow in PostScript function"); - return gFalse; - } - return gTrue; -} - -GBool PSStack::checkUnderflow() { - if (sp == psStackSize) { - error(-1, "Stack underflow in PostScript function"); - return gFalse; - } - return gTrue; -} - -GBool PSStack::checkType(PSObjectType t1, PSObjectType t2) { - if (stack[sp].type != t1 && stack[sp].type != t2) { - error(-1, "Type mismatch in PostScript function"); - return gFalse; - } - return gTrue; -} - -void PSStack::pushBool(GBool booln) { - if (checkOverflow()) { - stack[--sp].type = psBool; - stack[sp].booln = booln; - } -} - -void PSStack::pushInt(int intg) { - if (checkOverflow()) { - stack[--sp].type = psInt; - stack[sp].intg = intg; - } -} - -void PSStack::pushReal(double real) { - if (checkOverflow()) { - stack[--sp].type = psReal; - stack[sp].real = real; - } -} - -GBool PSStack::popBool() { - if (checkUnderflow() && checkType(psBool, psBool)) { - return stack[sp++].booln; - } - return gFalse; -} - -int PSStack::popInt() { - if (checkUnderflow() && checkType(psInt, psInt)) { - return stack[sp++].intg; - } - return 0; -} - -double PSStack::popNum() { - double ret; - - if (checkUnderflow() && checkType(psInt, psReal)) { - ret = (stack[sp].type == psInt) ? (double)stack[sp].intg : stack[sp].real; - ++sp; - return ret; - } - return 0; -} - -void PSStack::copy(int n) { - int i; - - if (sp + n > psStackSize) { - error(-1, "Stack underflow in PostScript function"); - return; - } - if (!checkOverflow(n)) { - return; - } - for (i = sp + n - 1; i >= sp; --i) { - stack[i - n] = stack[i]; - } - sp -= n; -} - -void PSStack::roll(int n, int j) { - PSObject obj; - int i, k; - - if (j >= 0) { - j %= n; - } else { - j = -j % n; - if (j != 0) { - j = n - j; - } - } - if (n <= 0 || j == 0) { - return; - } - for (i = 0; i < j; ++i) { - obj = stack[sp]; - for (k = sp; k < sp + n - 1; ++k) { - stack[k] = stack[k+1]; - } - stack[sp + n - 1] = obj; - } -} - -void PSStack::index(int i) { - if (!checkOverflow()) { - return; - } - --sp; - stack[sp] = stack[sp + 1 + i]; -} - -void PSStack::pop() { - if (!checkUnderflow()) { - return; - } - ++sp; -} - -PostScriptFunction::PostScriptFunction(Object *funcObj, Dict *dict) { - Stream *str; - int codePtr; - GString *tok; - - code = NULL; - codeSize = 0; - ok = gFalse; - - //----- initialize the generic stuff - if (!init(dict)) { - goto err1; - } - if (!hasRange) { - error(-1, "Type 4 function is missing range"); - goto err1; - } - - //----- get the stream - if (!funcObj->isStream()) { - error(-1, "Type 4 function isn't a stream"); - goto err1; - } - str = funcObj->getStream(); - - //----- parse the function - codeString = new GString(); - str->reset(); - if (!(tok = getToken(str)) || tok->cmp("{")) { - error(-1, "Expected '{' at start of PostScript function"); - if (tok) { - delete tok; - } - goto err1; - } - delete tok; - codePtr = 0; - if (!parseCode(str, &codePtr)) { - goto err2; - } - str->close(); - - ok = gTrue; - - err2: - str->close(); - err1: - return; -} - -PostScriptFunction::PostScriptFunction(PostScriptFunction *func) { - memcpy(this, func, sizeof(PostScriptFunction)); - code = (PSObject *)gmallocn(codeSize, sizeof(PSObject)); - memcpy(code, func->code, codeSize * sizeof(PSObject)); - codeString = func->codeString->copy(); -} - -PostScriptFunction::~PostScriptFunction() { - gfree(code); - delete codeString; -} - -void PostScriptFunction::transform(double *in, double *out) { - PSStack *stack; - int i; - - stack = new PSStack(); - for (i = 0; i < m; ++i) { - //~ may need to check for integers here - stack->pushReal(in[i]); - } - exec(stack, 0); - for (i = n - 1; i >= 0; --i) { - out[i] = stack->popNum(); - if (out[i] < range[i][0]) { - out[i] = range[i][0]; - } else if (out[i] > range[i][1]) { - out[i] = range[i][1]; - } - } - // if (!stack->empty()) { - // error(-1, "Extra values on stack at end of PostScript function"); - // } - delete stack; -} - -GBool PostScriptFunction::parseCode(Stream *str, int *codePtr) { - GString *tok; - char *p; - GBool isReal; - int opPtr, elsePtr; - int a, b, mid, cmp; - - while (1) { - if (!(tok = getToken(str))) { - error(-1, "Unexpected end of PostScript function stream"); - return gFalse; - } - p = tok->getCString(); - if (isdigit(*p) || *p == '.' || *p == '-') { - isReal = gFalse; - for (++p; *p; ++p) { - if (*p == '.') { - isReal = gTrue; - break; - } - } - resizeCode(*codePtr); - if (isReal) { - code[*codePtr].type = psReal; - code[*codePtr].real = atof(tok->getCString()); - } else { - code[*codePtr].type = psInt; - code[*codePtr].intg = atoi(tok->getCString()); - } - ++*codePtr; - delete tok; - } else if (!tok->cmp("{")) { - delete tok; - opPtr = *codePtr; - *codePtr += 3; - resizeCode(opPtr + 2); - if (!parseCode(str, codePtr)) { - return gFalse; - } - if (!(tok = getToken(str))) { - error(-1, "Unexpected end of PostScript function stream"); - return gFalse; - } - if (!tok->cmp("{")) { - elsePtr = *codePtr; - if (!parseCode(str, codePtr)) { - return gFalse; - } - delete tok; - if (!(tok = getToken(str))) { - error(-1, "Unexpected end of PostScript function stream"); - return gFalse; - } - } else { - elsePtr = -1; - } - if (!tok->cmp("if")) { - if (elsePtr >= 0) { - error(-1, "Got 'if' operator with two blocks in PostScript function"); - return gFalse; - } - code[opPtr].type = psOperator; - code[opPtr].op = psOpIf; - code[opPtr+2].type = psBlock; - code[opPtr+2].blk = *codePtr; - } else if (!tok->cmp("ifelse")) { - if (elsePtr < 0) { - error(-1, "Got 'ifelse' operator with one blocks in PostScript function"); - return gFalse; - } - code[opPtr].type = psOperator; - code[opPtr].op = psOpIfelse; - code[opPtr+1].type = psBlock; - code[opPtr+1].blk = elsePtr; - code[opPtr+2].type = psBlock; - code[opPtr+2].blk = *codePtr; - } else { - error(-1, "Expected if/ifelse operator in PostScript function"); - delete tok; - return gFalse; - } - delete tok; - } else if (!tok->cmp("}")) { - delete tok; - resizeCode(*codePtr); - code[*codePtr].type = psOperator; - code[*codePtr].op = psOpReturn; - ++*codePtr; - break; - } else { - a = -1; - b = nPSOps; - // 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(-1, "Unknown operator '%s' in PostScript function", - tok->getCString()); - delete tok; - return gFalse; - } - delete tok; - resizeCode(*codePtr); - code[*codePtr].type = psOperator; - code[*codePtr].op = (PSOp)a; - ++*codePtr; - } - } - return gTrue; -} - -GString *PostScriptFunction::getToken(Stream *str) { - GString *s; - int c; - - s = new GString(); - do { - c = str->getChar(); - if (c != EOF) { - codeString->append(c); - } - } while (c != EOF && isspace(c)); - 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(c); - } - } else { - while (1) { - s->append((char)c); - c = str->lookChar(); - if (c == EOF || !isalnum(c)) { - break; - } - str->getChar(); - codeString->append(c); - } - } - return s; -} - -void PostScriptFunction::resizeCode(int newSize) { - if (newSize >= codeSize) { - codeSize += 64; - code = (PSObject *)greallocn(code, codeSize, sizeof(PSObject)); - } -} - -void PostScriptFunction::exec(PSStack *stack, int codePtr) { - int i1, i2; - double r1, r2; - GBool b1, b2; - - while (1) { - switch (code[codePtr].type) { - case psInt: - stack->pushInt(code[codePtr++].intg); - break; - case psReal: - stack->pushReal(code[codePtr++].real); - break; - case psOperator: - switch (code[codePtr++].op) { - case psOpAbs: - if (stack->topIsInt()) { - stack->pushInt(abs(stack->popInt())); - } else { - stack->pushReal(fabs(stack->popNum())); - } - break; - case psOpAdd: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 + i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 + r2); - } - break; - case psOpAnd: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 & i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 && b2); - } - break; - case psOpAtan: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(atan2(r1, r2)); - break; - case psOpBitshift: - i2 = stack->popInt(); - i1 = stack->popInt(); - if (i2 > 0) { - stack->pushInt(i1 << i2); - } else if (i2 < 0) { - stack->pushInt((int)((Guint)i1 >> i2)); - } else { - stack->pushInt(i1); - } - break; - case psOpCeiling: - if (!stack->topIsInt()) { - stack->pushReal(ceil(stack->popNum())); - } - break; - case psOpCopy: - stack->copy(stack->popInt()); - break; - case psOpCos: - stack->pushReal(cos(stack->popNum())); - break; - case psOpCvi: - if (!stack->topIsInt()) { - stack->pushInt((int)stack->popNum()); - } - break; - case psOpCvr: - if (!stack->topIsReal()) { - stack->pushReal(stack->popNum()); - } - break; - case psOpDiv: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 / r2); - break; - case psOpDup: - stack->copy(1); - break; - case psOpEq: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 == i2); - } else if (stack->topTwoAreNums()) { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 == r2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 == b2); - } - break; - case psOpExch: - stack->roll(2, 1); - break; - case psOpExp: - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(pow(r1, r2)); - break; - case psOpFalse: - stack->pushBool(gFalse); - break; - case psOpFloor: - if (!stack->topIsInt()) { - stack->pushReal(floor(stack->popNum())); - } - break; - case psOpGe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 >= i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 >= r2); - } - break; - case psOpGt: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 > i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 > r2); - } - break; - case psOpIdiv: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 / i2); - break; - case psOpIndex: - stack->index(stack->popInt()); - break; - case psOpLe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 <= i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 <= r2); - } - break; - case psOpLn: - stack->pushReal(log(stack->popNum())); - break; - case psOpLog: - stack->pushReal(log10(stack->popNum())); - break; - case psOpLt: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 < i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 < r2); - } - break; - case psOpMod: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 % i2); - break; - case psOpMul: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - //~ should check for out-of-range, and push a real instead - stack->pushInt(i1 * i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 * r2); - } - break; - case psOpNe: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushBool(i1 != i2); - } else if (stack->topTwoAreNums()) { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushBool(r1 != r2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 != b2); - } - break; - case psOpNeg: - if (stack->topIsInt()) { - stack->pushInt(-stack->popInt()); - } else { - stack->pushReal(-stack->popNum()); - } - break; - case psOpNot: - if (stack->topIsInt()) { - stack->pushInt(~stack->popInt()); - } else { - stack->pushBool(!stack->popBool()); - } - break; - case psOpOr: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 | i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 || b2); - } - break; - case psOpPop: - stack->pop(); - break; - case psOpRoll: - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->roll(i1, i2); - break; - case psOpRound: - if (!stack->topIsInt()) { - r1 = stack->popNum(); - stack->pushReal((r1 >= 0) ? floor(r1 + 0.5) : ceil(r1 - 0.5)); - } - break; - case psOpSin: - stack->pushReal(sin(stack->popNum())); - break; - case psOpSqrt: - stack->pushReal(sqrt(stack->popNum())); - break; - case psOpSub: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 - i2); - } else { - r2 = stack->popNum(); - r1 = stack->popNum(); - stack->pushReal(r1 - r2); - } - break; - case psOpTrue: - stack->pushBool(gTrue); - break; - case psOpTruncate: - if (!stack->topIsInt()) { - r1 = stack->popNum(); - stack->pushReal((r1 >= 0) ? floor(r1) : ceil(r1)); - } - break; - case psOpXor: - if (stack->topTwoAreInts()) { - i2 = stack->popInt(); - i1 = stack->popInt(); - stack->pushInt(i1 ^ i2); - } else { - b2 = stack->popBool(); - b1 = stack->popBool(); - stack->pushBool(b1 ^ b2); - } - break; - case psOpIf: - b1 = stack->popBool(); - if (b1) { - exec(stack, codePtr + 2); - } - codePtr = code[codePtr + 1].blk; - break; - case psOpIfelse: - b1 = stack->popBool(); - if (b1) { - exec(stack, codePtr + 2); - } else { - exec(stack, code[codePtr].blk); - } - codePtr = code[codePtr + 1].blk; - break; - case psOpReturn: - return; - } - break; - default: - error(-1, "Internal: bad object in PostScript function code"); - break; - } - } -} diff --git a/pdf2swf/xpdf/Function.h b/pdf2swf/xpdf/Function.h deleted file mode 100644 index bfaf83e..0000000 --- a/pdf2swf/xpdf/Function.h +++ /dev/null @@ -1,225 +0,0 @@ -//======================================================================== -// -// Function.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef FUNCTION_H -#define FUNCTION_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" - -class Dict; -class Stream; -struct PSObject; -class PSStack; - -//------------------------------------------------------------------------ -// Function -//------------------------------------------------------------------------ - -#define funcMaxInputs 8 -#define funcMaxOutputs 32 - -class Function { -public: - - Function(); - - virtual ~Function(); - - // Construct a function. Returns NULL if unsuccessful. - static Function *parse(Object *funcObj); - - // 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(); - virtual ~IdentityFunction(); - virtual Function *copy() { return new IdentityFunction(); } - 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 idxMul[funcMaxInputs]; // sample array index multipliers - double *samples; // the samples - int nSamples; // size of the samples array - 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); - 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; } - -private: - - StitchingFunction(StitchingFunction *func); - - int k; - Function **funcs; - double *bounds; - double *encode; - 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(Stream *str, int *codePtr); - GString *getToken(Stream *str); - void resizeCode(int newSize); - void exec(PSStack *stack, int codePtr); - - GString *codeString; - PSObject *code; - int codeSize; - GBool ok; -}; - -#endif diff --git a/pdf2swf/xpdf/GHash.cc b/pdf2swf/xpdf/GHash.cc deleted file mode 100644 index b51a764..0000000 --- a/pdf2swf/xpdf/GHash.cc +++ /dev/null @@ -1,380 +0,0 @@ -//======================================================================== -// -// GHash.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "gmem.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; - 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; - 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(char *key) { - GHashBucket *p; - int h; - - if (!(p = find(key, &h))) { - return NULL; - } - return p->val.p; -} - -int GHash::lookupInt(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(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(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(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) { - 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(char *key) { - 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/pdf2swf/xpdf/GHash.h b/pdf2swf/xpdf/GHash.h deleted file mode 100644 index 31aba93..0000000 --- a/pdf2swf/xpdf/GHash.h +++ /dev/null @@ -1,78 +0,0 @@ -//======================================================================== -// -// GHash.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GHASH_H -#define GHASH_H - -#include - -#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(char *key); - int lookupInt(char *key); - void *remove(GString *key); - int removeInt(GString *key); - void *remove(char *key); - int removeInt(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(char *key, int *h); - int hash(GString *key); - int hash(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/pdf2swf/xpdf/GList.cc b/pdf2swf/xpdf/GList.cc deleted file mode 100644 index fb5fd62..0000000 --- a/pdf2swf/xpdf/GList.cc +++ /dev/null @@ -1,97 +0,0 @@ -//======================================================================== -// -// GList.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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; - data = (void **)gmallocn(size, sizeof(void*)); - length = 0; - inc = 0; -} - -GList::~GList() { - gfree(data); -} - -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 < 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::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/pdf2swf/xpdf/GList.h b/pdf2swf/xpdf/GList.h deleted file mode 100644 index e4d8ff8..0000000 --- a/pdf2swf/xpdf/GList.h +++ /dev/null @@ -1,96 +0,0 @@ -//======================================================================== -// -// GList.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GLIST_H -#define GLIST_H - -#include - -#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 elements. - GList(int sizeA); - - // Destructor - does not free pointed-to objects. - ~GList(); - - //----- general - - // Get the number of elements. - int getLength() { return length; } - - //----- ordered list support - - // Return the th element. - // Assumes 0 <= i < length. - void *get(int i) { return data[i]; } - - // 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 . - // Assumes 0 <= i <= length. - void insert(int i, void *p); - - // Deletes and returns the element at index . - // 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)); - - //----- control - - // Set allocation increment to . 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/pdf2swf/xpdf/GMutex.h b/pdf2swf/xpdf/GMutex.h deleted file mode 100644 index 7fa93d8..0000000 --- a/pdf2swf/xpdf/GMutex.h +++ /dev/null @@ -1,49 +0,0 @@ -//======================================================================== -// -// GMutex.h -// -// Portable mutex macros. -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GMUTEX_H -#define GMUTEX_H - -// Usage: -// -// GMutex m; -// gInitMutex(&m); -// ... -// gLockMutex(&m); -// ... critical section ... -// gUnlockMutex(&m); -// ... -// gDestroyMutex(&m); - -#ifdef WIN32 - -#include - -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 - -#include - -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 - -#endif diff --git a/pdf2swf/xpdf/GString.cc b/pdf2swf/xpdf/GString.cc deleted file mode 100644 index 049dcf3..0000000 --- a/pdf2swf/xpdf/GString.cc +++ /dev/null @@ -1,319 +0,0 @@ -//======================================================================== -// -// GString.cc -// -// Simple variable-length string type. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#include "gtypes.h" -#include "GString.h" - -static inline int size(int len) { - int delta; - - delta = len < 256 ? 7 : 255; - return ((len + 1) + delta) & ~delta; -} - -inline void GString::resize(int length1) { - char *s1; - - 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 = 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; - 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 - GBool neg; - Guint y; - int i; - - i = 24; - if (x == 0) { - buf[--i] = '0'; - } else { - if ((neg = x < 0)) { - y = (Guint)-x; - } else { - y = (Guint)x; - } - while (i > 0 && y > 0) { - buf[--i] = '0' + y % 10; - y /= 10; - } - if (neg && i > 0) { - buf[--i] = '-'; - } - } - return new GString(buf + i, 24 - i); -} - -GString::~GString() { - delete[] s; -} - -GString *GString::clear() { - s[length = 0] = '\0'; - resize(0); - return this; -} - -GString *GString::append(char c) { - resize(length + 1); - s[length++] = c; - s[length] = '\0'; - return this; -} - -GString *GString::append(GString *str) { - int n = str->getLength(); - - resize(length + n); - memcpy(s + length, str->getCString(), n + 1); - length += n; - return this; -} - -GString *GString::append(const char *str) { - int n = strlen(str); - - resize(length + n); - memcpy(s + length, str, n + 1); - length += n; - return this; -} - -GString *GString::append(const char *str, int lengthA) { - resize(length + lengthA); - memcpy(s + length, str, lengthA); - length += lengthA; - s[length] = '\0'; - return this; -} - -GString *GString::insert(int i, char c) { - int j; - - 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; - - 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 = strlen(str); - int j; - - 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; - - 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 (n > 0) { - 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])) - s[i] = toupper(s[i]); - } - return this; -} - -GString *GString::lowerCase() { - int i; - - for (i = 0; i < length; ++i) { - if (isupper(s[i])) - s[i] = tolower(s[i]); - } - 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 - *p2; - 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 - *p2; - 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 - *p2; - 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 - *p2; - if (x != 0) { - return x; - } - } - if (i == n) { - return 0; - } - if (i < n1) { - return 1; - } - if (*p2) { - return -1; - } - return 0; -} diff --git a/pdf2swf/xpdf/GString.h b/pdf2swf/xpdf/GString.h deleted file mode 100644 index f4ff7c6..0000000 --- a/pdf2swf/xpdf/GString.h +++ /dev/null @@ -1,97 +0,0 @@ -//======================================================================== -// -// GString.h -// -// Simple variable-length string type. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GSTRING_H -#define GSTRING_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -class GString { -public: - - // Create an empty string. - GString(); - - // Create a string from a C string. - GString(const char *sA); - - // Create a string from chars at . This string - // can contain null characters. - GString(const char *sA, int lengthA); - - // Create a string from chars at in . - 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); - - // Destructor. - ~GString(); - - // Get length. - int getLength() { return length; } - - // Get C string. - char *getCString() { return s; } - - // Get th character. - char getChar(int i) { return s[i]; } - - // Change 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); - - // 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); -}; - -#endif diff --git a/pdf2swf/xpdf/Gfx.cc b/pdf2swf/xpdf/Gfx.cc deleted file mode 100644 index 49e9407..0000000 --- a/pdf2swf/xpdf/Gfx.cc +++ /dev/null @@ -1,3596 +0,0 @@ -//======================================================================== -// -// Gfx.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#include -#include "gmem.h" -#include "GlobalParams.h" -#include "CharTypes.h" -#include "Object.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 "Error.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)) - -// Max number of splits along the t axis for an axial shading fill. -#define axialMaxSplits 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 4 - -// 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)) - -//------------------------------------------------------------------------ -// 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}, - &Gfx::opSetStrokeColor}, - {"SCN", -5, {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}, - &Gfx::opSetFillColor}, - {"scn", -5, {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) { - - // 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); - - } else { - fonts = NULL; - xObjDict.initNull(); - colorSpaceDict.initNull(); - patternDict.initNull(); - shadingDict.initNull(); - gStateDict.initNull(); - } - - next = nextA; -} - -GfxResources::~GfxResources() { - if (fonts) { - delete fonts; - } - xObjDict.free(); - colorSpaceDict.free(); - patternDict.free(); - shadingDict.free(); - gStateDict.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(-1, "Unknown font tag '%s'", name); - return NULL; -} - -GBool GfxResources::lookupXObject(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(-1, "XObject '%s' is unknown", name); - return gFalse; -} - -GBool GfxResources::lookupXObjectNF(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(-1, "XObject '%s' is unknown", name); - return gFalse; -} - -void GfxResources::lookupColorSpace(char *name, Object *obj) { - GfxResources *resPtr; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->colorSpaceDict.isDict()) { - if (!resPtr->colorSpaceDict.dictLookup(name, obj)->isNull()) { - return; - } - obj->free(); - } - } - obj->initNull(); -} - -GfxPattern *GfxResources::lookupPattern(char *name) { - GfxResources *resPtr; - GfxPattern *pattern; - Object obj; - - for (resPtr = this; resPtr; resPtr = resPtr->next) { - if (resPtr->patternDict.isDict()) { - if (!resPtr->patternDict.dictLookup(name, &obj)->isNull()) { - pattern = GfxPattern::parse(&obj); - obj.free(); - return pattern; - } - obj.free(); - } - } - error(-1, "Unknown pattern '%s'", name); - return NULL; -} - -GfxShading *GfxResources::lookupShading(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(-1, "Unknown shading '%s'", name); - return NULL; -} - -GBool GfxResources::lookupGState(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(-1, "ExtGState '%s' is unknown", name); - return gFalse; -} - -//------------------------------------------------------------------------ -// Gfx -//------------------------------------------------------------------------ - -Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, - double hDPI, double vDPI, PDFRectangle *box, - PDFRectangle *cropBox, int rotate, - GBool (*abortCheckCbkA)(void *data), - void *abortCheckCbkDataA) { - int i; - - xref = xrefA; - subPage = gFalse; - printCommands = globalParams->getPrintCommands(); - - // 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, cropBox->x1,cropBox->y1,cropBox->x2,cropBox->y2); - out->setDefaultCTM(state->getCTM()); - out->updateAll(state); - for (i = 0; i < 6; ++i) { - baseMatrix[i] = state->getCTM()[i]; - } - formDepth = 0; - 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(XRef *xrefA, OutputDev *outA, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox, - GBool (*abortCheckCbkA)(void *data), - void *abortCheckCbkDataA) { - int i; - - xref = xrefA; - subPage = gTrue; - printCommands = globalParams->getPrintCommands(); - - // 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; - 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() { - while (state->hasSaves()) { - restoreState(); - } - if (!subPage) { - out->endPage(); - } - while (res) { - popResources(); - } - if (state) { - delete state; - } -} - -void Gfx::display(Object *obj, GBool topLevel) { - Object obj2; - int i; - - if (obj->isArray()) { - for (i = 0; i < obj->arrayGetLength(); ++i) { - obj->arrayGet(i, &obj2); - if (!obj2.isStream()) { - error(-1, "Weird page contents"); - obj2.free(); - return; - } - obj2.free(); - } - } else if (!obj->isStream()) { - error(-1, "Weird page contents"); - return; - } - parser = new Parser(xref, new Lexer(xref, obj)); - go(topLevel); - delete parser; - parser = NULL; -} - -void Gfx::go(GBool topLevel) { - Object obj; - Object args[maxArgs]; - int numArgs, i; - int lastAbortCheck; - - // scan a sequence of objects - updateLevel = lastAbortCheck = 0; - numArgs = 0; - parser->getObj(&obj); - while (!obj.isEOF()) { - - // 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); - } - execOp(&obj, args, numArgs); - obj.free(); - for (i = 0; i < numArgs; ++i) - args[i].free(); - numArgs = 0; - - // periodically update display - if (++updateLevel >= 20000) { - out->dump(); - updateLevel = 0; - } - - // check for an abort - if (abortCheckCbk) { - if (updateLevel - lastAbortCheck > 10) { - if ((*abortCheckCbk)(abortCheckCbkData)) { - break; - } - lastAbortCheck = updateLevel; - } - } - - // got an argument - save it - } else if (numArgs < maxArgs) { - args[numArgs++] = obj; - - // too many arguments - something is wrong - } else { - error(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 - parser->getObj(&obj); - } - obj.free(); - - // args at end with no command - if (numArgs > 0) { - error(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(); - } - - // update display - if (topLevel && updateLevel > 0) { - out->dump(); - } -} - -void 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) - error(getPos(), "Unknown operator '%s'", name); - return; - } - - // type check args - argPtr = args; - if (op->numArgs >= 0) { - if (numArgs < op->numArgs) { - error(getPos(), "Too few (%d) args to '%s' operator", numArgs, name); - return; - } - if (numArgs > op->numArgs) { -#if 0 - error(getPos(), "Too many (%d) args to '%s' operator", numArgs, name); -#endif - argPtr += numArgs - op->numArgs; - numArgs = op->numArgs; - } - } else { - if (numArgs > -op->numArgs) { - error(getPos(), "Too many (%d) args to '%s' operator", - numArgs, name); - return; - } - } - for (i = 0; i < numArgs; ++i) { - if (!checkArg(&argPtr[i], op->tchk[i])) { - error(getPos(), "Arg #%d to '%s' operator is wrong type (%s)", - i, name, argPtr[i].getTypeName()); - return; - } - } - - // do it - (this->*op->func)(argPtr, numArgs); -} - -Operator *Gfx::findOp(char *name) { - int a, b, m, cmp; - - a = -1; - b = numOps; - // 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; -} - -int 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) { - state->setLineJoin(args[0].getInt()); - out->updateLineJoin(state); -} - -void Gfx::opSetLineCap(Object args[], int numArgs) { - state->setLineCap(args[0].getInt()); - 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; - GfxBlendMode mode; - GBool haveFillOP; - - if (!res->lookupGState(args[0].getName(), &obj1)) { - return; - } - if (!obj1.isDict()) { - error(getPos(), "ExtGState '%s' is wrong type", args[0].getName()); - obj1.free(); - return; - } - - // transparency support: blend mode, fill/stroke opacity - if (!obj1.dictLookup("BM", &obj2)->isNull()) { - if (state->parseBlendMode(&obj2, &mode)) { - state->setBlendMode(mode); - out->updateBlendMode(state); - } else { - error(getPos(), "Invalid blend mode in ExtGState"); - } - } - obj2.free(); - if (obj1.dictLookup("ca", &obj2)->isNum()) { - state->setFillOpacity(obj2.getNum()); - out->updateFillOpacity(state); - } - obj2.free(); - if (obj1.dictLookup("CA", &obj2)->isNum()) { - state->setStrokeOpacity(obj2.getNum()); - out->updateStrokeOpacity(state); - } - obj2.free(); - - // fill/stroke overprint - if ((haveFillOP = (obj1.dictLookup("op", &obj2)->isBool()))) { - state->setFillOverprint(obj2.getBool()); - out->updateFillOverprint(state); - } - obj2.free(); - if (obj1.dictLookup("OP", &obj2)->isBool()) { - state->setStrokeOverprint(obj2.getBool()); - out->updateStrokeOverprint(state); - if (!haveFillOP) { - state->setFillOverprint(obj2.getBool()); - out->updateFillOverprint(state); - } - } - obj2.free(); - - obj1.free(); -} - -void Gfx::opSetRenderingIntent(Object args[], int numArgs) { -} - -//------------------------------------------------------------------------ -// color operators -//------------------------------------------------------------------------ - -void Gfx::opSetFillGray(Object args[], int numArgs) { - GfxColor color; - - state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceGrayColorSpace()); - 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; - - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); - 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; - - state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceCMYKColorSpace()); - 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; - - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace()); - 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; - - state->setFillPattern(NULL); - state->setFillColorSpace(new GfxDeviceRGBColorSpace()); - 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; - - state->setStrokePattern(NULL); - state->setStrokeColorSpace(new GfxDeviceRGBColorSpace()); - 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; - int i; - - 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); - } else { - error(getPos(), "Bad color space (fill)"); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color.c[i] = 0; - } - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeColorSpace(Object args[], int numArgs) { - Object obj; - GfxColorSpace *colorSpace; - GfxColor color; - int i; - - 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); - } else { - error(getPos(), "Bad color space (stroke)"); - } - for (i = 0; i < gfxColorMaxComps; ++i) { - color.c[i] = 0; - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); -} - -void Gfx::opSetFillColor(Object args[], int numArgs) { - GfxColor color; - int i; - - state->setFillPattern(NULL); - for (i = 0; i < numArgs; ++i) { - color.c[i] = dblToCol(args[i].getNum()); - } - state->setFillColor(&color); - out->updateFillColor(state); -} - -void Gfx::opSetStrokeColor(Object args[], int numArgs) { - GfxColor color; - int i; - - 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->getFillColorSpace()->getMode() == csPattern) { - if (numArgs > 1) { - for (i = 0; i < numArgs && i < 4; ++i) { - if (args[i].isNum()) { - color.c[i] = dblToCol(args[i].getNum()); - } - } - state->setFillColor(&color); - out->updateFillColor(state); - } - if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { - state->setFillPattern(pattern); - } - - } else { - state->setFillPattern(NULL); - for (i = 0; i < numArgs && i < 4; ++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->getStrokeColorSpace()->getMode() == csPattern) { - if (numArgs > 1) { - for (i = 0; i < numArgs && i < 4; ++i) { - if (args[i].isNum()) { - color.c[i] = dblToCol(args[i].getNum()); - } - } - state->setStrokeColor(&color); - out->updateStrokeColor(state); - } - if (args[numArgs-1].isName() && - (pattern = res->lookupPattern(args[numArgs-1].getName()))) { - state->setStrokePattern(pattern); - } - - } else { - state->setStrokePattern(NULL); - for (i = 0; i < numArgs && i < 4; ++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(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(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(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(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(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(getPos(), "No path in stroke"); - return; - } - if (state->isPath()) - out->stroke(state); - doEndPath(); -} - -void Gfx::opCloseStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in closepath/stroke"); - return; - } - if (state->isPath()) { - state->closePath(); - out->stroke(state); - } - doEndPath(); -} - -void Gfx::opFill(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in fill"); - return; - } - if (state->isPath()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - } - doEndPath(); -} - -void Gfx::opEOFill(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in eofill"); - return; - } - if (state->isPath()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - } - doEndPath(); -} - -void Gfx::opFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in fill/stroke"); - return; - } - if (state->isPath()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - out->stroke(state); - } - doEndPath(); -} - -void Gfx::opCloseFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in closepath/fill/stroke"); - return; - } - if (state->isPath()) { - state->closePath(); - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gFalse); - } else { - out->fill(state); - } - out->stroke(state); - } - doEndPath(); -} - -void Gfx::opEOFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in eofill/stroke"); - return; - } - if (state->isPath()) { - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - out->stroke(state); - } - doEndPath(); -} - -void Gfx::opCloseEOFillStroke(Object args[], int numArgs) { - if (!state->isCurPt()) { - //error(getPos(), "No path in closepath/eofill/stroke"); - return; - } - if (state->isPath()) { - state->closePath(); - if (state->getFillColorSpace()->getMode() == csPattern) { - doPatternFill(gTrue); - } else { - out->eoFill(state); - } - 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, eoFill); - break; - case 2: - doShadingPatternFill((GfxShadingPattern *)pattern, eoFill); - break; - default: - error(getPos(), "Unimplemented pattern type (%d) in fill", - pattern->getType()); - break; - } -} - -void Gfx::doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill) { - GfxPatternColorSpace *patCS; - GfxColorSpace *cs; - GfxPath *savedPath; - double xMin, yMin, xMax, yMax, x, y, x1, y1; - double cxMin, cyMin, cxMax, cyMax; - int xi0, yi0, xi1, yi1, xi, yi; - double *ctm, *btm, *ptm; - double m[6], ictm[6], m1[6], imb[6]; - double det; - double xstep, ystep; - int i; - - // get color space - patCS = (GfxPatternColorSpace *)state->getFillColorSpace(); - - // construct a (pattern space) -> (current space) transform matrix - ctm = state->getCTM(); - btm = baseMatrix; - ptm = tPat->getMatrix(); - // iCTM = invert 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; - // 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 = 1 / (m1[0] * m1[3] - m1[1] * m1[2]); - 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 - savedPath = state->getPath()->copy(); - saveState(); - - // set underlying color space (for uncolored tiling patterns); set - // various other parameters (stroke color, line width) to match - // Adobe's behavior - if (tPat->getPaintType() == 2 && (cs = patCS->getUnder())) { - state->setFillColorSpace(cs->copy()); - out->updateFillColorSpace(state); - state->setStrokeColorSpace(cs->copy()); - out->updateStrokeColorSpace(state); - state->setStrokeColor(state->getFillColor()); - } else { - state->setFillColorSpace(new GfxDeviceGrayColorSpace()); - out->updateFillColorSpace(state); - state->setStrokeColorSpace(new GfxDeviceGrayColorSpace()); - out->updateStrokeColorSpace(state); - } - state->setFillPattern(NULL); - out->updateFillColor(state); - state->setStrokePattern(NULL); - out->updateStrokeColor(state); - state->setLineWidth(0); - out->updateLineWidth(state); - - // clip to current path - 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 (?) - xstep = fabs(tPat->getXStep()); - ystep = fabs(tPat->getYStep()); - xi0 = (int)floor((xMin - tPat->getBBox()[0]) / xstep); - xi1 = (int)ceil((xMax - tPat->getBBox()[0]) / xstep); - yi0 = (int)floor((yMin - tPat->getBBox()[1]) / ystep); - yi1 = (int)ceil((yMax - tPat->getBBox()[1]) / ystep); - for (i = 0; i < 4; ++i) { - m1[i] = m[i]; - } - if (out->useTilingPatternFill()) { - m1[4] = m[4]; - m1[5] = m[5]; - out->tilingPatternFill(state, tPat->getContentStream(), - tPat->getPaintType(), tPat->getResDict(), - m1, tPat->getBBox(), - xi0, yi0, xi1, yi1, xstep, ystep); - } else { - for (yi = yi0; yi < yi1; ++yi) { - for (xi = xi0; xi < xi1; ++xi) { - 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]; - doForm1(tPat->getContentStream(), tPat->getResDict(), - m1, tPat->getBBox()); - } - } - } - - // restore graphics state - err: - restoreState(); - state->setPath(savedPath); -} - -void Gfx::doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill) { - GfxShading *shading; - GfxPath *savedPath; - 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 - savedPath = state->getPath()->copy(); - saveState(); - - // clip to bbox - if (shading->getHasBBox()) { - shading->getBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMax, yMin); - state->lineTo(xMax, yMax); - state->lineTo(xMin, yMax); - state->closePath(); - state->clip(); - out->clip(state); - state->setPath(savedPath->copy()); - } - - // clip to current path - state->clip(); - if (eoFill) { - out->eoClip(state); - } else { - out->clip(state); - } - - // set the color space - state->setFillColorSpace(shading->getColorSpace()->copy()); - out->updateFillColorSpace(state); - - // background color fill - if (shading->getHasBackground()) { - state->setFillColor(shading->getBackground()); - out->updateFillColor(state); - out->fill(state); - } - state->clearPath(); - - // construct a (pattern space) -> (current space) transform matrix - ctm = state->getCTM(); - btm = baseMatrix; - ptm = sPat->getMatrix(); - // iCTM = invert 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; - // 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]); - - // 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; - } - - // restore graphics state - restoreState(); - state->setPath(savedPath); -} - -void Gfx::opShFill(Object args[], int numArgs) { - GfxShading *shading; - GfxPath *savedPath; - double xMin, yMin, xMax, yMax; - - if (!(shading = res->lookupShading(args[0].getName()))) { - return; - } - - // save current graphics state - savedPath = state->getPath()->copy(); - saveState(); - - // clip to bbox - if (shading->getHasBBox()) { - shading->getBBox(&xMin, &yMin, &xMax, &yMax); - state->moveTo(xMin, yMin); - state->lineTo(xMax, yMin); - state->lineTo(xMax, yMax); - state->lineTo(xMin, yMax); - state->closePath(); - state->clip(); - out->clip(state); - state->clearPath(); - } - - // set the color space - state->setFillColorSpace(shading->getColorSpace()->copy()); - out->updateFillColorSpace(state); - - // 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; - } - - // restore graphics state - restoreState(); - state->setPath(savedPath); - - delete shading; -} - -void Gfx::doFunctionShFill(GfxFunctionShading *shading) { - double x0, y0, x1, y1; - GfxColor colors[4]; - - if (out->useShadedFills()) { - out->functionShadedFill(state, shading); - } else { - 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 dxZero, dyZero; - double tMin, tMax, t, tx, ty; - double s[4], sMin, sMax, tmp; - double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1; - double t0, t1, tt; - double ta[axialMaxSplits + 1]; - int next[axialMaxSplits + 1]; - GfxColor color0, color1; - int nComps; - int i, j, k, kk; - - if (out->useShadedFills()) { - - out->axialShadedFill(state, shading); - - } else { - - // 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; - dxZero = fabs(dx) < 0.001; - dyZero = fabs(dy) < 0.001; - 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(); - - // 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). In the general case, there are four - // intersection points: - // - // s0 = (xMin - tx) / -dy - // s1 = (xMax - tx) / -dy - // s2 = (yMin - ty) / dx - // s3 = (yMax - ty) / dx - // - // and we want the middle two s values. - // - // In the case where dx = 0, take s0 and s1; in the case where dy = - // 0, take s2 and s3. - // - // 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. - - // set up: require at least one split to avoid problems when the two - // ends of the t axis have the same color - nComps = shading->getColorSpace()->getNComps(); - ta[0] = tMin; - next[0] = axialMaxSplits / 2; - ta[axialMaxSplits / 2] = 0.5 * (tMin + tMax); - next[axialMaxSplits / 2] = axialMaxSplits; - ta[axialMaxSplits] = tMax; - - // compute the color at t = tMin - if (tMin < 0) { - tt = t0; - } else if (tMin > 1) { - tt = t1; - } else { - tt = t0 + (t1 - t0) * tMin; - } - shading->getColor(tt, &color0); - - // 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 (dxZero && dyZero) { - sMin = sMax = 0; - } if (dxZero) { - sMin = (xMin - tx) / -dy; - sMax = (xMax - tx) / -dy; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else if (dyZero) { - sMin = (yMin - ty) / dx; - sMax = (yMax - ty) / dx; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else { - s[0] = (yMin - ty) / dx; - s[1] = (yMax - ty) / dx; - s[2] = (xMin - tx) / -dy; - s[3] = (xMax - tx) / -dy; - for (j = 0; j < 3; ++j) { - kk = j; - for (k = j + 1; k < 4; ++k) { - if (s[k] < s[kk]) { - kk = k; - } - } - tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; - } - sMin = s[1]; - sMax = s[2]; - } - ux0 = tx - sMin * dy; - uy0 = ty + sMin * dx; - vx0 = tx - sMax * dy; - vy0 = ty + sMax * dx; - - i = 0; - while (i < axialMaxSplits) { - - // bisect until color difference is small enough or we hit the - // bisection limit - j = next[i]; - while (j > i + 1) { - if (ta[j] < 0) { - tt = t0; - } else if (ta[j] > 1) { - tt = t1; - } else { - tt = t0 + (t1 - t0) * ta[j]; - } - shading->getColor(tt, &color1); - for (k = 0; k < nComps; ++k) { - if (abs(color1.c[k] - color0.c[k]) > axialColorDelta) { - break; - } - } - if (k == nComps) { - break; - } - k = (i + j) / 2; - ta[k] = 0.5 * (ta[i] + ta[j]); - next[i] = k; - next[k] = j; - j = k; - } - - // use the average of the colors of the two sides of the region - for (k = 0; k < nComps; ++k) { - color0.c[k] = (color0.c[k] + color1.c[k]) / 2; - } - - // compute the coordinates of the point on the t axis; then - // compute the intersection of the perpendicular line with the - // bounding box - tx = x0 + ta[j] * dx; - ty = y0 + ta[j] * dy; - if (dxZero && dyZero) { - sMin = sMax = 0; - } if (dxZero) { - sMin = (xMin - tx) / -dy; - sMax = (xMax - tx) / -dy; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else if (dyZero) { - sMin = (yMin - ty) / dx; - sMax = (yMax - ty) / dx; - if (sMin > sMax) { tmp = sMin; sMin = sMax; sMax = tmp; } - } else { - s[0] = (yMin - ty) / dx; - s[1] = (yMax - ty) / dx; - s[2] = (xMin - tx) / -dy; - s[3] = (xMax - tx) / -dy; - for (j = 0; j < 3; ++j) { - kk = j; - for (k = j + 1; k < 4; ++k) { - if (s[k] < s[kk]) { - kk = k; - } - } - tmp = s[j]; s[j] = s[kk]; s[kk] = tmp; - } - sMin = s[1]; - sMax = s[2]; - } - ux1 = tx - sMin * dy; - uy1 = ty + sMin * dx; - vx1 = tx - sMax * dy; - vy1 = ty + sMax * dx; - - // set the color - state->setFillColor(&color0); - 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; - color0 = color1; - i = next[i]; - } - } -} - -void Gfx::doRadialShFill(GfxRadialShading *shading) { - double sMin, sMax, 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; - int ia, ib, k, n; - double *ctm; - double angle, t, d0, d1; - - if (out->useShadedFills()) { - - out->radialShadedFill(state, shading); - - } else { - - // get the shading info - shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); - t0 = shading->getDomain0(); - t1 = shading->getDomain1(); - nComps = shading->getColorSpace()->getNComps(); - - // compute the (possibly extended) s range - sMin = 0; - sMax = 1; - if (shading->getExtend0()) { - if (r0 < r1) { - // extend the smaller end - sMin = -r0 / (r1 - r0); - } else { - // extend the larger end - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - d0 = (x0 - xMin) * (x0 - xMin); - d1 = (x0 - xMax) * (x0 - xMax); - sMin = d0 > d1 ? d0 : d1; - d0 = (y0 - yMin) * (y0 - yMin); - d1 = (y0 - yMax) * (y0 - yMax); - sMin += d0 > d1 ? d0 : d1; - sMin = (sqrt(sMin) - r0) / (r1 - r0); - if (sMin > 0) { - sMin = 0; - } else if (sMin < -20) { - // sanity check - sMin = -20; - } - } - } - if (shading->getExtend1()) { - if (r1 < r0) { - // extend the smaller end - sMax = -r0 / (r1 - r0); - } else if (r1 > r0) { - // extend the larger end - state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); - d0 = (x1 - xMin) * (x1 - xMin); - d1 = (x1 - xMax) * (x1 - xMax); - sMax = d0 > d1 ? d0 : d1; - d0 = (y1 - yMin) * (y1 - yMin); - d1 = (y1 - yMax) * (y1 - yMax); - sMax += d0 > d1 ? d0 : d1; - sMax = (sqrt(sMax) - r0) / (r1 - r0); - if (sMax < 1) { - sMax = 1; - } else if (sMax > 20) { - // sanity check - sMax = 20; - } - } - } - - // 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; - } - } - - // Traverse the t axis and do the shading. - // - // This generates and fills a series of rings. Each ring is defined - // by two circles: - // sa, ta, xa, ya, ra, colorA - // sb, tb, xb, yb, rb, colorB - // - // The s/t axis is divided into radialMaxSplits parts; these parts - // are combined as much as possible while respecting the - // radialColorDelta parameter. - - // 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); - } - - while (ia < radialMaxSplits) { - - // 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 = 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); - } - 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); - - // construct path for first circle - 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 - 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(); - - // fill the ring - out->eoFill(state); - state->clearPath(); - - // step to the next value of t - ia = ib; - sa = sb; - ta = tb; - xa = xb; - ya = yb; - ra = rb; - colorA = colorB; - } - } -} - -void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) { - double x0, y0, x1, y1, x2, y2; - GfxColor color0, color1, color2; - int i; - - for (i = 0; i < shading->getNTriangles(); ++i) { - shading->getTriangle(i, &x0, &y0, &color0, - &x1, &y1, &color1, - &x2, &y2, &color2); - gouraudFillTriangle(x0, y0, &color0, x1, y1, &color1, x2, y2, &color2, - shading->getColorSpace()->getNComps(), 0); - } -} - -void Gfx::gouraudFillTriangle(double x0, double y0, GfxColor *color0, - double x1, double y1, GfxColor *color1, - double x2, double y2, GfxColor *color2, - int nComps, int depth) { - double x01, y01, x12, y12, x20, y20; - GfxColor color01, color12, color20; - int i; - - for (i = 0; i < nComps; ++i) { - if (abs(color0->c[i] - color1->c[i]) > gouraudColorDelta || - abs(color1->c[i] - color2->c[i]) > gouraudColorDelta) { - break; - } - } - if (i == nComps || depth == gouraudMaxDepth) { - state->setFillColor(color0); - 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); - //~ if the shading has a Function, this should interpolate on the - //~ function parameter, not on the color components - for (i = 0; i < nComps; ++i) { - color01.c[i] = (color0->c[i] + color1->c[i]) / 2; - color12.c[i] = (color1->c[i] + color2->c[i]) / 2; - color20.c[i] = (color2->c[i] + color0->c[i]) / 2; - } - gouraudFillTriangle(x0, y0, color0, x01, y01, &color01, - x20, y20, &color20, nComps, depth + 1); - gouraudFillTriangle(x01, y01, &color01, x1, y1, color1, - x12, y12, &color12, nComps, depth + 1); - gouraudFillTriangle(x01, y01, &color01, x12, y12, &color12, - x20, y20, &color20, nComps, depth + 1); - gouraudFillTriangle(x20, y20, &color20, x12, y12, &color12, - x2, y2, color2, nComps, depth + 1); - } -} - -void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) { - int start, i; - - if (shading->getNPatches() > 128) { - start = 3; - } else if (shading->getNPatches() > 64) { - start = 2; - } else if (shading->getNPatches() > 16) { - start = 1; - } else { - start = 0; - } - for (i = 0; i < shading->getNPatches(); ++i) { - fillPatch(shading->getPatch(i), shading->getColorSpace()->getNComps(), - start); - } -} - -void Gfx::fillPatch(GfxPatch *patch, int nComps, int depth) { - GfxPatch patch00, patch01, patch10, patch11; - double xx[4][8], yy[4][8]; - double xxm, yym; - int i; - - for (i = 0; i < nComps; ++i) { - if (abs(patch->color[0][0].c[i] - patch->color[0][1].c[i]) - > patchColorDelta || - abs(patch->color[0][1].c[i] - patch->color[1][1].c[i]) - > patchColorDelta || - abs(patch->color[1][1].c[i] - patch->color[1][0].c[i]) - > patchColorDelta || - abs(patch->color[1][0].c[i] - patch->color[0][0].c[i]) - > patchColorDelta) { - break; - } - } - if (i == nComps || depth == patchMaxDepth) { - state->setFillColor(&patch->color[0][0]); - 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(); - } 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]; - } - //~ if the shading has a Function, this should interpolate on the - //~ function parameter, not on the color components - for (i = 0; i < nComps; ++i) { - patch00.color[0][0].c[i] = patch->color[0][0].c[i]; - patch00.color[0][1].c[i] = (patch->color[0][0].c[i] + - patch->color[0][1].c[i]) / 2; - patch01.color[0][0].c[i] = patch00.color[0][1].c[i]; - patch01.color[0][1].c[i] = patch->color[0][1].c[i]; - patch01.color[1][1].c[i] = (patch->color[0][1].c[i] + - patch->color[1][1].c[i]) / 2; - patch11.color[0][1].c[i] = patch01.color[1][1].c[i]; - patch11.color[1][1].c[i] = patch->color[1][1].c[i]; - patch11.color[1][0].c[i] = (patch->color[1][1].c[i] + - patch->color[1][0].c[i]) / 2; - patch10.color[1][1].c[i] = patch11.color[1][0].c[i]; - patch10.color[1][0].c[i] = patch->color[1][0].c[i]; - patch10.color[0][0].c[i] = (patch->color[1][0].c[i] + - patch->color[0][0].c[i]) / 2; - patch00.color[1][0].c[i] = patch10.color[0][0].c[i]; - patch00.color[1][1].c[i] = (patch00.color[1][0].c[i] + - patch01.color[1][1].c[i]) / 2; - patch01.color[1][0].c[i] = patch00.color[1][1].c[i]; - patch11.color[0][0].c[i] = patch00.color[1][1].c[i]; - patch10.color[0][1].c[i] = patch00.color[1][1].c[i]; - } - fillPatch(&patch00, nComps, depth + 1); - fillPatch(&patch10, nComps, depth + 1); - fillPatch(&patch01, nComps, depth + 1); - fillPatch(&patch11, nComps, depth + 1); - } -} - -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) { - GfxFont *font; - - if (!(font = res->lookupFont(args[0].getName()))) { - return; - } - if (printCommands) { - printf(" font: tag=%s name='%s' %g\n", - font->getTag()->getCString(), - font->getName() ? font->getName()->getCString() : "???", - args[1].getNum()); - fflush(stdout); - } - state->setFont(font, args[1].getNum()); - 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(getPos(), "No font in show"); - return; - } - if (fontChanged) { - out->updateFont(state); - fontChanged = gFalse; - } - out->beginStringOp(state); - doShowText(args[0].getString()); - out->endStringOp(state); -} - -void Gfx::opMoveShowText(Object args[], int numArgs) { - double tx, ty; - - if (!state->getFont()) { - error(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); - out->beginStringOp(state); - doShowText(args[0].getString()); - out->endStringOp(state); -} - -void Gfx::opMoveSetShowText(Object args[], int numArgs) { - double tx, ty; - - if (!state->getFont()) { - error(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); - out->beginStringOp(state); - doShowText(args[2].getString()); - out->endStringOp(state); -} - -void Gfx::opShowSpaceText(Object args[], int numArgs) { - Array *a; - Object obj; - int wMode; - int i; - - if (!state->getFont()) { - error(getPos(), "No font in show/space"); - return; - } - if (fontChanged) { - out->updateFont(state); - fontChanged = gFalse; - } - out->beginStringOp(state); - wMode = state->getFont()->getWMode(); - a = args[0].getArray(); - for (i = 0; i < a->getLength(); ++i) { - a->get(i, &obj); - if (obj.isNum()) { - // this uses the absolute value of the font size to match - // Acrobat's behavior - if (wMode) { - state->textShift(0, -obj.getNum() * 0.001 * - fabs(state->getFontSize())); - } else { - state->textShift(-obj.getNum() * 0.001 * - fabs(state->getFontSize()), 0); - } - out->updateTextShift(state, obj.getNum()); - } else if (obj.isString()) { - doShowText(obj.getString()); - } else { - error(getPos(), "Element of show/space array must be number or string"); - } - obj.free(); - } - out->endStringOp(state); -} - -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, lineX, lineY; - double originX, originY, tOriginX, tOriginY; - double oldCTM[6], newCTM[6]; - double *mat; - Object charProc; - Dict *resDict; - Parser *oldParser; - char *p; - int len, n, uLen, nChars, nSpaces, i; - - font = state->getFont(); - wMode = font->getWMode(); - - if (out->useDrawChar()) { - out->beginString(state, s); - } - - // 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[2] *= state->getHorizScaling(); - state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - curX = state->getCurX(); - curY = state->getCurY(); - lineX = state->getLineX(); - lineY = state->getLineY(); - oldParser = parser; - p = s->getCString(); - len = s->getLength(); - 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); - saveState(); - state->setCTM(newCTM[0], newCTM[1], newCTM[2], newCTM[3], x, y); - //~ out->updateCTM(???) - if (!out->beginType3Char(state, curX + riseX, curY + riseY, tdx, tdy, - code, u, uLen)) { - ((Gfx8BitFont *)font)->getCharProc(code, &charProc); - if ((resDict = ((Gfx8BitFont *)font)->getResources())) { - pushResources(resDict); - } - if (charProc.isStream()) { - display(&charProc, gFalse); - } else { - error(getPos(), "Missing or bad Type3 CharProc entry"); - } - out->endType3Char(state); - if (resDict) { - popResources(); - } - charProc.free(); - } - restoreState(); - // GfxState::restore() does *not* restore the current position, - // so we deal with it here using (curX, curY) and (lineX, lineY) - curX += tdx; - curY += tdy; - state->moveTo(curX, curY); - state->textSetPos(lineX, lineY); - p += n; - len -= n; - } - parser = oldParser; - - } else if (out->useDrawChar()) { - state->textTransformDelta(0, state->getRise(), &riseX, &riseY); - p = s->getCString(); - len = s->getLength(); - while (len > 0) { - 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); - } - - updateLevel += 10 * s->getLength(); -} - -//------------------------------------------------------------------------ -// XObject operators -//------------------------------------------------------------------------ - -void Gfx::opXObject(Object args[], int numArgs) { - Object obj1, obj2, obj3, refObj; -#if OPI_SUPPORT - Object opiDict; -#endif - - if (!res->lookupXObject(args[0].getName(), &obj1)) { - return; - } - if (!obj1.isStream()) { - error(getPos(), "XObject '%s' is wrong type", args[0].getName()); - obj1.free(); - return; - } -#if OPI_SUPPORT - obj1.streamGetDict()->lookup("OPI", &opiDict); - if (opiDict.isDict()) { - out->opiBegin(state, opiDict.getDict()); - } -#endif - obj1.streamGetDict()->lookup("Subtype", &obj2); - if (obj2.isName("Image")) { - if (out->needNonText()) { - res->lookupXObjectNF(args[0].getName(), &refObj); - doImage(&refObj, obj1.getStream(), gFalse); - refObj.free(); - } - } else if (obj2.isName("Form")) { - doForm(&obj1); - } else if (obj2.isName("PS")) { - obj1.streamGetDict()->lookup("Level1", &obj3); - out->psXObject(obj1.getStream(), - obj3.isStream() ? obj3.getStream() : (Stream *)NULL); - } else if (obj2.isName()) { - error(getPos(), "Unknown XObject subtype '%s'", obj2.getName()); - } else { - error(getPos(), "XObject subtype is missing or wrong type"); - } - obj2.free(); -#if OPI_SUPPORT - if (opiDict.isDict()) { - out->opiEnd(state, opiDict.getDict()); - } - opiDict.free(); -#endif - obj1.free(); -} - -void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) { - Dict *dict, *maskDict; - int width, height; - int bits, maskBits; - StreamColorSpaceMode csMode; - GBool mask; - GBool invert; - GfxColorSpace *colorSpace, *maskColorSpace; - GfxImageColorMap *colorMap, *maskColorMap; - Object maskObj, smaskObj; - GBool haveColorKeyMask, haveExplicitMask, haveSoftMask; - int maskColors[2*gfxColorMaxComps]; - int maskWidth, maskHeight; - GBool maskInvert; - Stream *maskStr; - Object obj1, obj2; - int i; - - // get info from the stream - bits = 0; - csMode = streamCSNone; - str->getImageParams(&bits, &csMode); - - // get stream dict - dict = str->getDict(); - - // 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(); - dict->lookup("Height", &obj1); - if (obj1.isNull()) { - obj1.free(); - dict->lookup("H", &obj1); - } - if (!obj1.isInt()) - goto err2; - height = obj1.getInt(); - obj1.free(); - - // 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(); - } else if (mask) { - bits = 1; - } else { - goto err2; - } - 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); - if (obj2.isInt() && obj2.getInt() == 1) - invert = gTrue; - obj2.free(); - } else if (!obj1.isNull()) { - goto err2; - } - obj1.free(); - - // draw it - out->drawImageMask(state, ref, str, width, height, invert, inlineImg); - - } else { - - // 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 = new GfxDeviceGrayColorSpace(); - } else if (csMode == streamCSDeviceRGB) { - colorSpace = new GfxDeviceRGBColorSpace(); - } else if (csMode == streamCSDeviceCMYK) { - colorSpace = new GfxDeviceCMYKColorSpace(); - } else { - colorSpace = NULL; - } - obj1.free(); - if (!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 = 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) { - goto err1; - } - maskStr = smaskObj.getStream(); - maskDict = smaskObj.streamGetDict(); - maskDict->lookup("Width", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("W", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskWidth = obj1.getInt(); - obj1.free(); - maskDict->lookup("Height", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("H", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskHeight = obj1.getInt(); - obj1.free(); - maskDict->lookup("BitsPerComponent", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("BPC", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskBits = obj1.getInt(); - obj1.free(); - 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(); - } - } - maskColorSpace = GfxColorSpace::parse(&obj1); - obj1.free(); - if (!maskColorSpace || maskColorSpace->getMode() != csDeviceGray) { - goto err1; - } - 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; - goto err1; - } - //~ handle the Matte entry - haveSoftMask = gTrue; - } else if (maskObj.isArray()) { - // color key mask - for (i = 0; - i < maskObj.arrayGetLength() && i < 2*gfxColorMaxComps; - ++i) { - maskObj.arrayGet(i, &obj1); - maskColors[i] = obj1.getInt(); - obj1.free(); - } - haveColorKeyMask = gTrue; - } else if (maskObj.isStream()) { - // explicit mask - if (inlineImg) { - goto err1; - } - maskStr = maskObj.getStream(); - maskDict = maskObj.streamGetDict(); - maskDict->lookup("Width", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("W", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskWidth = obj1.getInt(); - obj1.free(); - maskDict->lookup("Height", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("H", &obj1); - } - if (!obj1.isInt()) { - goto err2; - } - maskHeight = obj1.getInt(); - obj1.free(); - maskDict->lookup("ImageMask", &obj1); - if (obj1.isNull()) { - obj1.free(); - maskDict->lookup("IM", &obj1); - } - if (!obj1.isBool() || !obj1.getBool()) { - 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); - if (obj2.isInt() && obj2.getInt() == 1) { - maskInvert = gTrue; - } - obj2.free(); - } else if (!obj1.isNull()) { - goto err2; - } - obj1.free(); - haveExplicitMask = gTrue; - } - - // draw it - if (haveSoftMask) { - out->drawSoftMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskColorMap); - delete maskColorMap; - } else if (haveExplicitMask) { - out->drawMaskedImage(state, ref, str, width, height, colorMap, - maskStr, maskWidth, maskHeight, maskInvert); - } else { - out->drawImage(state, ref, str, width, height, colorMap, - haveColorKeyMask ? maskColors : (int *)NULL, inlineImg); - } - delete colorMap; - - maskObj.free(); - smaskObj.free(); - } - - if ((i = width * height) > 1000) { - i = 1000; - } - updateLevel += i; - - return; - - err2: - obj1.free(); - err1: - error(getPos(), "Bad image parameters"); -} - -void Gfx::doForm(Object *str) { - Dict *dict; - Object matrixObj, bboxObj; - double m[6], bbox[6]; - Object resObj; - Dict *resDict; - Object obj1; - 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(getPos(), "Unknown form type"); - } - obj1.free(); - - // get bounding box - dict->lookup("BBox", &bboxObj); - if (!bboxObj.isArray()) { - matrixObj.free(); - bboxObj.free(); - error(getPos(), "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; - - // draw it - ++formDepth; - doForm1(str, resDict, m, bbox); - --formDepth; - - resObj.free(); -} - -void Gfx::doAnnot(Object *str, double xMin, double yMin, - double xMax, double yMax) { - Dict *dict, *resDict; - Object matrixObj, bboxObj, resObj; - Object obj1; - double m[6], bbox[6], ictm[6]; - double *ctm; - double formX0, formY0, formX1, formY1; - double annotX0, annotY0, annotX1, annotY1; - double det, x, y, sx, sy; - int i; - - // get stream dict - dict = str->streamGetDict(); - - // get the form bounding box - dict->lookup("BBox", &bboxObj); - if (!bboxObj.isArray()) { - bboxObj.free(); - error(getPos(), "Bad form bounding box"); - return; - } - for (i = 0; i < 4; ++i) { - bboxObj.arrayGet(i, &obj1); - bbox[i] = obj1.getNum(); - 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 form bbox from form space to user space - formX0 = bbox[0] * m[0] + bbox[1] * m[2] + m[4]; - formY0 = bbox[0] * m[1] + bbox[1] * m[3] + m[5]; - formX1 = bbox[2] * m[0] + bbox[3] * m[2] + m[4]; - formY1 = bbox[2] * m[1] + bbox[3] * m[3] + m[5]; - - // transform the annotation bbox from default user space to user - // space: (bbox * baseMatrix) * iCTM - ctm = state->getCTM(); - det = 1 / (ctm[0] * ctm[3] - ctm[1] * ctm[2]); - ictm[0] = ctm[3] * det; - ictm[1] = -ctm[1] * det; - ictm[2] = -ctm[2] * det; - ictm[3] = ctm[0] * det; - ictm[4] = (ctm[2] * ctm[5] - ctm[3] * ctm[4]) * det; - ictm[5] = (ctm[1] * ctm[4] - ctm[0] * ctm[5]) * det; - x = baseMatrix[0] * xMin + baseMatrix[2] * yMin + baseMatrix[4]; - y = baseMatrix[1] * xMin + baseMatrix[3] * yMin + baseMatrix[5]; - annotX0 = ictm[0] * x + ictm[2] * y + ictm[4]; - annotY0 = ictm[1] * x + ictm[3] * y + ictm[5]; - x = baseMatrix[0] * xMax + baseMatrix[2] * yMax + baseMatrix[4]; - y = baseMatrix[1] * xMax + baseMatrix[3] * yMax + baseMatrix[5]; - annotX1 = ictm[0] * x + ictm[2] * y + ictm[4]; - annotY1 = ictm[1] * x + ictm[3] * y + ictm[5]; - - // swap min/max coords - if (formX0 > formX1) { - x = formX0; formX0 = formX1; formX1 = x; - } - if (formY0 > formY1) { - y = formY0; formY0 = formY1; formY1 = y; - } - if (annotX0 > annotX1) { - x = annotX0; annotX0 = annotX1; annotX1 = x; - } - if (annotY0 > annotY1) { - y = annotY0; annotY0 = annotY1; annotY1 = y; - } - - // scale the form to fit the annotation bbox - if (formX1 == formX0) { - // this shouldn't happen - sx = 1; - } else { - sx = (annotX1 - annotX0) / (formX1 - formX0); - } - if (formY1 == formY0) { - // this shouldn't happen - sy = 1; - } else { - sy = (annotY1 - annotY0) / (formY1 - formY0); - } - m[0] *= sx; - m[2] *= sx; - m[4] = (m[4] - formX0) * sx + annotX0; - m[1] *= sy; - m[3] *= sy; - m[5] = (m[5] - formY0) * sy + annotY0; - - // get resources - dict->lookup("Resources", &resObj); - resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL; - - // draw it - doForm1(str, resDict, m, bbox); - - resObj.free(); - bboxObj.free(); -} - -void Gfx::doForm1(Object *str, Dict *resDict, double *matrix, double *bbox) { - Parser *oldParser; - 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 new base matrix - for (i = 0; i < 6; ++i) { - oldBaseMatrix[i] = baseMatrix[i]; - baseMatrix[i] = state->getCTM()[i]; - } - - // 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(); - - // draw the form - display(str, gFalse); - - // 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(); - - return; -} - -//------------------------------------------------------------------------ -// in-line image operators -//------------------------------------------------------------------------ - -void Gfx::opBeginImage(Object args[], int numArgs) { - Stream *str; - int c1, c2; - - // build dict/stream - str = buildImageStream(); - - // display the image - if (str) { - doImage(NULL, str, gTrue); - - // skip 'EI' tag - c1 = str->getBaseStream()->getChar(); - c2 = str->getBaseStream()->getChar(); - while (!(c1 == 'E' && c2 == 'I') && c2 != EOF) { - c1 = c2; - c2 = str->getBaseStream()->getChar(); - } - delete str; - } -} - -Stream *Gfx::buildImageStream() { - Object dict; - Object obj; - char *key; - Stream *str; - - // build dictionary - dict.initDict(xref); - parser->getObj(&obj); - while (!obj.isCmd("ID") && !obj.isEOF()) { - if (!obj.isName()) { - error(getPos(), "Inline image dictionary key must be a name object"); - obj.free(); - } else { - key = copyString(obj.getName()); - obj.free(); - parser->getObj(&obj); - if (obj.isEOF() || obj.isError()) { - gfree(key); - break; - } - dict.dictAdd(key, &obj); - } - parser->getObj(&obj); - } - if (obj.isEOF()) { - error(getPos(), "End of file in inline image"); - obj.free(); - dict.free(); - return NULL; - } - obj.free(); - - // make stream - str = new EmbedStream(parser->getStream(), &dict, gFalse, 0); - str = str->addFilters(&dict); - - return str; -} - -void Gfx::opImageData(Object args[], int numArgs) { - error(getPos(), "Internal: got 'ID' operator"); -} - -void Gfx::opEndImage(Object args[], int numArgs) { - error(getPos(), "Internal: 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) { - 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) { - if (printCommands) { - printf(" marked content: %s ", args[0].getName()); - if (numArgs == 2) - args[2].print(stdout); - printf("\n"); - fflush(stdout); - } -} - -void Gfx::opEndMarkedContent(Object args[], int numArgs) { -} - -void Gfx::opMarkPoint(Object args[], int numArgs) { - if (printCommands) { - printf(" mark point: %s ", args[0].getName()); - if (numArgs == 2) - args[2].print(stdout); - printf("\n"); - fflush(stdout); - } -} - -//------------------------------------------------------------------------ -// misc -//------------------------------------------------------------------------ - -void Gfx::saveState() { - out->saveState(state); - state = state->save(); -} - -void Gfx::restoreState() { - state = state->restore(); - 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/pdf2swf/xpdf/Gfx.h b/pdf2swf/xpdf/Gfx.h deleted file mode 100644 index 168206d..0000000 --- a/pdf2swf/xpdf/Gfx.h +++ /dev/null @@ -1,293 +0,0 @@ -//======================================================================== -// -// Gfx.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFX_H -#define GFX_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -class GString; -class XRef; -class Array; -class Stream; -class Parser; -class Dict; -class OutputDev; -class GfxFontDict; -class GfxFont; -class GfxPattern; -class GfxTilingPattern; -class GfxShadingPattern; -class GfxShading; -class GfxFunctionShading; -class GfxAxialShading; -class GfxRadialShading; -class GfxGouraudTriangleShading; -class GfxPatchMeshShading; -struct GfxPatch; -class GfxState; -struct GfxColor; -class Gfx; -class PDFRectangle; - -//------------------------------------------------------------------------ -// Gfx -//------------------------------------------------------------------------ - -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 8 - -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); - GBool lookupXObject(char *name, Object *obj); - GBool lookupXObjectNF(char *name, Object *obj); - void lookupColorSpace(char *name, Object *obj); - GfxPattern *lookupPattern(char *name); - GfxShading *lookupShading(char *name); - GBool lookupGState(char *name, Object *obj); - - GfxResources *getNext() { return next; } - -private: - - GfxFontDict *fonts; - Object xObjDict; - Object colorSpaceDict; - Object patternDict; - Object shadingDict; - Object gStateDict; - GfxResources *next; -}; - -class Gfx { -public: - - // Constructor for regular output. - Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, - double hDPI, double vDPI, PDFRectangle *box, - PDFRectangle *cropBox, int rotate, - GBool (*abortCheckCbkA)(void *data) = NULL, - void *abortCheckCbkDataA = NULL); - - // Constructor for a sub-page object. - Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, - PDFRectangle *box, PDFRectangle *cropBox, - GBool (*abortCheckCbkA)(void *data) = NULL, - void *abortCheckCbkDataA = NULL); - - ~Gfx(); - - // Interpret a stream or array of streams. - void display(Object *obj, GBool topLevel = gTrue); - - // Display an annotation, given its appearance (a Form XObject) and - // bounding box (in default user space). - void doAnnot(Object *str, 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; } - -private: - - 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 - int updateLevel; - - 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; - - Parser *parser; // parser for page content stream(s) - - GBool // callback to check for an abort - (*abortCheckCbk)(void *data); - void *abortCheckCbkData; - - static Operator opTab[]; // table of operators - - void go(GBool topLevel); - void execOp(Object *cmd, Object args[], int numArgs); - Operator *findOp(char *name); - GBool checkArg(Object *arg, TchkType type); - int 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 opSetRenderingIntent(Object args[], int numArgs); - - // 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 doTilingPatternFill(GfxTilingPattern *tPat, GBool eoFill); - void doShadingPatternFill(GfxShadingPattern *sPat, GBool eoFill); - void opShFill(Object args[], int numArgs); - 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, GfxColor *color0, - double x1, double y1, GfxColor *color1, - double x2, double y2, GfxColor *color2, - int nComps, int depth); - void doPatchMeshShFill(GfxPatchMeshShading *shading); - void fillPatch(GfxPatch *patch, int nComps, 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 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); - - // XObject operators - void opXObject(Object args[], int numArgs); - void doImage(Object *ref, Stream *str, GBool inlineImg); - void doForm(Object *str); - void doForm1(Object *str, Dict *resDict, double *matrix, double *bbox); - - // in-line image operators - void opBeginImage(Object args[], int numArgs); - Stream *buildImageStream(); - 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); - - void pushResources(Dict *resDict); - void popResources(); -}; - -#endif diff --git a/pdf2swf/xpdf/GfxFont.cc b/pdf2swf/xpdf/GfxFont.cc deleted file mode 100644 index a4581c0..0000000 --- a/pdf2swf/xpdf/GfxFont.cc +++ /dev/null @@ -1,1546 +0,0 @@ -//======================================================================== -// -// GfxFont.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#include "gmem.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 "FoFiType1.h" -#include "FoFiType1C.h" -#include "FoFiTrueType.h" -#include "GfxFont.h" - -//------------------------------------------------------------------------ - -struct StdFontMapEntry { - char *altName; - char *properName; -}; - -// Acrobat 4.0 and earlier substituted Base14-compatible fonts without -// providing Widths and a FontDescriptor, so we munge the names into -// the proper Base14 names. This table is from implementation note 44 -// in the PDF 1.4 spec, with some additions based on empirical -// evidence. -static StdFontMapEntry stdFontMap[] = { - { "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,Bold", "Courier-Bold" }, - { "Courier,BoldItalic", "Courier-BoldOblique" }, - { "Courier,Italic", "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,Bold", "Helvetica-Bold" }, - { "Helvetica,BoldItalic", "Helvetica-BoldOblique" }, - { "Helvetica,Italic", "Helvetica-Oblique" }, - { "Helvetica-BoldItalic", "Helvetica-BoldOblique" }, - { "Helvetica-Italic", "Helvetica-Oblique" }, - { "Symbol,Bold", "Symbol" }, - { "Symbol,BoldItalic", "Symbol" }, - { "Symbol,Italic", "Symbol" }, - { "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" } -}; - -//------------------------------------------------------------------------ -// GfxFont -//------------------------------------------------------------------------ - -GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) { - GString *nameA; - GfxFont *font; - Object obj1; - - // get base font name - nameA = NULL; - fontDict->lookup("BaseFont", &obj1); - if (obj1.isName()) { - nameA = new GString(obj1.getName()); - } - obj1.free(); - - // get font type - font = NULL; - fontDict->lookup("Subtype", &obj1); - if (obj1.isName("Type1") || obj1.isName("MMType1")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict); - } else if (obj1.isName("Type1C")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict); - } else if (obj1.isName("Type3")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict); - } else if (obj1.isName("TrueType")) { - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict); - } else if (obj1.isName("Type0")) { - font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict); - } else { - error(-1, "Unknown font type: '%s'", - obj1.isName() ? obj1.getName() : "???"); - font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict); - } - obj1.free(); - - return font; -} - -GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) { - ok = gFalse; - tag = new GString(tagA); - id = idA; - name = nameA; - origName = nameA; - embFontName = NULL; - extFontFile = NULL; -} - -GfxFont::~GfxFont() { - delete tag; - if (origName && origName != name) { - delete origName; - } - if (name) { - delete name; - } - if (embFontName) { - delete embFontName; - } - if (extFontFile) { - delete extFontFile; - } -} - -void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) { - Object obj1, obj2, obj3, obj4; - double t; - int i; - - // assume Times-Roman by default (for substitution purposes) - flags = fontSerif; - - embFontID.num = -1; - embFontID.gen = -1; - missingWidth = 0; - - 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 embedded font file - if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) { - embFontID = obj2.getRef(); - if (type != fontType1) { - error(-1, "Mismatch between font type and embedded font file"); - type = fontType1; - } - } - obj2.free(); - if (embFontID.num == -1 && - obj1.dictLookupNF("FontFile2", &obj2)->isRef()) { - embFontID = obj2.getRef(); - if (type != fontTrueType && type != fontCIDType2) { - error(-1, "Mismatch between font type and embedded font file"); - type = type == fontCIDType0 ? fontCIDType2 : fontTrueType; - } - } - obj2.free(); - if (embFontID.num == -1 && - obj1.dictLookupNF("FontFile3", &obj2)->isRef()) { - if (obj2.fetch(xref, &obj3)->isStream()) { - obj3.streamGetDict()->lookup("Subtype", &obj4); - if (obj4.isName("Type1")) { - embFontID = obj2.getRef(); - if (type != fontType1) { - error(-1, "Mismatch between font type and embedded font file"); - type = fontType1; - } - } else if (obj4.isName("Type1C")) { - embFontID = obj2.getRef(); - if (type != fontType1 && type != fontType1C) { - error(-1, "Mismatch between font type and embedded font file"); - } - type = fontType1C; - } else if (obj4.isName("TrueType")) { - embFontID = obj2.getRef(); - if (type != fontTrueType) { - error(-1, "Mismatch between font type and embedded font file"); - type = fontTrueType; - } - } else if (obj4.isName("CIDFontType0C")) { - embFontID = obj2.getRef(); - if (type != fontCIDType0) { - error(-1, "Mismatch between font type and embedded font file"); - } - type = fontCIDType0C; - } else { - error(-1, "Unknown embedded font type '%s'", - obj4.isName() ? obj4.getName() : "???"); - } - obj4.free(); - } - obj3.free(); - } - obj2.free(); - - // look for MissingWidth - obj1.dictLookup("MissingWidth", &obj2); - if (obj2.isNum()) { - missingWidth = obj2.getNum(); - } - obj2.free(); - - // get Ascent and Descent - obj1.dictLookup("Ascent", &obj2); - if (obj2.isNum()) { - t = 0.001 * obj2.getNum(); - // some broken font descriptors set ascent and descent to 0 - if (t != 0) { - ascent = t; - } - } - obj2.free(); - obj1.dictLookup("Descent", &obj2); - if (obj2.isNum()) { - t = 0.001 * obj2.getNum(); - // some broken font descriptors set ascent and descent to 0 - if (t != 0) { - descent = t; - } - // some broken font descriptors specify a positive descent - if (descent > 0) { - descent = -descent; - } - } - 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; - int c; - - if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) { - obj1.free(); - return NULL; - } - buf = new GString(); - obj1.streamReset(); - while ((c = obj1.streamGetChar()) != EOF) { - buf->append(c); - } - obj1.streamClose(); - obj1.free(); - if (ctu) { - ctu->mergeCMap(buf, nBits); - } else { - ctu = CharCodeToUnicode::parseCMap(buf, nBits); - } - delete buf; - return ctu; -} - -void GfxFont::findExtFontFile() { - static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL }; - static char *ttExts[] = { ".ttf", NULL }; - - if (name) { - if (type == fontType1) { - extFontFile = globalParams->findFontFile(name, type1Exts); - } else if (type == fontTrueType) { - extFontFile = globalParams->findFontFile(name, ttExts); - } - } -} - -char *GfxFont::readExtFontFile(int *len) { - FILE *f; - char *buf; - - if (!(f = fopen(extFontFile->getCString(), "rb"))) { - error(-1, "External font file '%s' vanished", extFontFile->getCString()); - return NULL; - } - fseek(f, 0, SEEK_END); - *len = (int)ftell(f); - fseek(f, 0, SEEK_SET); - buf = (char *)gmalloc(*len); - if ((int)fread(buf, 1, *len, f) != *len) { - error(-1, "Error reading external font file '%s'", - extFontFile->getCString()); - } - fclose(f); - return buf; -} - -char *GfxFont::readEmbFontFile(XRef *xref, int *len) { - char *buf; - Object obj1, obj2; - Stream *str; - int c; - int size, i; - - obj1.initRef(embFontID.num, embFontID.gen); - obj1.fetch(xref, &obj2); - if (!obj2.isStream()) { - error(-1, "Embedded font file is not a stream"); - obj2.free(); - obj1.free(); - embFontID.num = -1; - return NULL; - } - str = obj2.getStream(); - - buf = NULL; - i = size = 0; - str->reset(); - while ((c = str->getChar()) != EOF) { - if (i == size) { - size += 4096; - buf = (char *)grealloc(buf, size); - } - buf[i++] = c; - } - *len = i; - str->close(); - - obj2.free(); - obj1.free(); - - return buf; -} - -//------------------------------------------------------------------------ -// Gfx8BitFont -//------------------------------------------------------------------------ - -Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - GfxFontType typeA, Dict *fontDict): - GfxFont(tagA, idA, nameA) -{ - GString *name2; - BuiltinFont *builtinFont; - char **baseEnc; - GBool baseEncFromFontFile; - 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; - - type = typeA; - ctu = NULL; - - // do font name substitution for various aliases of the Base 14 font - // names - if (name) { - name2 = name->copy(); - i = 0; - while (i < name2->getLength()) { - if (name2->getChar(i) == ' ') { - name2->del(i); - } else { - ++i; - } - } - a = 0; - b = sizeof(stdFontMap) / sizeof(StdFontMapEntry); - // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName - while (b - a > 1) { - m = (a + b) / 2; - if (name2->cmp(stdFontMap[m].altName) >= 0) { - a = m; - } else { - b = m; - } - } - if (!name2->cmp(stdFontMap[a].altName)) { - name = new GString(stdFontMap[a].properName); - } - delete name2; - } - - // is it a built-in font? - builtinFont = NULL; - if (name) { - for (i = 0; i < nBuiltinFonts; ++i) { - if (!name->cmp(builtinFonts[i].name)) { - builtinFont = &builtinFonts[i]; - break; - } - } - } - - // default ascent/descent values - if (builtinFont) { - ascent = 0.001 * builtinFont->ascent; - descent = 0.001 * builtinFont->descent; - 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 { - ascent = 0.95; - descent = -0.35; - fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; - } - - // get info from font descriptor - readFontDescriptor(xref, fontDict); - - // for non-embedded fonts, don't trust the ascent/descent/bbox - // values from the font descriptor - if (builtinFont && embFontID.num < 0) { - ascent = 0.001 * builtinFont->ascent; - descent = 0.001 * builtinFont->descent; - 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]; - } - - // look for an external font file - findExtFontFile(); - - // 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(-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 or external font file for base encoding - // (only for Type 1 fonts - trying to get an encoding out of a - // TrueType font is a losing proposition) - ffT1 = NULL; - ffT1C = NULL; - buf = NULL; - if (type == fontType1 && (extFontFile || embFontID.num >= 0)) { - if (extFontFile) { - ffT1 = FoFiType1::load(extFontFile->getCString()); - } else { - buf = readEmbFontFile(xref, &len); - ffT1 = FoFiType1::make(buf, len); - } - if (ffT1) { - if (ffT1->getName()) { - if (embFontName) { - delete embFontName; - } - embFontName = new GString(ffT1->getName()); - } - if (!baseEnc) { - baseEnc = ffT1->getEncoding(); - baseEncFromFontFile = gTrue; - } - } - } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) { - if (extFontFile) { - ffT1C = FoFiType1C::load(extFontFile->getCString()); - } else { - buf = readEmbFontFile(xref, &len); - ffT1C = FoFiType1C::make(buf, len); - } - if (ffT1C) { - if (ffT1C->getName()) { - if (embFontName) { - delete embFontName; - } - embFontName = new GString(ffT1C->getName()); - } - if (!baseEnc) { - baseEnc = ffT1C->getEncoding(); - baseEncFromFontFile = gTrue; - } - } - } - if (buf) { - 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] = baseEnc[i]; - if ((encFree[i] = 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 && (extFontFile || embFontID.num >= 0) && - baseEncFromFontFile) { - for (i = 0; i < 256; ++i) { - if (!enc[i] && standardEncoding[i]) { - enc[i] = 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(-1, "Wrong type in font encoding resource differences (%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]) && - isxdigit(charName[1]) && isxdigit(charName[2]) && - ((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]) && isxdigit(charName[1]) && - ((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 - // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B' - // are any letters, 'xx' is two hex digits, and 'nn' is 2-4 - // decimal digits - if (missing && globalParams->getMapNumericCharNames()) { - for (code = 0; code < 256; ++code) { - if ((charName = enc[code]) && !toUnicode[code] && - strcmp(charName, ".notdef")) { - n = strlen(charName); - code2 = -1; - if (hex && n == 3 && isalpha(charName[0]) && - isxdigit(charName[1]) && isxdigit(charName[2])) { - sscanf(charName+1, "%x", &code2); - } else if (hex && n == 2 && - isxdigit(charName[0]) && isxdigit(charName[1])) { - sscanf(charName, "%x", &code2); - } else if (!hex && n >= 2 && n <= 4 && - isdigit(charName[0]) && isdigit(charName[1])) { - code2 = atoi(charName); - } else if (n >= 3 && n <= 5 && - isdigit(charName[1]) && isdigit(charName[2])) { - code2 = atoi(charName+1); - } else if (n >= 4 && n <= 6 && - isdigit(charName[2]) && isdigit(charName[3])) { - code2 = atoi(charName+2); - } - if (code2 >= 0 && code2 <= 0xff) { - toUnicode[code] = (Unicode)code2; - } - } - } - } - - // 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 (widths[code] != widths[firstChar]) { - 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; -} - -Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) { - Gushort *map; - int cmapPlatform, cmapEncoding; - int unicodeCmap, macRomanCmap, msSymbolCmap, cmap; - GBool useMacRoman, useUnicode; - char *charName; - Unicode u; - int code, i, n; - - map = (Gushort *)gmallocn(256, sizeof(Gushort)); - for (i = 0; i < 256; ++i) { - map[i] = 0; - } - - // To match up with the Adobe-defined behaviour, we choose a cmap - // like this: - // 1. If the PDF font has an encoding: - // 1a. If the PDF font specified MacRomanEncoding and the - // TrueType font has a Macintosh Roman cmap, use it, and - // reverse map the char names through MacRomanEncoding to - // get char codes. - // 1b. If the TrueType font has a Microsoft Unicode cmap or a - // non-Microsoft Unicode cmap, use it, and use the Unicode - // indexes, not the char codes. - // 1c. If the PDF font is symbolic and the TrueType font has a - // Microsoft Symbol cmap, use it, and use char codes - // directly (possibly with an offset of 0xf000). - // 1d. If the TrueType font has a Macintosh Roman cmap, use it, - // as in case 1a. - // 2. If the PDF font does not have an encoding or the PDF font is - // symbolic: - // 2a. If the TrueType font has a Macintosh Roman cmap, use it, - // and use char codes directly (possibly with an offset of - // 0xf000). - // 2b. If the TrueType font has a Microsoft Symbol cmap, use it, - // and use char codes directly (possible with an offset of - // 0xf000). - // 3. If none of these rules apply, use the first cmap and hope for - // the best (this shouldn't happen). - 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) { - unicodeCmap = i; - } else if (cmapPlatform == 1 && cmapEncoding == 0) { - macRomanCmap = i; - } else if (cmapPlatform == 3 && cmapEncoding == 0) { - msSymbolCmap = i; - } - } - cmap = 0; - useMacRoman = gFalse; - useUnicode = gFalse; - if (hasEncoding) { - if (usesMacRomanEnc && macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } else if (unicodeCmap >= 0) { - cmap = unicodeCmap; - useUnicode = gTrue; - } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) { - cmap = msSymbolCmap; - } else if ((flags & fontSymbolic) && macRomanCmap >= 0) { - cmap = macRomanCmap; - } else if (macRomanCmap >= 0) { - cmap = macRomanCmap; - useMacRoman = gTrue; - } - } else { - if (macRomanCmap >= 0) { - cmap = macRomanCmap; - } else if (msSymbolCmap >= 0) { - cmap = msSymbolCmap; - } - } - - // reverse map the char names through MacRomanEncoding, then map the - // char codes through the cmap - if (useMacRoman) { - for (i = 0; i < 256; ++i) { - if ((charName = enc[i])) { - if ((code = globalParams->getMacRomanCharCode(charName))) { - map[i] = ff->mapCodeToGID(cmap, code); - } - } - } - - // 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); - } - } - - // 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] && (charName = enc[i])) { - map[i] = (Gushort)(int)ff->mapNameToGID(charName); - } - } - - 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; -} - -Dict *Gfx8BitFont::getResources() { - return resources.isDict() ? resources.getDict() : (Dict *)NULL; -} - -//------------------------------------------------------------------------ -// GfxCIDFont -//------------------------------------------------------------------------ - -static int CDECL cmpWidthExcep(const void *w1, const void *w2) { - return ((GfxFontCIDWidthExcep *)w1)->first - - ((GfxFontCIDWidthExcep *)w2)->first; -} - -static int CDECL cmpWidthExcepV(const void *w1, const void *w2) { - return ((GfxFontCIDWidthExcepV *)w1)->first - - ((GfxFontCIDWidthExcepV *)w2)->first; -} - -GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - Dict *fontDict): - GfxFont(tagA, idA, nameA) -{ - Dict *desFontDict; - GString *collection, *cMapName; - 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; - - ascent = 0.95; - descent = -0.35; - fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0; - cMap = NULL; - ctu = NULL; - 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()) { - error(-1, "Missing DescendantFonts entry in Type 0 font"); - obj1.free(); - goto err1; - } - if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) { - error(-1, "Bad descendant font in Type 0 font"); - goto err3; - } - obj1.free(); - desFontDict = desFontDictObj.getDict(); - - // font type - if (!desFontDict->lookup("Subtype", &obj1)) { - error(-1, "Missing Subtype entry in Type 0 descendant font"); - goto err3; - } - if (obj1.isName("CIDFontType0")) { - type = fontCIDType0; - } else if (obj1.isName("CIDFontType2")) { - type = fontCIDType2; - } else { - error(-1, "Unknown Type 0 descendant font type '%s'", - obj1.isName() ? obj1.getName() : "???"); - goto err3; - } - obj1.free(); - - // get info from font descriptor - readFontDescriptor(xref, desFontDict); - - // look for an external font file - findExtFontFile(); - - //----- encoding info ----- - - // char collection - if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) { - error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font"); - goto err3; - } - obj1.dictLookup("Registry", &obj2); - obj1.dictLookup("Ordering", &obj3); - if (!obj2.isString() || !obj3.isString()) { - error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font"); - goto err4; - } - collection = obj2.getString()->copy()->append('-')->append(obj3.getString()); - obj3.free(); - obj2.free(); - obj1.free(); - - // look for a ToUnicode CMap - if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) { - - // the "Adobe-Identity" and "Adobe-UCS" collections don't have - // cidToUnicode files - if (collection->cmp("Adobe-Identity") && - collection->cmp("Adobe-UCS")) { - - // look for a user-supplied .cidToUnicode file - if (!(ctu = globalParams->getCIDToUnicode(collection))) { - error(-1, "Unknown character collection '%s'", - collection->getCString()); - // fall-through, assuming the Identity mapping -- this appears - // to match Adobe's behavior - } - } - } - - // look for a Unicode-to-Unicode mapping - if (name && (utu = globalParams->getUnicodeToUnicode(name))) { - if (ctu) { - 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; - } - } - - // encoding (i.e., CMap) - //~ need to handle a CMap stream here - //~ also need to deal with the UseCMap entry in the stream dict - if (!fontDict->lookup("Encoding", &obj1)->isName()) { - error(-1, "Missing or invalid Encoding entry in Type 0 font"); - delete collection; - goto err3; - } - cMapName = new GString(obj1.getName()); - obj1.free(); - if (!(cMap = globalParams->getCMap(collection, cMapName))) { - error(-1, "Unknown CMap '%s' for character collection '%s'", - cMapName->getCString(), collection->getCString()); - delete collection; - delete cMapName; - goto err2; - } - delete collection; - delete cMapName; - - // CIDToGIDMap (for embedded TrueType fonts) - if (type == fontCIDType2) { - desFontDict->lookup("CIDToGIDMap", &obj1); - if (obj1.isStream()) { - cidToGIDLen = 0; - i = 64; - cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort)); - obj1.streamReset(); - while ((c1 = obj1.streamGetChar()) != EOF && - (c2 = obj1.streamGetChar()) != EOF) { - if (cidToGIDLen == i) { - i *= 2; - cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort)); - } - cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2); - } - } else if (!obj1.isName("Identity") && !obj1.isNull()) { - error(-1, "Invalid CIDToGIDMap entry in CID font"); - } - obj1.free(); - } - - //----- character metrics ----- - - // default char width - if (desFontDict->lookup("DW", &obj1)->isInt()) { - widths.defWidth = obj1.getInt() * 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(-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(-1, "Bad widths array in Type 0 font"); - } - obj4.free(); - } - i += 2; - } else { - error(-1, "Bad widths array in Type 0 font"); - ++i; - } - obj3.free(); - obj2.free(); - } - qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep), - &cmpWidthExcep); - } - 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(-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 < 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.nExceps].first = j; - widths.excepsV[widths.nExceps].last = j; - widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001; - widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001; - widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001; - ++j; - ++widths.nExcepsV; - } else { - error(-1, "Bad widths (W2) array in Type 0 font"); - } - obj6.free(); - obj5.free(); - obj4.free(); - } - i += 2; - } else { - error(-1, "Bad widths (W2) array in Type 0 font"); - ++i; - } - obj3.free(); - obj2.free(); - } - qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV), - &cmpWidthExcepV); - } - obj1.free(); - - desFontDictObj.free(); - ok = gTrue; - return; - - err4: - obj3.free(); - obj2.free(); - err3: - obj1.free(); - err2: - desFontDictObj.free(); - err1:; -} - -GfxCIDFont::~GfxCIDFont() { - if (cMap) { - cMap->decRefCnt(); - } - if (ctu) { - ctu->decRefCnt(); - } - gfree(widths.exceps); - gfree(widths.excepsV); - if (cidToGID) { - gfree(cidToGID); - } -} - -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; - double w, h, vx, vy; - int n, a, b, m; - - if (!cMap) { - *code = 0; - *uLen = 0; - *dx = *dy = 0; - return 1; - } - - *code = (CharCode)(cid = cMap->getCID(s, len, &n)); - if (ctu) { - *uLen = ctu->mapToUnicode(cid, u, uSize); - } else { - *uLen = 0; - } - - // horizontal - if (cMap->getWMode() == 0) { - w = widths.defWidth; - h = vx = vy = 0; - if (widths.nExceps > 0 && cid >= widths.exceps[0].first) { - a = 0; - b = widths.nExceps; - // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first - while (b - a > 1) { - m = (a + b) / 2; - if (widths.exceps[m].first <= cid) { - a = m; - } else { - b = m; - } - } - if (cid <= widths.exceps[a].last) { - w = widths.exceps[a].width; - } - } - - // vertical - } else { - w = 0; - h = widths.defHeight; - vx = widths.defWidth / 2; - vy = widths.defVY; - if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) { - a = 0; - b = widths.nExcepsV; - // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first - while (b - a > 1) { - m = (a + b) / 2; - if (widths.excepsV[m].last <= cid) { - a = m; - } else { - b = m; - } - } - if (cid <= widths.excepsV[a].last) { - h = widths.excepsV[a].height; - vx = widths.excepsV[a].vx; - vy = widths.excepsV[a].vy; - } - } - } - - *dx = w; - *dy = h; - *ox = vx; - *oy = vy; - - return n; -} - -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; -} - -//------------------------------------------------------------------------ -// GfxFontDict -//------------------------------------------------------------------------ - -GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) { - int i; - Object obj1, obj2; - Ref r; - - numFonts = fontDict->getLength(); - fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *)); - for (i = 0; i < numFonts; ++i) { - fontDict->getValNF(i, &obj1); - obj1.fetch(xref, &obj2); - if (obj2.isDict()) { - if (obj1.isRef()) { - r = obj1.getRef(); - } else { - // no indirect reference for this font, so invent a unique one - // (legal generation numbers are five digits, so any 6-digit - // number would be safe) - r.num = i; - if (fontDictRef) { - r.gen = 100000 + fontDictRef->num; - } else { - r.gen = 999999; - } - } - fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i), - r, obj2.getDict()); - if (fonts[i] && !fonts[i]->isOk()) { - delete fonts[i]; - fonts[i] = NULL; - } - } else { - error(-1, "font resource is not a dictionary"); - fonts[i] = NULL; - } - obj1.free(); - obj2.free(); - } -} - -GfxFontDict::~GfxFontDict() { - int i; - - for (i = 0; i < numFonts; ++i) { - if (fonts[i]) { - delete fonts[i]; - } - } - gfree(fonts); -} - -GfxFont *GfxFontDict::lookup(char *tag) { - int i; - - for (i = 0; i < numFonts; ++i) { - if (fonts[i] && fonts[i]->matches(tag)) { - return fonts[i]; - } - } - return NULL; -} diff --git a/pdf2swf/xpdf/GfxFont.h b/pdf2swf/xpdf/GfxFont.h deleted file mode 100644 index df1e00c..0000000 --- a/pdf2swf/xpdf/GfxFont.h +++ /dev/null @@ -1,315 +0,0 @@ -//======================================================================== -// -// GfxFont.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFXFONT_H -#define GFXFONT_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "GString.h" -#include "Object.h" -#include "CharTypes.h" - -class Dict; -class CMap; -class CharCodeToUnicode; -class FoFiTrueType; -struct GfxFontCIDWidths; - -//------------------------------------------------------------------------ -// GfxFontType -//------------------------------------------------------------------------ - -enum GfxFontType { - //----- Gfx8BitFont - fontUnknownType, - fontType1, - fontType1C, - fontType3, - fontTrueType, - //----- GfxCIDFont - fontCIDType0, - fontCIDType0C, - fontCIDType2 -}; - -//------------------------------------------------------------------------ -// GfxFontCIDWidths -//------------------------------------------------------------------------ - -struct GfxFontCIDWidthExcep { - CID first; // this record applies to - CID last; // CIDs .. - double width; // char width -}; - -struct GfxFontCIDWidthExcepV { - CID first; // this record applies to - CID last; // CIDs .. - double height; // char height - double vx, vy; // origin position -}; - -struct GfxFontCIDWidths { - double defWidth; // default char width - double defHeight; // default char height - double defVY; // default origin position - GfxFontCIDWidthExcep *exceps; // exceptions - int nExceps; // number of valid entries in exceps - GfxFontCIDWidthExcepV * // exceptions for vertical font - excepsV; - int nExcepsV; // number of valid entries in excepsV -}; - -//------------------------------------------------------------------------ -// 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, char *tagA, Ref idA, Dict *fontDict); - - GfxFont(char *tagA, Ref idA, GString *nameA); - - 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 base font name. - GString *getName() { return name; } - - // Get the original font name (ignornig any munging that might have - // been done to map to a canonical Base-14 font name). - GString *getOrigName() { return origName; } - - // 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 the name of the external font file. Returns NULL if there - // is no external font file. - GString *getExtFontFile() { return extFontFile; } - - // 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; } - - // 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; } - - // Return the writing mode (0=horizontal, 1=vertical). - virtual int getWMode() { return 0; } - - // Read an external or embedded font file into a buffer. - char *readExtFontFile(int *len); - char *readEmbFontFile(XRef *xref, int *len); - - // Get the next char from a string of bytes, returning the - // char , its Unicode mapping , its displacement vector - // (, ), and its origin offset vector (, ). - // is the number of entries available in , and is set to - // the number actually used. Returns the number of bytes used by - // the char code. - virtual int getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy) = 0; - -protected: - - void readFontDescriptor(XRef *xref, Dict *fontDict); - CharCodeToUnicode *readToUnicodeCMap(Dict *fontDict, int nBits, - CharCodeToUnicode *ctu); - void findExtFontFile(); - - GString *tag; // PDF font tag - Ref id; // reference (used as unique ID) - GString *name; // font name - GString *origName; // original font name - GfxFontType type; // type of font - int flags; // font descriptor flags - GString *embFontName; // name of embedded font - Ref embFontID; // ref to embedded font file stream - GString *extFontFile; // external font file name - double fontMat[6]; // font matrix (Type 3 only) - double fontBBox[4]; // font bounding box (Type 3 only) - double missingWidth; // "default" width - double ascent; // max height above baseline - double descent; // max depth below baseline - GBool ok; -}; - -//------------------------------------------------------------------------ -// Gfx8BitFont -//------------------------------------------------------------------------ - -class Gfx8BitFont: public GfxFont { -public: - - Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - GfxFontType typeA, Dict *fontDict); - - virtual ~Gfx8BitFont(); - - virtual int getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy); - - // Return the encoding. - char **getEncoding() { return enc; } - - // Return the Unicode map. - CharCodeToUnicode *getToUnicode(); - - // Return the character name associated with . - char *getCharName(int code) { return code>=256?0: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.) - Gushort *getCodeToGIDMap(FoFiTrueType *ff); - - // Return the Type 3 CharProc dictionary, or NULL if none. - Dict *getCharProcs(); - - // Return the Type 3 CharProc for the character associated with . - Object *getCharProc(int code, Object *proc); - - // Return the Type 3 Resources dictionary, or NULL if none. - Dict *getResources(); - -private: - - 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; - double widths[256]; // character widths - Object charProcs; // Type 3 CharProcs dictionary - Object resources; // Type 3 Resources dictionary -}; - -//------------------------------------------------------------------------ -// GfxCIDFont -//------------------------------------------------------------------------ - -class GfxCIDFont: public GfxFont { -public: - - GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA, - Dict *fontDict); - - virtual ~GfxCIDFont(); - - virtual GBool isCIDFont() { return gTrue; } - - virtual int getNextChar(char *s, int len, CharCode *code, - Unicode *u, int uSize, int *uLen, - double *dx, double *dy, double *ox, double *oy); - - // Return the writing mode (0=horizontal, 1=vertical). - virtual int getWMode(); - - // Return the Unicode map. - CharCodeToUnicode *getToUnicode(); - - // Get the collection name (-). - GString *getCollection(); - - // Return the CID-to-GID mapping table. These should only be called - // if type is fontCIDType2. - Gushort *getCIDToGID() { return cidToGID; } - int getCIDToGIDLen() { return cidToGIDLen; } - -private: - - CMap *cMap; // char code --> CID - CharCodeToUnicode *ctu; // CID --> Unicode - GfxFontCIDWidths widths; // character widths - Gushort *cidToGID; // CID --> GID mapping (for embedded - // TrueType fonts) - int cidToGIDLen; -}; - -//------------------------------------------------------------------------ -// 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); - - // Iterative access. - int getNumFonts() { return numFonts; } - GfxFont *getFont(int i) { return fonts[i]; } - -private: - - GfxFont **fonts; // list of fonts - int numFonts; // number of fonts -}; - -#endif diff --git a/pdf2swf/xpdf/GfxState.cc b/pdf2swf/xpdf/GfxState.cc deleted file mode 100644 index 6e38d55..0000000 --- a/pdf2swf/xpdf/GfxState.cc +++ /dev/null @@ -1,3961 +0,0 @@ -//======================================================================== -// -// GfxState.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include "gmem.h" -#include "Error.h" -#include "Object.h" -#include "Array.h" -#include "Page.h" -#include "GfxState.h" -#include "cmyk.h" - -//------------------------------------------------------------------------ - -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; -} - -//------------------------------------------------------------------------ - -static struct { - char *name; - GfxBlendMode mode; -} 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(char *)))) - -//------------------------------------------------------------------------ - -// NB: This must match the GfxColorSpaceMode enum defined in -// GfxState.h -static char *gfxColorSpaceModeNames[] = { - "DeviceGray", - "CalGray", - "DeviceRGB", - "CalRGB", - "DeviceCMYK", - "Lab", - "ICCBased", - "Indexed", - "Separation", - "DeviceN", - "Pattern" -}; - -#define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *))) - -//------------------------------------------------------------------------ -// GfxColorSpace -//------------------------------------------------------------------------ - -GfxColorSpace::GfxColorSpace() { -} - -GfxColorSpace::~GfxColorSpace() { -} - -GfxColorSpace *GfxColorSpace::parse(Object *csObj) { - GfxColorSpace *cs; - Object obj1; - - cs = NULL; - if (csObj->isName()) { - if (csObj->isName("DeviceGray") || csObj->isName("G")) { - cs = new GfxDeviceGrayColorSpace(); - } else if (csObj->isName("DeviceRGB") || csObj->isName("RGB")) { - cs = new GfxDeviceRGBColorSpace(); - } else if (csObj->isName("DeviceCMYK") || csObj->isName("CMYK")) { - cs = new GfxDeviceCMYKColorSpace(); - } else if (csObj->isName("Pattern")) { - cs = new GfxPatternColorSpace(NULL); - } else { - error(-1, "Bad color space '%s'", csObj->getName()); - } - } else if (csObj->isArray()) { - csObj->arrayGet(0, &obj1); - if (obj1.isName("DeviceGray") || obj1.isName("G")) { - cs = new GfxDeviceGrayColorSpace(); - } else if (obj1.isName("DeviceRGB") || obj1.isName("RGB")) { - cs = new GfxDeviceRGBColorSpace(); - } else if (obj1.isName("DeviceCMYK") || obj1.isName("CMYK")) { - cs = new GfxDeviceCMYKColorSpace(); - } else if (obj1.isName("CalGray")) { - cs = GfxCalGrayColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("CalRGB")) { - cs = GfxCalRGBColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Lab")) { - cs = GfxLabColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("ICCBased")) { - cs = GfxICCBasedColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Indexed") || obj1.isName("I")) { - cs = GfxIndexedColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Separation")) { - cs = GfxSeparationColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("DeviceN")) { - cs = GfxDeviceNColorSpace::parse(csObj->getArray()); - } else if (obj1.isName("Pattern")) { - cs = GfxPatternColorSpace::parse(csObj->getArray()); - } else { - error(-1, "Bad color space"); - } - obj1.free(); - } else { - error(-1, "Bad color space - expected name or array"); - } - 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; -} - -char *GfxColorSpace::getColorSpaceModeName(int idx) { - return gfxColorSpaceModeNames[idx]; -} - -//------------------------------------------------------------------------ -// GfxDeviceGrayColorSpace -//------------------------------------------------------------------------ - -GfxDeviceGrayColorSpace::GfxDeviceGrayColorSpace() { -} - -GfxDeviceGrayColorSpace::~GfxDeviceGrayColorSpace() { -} - -GfxColorSpace *GfxDeviceGrayColorSpace::copy() { - return new GfxDeviceGrayColorSpace(); -} - -void GfxDeviceGrayColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = clip01(color->c[0]); -} - -void GfxDeviceGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = rgb->g = rgb->b = clip01(color->c[0]); -} - -void GfxDeviceGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = cmyk->m = cmyk->y = 0; - cmyk->k = clip01(gfxColorComp1 - color->c[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) { - GfxCalGrayColorSpace *cs; - Object obj1, obj2, obj3; - - arr->get(1, &obj1); - if (!obj1.isDict()) { - error(-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) { - *gray = clip01(color->c[0]); -} - -void GfxCalGrayColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = rgb->g = rgb->b = clip01(color->c[0]); -} - -void GfxCalGrayColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = cmyk->m = cmyk->y = 0; - cmyk->k = clip01(gfxColorComp1 - color->c[0]); -} - -//------------------------------------------------------------------------ -// GfxDeviceRGBColorSpace -//------------------------------------------------------------------------ - -GfxDeviceRGBColorSpace::GfxDeviceRGBColorSpace() { -} - -GfxDeviceRGBColorSpace::~GfxDeviceRGBColorSpace() { -} - -GfxColorSpace *GfxDeviceRGBColorSpace::copy() { - return new GfxDeviceRGBColorSpace(); -} - -void GfxDeviceRGBColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *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) { - 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) { - 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; -} - -//------------------------------------------------------------------------ -// 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) { - GfxCalRGBColorSpace *cs; - Object obj1, obj2, obj3; - int i; - - arr->get(1, &obj1); - if (!obj1.isDict()) { - error(-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) { - *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) { - 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) { - 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; -} - -//------------------------------------------------------------------------ -// GfxDeviceCMYKColorSpace -//------------------------------------------------------------------------ - -GfxDeviceCMYKColorSpace::GfxDeviceCMYKColorSpace() { -} - -GfxDeviceCMYKColorSpace::~GfxDeviceCMYKColorSpace() { -} - -GfxColorSpace *GfxDeviceCMYKColorSpace::copy() { - return new GfxDeviceCMYKColorSpace(); -} - -void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *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) { - unsigned char r,g,b; - float c = color->c[0]; - float m = color->c[1]; - float y = color->c[2]; - float k = color->c[3]; - convert_cmyk2rgb(c,m,y,k, &r,&g,&b); - rgb->r = r/255.0; - rgb->g = g/255.0; - rgb->b = b/255.0; -}*/ - -void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - 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) { - cmyk->c = clip01(color->c[0]); - cmyk->m = clip01(color->c[1]); - cmyk->y = clip01(color->c[2]); - cmyk->k = clip01(color->c[3]); -} - -//------------------------------------------------------------------------ -// 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) { - GfxLabColorSpace *cs; - Object obj1, obj2, obj3; - - arr->get(1, &obj1); - if (!obj1.isDict()) { - error(-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) { - GfxRGB rgb; - - getRGB(color, &rgb); - *gray = clip01((GfxColorComp)(0.299 * rgb.r + - 0.587 * rgb.g + - 0.114 * rgb.b + 0.5)); -} - -void GfxLabColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - 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) { - GfxRGB rgb; - GfxColorComp c, m, y, k; - - getRGB(color, &rgb); - 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::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) { - GfxICCBasedColorSpace *cs; - Ref iccProfileStreamA; - int nCompsA; - GfxColorSpace *altA; - Dict *dict; - Object obj1, obj2, obj3; - int i; - - 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(-1, "Bad ICCBased color space (stream)"); - obj1.free(); - return NULL; - } - dict = obj1.streamGetDict(); - if (!dict->lookup("N", &obj2)->isInt()) { - error(-1, "Bad ICCBased color space (N)"); - obj2.free(); - obj1.free(); - return NULL; - } - nCompsA = obj2.getInt(); - obj2.free(); - if (nCompsA > gfxColorMaxComps) { - error(-1, "ICCBased color space with too many (%d > %d) components", - nCompsA, gfxColorMaxComps); - nCompsA = gfxColorMaxComps; - } - if (dict->lookup("Alternate", &obj2)->isNull() || - !(altA = GfxColorSpace::parse(&obj2))) { - switch (nCompsA) { - case 1: - altA = new GfxDeviceGrayColorSpace(); - break; - case 3: - altA = new GfxDeviceRGBColorSpace(); - break; - case 4: - altA = new GfxDeviceCMYKColorSpace(); - break; - default: - error(-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) { - alt->getGray(color, gray); -} - -void GfxICCBasedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - alt->getRGB(color, rgb); -} - -void GfxICCBasedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - alt->getCMYK(color, cmyk); -} - -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)); -} - -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) { - GfxIndexedColorSpace *cs; - GfxColorSpace *baseA; - int indexHighA; - Object obj1; - int x; - char *s; - int n, i, j; - - if (arr->getLength() != 4) { - error(-1, "Bad Indexed color space"); - goto err1; - } - arr->get(1, &obj1); - if (!(baseA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad Indexed color space (base color space)"); - goto err2; - } - obj1.free(); - if (!arr->get(2, &obj1)->isInt()) { - error(-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(-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(-1, "Bad Indexed color space (lookup table stream too short)"); - goto err3; - } - cs->lookup[i*n + j] = (Guchar)x; - } - } - obj1.streamClose(); - } else if (obj1.isString()) { - if (obj1.getString()->getLength() < (indexHighA + 1) * n) { - error(-1, "Bad Indexed color space (lookup table string too short)"); - goto err3; - } - 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(-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; - - n = base->getNComps(); - base->getDefaultRanges(low, range, indexHigh); - p = &lookup[(int)(colToDbl(color->c[0]) + 0.5) * 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) { - GfxColor color2; - - base->getGray(mapColorToBase(color, &color2), gray); -} - -void GfxIndexedColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - GfxColor color2; - - base->getRGB(mapColorToBase(color, &color2), rgb); -} - -void GfxIndexedColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - GfxColor color2; - - base->getCMYK(mapColorToBase(color, &color2), cmyk); -} - -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; -} - -GfxSeparationColorSpace::~GfxSeparationColorSpace() { - delete name; - delete alt; - delete func; -} - -GfxColorSpace *GfxSeparationColorSpace::copy() { - return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy()); -} - -//~ handle the 'All' and 'None' colorants -GfxColorSpace *GfxSeparationColorSpace::parse(Array *arr) { - GfxSeparationColorSpace *cs; - GString *nameA; - GfxColorSpace *altA; - Function *funcA; - Object obj1; - - if (arr->getLength() != 4) { - error(-1, "Bad Separation color space"); - goto err1; - } - if (!arr->get(1, &obj1)->isName()) { - error(-1, "Bad Separation color space (name)"); - goto err2; - } - nameA = new GString(obj1.getName()); - obj1.free(); - arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad Separation color space (alternate color space)"); - goto err3; - } - obj1.free(); - arr->get(3, &obj1); - if (!(funcA = Function::parse(&obj1))) { - 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) { - 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); -} - -void GfxSeparationColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - 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); -} - -void GfxSeparationColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - 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); -} - -//------------------------------------------------------------------------ -// GfxDeviceNColorSpace -//------------------------------------------------------------------------ - -GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA, - GfxColorSpace *altA, - Function *funcA) { - nComps = nCompsA; - alt = altA; - func = funcA; -} - -GfxDeviceNColorSpace::~GfxDeviceNColorSpace() { - int i; - - for (i = 0; i < nComps; ++i) { - delete names[i]; - } - delete alt; - delete func; -} - -GfxColorSpace *GfxDeviceNColorSpace::copy() { - GfxDeviceNColorSpace *cs; - int i; - - cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy()); - for (i = 0; i < nComps; ++i) { - cs->names[i] = names[i]->copy(); - } - return cs; -} - -//~ handle the 'None' colorant -GfxColorSpace *GfxDeviceNColorSpace::parse(Array *arr) { - GfxDeviceNColorSpace *cs; - int nCompsA; - GString *namesA[gfxColorMaxComps]; - GfxColorSpace *altA; - Function *funcA; - Object obj1, obj2; - int i; - - if (arr->getLength() != 4 && arr->getLength() != 5) { - error(-1, "Bad DeviceN color space"); - goto err1; - } - if (!arr->get(1, &obj1)->isArray()) { - error(-1, "Bad DeviceN color space (names)"); - goto err2; - } - nCompsA = obj1.arrayGetLength(); - if (nCompsA > gfxColorMaxComps) { - error(-1, "DeviceN color space with too many (%d > %d) components", - nCompsA, gfxColorMaxComps); - nCompsA = gfxColorMaxComps; - } - for (i = 0; i < nCompsA; ++i) { - if (!obj1.arrayGet(i, &obj2)->isName()) { - error(-1, "Bad DeviceN color space (names)"); - obj2.free(); - goto err2; - } - namesA[i] = new GString(obj2.getName()); - obj2.free(); - } - obj1.free(); - arr->get(2, &obj1); - if (!(altA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad DeviceN color space (alternate color space)"); - goto err3; - } - obj1.free(); - arr->get(3, &obj1); - if (!(funcA = Function::parse(&obj1))) { - goto err4; - } - obj1.free(); - cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA); - for (i = 0; i < nCompsA; ++i) { - cs->names[i] = namesA[i]; - } - 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) { - 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); -} - -void GfxDeviceNColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - 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); -} - -void GfxDeviceNColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - 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); -} - -//------------------------------------------------------------------------ -// GfxPatternColorSpace -//------------------------------------------------------------------------ - -GfxPatternColorSpace::GfxPatternColorSpace(GfxColorSpace *underA) { - under = underA; -} - -GfxPatternColorSpace::~GfxPatternColorSpace() { - if (under) { - delete under; - } -} - -GfxColorSpace *GfxPatternColorSpace::copy() { - return new GfxPatternColorSpace(under ? under->copy() : - (GfxColorSpace *)NULL); -} - -GfxColorSpace *GfxPatternColorSpace::parse(Array *arr) { - GfxPatternColorSpace *cs; - GfxColorSpace *underA; - Object obj1; - - if (arr->getLength() != 1 && arr->getLength() != 2) { - error(-1, "Bad Pattern color space"); - return NULL; - } - underA = NULL; - if (arr->getLength() == 2) { - arr->get(1, &obj1); - if (!(underA = GfxColorSpace::parse(&obj1))) { - error(-1, "Bad Pattern color space (underlying color space)"); - obj1.free(); - return NULL; - } - obj1.free(); - } - cs = new GfxPatternColorSpace(underA); - return cs; -} - -void GfxPatternColorSpace::getGray(GfxColor *color, GfxGray *gray) { - *gray = 0; -} - -void GfxPatternColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) { - rgb->r = rgb->g = rgb->b = 0; -} - -void GfxPatternColorSpace::getCMYK(GfxColor *color, GfxCMYK *cmyk) { - cmyk->c = cmyk->m = cmyk->y = 0; - cmyk->k = 1; -} - -//------------------------------------------------------------------------ -// Pattern -//------------------------------------------------------------------------ - -GfxPattern::GfxPattern(int typeA) { - type = typeA; -} - -GfxPattern::~GfxPattern() { -} - -GfxPattern *GfxPattern::parse(Object *obj) { - GfxPattern *pattern; - Object obj1; - - if (obj->isDict()) { - obj->dictLookup("PatternType", &obj1); - } else if (obj->isStream()) { - obj->streamGetDict()->lookup("PatternType", &obj1); - } else { - return NULL; - } - pattern = NULL; - if (obj1.isInt() && obj1.getInt() == 1) { - pattern = GfxTilingPattern::parse(obj); - } else if (obj1.isInt() && obj1.getInt() == 2) { - pattern = GfxShadingPattern::parse(obj); - } - obj1.free(); - return pattern; -} - -//------------------------------------------------------------------------ -// GfxTilingPattern -//------------------------------------------------------------------------ - -GfxTilingPattern *GfxTilingPattern::parse(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(-1, "Invalid or missing PaintType in pattern"); - } - obj1.free(); - if (dict->lookup("TilingType", &obj1)->isInt()) { - tilingTypeA = obj1.getInt(); - } else { - tilingTypeA = 1; - error(-1, "Invalid or missing TilingType in pattern"); - } - 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(-1, "Invalid or missing BBox in pattern"); - } - obj1.free(); - if (dict->lookup("XStep", &obj1)->isNum()) { - xStepA = obj1.getNum(); - } else { - xStepA = 1; - error(-1, "Invalid or missing XStep in pattern"); - } - obj1.free(); - if (dict->lookup("YStep", &obj1)->isNum()) { - yStepA = obj1.getNum(); - } else { - yStepA = 1; - error(-1, "Invalid or missing YStep in pattern"); - } - obj1.free(); - if (!dict->lookup("Resources", &resDictA)->isDict()) { - resDictA.free(); - resDictA.initNull(); - error(-1, "Invalid or missing Resources in pattern"); - } - 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, patObj); - resDictA.free(); - return pat; -} - -GfxTilingPattern::GfxTilingPattern(int paintTypeA, int tilingTypeA, - double *bboxA, double xStepA, double yStepA, - Object *resDictA, double *matrixA, - Object *contentStreamA): - 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]; - } - contentStreamA->copy(&contentStream); -} - -GfxTilingPattern::~GfxTilingPattern() { - resDict.free(); - contentStream.free(); -} - -GfxPattern *GfxTilingPattern::copy() { - return new GfxTilingPattern(paintType, tilingType, bbox, xStep, yStep, - &resDict, matrix, &contentStream); -} - -//------------------------------------------------------------------------ -// 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(-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(-1, "Invalid Type 4 shading object"); - goto err1; - } - break; - case 5: - if (obj->isStream()) { - shading = GfxGouraudTriangleShading::parse(5, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 5 shading object"); - goto err1; - } - break; - case 6: - if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(6, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 6 shading object"); - goto err1; - } - break; - case 7: - if (obj->isStream()) { - shading = GfxPatchMeshShading::parse(7, dict, obj->getStream()); - } else { - error(-1, "Invalid Type 7 shading object"); - goto err1; - } - break; - default: - error(-1, "Unimplemented shading type %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(-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(-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(-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; - 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(); - y0A = obj1.arrayGet(1, &obj2)->getNum(); - obj2.free(); - x1A = 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(-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))) { - goto err2; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - goto err1; - } - } - obj1.free(); - - shading = new GfxFunctionShading(x0A, y0A, x1A, y1A, matrixA, - funcsA, nFuncsA); - if (!shading->init(dict)) { - 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; - y1 = 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; - 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(-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(-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))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - 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; - } - 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; - y1 = 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; - 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(-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(-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))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - 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; - } - 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, - Function **funcsA, int nFuncsA): - GfxShading(typeA) -{ - int i; - - vertices = verticesA; - nVertices = nVerticesA; - triangles = trianglesA; - nTriangles = nTrianglesA; - 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)); - 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 nComps, nVerticesA, nTrianglesA, vertSize, triSize; - Guint x, y, flag; - Guint c[gfxColorMaxComps]; - GfxShadingBitBuf *bitBuf; - Object obj1, obj2; - int i, j, k, state; - - if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { - coordBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { - compBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerComponent in shading dictionary"); - goto err2; - } - obj1.free(); - flagBits = vertsPerRow = 0; // make gcc happy - if (typeA == 4) { - if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { - flagBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerFlag in shading dictionary"); - goto err2; - } - obj1.free(); - } else { - if (dict->lookup("VerticesPerRow", &obj1)->isInt()) { - vertsPerRow = obj1.getInt(); - } else { - error(-1, "Missing or invalid VerticesPerRow 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); - } - nComps = i; - } else { - error(-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(-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))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - 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 < nComps; ++i) { - if (!bitBuf->getBits(compBits, &c[i])) { - break; - } - } - if (i < nComps) { - 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 < nComps; ++i) { - verticesA[nVerticesA].color.c[i] = - dblToCol(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, - funcsA, nFuncsA); - if (!shading->init(dict)) { - 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, GfxColor *color0, - double *x1, double *y1, GfxColor *color1, - double *x2, double *y2, GfxColor *color2) { - double in; - double out[gfxColorMaxComps]; - int v, j; - - v = triangles[i][0]; - *x0 = vertices[v].x; - *y0 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color0->c[j] = dblToCol(out[j]); - } - } else { - *color0 = vertices[v].color; - } - v = triangles[i][1]; - *x1 = vertices[v].x; - *y1 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color1->c[j] = dblToCol(out[j]); - } - } else { - *color1 = vertices[v].color; - } - v = triangles[i][2]; - *x2 = vertices[v].x; - *y2 = vertices[v].y; - if (nFuncs > 0) { - in = colToDbl(vertices[v].color.c[0]); - for (j = 0; j < nFuncs; ++j) { - funcs[j]->transform(&in, &out[j]); - } - for (j = 0; j < gfxColorMaxComps; ++j) { - color2->c[j] = dblToCol(out[j]); - } - } else { - *color2 = vertices[v].color; - } -} - -//------------------------------------------------------------------------ -// GfxPatchMeshShading -//------------------------------------------------------------------------ - -GfxPatchMeshShading::GfxPatchMeshShading(int typeA, - GfxPatch *patchesA, int nPatchesA, - Function **funcsA, int nFuncsA): - GfxShading(typeA) -{ - int i; - - patches = patchesA; - nPatches = nPatchesA; - 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)); - 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 nComps, nPatchesA, patchesSize, nPts, nColors; - Guint flag; - double x[16], y[16]; - Guint xi, yi; - GfxColorComp c[4][gfxColorMaxComps]; - Guint ci[4]; - GfxShadingBitBuf *bitBuf; - Object obj1, obj2; - int i, j; - - if (dict->lookup("BitsPerCoordinate", &obj1)->isInt()) { - coordBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerCoordinate in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("BitsPerComponent", &obj1)->isInt()) { - compBits = obj1.getInt(); - } else { - error(-1, "Missing or invalid BitsPerComponent in shading dictionary"); - goto err2; - } - obj1.free(); - if (dict->lookup("BitsPerFlag", &obj1)->isInt()) { - flagBits = obj1.getInt(); - } else { - error(-1, "Missing or 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); - } - nComps = i; - } else { - error(-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(-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))) { - obj1.free(); - obj2.free(); - goto err1; - } - obj2.free(); - } - } else { - nFuncsA = 1; - if (!(funcsA[0] = Function::parse(&obj1))) { - obj1.free(); - goto err1; - } - } - } else { - nFuncsA = 0; - } - obj1.free(); - - nPatchesA = 0; - patchesA = NULL; - patchesSize = 0; - bitBuf = new GfxShadingBitBuf(str); - while (1) { - if (!bitBuf->getBits(flagBits, &flag)) { - break; - } - 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 < nComps; ++j) { - if (!bitBuf->getBits(compBits, &ci[j])) { - break; - } - c[i][j] = dblToCol(cMin[j] + cMul[j] * (double)ci[j]); - } - if (j < nComps) { - 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 < nComps; ++j) { - p->color[0][0].c[j] = c[0][j]; - p->color[0][1].c[j] = c[1][j]; - p->color[1][1].c[j] = c[2][j]; - p->color[1][0].c[j] = c[3][j]; - } - 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 < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - 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 < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - 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 < nComps; ++j) { - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - 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 < nComps; ++j) { - p->color[0][0].c[j] = c[0][j]; - p->color[0][1].c[j] = c[1][j]; - p->color[1][1].c[j] = c[2][j]; - p->color[1][0].c[j] = c[3][j]; - } - 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 < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[0][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - 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 < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][1].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - 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 < nComps; ++j) { - p->color[0][0].c[j] = patchesA[nPatchesA-1].color[1][0].c[j]; - p->color[0][1].c[j] = patchesA[nPatchesA-1].color[0][0].c[j]; - p->color[1][1].c[j] = c[0][j]; - p->color[1][0].c[j] = c[1][j]; - } - 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, - funcsA, nFuncsA); - if (!shading->init(dict)) { - delete shading; - return NULL; - } - return shading; - - err2: - obj1.free(); - err1: - return NULL; -} - -GfxShading *GfxPatchMeshShading::copy() { - return new GfxPatchMeshShading(this); -} - -//------------------------------------------------------------------------ -// GfxImageColorMap -//------------------------------------------------------------------------ - -GfxImageColorMap::GfxImageColorMap(int bitsA, Object *decode, - GfxColorSpace *colorSpaceA) { - GfxIndexedColorSpace *indexedCS; - GfxSeparationColorSpace *sepCS; - int maxPixel, indexHigh; - int maxPixelForAlloc; - Guchar *lookup2; - Function *sepFunc; - Object obj; - double x[gfxColorMaxComps]; - double y[gfxColorMaxComps]; - int i, j, k; - - ok = gTrue; - - // bits per component and color space - bits = bitsA; - maxPixel = (1 << bits) - 1; - maxPixelForAlloc = (1 << (bits>8?bits:8)); - colorSpace = colorSpaceA; - - // get decode map - if (decode->isNull()) { - nComps = colorSpace->getNComps(); - colorSpace->getDefaultRanges(decodeLow, decodeRange, maxPixel); - } else if (decode->isArray()) { - nComps = decode->arrayGetLength() / 2; - if (nComps != colorSpace->getNComps()) { - goto err1; - } - 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. - // - // Optimization: for Indexed and Separation color spaces (which have - // only one component), we store color values in the lookup table - // rather than component values. - for (k = 0; k < gfxColorMaxComps; ++k) { - lookup[k] = NULL; - } - colorSpace2 = NULL; - nComps2 = 0; - if (colorSpace->getMode() == csIndexed) { - // 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(); - lookup2 = indexedCS->getLookup(); - colorSpace2->getDefaultRanges(x, y, indexHigh); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, - sizeof(GfxColorComp)); - for (i = 0; i <= maxPixel; ++i) { - j = (int)(decodeLow[0] + (i * decodeRange[0]) / maxPixel + 0.5); - if (j < 0) { - j = 0; - } else if (j > indexHigh) { - j = indexHigh; - } - lookup[k][i] = - dblToCol(x[k] + (lookup2[j*nComps2 + k] / 255.0) * y[k]); - } - } - } else if (colorSpace->getMode() == csSeparation) { - sepCS = (GfxSeparationColorSpace *)colorSpace; - colorSpace2 = sepCS->getAlt(); - nComps2 = colorSpace2->getNComps(); - sepFunc = sepCS->getFunc(); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, - sizeof(GfxColorComp)); - for (i = 0; i <= maxPixel; ++i) { - x[0] = decodeLow[0] + (i * decodeRange[0]) / maxPixel; - sepFunc->transform(x, y); - lookup[k][i] = dblToCol(y[k]); - } - } - } else { - for (k = 0; k < nComps; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(maxPixelForAlloc + 1, - sizeof(GfxColorComp)); - for (i = 0; i <= maxPixel; ++i) { - lookup[k][i] = dblToCol(decodeLow[k] + - (i * decodeRange[k]) / maxPixel); - } - } - } - - 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; - } - n = 1 << bits; - if (colorSpace->getMode() == csIndexed) { - colorSpace2 = ((GfxIndexedColorSpace *)colorSpace)->getBase(); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - } else if (colorSpace->getMode() == csSeparation) { - colorSpace2 = ((GfxSeparationColorSpace *)colorSpace)->getAlt(); - for (k = 0; k < nComps2; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - } else { - for (k = 0; k < nComps; ++k) { - lookup[k] = (GfxColorComp *)gmallocn(n, sizeof(GfxColorComp)); - memcpy(lookup[k], colorMap->lookup[k], n * sizeof(GfxColorComp)); - } - } - 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]); - } -} - -void GfxImageColorMap::getGray(Guchar *x, GfxGray *gray) { - GfxColor color; - int i; - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { - color.c[i] = lookup[i][x[0]]; - } - colorSpace2->getGray(&color, gray); - } else { - for (i = 0; i < nComps; ++i) { - color.c[i] = lookup[i][x[i]]; - } - colorSpace->getGray(&color, gray); - } -} - -void GfxImageColorMap::getRGB(Guchar *x, GfxRGB *rgb) { - GfxColor color; - int i; - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { - color.c[i] = lookup[i][x[0]]; - } - colorSpace2->getRGB(&color, rgb); - } else { - for (i = 0; i < nComps; ++i) { - color.c[i] = lookup[i][x[i]]; - } - colorSpace->getRGB(&color, rgb); - } -} - -void GfxImageColorMap::getCMYK(Guchar *x, GfxCMYK *cmyk) { - GfxColor color; - int i; - - if (colorSpace2) { - for (i = 0; i < nComps2; ++i) { - color.c[i] = lookup[i][x[0]]; - } - colorSpace2->getCMYK(&color, cmyk); - } else { - for (i = 0; i < nComps; ++i) { - color.c[i] = lookup[i][x[i]]; - } - colorSpace->getCMYK(&color, cmyk); - } -} - -void GfxImageColorMap::getColor(Guchar *x, GfxColor *color) { - int maxPixel, i; - - maxPixel = (1 << bits) - 1; - for (i = 0; i < nComps; ++i) { - color->c[i] = dblToCol(decodeLow[i] + (x[i] * decodeRange[i]) / maxPixel); - } -} - -//------------------------------------------------------------------------ -// 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 += 16; - 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 += 16; - 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(); -} - -void GfxPath::moveTo(double x, double y) { - justMoved = gTrue; - firstX = x; - firstY = y; -} - -void GfxPath::lineTo(double x, double y) { - if (justMoved) { - if (n >= size) { - size += 16; - subpaths = (GfxSubpath **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } - subpaths[n] = new GfxSubpath(firstX, firstY); - ++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) { - if (n >= size) { - size += 16; - subpaths = (GfxSubpath **) - greallocn(subpaths, size, sizeof(GfxSubpath *)); - } - subpaths[n] = new GfxSubpath(firstX, firstY); - ++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 += 16; - 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 hDPI, double vDPI, PDFRectangle *pageBox, - int rotateA, GBool upsideDown) { - double kx, ky; - - 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 = new GfxDeviceGrayColorSpace(); - strokeColorSpace = new GfxDeviceGrayColorSpace(); - fillColor.c[0] = 0; - strokeColor.c[0] = 0; - fillPattern = NULL; - strokePattern = NULL; - blendMode = gfxBlendNormal; - fillOpacity = 1; - strokeOpacity = 1; - fillOverprint = gFalse; - strokeOverprint = gFalse; - - lineWidth = 1; - lineDash = NULL; - lineDashLength = 0; - lineDashStart = 0; - flatness = 1; - lineJoin = 0; - lineCap = 0; - miterLimit = 10; - - 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; - - saved = NULL; -} - -GfxState::~GfxState() { - if (fillColorSpace) { - delete fillColorSpace; - } - if (strokeColorSpace) { - delete strokeColorSpace; - } - if (fillPattern) { - delete fillPattern; - } - if (strokePattern) { - delete strokePattern; - } - gfree(lineDash); - if (path) { - // this gets set to NULL by restore() - delete path; - } - if (saved) { - delete saved; - } -} - -// Used for copy(); -GfxState::GfxState(GfxState *state) { - 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(); - } - if (lineDashLength > 0) { - lineDash = (double *)gmallocn(lineDashLength, sizeof(double)); - memcpy(lineDash, state->lineDash, lineDashLength * sizeof(double)); - } - 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; - *m12 = (textMat[0] * ctm[1] + textMat[1] * ctm[3]) * fontSize; - *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::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::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::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/pdf2swf/xpdf/GfxState.h b/pdf2swf/xpdf/GfxState.h deleted file mode 100644 index e1d6801..0000000 --- a/pdf2swf/xpdf/GfxState.h +++ /dev/null @@ -1,1206 +0,0 @@ -//======================================================================== -// -// GfxState.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFXSTATE_H -#define GFXSTATE_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" -#include "Function.h" - -class Array; -class GfxFont; -class PDFRectangle; -class GfxShading; - -//------------------------------------------------------------------------ -// GfxBlendMode -//------------------------------------------------------------------------ - -enum GfxBlendMode { - gfxBlendNormal, - gfxBlendMultiply, - gfxBlendScreen, - gfxBlendOverlay, - gfxBlendDarken, - gfxBlendLighten, - gfxBlendColorDodge, - gfxBlendColorBurn, - gfxBlendHardLight, - gfxBlendSoftLight, - gfxBlendDifference, - gfxBlendExclusion, - gfxBlendHue, - gfxBlendSaturation, - gfxBlendColor, - gfxBlendLuminosity -}; - -//------------------------------------------------------------------------ -// 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) + ...) << 16 - // = (x << 8) + (x) + (x >> 7) - // [for rounding] - return (GfxColorComp)((x << 8) + x + (x >> 7)); -} - -static inline Guchar colToByte(GfxColorComp x) { - // 255 * x + 0.5 = 256 * x - x + 0x8000 - return (Guchar)(((x << 8) - 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); - - // Convert to gray, RGB, or CMYK. - virtual void getGray(GfxColor *color, GfxGray *gray) = 0; - virtual void getRGB(GfxColor *color, GfxRGB *rgb) = 0; - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk) = 0; - - // Return the number of color components. - virtual int getNComps() = 0; - - // Return the default ranges for each component, assuming an image - // with a max pixel value of . - virtual void getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel); - - // Return the number of color space modes - static int getNumColorSpaceModes(); - - // Return the name of the th color space mode. - static char *getColorSpaceModeName(int idx); - -private: -}; - -//------------------------------------------------------------------------ -// GfxDeviceGrayColorSpace -//------------------------------------------------------------------------ - -class GfxDeviceGrayColorSpace: public GfxColorSpace { -public: - - GfxDeviceGrayColorSpace(); - virtual ~GfxDeviceGrayColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csDeviceGray; } - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - -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); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - - // 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); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 3; } - -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); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 3; } - - // 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); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 4; } - -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); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 3; } - - 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); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return nComps; } - - virtual void getDefaultRanges(double *decodeLow, double *decodeRange, - int maxImgPixel); - - // ICCBased-specific access. - GfxColorSpace *getAlt() { return alt; } - -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 a Lab color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - - 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); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 1; } - - // Separation-specific access. - GString *getName() { return name; } - GfxColorSpace *getAlt() { return alt; } - Function *getFunc() { return func; } - -private: - - GString *name; // colorant name - GfxColorSpace *alt; // alternate color space - Function *func; // tint transform (into alternate color space) -}; - -//------------------------------------------------------------------------ -// GfxDeviceNColorSpace -//------------------------------------------------------------------------ - -class GfxDeviceNColorSpace: public GfxColorSpace { -public: - - GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func); - virtual ~GfxDeviceNColorSpace(); - virtual GfxColorSpace *copy(); - virtual GfxColorSpaceMode getMode() { return csDeviceN; } - - // Construct a DeviceN color space. Returns NULL if unsuccessful. - static GfxColorSpace *parse(Array *arr); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return nComps; } - - // DeviceN-specific access. - GString *getColorantName(int i) { return names[i]; } - GfxColorSpace *getAlt() { return alt; } - Function *getTintTransformFunc() { return func; } - -private: - - int nComps; // number of components - GString // colorant names - *names[gfxColorMaxComps]; - GfxColorSpace *alt; // alternate color space - Function *func; // tint transform (into alternate color space) -}; - -//------------------------------------------------------------------------ -// 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); - - virtual void getGray(GfxColor *color, GfxGray *gray); - virtual void getRGB(GfxColor *color, GfxRGB *rgb); - virtual void getCMYK(GfxColor *color, GfxCMYK *cmyk); - - virtual int getNComps() { return 0; } - - // 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 *obj); - - virtual GfxPattern *copy() = 0; - - int getType() { return type; } - -private: - - int type; -}; - -//------------------------------------------------------------------------ -// GfxTilingPattern -//------------------------------------------------------------------------ - -class GfxTilingPattern: public GfxPattern { -public: - - static GfxTilingPattern *parse(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 *getContentStream() { return &contentStream; } - -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 contentStream; -}; - -//------------------------------------------------------------------------ -// 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; - GfxColor color; -}; - -class GfxGouraudTriangleShading: public GfxShading { -public: - - GfxGouraudTriangleShading(int typeA, - GfxGouraudVertex *verticesA, int nVerticesA, - int (*trianglesA)[3], int nTrianglesA, - Function **funcsA, int nFuncsA); - GfxGouraudTriangleShading(GfxGouraudTriangleShading *shading); - virtual ~GfxGouraudTriangleShading(); - - static GfxGouraudTriangleShading *parse(int typeA, Dict *dict, Stream *str); - - virtual GfxShading *copy(); - - int getNTriangles() { return nTriangles; } - void getTriangle(int i, double *x0, double *y0, GfxColor *color0, - double *x1, double *y1, GfxColor *color1, - double *x2, double *y2, GfxColor *color2); - -private: - - GfxGouraudVertex *vertices; - int nVertices; - int (*triangles)[3]; - int nTriangles; - Function *funcs[gfxColorMaxComps]; - int nFuncs; -}; - -//------------------------------------------------------------------------ -// GfxPatchMeshShading -//------------------------------------------------------------------------ - -struct GfxPatch { - double x[4][4]; - double y[4][4]; - GfxColor color[2][2]; -}; - -class GfxPatchMeshShading: public GfxShading { -public: - - GfxPatchMeshShading(int typeA, GfxPatch *patchesA, int nPatchesA, - Function **funcsA, int nFuncsA); - GfxPatchMeshShading(GfxPatchMeshShading *shading); - virtual ~GfxPatchMeshShading(); - - static GfxPatchMeshShading *parse(int typeA, Dict *dict, Stream *str); - - virtual GfxShading *copy(); - - int getNPatches() { return nPatches; } - GfxPatch *getPatch(int i) { return &patches[i]; } - -private: - - GfxPatch *patches; - int nPatches; - Function *funcs[gfxColorMaxComps]; - int nFuncs; -}; - -//------------------------------------------------------------------------ -// GfxImageColorMap -//------------------------------------------------------------------------ - -class GfxImageColorMap { -public: - - // Constructor. - GfxImageColorMap(int bitsA, Object *decode, GfxColorSpace *colorSpaceA); - - // 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); - void getRGB(Guchar *x, GfxRGB *rgb); - void getCMYK(Guchar *x, GfxCMYK *cmyk); - void getColor(Guchar *x, GfxColor *color); - -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]; - double // minimum values for each component - decodeLow[gfxColorMaxComps]; - double // max - min value for each component - decodeRange[gfxColorMaxComps]; - GBool ok; -}; - -//------------------------------------------------------------------------ -// GfxSubpath and GfxPath -//------------------------------------------------------------------------ - -class GfxSubpath { -public: - - // Constructor. - GfxSubpath(double x1, double y1); - - // Destructor. - ~GfxSubpath(); - - // Copy. - GfxSubpath *copy() { return new GfxSubpath(this); } - - // Get points. - int getNumPoints() { return n; } - double getX(int i) { return x[i]; } - double getY(int i) { return y[i]; } - GBool getCurve(int i) { return curve[i]; } - - // Get last point. - double getLastX() { return x[n-1]; } - double getLastY() { return y[n-1]; } - - // Add a line segment. - void lineTo(double x1, double y1); - - // Add a Bezier curve. - void curveTo(double x1, double y1, double x2, double y2, - double x3, double y3); - - // Close the subpath. - void close(); - GBool isClosed() { return closed; } - - // Add (, ) to each point in the subpath. - void offset(double dx, double dy); - -private: - - double *x, *y; // points - GBool *curve; // curve[i] => point i is a control point - // for a Bezier curve - int n; // number of points - int size; // size of x/y arrays - GBool closed; // set if path is closed - - GfxSubpath(GfxSubpath *subpath); -}; - -class GfxPath { -public: - - // Constructor. - GfxPath(); - - // Destructor. - ~GfxPath(); - - // Copy. - GfxPath *copy() - { return new GfxPath(justMoved, firstX, firstY, subpaths, n, size); } - - // Is there a current point? - GBool isCurPt() { return n > 0 || justMoved; } - - // Is the path non-empty, i.e., is there at least one segment? - GBool isPath() { return n > 0; } - - // Get subpaths. - int getNumSubpaths() { return n; } - GfxSubpath *getSubpath(int i) { return subpaths[i]; } - - // Get last point on last subpath. - double getLastX() { return subpaths[n-1]->getLastX(); } - double getLastY() { return subpaths[n-1]->getLastY(); } - - // Move the current point. - void moveTo(double x, double y); - - // Add a segment to the last subpath. - void lineTo(double x, double y); - - // Add a Bezier curve to the last subpath - void curveTo(double x1, double y1, double x2, double y2, - double x3, double y3); - - // Close the last subpath. - void close(); - - // Append to . - void append(GfxPath *path); - - // Add (, ) to each point in the path. - void offset(double dx, double dy); - -private: - - GBool justMoved; // set if a new subpath was just started - double firstX, firstY; // first point in new subpath - GfxSubpath **subpaths; // subpaths - int n; // number of subpaths - int size; // size of subpaths array - - GfxPath(GBool justMoved1, double firstX1, double firstY1, - GfxSubpath **subpaths1, int n1, int size1); -}; - -//------------------------------------------------------------------------ -// GfxState -//------------------------------------------------------------------------ - -class GfxState { -public: - - // Construct a default GfxState, for a device with resolution - // x , page box , page rotation , and - // coordinate system specified by . - GfxState(double hDPI, double vDPI, PDFRectangle *pageBox, - int rotateA, GBool upsideDown); - - // Destructor. - ~GfxState(); - - // Copy. - GfxState *copy() { return new GfxState(this); } - - // Accessors. - 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); } - void getStrokeGray(GfxGray *gray) - { strokeColorSpace->getGray(&strokeColor, gray); } - void getFillRGB(GfxRGB *rgb) - { fillColorSpace->getRGB(&fillColor, rgb); } - void getStrokeRGB(GfxRGB *rgb) - { strokeColorSpace->getRGB(&strokeColor, rgb); } - void getFillCMYK(GfxCMYK *cmyk) - { fillColorSpace->getCMYK(&fillColor, cmyk); } - void getStrokeCMYK(GfxCMYK *cmyk) - { strokeColorSpace->getCMYK(&strokeColor, cmyk); } - 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; } - double getLineWidth() { return lineWidth; } - void getLineDash(double **dash, int *length, double *start) - { *dash = lineDash; *length = lineDashLength; *start = lineDashStart; } - int getFlatness() { return flatness; } - int getLineJoin() { return lineJoin; } - int getLineCap() { return lineCap; } - double getMiterLimit() { return miterLimit; } - 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; } - - // 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 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 setLineWidth(double width) { lineWidth = width; } - void setLineDash(double *dash, int length, double start); - void setFlatness(int flatness1) { flatness = flatness1; } - void setLineJoin(int lineJoin1) { lineJoin = lineJoin1; } - void setLineCap(int lineCap1) { lineCap = lineCap1; } - void setMiterLimit(double limit) { miterLimit = limit; } - void 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(); - - // 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); - - // Push/pop GfxState on/off stack. - GfxState *save(); - GfxState *restore(); - GBool hasSaves() { return saved != NULL; } - - // Misc - GBool parseBlendMode(Object *obj, GfxBlendMode *mode); - -private: - - 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 - - double lineWidth; // line width - double *lineDash; // line dash - int lineDashLength; - double lineDashStart; - int flatness; // curve flatness - int lineJoin; // line join style - int lineCap; // line cap style - double miterLimit; // line miter limit - - 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; - - GfxState *saved; // next GfxState on stack - - GfxState(GfxState *state); -}; - -#endif diff --git a/pdf2swf/xpdf/GlobalParams.cc b/pdf2swf/xpdf/GlobalParams.cc deleted file mode 100644 index 8981ba9..0000000 --- a/pdf2swf/xpdf/GlobalParams.cc +++ /dev/null @@ -1,2057 +0,0 @@ -//======================================================================== -// -// GlobalParams.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#ifdef ENABLE_PLUGINS -# ifndef WIN32 -# include -# endif -#endif -#ifdef WIN32 -# include -#endif -#if HAVE_PAPER_H -#include -#endif -#include "gmem.h" -#include "GString.h" -#include "GList.h" -#include "GHash.h" -#include "gfile.h" -#include "Error.h" -#include "NameToCharCode.h" -#include "CharCodeToUnicode.h" -#include "UnicodeMap.h" -#include "CMap.h" -#include "BuiltinFontTables.h" -#include "FontEncodingTables.h" -#ifdef ENABLE_PLUGINS -# include "XpdfPluginAPI.h" -#endif -#include "GlobalParams.h" - -#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" - -#ifdef ENABLE_PLUGINS -# ifdef WIN32 -extern XpdfPluginVecTable xpdfPluginVecTable; -# endif -#endif - -//------------------------------------------------------------------------ - -#define cidToUnicodeCacheSize 4 -#define unicodeToUnicodeCacheSize 4 - -//------------------------------------------------------------------------ - -static struct { - char *name; - char *t1FileName; - char *ttFileName; -} displayFontTab[] = { - {"Courier", "n022003l.pfb", "cour.ttf"}, - {"Courier-Bold", "n022004l.pfb", "courbd.ttf"}, - {"Courier-BoldOblique", "n022024l.pfb", "courbi.ttf"}, - {"Courier-Oblique", "n022023l.pfb", "couri.ttf"}, - {"Helvetica", "n019003l.pfb", "arial.ttf"}, - {"Helvetica-Bold", "n019004l.pfb", "arialbd.ttf"}, - {"Helvetica-BoldOblique", "n019024l.pfb", "arialbi.ttf"}, - {"Helvetica-Oblique", "n019023l.pfb", "ariali.ttf"}, - {"Symbol", "s050000l.pfb", NULL}, - {"Times-Bold", "n021004l.pfb", "timesbd.ttf"}, - {"Times-BoldItalic", "n021024l.pfb", "timesbi.ttf"}, - {"Times-Italic", "n021023l.pfb", "timesi.ttf"}, - {"Times-Roman", "n021003l.pfb", "times.ttf"}, - {"ZapfDingbats", "d050000l.pfb", NULL}, - {NULL} -}; - -#ifdef WIN32 -static char *displayFontDirs[] = { - "c:/windows/fonts", - "c:/winnt/fonts", - NULL -}; -#else -static 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", - NULL -}; -#endif - -//------------------------------------------------------------------------ - -GlobalParams *globalParams = NULL; - -//------------------------------------------------------------------------ -// DisplayFontParam -//------------------------------------------------------------------------ - -DisplayFontParam::DisplayFontParam(GString *nameA, - DisplayFontParamKind kindA) { - name = nameA; - kind = kindA; - switch (kind) { - case displayFontT1: - t1.fileName = NULL; - break; - case displayFontTT: - tt.fileName = NULL; - break; - } -} - -DisplayFontParam::~DisplayFontParam() { - delete name; - switch (kind) { - case displayFontT1: - if (t1.fileName) { - delete t1.fileName; - } - break; - case displayFontTT: - if (tt.fileName) { - delete tt.fileName; - } - break; - } -} - -//------------------------------------------------------------------------ -// PSFontParam -//------------------------------------------------------------------------ - -PSFontParam::PSFontParam(GString *pdfFontNameA, int wModeA, - GString *psFontNameA, GString *encodingA) { - pdfFontName = pdfFontNameA; - wMode = wModeA; - psFontName = psFontNameA; - encoding = encodingA; -} - -PSFontParam::~PSFontParam() { - delete pdfFontName; - delete psFontName; - if (encoding) { - delete encoding; - } -} - -#ifdef ENABLE_PLUGINS -//------------------------------------------------------------------------ -// Plugin -//------------------------------------------------------------------------ - -class Plugin { -public: - - static Plugin *load(char *type, char *name); - ~Plugin(); - -private: - -#ifdef WIN32 - Plugin(HMODULE libA); - HMODULE lib; -#else - Plugin(void *dlA); - void *dl; -#endif -}; - -Plugin *Plugin::load(char *type, char *name) { - GString *path; - Plugin *plugin; - XpdfPluginVecTable *vt; - XpdfBool (*xpdfInitPlugin)(void); -#ifdef WIN32 - HMODULE libA; -#else - void *dlA; -#endif - - path = globalParams->getBaseDir(); - appendToPath(path, "plugins"); - appendToPath(path, type); - appendToPath(path, name); - -#ifdef WIN32 - path->append(".dll"); - if (!(libA = LoadLibrary(path->getCString()))) { - error(-1, "Failed to load plugin '%s'", - path->getCString()); - goto err1; - } - if (!(vt = (XpdfPluginVecTable *) - GetProcAddress(libA, "xpdfPluginVecTable"))) { - error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", - path->getCString()); - goto err2; - } -#else - //~ need to deal with other extensions here - path->append(".so"); - if (!(dlA = dlopen(path->getCString(), RTLD_NOW))) { - error(-1, "Failed to load plugin '%s': %s", - path->getCString(), dlerror()); - goto err1; - } - if (!(vt = (XpdfPluginVecTable *)dlsym(dlA, "xpdfPluginVecTable"))) { - error(-1, "Failed to find xpdfPluginVecTable in plugin '%s'", - path->getCString()); - goto err2; - } -#endif - - if (vt->version != xpdfPluginVecTable.version) { - error(-1, "Plugin '%s' is wrong version", path->getCString()); - goto err2; - } - memcpy(vt, &xpdfPluginVecTable, sizeof(xpdfPluginVecTable)); - -#ifdef WIN32 - if (!(xpdfInitPlugin = (XpdfBool (*)(void)) - GetProcAddress(libA, "xpdfInitPlugin"))) { - error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", - path->getCString()); - goto err2; - } -#else - if (!(xpdfInitPlugin = (XpdfBool (*)(void))dlsym(dlA, "xpdfInitPlugin"))) { - error(-1, "Failed to find xpdfInitPlugin in plugin '%s'", - path->getCString()); - goto err2; - } -#endif - - if (!(*xpdfInitPlugin)()) { - error(-1, "Initialization of plugin '%s' failed", - path->getCString()); - goto err2; - } - -#ifdef WIN32 - plugin = new Plugin(libA); -#else - plugin = new Plugin(dlA); -#endif - - delete path; - return plugin; - - err2: -#ifdef WIN32 - FreeLibrary(libA); -#else - dlclose(dlA); -#endif - err1: - delete path; - return NULL; -} - -#ifdef WIN32 -Plugin::Plugin(HMODULE libA) { - lib = libA; -} -#else -Plugin::Plugin(void *dlA) { - dl = dlA; -} -#endif - -Plugin::~Plugin() { - void (*xpdfFreePlugin)(void); - -#ifdef WIN32 - if ((xpdfFreePlugin = (void (*)(void)) - GetProcAddress(lib, "xpdfFreePlugin"))) { - (*xpdfFreePlugin)(); - } - FreeLibrary(lib); -#else - if ((xpdfFreePlugin = (void (*)(void))dlsym(dl, "xpdfFreePlugin"))) { - (*xpdfFreePlugin)(); - } - dlclose(dl); -#endif -} - -#endif // ENABLE_PLUGINS - -//------------------------------------------------------------------------ -// parsing -//------------------------------------------------------------------------ - -GlobalParams::GlobalParams(char *cfgFileName) { - UnicodeMap *map; - GString *fileName; - FILE *f; - int i; - -#if MULTITHREADED - gInitMutex(&mutex); - gInitMutex(&unicodeMapCacheMutex); - gInitMutex(&cMapCacheMutex); -#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 - 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(); - displayFonts = new GHash(); - displayCIDFonts = new GHash(); - displayNamedCIDFonts = new GHash(); -#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(-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; - psExpandSmaller = gFalse; - psShrinkLarger = gTrue; - psCenter = gTrue; - psDuplex = gFalse; - psLevel = psLevel2; - psFile = NULL; - psFonts = new GHash(); - psNamedFonts16 = new GList(); - psFonts16 = new GList(); - psEmbedType1 = gTrue; - psEmbedTrueType = gTrue; - psEmbedCIDPostScript = gTrue; - psEmbedCIDTrueType = gTrue; - psOPI = gFalse; - psASCIIHex = gFalse; - textEncoding = new GString("Latin1"); -#if defined(WIN32) - textEOL = eolDOS; -#elif defined(MACOS) - textEOL = eolMac; -#else - textEOL = eolUnix; -#endif - textPageBreaks = gTrue; - textKeepTinyChars = gFalse; - fontDirs = new GList(); - initialZoom = new GString("125"); - continuousView = gFalse; - enableT1lib = gTrue; - enableFreeType = gTrue; - antialias = gTrue; - urlCommand = NULL; - movieCommand = NULL; - mapNumericCharNames = gTrue; - printCommands = gFalse; - errQuiet = gFalse; - - cidToUnicodeCache = new CharCodeToUnicodeCache(cidToUnicodeCacheSize); - unicodeToUnicodeCache = - new CharCodeToUnicodeCache(unicodeToUnicodeCacheSize); - unicodeMapCache = new UnicodeMapCache(); - cMapCache = new CMapCache(); - -#ifdef ENABLE_PLUGINS - plugins = new GList(); - securityHandlers = new GList(); -#endif - - // 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) { -#if defined(WIN32) && !defined(__CYGWIN32__) - char buf[512]; - i = GetModuleFileName(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::parseFile(GString *fileName, FILE *f) { - int line; - GList *tokens; - GString *cmd, *incFile; - char *p1, *p2; - char buf[512]; - FILE *f2; - - /* extract path */ - if(fileName) { - char* cfgFileName = fileName->getCString(); - char* pos1 = strrchr(cfgFileName, '/'); - char* pos2 = strrchr(cfgFileName, '\\'); - char* p = pos1>pos2?pos1:pos2; - int pos = p ? p-cfgFileName : -1; - GString*path = new GString(new GString(cfgFileName), 0, (pos < 0 ? strlen(cfgFileName): pos)); - if(pos1>=0) - path->append('/'); - else if(pos2>=0) - path->append('\\'); - else -#ifdef WIN32 - path->append('\\'); -#else - path->append('/'); -#endif - this->path = path; - } else { - this->path = new GString(); - } - - line = 1; - while (getLine(buf, sizeof(buf) - 1, f)) { - - // break the line into tokens - tokens = new GList(); - p1 = buf; - while (*p1) { - for (; *p1 && isspace(*p1); ++p1) ; - if (!*p1) { - break; - } - if (*p1 == '"' || *p1 == '\'') { - for (p2 = p1 + 1; *p2 && *p2 != *p1; ++p2) ; - ++p1; - } else { - for (p2 = p1 + 1; *p2 && !isspace(*p2); ++p2) ; - } - tokens->append(new GString(p1, p2 - p1)); - p1 = *p2 ? p2 + 1 : p2; - } - - if (tokens->getLength() > 0 && - ((GString *)tokens->get(0))->getChar(0) != '#') { - cmd = (GString *)tokens->get(0); - if (!cmd->cmp("include")) { - if (tokens->getLength() == 2) { - incFile = (GString *)tokens->get(1); - if ((f2 = fopen(incFile->getCString(), "r"))) { - parseFile(incFile, f2); - fclose(f2); - } else { - error(-1, "Couldn't find included config file: '%s' (%s:%d)", - incFile->getCString(), fileName->getCString(), line); - } - } else { - error(-1, "Bad 'include' config file command (%s:%d)", - fileName->getCString(), line); - } - } else if (!cmd->cmp("nameToUnicode")) { - parseNameToUnicode(tokens, fileName, line); - } else if (!cmd->cmp("cidToUnicode")) { - parseCIDToUnicode(tokens, fileName, line); - } else if (!cmd->cmp("unicodeToUnicode")) { - parseUnicodeToUnicode(tokens, fileName, line); - } else if (!cmd->cmp("unicodeMap")) { - parseUnicodeMap(tokens, fileName, line); - } else if (!cmd->cmp("cMapDir")) { - parseCMapDir(tokens, fileName, line); - } else if (!cmd->cmp("toUnicodeDir")) { - parseToUnicodeDir(tokens, fileName, line); - } else if (!cmd->cmp("displayFontT1")) { - parseDisplayFont(tokens, displayFonts, displayFontT1, fileName, line); - } else if (!cmd->cmp("displayFontTT")) { - parseDisplayFont(tokens, displayFonts, displayFontTT, fileName, line); - } else if (!cmd->cmp("displayNamedCIDFontT1")) { - parseDisplayFont(tokens, displayNamedCIDFonts, - displayFontT1, fileName, line); - } else if (!cmd->cmp("displayCIDFontT1")) { - parseDisplayFont(tokens, displayCIDFonts, - displayFontT1, fileName, line); - } else if (!cmd->cmp("displayNamedCIDFontTT")) { - parseDisplayFont(tokens, displayNamedCIDFonts, - displayFontTT, fileName, line); - } else if (!cmd->cmp("displayCIDFontTT")) { - parseDisplayFont(tokens, displayCIDFonts, - displayFontTT, fileName, line); - } else if (!cmd->cmp("psFile")) { - parsePSFile(tokens, fileName, line); - } else if (!cmd->cmp("psFont")) { - parsePSFont(tokens, fileName, line); - } else if (!cmd->cmp("psNamedFont16")) { - parsePSFont16("psNamedFont16", psNamedFonts16, - tokens, fileName, line); - } else if (!cmd->cmp("psFont16")) { - parsePSFont16("psFont16", psFonts16, tokens, fileName, line); - } else if (!cmd->cmp("psPaperSize")) { - parsePSPaperSize(tokens, fileName, line); - } else if (!cmd->cmp("psImageableArea")) { - parsePSImageableArea(tokens, fileName, line); - } else if (!cmd->cmp("psCrop")) { - parseYesNo("psCrop", &psCrop, tokens, fileName, line); - } else if (!cmd->cmp("psExpandSmaller")) { - parseYesNo("psExpandSmaller", &psExpandSmaller, - tokens, fileName, line); - } else if (!cmd->cmp("psShrinkLarger")) { - parseYesNo("psShrinkLarger", &psShrinkLarger, tokens, fileName, line); - } else if (!cmd->cmp("psCenter")) { - parseYesNo("psCenter", &psCenter, tokens, fileName, line); - } else if (!cmd->cmp("psDuplex")) { - parseYesNo("psDuplex", &psDuplex, tokens, fileName, line); - } else if (!cmd->cmp("psLevel")) { - parsePSLevel(tokens, fileName, line); - } else if (!cmd->cmp("psEmbedType1Fonts")) { - parseYesNo("psEmbedType1", &psEmbedType1, tokens, fileName, line); - } else if (!cmd->cmp("psEmbedTrueTypeFonts")) { - parseYesNo("psEmbedTrueType", &psEmbedTrueType, - tokens, fileName, line); - } else if (!cmd->cmp("psEmbedCIDPostScriptFonts")) { - parseYesNo("psEmbedCIDPostScript", &psEmbedCIDPostScript, - tokens, fileName, line); - } else if (!cmd->cmp("psEmbedCIDTrueTypeFonts")) { - parseYesNo("psEmbedCIDTrueType", &psEmbedCIDTrueType, - tokens, fileName, line); - } else if (!cmd->cmp("psOPI")) { - parseYesNo("psOPI", &psOPI, tokens, fileName, line); - } else if (!cmd->cmp("psASCIIHex")) { - parseYesNo("psASCIIHex", &psASCIIHex, tokens, fileName, line); - } else if (!cmd->cmp("textEncoding")) { - parseTextEncoding(tokens, fileName, line); - } else if (!cmd->cmp("textEOL")) { - parseTextEOL(tokens, fileName, line); - } else if (!cmd->cmp("textPageBreaks")) { - parseYesNo("textPageBreaks", &textPageBreaks, - tokens, fileName, line); - } else if (!cmd->cmp("textKeepTinyChars")) { - parseYesNo("textKeepTinyChars", &textKeepTinyChars, - tokens, fileName, line); - } else if (!cmd->cmp("fontDir")) { - parseFontDir(tokens, fileName, line); - } else if (!cmd->cmp("initialZoom")) { - parseInitialZoom(tokens, fileName, line); - } else if (!cmd->cmp("continuousView")) { - parseYesNo("continuousView", &continuousView, tokens, fileName, line); - } else if (!cmd->cmp("enableT1lib")) { - parseYesNo("enableT1lib", &enableT1lib, tokens, fileName, line); - } else if (!cmd->cmp("enableFreeType")) { - parseYesNo("enableFreeType", &enableFreeType, tokens, fileName, line); - } else if (!cmd->cmp("antialias")) { - parseYesNo("antialias", &antialias, tokens, fileName, line); - } else if (!cmd->cmp("urlCommand")) { - parseCommand("urlCommand", &urlCommand, tokens, fileName, line); - } else if (!cmd->cmp("movieCommand")) { - parseCommand("movieCommand", &movieCommand, tokens, fileName, line); - } else if (!cmd->cmp("mapNumericCharNames")) { - parseYesNo("mapNumericCharNames", &mapNumericCharNames, - tokens, fileName, line); - } else if (!cmd->cmp("printCommands")) { - parseYesNo("printCommands", &printCommands, tokens, fileName, line); - } else if (!cmd->cmp("errQuiet")) { - parseYesNo("errQuiet", &errQuiet, tokens, fileName, line); - } else { - error(-1, "Unknown config file command '%s' (%s:%d)", - cmd->getCString(), fileName->getCString(), line); - if (!cmd->cmp("displayFontX") || - !cmd->cmp("displayNamedCIDFontX") || - !cmd->cmp("displayCIDFontX")) { - error(-1, "-- Xpdf no longer supports X fonts"); - } else if (!cmd->cmp("t1libControl") || !cmd->cmp("freetypeControl")) { - error(-1, "-- The t1libControl and freetypeControl options have been replaced"); - error(-1, " by the enableT1lib, enableFreeType, and antialias options"); - } else if (!cmd->cmp("fontpath") || !cmd->cmp("fontmap")) { - error(-1, "-- the config file format has changed since Xpdf 0.9x"); - } - } - } - - deleteGList(tokens, GString); - ++line; - } -} - -static GString* qualify_filename(GString*path, GString*filename) -{ - GString*fullpath = 0; - char*prefix = "/usr/local/share/xpdf/"; - - if (filename->getChar(0) != '\\' && filename->getChar(0) != '/') { - /* relative path */ - fullpath = path->copy(); - fullpath->append(filename); - } else if (!strncmp(filename->getCString(), prefix, strlen(prefix))) { - /* xpdf default path */ - char*s = strchr(filename->getCString()+strlen(prefix), '/'); - if(s) { - fullpath = path->copy(); - fullpath->append(s+1); - } else { - fullpath = filename->copy(); - } - } else { - /* absolute path */ - fullpath = filename->copy(); - } - //printf("%s -%s-> %s\n", filename->getCString(), path->getCString(), fullpath->getCString()); - return fullpath; -} - -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(-1, "Bad 'nameToUnicode' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - name = qualify_filename(this->path, (GString *)tokens->get(1)); - if (!(f = fopen(name->getCString(), "r"))) { - error(-1, "Couldn't open 'nameToUnicode' file '%s'", - name->getCString()); - 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(-1, "Bad line in 'nameToUnicode' file (%s:%d)", name, line2); - } - ++line2; - } - fclose(f); -} - -void GlobalParams::parseCIDToUnicode(GList *tokens, GString *fileName, - int line) { - GString *collection, *name, *old; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'cidToUnicode' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - collection = (GString *)tokens->get(1); - name = (GString *)tokens->get(2); - - if ((old = (GString *)cidToUnicodes->remove(collection))) { - delete old; - } - - cidToUnicodes->add(collection->copy(), qualify_filename(this->path, name)); -} - -void GlobalParams::parseUnicodeToUnicode(GList *tokens, GString *fileName, - int line) { - GString *font, *file, *old; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'unicodeToUnicode' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - font = (GString *)tokens->get(1); - file = (GString *)tokens->get(2); - if ((old = (GString *)unicodeToUnicodes->remove(font))) { - delete old; - } - - unicodeToUnicodes->add(font->copy(), qualify_filename(this->path, file)); -} - -void GlobalParams::parseUnicodeMap(GList *tokens, GString *fileName, - int line) { - GString *encodingName, *name, *old; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'unicodeMap' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - encodingName = (GString *)tokens->get(1); - name = (GString *)tokens->get(2); - if ((old = (GString *)unicodeMaps->remove(encodingName))) { - delete old; - } - - unicodeMaps->add(encodingName->copy(), qualify_filename(this->path, name)); -} - -void GlobalParams::parseCMapDir(GList *tokens, GString *fileName, int line) { - GString *collection, *dir; - GList *list; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'cMapDir' config file command (%s:%d)", - fileName->getCString(), 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(qualify_filename(this->path, dir)); -} - -void GlobalParams::parseToUnicodeDir(GList *tokens, GString *fileName, - int line) { - GString *dir; - - if (tokens->getLength() != 2) { - error(-1, "Bad 'toUnicodeDir' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - - dir = (GString *)tokens->get(1); - - toUnicodeDirs->append(qualify_filename(this->path, dir)); -} - -void GlobalParams::parseDisplayFont(GList *tokens, GHash *fontHash, - DisplayFontParamKind kind, - GString *fileName, int line) { - DisplayFontParam *param, *old; - GString *file; - - if (tokens->getLength() < 2) { - goto err1; - } - param = new DisplayFontParam(((GString *)tokens->get(1))->copy(), kind); - - switch (kind) { - case displayFontT1: - if (tokens->getLength() != 3) { - goto err2; - } - file = (GString *)tokens->get(2); - param->t1.fileName = qualify_filename(this->path, file); - break; - case displayFontTT: - if (tokens->getLength() != 3) { - goto err2; - } - file = (GString *)tokens->get(2); - param->tt.fileName = qualify_filename(this->path, file); - break; - } - - if ((old = (DisplayFontParam *)fontHash->remove(param->name))) { - delete old; - } - fontHash->add(param->name, param); - return; - - err2: - delete param; - err1: - error(-1, "Bad 'display*Font*' config file command (%s:%d)", - fileName->getCString(), line); -} - -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(-1, "Bad 'psPaperSize' config file command (%s:%d)", - fileName->getCString(), 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(-1, "Bad 'psPaperSize' config file command (%s:%d)", - fileName->getCString(), line); - } -} - -void GlobalParams::parsePSImageableArea(GList *tokens, GString *fileName, - int line) { - if (tokens->getLength() != 5) { - error(-1, "Bad 'psImageableArea' config file command (%s:%d)", - fileName->getCString(), line); - 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(-1, "Bad 'psLevel' config file command (%s:%d)", - fileName->getCString(), 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("level2sep")) { - psLevel = psLevel2Sep; - } else if (!tok->cmp("level3")) { - psLevel = psLevel3; - } else if (!tok->cmp("level3Sep")) { - psLevel = psLevel3Sep; - } else { - error(-1, "Bad 'psLevel' config file command (%s:%d)", - fileName->getCString(), line); - } -} - -void GlobalParams::parsePSFile(GList *tokens, GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'psFile' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - if (psFile) { - delete psFile; - } - psFile = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parsePSFont(GList *tokens, GString *fileName, int line) { - PSFontParam *param; - - if (tokens->getLength() != 3) { - error(-1, "Bad 'psFont' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - param = new PSFontParam(((GString *)tokens->get(1))->copy(), 0, - ((GString *)tokens->get(2))->copy(), NULL); - psFonts->add(param->pdfFontName, param); -} - -void GlobalParams::parsePSFont16(char *cmdName, GList *fontList, - GList *tokens, GString *fileName, int line) { - PSFontParam *param; - int wMode; - GString *tok; - - if (tokens->getLength() != 5) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - tok = (GString *)tokens->get(2); - if (!tok->cmp("H")) { - wMode = 0; - } else if (!tok->cmp("V")) { - wMode = 1; - } else { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - param = new PSFontParam(((GString *)tokens->get(1))->copy(), - wMode, - ((GString *)tokens->get(3))->copy(), - ((GString *)tokens->get(4))->copy()); - fontList->append(param); -} - -void GlobalParams::parseTextEncoding(GList *tokens, GString *fileName, - int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'textEncoding' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - delete textEncoding; - textEncoding = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parseTextEOL(GList *tokens, GString *fileName, int line) { - GString *tok; - - if (tokens->getLength() != 2) { - error(-1, "Bad 'textEOL' config file command (%s:%d)", - fileName->getCString(), line); - 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(-1, "Bad 'textEOL' config file command (%s:%d)", - fileName->getCString(), line); - } -} - -void GlobalParams::parseFontDir(GList *tokens, GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'fontDir' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - fontDirs->append(((GString *)tokens->get(1))->copy()); -} - -void GlobalParams::parseInitialZoom(GList *tokens, - GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad 'initialZoom' config file command (%s:%d)", - fileName->getCString(), line); - return; - } - delete initialZoom; - initialZoom = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parseCommand(char *cmdName, GString **val, - GList *tokens, GString *fileName, int line) { - if (tokens->getLength() != 2) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - if (*val) { - delete *val; - } - *val = ((GString *)tokens->get(1))->copy(); -} - -void GlobalParams::parseYesNo(char *cmdName, GBool *flag, - GList *tokens, GString *fileName, int line) { - GString *tok; - - if (tokens->getLength() != 2) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), line); - return; - } - tok = (GString *)tokens->get(1); - if (!parseYesNo2(tok->getCString(), flag)) { - error(-1, "Bad '%s' config file command (%s:%d)", - cmdName, fileName->getCString(), 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; -} - -GlobalParams::~GlobalParams() { - GHashIter *iter; - GString *key; - GList *list; - - freeBuiltinFontTables(); - - delete macRomanReverseMap; - - delete baseDir; - delete nameToUnicode; - deleteGHash(cidToUnicodes, GString); - deleteGHash(unicodeToUnicodes, GString); - deleteGHash(residentUnicodeMaps, UnicodeMap); - deleteGHash(unicodeMaps, GString); - deleteGList(toUnicodeDirs, GString); - deleteGHash(displayFonts, DisplayFontParam); - deleteGHash(displayCIDFonts, DisplayFontParam); - deleteGHash(displayNamedCIDFonts, DisplayFontParam); - if (psFile) { - delete psFile; - } - deleteGHash(psFonts, PSFontParam); - deleteGList(psNamedFonts16, PSFontParam); - deleteGList(psFonts16, PSFontParam); - delete textEncoding; - deleteGList(fontDirs, GString); - delete initialZoom; - if (urlCommand) { - delete urlCommand; - } - if (movieCommand) { - delete movieCommand; - } - - cMapDirs->startIter(&iter); - while (cMapDirs->getNext(&iter, &key, (void **)&list)) { - deleteGList(list, GString); - } - delete cMapDirs; - - delete cidToUnicodeCache; - delete unicodeToUnicodeCache; - delete unicodeMapCache; - delete cMapCache; - -#ifdef ENABLE_PLUGINS - delete securityHandlers; - deleteGList(plugins, Plugin); -#endif - -#if MULTITHREADED - gDestroyMutex(&mutex); - gDestroyMutex(&unicodeMapCacheMutex); - gDestroyMutex(&cMapCacheMutex); -#endif -} - -//------------------------------------------------------------------------ - -void GlobalParams::setBaseDir(char *dir) { - delete baseDir; - baseDir = new GString(dir); -} - -void GlobalParams::setupBaseFonts(char *dir) { - GString *fontName; - GString *fileName; -#ifdef WIN32 - HMODULE shell32Lib; - BOOL (__stdcall *SHGetSpecialFolderPathFunc)(HWND hwndOwner, - LPTSTR lpszPath, - int nFolder, - BOOL fCreate); - char winFontDir[MAX_PATH]; -#endif - FILE *f; - DisplayFontParamKind kind; - DisplayFontParam *dfp; - int i, j; - -#ifdef WIN32 - // SHGetSpecialFolderPath isn't available in older versions of - // shell32.dll (Win95 and WinNT4), so do a dynamic load - winFontDir[0] = '\0'; - if ((shell32Lib = LoadLibrary("shell32.dll"))) { - if ((SHGetSpecialFolderPathFunc = - (BOOL (__stdcall *)(HWND hwndOwner, LPTSTR lpszPath, - int nFolder, BOOL fCreate)) - GetProcAddress(shell32Lib, "SHGetSpecialFolderPath"))) { - if (!(*SHGetSpecialFolderPathFunc)(NULL, winFontDir, - CSIDL_FONTS, FALSE)) { - winFontDir[0] = '\0'; - } - } - } -#endif - for (i = 0; displayFontTab[i].name; ++i) { - fontName = new GString(displayFontTab[i].name); - if (getDisplayFont(fontName)) { - delete fontName; - continue; - } - fileName = NULL; - kind = displayFontT1; // make gcc happy - if (dir) { - fileName = appendToPath(new GString(dir), displayFontTab[i].t1FileName); - kind = displayFontT1; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } -#ifdef WIN32 - if (!fileName && winFontDir[0] && displayFontTab[i].ttFileName) { - fileName = appendToPath(new GString(winFontDir), - displayFontTab[i].ttFileName); - kind = displayFontTT; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } - // SHGetSpecialFolderPath(CSIDL_FONTS) doesn't work on Win 2k Server - // or Win2003 Server, or with older versions of shell32.dll, so check - // the "standard" directories - if (displayFontTab[i].ttFileName) { - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].ttFileName); - kind = displayFontTT; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } - } -#else - for (j = 0; !fileName && displayFontDirs[j]; ++j) { - fileName = appendToPath(new GString(displayFontDirs[j]), - displayFontTab[i].t1FileName); - kind = displayFontT1; - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - } else { - delete fileName; - fileName = NULL; - } - } -#endif - if (!fileName) { - error(-1, "No display font for '%s'", displayFontTab[i].name); - delete fontName; - continue; - } - dfp = new DisplayFontParam(fontName, kind); - dfp->t1.fileName = fileName; - globalParams->addDisplayFont(dfp); - } -} - -//------------------------------------------------------------------------ -// 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(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 = fopen(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 = fopen(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 = fopen(fileName->getCString(), "r"); - delete fileName; - if (f) { - unlockGlobalParams; - return f; - } - } - unlockGlobalParams; - return NULL; -} - -DisplayFontParam *GlobalParams::getDisplayFont(GString *fontName) { - DisplayFontParam *dfp; - - lockGlobalParams; - dfp = (DisplayFontParam *)displayFonts->lookup(fontName); - unlockGlobalParams; - return dfp; -} - -DisplayFontParam *GlobalParams::getDisplayCIDFont(GString *fontName, - GString *collection) { - DisplayFontParam *dfp; - - lockGlobalParams; - if (!fontName || - !(dfp = (DisplayFontParam *)displayNamedCIDFonts->lookup(fontName))) { - dfp = (DisplayFontParam *)displayCIDFonts->lookup(collection); - } - unlockGlobalParams; - return dfp; -} - -GString *GlobalParams::getPSFile() { - GString *s; - - lockGlobalParams; - s = psFile ? psFile->copy() : (GString *)NULL; - unlockGlobalParams; - return s; -} - -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::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; -} - -PSFontParam *GlobalParams::getPSFont(GString *fontName) { - PSFontParam *p; - - lockGlobalParams; - p = (PSFontParam *)psFonts->lookup(fontName); - unlockGlobalParams; - return p; -} - -PSFontParam *GlobalParams::getPSFont16(GString *fontName, - GString *collection, int wMode) { - PSFontParam *p; - int i; - - lockGlobalParams; - p = NULL; - if (fontName) { - for (i = 0; i < psNamedFonts16->getLength(); ++i) { - p = (PSFontParam *)psNamedFonts16->get(i); - if (!p->pdfFontName->cmp(fontName) && - p->wMode == wMode) { - break; - } - p = NULL; - } - } - if (!p && collection) { - for (i = 0; i < psFonts16->getLength(); ++i) { - p = (PSFontParam *)psFonts16->get(i); - if (!p->pdfFontName->cmp(collection) && - p->wMode == wMode) { - break; - } - p = NULL; - } - } - unlockGlobalParams; - return p; -} - -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::getPSOPI() { - GBool opi; - - lockGlobalParams; - opi = psOPI; - unlockGlobalParams; - return opi; -} - -GBool GlobalParams::getPSASCIIHex() { - GBool ah; - - lockGlobalParams; - ah = psASCIIHex; - unlockGlobalParams; - return ah; -} - -GString *GlobalParams::getTextEncodingName() { - GString *s; - - lockGlobalParams; - s = textEncoding->copy(); - unlockGlobalParams; - return s; -} - -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::findFontFile(GString *fontName, char **exts) { - GString *dir, *fileName; - char **ext; - FILE *f; - int i; - - lockGlobalParams; - for (i = 0; i < fontDirs->getLength(); ++i) { - dir = (GString *)fontDirs->get(i); - for (ext = exts; *ext; ++ext) { - fileName = appendToPath(dir->copy(), fontName->getCString()); - fileName->append(*ext); - if ((f = fopen(fileName->getCString(), "rb"))) { - fclose(f); - unlockGlobalParams; - return fileName; - } - delete fileName; - } - } - unlockGlobalParams; - return NULL; -} - -GString *GlobalParams::getInitialZoom() { - GString *s; - - lockGlobalParams; - s = initialZoom->copy(); - unlockGlobalParams; - return s; -} - -GBool GlobalParams::getContinuousView() { - GBool f; - - lockGlobalParams; - f = continuousView; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getEnableT1lib() { - GBool f; - - lockGlobalParams; - f = enableT1lib; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getEnableFreeType() { - GBool f; - - lockGlobalParams; - f = enableFreeType; - unlockGlobalParams; - return f; -} - - -GBool GlobalParams::getAntialias() { - GBool f; - - lockGlobalParams; - f = antialias; - unlockGlobalParams; - return f; -} - -GBool GlobalParams::getMapNumericCharNames() { - GBool map; - - lockGlobalParams; - map = mapNumericCharNames; - unlockGlobalParams; - return map; -} - -GBool GlobalParams::getPrintCommands() { - GBool p; - - lockGlobalParams; - p = printCommands; - unlockGlobalParams; - return p; -} - -GBool GlobalParams::getErrQuiet() { - GBool q; - - lockGlobalParams; - q = errQuiet; - unlockGlobalParams; - return q; -} - -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::addDisplayFont(DisplayFontParam *param) { - DisplayFontParam *old; - - lockGlobalParams; - if ((old = (DisplayFontParam *)displayFonts->remove(param->name))) { - delete old; - } - displayFonts->add(param->name, param); - unlockGlobalParams; -} - -void GlobalParams::setPSFile(char *file) { - lockGlobalParams; - if (psFile) { - delete psFile; - } - psFile = new GString(file); - 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::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::setPSOPI(GBool opi) { - lockGlobalParams; - psOPI = opi; - unlockGlobalParams; -} - -void GlobalParams::setPSASCIIHex(GBool hex) { - lockGlobalParams; - psASCIIHex = hex; - unlockGlobalParams; -} - -void GlobalParams::setTextEncoding(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; -} - -void GlobalParams::setContinuousView(GBool cont) { - lockGlobalParams; - continuousView = cont; - unlockGlobalParams; -} - -GBool GlobalParams::setEnableT1lib(char *s) { - GBool ok; - - lockGlobalParams; - ok = parseYesNo2(s, &enableT1lib); - unlockGlobalParams; - return ok; -} - -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; -} - -void GlobalParams::setMapNumericCharNames(GBool map) { - lockGlobalParams; - mapNumericCharNames = map; - unlockGlobalParams; -} - -void GlobalParams::setPrintCommands(GBool printCommandsA) { - lockGlobalParams; - printCommands = printCommandsA; - unlockGlobalParams; -} - -void GlobalParams::setErrQuiet(GBool errQuietA) { - lockGlobalParams; - errQuiet = errQuietA; - unlockGlobalParams; -} - -void GlobalParams::addSecurityHandler(XpdfSecurityHandler *handler) { -#ifdef ENABLE_PLUGINS - lockGlobalParams; - securityHandlers->append(handler); - unlockGlobalParams; -#endif -} - -XpdfSecurityHandler *GlobalParams::getSecurityHandler(char *name) { -#ifdef ENABLE_PLUGINS - XpdfSecurityHandler *hdlr; - int i; - - lockGlobalParams; - for (i = 0; i < securityHandlers->getLength(); ++i) { - hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); - if (!stricmp(hdlr->name, name)) { - unlockGlobalParams; - return hdlr; - } - } - unlockGlobalParams; - - if (!loadPlugin("security", name)) { - return NULL; - } - - lockGlobalParams; - for (i = 0; i < securityHandlers->getLength(); ++i) { - hdlr = (XpdfSecurityHandler *)securityHandlers->get(i); - if (!strcmp(hdlr->name, name)) { - unlockGlobalParams; - return hdlr; - } - } - unlockGlobalParams; -#endif - - return NULL; -} - -#ifdef ENABLE_PLUGINS -//------------------------------------------------------------------------ -// plugins -//------------------------------------------------------------------------ - -GBool GlobalParams::loadPlugin(char *type, char *name) { - Plugin *plugin; - - if (!(plugin = Plugin::load(type, name))) { - return gFalse; - } - lockGlobalParams; - plugins->append(plugin); - unlockGlobalParams; - return gTrue; -} - -#endif // ENABLE_PLUGINS diff --git a/pdf2swf/xpdf/GlobalParams.h b/pdf2swf/xpdf/GlobalParams.h deleted file mode 100644 index 1fdef63..0000000 --- a/pdf2swf/xpdf/GlobalParams.h +++ /dev/null @@ -1,336 +0,0 @@ -//======================================================================== -// -// GlobalParams.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GLOBALPARAMS_H -#define GLOBALPARAMS_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include -#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 CMap; -class CMapCache; -struct XpdfSecurityHandler; -class GlobalParams; - -//------------------------------------------------------------------------ - -// The global parameters object. -extern GlobalParams *globalParams; - -//------------------------------------------------------------------------ - -enum DisplayFontParamKind { - displayFontT1, - displayFontTT -}; - -struct DisplayFontParamT1 { - GString *fileName; -}; - -struct DisplayFontParamTT { - GString *fileName; -}; - -class DisplayFontParam { -public: - - GString *name; // font name for 8-bit fonts and named - // CID fonts; collection name for - // generic CID fonts - DisplayFontParamKind kind; - union { - DisplayFontParamT1 t1; - DisplayFontParamTT tt; - }; - - DisplayFontParam(GString *nameA, DisplayFontParamKind kindA); - ~DisplayFontParam(); -}; - -//------------------------------------------------------------------------ - -class PSFontParam { -public: - - GString *pdfFontName; // PDF font name for 8-bit fonts and - // named 16-bit fonts; char collection - // name for generic 16-bit fonts - int wMode; // writing mode (0=horiz, 1=vert) for - // 16-bit fonts - GString *psFontName; // PostScript font name - GString *encoding; // encoding, for 16-bit fonts only - - PSFontParam(GString *pdfFontNameA, int wModeA, - GString *psFontNameA, GString *encodingA); - ~PSFontParam(); -}; - -//------------------------------------------------------------------------ - -enum PSLevel { - psLevel1, - psLevel1Sep, - psLevel2, - psLevel2Sep, - psLevel3, - psLevel3Sep -}; - -//------------------------------------------------------------------------ - -enum EndOfLineKind { - eolUnix, // LF - eolDOS, // CR+LF - eolMac // CR -}; - -//------------------------------------------------------------------------ - -class GlobalParams { -public: - - // Initialize the global parameters by attempting to read a config - // file. - GlobalParams(char *cfgFileName); - - ~GlobalParams(); - - void setBaseDir(char *dir); - void setupBaseFonts(char *dir); - - //----- accessors - - CharCode getMacRomanCharCode(char *charName); - - GString *getBaseDir(); - Unicode mapNameToUnicode(char *charName); - UnicodeMap *getResidentUnicodeMap(GString *encodingName); - FILE *getUnicodeMapFile(GString *encodingName); - FILE *findCMapFile(GString *collection, GString *cMapName); - FILE *findToUnicodeFile(GString *name); - DisplayFontParam *getDisplayFont(GString *fontName); - DisplayFontParam *getDisplayCIDFont(GString *fontName, GString *collection); - GString *getPSFile(); - int getPSPaperWidth(); - int getPSPaperHeight(); - void getPSImageableArea(int *llx, int *lly, int *urx, int *ury); - GBool getPSDuplex(); - GBool getPSCrop(); - GBool getPSExpandSmaller(); - GBool getPSShrinkLarger(); - GBool getPSCenter(); - PSLevel getPSLevel(); - PSFontParam *getPSFont(GString *fontName); - PSFontParam *getPSFont16(GString *fontName, GString *collection, int wMode); - GBool getPSEmbedType1(); - GBool getPSEmbedTrueType(); - GBool getPSEmbedCIDPostScript(); - GBool getPSEmbedCIDTrueType(); - GBool getPSOPI(); - GBool getPSASCIIHex(); - GString *getTextEncodingName(); - EndOfLineKind getTextEOL(); - GBool getTextPageBreaks(); - GBool getTextKeepTinyChars(); - GString *findFontFile(GString *fontName, char **exts); - GString *getInitialZoom(); - GBool getContinuousView(); - GBool getEnableT1lib(); - GBool getEnableFreeType(); - GBool getAntialias(); - GString *getURLCommand() { return urlCommand; } - GString *getMovieCommand() { return movieCommand; } - GBool getMapNumericCharNames(); - GBool getPrintCommands(); - GBool getErrQuiet(); - - 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 addDisplayFont(DisplayFontParam *param); - void setPSFile(char *file); - 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 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 setPSOPI(GBool opi); - void setPSASCIIHex(GBool hex); - void setTextEncoding(char *encodingName); - GBool setTextEOL(char *s); - void setTextPageBreaks(GBool pageBreaks); - void setTextKeepTinyChars(GBool keep); - void setInitialZoom(char *s); - void setContinuousView(GBool cont); - GBool setEnableT1lib(char *s); - GBool setEnableFreeType(char *s); - GBool setAntialias(char *s); - void setMapNumericCharNames(GBool map); - void setPrintCommands(GBool printCommandsA); - void setErrQuiet(GBool errQuietA); - - //----- security handlers - - void addSecurityHandler(XpdfSecurityHandler *handler); - XpdfSecurityHandler *getSecurityHandler(char *name); - -private: - - void parseFile(GString *fileName, FILE *f); - 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 parseDisplayFont(GList *tokens, GHash *fontHash, - DisplayFontParamKind kind, - GString *fileName, int line); - void parsePSFile(GList *tokens, GString *fileName, int line); - void parsePSPaperSize(GList *tokens, GString *fileName, int line); - void parsePSImageableArea(GList *tokens, GString *fileName, int line); - void parsePSLevel(GList *tokens, GString *fileName, int line); - void parsePSFont(GList *tokens, GString *fileName, int line); - void parsePSFont16(char *cmdName, GList *fontList, - GList *tokens, GString *fileName, int line); - void parseTextEncoding(GList *tokens, GString *fileName, int line); - void parseTextEOL(GList *tokens, GString *fileName, int line); - void parseFontDir(GList *tokens, GString *fileName, int line); - void parseInitialZoom(GList *tokens, GString *fileName, int line); - void parseCommand(char *cmdName, GString **val, - GList *tokens, GString *fileName, int line); - void parseYesNo(char *cmdName, GBool *flag, - GList *tokens, GString *fileName, int line); - GBool parseYesNo2(char *token, GBool *flag); - UnicodeMap *getUnicodeMap2(GString *encodingName); -#ifdef ENABLE_PLUGINS - GBool loadPlugin(char *type, char *name); -#endif - - //----- static tables - - NameToCharCode * // mapping from char name to - macRomanReverseMap; // MacRomanEncoding index - - //----- user-modifiable settings - - GString *baseDir; // base directory - for plugins, etc. - 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] - GHash *displayFonts; // display font info, indexed by font name - // [DisplayFontParam] - GHash *displayCIDFonts; // display CID font info, indexed by - // collection [DisplayFontParam] - GHash *displayNamedCIDFonts; // display CID font info, indexed by - // font name [DisplayFontParam] - GString *psFile; // PostScript file or command (for xpdf) - 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 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 *psFonts; // PostScript font info, indexed by PDF - // font name [PSFontParam] - GList *psNamedFonts16; // named 16-bit fonts [PSFontParam] - GList *psFonts16; // generic 16-bit fonts [PSFontParam] - GBool psEmbedType1; // embed Type 1 fonts? - GBool psEmbedTrueType; // embed TrueType fonts? - GBool psEmbedCIDPostScript; // embed CID PostScript fonts? - GBool psEmbedCIDTrueType; // embed CID TrueType fonts? - GBool psOPI; // generate PostScript OPI comments? - GBool psASCIIHex; // use ASCIIHex instead of ASCII85? - GString *textEncoding; // encoding (unicodeMap) to use for text - // output - EndOfLineKind textEOL; // type of EOL marker to use for text - // output - GBool textPageBreaks; // insert end-of-page markers? - GBool textKeepTinyChars; // keep all characters in text output - GList *fontDirs; // list of font dirs [GString] - GString *initialZoom; // initial zoom level - GBool continuousView; // continuous view mode - GBool enableT1lib; // t1lib enable flag - GBool enableFreeType; // FreeType enable flag - GBool antialias; // anti-aliasing enable flag - GString *urlCommand; // command executed for URL links - GString *movieCommand; // command executed for movie annotations - GBool mapNumericCharNames; // map numeric char names (from font subsets)? - GBool printCommands; // print the drawing commands - GBool errQuiet; // suppress error messages? - - CharCodeToUnicodeCache *cidToUnicodeCache; - CharCodeToUnicodeCache *unicodeToUnicodeCache; - UnicodeMapCache *unicodeMapCache; - CMapCache *cMapCache; - -#ifdef ENABLE_PLUGINS - GList *plugins; // list of plugins [Plugin] - GList *securityHandlers; // list of loaded security handlers - // [XpdfSecurityHandler] -#endif - -#if MULTITHREADED - GMutex mutex; - GMutex unicodeMapCacheMutex; - GMutex cMapCacheMutex; -#endif -}; - -#endif diff --git a/pdf2swf/xpdf/JArithmeticDecoder.cc b/pdf2swf/xpdf/JArithmeticDecoder.cc deleted file mode 100644 index 195b73e..0000000 --- a/pdf2swf/xpdf/JArithmeticDecoder.cc +++ /dev/null @@ -1,322 +0,0 @@ -//======================================================================== -// -// JArithmeticDecoder.cc -// -// Copyright 2002-2004 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#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] = (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; -} - -inline Guint JArithmeticDecoder::readByte() { - if (limitStream) { - --dataLen; - if (dataLen < 0) { - return 0xff; - } - } - 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) { - int oldDataLen; - - oldDataLen = dataLen; - dataLen = dataLenA; - if (oldDataLen == -1) { - buf1 = readByte(); - } else if (oldDataLen <= -2) { - buf0 = readByte(); - buf1 = readByte(); - } -} - -void JArithmeticDecoder::cleanup() { - if (limitStream) { - while (dataLen > 0) { - buf0 = buf1; - buf1 = 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] = (nlpsTab[iCX] << 1) | (1 - mpsCX); - } else { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | mpsCX; - } - } else { - bit = mpsCX; - stats->cxTab[context] = (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] = (nmpsTab[iCX] << 1) | mpsCX; - } else { - bit = 1 - mpsCX; - if (switchTab[iCX]) { - stats->cxTab[context] = (nlpsTab[iCX] << 1) | (1 - mpsCX); - } else { - stats->cxTab[context] = (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) { - 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/pdf2swf/xpdf/JArithmeticDecoder.h b/pdf2swf/xpdf/JArithmeticDecoder.h deleted file mode 100644 index a40823d..0000000 --- a/pdf2swf/xpdf/JArithmeticDecoder.h +++ /dev/null @@ -1,109 +0,0 @@ -//======================================================================== -// -// JArithmeticDecoder.h -// -// Arithmetic decoder used by the JBIG2 and JPEG2000 decoders. -// -// Copyright 2002-2004 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef JARITHMETICDECODER_H -#define JARITHMETICDECODER_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -class Stream; - -//------------------------------------------------------------------------ -// JArithmeticDecoderStats -//------------------------------------------------------------------------ - -class JArithmeticDecoderStats { -public: - - JArithmeticDecoderStats(int contextSizeA); - ~JArithmeticDecoderStats(); - JArithmeticDecoderStats *copy(); - void reset(); - int getContextSize() { return contextSize; } - void copyFrom(JArithmeticDecoderStats *stats); - void setEntry(Guint cx, int i, int mps); - -private: - - Guchar *cxTab; // cxTab[cx] = (i[cx] << 1) + mps[cx] - int contextSize; - - friend class JArithmeticDecoder; -}; - -//------------------------------------------------------------------------ -// JArithmeticDecoder -//------------------------------------------------------------------------ - -class JArithmeticDecoder { -public: - - JArithmeticDecoder(); - ~JArithmeticDecoder(); - - void setStream(Stream *strA) - { str = strA; dataLen = 0; limitStream = gFalse; } - void setStream(Stream *strA, int dataLenA) - { str = strA; dataLen = dataLenA; limitStream = gTrue; } - - // Start decoding on a new stream. This fills the byte buffers and - // runs INITDEC. - void start(); - - // Restart decoding on an interrupted stream. This refills the - // buffers if needed, but does not run INITDEC. (This is used in - // JPEG 2000 streams when codeblock data is split across multiple - // packets/layers.) - void restart(int dataLenA); - - // Read any leftover data in the stream. - void cleanup(); - - // Decode one bit. - int decodeBit(Guint context, JArithmeticDecoderStats *stats); - - // Decode eight bits. - int decodeByte(Guint context, JArithmeticDecoderStats *stats); - - // Returns false for OOB, otherwise sets * and returns true. - GBool decodeInt(int *x, JArithmeticDecoderStats *stats); - - Guint decodeIAID(Guint codeLen, - JArithmeticDecoderStats *stats); - -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; - int dataLen; - GBool limitStream; -}; - -#endif diff --git a/pdf2swf/xpdf/JBIG2Stream.cc b/pdf2swf/xpdf/JBIG2Stream.cc deleted file mode 100644 index a90db80..0000000 --- a/pdf2swf/xpdf/JBIG2Stream.cc +++ /dev/null @@ -1,3386 +0,0 @@ -//======================================================================== -// -// JBIG2Stream.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "GList.h" -#include "Error.h" -#include "JArithmeticDecoder.h" -#include "JBIG2Stream.h" - -//~ share these tables -#include "Stream-CCITT.h" - -//------------------------------------------------------------------------ - -static int contextSize[4] = { 16, 13, 10, 10 }; -static int refContextSize[2] = { 13, 10 }; - -//------------------------------------------------------------------------ -// JBIG2HuffmanTable -//------------------------------------------------------------------------ - -#define jbig2HuffmanLOW 0xfffffffd -#define jbig2HuffmanOOB 0xfffffffe -#define jbig2HuffmanEOT 0xffffffff - -struct JBIG2HuffmanTable { - int val; - Guint prefixLen; - Guint rangeLen; // can also be LOW, OOB, or EOT - Guint prefix; -}; - -JBIG2HuffmanTable huffTableA[] = { - { 0, 1, 4, 0x000 }, - { 16, 2, 8, 0x002 }, - { 272, 3, 16, 0x006 }, - { 65808, 3, 32, 0x007 }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableB[] = { - { 0, 1, 0, 0x000 }, - { 1, 2, 0, 0x002 }, - { 2, 3, 0, 0x006 }, - { 3, 4, 3, 0x00e }, - { 11, 5, 6, 0x01e }, - { 75, 6, 32, 0x03e }, - { 0, 6, jbig2HuffmanOOB, 0x03f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableC[] = { - { 0, 1, 0, 0x000 }, - { 1, 2, 0, 0x002 }, - { 2, 3, 0, 0x006 }, - { 3, 4, 3, 0x00e }, - { 11, 5, 6, 0x01e }, - { 0, 6, jbig2HuffmanOOB, 0x03e }, - { 75, 7, 32, 0x0fe }, - { -256, 8, 8, 0x0fe }, - { -257, 8, jbig2HuffmanLOW, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableD[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 0, 0x006 }, - { 4, 4, 3, 0x00e }, - { 12, 5, 6, 0x01e }, - { 76, 5, 32, 0x01f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableE[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 0, 0x006 }, - { 4, 4, 3, 0x00e }, - { 12, 5, 6, 0x01e }, - { 76, 6, 32, 0x03e }, - { -255, 7, 8, 0x07e }, - { -256, 7, jbig2HuffmanLOW, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableF[] = { - { 0, 2, 7, 0x000 }, - { 128, 3, 7, 0x002 }, - { 256, 3, 8, 0x003 }, - { -1024, 4, 9, 0x008 }, - { -512, 4, 8, 0x009 }, - { -256, 4, 7, 0x00a }, - { -32, 4, 5, 0x00b }, - { 512, 4, 9, 0x00c }, - { 1024, 4, 10, 0x00d }, - { -2048, 5, 10, 0x01c }, - { -128, 5, 6, 0x01d }, - { -64, 5, 5, 0x01e }, - { -2049, 6, jbig2HuffmanLOW, 0x03e }, - { 2048, 6, 32, 0x03f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableG[] = { - { -512, 3, 8, 0x000 }, - { 256, 3, 8, 0x001 }, - { 512, 3, 9, 0x002 }, - { 1024, 3, 10, 0x003 }, - { -1024, 4, 9, 0x008 }, - { -256, 4, 7, 0x009 }, - { -32, 4, 5, 0x00a }, - { 0, 4, 5, 0x00b }, - { 128, 4, 7, 0x00c }, - { -128, 5, 6, 0x01a }, - { -64, 5, 5, 0x01b }, - { 32, 5, 5, 0x01c }, - { 64, 5, 6, 0x01d }, - { -1025, 5, jbig2HuffmanLOW, 0x01e }, - { 2048, 5, 32, 0x01f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableH[] = { - { 0, 2, 1, 0x000 }, - { 0, 2, jbig2HuffmanOOB, 0x001 }, - { 4, 3, 4, 0x004 }, - { -1, 4, 0, 0x00a }, - { 22, 4, 4, 0x00b }, - { 38, 4, 5, 0x00c }, - { 2, 5, 0, 0x01a }, - { 70, 5, 6, 0x01b }, - { 134, 5, 7, 0x01c }, - { 3, 6, 0, 0x03a }, - { 20, 6, 1, 0x03b }, - { 262, 6, 7, 0x03c }, - { 646, 6, 10, 0x03d }, - { -2, 7, 0, 0x07c }, - { 390, 7, 8, 0x07d }, - { -15, 8, 3, 0x0fc }, - { -5, 8, 1, 0x0fd }, - { -7, 9, 1, 0x1fc }, - { -3, 9, 0, 0x1fd }, - { -16, 9, jbig2HuffmanLOW, 0x1fe }, - { 1670, 9, 32, 0x1ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableI[] = { - { 0, 2, jbig2HuffmanOOB, 0x000 }, - { -1, 3, 1, 0x002 }, - { 1, 3, 1, 0x003 }, - { 7, 3, 5, 0x004 }, - { -3, 4, 1, 0x00a }, - { 43, 4, 5, 0x00b }, - { 75, 4, 6, 0x00c }, - { 3, 5, 1, 0x01a }, - { 139, 5, 7, 0x01b }, - { 267, 5, 8, 0x01c }, - { 5, 6, 1, 0x03a }, - { 39, 6, 2, 0x03b }, - { 523, 6, 8, 0x03c }, - { 1291, 6, 11, 0x03d }, - { -5, 7, 1, 0x07c }, - { 779, 7, 9, 0x07d }, - { -31, 8, 4, 0x0fc }, - { -11, 8, 2, 0x0fd }, - { -15, 9, 2, 0x1fc }, - { -7, 9, 1, 0x1fd }, - { -32, 9, jbig2HuffmanLOW, 0x1fe }, - { 3339, 9, 32, 0x1ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableJ[] = { - { -2, 2, 2, 0x000 }, - { 6, 2, 6, 0x001 }, - { 0, 2, jbig2HuffmanOOB, 0x002 }, - { -3, 5, 0, 0x018 }, - { 2, 5, 0, 0x019 }, - { 70, 5, 5, 0x01a }, - { 3, 6, 0, 0x036 }, - { 102, 6, 5, 0x037 }, - { 134, 6, 6, 0x038 }, - { 198, 6, 7, 0x039 }, - { 326, 6, 8, 0x03a }, - { 582, 6, 9, 0x03b }, - { 1094, 6, 10, 0x03c }, - { -21, 7, 4, 0x07a }, - { -4, 7, 0, 0x07b }, - { 4, 7, 0, 0x07c }, - { 2118, 7, 11, 0x07d }, - { -5, 8, 0, 0x0fc }, - { 5, 8, 0, 0x0fd }, - { -22, 8, jbig2HuffmanLOW, 0x0fe }, - { 4166, 8, 32, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableK[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 1, 0x002 }, - { 4, 4, 0, 0x00c }, - { 5, 4, 1, 0x00d }, - { 7, 5, 1, 0x01c }, - { 9, 5, 2, 0x01d }, - { 13, 6, 2, 0x03c }, - { 17, 7, 2, 0x07a }, - { 21, 7, 3, 0x07b }, - { 29, 7, 4, 0x07c }, - { 45, 7, 5, 0x07d }, - { 77, 7, 6, 0x07e }, - { 141, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableL[] = { - { 1, 1, 0, 0x000 }, - { 2, 2, 0, 0x002 }, - { 3, 3, 1, 0x006 }, - { 5, 5, 0, 0x01c }, - { 6, 5, 1, 0x01d }, - { 8, 6, 1, 0x03c }, - { 10, 7, 0, 0x07a }, - { 11, 7, 1, 0x07b }, - { 13, 7, 2, 0x07c }, - { 17, 7, 3, 0x07d }, - { 25, 7, 4, 0x07e }, - { 41, 8, 5, 0x0fe }, - { 73, 8, 32, 0x0ff }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableM[] = { - { 1, 1, 0, 0x000 }, - { 2, 3, 0, 0x004 }, - { 7, 3, 3, 0x005 }, - { 3, 4, 0, 0x00c }, - { 5, 4, 1, 0x00d }, - { 4, 5, 0, 0x01c }, - { 15, 6, 1, 0x03a }, - { 17, 6, 2, 0x03b }, - { 21, 6, 3, 0x03c }, - { 29, 6, 4, 0x03d }, - { 45, 6, 5, 0x03e }, - { 77, 7, 6, 0x07e }, - { 141, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableN[] = { - { 0, 1, 0, 0x000 }, - { -2, 3, 0, 0x004 }, - { -1, 3, 0, 0x005 }, - { 1, 3, 0, 0x006 }, - { 2, 3, 0, 0x007 }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -JBIG2HuffmanTable huffTableO[] = { - { 0, 1, 0, 0x000 }, - { -1, 3, 0, 0x004 }, - { 1, 3, 0, 0x005 }, - { -2, 4, 0, 0x00c }, - { 2, 4, 0, 0x00d }, - { -4, 5, 1, 0x01c }, - { 3, 5, 1, 0x01d }, - { -8, 6, 2, 0x03c }, - { 5, 6, 2, 0x03d }, - { -24, 7, 4, 0x07c }, - { 9, 7, 4, 0x07d }, - { -25, 7, jbig2HuffmanLOW, 0x07e }, - { 25, 7, 32, 0x07f }, - { 0, 0, jbig2HuffmanEOT, 0 } -}; - -//------------------------------------------------------------------------ -// JBIG2HuffmanDecoder -//------------------------------------------------------------------------ - -class JBIG2HuffmanDecoder { -public: - - JBIG2HuffmanDecoder(); - ~JBIG2HuffmanDecoder(); - void setStream(Stream *strA) { str = strA; } - - void reset(); - - // Returns false for OOB, otherwise sets * and returns true. - GBool decodeInt(int *x, JBIG2HuffmanTable *table); - - Guint readBits(Guint n); - Guint readBit(); - - // Sort the table by prefix length and assign prefix values. - void buildTable(JBIG2HuffmanTable *table, Guint len); - -private: - - Stream *str; - Guint buf; - Guint bufLen; -}; - -JBIG2HuffmanDecoder::JBIG2HuffmanDecoder() { - str = NULL; - 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); - nLeft -= 8; - } - if (nLeft > 0) { - buf = str->getChar(); - bufLen = 8 - nLeft; - x = (x << nLeft) | ((buf >> bufLen) & ((1 << nLeft) - 1)); - } - } - return x; -} - -Guint JBIG2HuffmanDecoder::readBit() { - if (bufLen == 0) { - buf = str->getChar(); - 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 - 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 skipTo(Guint length); - -private: - - Stream *str; - Guint buf; - Guint bufLen; - Guint nBytesRead; -}; - -JBIG2MMRDecoder::JBIG2MMRDecoder() { - str = NULL; - 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; - p = &twoDimTab1[(buf >> 1) & 0x7f]; - } else if (bufLen == 8) { - p = &twoDimTab1[(buf >> 1) & 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; - p = &twoDimTab1[(buf >> (bufLen - 7)) & 0x7f]; - } - } - if (p->bits < 0) { - error(str->getPos(), "Bad two dim code in JBIG2 MMR stream"); - return 0; - } - bufLen -= p->bits; - return p->n; -} - -int JBIG2MMRDecoder::getWhiteCode() { - CCITTCode *p; - Guint code; - - if (bufLen == 0) { - buf = str->getChar() & 0xff; - bufLen = 8; - ++nBytesRead; - } - while (1) { - if (bufLen >= 7 && ((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; - } - error(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; - } - while (1) { - if (bufLen >= 6 && ((buf >> (bufLen - 6)) & 0x3f) == 0) { - if (bufLen <= 13) { - code = buf << (13 - bufLen); - } else { - code = buf >> (bufLen - 13); - } - p = &blackTab1[code & 0x7f]; - } else if (bufLen >= 4 && ((buf >> (bufLen - 4)) & 0x0f) == 0) { - 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; - } - error(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; - } - return (buf >> (bufLen - 24)) & 0xffffff; -} - -void JBIG2MMRDecoder::skipTo(Guint length) { - while (nBytesRead < length) { - str->getChar(); - ++nBytesRead; - } -} - -//------------------------------------------------------------------------ -// 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 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)] |= 1 << (7 - (x & 7)); } - void clearPixel(int x, int y) - { data[y * line + (x >> 3)] &= 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; - // 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; - // 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) { - 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; - } 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; - Guint src0, src1, src, dest, s1, s2, m1, m2, m3; - GBool oneByte; - - if (y < 0) { - y0 = -y; - } else { - y0 = 0; - } - 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 = 0xff >> (x1 & 7); - m2 = 0xff << (((x1 & 7) == 0) ? 0 : 8 - (x1 & 7)); - m3 = (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 |= (src1 >> s1) & m2; - break; - case 1: // and - dest &= ((0xff00 | src1) >> s1) | m1; - break; - case 2: // xor - dest ^= (src1 >> s1) & m2; - break; - case 3: // xnor - dest ^= ((src1 ^ 0xff) >> s1) & m2; - break; - case 4: // replace - dest = (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 |= src1 >> s1; - break; - case 1: // and - dest &= (0xff00 | src1) >> s1; - break; - case 2: // xor - dest ^= src1 >> s1; - break; - case 3: // xnor - dest ^= (src1 ^ 0xff) >> s1; - break; - case 4: // replace - dest = (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 = (((src0 << 8) | src1) >> s1) & 0xff; - 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 = (((src0 << 8) | src1) >> s1) & 0xff; - 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) -{ - size = sizeA; - bitmaps = (JBIG2Bitmap **)gmallocn(size, sizeof(JBIG2Bitmap *)); - genericRegionStats = NULL; - refinementRegionStats = NULL; -} - -JBIG2SymbolDict::~JBIG2SymbolDict() { - Guint i; - - for (i = 0; i < size; ++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 *globalsStream): - FilterStream(strA) -{ - 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(); - - segments = globalSegments = new GList(); - if (globalsStream->isStream()) { - curStr = globalsStream->getStream(); - curStr->reset(); - arithDecoder->setStream(curStr); - huffDecoder->setStream(curStr); - mmrDecoder->setStream(curStr); - readSegments(); - } - - segments = NULL; - curStr = NULL; - dataPtr = dataEnd = NULL; -} - -JBIG2Stream::~JBIG2Stream() { - 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; - if (pageBitmap) { - delete pageBitmap; - } - if (segments) { - deleteGList(segments, JBIG2Segment); - } - if (globalSegments) { - deleteGList(globalSegments, JBIG2Segment); - } - delete str; -} - -void JBIG2Stream::reset() { - if (pageBitmap) { - delete pageBitmap; - pageBitmap = NULL; - } - if (segments) { - deleteGList(segments, JBIG2Segment); - } - segments = new GList(); - - 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 = NULL; - } -} - -int JBIG2Stream::getChar() { - if (dataPtr && dataPtr < dataEnd) { - return (*dataPtr++ ^ 0xff) & 0xff; - } - return EOF; -} - -int JBIG2Stream::lookChar() { - if (dataPtr && dataPtr < dataEnd) { - return (*dataPtr ^ 0xff) & 0xff; - } - return EOF; -} - -GString *JBIG2Stream::getPSFilter(int psLevel, char *indent) { - return NULL; -} - -GBool JBIG2Stream::isBinary(GBool last) { - return str->isBinary(gTrue); -} - -void JBIG2Stream::readSegments() { - Guint segNum, segFlags, segType, page, segLength; - Guint refFlags, nRefSegs; - Guint *refSegs; - int c1, c2, c3; - Guint i; - - while (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; - for (i = 0; i < (nRefSegs + 9) >> 3; ++i) { - c1 = curStr->getChar(); - } - } - - // 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; - } - - // read the segment data - 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 52: - readProfilesSeg(segLength); - break; - case 53: - readCodeTableSeg(segNum, segLength); - break; - case 62: - readExtensionSeg(segLength); - break; - default: - error(getPos(), "Unknown segment type in JBIG2 stream"); - for (i = 0; i < segLength; ++i) { - if ((c1 = curStr->getChar()) == EOF) { - goto eofError2; - } - } - break; - } - - gfree(refSegs); - } - - return; - - syntaxError: - gfree(refSegs); - return; - - eofError2: - gfree(refSegs); - eofError1: - error(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, cnt; - Guint i, j, k; - Guchar *p; - - // 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) { - seg = findSegment(refSegs[i]); - if (seg->getType() == jbig2SegSymbolDict) { - numInputSyms += ((JBIG2SymbolDict *)seg)->getSize(); - } else if (seg->getType() == jbig2SegCodeTable) { - codeTables->append(seg); - } - } - - // compute symbol code length - symCodeLen = 0; - i = 1; - while (i < numInputSyms + numNewSyms) { - ++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) { - 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 { - huffDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDW == 0) { - huffDWTable = huffTableB; - } else if (huffDW == 1) { - huffDWTable = huffTableC; - } else { - huffDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffBMSize == 0) { - huffBMSizeTable = huffTableA; - } else { - huffBMSizeTable = - ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffAggInst == 0) { - huffAggInstTable = huffTableA; - } else { - 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 - symWidths = NULL; - 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) { - error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); - goto syntaxError; - } - symHeight += dh; - symWidth = 0; - totalWidth = 0; - j = i; - - // 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) { - error(getPos(), "Bad delta-height value in JBIG2 symbol dictionary"); - goto syntaxError; - } - symWidth += dw; - - // 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); - } - 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) { - huffDecoder->decodeInt(&bmSize, huffBMSizeTable); - huffDecoder->reset(); - if (bmSize == 0) { - collBitmap = new JBIG2Bitmap(0, totalWidth, symHeight); - bmSize = symHeight * ((totalWidth + 7) >> 3); - p = collBitmap->getDataPtr(); - for (k = 0; k < (Guint)bmSize; ++k) { - *p++ = curStr->getChar(); - } - } 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; - while (i < numInputSyms + numNewSyms) { - if (huff) { - huffDecoder->decodeInt(&run, huffTableA); - } else { - arithDecoder->decodeInt(&run, iaexStats); - } - if (ex) { - for (cnt = 0; cnt < run; ++cnt) { - symbolDict->setBitmap(j++, bitmaps[i++]->copy()); - } - } else { - i += run; - } - ex = !ex; - } - - 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; - - 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(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; - } - 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) { - numSyms += ((JBIG2SymbolDict *)seg)->getSize(); - } else if (seg->getType() == jbig2SegCodeTable) { - codeTables->append(seg); - } - } else { - error(getPos(), "Invalid segment reference in JBIG2 text region"); - } - } - symCodeLen = 0; - i = 1; - while (i < numSyms) { - ++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 { - huffFSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDS == 0) { - huffDSTable = huffTableH; - } else if (huffDS == 1) { - huffDSTable = huffTableI; - } else if (huffDS == 2) { - huffDSTable = huffTableJ; - } else { - huffDSTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffDT == 0) { - huffDTTable = huffTableK; - } else if (huffDT == 1) { - huffDTTable = huffTableL; - } else if (huffDT == 2) { - huffDTTable = huffTableM; - } else { - huffDTTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDW == 0) { - huffRDWTable = huffTableN; - } else if (huffRDW == 1) { - huffRDWTable = huffTableO; - } else { - huffRDWTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDH == 0) { - huffRDHTable = huffTableN; - } else if (huffRDH == 1) { - huffRDHTable = huffTableO; - } else { - huffRDHTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDX == 0) { - huffRDXTable = huffTableN; - } else if (huffRDX == 1) { - huffRDXTable = huffTableO; - } else { - huffRDXTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRDY == 0) { - huffRDYTable = huffTableN; - } else if (huffRDY == 1) { - huffRDYTable = huffTableO; - } else { - huffRDYTable = ((JBIG2CodeTable *)codeTables->get(i++))->getHuffTable(); - } - if (huffRSize == 0) { - huffRSizeTable = huffTableA; - } else { - 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[32].val = 0x103; - runLengthTab[32].prefixLen = huffDecoder->readBits(4); - runLengthTab[32].rangeLen = 2; - runLengthTab[33].val = 0x203; - runLengthTab[33].prefixLen = huffDecoder->readBits(4); - runLengthTab[33].rangeLen = 3; - runLengthTab[34].val = 0x20b; - runLengthTab[34].prefixLen = huffDecoder->readBits(4); - runLengthTab[34].rangeLen = 7; - runLengthTab[35].prefixLen = 0; - runLengthTab[35].rangeLen = jbig2HuffmanEOT; - 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) { - 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; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -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) { - huffDecoder->decodeInt(&dt, huffDTTable); - } else { - arithDecoder->decodeInt(&dt, iadtStats); - } - t += dt * strips; - - // first S value - if (huff) { - huffDecoder->decodeInt(&ds, huffFSTable); - } else { - arithDecoder->decodeInt(&ds, iafsStats); - } - sFirst += ds; - s = sFirst; - - // read the instances - while (1) { - - // 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(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; - } - 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(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; - } - 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; - } - - // get pattern dictionary - if (nRefSegs != 1) { - error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); - return; - } - seg = findSegment(refSegs[0]); - if (seg->getType() != jbig2SegPatternDict) { - error(getPos(), "Bad symbol dictionary reference in JBIG2 halftone segment"); - return; - } - patternDict = (JBIG2PatternDict *)seg; - bpp = 0; - i = 1; - while (i < patternDict->getSize()) { - ++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) { - xx = gridX + m * stepY; - yy = gridY + m * stepX; - for (n = 0; n < gridW; ++n) { - 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); - - // 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(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readGenericRegionSeg(Guint segNum, GBool imm, - GBool lossless, Guint length) { - JBIG2Bitmap *bitmap; - Guint w, h, x, y, segInfoFlags, extCombOp; - Guint 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; - } - 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 ? 0 : length - 18); - - // 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); - } - - return; - - eofError: - error(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -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; - JBIG2BitmapPtr cxPtr0, cxPtr1; - JBIG2BitmapPtr atPtr0, atPtr1, atPtr2, atPtr3; - int *refLine, *codingLine; - int code1, code2, code3; - int x, y, a0, pix, i, refI, codingI; - - bitmap = new JBIG2Bitmap(0, w, h); - bitmap->clearToZero(); - - //----- MMR decode - - if (mmr) { - - mmrDecoder->reset(); - refLine = (int *)gmallocn(w + 2, sizeof(int)); - codingLine = (int *)gmallocn(w + 2, sizeof(int)); - codingLine[0] = codingLine[1] = 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] = refLine[i + 1] = w; - - // decode a line - refI = 0; // b1 = refLine[refI] - codingI = 0; // a1 = codingLine[codingI] - a0 = 0; - do { - code1 = mmrDecoder->get2DCode(); - switch (code1) { - case twoDimPass: - if (refLine[refI] < w) { - a0 = refLine[refI + 1]; - refI += 2; - } - break; - case twoDimHoriz: - if (codingI & 1) { - code1 = 0; - do { - code1 += code3 = mmrDecoder->getBlackCode(); - } while (code3 >= 64); - code2 = 0; - do { - code2 += code3 = mmrDecoder->getWhiteCode(); - } while (code3 >= 64); - } else { - code1 = 0; - do { - code1 += code3 = mmrDecoder->getWhiteCode(); - } while (code3 >= 64); - code2 = 0; - do { - code2 += code3 = mmrDecoder->getBlackCode(); - } while (code3 >= 64); - } - if (code1 > 0 || code2 > 0) { - a0 = codingLine[codingI++] = a0 + code1; - a0 = codingLine[codingI++] = a0 + code2; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVert0: - a0 = codingLine[codingI++] = refLine[refI]; - if (refLine[refI] < w) { - ++refI; - } - break; - case twoDimVertR1: - a0 = codingLine[codingI++] = refLine[refI] + 1; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertR2: - a0 = codingLine[codingI++] = refLine[refI] + 2; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertR3: - a0 = codingLine[codingI++] = refLine[refI] + 3; - if (refLine[refI] < w) { - ++refI; - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - } - break; - case twoDimVertL1: - a0 = codingLine[codingI++] = refLine[refI] - 1; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - case twoDimVertL2: - a0 = codingLine[codingI++] = refLine[refI] - 2; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - case twoDimVertL3: - a0 = codingLine[codingI++] = refLine[refI] - 3; - if (refI > 0) { - --refI; - } else { - ++refI; - } - while (refLine[refI] <= a0 && refLine[refI] < w) { - refI += 2; - } - break; - default: - error(getPos(), "Illegal code in JBIG2 MMR bitmap data"); - break; - } - } while (a0 < w); - codingLine[codingI++] = w; - - // convert the run lengths to a bitmap line - i = 0; - while (codingLine[i] < w) { - for (x = codingLine[i]; x < codingLine[i+1]; ++x) { - bitmap->setPixel(x, y); - } - i += 2; - } - } - - if (mmrDataLength >= 0) { - mmrDecoder->skipTo(mmrDataLength); - } else { - if (mmrDecoder->get24Bits() != 0x001001) { - error(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 = 0x18a; // 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) { - bitmap->duplicateRow(y, y-1); - continue; - } - } - - switch (templ) { - case 0: - - // set up the context - bitmap->getPixelPtr(0, y-2, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - bitmap->getPixelPtr(atx[1], y + aty[1], &atPtr1); - bitmap->getPixelPtr(atx[2], y + aty[2], &atPtr2); - bitmap->getPixelPtr(atx[3], y + aty[3], &atPtr3); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx0 << 13) | (cx1 << 8) | (cx2 << 4) | - (bitmap->nextPixel(&atPtr0) << 3) | - (bitmap->nextPixel(&atPtr1) << 2) | - (bitmap->nextPixel(&atPtr2) << 1) | - bitmap->nextPixel(&atPtr3); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - } - break; - - case 1: - - // set up the context - bitmap->getPixelPtr(0, y-2, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx0 << 9) | (cx1 << 4) | (cx2 << 1) | - bitmap->nextPixel(&atPtr0); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x0f; - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x07; - } - break; - - case 2: - - // set up the context - bitmap->getPixelPtr(0, y-2, &cxPtr0); - cx0 = bitmap->nextPixel(&cxPtr0); - cx0 = (cx0 << 1) | bitmap->nextPixel(&cxPtr0); - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx0 << 7) | (cx1 << 3) | (cx2 << 1) | - bitmap->nextPixel(&atPtr0); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx0 = ((cx0 << 1) | bitmap->nextPixel(&cxPtr0)) & 0x07; - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x0f; - cx2 = ((cx2 << 1) | pix) & 0x03; - } - break; - - case 3: - - // set up the context - bitmap->getPixelPtr(0, y-1, &cxPtr1); - cx1 = bitmap->nextPixel(&cxPtr1); - cx1 = (cx1 << 1) | bitmap->nextPixel(&cxPtr1); - cx2 = 0; - bitmap->getPixelPtr(atx[0], y + aty[0], &atPtr0); - - // decode the row - for (x = 0; x < w; ++x) { - - // build the context - cx = (cx1 << 5) | (cx2 << 1) | - bitmap->nextPixel(&atPtr0); - - // check for a skipped pixel - if (useSkip && skip->getPixel(x, y)) { - pix = 0; - - // decode the pixel - } else if ((pix = arithDecoder->decodeBit(cx, genericRegionStats))) { - bitmap->setPixel(x, y); - } - - // update the context - cx1 = ((cx1 << 1) | bitmap->nextPixel(&cxPtr1)) & 0x1f; - cx2 = ((cx2 << 1) | pix) & 0x0f; - } - 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; - } - 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(getPos(), "Bad reference in JBIG2 generic refinement segment"); - return; - } - if (nRefSegs == 1) { - seg = findSegment(refSegs[0]); - if (seg->getType() != jbig2SegBitmap) { - error(getPos(), "Bad bitmap reference in JBIG2 generic refinement segment"); - 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(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); - } - - 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); - } - - 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; - } - pageDefPixel = (flags >> 2) & 1; - defCombOp = (flags >> 3) & 3; - - // 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(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readEndOfStripeSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -void JBIG2Stream::readProfilesSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -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(getPos(), "Unexpected EOF in JBIG2 stream"); -} - -void JBIG2Stream::readExtensionSeg(Guint length) { - Guint i; - - // skip the segment - for (i = 0; i < length; ++i) { - curStr->getChar(); - } -} - -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() == 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; - } - *x = (Guint)c0; - return gTrue; -} - -GBool JBIG2Stream::readByte(int *x) { - int c0; - - if ((c0 = curStr->getChar()) == EOF) { - return gFalse; - } - *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; - } - *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; - } - *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; - } - *x = ((c0 << 24) | (c1 << 16) | (c2 << 8) | c3); - if (c0 & 0x80) { - *x |= -1 - (int)0xffffffff; - } - return gTrue; -} diff --git a/pdf2swf/xpdf/JBIG2Stream.h b/pdf2swf/xpdf/JBIG2Stream.h deleted file mode 100644 index 44e09db..0000000 --- a/pdf2swf/xpdf/JBIG2Stream.h +++ /dev/null @@ -1,143 +0,0 @@ -//======================================================================== -// -// JBIG2Stream.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef JBIG2STREAM_H -#define JBIG2STREAM_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" -#include "Stream.h" - -class GList; -class JBIG2Segment; -class JBIG2Bitmap; -class JArithmeticDecoder; -class JArithmeticDecoderStats; -class JBIG2HuffmanDecoder; -struct JBIG2HuffmanTable; -class JBIG2MMRDecoder; - -//------------------------------------------------------------------------ - -class JBIG2Stream: public FilterStream { -public: - - JBIG2Stream(Stream *strA, Object *globalsStream); - virtual ~JBIG2Stream(); - virtual StreamKind getKind() { return strJBIG2; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - -private: - - 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); - 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); - - Guint pageW, pageH, curPageH; - Guint pageDefPixel; - JBIG2Bitmap *pageBitmap; - Guint defCombOp; - GList *segments; // [JBIG2Segment] - GList *globalSegments; // [JBIG2Segment] - Stream *curStr; - Guchar *dataPtr; - Guchar *dataEnd; - - 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/pdf2swf/xpdf/JPXStream.cc b/pdf2swf/xpdf/JPXStream.cc deleted file mode 100644 index 336b7ba..0000000 --- a/pdf2swf/xpdf/JPXStream.cc +++ /dev/null @@ -1,2953 +0,0 @@ -//======================================================================== -// -// JPXStream.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "gmem.h" -#include "Error.h" -#include "JArithmeticDecoder.h" -#include "JPXStream.h" - -//~ to do: -// - precincts -// - 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? -// - skip EPH markers (readTilePartData) -// - handle tilePartToEOC in readTilePartData -// - deal with multiple codeword segments (readTilePartData, -// readCodeBlockData) -// - progression orders 2, 3, and 4 -// - in coefficient decoding (readCodeBlockData): -// - termination pattern: terminate after every coding pass -// - error resilience segmentation symbol -// - selective arithmetic coding bypass -// - vertically causal context formation -// - 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) - -// number of bits to the right of the decimal point for the fixed -// point arithmetic used in the IDWT -#define fracBits 16 - -//------------------------------------------------------------------------ - -// 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)) - -//------------------------------------------------------------------------ - -JPXStream::JPXStream(Stream *strA): - FilterStream(strA) -{ - nComps = 0; - bpc = NULL; - width = height = 0; - haveCS = gFalse; - havePalette = gFalse; - haveCompMap = gFalse; - haveChannelDefn = gFalse; - - img.tiles = NULL; - bitBuf = 0; - bitBufLen = 0; - bitBufSkip = gFalse; - byteCount = 0; -} - -JPXStream::~JPXStream() { - JPXTile *tile; - JPXTileComp *tileComp; - JPXResLevel *resLevel; - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - Guint comp, i, k, r, pre, sb; - - gfree(bpc); - if (havePalette) { - gfree(palette.bpc); - gfree(palette.c); - } - if (haveCompMap) { - gfree(compMap.comp); - gfree(compMap.type); - gfree(compMap.pComp); - } - if (haveChannelDefn) { - gfree(channelDefn.idx); - gfree(channelDefn.type); - gfree(channelDefn.assoc); - } - - 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 < 1; ++pre) { - precinct = &resLevel->precincts[pre]; - if (precinct->subbands) { - for (sb = 0; sb < (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->coeffs); - if (cb->arithDecoder) { - delete cb->arithDecoder; - } - if (cb->stats) { - delete cb->stats; - } - } - gfree(subband->cbs); - } - } - gfree(precinct->subbands); - } - } - gfree(img.tiles[i].tileComps[comp].resLevels[r].precincts); - } - } - gfree(img.tiles[i].tileComps[comp].resLevels); - } - } - gfree(img.tiles[i].tileComps); - } - } - gfree(img.tiles); - } - delete str; -} - -void JPXStream::reset() { - str->reset(); - if (readBoxes()) { - curY = img.yOffset; - } else { - // readBoxes reported an error, so we go immediately to EOF - curY = img.ySize; - } - curX = img.xOffset; - curComp = 0; - readBufLen = 0; -} - -int JPXStream::getChar() { - int c; - - 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 (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; - - do { - if (curY >= img.ySize) { - return; - } - tileIdx = ((curY - img.yTileOffset) / img.yTileSize) * img.nXTiles - + (curX - 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 = jpxCeilDiv((curX - img.xTileOffset) % img.xTileSize, tileComp->hSep); - ty = jpxCeilDiv((curY - img.yTileOffset) % img.yTileSize, tileComp->vSep); - pix = (int)tileComp->data[ty * (tileComp->x1 - tileComp->x0) + tx]; - pixBits = tileComp->prec; -#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 = - pixBits = palette.bpc[curComp]; - } - if (++curComp == (Guint)(havePalette ? palette.nComps : img.nComps)) { -#endif - curComp = 0; - if (++curX == img.xSize) { - curX = img.xOffset; - ++curY; - } - } - if (pixBits == 8) { - readBuf = (readBuf << 8) | (pix & 0xff); - } else { - readBuf = (readBuf << pixBits) | (pix & ((1 << pixBits) - 1)); - } - readBufLen += pixBits; - } while (readBufLen < 8); -} - -GString *JPXStream::getPSFilter(int psLevel, char *indent) { - 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, i; - int csMeth, csPrec, csPrec1, dummy2; - StreamColorSpaceMode csMode1; - GBool haveBPC, haveCSMode; - - csPrec = 0; // make gcc happy - haveBPC = haveCSMode = gFalse; - str->reset(); - if (str->lookChar() == 0xff) { - getImageParams2(bitsPerComponent, csMode); - } else { - while (readBoxHdr(&boxType, &boxLen, &dataLen)) { - if (boxType == 0x6a703268) { // JP2 header - // skip the superbox - } else if (boxType == 0x69686472) { // image header - 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 - 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; - } - for (i = 0; i < dataLen - 7; ++i) { - str->getChar(); - } - } - } else { - for (i = 0; i < dataLen - 3; ++i) { - str->getChar(); - } - } - } - } else if (boxType == 0x6A703263) { // codestream - if (!(haveBPC && haveCSMode)) { - getImageParams2(bitsPerComponent, csMode); - } - break; - } else { - for (i = 0; i < dataLen; ++i) { - str->getChar(); - } - } - } - } - str->close(); -} - -// Get image parameters from the codestream. -void JPXStream::getImageParams2(int *bitsPerComponent, - StreamColorSpaceMode *csMode) { - int segType; - Guint segLen, nComps1, bpc1, dummy, i; - - while (readMarkerHdr(&segType, &segLen)) { - if (segType == 0x51) { // SIZ - image and tile size - 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 { - if (segLen > 2) { - for (i = 0; i < segLen - 2; ++i) { - str->getChar(); - } - } - } - } -} - -GBool JPXStream::readBoxes() { - Guint boxType, boxLen, dataLen; - Guint bpc1, compression, unknownColorspace, ipr; - Guint i, j; - - haveImgHdr = 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 (str->lookChar() == 0xff) { - error(getPos(), "Naked JPEG 2000 codestream, missing JP2/JPX wrapper"); - readCodestream(0); - 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 gTrue; - } - - 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 - break; - case 0x69686472: // image header - if (!readULong(&height) || - !readULong(&width) || - !readUWord(&nComps) || - !readUByte(&bpc1) || - !readUByte(&compression) || - !readUByte(&unknownColorspace) || - !readUByte(&ipr)) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - if (compression != 7) { - error(getPos(), "Unknown compression type in JPX stream"); - return gFalse; - } - bpc = (Guint *)gmallocn(nComps, sizeof(Guint)); - for (i = 0; i < nComps; ++i) { - bpc[i] = bpc1; - } - haveImgHdr = gTrue; - break; - case 0x62706363: // bits per component - if (!haveImgHdr) { - error(getPos(), "Found bits per component box before image header box in JPX stream"); - return gFalse; - } - if (dataLen != nComps) { - error(getPos(), "Invalid bits per component box in JPX stream"); - return gFalse; - } - for (i = 0; i < nComps; ++i) { - if (!readUByte(&bpc[i])) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - break; - case 0x636F6C72: // color specification - if (!readColorSpecBox(dataLen)) { - return gFalse; - } - break; - case 0x70636c72: // palette - if (!readUWord(&palette.nEntries) || - !readUByte(&palette.nComps)) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - 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(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - ++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(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - } - havePalette = gTrue; - break; - case 0x636d6170: // component mapping - 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(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - haveCompMap = gTrue; - break; - case 0x63646566: // channel definition - if (!readUWord(&channelDefn.nChannels)) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - 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(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - haveChannelDefn = gTrue; - break; - case 0x6A703263: // contiguous codestream - if (!bpc) { - error(getPos(), "JPX stream is missing the image header box"); - } - if (!haveCS) { - error(getPos(), "JPX stream has no supported color spec"); - } - if (!readCodestream(dataLen)) { - return gFalse; - } - break; - default: - for (i = 0; i < dataLen; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Unexpected EOF in JPX stream"); - return gFalse; - } - } - break; - } - } - return gTrue; -} - -GBool JPXStream::readColorSpecBox(Guint dataLen) { - JPXColorSpec newCS; - Guint csApprox, csEnum; - Guint i; - GBool ok; - - ok = gFalse; - if (!readUByte(&newCS.meth) || - !readByte(&newCS.prec) || - !readUByte(&csApprox)) { - goto err; - } - switch (newCS.meth) { - case 1: // enumerated colorspace - 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 - 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) - for (i = 0; i < dataLen - 3; ++i) { - if (str->getChar() == EOF) { - goto err; - } - } - break; - } - - if (ok && (!haveCS || newCS.prec > cs.prec)) { - cs = newCS; - haveCS = gTrue; - } - - return gTrue; - - err: - error(getPos(), "Error in JPX color spec"); - return gFalse; -} - -GBool JPXStream::readCodestream(Guint len) { - JPXTile *tile; - JPXTileComp *tileComp; - int segType; - GBool haveSIZ, haveCOD, haveQCD, haveSOT; - Guint precinctSize, style; - Guint segLen, capabilities, nTiles, comp, i, j, r; - - //----- main header - haveSIZ = haveCOD = haveQCD = haveSOT = gFalse; - do { - if (!readMarkerHdr(&segType, &segLen)) { - error(getPos(), "Error in JPX codestream"); - return gFalse; - } - switch (segType) { - case 0x4f: // SOC - start of codestream - // marker only - break; - case 0x51: // SIZ - image and tile size - 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(getPos(), "Error in JPX SIZ marker segment"); - return gFalse; - } - if (haveImgHdr && img.nComps != nComps) { - error(getPos(), "Different number of components in JPX SIZ marker segment"); - return gFalse; - } - img.nXTiles = (img.xSize - img.xTileOffset + img.xTileSize - 1) - / img.xTileSize; - img.nYTiles = (img.ySize - img.yTileOffset + img.yTileSize - 1) - / img.yTileSize; - nTiles = img.nXTiles * img.nYTiles; - // check for overflow before allocating memory - if (nTiles == 0 || nTiles / img.nXTiles != img.nYTiles) { - error(getPos(), "Bad tile count in JPX SIZ marker segment"); - return gFalse; - } - img.tiles = (JPXTile *)gmallocn(nTiles, sizeof(JPXTile)); - 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(getPos(), "Error in JPX SIZ marker segment"); - return gFalse; - } - 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 - if (!readUByte(&img.tiles[0].tileComps[0].style) || - !readUByte(&img.tiles[0].progOrder) || - !readUWord(&img.tiles[0].nLayers) || - !readUByte(&img.tiles[0].multiComp) || - !readUByte(&img.tiles[0].tileComps[0].nDecompLevels) || - !readUByte(&img.tiles[0].tileComps[0].codeBlockW) || - !readUByte(&img.tiles[0].tileComps[0].codeBlockH) || - !readUByte(&img.tiles[0].tileComps[0].codeBlockStyle) || - !readUByte(&img.tiles[0].tileComps[0].transform)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[0].tileComps[0].codeBlockW += 2; - img.tiles[0].tileComps[0].codeBlockH += 2; - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - if (i != 0) { - img.tiles[i].progOrder = img.tiles[0].progOrder; - img.tiles[i].nLayers = img.tiles[0].nLayers; - img.tiles[i].multiComp = img.tiles[0].multiComp; - } - for (comp = 0; comp < img.nComps; ++comp) { - if (!(i == 0 && comp == 0)) { - img.tiles[i].tileComps[comp].style = - img.tiles[0].tileComps[0].style; - img.tiles[i].tileComps[comp].nDecompLevels = - img.tiles[0].tileComps[0].nDecompLevels; - img.tiles[i].tileComps[comp].codeBlockW = - img.tiles[0].tileComps[0].codeBlockW; - img.tiles[i].tileComps[comp].codeBlockH = - img.tiles[0].tileComps[0].codeBlockH; - img.tiles[i].tileComps[comp].codeBlockStyle = - img.tiles[0].tileComps[0].codeBlockStyle; - img.tiles[i].tileComps[comp].transform = - img.tiles[0].tileComps[0].transform; - } - img.tiles[i].tileComps[comp].resLevels = - (JPXResLevel *)gmallocn( - (img.tiles[i].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { - img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; - } - } - } - for (r = 0; r <= img.tiles[0].tileComps[0].nDecompLevels; ++r) { - if (img.tiles[0].tileComps[0].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - 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 <= img.tiles[i].tileComps[comp].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 - if (!haveCOD) { - error(getPos(), "JPX COC marker segment before COD segment"); - return gFalse; - } - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&style) || - !readUByte(&img.tiles[0].tileComps[comp].nDecompLevels) || - !readUByte(&img.tiles[0].tileComps[comp].codeBlockW) || - !readUByte(&img.tiles[0].tileComps[comp].codeBlockH) || - !readUByte(&img.tiles[0].tileComps[comp].codeBlockStyle) || - !readUByte(&img.tiles[0].tileComps[comp].transform)) { - error(getPos(), "Error in JPX COC marker segment"); - return gFalse; - } - img.tiles[0].tileComps[comp].style = - (img.tiles[0].tileComps[comp].style & ~1) | (style & 1); - img.tiles[0].tileComps[comp].codeBlockW += 2; - img.tiles[0].tileComps[comp].codeBlockH += 2; - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - if (i != 0) { - img.tiles[i].tileComps[comp].style = - img.tiles[0].tileComps[comp].style; - img.tiles[i].tileComps[comp].nDecompLevels = - img.tiles[0].tileComps[comp].nDecompLevels; - img.tiles[i].tileComps[comp].codeBlockW = - img.tiles[0].tileComps[comp].codeBlockW; - img.tiles[i].tileComps[comp].codeBlockH = - img.tiles[0].tileComps[comp].codeBlockH; - img.tiles[i].tileComps[comp].codeBlockStyle = - img.tiles[0].tileComps[comp].codeBlockStyle; - img.tiles[i].tileComps[comp].transform = - img.tiles[0].tileComps[comp].transform; - } - img.tiles[i].tileComps[comp].resLevels = - (JPXResLevel *)greallocn( - img.tiles[i].tileComps[comp].resLevels, - (img.tiles[i].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; r <= img.tiles[i].tileComps[comp].nDecompLevels; ++r) { - img.tiles[i].tileComps[comp].resLevels[r].precincts = NULL; - } - } - for (r = 0; r <= img.tiles[0].tileComps[comp].nDecompLevels; ++r) { - if (img.tiles[0].tileComps[comp].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - 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 - if (!readUByte(&img.tiles[0].tileComps[0].quantStyle)) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x00) { - 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } else if ((img.tiles[0].tileComps[0].quantStyle & 0x1f) == 0x02) { - 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - 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 - if (!haveQCD) { - error(getPos(), "JPX QCC marker segment before QCD segment"); - return gFalse; - } - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&img.tiles[0].tileComps[comp].quantStyle)) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x00) { - 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(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } - } 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(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } else if ((img.tiles[0].tileComps[comp].quantStyle & 0x1f) == 0x02) { - 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - 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 -#if 1 //~ ROI is unimplemented - fprintf(stderr, "RGN\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#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(getPos(), "Error in JPX RGN marker segment"); - return gFalse; - } -#endif - break; - case 0x5f: // POC - progression order change -#if 1 //~ progression order changes are unimplemented - fprintf(stderr, "POC\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#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(getPos(), "Error in JPX POC marker segment"); - return gFalse; - } - } -#endif - break; - case 0x60: // PPM - packed packet headers, main header -#if 1 //~ packed packet headers are unimplemented - fprintf(stderr, "PPM\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM marker segment"); - return gFalse; - } - } -#endif - break; - case 0x55: // TLM - tile-part lengths - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX TLM marker segment"); - return gFalse; - } - } - break; - case 0x57: // PLM - packet length, main header - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PLM marker segment"); - return gFalse; - } - } - break; - case 0x63: // CRG - component registration - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX CRG marker segment"); - return gFalse; - } - } - break; - case 0x64: // COM - comment - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX COM marker segment"); - return gFalse; - } - } - break; - case 0x90: // SOT - start of tile - haveSOT = gTrue; - break; - default: - error(getPos(), "Unknown marker segment %02x in JPX stream", segType); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - break; - } - } - break; - } - } while (!haveSOT); - - if (!haveSIZ) { - error(getPos(), "Missing SIZ marker segment in JPX stream"); - return gFalse; - } - if (!haveCOD) { - error(getPos(), "Missing COD marker segment in JPX stream"); - return gFalse; - } - if (!haveQCD) { - error(getPos(), "Missing QCD marker segment in JPX stream"); - return gFalse; - } - - //----- read the tile-parts - while (1) { - if (!readTilePart()) { - return gFalse; - } - if (!readMarkerHdr(&segType, &segLen)) { - error(getPos(), "Error in JPX codestream"); - return gFalse; - } - if (segType != 0x90) { // SOT - start of tile - break; - } - } - - if (segType != 0xd9) { // EOC - end of codestream - error(getPos(), "Missing EOC marker in JPX codestream"); - return gFalse; - } - - //----- finish decoding the image - for (i = 0; i < img.nXTiles * img.nYTiles; ++i) { - tile = &img.tiles[i]; - for (comp = 0; comp < img.nComps; ++comp) { - tileComp = &tile->tileComps[comp]; - inverseTransform(tileComp); - } - if (!inverseMultiCompAndDC(tile)) { - return gFalse; - } - } - - //~ can free memory below tileComps here, and also tileComp.buf - - return gTrue; -} - -GBool JPXStream::readTilePart() { - JPXTile *tile; - JPXTileComp *tileComp; - JPXResLevel *resLevel; - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - GBool haveSOD; - Guint tileIdx, tilePartLen, tilePartIdx, nTileParts; - GBool tilePartToEOC; - Guint precinctSize, style; - Guint n, nSBs, nx, ny, sbx0, sby0, comp, segLen; - Guint i, j, k, cbX, cbY, r, pre, sb, cbi; - int segType, level; - - // process the SOT marker segment - if (!readUWord(&tileIdx) || - !readULong(&tilePartLen) || - !readUByte(&tilePartIdx) || - !readUByte(&nTileParts)) { - error(getPos(), "Error in JPX SOT marker segment"); - return gFalse; - } - - if (tileIdx >= img.nXTiles * img.nYTiles) { - error(getPos(), "Weird tile index in JPX stream"); - return gFalse; - } - - tilePartToEOC = tilePartLen == 0; - tilePartLen -= 12; // subtract size of SOT segment - - haveSOD = gFalse; - do { - if (!readMarkerHdr(&segType, &segLen)) { - error(getPos(), "Error in JPX tile-part codestream"); - return gFalse; - } - tilePartLen -= 2 + segLen; - switch (segType) { - case 0x52: // COD - coding style default - if (!readUByte(&img.tiles[tileIdx].tileComps[0].style) || - !readUByte(&img.tiles[tileIdx].progOrder) || - !readUWord(&img.tiles[tileIdx].nLayers) || - !readUByte(&img.tiles[tileIdx].multiComp) || - !readUByte(&img.tiles[tileIdx].tileComps[0].nDecompLevels) || - !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockW) || - !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockH) || - !readUByte(&img.tiles[tileIdx].tileComps[0].codeBlockStyle) || - !readUByte(&img.tiles[tileIdx].tileComps[0].transform)) { - error(getPos(), "Error in JPX COD marker segment"); - return gFalse; - } - img.tiles[tileIdx].tileComps[0].codeBlockW += 2; - img.tiles[tileIdx].tileComps[0].codeBlockH += 2; - for (comp = 0; comp < img.nComps; ++comp) { - if (comp != 0) { - img.tiles[tileIdx].tileComps[comp].style = - img.tiles[tileIdx].tileComps[0].style; - img.tiles[tileIdx].tileComps[comp].nDecompLevels = - img.tiles[tileIdx].tileComps[0].nDecompLevels; - img.tiles[tileIdx].tileComps[comp].codeBlockW = - img.tiles[tileIdx].tileComps[0].codeBlockW; - img.tiles[tileIdx].tileComps[comp].codeBlockH = - img.tiles[tileIdx].tileComps[0].codeBlockH; - img.tiles[tileIdx].tileComps[comp].codeBlockStyle = - img.tiles[tileIdx].tileComps[0].codeBlockStyle; - img.tiles[tileIdx].tileComps[comp].transform = - img.tiles[tileIdx].tileComps[0].transform; - } - img.tiles[tileIdx].tileComps[comp].resLevels = - (JPXResLevel *)greallocn( - img.tiles[tileIdx].tileComps[comp].resLevels, - (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; - r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; - ++r) { - img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; - } - } - for (r = 0; r <= img.tiles[tileIdx].tileComps[0].nDecompLevels; ++r) { - if (img.tiles[tileIdx].tileComps[0].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - 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 <= img.tiles[tileIdx].tileComps[comp].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 - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&style) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].nDecompLevels) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockW) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockH) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].codeBlockStyle) || - !readUByte(&img.tiles[tileIdx].tileComps[comp].transform)) { - error(getPos(), "Error in JPX COC marker segment"); - return gFalse; - } - img.tiles[tileIdx].tileComps[comp].style = - (img.tiles[tileIdx].tileComps[comp].style & ~1) | (style & 1); - img.tiles[tileIdx].tileComps[comp].codeBlockW += 2; - img.tiles[tileIdx].tileComps[comp].codeBlockH += 2; - img.tiles[tileIdx].tileComps[comp].resLevels = - (JPXResLevel *)greallocn( - img.tiles[tileIdx].tileComps[comp].resLevels, - (img.tiles[tileIdx].tileComps[comp].nDecompLevels + 1), - sizeof(JPXResLevel)); - for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) { - img.tiles[tileIdx].tileComps[comp].resLevels[r].precincts = NULL; - } - for (r = 0; r <= img.tiles[tileIdx].tileComps[comp].nDecompLevels; ++r) { - if (img.tiles[tileIdx].tileComps[comp].style & 0x01) { - if (!readUByte(&precinctSize)) { - error(getPos(), "Error in JPX COD marker segment"); - 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 - if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantStyle)) { - error(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x00) { - img.tiles[tileIdx].tileComps[0].nQuantSteps = - segLen - 3; - img.tiles[tileIdx].tileComps[0].quantSteps = - (Guint *)greallocn(img.tiles[tileIdx].tileComps[0].quantSteps, - img.tiles[tileIdx].tileComps[0].nQuantSteps, - sizeof(Guint)); - for (i = 0; i < img.tiles[tileIdx].tileComps[0].nQuantSteps; ++i) { - if (!readUByte(&img.tiles[tileIdx].tileComps[0].quantSteps[i])) { - error(getPos(), "Error in JPX QCD marker segment"); - 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } else if ((img.tiles[tileIdx].tileComps[0].quantStyle & 0x1f) == 0x02) { - 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(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 - if ((img.nComps > 256 && !readUWord(&comp)) || - (img.nComps <= 256 && !readUByte(&comp)) || - comp >= img.nComps || - !readUByte(&img.tiles[tileIdx].tileComps[comp].quantStyle)) { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) == 0x00) { - 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(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(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - } else if ((img.tiles[tileIdx].tileComps[comp].quantStyle & 0x1f) - == 0x02) { - 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(getPos(), "Error in JPX QCD marker segment"); - return gFalse; - } - } - } else { - error(getPos(), "Error in JPX QCC marker segment"); - return gFalse; - } - break; - case 0x5e: // RGN - region of interest -#if 1 //~ ROI is unimplemented - fprintf(stderr, "RGN\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM 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(getPos(), "Error in JPX RGN marker segment"); - return gFalse; - } -#endif - break; - case 0x5f: // POC - progression order change -#if 1 //~ progression order changes are unimplemented - fprintf(stderr, "POC\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPM 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(getPos(), "Error in JPX POC marker segment"); - return gFalse; - } - } -#endif - break; - case 0x61: // PPT - packed packet headers, tile-part hdr -#if 1 //~ packed packet headers are unimplemented - fprintf(stderr, "PPT\n"); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PPT marker segment"); - return gFalse; - } - } -#endif - case 0x58: // PLT - packet length, tile-part header - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX PLT marker segment"); - return gFalse; - } - } - break; - case 0x64: // COM - comment - // skipped - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - error(getPos(), "Error in JPX COM marker segment"); - return gFalse; - } - } - break; - case 0x93: // SOD - start of data - haveSOD = gTrue; - break; - default: - error(getPos(), "Unknown marker segment %02x in JPX tile-part stream", - segType); - for (i = 0; i < segLen - 2; ++i) { - if (str->getChar() == EOF) { - break; - } - } - break; - } - } while (!haveSOD); - - //----- 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->maxNDecompLevels = 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->hSep); - tileComp->x1 = jpxCeilDiv(tile->x1, tileComp->hSep); - tileComp->y1 = jpxCeilDiv(tile->y1, tileComp->hSep); - tileComp->cbW = 1 << tileComp->codeBlockW; - tileComp->cbH = 1 << tileComp->codeBlockH; - tileComp->data = (int *)gmallocn((tileComp->x1 - tileComp->x0) * - (tileComp->y1 - tileComp->y0), - 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]; - k = r == 0 ? tileComp->nDecompLevels - : tileComp->nDecompLevels - r + 1; - resLevel->x0 = jpxCeilDivPow2(tileComp->x0, k); - resLevel->y0 = jpxCeilDivPow2(tileComp->y0, k); - resLevel->x1 = jpxCeilDivPow2(tileComp->x1, k); - resLevel->y1 = jpxCeilDivPow2(tileComp->y1, k); - if (r == 0) { - resLevel->bx0[0] = resLevel->x0; - resLevel->by0[0] = resLevel->y0; - resLevel->bx1[0] = resLevel->x1; - resLevel->by1[0] = resLevel->y1; - } else { - resLevel->bx0[0] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k); - resLevel->by0[0] = resLevel->y0; - resLevel->bx1[0] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k); - resLevel->by1[0] = resLevel->y1; - resLevel->bx0[1] = resLevel->x0; - resLevel->by0[1] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k); - resLevel->bx1[1] = resLevel->x1; - resLevel->by1[1] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k); - resLevel->bx0[2] = jpxCeilDivPow2(tileComp->x0 - (1 << (k-1)), k); - resLevel->by0[2] = jpxCeilDivPow2(tileComp->y0 - (1 << (k-1)), k); - resLevel->bx1[2] = jpxCeilDivPow2(tileComp->x1 - (1 << (k-1)), k); - resLevel->by1[2] = jpxCeilDivPow2(tileComp->y1 - (1 << (k-1)), k); - } - resLevel->precincts = (JPXPrecinct *)gmallocn(1, sizeof(JPXPrecinct)); - for (pre = 0; pre < 1; ++pre) { - precinct = &resLevel->precincts[pre]; - precinct->x0 = resLevel->x0; - precinct->y0 = resLevel->y0; - precinct->x1 = resLevel->x1; - precinct->y1 = resLevel->y1; - nSBs = r == 0 ? 1 : 3; - precinct->subbands = - (JPXSubband *)gmallocn(nSBs, sizeof(JPXSubband)); - for (sb = 0; sb < nSBs; ++sb) { - subband = &precinct->subbands[sb]; - subband->x0 = resLevel->bx0[sb]; - subband->y0 = resLevel->by0[sb]; - subband->x1 = resLevel->bx1[sb]; - subband->y1 = resLevel->by1[sb]; - subband->nXCBs = jpxCeilDivPow2(subband->x1, - tileComp->codeBlockW) - - jpxFloorDivPow2(subband->x0, - tileComp->codeBlockW); - subband->nYCBs = jpxCeilDivPow2(subband->y1, - tileComp->codeBlockH) - - jpxFloorDivPow2(subband->y0, - tileComp->codeBlockH); - 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)); - sbx0 = jpxFloorDivPow2(subband->x0, tileComp->codeBlockW); - sby0 = jpxFloorDivPow2(subband->y0, tileComp->codeBlockH); - cb = subband->cbs; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - cb->x0 = (sbx0 + cbX) << tileComp->codeBlockW; - cb->x1 = cb->x0 + tileComp->cbW; - if (subband->x0 > cb->x0) { - cb->x0 = subband->x0; - } - if (subband->x1 < cb->x1) { - cb->x1 = subband->x1; - } - cb->y0 = (sby0 + cbY) << tileComp->codeBlockH; - cb->y1 = cb->y0 + tileComp->cbH; - if (subband->y0 > cb->y0) { - cb->y0 = subband->y0; - } - if (subband->y1 < cb->y1) { - cb->y1 = subband->y1; - } - cb->seen = gFalse; - cb->lBlock = 3; - cb->nextPass = jpxPassCleanup; - cb->nZeroBitPlanes = 0; - cb->coeffs = - (JPXCoeff *)gmallocn((1 << (tileComp->codeBlockW - + tileComp->codeBlockH)), - sizeof(JPXCoeff)); - for (cbi = 0; - cbi < (Guint)(1 << (tileComp->codeBlockW - + tileComp->codeBlockH)); - ++cbi) { - cb->coeffs[cbi].flags = 0; - cb->coeffs[cbi].len = 0; - cb->coeffs[cbi].mag = 0; - } - cb->arithDecoder = NULL; - cb->stats = NULL; - ++cb; - } - } - } - } - } - } - } - - 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 (tilePartToEOC) { - //~ peek for an EOC marker - } else if (tilePartLen == 0) { - break; - } - - tileComp = &tile->tileComps[tile->comp]; - resLevel = &tileComp->resLevels[tile->res]; - precinct = &resLevel->precincts[tile->precinct]; - - //----- packet header - - // zero-length flag - if (!readBits(1, &bits)) { - goto err; - } - if (!bits) { - // packet is empty -- clear all code-block inclusion flags - for (sb = 0; sb < (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 < (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) { - cb->included = gFalse; - continue; - } - - // code-block inclusion - if (cb->seen) { - if (!readBits(1, &cb->included)) { - goto err; - } - } else { - 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) { - - // zero bit-plane count - if (!cb->seen) { - 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) { - cb->nCodingPasses = 1; - } else { - if (!readBits(1, &bits)) { - goto err; - } - if (bits == 0) { - cb->nCodingPasses = 2; - } else { - if (!readBits(2, &bits)) { - goto err; - } - if (bits < 3) { - cb->nCodingPasses = 3 + bits; - } else { - if (!readBits(5, &bits)) { - goto err; - } - if (bits < 31) { - cb->nCodingPasses = 6 + bits; - } else { - 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; - } - - // length of compressed data - //~ deal with multiple codeword segments - for (n = cb->lBlock, i = cb->nCodingPasses >> 1; - i; - ++n, i >>= 1) ; - if (!readBits(n, &cb->dataLen)) { - goto err; - } - } - } - } - } - } - tilePartLen -= byteCount; - clearBitBuf(); - - //----- packet data - - for (sb = 0; sb < (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; - } - tilePartLen -= cb->dataLen; - cb->seen = gTrue; - } - } - } - } - - //----- next packet - - switch (tile->progOrder) { - case 0: // layer, resolution level, component, precinct - 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; - } - } - } - break; - case 1: // resolution level, layer, component, precinct - 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; - } - } - } - break; - case 2: // resolution level, precinct, component, layer - //~ this isn't correct -- see B.12.1.3 - if (++tile->layer == tile->nLayers) { - tile->layer = 0; - if (++tile->comp == img.nComps) { - tile->comp = 0; - if (++tile->res == tile->maxNDecompLevels + 1) { - tile->res = 0; - } - } - } - break; - case 3: // precinct, component, resolution level, layer - //~ this isn't correct -- see B.12.1.4 - 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; - } - } - } - break; - case 4: // component, precinct, resolution level, layer - //~ this isn't correct -- see B.12.1.5 - 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; - } - } - } - break; - } - } - - return gTrue; - - err: - error(getPos(), "Error in JPX stream"); - return gFalse; -} - -GBool JPXStream::readCodeBlockData(JPXTileComp *tileComp, - JPXResLevel *resLevel, - JPXPrecinct *precinct, - JPXSubband *subband, - Guint res, Guint sb, - JPXCodeBlock *cb) { - JPXCoeff *coeff0, *coeff1, *coeff; - Guint horiz, vert, diag, all, cx, xorBit; - int horizSign, vertSign; - Guint i, x, y0, y1, y2; - - if (cb->arithDecoder) { - cb->arithDecoder->restart(cb->dataLen); - } else { - cb->arithDecoder = new JArithmeticDecoder(); - cb->arithDecoder->setStream(str, cb->dataLen); - 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) { - switch (cb->nextPass) { - - //----- significance propagation pass - case jpxPassSigProp: - for (y0 = cb->y0, coeff0 = cb->coeffs; - y0 < cb->y1; - y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { - for (x = cb->x0, coeff1 = coeff0; - x < cb->x1; - ++x, ++coeff1) { - for (y1 = 0, coeff = coeff1; - y1 < 4 && y0+y1 < cb->y1; - ++y1, coeff += tileComp->cbW) { - if (!(coeff->flags & jpxCoeffSignificant)) { - horiz = vert = diag = 0; - horizSign = vertSign = 2; - if (x > cb->x0) { - if (coeff[-1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (x < cb->x1 - 1) { - if (coeff[1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (y0+y1 > cb->y0) { - if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - if (y0+y1 < cb->y1 - 1) { - if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; - if (cx != 0) { - if (cb->arithDecoder->decodeBit(cx, cb->stats)) { - coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; - coeff->mag = (coeff->mag << 1) | 1; - cx = signContext[horizSign][vertSign][0]; - xorBit = signContext[horizSign][vertSign][1]; - if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { - coeff->flags |= jpxCoeffSign; - } - } - ++coeff->len; - coeff->flags |= jpxCoeffTouched; - } - } - } - } - } - ++cb->nextPass; - break; - - //----- magnitude refinement pass - case jpxPassMagRef: - for (y0 = cb->y0, coeff0 = cb->coeffs; - y0 < cb->y1; - y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { - for (x = cb->x0, coeff1 = coeff0; - x < cb->x1; - ++x, ++coeff1) { - for (y1 = 0, coeff = coeff1; - y1 < 4 && y0+y1 < cb->y1; - ++y1, coeff += tileComp->cbW) { - if ((coeff->flags & jpxCoeffSignificant) && - !(coeff->flags & jpxCoeffTouched)) { - if (coeff->flags & jpxCoeffFirstMagRef) { - all = 0; - if (x > cb->x0) { - all += (coeff[-1].flags >> jpxCoeffSignificantB) & 1; - if (y0+y1 > cb->y0) { - all += (coeff[-(int)tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - all += (coeff[tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (x < cb->x1 - 1) { - all += (coeff[1].flags >> jpxCoeffSignificantB) & 1; - if (y0+y1 > cb->y0) { - all += (coeff[-(int)tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - all += (coeff[tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (y0+y1 > cb->y0) { - all += (coeff[-(int)tileComp->cbW].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - all += (coeff[tileComp->cbW].flags - >> jpxCoeffSignificantB) & 1; - } - cx = all ? 15 : 14; - } else { - cx = 16; - } - coeff->mag = (coeff->mag << 1) | - cb->arithDecoder->decodeBit(cx, cb->stats); - ++coeff->len; - coeff->flags |= jpxCoeffTouched; - coeff->flags &= ~jpxCoeffFirstMagRef; - } - } - } - } - ++cb->nextPass; - break; - - //----- cleanup pass - case jpxPassCleanup: - for (y0 = cb->y0, coeff0 = cb->coeffs; - y0 < cb->y1; - y0 += 4, coeff0 += 4 << tileComp->codeBlockW) { - for (x = cb->x0, coeff1 = coeff0; - x < cb->x1; - ++x, ++coeff1) { - y1 = 0; - if (y0 + 3 < cb->y1 && - !(coeff1->flags & jpxCoeffTouched) && - !(coeff1[tileComp->cbW].flags & jpxCoeffTouched) && - !(coeff1[2 * tileComp->cbW].flags & jpxCoeffTouched) && - !(coeff1[3 * tileComp->cbW].flags & jpxCoeffTouched) && - (x == cb->x0 || y0 == cb->y0 || - !(coeff1[-(int)tileComp->cbW - 1].flags - & jpxCoeffSignificant)) && - (y0 == cb->y0 || - !(coeff1[-(int)tileComp->cbW].flags - & jpxCoeffSignificant)) && - (x == cb->x1 - 1 || y0 == cb->y0 || - !(coeff1[-(int)tileComp->cbW + 1].flags - & jpxCoeffSignificant)) && - (x == cb->x0 || - (!(coeff1[-1].flags & jpxCoeffSignificant) && - !(coeff1[tileComp->cbW - 1].flags - & jpxCoeffSignificant) && - !(coeff1[2 * tileComp->cbW - 1].flags - & jpxCoeffSignificant) && - !(coeff1[3 * tileComp->cbW - 1].flags - & jpxCoeffSignificant))) && - (x == cb->x1 - 1 || - (!(coeff1[1].flags & jpxCoeffSignificant) && - !(coeff1[tileComp->cbW + 1].flags - & jpxCoeffSignificant) && - !(coeff1[2 * tileComp->cbW + 1].flags - & jpxCoeffSignificant) && - !(coeff1[3 * tileComp->cbW + 1].flags - & jpxCoeffSignificant))) && - (x == cb->x0 || y0+4 == cb->y1 || - !(coeff1[4 * tileComp->cbW - 1].flags & jpxCoeffSignificant)) && - (y0+4 == cb->y1 || - !(coeff1[4 * tileComp->cbW].flags & jpxCoeffSignificant)) && - (x == cb->x1 - 1 || y0+4 == cb->y1 || - !(coeff1[4 * tileComp->cbW + 1].flags - & jpxCoeffSignificant))) { - if (cb->arithDecoder->decodeBit(jpxContextRunLength, cb->stats)) { - y1 = cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats); - y1 = (y1 << 1) | - cb->arithDecoder->decodeBit(jpxContextUniform, cb->stats); - for (y2 = 0, coeff = coeff1; - y2 < y1; - ++y2, coeff += tileComp->cbW) { - ++coeff->len; - } - coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; - coeff->mag = (coeff->mag << 1) | 1; - ++coeff->len; - cx = signContext[2][2][0]; - xorBit = signContext[2][2][1]; - if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { - coeff->flags |= jpxCoeffSign; - } - ++y1; - } else { - for (y1 = 0, coeff = coeff1; - y1 < 4; - ++y1, coeff += tileComp->cbW) { - ++coeff->len; - } - y1 = 4; - } - } - for (coeff = &coeff1[y1 << tileComp->codeBlockW]; - y1 < 4 && y0 + y1 < cb->y1; - ++y1, coeff += tileComp->cbW) { - if (!(coeff->flags & jpxCoeffTouched)) { - horiz = vert = diag = 0; - horizSign = vertSign = 2; - if (x > cb->x0) { - if (coeff[-1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[-1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW - 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (x < cb->x1 - 1) { - if (coeff[1].flags & jpxCoeffSignificant) { - ++horiz; - horizSign += (coeff[1].flags & jpxCoeffSign) ? -1 : 1; - } - if (y0+y1 > cb->y0) { - diag += (coeff[-(int)tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - if (y0+y1 < cb->y1 - 1) { - diag += (coeff[tileComp->cbW + 1].flags - >> jpxCoeffSignificantB) & 1; - } - } - if (y0+y1 > cb->y0) { - if (coeff[-(int)tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[-(int)tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - if (y0+y1 < cb->y1 - 1) { - if (coeff[tileComp->cbW].flags & jpxCoeffSignificant) { - ++vert; - vertSign += (coeff[tileComp->cbW].flags & jpxCoeffSign) - ? -1 : 1; - } - } - cx = sigPropContext[horiz][vert][diag][res == 0 ? 1 : sb]; - if (cb->arithDecoder->decodeBit(cx, cb->stats)) { - coeff->flags |= jpxCoeffSignificant | jpxCoeffFirstMagRef; - coeff->mag = (coeff->mag << 1) | 1; - cx = signContext[horizSign][vertSign][0]; - xorBit = signContext[horizSign][vertSign][1]; - if (cb->arithDecoder->decodeBit(cx, cb->stats) ^ xorBit) { - coeff->flags |= jpxCoeffSign; - } - } - ++coeff->len; - } else { - coeff->flags &= ~jpxCoeffTouched; - } - } - } - } - cb->nextPass = jpxPassSigProp; - break; - } - } - - 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; - JPXCoeff *coeff0, *coeff; - Guint qStyle, guard, eps, shift; - int shift2; - double mu; - int val; - int *dataPtr; - Guint nx0, ny0, nx1, ny1; - Guint r, cbX, cbY, x, y; - - //----- (NL)LL subband (resolution level 0) - - resLevel = &tileComp->resLevels[0]; - precinct = &resLevel->precincts[0]; - subband = &precinct->subbands[0]; - - // i-quant parameters - qStyle = tileComp->quantStyle & 0x1f; - guard = (tileComp->quantStyle >> 5) & 7; - if (qStyle == 0) { - eps = (tileComp->quantSteps[0] >> 3) & 0x1f; - shift = guard + eps - 1; - mu = 0; // make gcc happy - } else { - shift = guard - 1 + tileComp->prec; - mu = (double)(0x800 + (tileComp->quantSteps[0] & 0x7ff)) / 2048.0; - } - if (tileComp->transform == 0) { - shift += fracBits; - } - - // copy (NL)LL into the upper-left corner of the data array, doing - // the fixed point adjustment and dequantization along the way - cb = subband->cbs; - for (cbY = 0; cbY < subband->nYCBs; ++cbY) { - for (cbX = 0; cbX < subband->nXCBs; ++cbX) { - for (y = cb->y0, coeff0 = cb->coeffs; - y < cb->y1; - ++y, coeff0 += tileComp->cbW) { - dataPtr = &tileComp->data[(y - subband->y0) - * (tileComp->x1 - tileComp->x0) - + (cb->x0 - subband->x0)]; - for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) { - val = (int)coeff->mag; - if (val != 0) { - shift2 = shift - (cb->nZeroBitPlanes + coeff->len); - if (shift2 > 0) { - val = (val << shift2) + (1 << (shift2 - 1)); - } else { - val >>= -shift2; - } - if (qStyle == 0) { - if (tileComp->transform == 0) { - val &= -1 << fracBits; - } - } else { - val = (int)((double)val * mu); - } - if (coeff->flags & jpxCoeffSign) { - val = -val; - } - } - *dataPtr++ = val; - } - } - ++cb; - } - } - - //----- IDWT for each level - - for (r = 1; r <= tileComp->nDecompLevels; ++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 - if (r == tileComp->nDecompLevels) { - nx0 = tileComp->x0; - ny0 = tileComp->y0; - nx1 = tileComp->x1; - ny1 = tileComp->y1; - } else { - nx0 = tileComp->resLevels[r+1].x0; - ny0 = tileComp->resLevels[r+1].y0; - nx1 = tileComp->resLevels[r+1].x1; - ny1 = tileComp->resLevels[r+1].y1; - } - inverseTransformLevel(tileComp, r, resLevel, nx0, ny0, nx1, ny1); - } -} - -// Do one level of the inverse transform: -// - take (n)LL from the tile-component data array -// - take (n)HL/LH/HH from -// - leave the resulting (n-1)LL in the tile-component data array -void JPXStream::inverseTransformLevel(JPXTileComp *tileComp, - Guint r, JPXResLevel *resLevel, - Guint nx0, Guint ny0, - Guint nx1, Guint ny1) { - JPXPrecinct *precinct; - JPXSubband *subband; - JPXCodeBlock *cb; - JPXCoeff *coeff0, *coeff; - Guint qStyle, guard, eps, shift, t; - int shift2; - double mu; - int val; - int *dataPtr; - Guint xo, yo; - Guint x, y, sb, cbX, cbY; - int xx, yy; - - //----- interleave - - // spread out LL - for (yy = resLevel->y1 - 1; yy >= (int)resLevel->y0; --yy) { - for (xx = resLevel->x1 - 1; xx >= (int)resLevel->x0; --xx) { - tileComp->data[(2 * yy - ny0) * (tileComp->x1 - tileComp->x0) - + (2 * xx - nx0)] = - tileComp->data[(yy - resLevel->y0) * (tileComp->x1 - tileComp->x0) - + (xx - resLevel->x0)]; - } - } - - // i-quant parameters - qStyle = tileComp->quantStyle & 0x1f; - guard = (tileComp->quantStyle >> 5) & 7; - - // interleave HL/LH/HH - precinct = &resLevel->precincts[0]; - for (sb = 0; sb < 3; ++sb) { - - // i-quant parameters - if (qStyle == 0) { - eps = (tileComp->quantSteps[3*r - 2 + sb] >> 3) & 0x1f; - shift = guard + eps - 1; - mu = 0; // make gcc happy - } else { - shift = guard + tileComp->prec; - if (sb == 2) { - ++shift; - } - t = tileComp->quantSteps[qStyle == 1 ? 0 : (3*r - 2 + sb)]; - mu = (double)(0x800 + (t & 0x7ff)) / 2048.0; - } - if (tileComp->transform == 0) { - shift += fracBits; - } - - // copy the subband coefficients into the data array, doing the - // fixed point adjustment and dequantization along the way - xo = (sb & 1) ? 0 : 1; - yo = (sb > 0) ? 1 : 0; - 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; - y < cb->y1; - ++y, coeff0 += tileComp->cbW) { - dataPtr = &tileComp->data[(2 * y + yo - ny0) - * (tileComp->x1 - tileComp->x0) - + (2 * cb->x0 + xo - nx0)]; - for (x = cb->x0, coeff = coeff0; x < cb->x1; ++x, ++coeff) { - val = (int)coeff->mag; - if (val != 0) { - shift2 = shift - (cb->nZeroBitPlanes + coeff->len); - if (shift2 > 0) { - val = (val << shift2) + (1 << (shift2 - 1)); - } else { - val >>= -shift2; - } - if (qStyle == 0) { - if (tileComp->transform == 0) { - val &= -1 << fracBits; - } - } else { - val = (int)((double)val * mu); - } - if (coeff->flags & jpxCoeffSign) { - val = -val; - } - } - *dataPtr = val; - dataPtr += 2; - } - } - ++cb; - } - } - } - - //----- horizontal (row) transforms - dataPtr = tileComp->data; - for (y = 0; y < ny1 - ny0; ++y) { - inverseTransform1D(tileComp, dataPtr, 1, nx0, nx1); - dataPtr += tileComp->x1 - tileComp->x0; - } - - //----- vertical (column) transforms - dataPtr = tileComp->data; - for (x = 0; x < nx1 - nx0; ++x) { - inverseTransform1D(tileComp, dataPtr, - tileComp->x1 - tileComp->x0, ny0, ny1); - ++dataPtr; - } -} - -void JPXStream::inverseTransform1D(JPXTileComp *tileComp, - int *data, Guint stride, - Guint i0, Guint i1) { - int *buf; - Guint offset, end, i; - - //----- special case for length = 1 - if (i1 - i0 == 1) { - if (i0 & 1) { - *data >>= 1; - } - - } else { - - // choose an offset: this makes even buf[] indexes correspond to - // odd values of i, and vice versa - offset = 3 + (i0 & 1); - end = offset + i1 - i0; - - //----- gather - buf = tileComp->buf; - for (i = 0; i < i1 - i0; ++i) { - buf[offset + i] = data[i * stride]; - } - - //----- extend right - buf[end] = buf[end - 2]; - if (i1 - i0 == 2) { - buf[end+1] = buf[offset + 1]; - buf[end+2] = buf[offset]; - buf[end+3] = buf[offset + 1]; - } else { - buf[end+1] = buf[end - 3]; - if (i1 - i0 == 3) { - buf[end+2] = buf[offset + 1]; - buf[end+3] = buf[offset + 2]; - } else { - buf[end+2] = buf[end - 4]; - if (i1 - i0 == 4) { - buf[end+3] = buf[offset + 1]; - } else { - buf[end+3] = buf[end - 5]; - } - } - } - - //----- extend left - buf[offset - 1] = buf[offset + 1]; - buf[offset - 2] = buf[offset + 2]; - buf[offset - 3] = buf[offset + 3]; - if (offset == 4) { - buf[0] = buf[offset + 4]; - } - - //----- 9-7 irreversible filter - - if (tileComp->transform == 0) { - // step 1 (even) - for (i = 1; i <= end + 2; i += 2) { - buf[i] = (int)(idwtKappa * buf[i]); - } - // step 2 (odd) - for (i = 0; i <= end + 3; i += 2) { - buf[i] = (int)(idwtIKappa * buf[i]); - } - // step 3 (even) - for (i = 1; i <= end + 2; i += 2) { - buf[i] = (int)(buf[i] - idwtDelta * (buf[i-1] + buf[i+1])); - } - // step 4 (odd) - for (i = 2; i <= end + 1; i += 2) { - buf[i] = (int)(buf[i] - idwtGamma * (buf[i-1] + buf[i+1])); - } - // step 5 (even) - for (i = 3; i <= end; i += 2) { - buf[i] = (int)(buf[i] - idwtBeta * (buf[i-1] + buf[i+1])); - } - // step 6 (odd) - for (i = 4; i <= end - 1; i += 2) { - buf[i] = (int)(buf[i] - idwtAlpha * (buf[i-1] + buf[i+1])); - } - - //----- 5-3 reversible filter - - } else { - // step 1 (even) - for (i = 3; i <= end; i += 2) { - buf[i] -= (buf[i-1] + buf[i+1] + 2) >> 2; - } - // step 2 (odd) - for (i = 4; i < end; i += 2) { - buf[i] += (buf[i-1] + buf[i+1]) >> 1; - } - } - - //----- scatter - for (i = 0; i < i1 - i0; ++i) { - data[i * stride] = buf[offset + i]; - } - } -} - -// 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) { - 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) { - j = 0; - for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { - for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { - 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 { - j = 0; - for (y = 0; y < tile->tileComps[0].y1 - tile->tileComps[0].y0; ++y) { - for (x = 0; x < tile->tileComps[0].x1 - tile->tileComps[0].x0; ++x) { - 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) { - minVal = -(1 << (tileComp->prec - 1)); - maxVal = (1 << (tileComp->prec - 1)) - 1; - dataPtr = tileComp->data; - for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { - for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { - coeff = *dataPtr; - if (tileComp->transform == 0) { - coeff >>= fracBits; - } - if (coeff < minVal) { - coeff = minVal; - } else if (coeff > maxVal) { - coeff = maxVal; - } - *dataPtr++ = coeff; - } - } - - // unsigned: inverse DC level shift and clip - } else { - maxVal = (1 << tileComp->prec) - 1; - zeroVal = 1 << (tileComp->prec - 1); - dataPtr = tileComp->data; - for (y = 0; y < tileComp->y1 - tileComp->y0; ++y) { - for (x = 0; x < tileComp->x1 - tileComp->x0; ++x) { - coeff = *dataPtr; - if (tileComp->transform == 0) { - coeff >>= fracBits; - } - coeff += zeroVal; - if (coeff < 0) { - coeff = 0; - } else if (coeff > maxVal) { - 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(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 = str->getChar()) == EOF) { - return gFalse; - } - } while (c != 0xff); - do { - if ((c = str->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 = str->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)c0; - return gTrue; -} - -GBool JPXStream::readByte(int *x) { - int c0; - - if ((c0 = str->getChar()) == EOF) { - return gFalse; - } - *x = c0; - if (c0 & 0x80) { - *x |= -1 - 0xff; - } - return gTrue; -} - -GBool JPXStream::readUWord(Guint *x) { - int c0, c1; - - if ((c0 = str->getChar()) == EOF || - (c1 = str->getChar()) == EOF) { - return gFalse; - } - *x = (Guint)((c0 << 8) | c1); - return gTrue; -} - -GBool JPXStream::readULong(Guint *x) { - int c0, c1, c2, c3; - - if ((c0 = str->getChar()) == EOF || - (c1 = str->getChar()) == EOF || - (c2 = str->getChar()) == EOF || - (c3 = str->getChar()) == EOF) { - 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 = str->getChar()) == EOF) { - return gFalse; - } - y = (y << 8) + c; - } - if (signd) { - if (y & (1 << (8 * nBytes - 1))) { - y |= -1 << (8 * nBytes); - } - } - *x = y; - return gTrue; -} - -GBool JPXStream::readBits(int nBits, Guint *x) { - int c; - - while (bitBufLen < nBits) { - if ((c = str->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::clearBitBuf() { - bitBufLen = 0; - bitBufSkip = gFalse; - byteCount = 0; -} diff --git a/pdf2swf/xpdf/JPXStream.h b/pdf2swf/xpdf/JPXStream.h deleted file mode 100644 index e64731d..0000000 --- a/pdf2swf/xpdf/JPXStream.h +++ /dev/null @@ -1,349 +0,0 @@ -//======================================================================== -// -// JPXStream.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef JPXSTREAM_H -#define JPXSTREAM_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" -#include "Stream.h" - -class 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 JPXCoeff { - Gushort flags; // flag bits - Gushort len; // number of significant bits in mag - Guint mag; // magnitude value -}; - -// coefficient flags -#define jpxCoeffSignificantB 0 -#define jpxCoeffTouchedB 1 -#define jpxCoeffFirstMagRefB 2 -#define jpxCoeffSignB 7 -#define jpxCoeffSignificant (1 << jpxCoeffSignificantB) -#define jpxCoeffTouched (1 << jpxCoeffTouchedB) -#define jpxCoeffFirstMagRef (1 << jpxCoeffFirstMagRefB) -#define jpxCoeffSign (1 << jpxCoeffSignB) - -//------------------------------------------------------------------------ - -struct JPXCodeBlock { - //----- size - Guint x0, y0, x1, y1; // bounds - - //----- 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; // pkt data length - - //----- coefficient data - JPXCoeff *coeffs; // the coefficients - JArithmeticDecoder // arithmetic decoder - *arithDecoder; - JArithmeticDecoderStats // arithmetic decoder stats - *stats; -}; - -//------------------------------------------------------------------------ - -struct JPXSubband { - //----- computed - Guint x0, y0, x1, y1; // bounds - 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 { - //----- computed - Guint x0, y0, x1, y1; // bounds of the precinct - - //----- 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) - - //----- computed - Guint x0, y0, x1, y1; // bounds of the tile-comp (for this res level) - Guint bx0[3], by0[3], // subband bounds - bx1[3], by1[3]; - - //---- 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 cbW; // code-block width - Guint cbH; // code-block height - - //----- 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 { - //----- 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 - - //----- progression order loop counters - Guint comp; // component - Guint res; // resolution level - Guint precinct; // precinct - Guint layer; // layer - - //----- 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 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) -}; - -//------------------------------------------------------------------------ - -class JPXStream: public FilterStream { -public: - - JPXStream(Stream *strA); - virtual ~JPXStream(); - virtual StreamKind getKind() { return strJPX; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - virtual void getImageParams(int *bitsPerComponent, - StreamColorSpaceMode *csMode); - -private: - - void fillReadBuf(); - void getImageParams2(int *bitsPerComponent, StreamColorSpaceMode *csMode); - GBool readBoxes(); - GBool readColorSpecBox(Guint dataLen); - GBool 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, - Guint nx0, Guint ny0, - Guint nx1, Guint ny1); - void inverseTransform1D(JPXTileComp *tileComp, - int *data, Guint stride, - Guint i0, Guint i1); - 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); - GBool readBits(int nBits, Guint *x); - void clearBitBuf(); - - Guint nComps; // number of components - Guint *bpc; // bits per component, for each component - Guint width, height; // image size - 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 bytes read since last call - // to clearBitBuf - - 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/pdf2swf/xpdf/Lexer.cc b/pdf2swf/xpdf/Lexer.cc deleted file mode 100644 index ee9dc59..0000000 --- a/pdf2swf/xpdf/Lexer.cc +++ /dev/null @@ -1,493 +0,0 @@ -//======================================================================== -// -// Lexer.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#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(); - } -} -static int illegalChars = 0; - -Lexer::~Lexer() { - if (!curStr.isNone()) { - curStr.streamClose(); - curStr.free(); - } - if (freeArray) { - delete streams; - } - if(illegalChars) - error(0, "Illegal characters in hex string (%d)", illegalChars); - illegalChars = 0; -} - -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, done; - 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 '.': - neg = gFalse; - xi = 0; - if (c == '-') { - neg = gTrue; - } else if (c == '.') { - goto doReal; - } else { - xi = c - '0'; - } - while (1) { - c = lookChar(); - if (isdigit(c)) { - getChar(); - xi = xi * 10 + (c - '0'); - } else if (c == '.') { - getChar(); - goto doReal; - } else { - break; - } - } - if (neg) - xi = -xi; - obj->initInt(xi); - break; - doReal: - xf = xi; - scale = 0.1; - while (1) { - c = lookChar(); - if (c == '-') { - // ignore minus signs in the middle of numbers to match - // Adobe's behavior - error(getPos(), "Badly formatted number"); - getChar(); - continue; - } - if (!isdigit(c)) { - break; - } - getChar(); - xf = xf + scale * (c - '0'); - scale *= 0.1; - } - 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: -#if 0 - // This breaks some PDF files, e.g., ones from Photoshop. - case '\r': - case '\n': -#endif - error(getPos(), "Unterminated string"); - done = gTrue; - break; - - case '(': - ++numParen; - c2 = c; - break; - - case ')': - if (--numParen == 0) { - done = gTrue; - } else { - c2 = c; - } - 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(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; - 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 { - goto notEscChar; - } - getChar(); - c <<= 4; - c2 = getChar(); - 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 { - illegalChars++; - //error(getPos(), "Illegal digit in hex char in name"); - } - } - notEscChar: - if (++n == tokBufSize) { - error(getPos(), "Name token too long"); - break; - } - *p++ = c; - } - *p = '\0'; - obj->initName(tokBuf); - break; - - // array punctuation - case '[': - case ']': - tokBuf[0] = 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(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 { - illegalChars++; - //error(getPos(), "Illegal character <%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 { - illegalChars++; - //error(getPos(), "Illegal character '>'"); - obj->initError(); - } - break; - - // error - case ')': - case '{': - case '}': - //error(getPos(), "Illegal character '%c'", c); - illegalChars++; - obj->initError(); - break; - - // command - default: - p = tokBuf; - *p++ = c; - n = 1; - while ((c = lookChar()) != EOF && !specialChars[c]) { - getChar(); - if (++n == tokBufSize) { - error(getPos(), "Command token too long"); - break; - } - *p++ = 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; - } - } -} - -GBool Lexer::isSpace(int c) { - return c >= 0 && c <= 0xff && specialChars[c] == 1; -} diff --git a/pdf2swf/xpdf/Lexer.h b/pdf2swf/xpdf/Lexer.h deleted file mode 100644 index f6ad9ce..0000000 --- a/pdf2swf/xpdf/Lexer.h +++ /dev/null @@ -1,80 +0,0 @@ -//======================================================================== -// -// Lexer.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef LEXER_H -#define LEXER_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" -#include "Stream.h" - -class XRef; - -#define tokBufSize 128 // size of token buffer - -//------------------------------------------------------------------------ -// Lexer -//------------------------------------------------------------------------ - -class Lexer { -public: - - // Construct a lexer for a single stream. Deletes the stream when - // lexer is deleted. - Lexer(XRef *xref, Stream *str); - - // Construct a lexer for a stream or array of streams (assumes obj - // is either a stream or array of streams). - Lexer(XRef *xref, Object *obj); - - // Destructor. - ~Lexer(); - - // Get the next object from the input stream. - Object *getObj(Object *obj); - - // Skip to the beginning of the next line in the input stream. - void skipToNextLine(); - - // Skip over one character. - void skipChar() { getChar(); } - - // Get stream. - Stream *getStream() - { return curStr.isNone() ? (Stream *)NULL : curStr.getStream(); } - - // Get current position in file. This is only used for error - // messages, so it returns an int instead of a Guint. - int getPos() - { return curStr.isNone() ? -1 : (int)curStr.streamGetPos(); } - - // Set position in file. - void setPos(Guint pos, int dir = 0) - { if (!curStr.isNone()) curStr.streamSetPos(pos, dir); } - - // Returns true if is a whitespace character. - static GBool isSpace(int c); - -private: - - int getChar(); - int lookChar(); - - Array *streams; // array of input streams - int strPtr; // index of current stream - Object curStr; // current stream - GBool freeArray; // should lexer free the streams array? - char tokBuf[tokBufSize]; // temporary token buffer -}; - -#endif diff --git a/pdf2swf/xpdf/Link.cc b/pdf2swf/xpdf/Link.cc deleted file mode 100644 index 422edc8..0000000 --- a/pdf2swf/xpdf/Link.cc +++ /dev/null @@ -1,905 +0,0 @@ -//======================================================================== -// -// Link.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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; - - if (!obj->isDict()) { - error(-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(); - - // unknown action - } else if (obj2.isName()) { - action = new LinkUnknown(obj2.getName()); - - // action is missing or wrong type - } else { - error(-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(-1, "Illegal file spec in link"); - } - obj1.free(); - - // error - } else { - error(-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(-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(-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(-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(-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(-1, "Bad annotation destination position"); - goto err1; - } - obj2.free(); - } - - // Fit link - } else if (obj1.isName("Fit")) { - if (a->getLength() < 2) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFit; - - // FitH link - } else if (obj1.isName("FitH")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitH; - if (!a->get(2, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - top = obj2.getNum(); - obj2.free(); - - // FitV link - } else if (obj1.isName("FitV")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitV; - if (!a->get(2, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - left = obj2.getNum(); - obj2.free(); - - // FitR link - } else if (obj1.isName("FitR")) { - if (a->getLength() < 6) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitR; - if (!a->get(2, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - left = obj2.getNum(); - obj2.free(); - if (!a->get(3, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - bottom = obj2.getNum(); - obj2.free(); - if (!a->get(4, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - right = obj2.getNum(); - obj2.free(); - if (!a->get(5, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - top = obj2.getNum(); - obj2.free(); - - // FitB link - } else if (obj1.isName("FitB")) { - if (a->getLength() < 2) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitB; - - // FitBH link - } else if (obj1.isName("FitBH")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitBH; - if (!a->get(2, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - top = obj2.getNum(); - obj2.free(); - - // FitBV link - } else if (obj1.isName("FitBV")) { - if (a->getLength() < 3) { - error(-1, "Annotation destination array is too short"); - goto err2; - } - kind = destFitBV; - if (!a->get(2, &obj2)->isNum()) { - error(-1, "Bad annotation destination position"); - goto err1; - } - left = obj2.getNum(); - obj2.free(); - - // unknown link kind - } else { - error(-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(-1, "Illegal annotation destination %d", destObj->getType()); - } -} - -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(-1, "Illegal annotation destination %d", destObj->getType()); - } -} - -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(-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(-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()->copy(); - if (baseURI && baseURI->getLength() > 0) { - n = strcspn(uri2->getCString(), "/:"); - if (n == uri2->getLength() || uri2->getChar(n) == '/') { - uri = baseURI->copy(); - c = uri->getChar(uri->getLength() - 1); - if (c == '/' || c == '?') { - if (uri2->getChar(0) == '/') { - uri2->del(0); - } - } else { - if (uri2->getChar(0) != '/') { - uri->append('/'); - } - } - uri->append(uri2); - delete uri2; - } else { - uri = uri2; - } - } else { - uri = uri2; - } - } else { - error(-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(-1, "Movie action is missing both the Annot and T keys"); - } -} - -LinkMovie::~LinkMovie() { - if (title) { - delete title; - } -} - -//------------------------------------------------------------------------ -// LinkUnknown -//------------------------------------------------------------------------ - -LinkUnknown::LinkUnknown(char *actionA) { - action = new GString(actionA); -} - -LinkUnknown::~LinkUnknown() { - delete action; -} - -//------------------------------------------------------------------------ -// LinkBorderStyle -//------------------------------------------------------------------------ - -LinkBorderStyle::LinkBorderStyle(LinkBorderType typeA, double widthA, - double *dashA, int dashLengthA, - double rA, double gA, double bA) { - type = typeA; - width = widthA; - dash = dashA; - dashLength = dashLengthA; - r = rA; - g = gA; - b = bA; -} - -LinkBorderStyle::~LinkBorderStyle() { - if (dash) { - gfree(dash); - } -} - -//------------------------------------------------------------------------ -// Link -//------------------------------------------------------------------------ - -Link::Link(Dict *dict, GString *baseURI) { - Object obj1, obj2, obj3; - LinkBorderType borderType; - double borderWidth; - double *borderDash; - int borderDashLength; - double borderR, borderG, borderB; - double t; - int i; - - borderStyle = NULL; - action = NULL; - ok = gFalse; - - // get rectangle - if (!dict->lookup("Rect", &obj1)->isArray()) { - error(-1, "Annotation rectangle is wrong type"); - goto err2; - } - if (!obj1.arrayGet(0, &obj2)->isNum()) { - error(-1, "Bad annotation rectangle"); - goto err1; - } - x1 = obj2.getNum(); - obj2.free(); - if (!obj1.arrayGet(1, &obj2)->isNum()) { - error(-1, "Bad annotation rectangle"); - goto err1; - } - y1 = obj2.getNum(); - obj2.free(); - if (!obj1.arrayGet(2, &obj2)->isNum()) { - error(-1, "Bad annotation rectangle"); - goto err1; - } - x2 = obj2.getNum(); - obj2.free(); - if (!obj1.arrayGet(3, &obj2)->isNum()) { - error(-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; - } - - // get the border style info - borderType = linkBorderSolid; - borderWidth = 1; - borderDash = NULL; - borderDashLength = 0; - borderR = 0; - borderG = 0; - borderB = 1; - if (dict->lookup("BS", &obj1)->isDict()) { - if (obj1.dictLookup("S", &obj2)->isName()) { - if (obj2.isName("S")) { - borderType = linkBorderSolid; - } else if (obj2.isName("D")) { - borderType = linkBorderDashed; - } else if (obj2.isName("B")) { - borderType = linkBorderEmbossed; - } else if (obj2.isName("I")) { - borderType = linkBorderEngraved; - } else if (obj2.isName("U")) { - borderType = linkBorderUnderlined; - } - } - obj2.free(); - if (obj1.dictLookup("W", &obj2)->isNum()) { - borderWidth = obj2.getNum(); - } - obj2.free(); - if (obj1.dictLookup("D", &obj2)->isArray()) { - borderDashLength = obj2.arrayGetLength(); - borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); - for (i = 0; i < borderDashLength; ++i) { - if (obj2.arrayGet(i, &obj3)->isNum()) { - borderDash[i] = obj3.getNum(); - } else { - borderDash[i] = 1; - } - obj3.free(); - } - } - obj2.free(); - } else { - obj1.free(); - if (dict->lookup("Border", &obj1)->isArray()) { - if (obj1.arrayGetLength() >= 3) { - if (obj1.arrayGet(2, &obj2)->isNum()) { - borderWidth = obj2.getNum(); - } - obj2.free(); - if (obj1.arrayGetLength() >= 4) { - if (obj1.arrayGet(3, &obj2)->isArray()) { - borderType = linkBorderDashed; - borderDashLength = obj2.arrayGetLength(); - borderDash = (double *)gmallocn(borderDashLength, sizeof(double)); - for (i = 0; i < borderDashLength; ++i) { - if (obj2.arrayGet(i, &obj3)->isNum()) { - borderDash[i] = obj3.getNum(); - } else { - borderDash[i] = 1; - } - obj3.free(); - } - } else { - // Adobe draws no border at all if the last element is of - // the wrong type. - borderWidth = 0; - } - obj2.free(); - } - } - } - } - obj1.free(); - if (dict->lookup("C", &obj1)->isArray() && obj1.arrayGetLength() == 3) { - if (obj1.arrayGet(0, &obj2)->isNum()) { - borderR = obj2.getNum(); - } - obj1.free(); - if (obj1.arrayGet(1, &obj2)->isNum()) { - borderG = obj2.getNum(); - } - obj1.free(); - if (obj1.arrayGet(2, &obj2)->isNum()) { - borderB = obj2.getNum(); - } - obj1.free(); - } - obj1.free(); - borderStyle = new LinkBorderStyle(borderType, borderWidth, - borderDash, borderDashLength, - borderR, borderG, borderB); - - // look for destination - if (!dict->lookup("Dest", &obj1)->isNull()) { - action = LinkAction::parseDest(&obj1); - - // 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 (borderStyle) { - delete borderStyle; - } - if (action) { - delete action; - } -} - -//------------------------------------------------------------------------ -// Links -//------------------------------------------------------------------------ - -Links::Links(Object *annots, GString *baseURI) { - Link *link; - Object obj1, obj2; - 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()) { - if (obj1.dictLookup("Subtype", &obj2)->isName("Link")) { - 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; - } - } - 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/pdf2swf/xpdf/Link.h b/pdf2swf/xpdf/Link.h deleted file mode 100644 index 9f04420..0000000 --- a/pdf2swf/xpdf/Link.h +++ /dev/null @@ -1,409 +0,0 @@ -//======================================================================== -// -// Link.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef LINK_H -#define LINK_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -class GString; -class Array; -class Dict; - -//------------------------------------------------------------------------ -// LinkAction -//------------------------------------------------------------------------ - -enum LinkActionKind { - actionGoTo, // go to destination - actionGoToR, // go to destination in new file - actionLaunch, // launch app (or open document) - actionURI, // URI - actionNamed, // named action - actionMovie, // movie action - 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; // for destXYZ links, which position - GBool changeZoom; // components to change - 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(); - - virtual GBool isOk() { return name != NULL; } - - 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(); - - virtual GBool isOk() { return annotRef.num >= 0 || title != NULL; } - - virtual LinkActionKind getKind() { return actionMovie; } - GBool hasAnnotRef() { return annotRef.num >= 0; } - Ref *getAnnotRef() { return &annotRef; } - GString *getTitle() { return title; } - -private: - - Ref annotRef; - GString *title; -}; - -//------------------------------------------------------------------------ -// 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 -}; - -//------------------------------------------------------------------------ -// LinkBorderStyle -//------------------------------------------------------------------------ - -enum LinkBorderType { - linkBorderSolid, - linkBorderDashed, - linkBorderEmbossed, - linkBorderEngraved, - linkBorderUnderlined -}; - -class LinkBorderStyle { -public: - - LinkBorderStyle(LinkBorderType typeA, double widthA, - double *dashA, int dashLengthA, - double rA, double gA, double bA); - ~LinkBorderStyle(); - - LinkBorderType getType() { return type; } - double getWidth() { return width; } - void getDash(double **dashA, int *dashLengthA) - { *dashA = dash; *dashLengthA = dashLength; } - void getColor(double *rA, double *gA, double *bA) - { *rA = r; *gA = g; *bA = b; } - -private: - - LinkBorderType type; - double width; - double *dash; - int dashLength; - double r, g, b; -}; - -//------------------------------------------------------------------------ -// Link -//------------------------------------------------------------------------ - -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; } - - // Get the border style info. - LinkBorderStyle *getBorderStyle() { return borderStyle; } - -private: - - double x1, y1; // lower left corner - double x2, y2; // upper right corner - LinkBorderStyle *borderStyle; // border style - LinkAction *action; // action - GBool ok; // is link valid? -}; - -//------------------------------------------------------------------------ -// Links -//------------------------------------------------------------------------ - -class Links { -public: - - // Extract links from array of annotations. - Links(Object *annots, GString *baseURI); - - // Destructor. - ~Links(); - - // Iterate through list of links. - int getNumLinks() { return numLinks; } - Link *getLink(int i) { return links[i]; } - - // If point , is in a link, return the associated action; - // else return NULL. - LinkAction *find(double x, double y); - - // Return true if , is in a link. - GBool onLink(double x, double y); - -private: - - Link **links; - int numLinks; -}; - -#endif diff --git a/pdf2swf/xpdf/Makefile.in b/pdf2swf/xpdf/Makefile.in deleted file mode 100644 index c47fa5f..0000000 --- a/pdf2swf/xpdf/Makefile.in +++ /dev/null @@ -1,119 +0,0 @@ -top_builddir = ../.. -srcdir = @srcdir@ -top_srcdir = @top_srcdir@ -include ../../Makefile.common - -all: libpdf$(A) - -libpdf_objects = GHash.$(O) GList.$(O) GString.$(O) gmem.$(O) gfile.$(O) \ - FoFiTrueType.$(O) FoFiType1.$(O) FoFiType1C.$(O) FoFiBase.$(O) FoFiEncodings.$(O) \ - OutputDev.$(O) PDFDoc.$(O) Error.$(O) Stream.$(O) Object.$(O) \ - Decrypt.$(O) Array.$(O) XRef.$(O) Dict.$(O) Parser.$(O) \ - Lexer.$(O) Outline.$(O) PDFDocEncoding.$(O) Catalog.$(O) \ - Link.$(O) GlobalParams.$(O) JBIG2Stream.$(O) Page.$(O) JPXStream.$(O) \ - JArithmeticDecoder.$(O) Gfx.$(O) GfxFont.$(O) CMap.$(O) CharCodeToUnicode.$(O) \ - PSTokenizer.$(O) FontEncodingTables.$(O) BuiltinFont.$(O) BuiltinFontTables.$(O) \ - GfxState.$(O) Function.$(O) Annot.$(O) NameToCharCode.$(O) UnicodeMap.$(O) cmyk.$(O) \ - SecurityHandler.$(O) - -cmyk.$(O): cmyk.cc - $(CC) -I./ cmyk.cc -o $@ -UnicodeMap.$(O): UnicodeMap.cc - $(CC) -I./ UnicodeMap.cc -o $@ -NameToCharCode.$(O): NameToCharCode.cc - $(CC) -I./ NameToCharCode.cc -o $@ -Annot.$(O): Annot.cc - $(CC) -I./ Annot.cc -o $@ -Function.$(O): Function.cc - $(CC) -I./ Function.cc -o $@ -BuiltinFontTables.$(O): BuiltinFontTables.cc - $(CC) -I./ BuiltinFontTables.cc -o $@ -BuiltinFont.$(O): BuiltinFont.cc - $(CC) -I./ BuiltinFont.cc -o $@ -FontEncodingTables.$(O): FontEncodingTables.cc - $(CC) -I./ FontEncodingTables.cc -o $@ -PSTokenizer.$(O): PSTokenizer.cc - $(CC) -I./ PSTokenizer.cc -o $@ -CharCodeToUnicode.$(O): CharCodeToUnicode.cc - $(CC) -I./ CharCodeToUnicode.cc -o $@ -CMap.$(O): CMap.cc - $(CC) -I./ CMap.cc -o $@ -GfxFont.$(O): GfxFont.cc - $(CC) -I./ GfxFont.cc -o $@ -Gfx.$(O): Gfx.cc - $(CC) -I./ Gfx.cc -o $@ -GfxState.$(O): GfxState.cc - $(CC) -I./ GfxState.cc -o $@ -JArithmeticDecoder.$(O): JArithmeticDecoder.cc - $(CC) -I./ JArithmeticDecoder.cc -o $@ -JPXStream.$(O): JPXStream.cc - $(CC) -I./ JPXStream.cc -o $@ -GlobalParams.$(O): GlobalParams.cc GlobalParams.h - $(CC) -I./ GlobalParams.cc -o $@ -JBIG2Stream.$(O): JBIG2Stream.cc - $(CC) -I./ JBIG2Stream.cc -o $@ -Page.$(O): Page.cc - $(CC) -I./ Page.cc -o $@ -Link.$(O): Link.cc - $(CC) -I./ Link.cc -o $@ -Catalog.$(O): Catalog.cc - $(CC) -I./ Catalog.cc -o $@ -PDFDocEncoding.$(O): PDFDocEncoding.cc - $(CC) -I./ PDFDocEncoding.cc -o $@ -Outline.$(O): Outline.cc - $(CC) -I./ Outline.cc -o $@ -Lexer.$(O): Lexer.cc - $(CC) -I./ Lexer.cc -o $@ -Parser.$(O): Parser.cc - $(CC) -I./ Parser.cc -o $@ -XRef.$(O): XRef.cc - $(CC) -I./ XRef.cc -o $@ -Array.$(O): Array.cc - $(CC) -I./ Array.cc -o $@ -Dict.$(O): Dict.cc - $(CC) -I./ Dict.cc -o $@ -Decrypt.$(O): Decrypt.cc - $(CC) -I./ Decrypt.cc -o $@ -Object.$(O): Object.cc - $(CC) -I./ Object.cc -o $@ -Error.$(O): Error.cc aconf.h - $(CC) -I./ Error.cc -o $@ -Stream.$(O): Stream.cc - $(CC) -I./ Stream.cc -o $@ -PDFDoc.$(O): PDFDoc.cc - $(CC) -I./ PDFDoc.cc -o $@ -SecurityHandler.$(O): SecurityHandler.cc SecurityHandler.h - $(CC) -I./ SecurityHandler.cc -o $@ -OutputDev.$(O): OutputDev.cc GfxState.h Stream.h Object.h OutputDev.h gtypes.h CharTypes.h - $(CC) -I./ OutputDev.cc -o $@ -FoFiBase.$(O): FoFiBase.cc - $(CC) -I./ FoFiBase.cc -o $@ -FoFiTrueType.$(O): FoFiTrueType.cc FoFiBase.h - $(CC) -I./ FoFiTrueType.cc -o $@ -FoFiEncodings.$(O): FoFiEncodings.cc FoFiEncodings.h - $(CC) -I./ FoFiEncodings.cc -o $@ -FoFiType1C.$(O): FoFiType1C.cc FoFiBase.h - $(CC) -I./ FoFiType1C.cc -o $@ -FoFiType1.$(O): FoFiType1.cc FoFiBase.h - $(CC) -I./ FoFiType1.cc -o $@ -GList.$(O): GList.cc - $(CC) -I./ GList.cc -o $@ -GString.$(O): GString.cc - $(CC) -I./ GString.cc -o $@ -GHash.$(O): GHash.cc - $(CC) -I./ GHash.cc -o $@ -gfile.$(O): gfile.cc - $(CC) -I./ gfile.cc -o $@ -gmem.$(O): gmem.c - $(C) -I./ gmem.c -o $@ - -libpdf$(A): $(libpdf_objects) - $(AR) r libpdf$(A) $(libpdf_objects) - $(RANLIB) libpdf$(A) - -install: -uninstall: - -clean: - rm -f *.o *.obj *.lo *.a *.lib *.la gmon.out - diff --git a/pdf2swf/xpdf/NameToCharCode.cc b/pdf2swf/xpdf/NameToCharCode.cc deleted file mode 100644 index 7ebf4e1..0000000 --- a/pdf2swf/xpdf/NameToCharCode.cc +++ /dev/null @@ -1,116 +0,0 @@ -//======================================================================== -// -// NameToCharCode.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "gmem.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(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(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(char *name) { - 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/pdf2swf/xpdf/NameToCharCode.h b/pdf2swf/xpdf/NameToCharCode.h deleted file mode 100644 index 65453c3..0000000 --- a/pdf2swf/xpdf/NameToCharCode.h +++ /dev/null @@ -1,42 +0,0 @@ -//======================================================================== -// -// NameToCharCode.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef NAMETOCHARCODE_H -#define NAMETOCHARCODE_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "CharTypes.h" - -struct NameToCharCodeEntry; - -//------------------------------------------------------------------------ - -class NameToCharCode { -public: - - NameToCharCode(); - ~NameToCharCode(); - - void add(char *name, CharCode c); - CharCode lookup(char *name); - -private: - - int hash(char *name); - - NameToCharCodeEntry *tab; - int size; - int len; -}; - -#endif diff --git a/pdf2swf/xpdf/NameToUnicodeTable.h b/pdf2swf/xpdf/NameToUnicodeTable.h deleted file mode 100644 index c5ecba4..0000000 --- a/pdf2swf/xpdf/NameToUnicodeTable.h +++ /dev/null @@ -1,1097 +0,0 @@ -//======================================================================== -// -// NameToUnicodeTable.h -// -// Copyright 2001-2004 Glyph & Cog, LLC -// -//======================================================================== - -static struct { - Unicode u; - 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"}, - {0xf7e6, "AEsmall"}, - {0x00c1, "Aacute"}, - {0xf7e1, "Aacutesmall"}, - {0x0102, "Abreve"}, - {0x00c2, "Acircumflex"}, - {0xf7e2, "Acircumflexsmall"}, - {0xf6c9, "Acute"}, - {0xf7b4, "Acutesmall"}, - {0x00c4, "Adieresis"}, - {0xf7e4, "Adieresissmall"}, - {0x00c0, "Agrave"}, - {0xf7e0, "Agravesmall"}, - {0x0391, "Alpha"}, - {0x0386, "Alphatonos"}, - {0x0100, "Amacron"}, - {0x0104, "Aogonek"}, - {0x00c5, "Aring"}, - {0x01fa, "Aringacute"}, - {0xf7e5, "Aringsmall"}, - {0xf761, "Asmall"}, - {0x00c3, "Atilde"}, - {0xf7e3, "Atildesmall"}, - {0x0042, "B"}, - {0x0392, "Beta"}, - {0xf6f4, "Brevesmall"}, - {0xf762, "Bsmall"}, - {0x0043, "C"}, - {0x0106, "Cacute"}, - {0xf6ca, "Caron"}, - {0xf6f5, "Caronsmall"}, - {0x010c, "Ccaron"}, - {0x00c7, "Ccedilla"}, - {0xf7e7, "Ccedillasmall"}, - {0x0108, "Ccircumflex"}, - {0x010a, "Cdotaccent"}, - {0xf7b8, "Cedillasmall"}, - {0x03a7, "Chi"}, - {0xf6f6, "Circumflexsmall"}, - {0xf763, "Csmall"}, - {0x0044, "D"}, - {0x010e, "Dcaron"}, - {0x0110, "Dcroat"}, - {0x2206, "Delta"}, - {0xf6cb, "Dieresis"}, - {0xf6cc, "DieresisAcute"}, - {0xf6cd, "DieresisGrave"}, - {0xf7a8, "Dieresissmall"}, - {0xf6f7, "Dotaccentsmall"}, - {0xf764, "Dsmall"}, - {0x0045, "E"}, - {0x00c9, "Eacute"}, - {0xf7e9, "Eacutesmall"}, - {0x0114, "Ebreve"}, - {0x011a, "Ecaron"}, - {0x00ca, "Ecircumflex"}, - {0xf7ea, "Ecircumflexsmall"}, - {0x00cb, "Edieresis"}, - {0xf7eb, "Edieresissmall"}, - {0x0116, "Edotaccent"}, - {0x00c8, "Egrave"}, - {0xf7e8, "Egravesmall"}, - {0x0112, "Emacron"}, - {0x014a, "Eng"}, - {0x0118, "Eogonek"}, - {0x0395, "Epsilon"}, - {0x0388, "Epsilontonos"}, - {0xf765, "Esmall"}, - {0x0397, "Eta"}, - {0x0389, "Etatonos"}, - {0x00d0, "Eth"}, - {0xf7f0, "Ethsmall"}, - {0x20ac, "Euro"}, - {0x0046, "F"}, - {0xf766, "Fsmall"}, - {0x0047, "G"}, - {0x0393, "Gamma"}, - {0x011e, "Gbreve"}, - {0x01e6, "Gcaron"}, - {0x011c, "Gcircumflex"}, - {0x0122, "Gcommaaccent"}, - {0x0120, "Gdotaccent"}, - {0xf6ce, "Grave"}, - {0xf760, "Gravesmall"}, - {0xf767, "Gsmall"}, - {0x0048, "H"}, - {0x25cf, "H18533"}, - {0x25aa, "H18543"}, - {0x25ab, "H18551"}, - {0x25a1, "H22073"}, - {0x0126, "Hbar"}, - {0x0124, "Hcircumflex"}, - {0xf768, "Hsmall"}, - {0xf6cf, "Hungarumlaut"}, - {0xf6f8, "Hungarumlautsmall"}, - {0x0049, "I"}, - {0x0132, "IJ"}, - {0x00cd, "Iacute"}, - {0xf7ed, "Iacutesmall"}, - {0x012c, "Ibreve"}, - {0x00ce, "Icircumflex"}, - {0xf7ee, "Icircumflexsmall"}, - {0x00cf, "Idieresis"}, - {0xf7ef, "Idieresissmall"}, - {0x0130, "Idotaccent"}, - {0x2111, "Ifraktur"}, - {0x00cc, "Igrave"}, - {0xf7ec, "Igravesmall"}, - {0x012a, "Imacron"}, - {0x012e, "Iogonek"}, - {0x0399, "Iota"}, - {0x03aa, "Iotadieresis"}, - {0x038a, "Iotatonos"}, - {0xf769, "Ismall"}, - {0x0128, "Itilde"}, - {0x004a, "J"}, - {0x0134, "Jcircumflex"}, - {0xf76a, "Jsmall"}, - {0x004b, "K"}, - {0x039a, "Kappa"}, - {0x0136, "Kcommaaccent"}, - {0xf76b, "Ksmall"}, - {0x004c, "L"}, - {0xf6bf, "LL"}, - {0x0139, "Lacute"}, - {0x039b, "Lambda"}, - {0x013d, "Lcaron"}, - {0x013b, "Lcommaaccent"}, - {0x013f, "Ldot"}, - {0x0141, "Lslash"}, - {0xf6f9, "Lslashsmall"}, - {0xf76c, "Lsmall"}, - {0x004d, "M"}, - {0xf6d0, "Macron"}, - {0xf7af, "Macronsmall"}, - {0xf76d, "Msmall"}, - {0x039c, "Mu"}, - {0x004e, "N"}, - {0x0143, "Nacute"}, - {0x0147, "Ncaron"}, - {0x0145, "Ncommaaccent"}, - {0xf76e, "Nsmall"}, - {0x00d1, "Ntilde"}, - {0xf7f1, "Ntildesmall"}, - {0x039d, "Nu"}, - {0x004f, "O"}, - {0x0152, "OE"}, - {0xf6fa, "OEsmall"}, - {0x00d3, "Oacute"}, - {0xf7f3, "Oacutesmall"}, - {0x014e, "Obreve"}, - {0x00d4, "Ocircumflex"}, - {0xf7f4, "Ocircumflexsmall"}, - {0x00d6, "Odieresis"}, - {0xf7f6, "Odieresissmall"}, - {0xf6fb, "Ogoneksmall"}, - {0x00d2, "Ograve"}, - {0xf7f2, "Ogravesmall"}, - {0x01a0, "Ohorn"}, - {0x0150, "Ohungarumlaut"}, - {0x014c, "Omacron"}, - {0x2126, "Omega"}, - {0x038f, "Omegatonos"}, - {0x039f, "Omicron"}, - {0x038c, "Omicrontonos"}, - {0x00d8, "Oslash"}, - {0x01fe, "Oslashacute"}, - {0xf7f8, "Oslashsmall"}, - {0xf76f, "Osmall"}, - {0x00d5, "Otilde"}, - {0xf7f5, "Otildesmall"}, - {0x0050, "P"}, - {0x03a6, "Phi"}, - {0x03a0, "Pi"}, - {0x03a8, "Psi"}, - {0xf770, "Psmall"}, - {0x0051, "Q"}, - {0xf771, "Qsmall"}, - {0x0052, "R"}, - {0x0154, "Racute"}, - {0x0158, "Rcaron"}, - {0x0156, "Rcommaaccent"}, - {0x211c, "Rfraktur"}, - {0x03a1, "Rho"}, - {0xf6fc, "Ringsmall"}, - {0xf772, "Rsmall"}, - {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"}, - {0x0160, "Scaron"}, - {0xf6fd, "Scaronsmall"}, - {0x015e, "Scedilla"}, - {0x015c, "Scircumflex"}, - {0x0218, "Scommaaccent"}, - {0x03a3, "Sigma"}, - {0xf773, "Ssmall"}, - {0x0054, "T"}, - {0x03a4, "Tau"}, - {0x0166, "Tbar"}, - {0x0164, "Tcaron"}, - {0x0162, "Tcommaaccent"}, - {0x0398, "Theta"}, - {0x00de, "Thorn"}, - {0xf7fe, "Thornsmall"}, - {0xf6fe, "Tildesmall"}, - {0xf774, "Tsmall"}, - {0x0055, "U"}, - {0x00da, "Uacute"}, - {0xf7fa, "Uacutesmall"}, - {0x016c, "Ubreve"}, - {0x00db, "Ucircumflex"}, - {0xf7fb, "Ucircumflexsmall"}, - {0x00dc, "Udieresis"}, - {0xf7fc, "Udieresissmall"}, - {0x00d9, "Ugrave"}, - {0xf7f9, "Ugravesmall"}, - {0x01af, "Uhorn"}, - {0x0170, "Uhungarumlaut"}, - {0x016a, "Umacron"}, - {0x0172, "Uogonek"}, - {0x03a5, "Upsilon"}, - {0x03d2, "Upsilon1"}, - {0x03ab, "Upsilondieresis"}, - {0x038e, "Upsilontonos"}, - {0x016e, "Uring"}, - {0xf775, "Usmall"}, - {0x0168, "Utilde"}, - {0x0056, "V"}, - {0xf776, "Vsmall"}, - {0x0057, "W"}, - {0x1e82, "Wacute"}, - {0x0174, "Wcircumflex"}, - {0x1e84, "Wdieresis"}, - {0x1e80, "Wgrave"}, - {0xf777, "Wsmall"}, - {0x0058, "X"}, - {0x039e, "Xi"}, - {0xf778, "Xsmall"}, - {0x0059, "Y"}, - {0x00dd, "Yacute"}, - {0xf7fd, "Yacutesmall"}, - {0x0176, "Ycircumflex"}, - {0x0178, "Ydieresis"}, - {0xf7ff, "Ydieresissmall"}, - {0x1ef2, "Ygrave"}, - {0xf779, "Ysmall"}, - {0x005a, "Z"}, - {0x0179, "Zacute"}, - {0x017d, "Zcaron"}, - {0xf6ff, "Zcaronsmall"}, - {0x017b, "Zdotaccent"}, - {0x0396, "Zeta"}, - {0xf77a, "Zsmall"}, - {0x0022, "\""}, - {0x005c, "\\"}, - {0x005d, "]"}, - {0x005e, "^"}, - {0x005f, "_"}, - {0x0060, "`"}, - {0x0061, "a"}, - {0x00e1, "aacute"}, - {0x0103, "abreve"}, - {0x00e2, "acircumflex"}, - {0x00b4, "acute"}, - {0x0301, "acutecomb"}, - {0x00e4, "adieresis"}, - {0x00e6, "ae"}, - {0x01fd, "aeacute"}, - {0x2015, "afii00208"}, - {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"}, - {0x2135, "aleph"}, - {0x03b1, "alpha"}, - {0x03ac, "alphatonos"}, - {0x0101, "amacron"}, - {0x0026, "ampersand"}, - {0xf726, "ampersandsmall"}, - {0x2220, "angle"}, - {0x2329, "angleleft"}, - {0x232a, "angleright"}, - {0x0387, "anoteleia"}, - {0x0105, "aogonek"}, - {0x2248, "approxequal"}, - {0x00e5, "aring"}, - {0x01fb, "aringacute"}, - {0x2194, "arrowboth"}, - {0x21d4, "arrowdblboth"}, - {0x21d3, "arrowdbldown"}, - {0x21d0, "arrowdblleft"}, - {0x21d2, "arrowdblright"}, - {0x21d1, "arrowdblup"}, - {0x2193, "arrowdown"}, - {0xf8e7, "arrowhorizex"}, - {0x2190, "arrowleft"}, - {0x2192, "arrowright"}, - {0x2191, "arrowup"}, - {0x2195, "arrowupdn"}, - {0x21a8, "arrowupdnbse"}, - {0xf8e6, "arrowvertex"}, - {0x005e, "asciicircum"}, - {0x007e, "asciitilde"}, - {0x002a, "asterisk"}, - {0x2217, "asteriskmath"}, - {0xf6e9, "asuperior"}, - {0x0040, "at"}, - {0x00e3, "atilde"}, - {0x0062, "b"}, - {0x005c, "backslash"}, - {0x007c, "bar"}, - {0x03b2, "beta"}, - {0x2588, "block"}, - {0xf8f4, "braceex"}, - {0x007b, "braceleft"}, - {0xf8f3, "braceleftbt"}, - {0xf8f2, "braceleftmid"}, - {0xf8f1, "bracelefttp"}, - {0x007d, "braceright"}, - {0xf8fe, "bracerightbt"}, - {0xf8fd, "bracerightmid"}, - {0xf8fc, "bracerighttp"}, - {0x005b, "bracketleft"}, - {0xf8f0, "bracketleftbt"}, - {0xf8ef, "bracketleftex"}, - {0xf8ee, "bracketlefttp"}, - {0x005d, "bracketright"}, - {0xf8fb, "bracketrightbt"}, - {0xf8fa, "bracketrightex"}, - {0xf8f9, "bracketrighttp"}, - {0x02d8, "breve"}, - {0x00a6, "brokenbar"}, - {0xf6ea, "bsuperior"}, - {0x2022, "bullet"}, - {0x0063, "c"}, - {0x0107, "cacute"}, - {0x02c7, "caron"}, - {0x21b5, "carriagereturn"}, - {0x010d, "ccaron"}, - {0x00e7, "ccedilla"}, - {0x0109, "ccircumflex"}, - {0x010b, "cdotaccent"}, - {0x00b8, "cedilla"}, - {0x00a2, "cent"}, - {0xf6df, "centinferior"}, - {0xf7a2, "centoldstyle"}, - {0xf6e0, "centsuperior"}, - {0x03c7, "chi"}, - {0x25cb, "circle"}, - {0x2297, "circlemultiply"}, - {0x2295, "circleplus"}, - {0x02c6, "circumflex"}, - {0x2663, "club"}, - {0x003a, "colon"}, - {0x20a1, "colonmonetary"}, - {0x002c, "comma"}, - {0xf6c3, "commaaccent"}, - {0xf6e1, "commainferior"}, - {0xf6e2, "commasuperior"}, - {0x2245, "congruent"}, - {0x00a9, "copyright"}, - {0x00a9, "copyrightsans"}, - {0x00a9, "copyrightserif"}, - {0x00a4, "currency"}, - {0xf6d1, "cyrBreve"}, - {0xf6d2, "cyrFlex"}, - {0xf6d4, "cyrbreve"}, - {0xf6d5, "cyrflex"}, - {0x0064, "d"}, - {0x2020, "dagger"}, - {0x2021, "daggerdbl"}, - {0xf6d3, "dblGrave"}, - {0xf6d6, "dblgrave"}, - {0x010f, "dcaron"}, - {0x0111, "dcroat"}, - {0x00b0, "degree"}, - {0x03b4, "delta"}, - {0x2666, "diamond"}, - {0x00a8, "dieresis"}, - {0xf6d7, "dieresisacute"}, - {0xf6d8, "dieresisgrave"}, - {0x0385, "dieresistonos"}, - {0x00f7, "divide"}, - {0x2593, "dkshade"}, - {0x2584, "dnblock"}, - {0x0024, "dollar"}, - {0xf6e3, "dollarinferior"}, - {0xf724, "dollaroldstyle"}, - {0xf6e4, "dollarsuperior"}, - {0x20ab, "dong"}, - {0x02d9, "dotaccent"}, - {0x0323, "dotbelowcomb"}, - {0x0131, "dotlessi"}, - {0xf6be, "dotlessj"}, - {0x22c5, "dotmath"}, - {0xf6eb, "dsuperior"}, - {0x0065, "e"}, - {0x00e9, "eacute"}, - {0x0115, "ebreve"}, - {0x011b, "ecaron"}, - {0x00ea, "ecircumflex"}, - {0x00eb, "edieresis"}, - {0x0117, "edotaccent"}, - {0x00e8, "egrave"}, - {0x0038, "eight"}, - {0x2088, "eightinferior"}, - {0xf738, "eightoldstyle"}, - {0x2078, "eightsuperior"}, - {0x2208, "element"}, - {0x2026, "ellipsis"}, - {0x0113, "emacron"}, - {0x2014, "emdash"}, - {0x2205, "emptyset"}, - {0x2013, "endash"}, - {0x014b, "eng"}, - {0x0119, "eogonek"}, - {0x03b5, "epsilon"}, - {0x03ad, "epsilontonos"}, - {0x003d, "equal"}, - {0x2261, "equivalence"}, - {0x212e, "estimated"}, - {0xf6ec, "esuperior"}, - {0x03b7, "eta"}, - {0x03ae, "etatonos"}, - {0x00f0, "eth"}, - {0x0021, "exclam"}, - {0x203c, "exclamdbl"}, - {0x00a1, "exclamdown"}, - {0xf7a1, "exclamdownsmall"}, - {0x0021, "exclamleft"}, - {0xf721, "exclamsmall"}, - {0x2203, "existential"}, - {0x0066, "f"}, - {0x2640, "female"}, - {0xfb00, "ff"}, - {0xfb03, "ffi"}, - {0xfb04, "ffl"}, - {0xfb01, "fi"}, - {0x2012, "figuredash"}, - {0x25a0, "filledbox"}, - {0x25ac, "filledrect"}, - {0x0035, "five"}, - {0x215d, "fiveeighths"}, - {0x2085, "fiveinferior"}, - {0xf735, "fiveoldstyle"}, - {0x2075, "fivesuperior"}, - {0xfb02, "fl"}, - {0x0192, "florin"}, - {0x0034, "four"}, - {0x2084, "fourinferior"}, - {0xf734, "fouroldstyle"}, - {0x2074, "foursuperior"}, - {0x2044, "fraction"}, - {0x20a3, "franc"}, - {0x0067, "g"}, - {0x03b3, "gamma"}, - {0x011f, "gbreve"}, - {0x01e7, "gcaron"}, - {0x011d, "gcircumflex"}, - {0x0123, "gcommaaccent"}, - {0x0121, "gdotaccent"}, - {0x00df, "germandbls"}, - {0x2207, "gradient"}, - {0x0060, "grave"}, - {0x0300, "gravecomb"}, - {0x003e, "greater"}, - {0x2265, "greaterequal"}, - {0x00ab, "guillemotleft"}, - {0x00bb, "guillemotright"}, - {0x2039, "guilsinglleft"}, - {0x203a, "guilsinglright"}, - {0x0068, "h"}, - {0x0127, "hbar"}, - {0x0125, "hcircumflex"}, - {0x2665, "heart"}, - {0x0309, "hookabovecomb"}, - {0x2302, "house"}, - {0x02dd, "hungarumlaut"}, - {0x002d, "hyphen"}, - {0xf6e5, "hypheninferior"}, - {0xf6e6, "hyphensuperior"}, - {0x0069, "i"}, - {0x00ed, "iacute"}, - {0x012d, "ibreve"}, - {0x00ee, "icircumflex"}, - {0x00ef, "idieresis"}, - {0x00ec, "igrave"}, - {0x0133, "ij"}, - {0x012b, "imacron"}, - {0x221e, "infinity"}, - {0x222b, "integral"}, - {0x2321, "integralbt"}, - {0xf8f5, "integralex"}, - {0x2320, "integraltp"}, - {0x2229, "intersection"}, - {0x25d8, "invbullet"}, - {0x25d9, "invcircle"}, - {0x263b, "invsmileface"}, - {0x012f, "iogonek"}, - {0x03b9, "iota"}, - {0x03ca, "iotadieresis"}, - {0x0390, "iotadieresistonos"}, - {0x03af, "iotatonos"}, - {0xf6ed, "isuperior"}, - {0x0129, "itilde"}, - {0x006a, "j"}, - {0x0135, "jcircumflex"}, - {0x006b, "k"}, - {0x03ba, "kappa"}, - {0x0137, "kcommaaccent"}, - {0x0138, "kgreenlandic"}, - {0x006c, "l"}, - {0x013a, "lacute"}, - {0x03bb, "lambda"}, - {0x013e, "lcaron"}, - {0x013c, "lcommaaccent"}, - {0x0140, "ldot"}, - {0x003c, "less"}, - {0x2264, "lessequal"}, - {0x258c, "lfblock"}, - {0x20a4, "lira"}, - {0xf6c0, "ll"}, - {0x2227, "logicaland"}, - {0x00ac, "logicalnot"}, - {0x2228, "logicalor"}, - {0x017f, "longs"}, - {0x25ca, "lozenge"}, - {0x0142, "lslash"}, - {0xf6ee, "lsuperior"}, - {0x2591, "ltshade"}, - {0x006d, "m"}, - {0x00af, "macron"}, - {0x2642, "male"}, - {0x2212, "minus"}, - {0x2032, "minute"}, - {0xf6ef, "msuperior"}, - {0x00b5, "mu"}, - {0x00d7, "multiply"}, - {0x266a, "musicalnote"}, - {0x266b, "musicalnotedbl"}, - {0x006e, "n"}, - {0x0144, "nacute"}, - {0x0149, "napostrophe"}, - {0x00a0, "nbspace"}, - {0x0148, "ncaron"}, - {0x0146, "ncommaaccent"}, - {0x0039, "nine"}, - {0x2089, "nineinferior"}, - {0xf739, "nineoldstyle"}, - {0x2079, "ninesuperior"}, - {0x00a0, "nonbreakingspace"}, - {0x2209, "notelement"}, - {0x2260, "notequal"}, - {0x2284, "notsubset"}, - {0x207f, "nsuperior"}, - {0x00f1, "ntilde"}, - {0x03bd, "nu"}, - {0x0023, "numbersign"}, - {0x006f, "o"}, - {0x00f3, "oacute"}, - {0x014f, "obreve"}, - {0x00f4, "ocircumflex"}, - {0x00f6, "odieresis"}, - {0x0153, "oe"}, - {0x02db, "ogonek"}, - {0x00f2, "ograve"}, - {0x01a1, "ohorn"}, - {0x0151, "ohungarumlaut"}, - {0x014d, "omacron"}, - {0x03c9, "omega"}, - {0x03d6, "omega1"}, - {0x03ce, "omegatonos"}, - {0x03bf, "omicron"}, - {0x03cc, "omicrontonos"}, - {0x0031, "one"}, - {0x2024, "onedotenleader"}, - {0x215b, "oneeighth"}, - {0xf6dc, "onefitted"}, - {0x00bd, "onehalf"}, - {0x2081, "oneinferior"}, - {0xf731, "oneoldstyle"}, - {0x00bc, "onequarter"}, - {0x00b9, "onesuperior"}, - {0x2153, "onethird"}, - {0x25e6, "openbullet"}, - {0x00aa, "ordfeminine"}, - {0x00ba, "ordmasculine"}, - {0x221f, "orthogonal"}, - {0x00f8, "oslash"}, - {0x01ff, "oslashacute"}, - {0xf6f0, "osuperior"}, - {0x00f5, "otilde"}, - {0x0070, "p"}, - {0x00b6, "paragraph"}, - {0x0028, "parenleft"}, - {0xf8ed, "parenleftbt"}, - {0xf8ec, "parenleftex"}, - {0x208d, "parenleftinferior"}, - {0x207d, "parenleftsuperior"}, - {0xf8eb, "parenlefttp"}, - {0x0029, "parenright"}, - {0xf8f8, "parenrightbt"}, - {0xf8f7, "parenrightex"}, - {0x208e, "parenrightinferior"}, - {0x207e, "parenrightsuperior"}, - {0xf8f6, "parenrighttp"}, - {0x2202, "partialdiff"}, - {0x0025, "percent"}, - {0x002e, "period"}, - {0x00b7, "periodcentered"}, - {0xf6e7, "periodinferior"}, - {0xf6e8, "periodsuperior"}, - {0x22a5, "perpendicular"}, - {0x2030, "perthousand"}, - {0x20a7, "peseta"}, - {0x03c6, "phi"}, - {0x03d5, "phi1"}, - {0x03c0, "pi"}, - {0x002b, "plus"}, - {0x00b1, "plusminus"}, - {0x211e, "prescription"}, - {0x220f, "product"}, - {0x2282, "propersubset"}, - {0x2283, "propersuperset"}, - {0x221d, "proportional"}, - {0x03c8, "psi"}, - {0x0071, "q"}, - {0x003f, "question"}, - {0x00bf, "questiondown"}, - {0xf7bf, "questiondownsmall"}, - {0xf73f, "questionsmall"}, - {0x0022, "quotedbl"}, - {0x201e, "quotedblbase"}, - {0x201c, "quotedblleft"}, - {0x201d, "quotedblright"}, - {0x2018, "quoteleft"}, - {0x201b, "quotereversed"}, - {0x2019, "quoteright"}, - {0x201a, "quotesinglbase"}, - {0x0027, "quotesingle"}, - {0x0072, "r"}, - {0x0155, "racute"}, - {0x221a, "radical"}, - {0xf8e5, "radicalex"}, - {0x0159, "rcaron"}, - {0x0157, "rcommaaccent"}, - {0x2286, "reflexsubset"}, - {0x2287, "reflexsuperset"}, - {0x00ae, "registered"}, - {0x00ae, "registersans"}, - {0x00ae, "registerserif"}, - {0x2310, "revlogicalnot"}, - {0x03c1, "rho"}, - {0x02da, "ring"}, - {0xf6f1, "rsuperior"}, - {0x2590, "rtblock"}, - {0xf6dd, "rupiah"}, - {0x0073, "s"}, - {0x015b, "sacute"}, - {0x0161, "scaron"}, - {0x015f, "scedilla"}, - {0x015d, "scircumflex"}, - {0x0219, "scommaaccent"}, - {0x2033, "second"}, - {0x00a7, "section"}, - {0x003b, "semicolon"}, - {0x0037, "seven"}, - {0x215e, "seveneighths"}, - {0x2087, "seveninferior"}, - {0xf737, "sevenoldstyle"}, - {0x2077, "sevensuperior"}, - {0x2592, "shade"}, - {0x03c3, "sigma"}, - {0x03c2, "sigma1"}, - {0x223c, "similar"}, - {0x0036, "six"}, - {0x2086, "sixinferior"}, - {0xf736, "sixoldstyle"}, - {0x2076, "sixsuperior"}, - {0x002f, "slash"}, - {0x263a, "smileface"}, - {0x0020, "space"}, - {0x2660, "spade"}, - {0xf6f2, "ssuperior"}, - {0x00a3, "sterling"}, - {0x220b, "suchthat"}, - {0x2211, "summation"}, - {0x263c, "sun"}, - {0x0074, "t"}, - {0x03c4, "tau"}, - {0x0167, "tbar"}, - {0x0165, "tcaron"}, - {0x0163, "tcommaaccent"}, - {0x2234, "therefore"}, - {0x03b8, "theta"}, - {0x03d1, "theta1"}, - {0x00fe, "thorn"}, - {0x0033, "three"}, - {0x215c, "threeeighths"}, - {0x2083, "threeinferior"}, - {0xf733, "threeoldstyle"}, - {0x00be, "threequarters"}, - {0xf6de, "threequartersemdash"}, - {0x00b3, "threesuperior"}, - {0x02dc, "tilde"}, - {0x0303, "tildecomb"}, - {0x0384, "tonos"}, - {0x2122, "trademark"}, - {0x2122, "trademarksans"}, - {0x2122, "trademarkserif"}, - {0x25bc, "triagdn"}, - {0x25c4, "triaglf"}, - {0x25ba, "triagrt"}, - {0x25b2, "triagup"}, - {0xf6f3, "tsuperior"}, - {0x0032, "two"}, - {0x2025, "twodotenleader"}, - {0x2082, "twoinferior"}, - {0xf732, "twooldstyle"}, - {0x00b2, "twosuperior"}, - {0x2154, "twothirds"}, - {0x0075, "u"}, - {0x00fa, "uacute"}, - {0x016d, "ubreve"}, - {0x00fb, "ucircumflex"}, - {0x00fc, "udieresis"}, - {0x00f9, "ugrave"}, - {0x01b0, "uhorn"}, - {0x0171, "uhungarumlaut"}, - {0x016b, "umacron"}, - {0x005f, "underscore"}, - {0x2017, "underscoredbl"}, - {0x222a, "union"}, - {0x2200, "universal"}, - {0x0173, "uogonek"}, - {0x2580, "upblock"}, - {0x03c5, "upsilon"}, - {0x03cb, "upsilondieresis"}, - {0x03b0, "upsilondieresistonos"}, - {0x03cd, "upsilontonos"}, - {0x016f, "uring"}, - {0x0169, "utilde"}, - {0x0076, "v"}, - {0x0077, "w"}, - {0x1e83, "wacute"}, - {0x0175, "wcircumflex"}, - {0x1e85, "wdieresis"}, - {0x2118, "weierstrass"}, - {0x1e81, "wgrave"}, - {0x0078, "x"}, - {0x03be, "xi"}, - {0x0079, "y"}, - {0x00fd, "yacute"}, - {0x0177, "ycircumflex"}, - {0x00ff, "ydieresis"}, - {0x00a5, "yen"}, - {0x1ef3, "ygrave"}, - {0x007a, "z"}, - {0x017a, "zacute"}, - {0x017e, "zcaron"}, - {0x017c, "zdotaccent"}, - {0x0030, "zero"}, - {0x2080, "zeroinferior"}, - {0xf730, "zerooldstyle"}, - {0x2070, "zerosuperior"}, - {0x03b6, "zeta"}, - {0x007b, "{"}, - {0x007c, "|"}, - {0x007d, "}"}, - {0x007e, "~"}, - { 0, NULL } -}; diff --git a/pdf2swf/xpdf/Object.cc b/pdf2swf/xpdf/Object.cc deleted file mode 100644 index 71c632a..0000000 --- a/pdf2swf/xpdf/Object.cc +++ /dev/null @@ -1,231 +0,0 @@ -//======================================================================== -// -// Object.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "Object.h" -#include "Array.h" -#include "Dict.h" -#include "Error.h" -#include "Stream.h" -#include "XRef.h" - -//------------------------------------------------------------------------ -// Object -//------------------------------------------------------------------------ - -char *objTypeNames[numObjTypes] = { - "boolean", - "integer", - "real", - "string", - "name", - "null", - "array", - "dictionary", - "stream", - "ref", - "cmd", - "error", - "eof", - "none" -}; - -#ifdef DEBUG_MEM -int Object::numAlloc[numObjTypes] = - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; -#endif - -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: - stream->incRef(); - break; - case objCmd: - obj->cmd = copyString(cmd); - break; - default: - break; - } -#ifdef DEBUG_MEM - ++numAlloc[type]; -#endif - return obj; -} - -Object *Object::fetch(XRef *xref, Object *obj) { - return (type == objRef && xref) ? - xref->fetch(ref.num, ref.gen, obj) : 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: - if (!stream->decRef()) { - delete stream; - } - break; - case objCmd: - gfree(cmd); - break; - default: - break; - } -#ifdef DEBUG_MEM - --numAlloc[type]; -#endif - type = objNone; -} - -char *Object::getTypeName() { - return objTypeNames[type]; -} - -void Object::print(FILE *f) { - Object obj; - int i; - - switch (type) { - case objBool: - fprintf(f, "%s", booln ? "true" : "false"); - break; - case objInt: - fprintf(f, "%d", intg); - break; - case objReal: - fprintf(f, "%g", real); - break; - case objString: - fprintf(f, "("); - fwrite(string->getCString(), 1, string->getLength(), f); - fprintf(f, ")"); - break; - case objName: - fprintf(f, "/%s", name); - break; - case objNull: - fprintf(f, "null"); - break; - case objArray: - fprintf(f, "["); - for (i = 0; i < arrayGetLength(); ++i) { - if (i > 0) - fprintf(f, " "); - arrayGetNF(i, &obj); - obj.print(f); - obj.free(); - } - fprintf(f, "]"); - break; - case objDict: - fprintf(f, "<<"); - for (i = 0; i < dictGetLength(); ++i) { - fprintf(f, " /%s ", dictGetKey(i)); - dictGetValNF(i, &obj); - obj.print(f); - obj.free(); - } - fprintf(f, " >>"); - break; - case objStream: - fprintf(f, ""); - break; - case objRef: - fprintf(f, "%d %d R", ref.num, ref.gen); - break; - case objCmd: - fprintf(f, "%s", cmd); - break; - case objError: - fprintf(f, ""); - break; - case objEOF: - fprintf(f, ""); - break; - case objNone: - fprintf(f, ""); - break; - } -} - -void Object::memCheck(FILE *f) { -#ifdef DEBUG_MEM - int i; - int 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: %6d\n", objTypeNames[i], numAlloc[i]); - } - } -#endif -} diff --git a/pdf2swf/xpdf/Object.h b/pdf2swf/xpdf/Object.h deleted file mode 100644 index 8b1807c..0000000 --- a/pdf2swf/xpdf/Object.h +++ /dev/null @@ -1,303 +0,0 @@ -//======================================================================== -// -// Object.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef OBJECT_H -#define OBJECT_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include -#include -#include "gtypes.h" -#include "gmem.h" -#include "GString.h" - -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 -#define initObj(t) ++numAlloc[type = t] -#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(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); - - // 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(char *nameA) - { return type == objName && !strcmp(name, nameA); } - GBool isDict(char *dictType); - GBool isStream(char *dictType); - GBool isCmd(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); - Object *arrayGetNF(int i, Object *obj); - - // Dict accessors. - int dictGetLength(); - void dictAdd(char *key, Object *val); - GBool dictIs(char *dictType); - Object *dictLookup(char *key, Object *obj); - Object *dictLookupNF(char *key, Object *obj); - 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(); - char *streamGetLine(char *buf, int size); - Guint streamGetPos(); - void streamSetPos(Guint pos, int dir = 0); - Dict *streamGetDict(); - - // Output. - 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 - static int // number of each type of object - numAlloc[numObjTypes]; // currently allocated -#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) - { return array->get(i, obj); } - -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(char *dictType) - { return dict->is(dictType); } - -inline GBool Object::isDict(char *dictType) - { return type == objDict && dictIs(dictType); } - -inline Object *Object::dictLookup(char *key, Object *obj) - { return dict->lookup(key, obj); } - -inline Object *Object::dictLookupNF(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 char *Object::streamGetLine(char *buf, int size) - { return stream->getLine(buf, size); } - -inline Guint Object::streamGetPos() - { return stream->getPos(); } - -inline void Object::streamSetPos(Guint pos, int dir) - { stream->setPos(pos, dir); } - -inline Dict *Object::streamGetDict() - { return stream->getDict(); } - -#endif diff --git a/pdf2swf/xpdf/Outline.cc b/pdf2swf/xpdf/Outline.cc deleted file mode 100644 index 39e89a3..0000000 --- a/pdf2swf/xpdf/Outline.cc +++ /dev/null @@ -1,151 +0,0 @@ -//======================================================================== -// -// Outline.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "gmem.h" -#include "GString.h" -#include "GList.h" -#include "Link.h" -#include "PDFDocEncoding.h" -#include "Outline.h" - -//------------------------------------------------------------------------ - -Outline::Outline(Object *outlineObj, XRef *xref) { - Object first, last; - - items = NULL; - if (!outlineObj->isDict()) { - return; - } - items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first), - outlineObj->dictLookupNF("Last", &last), - xref); - first.free(); - last.free(); -} - -Outline::~Outline() { - if (items) { - deleteGList(items, OutlineItem); - } -} - -//------------------------------------------------------------------------ - -OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) { - Object obj1; - GString *s; - int i; - - xref = xrefA; - title = NULL; - action = NULL; - kids = NULL; - - if (dict->lookup("Title", &obj1)->isString()) { - s = obj1.getString(); - if ((s->getChar(0) & 0xff) == 0xfe && - (s->getChar(1) & 0xff) == 0xff) { - titleLen = (s->getLength() - 2) / 2; - title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); - for (i = 0; i < titleLen; ++i) { - title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) | - (s->getChar(3 + 2*i) & 0xff); - } - } else { - titleLen = s->getLength(); - title = (Unicode *)gmallocn(titleLen, sizeof(Unicode)); - for (i = 0; i < titleLen; ++i) { - title[i] = pdfDocEncoding[s->getChar(i) & 0xff]; - } - } - } else { - titleLen = 0; - } - 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(); - - 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(); -} - -OutlineItem::~OutlineItem() { - close(); - if (title) { - gfree(title); - } - if (action) { - delete action; - } - firstRef.free(); - lastRef.free(); - nextRef.free(); -} - -GList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef, - XRef *xrefA) { - GList *items; - OutlineItem *item; - Object obj; - Object *p; - - items = new GList(); - p = firstItemRef; - while (p->isRef()) { - if (!p->fetch(xrefA, &obj)->isDict()) { - obj.free(); - break; - } - item = new OutlineItem(obj.getDict(), xrefA); - obj.free(); - items->append(item); - if (p->getRef().num == lastItemRef->getRef().num && - p->getRef().gen == lastItemRef->getRef().gen) { - break; - } - p = &item->nextRef; - } - return items; -} - -void OutlineItem::open() { - if (!kids) { - kids = readItemList(&firstRef, &lastRef, xref); - } -} - -void OutlineItem::close() { - if (kids) { - deleteGList(kids, OutlineItem); - kids = NULL; - } -} diff --git a/pdf2swf/xpdf/Outline.h b/pdf2swf/xpdf/Outline.h deleted file mode 100644 index f38f8d1..0000000 --- a/pdf2swf/xpdf/Outline.h +++ /dev/null @@ -1,76 +0,0 @@ -//======================================================================== -// -// Outline.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef OUTLINE_H -#define OUTLINE_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" -#include "CharTypes.h" - -class GString; -class GList; -class XRef; -class LinkAction; - -//------------------------------------------------------------------------ - -class 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(Dict *dict, XRef *xrefA); - ~OutlineItem(); - - static GList *readItemList(Object *firstItemRef, Object *lastItemRef, - XRef *xrefA); - - void open(); - void close(); - - Unicode *getTitle() { return title; } - int getTitleLength() { return titleLen; } - LinkAction *getAction() { return action; } - GBool isOpen() { return startsOpen; } - GBool hasKids() { return firstRef.isRef(); } - GList *getKids() { return kids; } - -private: - - XRef *xref; - Unicode *title; - int titleLen; - LinkAction *action; - Object firstRef; - Object lastRef; - Object nextRef; - GBool startsOpen; - GList *kids; // NULL unless this item is open [OutlineItem] -}; - -#endif diff --git a/pdf2swf/xpdf/OutputDev.cc b/pdf2swf/xpdf/OutputDev.cc deleted file mode 100644 index cfa4161..0000000 --- a/pdf2swf/xpdf/OutputDev.cc +++ /dev/null @@ -1,129 +0,0 @@ -//======================================================================== -// -// OutputDev.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#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, 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); - updateFillColorSpace(state); - updateFillColor(state); - updateStrokeColorSpace(state); - updateStrokeColor(state); - updateBlendMode(state); - updateFillOpacity(state); - updateStrokeOpacity(state); - updateFillOverprint(state); - updateStrokeOverprint(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) { - int i, j; - - if (inlineImg) { - str->reset(); - j = height * ((width + 7) / 8); - for (i = 0; i < j; ++i) - str->getChar(); - str->close(); - } -} - -void OutputDev::drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg) { - int i, j; - - if (inlineImg) { - str->reset(); - j = height * ((width * colorMap->getNumPixelComps() * - colorMap->getBits() + 7) / 8); - for (i = 0; i < j; ++i) - str->getChar(); - str->close(); - } -} - -void OutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GBool maskInvert) { - drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); -} - -void OutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap) { - drawImage(state, ref, str, width, height, colorMap, NULL, gFalse); -} - -#if OPI_SUPPORT -void OutputDev::opiBegin(GfxState *state, Dict *opiDict) { -} - -void OutputDev::opiEnd(GfxState *state, Dict *opiDict) { -} -#endif diff --git a/pdf2swf/xpdf/OutputDev.h b/pdf2swf/xpdf/OutputDev.h deleted file mode 100644 index 8d2c9f3..0000000 --- a/pdf2swf/xpdf/OutputDev.h +++ /dev/null @@ -1,205 +0,0 @@ -//======================================================================== -// -// OutputDev.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef OUTPUTDEV_H -#define OUTPUTDEV_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "CharTypes.h" - -class GString; -class GfxState; -class GfxColorSpace; -class GfxImageColorMap; -class GfxFunctionShading; -class GfxAxialShading; -class GfxRadialShading; -class Stream; -class Link; -class Catalog; - -//------------------------------------------------------------------------ -// 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 functionShadedFill(), axialShadedFill(), and - // radialShadedFill()? If this returns false, these shaded fills - // will be reduced to a series of other drawing operations. - virtual GBool useShadedFills() { return 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; } - - //----- initialization and control - - // Set default transform matrix. - virtual void setDefaultCTM(double *ctm); - - // Start a page. - virtual void startPage(int pageNum, GfxState *state, double x1,double y1,double x2,double y2) {} - - // End a page. - virtual void endPage() {} - - // Dump page contents to display. - virtual void dump() {} - - //----- 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, int *dx, int *dy); - - double *getDefCTM() { return defCTM; } - double *getDefICTM() { return defICTM; } - - //----- link borders - virtual void drawLink(Link *link, Catalog *catalog) {} - - //----- save/restore graphics state - virtual void saveState(GfxState *state) {} - virtual void restoreState(GfxState *state) {} - - //----- 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 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) {} - - //----- 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) {} - - //----- path painting - virtual void stroke(GfxState *state) {} - virtual void fill(GfxState *state) {} - virtual void eoFill(GfxState *state) {} - virtual void tilingPatternFill(GfxState *state, Object *str, - int paintType, Dict *resDict, - double *mat, double *bbox, - int x0, int y0, int x1, int y1, - double xStep, double yStep) {} - virtual void functionShadedFill(GfxState *state, - GfxFunctionShading *shading) {} - virtual void axialShadedFill(GfxState *state, GfxAxialShading *shading) {} - virtual void radialShadedFill(GfxState *state, GfxRadialShading *shading) {} - - //----- 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 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) {} - - //----- image drawing - virtual void drawImageMask(GfxState *state, Object *ref, Stream *str, - int width, int height, GBool invert, - GBool inlineImg); - virtual void drawImage(GfxState *state, Object *ref, Stream *str, - int width, int height, GfxImageColorMap *colorMap, - int *maskColors, GBool inlineImg); - virtual void drawMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, int maskWidth, int maskHeight, - GBool maskInvert); - virtual void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, - int width, int height, - GfxImageColorMap *colorMap, - Stream *maskStr, - int maskWidth, int maskHeight, - GfxImageColorMap *maskColorMap); - -#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) {} - - //----- PostScript XObjects - virtual void psXObject(Stream *psStream, Stream *level1Stream) {} - -private: - - double defCTM[6]; // default coordinate transform matrix - double defICTM[6]; // inverse of default CTM -}; - -#endif diff --git a/pdf2swf/xpdf/PDFDoc.cc b/pdf2swf/xpdf/PDFDoc.cc deleted file mode 100644 index 92863e4..0000000 --- a/pdf2swf/xpdf/PDFDoc.cc +++ /dev/null @@ -1,431 +0,0 @@ -//======================================================================== -// -// PDFDoc.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#ifdef WIN32 -# include -#endif -#include "GString.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" -#ifndef DISABLE_OUTLINE -#include "Outline.h" -#endif -#include "PDFDoc.h" - -//------------------------------------------------------------------------ - -#define headerSearchSize 1024 // read this many bytes at beginning of - // file to look for '%PDF' - -//------------------------------------------------------------------------ -// PDFDoc -//------------------------------------------------------------------------ - -PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword, - GString *userPassword, void *guiDataA) { - Object obj; - GString *fileName1, *fileName2; - - ok = gFalse; - errCode = errNone; - - guiData = guiDataA; - - file = NULL; - str = NULL; - xref = NULL; - catalog = NULL; - links = NULL; -#ifndef DISABLE_OUTLINE - outline = NULL; -#endif - - fileName = fileNameA; - fileName1 = fileName; - - - // try to open file - fileName2 = NULL; -#ifdef VMS - if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) { - error(-1, "Couldn't open file '%s'", fileName1->getCString()); - errCode = errOpenFile; - return; - } -#else - if (!(file = fopen(fileName1->getCString(), "rb"))) { - fileName2 = fileName->copy(); - fileName2->lowerCase(); - if (!(file = fopen(fileName2->getCString(), "rb"))) { - fileName2->upperCase(); - if (!(file = fopen(fileName2->getCString(), "rb"))) { - error(-1, "Couldn't open file '%s'", fileName->getCString()); - 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, void *guiDataA) { - OSVERSIONINFO version; - wchar_t fileName2[_MAX_PATH + 1]; - Object obj; - int i; - - ok = gFalse; - errCode = errNone; - - guiData = guiDataA; - - file = NULL; - str = NULL; - xref = NULL; - catalog = NULL; - links = NULL; -#ifndef DISABLE_OUTLINE - outline = NULL; -#endif - - //~ file name should be stored in Unicode (?) - fileName = new GString(); - for (i = 0; i < fileNameLen; ++i) { - fileName->append((char)fileNameA[i]); - } - - // zero-terminate the file name string - for (i = 0; i < fileNameLen && i < _MAX_PATH; ++i) { - fileName2[i] = fileNameA[i]; - } - fileName2[i] = 0; - - // try to open file - // NB: _wfopen is only available in NT - version.dwOSVersionInfoSize = sizeof(version); - GetVersionEx(&version); - if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) { - file = _wfopen(fileName2, L"rb"); - } else { - file = fopen(fileName->getCString(), "rb"); - } - if (!file) { - error(-1, "Couldn't open file '%s'", fileName->getCString()); - errCode = errOpenFile; - return; - } - - // create stream - obj.initNull(); - str = new FileStream(file, 0, gFalse, 0, &obj); - - ok = setup(ownerPassword, userPassword); -} -#endif - -PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword, - GString *userPassword, void *guiDataA) { - ok = gFalse; - errCode = errNone; - guiData = guiDataA; - fileName = NULL; - file = NULL; - str = strA; - xref = NULL; - catalog = NULL; - links = NULL; -#ifndef DISABLE_OUTLINE - outline = NULL; -#endif - ok = setup(ownerPassword, userPassword); -} - -GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) { - str->reset(); - - // check header - checkHeader(); - - // read xref table - xref = new XRef(str); - if (!xref->isOk()) { - error(-1, "Couldn't read xref table"); - errCode = xref->getErrorCode(); - return gFalse; - } - - // check for encryption - if (!checkEncryption(ownerPassword, userPassword)) { - errCode = errEncrypted; - return gFalse; - } - - // read catalog - catalog = new Catalog(xref); - if (!catalog->isOk()) { - error(-1, "Couldn't read page catalog"); - errCode = errBadCatalog; - return gFalse; - } - -#ifndef DISABLE_OUTLINE - // read outline - outline = new Outline(catalog->getOutline(), xref); -#endif - - // done - return gTrue; -} - -PDFDoc::~PDFDoc() { -#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; - } - if (links) { - delete links; - } -} - -// 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; - for (i = 0; i < headerSearchSize; ++i) { - hdrBuf[i] = str->getChar(); - } - hdrBuf[headerSearchSize] = '\0'; - for (i = 0; i < headerSearchSize - 5; ++i) { - if (!strncmp(&hdrBuf[i], "%PDF-", 5)) { - break; - } - } - if (i >= headerSearchSize - 5) { - error(-1, "May not be a PDF file (continuing anyway)"); - return; - } - str->moveStart(i); - if (!(p = strtok(&hdrBuf[i+5], " \t\n\r"))) { - error(-1, "May not be a PDF file (continuing anyway)"); - return; - } - pdfVersion = atof(p); - if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') || - pdfVersion > supportedPDFVersionNum + 0.0001) { - error(-1, "PDF version %s -- xpdf supports version %s" - " (continuing anyway)", p, supportedPDFVersionStr); - } -} - -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->checkEncryption(ownerPassword, userPassword)) { - // authorization succeeded - xref->setEncryption(secHdlr->getPermissionFlags(), - secHdlr->getOwnerPasswordOk(), - secHdlr->getFileKey(), - secHdlr->getFileKeyLength(), - secHdlr->getEncVersion()); - 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 doLinks, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - Page *p; - - if (globalParams->getPrintCommands()) { - printf("***** page %d *****\n", page); - } - p = catalog->getPage(page); - if (doLinks) { - if (links) { - delete links; - } - getLinks(p); - p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, links, catalog, - abortCheckCbk, abortCheckCbkData); - } else { - p->display(out, hDPI, vDPI, rotate, useMediaBox, crop, NULL, catalog, - abortCheckCbk, abortCheckCbkData); - } -} - -void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - int page; - - for (page = firstPage; page <= lastPage; ++page) { - displayPage(out, page, hDPI, vDPI, rotate, useMediaBox, crop, doLinks, - abortCheckCbk, abortCheckCbkData); - } -} - -void PDFDoc::displayPageSlice(OutputDev *out, int page, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - int sliceX, int sliceY, int sliceW, int sliceH, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - Page *p; - - p = catalog->getPage(page); - if (doLinks) { - if (links) { - delete links; - } - getLinks(p); - p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, - sliceX, sliceY, sliceW, sliceH, - links, catalog, abortCheckCbk, abortCheckCbkData); - } else { - p->displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, - sliceX, sliceY, sliceW, sliceH, - NULL, catalog, abortCheckCbk, abortCheckCbkData); - } -} - -Links *PDFDoc::takeLinks() { - Links *ret; - - ret = links; - links = NULL; - return ret; -} - -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))); - 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; - int c; - - if (!(f = fopen(name->getCString(), "wb"))) { - error(-1, "Couldn't open file '%s'", name->getCString()); - return gFalse; - } - str->reset(); - while ((c = str->getChar()) != EOF) { - fputc(c, f); - } - str->close(); - fclose(f); - return gTrue; -} - -void PDFDoc::getLinks(Page *page) { - Object obj; - - links = new Links(page->getAnnots(&obj), catalog->getBaseURI()); - obj.free(); -} diff --git a/pdf2swf/xpdf/PDFDoc.h b/pdf2swf/xpdf/PDFDoc.h deleted file mode 100644 index a1f42c0..0000000 --- a/pdf2swf/xpdf/PDFDoc.h +++ /dev/null @@ -1,182 +0,0 @@ -//======================================================================== -// -// PDFDoc.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PDFDOC_H -#define PDFDOC_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include -#include "XRef.h" -#include "Catalog.h" -#include "Page.h" - -class GString; -class BaseStream; -class OutputDev; -class Links; -class LinkAction; -class LinkDest; -class Outline; - -//------------------------------------------------------------------------ -// PDFDoc -//------------------------------------------------------------------------ - -class PDFDoc { -public: - - PDFDoc(GString *fileNameA, GString *ownerPassword = NULL, - GString *userPassword = NULL, void *guiDataA = NULL); -#ifdef WIN32 - PDFDoc(wchar_t *fileNameA, int fileNameLen, GString *ownerPassword = NULL, - GString *userPassword = NULL, void *guiDataA = NULL); -#endif - PDFDoc(BaseStream *strA, GString *ownerPassword = NULL, - GString *userPassword = NULL, void *guiDataA = 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; } - - // 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 doLinks, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Display a range of pages. - void displayPages(OutputDev *out, int firstPage, int lastPage, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Display part of a page. - void displayPageSlice(OutputDev *out, int page, - double hDPI, double vDPI, int rotate, - GBool useMediaBox, GBool crop, GBool doLinks, - 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 *takeLinks(); - - // Find a named destination. Returns the link destination, or - // NULL if is not a destination. - LinkDest *findDest(GString *name) - { return catalog->findDest(name); } - -#ifndef DISABLE_OUTLINE - // Return the outline object. - Outline *getOutline() { return outline; } -#endif - - // 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 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 GUI (XPDFCore or WinPDFCore object). - void *getGUIData() { return guiData; } - - -private: - - GBool setup(GString *ownerPassword, GString *userPassword); - void checkHeader(); - GBool checkEncryption(GString *ownerPassword, GString *userPassword); - void getLinks(Page *page); - - GString *fileName; - FILE *file; - BaseStream *str; - void *guiData; - double pdfVersion; - XRef *xref; - Catalog *catalog; - Links *links; -#ifndef DISABLE_OUTLINE - Outline *outline; -#endif - - - GBool ok; - int errCode; -}; - -#endif diff --git a/pdf2swf/xpdf/PDFDocEncoding.cc b/pdf2swf/xpdf/PDFDocEncoding.cc deleted file mode 100644 index 89dc382..0000000 --- a/pdf2swf/xpdf/PDFDocEncoding.cc +++ /dev/null @@ -1,44 +0,0 @@ -//======================================================================== -// -// PDFDocEncoding.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include "PDFDocEncoding.h" - -Unicode pdfDocEncoding[256] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 00 - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, // 10 - 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/pdf2swf/xpdf/PDFDocEncoding.h b/pdf2swf/xpdf/PDFDocEncoding.h deleted file mode 100644 index 3259d3e..0000000 --- a/pdf2swf/xpdf/PDFDocEncoding.h +++ /dev/null @@ -1,16 +0,0 @@ -//======================================================================== -// -// 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/pdf2swf/xpdf/PSTokenizer.cc b/pdf2swf/xpdf/PSTokenizer.cc deleted file mode 100644 index a65c324..0000000 --- a/pdf2swf/xpdf/PSTokenizer.cc +++ /dev/null @@ -1,135 +0,0 @@ -//======================================================================== -// -// PSTokenizer.cc -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#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++] = c; - if (c == '(') { - backslash = gFalse; - while ((c = lookChar()) != EOF) { - if (i < size - 1) { - buf[i++] = 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) { - buf[i++] = c; - } - if (c == '>') { - break; - } - } - } else if (c != '[' && c != ']') { - while ((c = lookChar()) != EOF && !specialChars[c]) { - getChar(); - if (i < size - 1) { - buf[i++] = 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/pdf2swf/xpdf/PSTokenizer.h b/pdf2swf/xpdf/PSTokenizer.h deleted file mode 100644 index 4d5ee97..0000000 --- a/pdf2swf/xpdf/PSTokenizer.h +++ /dev/null @@ -1,41 +0,0 @@ -//======================================================================== -// -// PSTokenizer.h -// -// Copyright 2002-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PSTOKENIZER_H -#define PSTOKENIZER_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" - -//------------------------------------------------------------------------ - -class PSTokenizer { -public: - - PSTokenizer(int (*getCharFuncA)(void *), void *dataA); - ~PSTokenizer(); - - // Get the next PostScript token. Returns false at end-of-stream. - GBool getToken(char *buf, int size, int *length); - -private: - - int lookChar(); - int getChar(); - - int (*getCharFunc)(void *); - void *data; - int charBuf; -}; - -#endif diff --git a/pdf2swf/xpdf/Page.cc b/pdf2swf/xpdf/Page.cc deleted file mode 100644 index 6ef8433..0000000 --- a/pdf2swf/xpdf/Page.cc +++ /dev/null @@ -1,367 +0,0 @@ -//======================================================================== -// -// Page.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "GlobalParams.h" -#include "Object.h" -#include "Array.h" -#include "Dict.h" -#include "XRef.h" -#include "Link.h" -#include "OutputDev.h" -#ifndef PDF_PARSER_ONLY -#include "Gfx.h" -#include "GfxState.h" -#include "Annot.h" -#endif -#include "Error.h" -#include "Page.h" - -//------------------------------------------------------------------------ -// PageAttrs -//------------------------------------------------------------------------ - -PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) { - Object obj1; - - // get old/default values - if (attrs) { - mediaBox = attrs->mediaBox; - cropBox = attrs->cropBox; - haveCropBox = attrs->haveCropBox; - rotate = attrs->rotate; - attrs->resources.copy(&resources); - } 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; - resources.initNull(); - } - - // 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); - - // resource dictionary - dict->lookup("Resources", &obj1); - if (obj1.isDict()) { - resources.free(); - obj1.copy(&resources); - } - obj1.free(); -} - -PageAttrs::~PageAttrs() { - lastModified.free(); - boxColorInfo.free(); - group.free(); - metadata.free(); - pieceInfo.free(); - separationInfo.free(); - resources.free(); -} - -GBool PageAttrs::readBox(Dict *dict, 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(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) { - ok = gTrue; - xref = xrefA; - num = numA; - - // get attributes - attrs = attrsA; - - // annotations - pageDict->lookupNF("Annots", &annots); - if (!(annots.isRef() || annots.isArray() || annots.isNull())) { - error(-1, "Page annotations object (page %d) is wrong type (%s)", - num, annots.getTypeName()); - annots.free(); - goto err2; - } - - // contents - pageDict->lookupNF("Contents", &contents); - if (!(contents.isRef() || contents.isArray() || - contents.isNull())) { - error(-1, "Page contents object (page %d) is wrong type (%s)", - num, contents.getTypeName()); - contents.free(); - goto err1; - } - - return; - - err2: - annots.initNull(); - err1: - contents.initNull(); - ok = gFalse; -} - -Page::~Page() { - delete attrs; - annots.free(); - contents.free(); -} - -void Page::display(OutputDev *out, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { - displaySlice(out, hDPI, vDPI, rotate, useMediaBox, crop, - -1, -1, -1, -1, links, catalog, - abortCheckCbk, abortCheckCbkData); -} - -void Page::displaySlice(OutputDev *out, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - int sliceX, int sliceY, int sliceW, int sliceH, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data), - void *abortCheckCbkData) { -#ifndef PDF_PARSER_ONLY - PDFRectangle *mediaBox, *cropBox, *baseBox; - PDFRectangle box; - Gfx *gfx; - Object obj; - Link *link; - Annots *annotList; - double kx, ky; - int i; - - rotate += getRotate(); - if (rotate >= 360) { - rotate -= 360; - } else if (rotate < 0) { - rotate += 360; - } - - 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 (out->upsideDown()) { - box.x1 = baseBox->x1 + ky * sliceY; - box.x2 = baseBox->x1 + ky * (sliceY + sliceH); - } else { - box.x1 = baseBox->x2 - ky * (sliceY + sliceH); - box.x2 = baseBox->x2 - ky * sliceY; - } - box.y1 = baseBox->y1 + kx * sliceX; - box.y2 = baseBox->y1 + kx * (sliceX + sliceW); - } else if (rotate == 180) { - box.x1 = baseBox->x2 - kx * (sliceX + sliceW); - box.x2 = baseBox->x2 - kx * sliceX; - if (out->upsideDown()) { - box.y1 = baseBox->y1 + ky * sliceY; - box.y2 = baseBox->y1 + ky * (sliceY + sliceH); - } else { - box.y1 = baseBox->y2 - ky * (sliceY + sliceH); - box.y2 = baseBox->y2 - ky * sliceY; - } - } else if (rotate == 270) { - if (out->upsideDown()) { - box.x1 = baseBox->x2 - ky * (sliceY + sliceH); - box.x2 = baseBox->x2 - ky * sliceY; - } else { - box.x1 = baseBox->x1 + ky * sliceY; - box.x2 = baseBox->x1 + ky * (sliceY + sliceH); - } - box.y1 = baseBox->y2 - kx * (sliceX + sliceW); - box.y2 = baseBox->y2 - kx * sliceX; - } else { - box.x1 = baseBox->x1 + kx * sliceX; - box.x2 = baseBox->x1 + kx * (sliceX + sliceW); - if (out->upsideDown()) { - box.y1 = baseBox->y2 - ky * (sliceY + sliceH); - box.y2 = baseBox->y2 - ky * sliceY; - } else { - box.y1 = baseBox->y1 + ky * sliceY; - box.y2 = baseBox->y1 + ky * (sliceY + sliceH); - } - } - } else if (useMediaBox) { - box = *mediaBox; - } else { - box = *cropBox; - crop = gFalse; - } - - if (globalParams->getPrintCommands()) { - 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(xref, 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(&obj); - gfx->restoreState(); - } - obj.free(); - - // draw links - if (links) { - gfx->saveState(); - for (i = 0; i < links->getNumLinks(); ++i) { - link = links->getLink(i); - out->drawLink(link, catalog); - } - gfx->restoreState(); - out->dump(); - } - - // draw non-link annotations - annotList = new Annots(xref, catalog, annots.fetch(xref, &obj)); - obj.free(); - if (annotList->getNumAnnots() > 0) { - if (globalParams->getPrintCommands()) { - printf("***** Annotations\n"); - } - for (i = 0; i < annotList->getNumAnnots(); ++i) { - annotList->getAnnot(i)->draw(gfx); - } - out->dump(); - } - delete annotList; - - delete gfx; -#endif -} - -void Page::getDefaultCTM(double *ctm, double hDPI, double vDPI, - int rotate, GBool upsideDown) { - GfxState *state; - int i; - - rotate += getRotate(); - if (rotate >= 360) { - rotate -= 360; - } else if (rotate < 0) { - rotate += 360; - } - state = new GfxState(hDPI, vDPI, getMediaBox(), rotate, upsideDown); - for (i = 0; i < 6; ++i) { - ctm[i] = state->getCTM()[i]; - } - delete state; -} diff --git a/pdf2swf/xpdf/Page.h b/pdf2swf/xpdf/Page.h deleted file mode 100644 index 36f96e1..0000000 --- a/pdf2swf/xpdf/Page.h +++ /dev/null @@ -1,175 +0,0 @@ -//======================================================================== -// -// Page.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PAGE_H -#define PAGE_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Object.h" - -class Dict; -class XRef; -class OutputDev; -class Links; -class Catalog; - -//------------------------------------------------------------------------ - -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; } -}; - -//------------------------------------------------------------------------ -// PageAttrs -//------------------------------------------------------------------------ - -class PageAttrs { -public: - - // Construct a new PageAttrs object by merging a dictionary - // (of type Pages or Page) into another PageAttrs object. If - // is NULL, uses defaults. - PageAttrs(PageAttrs *attrs, Dict *dict); - - // 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; } - Dict *getResourceDict() - { return resources.isDict() ? resources.getDict() : (Dict *)NULL; } - -private: - - GBool readBox(Dict *dict, 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; - Object resources; -}; - -//------------------------------------------------------------------------ -// Page -//------------------------------------------------------------------------ - -class Page { -public: - - // Constructor. - Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA); - - // Destructor. - ~Page(); - - // Is page valid? - GBool isOk() { return ok; } - - // Get page parameters. - 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(); } - - // Get resource dictionary. - Dict *getResourceDict() { return attrs->getResourceDict(); } - - // Get annotations array. - Object *getAnnots(Object *obj) { return annots.fetch(xref, obj); } - - // Get contents. - Object *getContents(Object *obj) { return contents.fetch(xref, obj); } - - // Display a page. - void display(OutputDev *out, double hDPI, double vDPI, - int rotate, GBool useMediaBox, GBool crop, - Links *links, Catalog *catalog, - GBool (*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, - Links *links, Catalog *catalog, - GBool (*abortCheckCbk)(void *data) = NULL, - void *abortCheckCbkData = NULL); - - // Get the page's default CTM. - void getDefaultCTM(double *ctm, double hDPI, double vDPI, - int rotate, GBool upsideDown); - -private: - - 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 - GBool ok; // true if page is valid -}; - -#endif diff --git a/pdf2swf/xpdf/Parser.cc b/pdf2swf/xpdf/Parser.cc deleted file mode 100644 index af7c933..0000000 --- a/pdf2swf/xpdf/Parser.cc +++ /dev/null @@ -1,214 +0,0 @@ -//======================================================================== -// -// Parser.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include "Object.h" -#include "Array.h" -#include "Dict.h" -#include "Parser.h" -#include "XRef.h" -#include "Error.h" -#include "Decrypt.h" - -Parser::Parser(XRef *xrefA, Lexer *lexerA) { - xref = xrefA; - lexer = lexerA; - inlineImg = 0; - lexer->getObj(&buf1); - lexer->getObj(&buf2); -} - -Parser::~Parser() { - buf1.free(); - buf2.free(); - delete lexer; -} - -Object *Parser::getObj(Object *obj, - Guchar *fileKey, int keyLength, - int objNum, int objGen) { - char *key; - Stream *str; - Object obj2; - int num; - Decrypt *decrypt; - GString *s; - char *p; - int i; - - // refill buffer after inline image data - if (inlineImg == 2) { - buf1.free(); - buf2.free(); - lexer->getObj(&buf1); - lexer->getObj(&buf2); - inlineImg = 0; - } - - // array - if (buf1.isCmd("[")) { - shift(); - obj->initArray(xref); - while (!buf1.isCmd("]") && !buf1.isEOF()) - obj->arrayAdd(getObj(&obj2, fileKey, keyLength, objNum, objGen)); - if (buf1.isEOF()) - error(getPos(), "End of file inside array"); - shift(); - - // dictionary or stream - } else if (buf1.isCmd("<<")) { - shift(); - obj->initDict(xref); - while (!buf1.isCmd(">>") && !buf1.isEOF()) { - if (!buf1.isName()) { - error(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, fileKey, keyLength, objNum, objGen)); - } - } - if (buf1.isEOF()) - error(getPos(), "End of file inside dictionary"); - if (buf2.isCmd("stream")) { - if ((str = makeStream(obj))) { - obj->initStream(str); - if (fileKey) { - str->getBaseStream()->doDecryption(fileKey, keyLength, - objNum, objGen); - } - } 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) { - buf1.copy(obj); - s = obj->getString(); - decrypt = new Decrypt(fileKey, keyLength, objNum, objGen); - for (i = 0, p = obj->getString()->getCString(); - i < s->getLength(); - ++i, ++p) { - *p = decrypt->decryptByte(*p); - } - delete decrypt; - shift(); - - // simple object - } else { - buf1.copy(obj); - shift(); - } - - return obj; -} - -Stream *Parser::makeStream(Object *dict) { - Object obj; - BaseStream *baseStr; - Stream *str; - Guint pos, endPos, length; - - // get stream start position - lexer->skipToNextLine(); - pos = lexer->getPos(); - - // get length - dict->dictLookup("Length", &obj); - if (obj.isInt()) { - length = (Guint)obj.getInt(); - obj.free(); - } else { - error(getPos(), "Bad 'Length' attribute in stream"); - obj.free(); - return NULL; - } - - // check for length in damaged file - if (xref && xref->getStreamEnd(pos, &endPos)) { - length = endPos - pos; - } - - // 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; - } - baseStr = lexer->getStream()->getBaseStream(); - - // skip over stream data - lexer->setPos(pos + length); - - // refill token buffers and check for 'endstream' - shift(); // kill '>>' - shift(); // kill 'stream' - if (buf1.isCmd("endstream")) { - shift(); - } else { - error(getPos(), "Missing 'endstream'"); - // kludge for broken PDF files: just add 5k to the length, and - // hope its enough - length += 5000; - } - - // make base stream - str = baseStr->makeSubStream(pos, gTrue, length, dict); - - // get filters - str = str->addFilters(dict); - - 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/pdf2swf/xpdf/Parser.h b/pdf2swf/xpdf/Parser.h deleted file mode 100644 index b583baf..0000000 --- a/pdf2swf/xpdf/Parser.h +++ /dev/null @@ -1,56 +0,0 @@ -//======================================================================== -// -// Parser.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef PARSER_H -#define PARSER_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "Lexer.h" - -//------------------------------------------------------------------------ -// Parser -//------------------------------------------------------------------------ - -class Parser { -public: - - // Constructor. - Parser(XRef *xrefA, Lexer *lexerA); - - // Destructor. - ~Parser(); - - // Get the next object from the input stream. - Object *getObj(Object *obj, - Guchar *fileKey = NULL, int keyLength = 0, - int objNum = 0, int objGen = 0); - - // Get stream. - Stream *getStream() { return lexer->getStream(); } - - // Get current position in file. - int getPos() { return lexer->getPos(); } - -private: - - XRef *xref; // the xref table for this PDF file - Lexer *lexer; // input stream - Object buf1, buf2; // next two tokens - int inlineImg; // set when inline image data is encountered - - Stream *makeStream(Object *dict); - void shift(); -}; - -#endif - diff --git a/pdf2swf/xpdf/SecurityHandler.cc b/pdf2swf/xpdf/SecurityHandler.cc deleted file mode 100644 index 8825ce8..0000000 --- a/pdf2swf/xpdf/SecurityHandler.cc +++ /dev/null @@ -1,376 +0,0 @@ -//======================================================================== -// -// SecurityHandler.cc -// -// Copyright 2004 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include "GString.h" -#include "PDFDoc.h" -#include "Decrypt.h" -#include "Error.h" -#include "GlobalParams.h" -#if HAVE_XPDFCORE -# include "XPDFCore.h" -#elif HAVE_WINPDFCORE -# include "WinPDFCore.h" -#endif -#ifdef ENABLE_PLUGINS -# include "XpdfPluginAPI.h" -#endif -#include "SecurityHandler.h" - -//------------------------------------------------------------------------ -// SecurityHandler -//------------------------------------------------------------------------ - -SecurityHandler *SecurityHandler::make(PDFDoc *docA, Object *encryptDictA) { - Object filterObj; - SecurityHandler *secHdlr; - XpdfSecurityHandler *xsh; - - encryptDictA->dictLookup("Filter", &filterObj); - if (filterObj.isName("Standard")) { - secHdlr = new StandardSecurityHandler(docA, encryptDictA); - } else if (filterObj.isName()) { -#ifdef ENABLE_PLUGINS - if ((xsh = globalParams->getSecurityHandler(filterObj.getName()))) { - secHdlr = new ExternalSecurityHandler(docA, encryptDictA, xsh); - } else { -#endif - error(-1, "Couldn't find the '%s' security handler", - filterObj.getName()); - secHdlr = NULL; -#ifdef ENABLE_PLUGINS - } -#endif - } else { - error(-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(-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, permObj, fileIDObj; - Object fileIDObj1; - Object cryptFiltersObj, streamFilterObj, stringFilterObj; - Object cryptFilterObj, cfmObj, cfLengthObj; - Object encryptMetadataObj; - - ok = gFalse; - fileID = NULL; - ownerKey = NULL; - userKey = NULL; - - encryptDictA->dictLookup("V", &versionObj); - encryptDictA->dictLookup("R", &revisionObj); - encryptDictA->dictLookup("Length", &lengthObj); - encryptDictA->dictLookup("O", &ownerKeyObj); - encryptDictA->dictLookup("U", &userKeyObj); - encryptDictA->dictLookup("P", &permObj); - doc->getXRef()->getTrailerDict()->dictLookup("ID", &fileIDObj); - if (versionObj.isInt() && - revisionObj.isInt() && - ownerKeyObj.isString() && ownerKeyObj.getString()->getLength() == 32 && - userKeyObj.isString() && userKeyObj.getString()->getLength() == 32 && - permObj.isInt()) { - encVersion = versionObj.getInt(); - encRevision = revisionObj.getInt(); - // revision 2 forces a 40-bit key - some buggy PDF generators - // set the Length value incorrectly - if (encRevision == 2 || !lengthObj.isInt()) { - fileKeyLength = 5; - } else { - fileKeyLength = lengthObj.getInt() / 8; - } - encryptMetadata = gTrue; - //~ this currently only handles a subset of crypt filter functionality - if (encVersion == 4 && encRevision == 4) { - encryptDictA->dictLookup("CF", &cryptFiltersObj); - encryptDictA->dictLookup("StmF", &streamFilterObj); - encryptDictA->dictLookup("StrF", &stringFilterObj); - if (cryptFiltersObj.isDict() && - streamFilterObj.isName() && - stringFilterObj.isName() && - !strcmp(streamFilterObj.getName(), stringFilterObj.getName())) { - if (cryptFiltersObj.dictLookup(streamFilterObj.getName(), - &cryptFilterObj)->isDict()) { - if (cryptFilterObj.dictLookup("CFM", &cfmObj)->isName("V2")) { - encVersion = 2; - encRevision = 3; - if (cryptFilterObj.dictLookup("Length", &cfLengthObj)->isInt()) { - //~ according to the spec, this should be cfLengthObj / 8 - fileKeyLength = cfLengthObj.getInt(); - } - cfLengthObj.free(); - } - cfmObj.free(); - } - cryptFilterObj.free(); - } - stringFilterObj.free(); - streamFilterObj.free(); - cryptFiltersObj.free(); - if (encryptDictA->dictLookup("EncryptMetadata", - &encryptMetadataObj)->isBool()) { - encryptMetadata = encryptMetadataObj.getBool(); - } - encryptMetadataObj.free(); - } - permFlags = permObj.getInt(); - ownerKey = ownerKeyObj.getString()->copy(); - userKey = userKeyObj.getString()->copy(); - if (encVersion >= 1 && encVersion <= 2 && - encRevision >= 2 && encRevision <= 3) { - if (fileIDObj.isArray()) { - if (fileIDObj.arrayGet(0, &fileIDObj1)->isString()) { - fileID = fileIDObj1.getString()->copy(); - } else { - fileID = new GString(); - } - fileIDObj1.free(); - } else { - fileID = new GString(); - } - ok = gTrue; - } else { - error(-1, "Unsupported version/revision (%d/%d) of Standard security handler", - encVersion, encRevision); - } - } else { - error(-1, "Weird encryption info"); - } - if (fileKeyLength > 16) { - fileKeyLength = 16; - } - fileIDObj.free(); - permObj.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; - } -} - -void *StandardSecurityHandler::makeAuthData(GString *ownerPassword, - GString *userPassword) { - return new StandardAuthData(ownerPassword ? ownerPassword->copy() - : (GString *)NULL, - userPassword ? userPassword->copy() - : (GString *)NULL); -} - -void *StandardSecurityHandler::getAuthData() { -#if HAVE_XPDFCORE - XPDFCore *core; - GString *password; - - if (!(core = (XPDFCore *)doc->getGUIData()) || - !(password = core->getPassword())) { - return NULL; - } - return new StandardAuthData(password, password->copy()); -#elif HAVE_WINPDFCORE - WinPDFCore *core; - GString *password; - - if (!(core = (WinPDFCore *)doc->getGUIData()) || - !(password = core->getPassword())) { - return NULL; - } - return new StandardAuthData(password, password->copy()); -#else - return NULL; -#endif -} - -void StandardSecurityHandler::freeAuthData(void *authData) { - 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, permFlags, fileID, - ownerPassword, userPassword, fileKey, - encryptMetadata, &ownerPasswordOk)) { - return gFalse; - } - return gTrue; -} - -#ifdef ENABLE_PLUGINS - -//------------------------------------------------------------------------ -// ExternalSecurityHandler -//------------------------------------------------------------------------ - -ExternalSecurityHandler::ExternalSecurityHandler(PDFDoc *docA, - Object *encryptDictA, - XpdfSecurityHandler *xshA): - SecurityHandler(docA) -{ - encryptDictA->copy(&encryptDict); - xsh = xshA; - ok = gFalse; - - if (!(*xsh->newDoc)(xsh->handlerData, (XpdfDoc)docA, - (XpdfObject)encryptDictA, &docData)) { - return; - } - - ok = gTrue; -} - -ExternalSecurityHandler::~ExternalSecurityHandler() { - (*xsh->freeDoc)(xsh->handlerData, docData); - encryptDict.free(); -} - -void *ExternalSecurityHandler::makeAuthData(GString *ownerPassword, - GString *userPassword) { - char *opw, *upw; - void *authData; - - opw = ownerPassword ? ownerPassword->getCString() : (char *)NULL; - upw = userPassword ? userPassword->getCString() : (char *)NULL; - if (!(*xsh->makeAuthData)(xsh->handlerData, docData, opw, upw, &authData)) { - return NULL; - } - return authData; -} - -void *ExternalSecurityHandler::getAuthData() { - void *authData; - - if (!(*xsh->getAuthData)(xsh->handlerData, docData, &authData)) { - return NULL; - } - return authData; -} - -void ExternalSecurityHandler::freeAuthData(void *authData) { - (*xsh->freeAuthData)(xsh->handlerData, docData, authData); -} - -GBool ExternalSecurityHandler::authorize(void *authData) { - char *key; - int length; - - if (!ok) { - return gFalse; - } - permFlags = (*xsh->authorize)(xsh->handlerData, docData, authData); - if (!(permFlags & xpdfPermissionOpen)) { - return gFalse; - } - if (!(*xsh->getKey)(xsh->handlerData, docData, &key, &length, &encVersion)) { - return gFalse; - } - if ((fileKeyLength = length) > 16) { - fileKeyLength = 16; - } - memcpy(fileKey, key, fileKeyLength); - (*xsh->freeKey)(xsh->handlerData, docData, key, length); - return gTrue; -} - -#endif // ENABLE_PLUGINS diff --git a/pdf2swf/xpdf/SecurityHandler.h b/pdf2swf/xpdf/SecurityHandler.h deleted file mode 100644 index 127acb7..0000000 --- a/pdf2swf/xpdf/SecurityHandler.h +++ /dev/null @@ -1,155 +0,0 @@ -//======================================================================== -// -// SecurityHandler.h -// -// Copyright 2004 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef SECURITYHANDLER_H -#define SECURITYHANDLER_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" - -class GString; -class PDFDoc; -struct XpdfSecurityHandler; - -//------------------------------------------------------------------------ -// SecurityHandler -//------------------------------------------------------------------------ - -class SecurityHandler { -public: - - static SecurityHandler *make(PDFDoc *docA, Object *encryptDictA); - - SecurityHandler(PDFDoc *docA); - virtual ~SecurityHandler(); - - // Check the document's encryption. If the document is encrypted, - // this will first try and (in - // "batch" mode), and if those fail, it will attempt to request a - // password from the user. This is the high-level function that - // calls the lower level functions for the specific security handler - // (requesting a password three times, etc.). Returns true if the - // document can be opened (if it's unencrypted, or if a correct - // password is obtained); false otherwise (encrypted and no correct - // password). - GBool checkEncryption(GString *ownerPassword, - GString *userPassword); - - // Create authorization data for the specified owner and user - // passwords. If the security handler doesn't support "batch" mode, - // this function should return NULL. - virtual void *makeAuthData(GString *ownerPassword, - GString *userPassword) = 0; - - // Construct authorization data, typically by prompting the user for - // a password. Returns an authorization data object, or NULL to - // cancel. - virtual void *getAuthData() = 0; - - // Free the authorization data returned by makeAuthData or - // getAuthData. - virtual void freeAuthData(void *authData) = 0; - - // Attempt to authorize the document, using the supplied - // authorization data (which may be NULL). Returns true if - // successful (i.e., if at least the right to open the document was - // granted). - virtual GBool authorize(void *authData) = 0; - - // Return the various authorization parameters. These are only - // valid after authorize has returned true. - virtual int getPermissionFlags() = 0; - virtual GBool getOwnerPasswordOk() = 0; - virtual Guchar *getFileKey() = 0; - virtual int getFileKeyLength() = 0; - virtual int getEncVersion() = 0; - -protected: - - PDFDoc *doc; -}; - -//------------------------------------------------------------------------ -// StandardSecurityHandler -//------------------------------------------------------------------------ - -class StandardSecurityHandler: public SecurityHandler { -public: - - StandardSecurityHandler(PDFDoc *docA, Object *encryptDictA); - virtual ~StandardSecurityHandler(); - - 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; } - -private: - - int permFlags; - GBool ownerPasswordOk; - Guchar fileKey[16]; - int fileKeyLength; - int encVersion; - int encRevision; - GBool encryptMetadata; - - GString *ownerKey, *userKey; - GString *fileID; - GBool ok; -}; - -#ifdef ENABLE_PLUGINS -//------------------------------------------------------------------------ -// ExternalSecurityHandler -//------------------------------------------------------------------------ - -class ExternalSecurityHandler: public SecurityHandler { -public: - - ExternalSecurityHandler(PDFDoc *docA, Object *encryptDictA, - XpdfSecurityHandler *xshA); - virtual ~ExternalSecurityHandler(); - - 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 gFalse; } - virtual Guchar *getFileKey() { return fileKey; } - virtual int getFileKeyLength() { return fileKeyLength; } - virtual int getEncVersion() { return encVersion; } - -private: - - Object encryptDict; - XpdfSecurityHandler *xsh; - void *docData; - int permFlags; - Guchar fileKey[16]; - int fileKeyLength; - int encVersion; - GBool ok; -}; -#endif // ENABLE_PLUGINS - -#endif diff --git a/pdf2swf/xpdf/Stream-CCITT.h b/pdf2swf/xpdf/Stream-CCITT.h deleted file mode 100644 index c4458fe..0000000 --- a/pdf2swf/xpdf/Stream-CCITT.h +++ /dev/null @@ -1,459 +0,0 @@ -//======================================================================== -// -// Stream-CCITT.h -// -// Tables for CCITT Fax decoding. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -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} -}; diff --git a/pdf2swf/xpdf/Stream.cc b/pdf2swf/xpdf/Stream.cc deleted file mode 100644 index 3306279..0000000 --- a/pdf2swf/xpdf/Stream.cc +++ /dev/null @@ -1,4572 +0,0 @@ -//======================================================================== -// -// Stream.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#ifndef WIN32 -#include -#endif -#include -#include -#include "gmem.h" -#include "gfile.h" -#include "config.h" -#include "Error.h" -#include "Object.h" -#include "Lexer.h" -#include "Decrypt.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 - -//------------------------------------------------------------------------ -// Stream (base class) -//------------------------------------------------------------------------ - -Stream::Stream() { - ref = 1; -} - -Stream::~Stream() { -} - -void Stream::close() { -} - -int Stream::getRawChar() { - error(-1, "Internal: called getRawChar() on non-predictor stream"); - return EOF; -} - -char *Stream::getLine(char *buf, int size) { - int i; - int c; - - if (lookChar() == EOF) - 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] = c; - } - buf[i] = '\0'; - return buf; -} - -GString *Stream::getPSFilter(int psLevel, char *indent) { - return new GString(); -} - -Stream *Stream::addFilters(Object *dict) { - Object obj, obj2; - Object params, params2; - Stream *str; - int i; - - str = this; - dict->dictLookup("Filter", &obj); - if (obj.isNull()) { - obj.free(); - dict->dictLookup("F", &obj); - } - dict->dictLookup("DecodeParms", ¶ms); - if (params.isNull()) { - params.free(); - dict->dictLookup("DP", ¶ms); - } - if (obj.isName()) { - str = makeFilter(obj.getName(), str, ¶ms); - } else if (obj.isArray()) { - for (i = 0; i < obj.arrayGetLength(); ++i) { - obj.arrayGet(i, &obj2); - if (params.isArray()) - params.arrayGet(i, ¶ms2); - else - params2.initNull(); - if (obj2.isName()) { - str = makeFilter(obj2.getName(), str, ¶ms2); - } else { - error(getPos(), "Bad filter name"); - str = new EOFStream(str); - } - obj2.free(); - params2.free(); - } - } else if (!obj.isNull()) { - error(getPos(), "Bad 'Filter' attribute in stream"); - } - obj.free(); - params.free(); - - return str; -} - -Stream *Stream::makeFilter(char *name, Stream *str, Object *params) { - int pred; // parameters - int colors; - int bits; - int early; - int encoding; - GBool endOfLine, byteAlign, endOfBlock, black; - int columns, rows; - 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); - if (obj.isInt()) - pred = obj.getInt(); - obj.free(); - params->dictLookup("Columns", &obj); - if (obj.isInt()) - columns = obj.getInt(); - obj.free(); - params->dictLookup("Colors", &obj); - if (obj.isInt()) - colors = obj.getInt(); - obj.free(); - params->dictLookup("BitsPerComponent", &obj); - if (obj.isInt()) - bits = obj.getInt(); - obj.free(); - params->dictLookup("EarlyChange", &obj); - 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); - if (obj.isInt()) { - encoding = obj.getInt(); - } - obj.free(); - params->dictLookup("EndOfLine", &obj); - if (obj.isBool()) { - endOfLine = obj.getBool(); - } - obj.free(); - params->dictLookup("EncodedByteAlign", &obj); - if (obj.isBool()) { - byteAlign = obj.getBool(); - } - obj.free(); - params->dictLookup("Columns", &obj); - if (obj.isInt()) { - columns = obj.getInt(); - } - obj.free(); - params->dictLookup("Rows", &obj); - if (obj.isInt()) { - rows = obj.getInt(); - } - obj.free(); - params->dictLookup("EndOfBlock", &obj); - if (obj.isBool()) { - endOfBlock = obj.getBool(); - } - obj.free(); - params->dictLookup("BlackIs1", &obj); - 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")) { - str = new DCTStream(str); - } else if (!strcmp(name, "FlateDecode") || !strcmp(name, "Fl")) { - pred = 1; - columns = 1; - colors = 1; - bits = 8; - if (params->isDict()) { - params->dictLookup("Predictor", &obj); - if (obj.isInt()) - pred = obj.getInt(); - obj.free(); - params->dictLookup("Columns", &obj); - if (obj.isInt()) - columns = obj.getInt(); - obj.free(); - params->dictLookup("Colors", &obj); - if (obj.isInt()) - colors = obj.getInt(); - obj.free(); - params->dictLookup("BitsPerComponent", &obj); - 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); - } - str = new JBIG2Stream(str, &globals); - globals.free(); - } else if (!strcmp(name, "JPXDecode")) { - str = new JPXStream(str); - } else { - error(getPos(), "Unknown filter '%s'", name); - str = new EOFStream(str); - } - return str; -} - -//------------------------------------------------------------------------ -// BaseStream -//------------------------------------------------------------------------ - -BaseStream::BaseStream(Object *dictA) { - dict = *dictA; - decrypt = NULL; -} - -BaseStream::~BaseStream() { - dict.free(); - if (decrypt) - delete decrypt; -} - -void BaseStream::doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen) { - decrypt = new Decrypt(fileKey, keyLength, objNum, objGen); -} - -//------------------------------------------------------------------------ -// FilterStream -//------------------------------------------------------------------------ - -FilterStream::FilterStream(Stream *strA) { - str = strA; -} - -FilterStream::~FilterStream() { -} - -void FilterStream::close() { - str->close(); -} - -void FilterStream::setPos(Guint pos, int dir) { - error(-1, "Internal: 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; - if (nBits == 1) { - imgLineSize = (nVals + 7) & ~7; - } else { - imgLineSize = nVals; - } - imgLine = (Guchar *)gmallocn(imgLineSize, sizeof(Guchar)); - imgIdx = nVals; -} - -ImageStream::~ImageStream() { - gfree(imgLine); -} - -void ImageStream::reset() { - str->reset(); -} - -GBool ImageStream::getPixel(Guchar *pix) { - int i; - - if (imgIdx >= nVals) { - getLine(); - 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; - - if (nBits == 1) { - for (i = 0; i < nVals; i += 8) { - c = str->getChar(); - 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) { - for (i = 0; i < nVals; ++i) { - imgLine[i] = str->getChar(); - } - } else { - bitMask = (1 << nBits) - 1; - buf = 0; - bits = 0; - for (i = 0; i < nVals; ++i) { - if (bits < nBits) { - buf = (buf << 8) | (str->getChar() & 0xff); - bits += 8; - } - imgLine[i] = (Guchar)((buf >> (bits - nBits)) & bitMask); - bits -= nBits; - } - } - return imgLine; -} - -void ImageStream::skipLine() { - int n, i; - - n = (nVals * nBits + 7) >> 3; - for (i = 0; i < n; ++i) { - str->getChar(); - } -} - -//------------------------------------------------------------------------ -// StreamPredictor -//------------------------------------------------------------------------ - -StreamPredictor::StreamPredictor(Stream *strA, int predictorA, - int widthA, int nCompsA, int nBitsA) { - int totalBits; - - str = strA; - predictor = predictorA; - width = widthA; - nComps = nCompsA; - nBits = nBitsA; - predLine = NULL; - ok = gFalse; - - nVals = width * nComps; - totalBits = nVals * nBits; - if (totalBits == 0 || - (totalBits / nBits) / nComps != width || - totalBits + 7 < 0) { - return; - } - pixBytes = (nComps * nBits + 7) >> 3; - rowBytes = ((totalBits + 7) >> 3) + pixBytes; - if (rowBytes < 0) { - return; - } - predLine = (Guchar *)gmalloc(rowBytes); - memset(predLine, 0, rowBytes); - predIdx = rowBytes; - - ok = gTrue; -} - -StreamPredictor::~StreamPredictor() { - gfree(predLine); -} - -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++]; -} - -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] = predLine[i - pixBytes] + (Guchar)c; - break; - case 12: // PNG up - predLine[i] = predLine[i] + (Guchar)c; - break; - case 13: // PNG average - predLine[i] = ((predLine[i - pixBytes] + predLine[i]) >> 1) + - (Guchar)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] = left + (Guchar)c; - else if (pb <= pc) - predLine[i] = up + (Guchar)c; - else - predLine[i] = upLeft + (Guchar)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 == 1) { - inBuf = predLine[pixBytes - 1]; - for (i = pixBytes; i < rowBytes; i += 8) { - // 1-bit add is just xor - inBuf = (inBuf << 8) | predLine[i]; - predLine[i] ^= inBuf >> nComps; - } - } else if (nBits == 8) { - for (i = pixBytes; i < rowBytes; ++i) { - predLine[i] += predLine[i - nComps]; - } - } else { - memset(upLeftBuf, 0, nComps + 1); - 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] = (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; -} - -//------------------------------------------------------------------------ -// FileStream -//------------------------------------------------------------------------ - -FileStream::FileStream(FILE *fA, Guint startA, GBool limitedA, - Guint lengthA, Object *dictA): - BaseStream(dictA) { - f = fA; - start = startA; - limited = limitedA; - length = lengthA; - bufPtr = bufEnd = buf; - bufPos = start; - savePos = 0; - saved = gFalse; -} - -FileStream::~FileStream() { - close(); -} - -Stream *FileStream::makeSubStream(Guint startA, GBool limitedA, - Guint lengthA, Object *dictA) { - return new FileStream(f, startA, limitedA, lengthA, dictA); -} - -void FileStream::reset() { -#if HAVE_FSEEKO - savePos = (Guint)ftello(f); - fseeko(f, start, SEEK_SET); -#elif HAVE_FSEEK64 - savePos = (Guint)ftell64(f); - fseek64(f, start, SEEK_SET); -#else - savePos = (Guint)ftell(f); - fseek(f, start, SEEK_SET); -#endif - saved = gTrue; - bufPtr = bufEnd = buf; - bufPos = start; - if (decrypt) - decrypt->reset(); -} - -void FileStream::close() { - if (saved) { -#if HAVE_FSEEKO - fseeko(f, savePos, SEEK_SET); -#elif HAVE_FSEEK64 - fseek64(f, savePos, SEEK_SET); -#else - fseek(f, savePos, SEEK_SET); -#endif - saved = gFalse; - } -} - -GBool FileStream::fillBuf() { - int n; - char *p; - - bufPos += bufEnd - buf; - bufPtr = bufEnd = buf; - if (limited && bufPos >= start + length) { - return gFalse; - } - if (limited && bufPos + fileStreamBufSize > start + length) { - n = start + length - bufPos; - } else { - n = fileStreamBufSize; - } - n = fread(buf, 1, n, f); - bufEnd = buf + n; - if (bufPtr >= bufEnd) { - return gFalse; - } - if (decrypt) { - for (p = buf; p < bufEnd; ++p) { - *p = (char)decrypt->decryptByte((Guchar)*p); - } - } - return gTrue; -} - -void FileStream::setPos(Guint pos, int dir) { - Guint size; - - if (dir >= 0) { -#if HAVE_FSEEKO - fseeko(f, pos, SEEK_SET); -#elif HAVE_FSEEK64 - fseek64(f, pos, SEEK_SET); -#else - fseek(f, pos, SEEK_SET); -#endif - bufPos = pos; - } else { -#if HAVE_FSEEKO - fseeko(f, 0, SEEK_END); - size = (Guint)ftello(f); -#elif HAVE_FSEEK64 - fseek64(f, 0, SEEK_END); - size = (Guint)ftell64(f); -#else - fseek(f, 0, SEEK_END); - size = (Guint)ftell(f); -#endif - if (pos > size) - pos = (Guint)size; -#ifdef __CYGWIN32__ - //~ work around a bug in cygwin's implementation of fseek - rewind(f); -#endif -#if HAVE_FSEEKO - fseeko(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftello(f); -#elif HAVE_FSEEK64 - fseek64(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftell64(f); -#else - fseek(f, -(int)pos, SEEK_END); - bufPos = (Guint)ftell(f); -#endif - } - 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::makeSubStream(Guint startA, GBool limited, - Guint lengthA, Object *dictA) { - MemStream *subStr; - Guint newLength; - - if (!limited || startA + lengthA > start + length) { - newLength = start + length - startA; - } else { - newLength = lengthA; - } - subStr = new MemStream(buf, startA, newLength, dictA); - return subStr; -} - -void MemStream::reset() { - bufPtr = buf + start; - if (decrypt) { - decrypt->reset(); - } -} - -void MemStream::close() { -} - -void MemStream::setPos(Guint pos, int dir) { - Guint i; - - if (dir >= 0) { - i = pos; - } else { - i = 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; -} - -void MemStream::doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen) { - char *newBuf; - char *p, *q; - - this->BaseStream::doDecryption(fileKey, keyLength, objNum, objGen); - if (decrypt) { - newBuf = (char *)gmalloc(length); - for (p = buf + start, q = newBuf; p < bufEnd; ++p, ++q) { - *q = (char)decrypt->decryptByte((Guchar)*p); - } - bufEnd = newBuf + length; - bufPtr = newBuf + (bufPtr - (buf + start)); - start = 0; - buf = newBuf; - needFree = gTrue; - } -} - -//------------------------------------------------------------------------ -// EmbedStream -//------------------------------------------------------------------------ - -EmbedStream::EmbedStream(Stream *strA, Object *dictA, - GBool limitedA, Guint lengthA): - BaseStream(dictA) { - str = strA; - limited = limitedA; - length = lengthA; -} - -EmbedStream::~EmbedStream() { -} - -Stream *EmbedStream::makeSubStream(Guint start, GBool limitedA, - Guint lengthA, Object *dictA) { - error(-1, "Internal: 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(); -} - -void EmbedStream::setPos(Guint pos, int dir) { - error(-1, "Internal: called setPos() on EmbedStream"); -} - -Guint EmbedStream::getStart() { - error(-1, "Internal: called getStart() on EmbedStream"); - return 0; -} - -void EmbedStream::moveStart(int delta) { - error(-1, "Internal: called moveStart() on EmbedStream"); -} - -//------------------------------------------------------------------------ -// ASCIIHexStream -//------------------------------------------------------------------------ - -ASCIIHexStream::ASCIIHexStream(Stream *strA): - FilterStream(strA) { - buf = EOF; - eof = gFalse; -} - -ASCIIHexStream::~ASCIIHexStream() { - delete str; -} - -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(getPos(), "Illegal character <%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(getPos(), "Illegal character <%02x> in ASCIIHex stream", c2); - } - buf = x & 0xff; - return buf; -} - -GString *ASCIIHexStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - 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; -} - -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, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - 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(); -} - -LZWStream::~LZWStream() { - if (pred) { - delete pred; - } - delete str; -} - -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++]; -} - -void LZWStream::reset() { - str->reset(); - eof = gFalse; - inputBits = 0; - clearTable(); -} - -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(getPos(), "Bad LZW stream - expected clear-table code"); - clearTable(); - } - - // process the next code - nextLength = seqLength + 1; - if (code < 256) { - seqBuf[0] = 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] = j; - } else if (code == nextCode) { - seqBuf[seqLength] = newChar; - ++seqLength; - } else { - error(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 = newChar; - ++nextCode; - if (nextCode + early == 512) - nextBits = 10; - else if (nextCode + early == 1024) - nextBits = 11; - else if (nextCode + early == 2048) - nextBits = 12; - } - prevCode = code; - - // 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; - } - code = (inputBuf >> (inputBits - nextBits)) & ((1 << nextBits) - 1); - inputBits -= nextBits; - return code; -} - -GString *LZWStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2 || pred) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - 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; -} - -void RunLengthStream::reset() { - str->reset(); - bufPtr = bufEnd = buf; - eof = gFalse; -} - -GString *RunLengthStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - 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; - } - rows = rowsA; - endOfBlock = endOfBlockA; - black = blackA; - refLine = (short *)gmallocn(columns + 4, sizeof(short)); - codingLine = (short *)gmallocn(columns + 3, sizeof(short)); - - eof = gFalse; - row = 0; - nextLine2D = encoding < 0; - inputBits = 0; - codingLine[0] = 0; - codingLine[1] = refLine[2] = columns; - a0 = 1; - - buf = EOF; -} - -CCITTFaxStream::~CCITTFaxStream() { - delete str; - gfree(refLine); - gfree(codingLine); -} - -void CCITTFaxStream::reset() { - short code1; - - str->reset(); - eof = gFalse; - row = 0; - nextLine2D = encoding < 0; - inputBits = 0; - codingLine[0] = 0; - codingLine[1] = refLine[2] = columns; - a0 = 1; - buf = EOF; - - // 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); - } - if (encoding > 0) { - nextLine2D = !lookBits(1); - eatBits(1); - } -} - -int CCITTFaxStream::lookChar() { - short code1, code2, code3; - int a0New; - GBool err, gotEOL; - int ret; - int bits, i; - - // if at eof just return EOF - if (eof && codingLine[a0] >= columns) { - return EOF; - } - - // read the next row - err = gFalse; - if (codingLine[a0] >= columns) { - - // 2-D encoding - if (nextLine2D) { - for (i = 0; codingLine[i] < columns; ++i) - refLine[i] = codingLine[i]; - refLine[i] = refLine[i + 1] = columns; - b1 = 1; - a0New = codingLine[a0 = 0] = 0; - do { - code1 = getTwoDimCode(); - switch (code1) { - case twoDimPass: - if (refLine[b1] < columns) { - a0New = refLine[b1 + 1]; - b1 += 2; - } - break; - case twoDimHoriz: - if ((a0 & 1) == 0) { - code1 = code2 = 0; - do { - code1 += code3 = getWhiteCode(); - } while (code3 >= 64); - do { - code2 += code3 = getBlackCode(); - } while (code3 >= 64); - } else { - code1 = code2 = 0; - do { - code1 += code3 = getBlackCode(); - } while (code3 >= 64); - do { - code2 += code3 = getWhiteCode(); - } while (code3 >= 64); - } - if (code1 > 0 || code2 > 0) { - codingLine[a0 + 1] = a0New + code1; - ++a0; - a0New = codingLine[a0 + 1] = codingLine[a0] + code2; - ++a0; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVert0: - a0New = codingLine[++a0] = refLine[b1]; - if (refLine[b1] < columns) { - ++b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVertR1: - a0New = codingLine[++a0] = refLine[b1] + 1; - if (refLine[b1] < columns) { - ++b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVertL1: - if (a0 == 0 || refLine[b1] - 1 > a0New) { - a0New = codingLine[++a0] = refLine[b1] - 1; - --b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVertR2: - a0New = codingLine[++a0] = refLine[b1] + 2; - if (refLine[b1] < columns) { - ++b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVertL2: - if (a0 == 0 || refLine[b1] - 2 > a0New) { - a0New = codingLine[++a0] = refLine[b1] - 2; - --b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVertR3: - a0New = codingLine[++a0] = refLine[b1] + 3; - if (refLine[b1] < columns) { - ++b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case twoDimVertL3: - if (a0 == 0 || refLine[b1] - 3 > a0New) { - a0New = codingLine[++a0] = refLine[b1] - 3; - --b1; - while (refLine[b1] <= codingLine[a0] && refLine[b1] < columns) - b1 += 2; - } - break; - case EOF: - eof = gTrue; - codingLine[a0 = 0] = columns; - return EOF; - default: - error(getPos(), "Bad 2D code %04x in CCITTFax stream", code1); - err = gTrue; - break; - } - } while (codingLine[a0] < columns); - - // 1-D encoding - } else { - codingLine[a0 = 0] = 0; - while (1) { - code1 = 0; - do { - code1 += code3 = getWhiteCode(); - } while (code3 >= 64); - codingLine[a0+1] = codingLine[a0] + code1; - ++a0; - if (codingLine[a0] >= columns) - break; - code2 = 0; - do { - code2 += code3 = getBlackCode(); - } while (code3 >= 64); - codingLine[a0+1] = codingLine[a0] + code2; - ++a0; - if (codingLine[a0] >= columns) - break; - } - } - - if (codingLine[a0] != columns) { - error(getPos(), "CCITTFax row is wrong length (%d)", codingLine[a0]); - // force the row to be the correct length - while (codingLine[a0] > columns) { - --a0; - } - codingLine[++a0] = columns; - err = gTrue; - } - - // byte-align the row - if (byteAlign) { - inputBits &= ~7; - } - - // check for end-of-line marker, skipping over any extra zero bits - gotEOL = gFalse; - if (!endOfBlock && row == rows - 1) { - eof = gTrue; - } else { - code1 = lookBits(12); - while (code1 == 0) { - eatBits(1); - code1 = lookBits(12); - } - if (code1 == 0x001) { - eatBits(12); - gotEOL = gTrue; - } else if (code1 == EOF) { - eof = gTrue; - } - } - - // get 2D encoding tag - if (!eof && encoding > 0) { - nextLine2D = !lookBits(1); - eatBits(1); - } - - // check for end-of-block marker - 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(getPos(), "Bad RTC code in CCITTFax stream"); - } - 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) { - do { - if (code1 == EOF) { - eof = gTrue; - return EOF; - } - eatBits(1); - code1 = lookBits(13); - } while ((code1 >> 1) != 0x001); - eatBits(12); - if (encoding > 0) { - eatBits(1); - nextLine2D = !(code1 & 1); - } - } - - a0 = 0; - outputBits = codingLine[1] - codingLine[0]; - if (outputBits == 0) { - a0 = 1; - outputBits = codingLine[2] - codingLine[1]; - } - - ++row; - } - - // get a byte - if (outputBits >= 8) { - ret = ((a0 & 1) == 0) ? 0xff : 0x00; - if ((outputBits -= 8) == 0) { - ++a0; - if (codingLine[a0] < columns) { - outputBits = codingLine[a0 + 1] - codingLine[a0]; - } - } - } else { - bits = 8; - ret = 0; - do { - if (outputBits > bits) { - i = bits; - bits = 0; - if ((a0 & 1) == 0) { - ret |= 0xff >> (8 - i); - } - outputBits -= i; - } else { - i = outputBits; - bits -= outputBits; - if ((a0 & 1) == 0) { - ret |= (0xff >> (8 - i)) << bits; - } - outputBits = 0; - ++a0; - if (codingLine[a0] < columns) { - outputBits = codingLine[a0 + 1] - codingLine[a0]; - } - } - } while (bits > 0 && codingLine[a0] < columns); - } - buf = black ? (ret ^ 0xff) : ret; - return buf; -} - -short CCITTFaxStream::getTwoDimCode() { - short code; - CCITTCode *p; - int n; - - code = 0; // make gcc happy - if (endOfBlock) { - code = lookBits(7); - p = &twoDimTab1[code]; - if (p->bits > 0) { - eatBits(p->bits); - return p->n; - } - } else { - for (n = 1; n <= 7; ++n) { - code = lookBits(n); - if (n < 7) { - code <<= 7 - n; - } - p = &twoDimTab1[code]; - if (p->bits == n) { - eatBits(n); - return p->n; - } - } - } - error(getPos(), "Bad two dim code (%04x) in CCITTFax stream", code); - return EOF; -} - -short CCITTFaxStream::getWhiteCode() { - short code; - CCITTCode *p; - int n; - - code = 0; // make gcc happy - if (endOfBlock) { - code = lookBits(12); - 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 (n < 9) { - 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 (n < 12) { - code <<= 12 - n; - } - p = &whiteTab1[code]; - if (p->bits == n) { - eatBits(n); - return p->n; - } - } - } - error(getPos(), "Bad white code (%04x) in CCITTFax stream", code); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - eatBits(1); - return 1; -} - -short CCITTFaxStream::getBlackCode() { - short code; - CCITTCode *p; - int n; - - code = 0; // make gcc happy - if (endOfBlock) { - code = lookBits(13); - if ((code >> 7) == 0) { - p = &blackTab1[code]; - } else if ((code >> 9) == 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 (n < 6) { - 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 (n < 12) { - 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 (n < 13) { - code <<= 13 - n; - } - p = &blackTab1[code]; - if (p->bits == n) { - eatBits(n); - return p->n; - } - } - } - error(getPos(), "Bad black code (%04x) in CCITTFax stream", code); - // eat a bit and return a positive number so that the caller doesn't - // go into an infinite loop - eatBits(1); - 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 (inputBuf << (n - inputBits)) & (0xffff >> (16 - n)); - } - inputBuf = (inputBuf << 8) + c; - inputBits += 8; - } - return (inputBuf >> (inputBits - n)) & (0xffff >> (16 - n)); -} - -GString *CCITTFaxStream::getPSFilter(int psLevel, char *indent) { - GString *s; - char s1[50]; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - return NULL; - } - s->append(indent)->append("<< "); - if (encoding != 0) { - sprintf(s1, "/K %d ", encoding); - s->append(s1); - } - if (endOfLine) { - s->append("/EndOfLine true "); - } - if (byteAlign) { - s->append("/EncodedByteAlign true "); - } - sprintf(s1, "/Columns %d ", columns); - s->append(s1); - if (rows != 0) { - sprintf(s1, "/Rows %d ", rows); - s->append(s1); - } - 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 -//------------------------------------------------------------------------ - -// IDCT constants (20.12 fixed point format) -#define dctCos1 4017 // cos(pi/16) -#define dctSin1 799 // sin(pi/16) -#define dctCos3 3406 // cos(3*pi/16) -#define dctSin3 2276 // sin(3*pi/16) -#define dctCos6 1567 // cos(6*pi/16) -#define dctSin6 3784 // sin(6*pi/16) -#define dctSqrt2 5793 // sqrt(2) -#define dctSqrt1d2 2896 // sqrt(2) / 2 - -// 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 - -// clip [-256,511] --> [0,255] -#define dctClipOffset 256 -static Guchar dctClip[768]; -static int dctClipInit = 0; - -// 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): - FilterStream(strA) { - int i, j; - - progressive = interleaved = gFalse; - width = height = 0; - mcuWidth = mcuHeight = 0; - numComps = 0; - comp = 0; - x = y = dy = 0; - for (i = 0; i < 4; ++i) { - for (j = 0; j < 32; ++j) { - rowBuf[i][j] = NULL; - } - frameBuf[i] = NULL; - } - - if (!dctClipInit) { - for (i = -256; i < 0; ++i) - dctClip[dctClipOffset + i] = 0; - for (i = 0; i < 256; ++i) - dctClip[dctClipOffset + i] = i; - for (i = 256; i < 512; ++i) - dctClip[dctClipOffset + i] = 255; - dctClipInit = 1; - } -} - -DCTStream::~DCTStream() { - int i, j; - - delete str; - if (progressive || !interleaved) { - for (i = 0; i < numComps; ++i) { - gfree(frameBuf[i]); - } - } else { - for (i = 0; i < numComps; ++i) { - for (j = 0; j < mcuHeight; ++j) { - gfree(rowBuf[i][j]); - } - } - } -} - -void DCTStream::reset() { - int i, j; - - str->reset(); - - progressive = interleaved = gFalse; - width = height = 0; - numComps = 0; - numQuantTables = 0; - numDCHuffTables = 0; - numACHuffTables = 0; - colorXform = 0; - gotJFIFMarker = gFalse; - gotAdobeMarker = gFalse; - restartInterval = 0; - - if (!readHeader()) { - y = height; - 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 (!gotAdobeMarker && numComps == 3) { - if (gotJFIFMarker) { - colorXform = 1; - } else if (compInfo[0].id == 82 && compInfo[1].id == 71 && - compInfo[2].id == 66) { // ASCII "RGB" - colorXform = 0; - } else { - colorXform = 1; - } - } - - if (progressive || !interleaved) { - - // allocate a buffer for the whole image - bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - bufHeight = ((height + mcuHeight - 1) / mcuHeight) * mcuHeight; - for (i = 0; i < numComps; ++i) { - frameBuf[i] = (int *)gmallocn(bufWidth * bufHeight, sizeof(int)); - memset(frameBuf[i], 0, bufWidth * bufHeight * sizeof(int)); - } - - // read the image data - do { - restartMarker = 0xd0; - restart(); - readScan(); - } while (readHeader()); - - // decode - decodeImage(); - - // initialize counters - comp = 0; - x = 0; - y = 0; - - } else { - - // allocate a buffer for one row of MCUs - bufWidth = ((width + mcuWidth - 1) / mcuWidth) * mcuWidth; - for (i = 0; i < numComps; ++i) { - for (j = 0; j < mcuHeight; ++j) { - rowBuf[i][j] = (Guchar *)gmallocn(bufWidth, sizeof(Guchar)); - } - } - - // initialize counters - comp = 0; - x = 0; - y = 0; - dy = mcuHeight; - - restartMarker = 0xd0; - restart(); - } -} - -int DCTStream::getChar() { - int c; - - if (y >= height) { - return EOF; - } - if (progressive || !interleaved) { - c = frameBuf[comp][y * bufWidth + x]; - if (++comp == numComps) { - comp = 0; - if (++x == width) { - x = 0; - ++y; - } - } - } else { - if (dy >= mcuHeight) { - if (!readMCURow()) { - y = height; - return EOF; - } - comp = 0; - x = 0; - dy = 0; - } - c = rowBuf[comp][dy][x]; - if (++comp == numComps) { - comp = 0; - if (++x == width) { - x = 0; - ++y; - ++dy; - if (y == height) { - readTrailer(); - } - } - } - } - return c; -} - -int DCTStream::lookChar() { - if (y >= height) { - return EOF; - } - if (progressive || !interleaved) { - return frameBuf[comp][y * bufWidth + x]; - } else { - if (dy >= mcuHeight) { - if (!readMCURow()) { - y = height; - return EOF; - } - comp = 0; - x = 0; - dy = 0; - } - return rowBuf[comp][dy][x]; - } -} - -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 (x1 = 0; x1 < width; x1 += mcuWidth) { - - // deal with restart marker - if (restartInterval > 0 && restartCtr == 0) { - c = readMarker(); - if (c != restartMarker) { - error(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) { - for (y3 = 0, i = 0; y3 < 8; ++y3, i += 8) { - p1 = &rowBuf[cc][y2+y3][x1+x2]; - p1[0] = data2[i]; - p1[1] = data2[i+1]; - p1[2] = data2[i+2]; - p1[3] = data2[i+3]; - p1[4] = data2[i+4]; - p1[5] = data2[i+5]; - p1[6] = data2[i+6]; - p1[7] = data2[i+7]; - } - } else if (hSub == 2 && vSub == 2) { - for (y3 = 0, i = 0; y3 < 16; y3 += 2, i += 8) { - p1 = &rowBuf[cc][y2+y3][x1+x2]; - p2 = &rowBuf[cc][y2+y3+1][x1+x2]; - p1[0] = p1[1] = p2[0] = p2[1] = data2[i]; - p1[2] = p1[3] = p2[2] = p2[3] = data2[i+1]; - p1[4] = p1[5] = p2[4] = p2[5] = data2[i+2]; - p1[6] = p1[7] = p2[6] = p2[7] = data2[i+3]; - p1[8] = p1[9] = p2[8] = p2[9] = data2[i+4]; - p1[10] = p1[11] = p2[10] = p2[11] = data2[i+5]; - p1[12] = p1[13] = p2[12] = p2[13] = data2[i+6]; - p1[14] = p1[15] = p2[14] = p2[15] = data2[i+7]; - } - } else { - i = 0; - for (y3 = 0, y4 = 0; y3 < 8; ++y3, y4 += vSub) { - for (x3 = 0, x4 = 0; x3 < 8; ++x3, x4 += hSub) { - for (y5 = 0; y5 < vSub; ++y5) - for (x5 = 0; x5 < hSub; ++x5) - rowBuf[cc][y2+y4+y5][x1+x2+x4+x5] = data2[i]; - ++i; - } - } - } - } - } - } - --restartCtr; - - // color space conversion - if (colorXform) { - // convert YCbCr to RGB - if (numComps == 3) { - for (y2 = 0; y2 < mcuHeight; ++y2) { - for (x2 = 0; x2 < mcuWidth; ++x2) { - pY = rowBuf[0][y2][x1+x2]; - pCb = rowBuf[1][y2][x1+x2] - 128; - pCr = rowBuf[2][y2][x1+x2] - 128; - pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - rowBuf[0][y2][x1+x2] = dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; - rowBuf[1][y2][x1+x2] = dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - rowBuf[2][y2][x1+x2] = dctClip[dctClipOffset + pB]; - } - } - // convert YCbCrK to CMYK (K is passed through unchanged) - } else if (numComps == 4) { - for (y2 = 0; y2 < mcuHeight; ++y2) { - for (x2 = 0; x2 < mcuWidth; ++x2) { - pY = rowBuf[0][y2][x1+x2]; - pCb = rowBuf[1][y2][x1+x2] - 128; - pCr = rowBuf[2][y2][x1+x2] - 128; - pR = ((pY << 16) + dctCrToR * pCr + 32768) >> 16; - rowBuf[0][y2][x1+x2] = 255 - dctClip[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + 32768) >> 16; - rowBuf[1][y2][x1+x2] = 255 - dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - rowBuf[2][y2][x1+x2] = 255 - dctClip[dctClipOffset + pB]; - } - } - } - } - } - 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; - - 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(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 sequential 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; - } - data[0] += bit << 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) { - 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) { - j = dctZigZag[i++]; - if (data[j] == 0) { - ++k; - } else { - if ((bit = readBit()) == EOF) { - return gFalse; - } - if (bit) { - 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) { - 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; - } - k = 0; - do { - j = dctZigZag[i++]; - while (data[j] != 0) { - if ((bit = readBit()) == EOF) { - return gFalse; - } - if (bit) { - data[j] += 1 << scanInfo.al; - } - j = dctZigZag[i++]; - } - ++k; - } while (k <= run); - 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[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + - 32768) >> 16; - *p1++ = dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - *p2++ = dctClip[dctClipOffset + 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[dctClipOffset + pR]; - pG = ((pY << 16) + dctCbToG * pCb + dctCrToG * pCr + - 32768) >> 16; - *p1++ = 255 - dctClip[dctClipOffset + pG]; - pB = ((pY << 16) + dctCbToB * pCb + 32768) >> 16; - *p2++ = 255 - dctClip[dctClipOffset + pB]; - } - } - } - } - } - } -} - -// Transform one data unit -- this performs the dequantization and -// IDCT steps. This IDCT algorithm is taken from: -// 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 this -// paper. -void DCTStream::transformDataUnit(Gushort *quantTable, - int dataIn[64], Guchar dataOut[64]) { - int v0, v1, v2, v3, v4, v5, v6, v7, t; - int *p; - int i; - - // dequant - for (i = 0; i < 64; ++i) { - dataIn[i] *= quantTable[i]; - } - - // inverse DCT on rows - for (i = 0; i < 64; i += 8) { - p = dataIn + i; - - // check for all-zero AC coefficients - if (p[1] == 0 && p[2] == 0 && p[3] == 0 && - p[4] == 0 && p[5] == 0 && p[6] == 0 && p[7] == 0) { - t = (dctSqrt2 * p[0] + 512) >> 10; - p[0] = t; - p[1] = t; - p[2] = t; - p[3] = t; - p[4] = t; - p[5] = t; - p[6] = t; - p[7] = t; - continue; - } - - // stage 4 - v0 = (dctSqrt2 * p[0] + 128) >> 8; - v1 = (dctSqrt2 * p[4] + 128) >> 8; - v2 = p[2]; - v3 = p[6]; - v4 = (dctSqrt1d2 * (p[1] - p[7]) + 128) >> 8; - v7 = (dctSqrt1d2 * (p[1] + p[7]) + 128) >> 8; - v5 = p[3] << 4; - v6 = p[5] << 4; - - // stage 3 - t = (v0 - v1+ 1) >> 1; - v0 = (v0 + v1 + 1) >> 1; - v1 = t; - t = (v2 * dctSin6 + v3 * dctCos6 + 128) >> 8; - v2 = (v2 * dctCos6 - v3 * dctSin6 + 128) >> 8; - v3 = t; - t = (v4 - v6 + 1) >> 1; - v4 = (v4 + v6 + 1) >> 1; - v6 = t; - t = (v7 + v5 + 1) >> 1; - v5 = (v7 - v5 + 1) >> 1; - v7 = t; - - // stage 2 - t = (v0 - v3 + 1) >> 1; - v0 = (v0 + v3 + 1) >> 1; - v3 = t; - t = (v1 - v2 + 1) >> 1; - v1 = (v1 + v2 + 1) >> 1; - v2 = t; - t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; - v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; - v7 = t; - t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; - v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; - v6 = t; - - // 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) { - t = (dctSqrt2 * dataIn[i+0] + 8192) >> 14; - p[0*8] = t; - p[1*8] = t; - p[2*8] = t; - p[3*8] = t; - p[4*8] = t; - p[5*8] = t; - p[6*8] = t; - p[7*8] = t; - continue; - } - - // stage 4 - v0 = (dctSqrt2 * p[0*8] + 2048) >> 12; - v1 = (dctSqrt2 * p[4*8] + 2048) >> 12; - v2 = p[2*8]; - v3 = p[6*8]; - v4 = (dctSqrt1d2 * (p[1*8] - p[7*8]) + 2048) >> 12; - v7 = (dctSqrt1d2 * (p[1*8] + p[7*8]) + 2048) >> 12; - v5 = p[3*8]; - v6 = p[5*8]; - - // stage 3 - t = (v0 - v1 + 1) >> 1; - v0 = (v0 + v1 + 1) >> 1; - v1 = t; - t = (v2 * dctSin6 + v3 * dctCos6 + 2048) >> 12; - v2 = (v2 * dctCos6 - v3 * dctSin6 + 2048) >> 12; - v3 = t; - t = (v4 - v6 + 1) >> 1; - v4 = (v4 + v6 + 1) >> 1; - v6 = t; - t = (v7 + v5 + 1) >> 1; - v5 = (v7 - v5 + 1) >> 1; - v7 = t; - - // stage 2 - t = (v0 - v3 + 1) >> 1; - v0 = (v0 + v3 + 1) >> 1; - v3 = t; - t = (v1 - v2 + 1) >> 1; - v1 = (v1 + v2 + 1) >> 1; - v2 = t; - t = (v4 * dctSin3 + v7 * dctCos3 + 2048) >> 12; - v4 = (v4 * dctCos3 - v7 * dctSin3 + 2048) >> 12; - v7 = t; - t = (v5 * dctSin1 + v6 * dctCos1 + 2048) >> 12; - v5 = (v5 * dctCos1 - v6 * dctSin1 + 2048) >> 12; - v6 = t; - - // 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[dctClipOffset + 128 + ((dataIn[i] + 8) >> 4)]; - } -} - -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 = (code << 1) + bit; - ++codeBits; - - // look up code - if (code - table->firstCode[codeBits] < table->numCodes[codeBits]) { - code -= table->firstCode[codeBits]; - return table->sym[table->firstSym[codeBits] + code]; - } - } while (codeBits < 16); - - error(getPos(), "Bad Huffman code in DCT stream"); - 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(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 doScan; - int n; - int c = 0; - int i; - - // read headers - doScan = gFalse; - while (!doScan) { - c = readMarker(); - switch (c) { - case 0xc0: // SOF0 (sequential) - case 0xc1: // SOF1 (extended sequential) - if (!readBaselineSOF()) { - return gFalse; - } - break; - case 0xc2: // SOF2 (progressive) - if (!readProgressiveSOF()) { - return gFalse; - } - break; - case 0xc4: // DHT - if (!readHuffmanTables()) { - return gFalse; - } - break; - case 0xd8: // SOI - break; - case 0xd9: // EOI - return gFalse; - case 0xda: // SOS - if (!readScanInfo()) { - return gFalse; - } - doScan = gTrue; - break; - case 0xdb: // DQT - if (!readQuantTables()) { - return gFalse; - } - break; - case 0xdd: // DRI - if (!readRestartInterval()) { - return gFalse; - } - break; - case 0xe0: // APP0 - if (!readJFIFMarker()) { - return gFalse; - } - break; - case 0xee: // APP14 - if (!readAdobeMarker()) { - return gFalse; - } - break; - case EOF: - error(getPos(), "Bad DCT header"); - return gFalse; - default: - // skip APPn / COM / etc. - if (c >= 0xe0) { - n = read16() - 2; - for (i = 0; i < n; ++i) { - str->getChar(); - } - } else { - error(getPos(), "Unknown DCT marker <%02x>", c); - return gFalse; - } - break; - } - } - - return gTrue; -} - -GBool DCTStream::readBaselineSOF() { - int length; - int prec; - int i; - int c; - - length = read16(); - prec = str->getChar(); - height = read16(); - width = read16(); - numComps = str->getChar(); - if (numComps <= 0 || numComps > 4) { - error(getPos(), "Bad number of components in DCT stream", prec); - return gFalse; - } - if (numComps <= 0 || numComps > 4) { - error(getPos(), "Bad number of components in DCT stream", prec); - return gFalse; - } - if (prec != 8) { - error(getPos(), "Bad DCT precision %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(); - } - progressive = gFalse; - return gTrue; -} - -GBool DCTStream::readProgressiveSOF() { - int length; - int prec; - int i; - int c; - - length = read16(); - prec = str->getChar(); - height = read16(); - width = read16(); - numComps = str->getChar(); - if (prec != 8) { - error(getPos(), "Bad DCT precision %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(); - } - progressive = gTrue; - return gTrue; -} - -GBool DCTStream::readScanInfo() { - int length; - int id, c; - int i, j; - - length = read16() - 2; - scanInfo.numComps = str->getChar(); - --length; - if (length != 2 * scanInfo.numComps + 3) { - error(getPos(), "Bad DCT scan info block"); - return gFalse; - } - interleaved = scanInfo.numComps == numComps; - 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(getPos(), "Bad 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(); - 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(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]] = read16(); - } else { - quantTables[index][dctZigZag[i]] = 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(getPos(), "Bad DCT Huffman table"); - return gFalse; - } - if (index & 0x10) { - index &= 0x0f; - if (index >= numACHuffTables) - numACHuffTables = index+1; - tbl = &acHuffTables[index]; - } else { - 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] = c; - sym += c; - code = (code + c) << 1; - } - length -= 16; - for (i = 0; i < sym; ++i) - tbl->sym[i] = str->getChar(); - length -= sym; - } - return gTrue; -} - -GBool DCTStream::readRestartInterval() { - int length; - - length = read16(); - if (length != 4) { - error(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(getPos(), "Bad DCT APP0 marker"); - return gFalse; - } - buf[i] = c; - } - length -= 5; - if (!memcmp(buf, "JFIF\0", 5)) { - gotJFIFMarker = gTrue; - } - } - while (length > 0) { - if (str->getChar() == EOF) { - error(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] = c; - } - if (strncmp(buf, "Adobe", 5)) { - goto err; - } - colorXform = buf[11]; - gotAdobeMarker = gTrue; - for (i = 14; i < length; ++i) { - if (str->getChar() == EOF) { - goto err; - } - } - return gTrue; - - err: - error(getPos(), "Bad DCT Adobe APP14 marker"); - return gFalse; -} - -GBool DCTStream::readTrailer() { - int c; - - c = readMarker(); - if (c != 0xd9) { // EOI - error(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; -} - -GString *DCTStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 2) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - 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; -} - -FlateStream::~FlateStream() { - if (litCodeTab.codes != fixedLitCodeTab.codes) { - gfree(litCodeTab.codes); - } - if (distCodeTab.codes != fixedDistCodeTab.codes) { - gfree(distCodeTab.codes); - } - if (pred) { - delete pred; - } - delete str; -} - -void FlateStream::reset() { - int cmf, flg; - - index = 0; - remain = 0; - codeBuf = 0; - codeSize = 0; - compressedBlock = gFalse; - endOfBlock = gTrue; - eof = gTrue; - - str->reset(); - - // read header - //~ need to look at window size? - endOfBlock = eof = gTrue; - cmf = str->getChar(); - flg = str->getChar(); - if (cmf == EOF || flg == EOF) - return; - if ((cmf & 0x0f) != 0x08) { - error(getPos(), "Unknown compression method in flate stream"); - return; - } - if ((((cmf << 8) + flg) % 31) != 0) { - error(getPos(), "Bad FCHECK in flate stream"); - return; - } - if (flg & 0x20) { - error(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; -} - -GString *FlateStream::getPSFilter(int psLevel, char *indent) { - GString *s; - - if (psLevel < 3 || pred) { - return NULL; - } - if (!(s = str->getPSFilter(psLevel, indent))) { - 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 i, j, k; - int c; - - if (endOfBlock) { - if (!startBlock()) - return; - } - - if (compressedBlock) { - if ((code1 = getHuffmanCodeWord(&litCodeTab)) == EOF) - goto err; - if (code1 < 256) { - buf[index] = 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; - i = index; - j = (index - dist) & flateMask; - for (k = 0; k < len; ++k) { - buf[i] = buf[j]; - i = (i + 1) & flateMask; - j = (j + 1) & flateMask; - } - 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] = c & 0xff; - } - remain = i; - blockLen -= len; - if (blockLen == 0) - endOfBlock = gTrue; - } - - return; - -err: - error(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)) - error(getPos(), "Bad uncompressed block length in flate stream"); - codeBuf = 0; - codeSize = 0; - - // 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(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(getPos(), "Bad dynamic code table in flate stream"); - gfree(codeLenCodeTab.codes); - return gFalse; -} - -// Convert an array of lengths, in value order, into a -// Huffman code lookup table. -void FlateStream::compHuffmanCodes(int *lengths, int n, FlateHuffmanTab *tab) { - int tabSize, len, code, code2, skip, val, i, t; - - // find max code length - tab->maxLen = 0; - for (val = 0; val < n; ++val) { - if (lengths[val] > tab->maxLen) { - tab->maxLen = lengths[val]; - } - } - - // allocate the table - tabSize = 1 << tab->maxLen; - tab->codes = (FlateCode *)gmallocn(tabSize, sizeof(FlateCode)); - - // clear the table - for (i = 0; i < tabSize; ++i) { - tab->codes[i].len = 0; - tab->codes[i].val = 0; - } - - // build the table - for (len = 1, code = 0, skip = 2; - len <= tab->maxLen; - ++len, code <<= 1, skip <<= 1) { - for (val = 0; val < n; ++val) { - if (lengths[val] == len) { - - // bit-reverse the code - code2 = 0; - t = code; - for (i = 0; i < len; ++i) { - code2 = (code2 << 1) | (t & 1); - t >>= 1; - } - - // fill in the table entries - for (i = code2; i < tabSize; i += skip) { - tab->codes[i].len = (Gushort)len; - tab->codes[i].val = (Gushort)val; - } - - ++code; - } - } - } -} - -int FlateStream::getHuffmanCodeWord(FlateHuffmanTab *tab) { - FlateCode *code; - int c; - - while (codeSize < tab->maxLen) { - if ((c = str->getChar()) == EOF) { - break; - } - codeBuf |= (c & 0xff) << codeSize; - codeSize += 8; - } - 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; - } - c = codeBuf & ((1 << bits) - 1); - codeBuf >>= bits; - codeSize -= bits; - return c; -} - -//------------------------------------------------------------------------ -// EOFStream -//------------------------------------------------------------------------ - -EOFStream::EOFStream(Stream *strA): - FilterStream(strA) { -} - -EOFStream::~EOFStream() { - delete str; -} - -//------------------------------------------------------------------------ -// FixedLengthEncoder -//------------------------------------------------------------------------ - -FixedLengthEncoder::FixedLengthEncoder(Stream *strA, int lengthA): - FilterStream(strA) { - length = lengthA; - count = 0; -} - -FixedLengthEncoder::~FixedLengthEncoder() { - if (str->isEncoder()) - delete str; -} - -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; - } -} - -void ASCIIHexEncoder::reset() { - str->reset(); - bufPtr = bufEnd = buf; - lineLen = 0; - eof = gFalse; -} - -GBool ASCIIHexEncoder::fillBuf() { - static 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; -} - -void ASCII85Encoder::reset() { - str->reset(); - bufPtr = bufEnd = buf; - lineLen = 0; - eof = gFalse; -} - -GBool ASCII85Encoder::fillBuf() { - Gulong t; - char buf1[5]; - int c; - int n, i; - - if (eof) - return gFalse; - t = 0; - for (n = 0; n < 4; ++n) { - if ((c = str->getChar()) == EOF) - break; - t = (t << 8) + c; - } - bufPtr = bufEnd = buf; - if (n > 0) { - if (n == 4 && t == 0) { - *bufEnd++ = 'z'; - if (++lineLen == 65) { - *bufEnd++ = '\n'; - lineLen = 0; - } - } else { - if (n < 4) - t <<= 8 * (4 - n); - for (i = 4; i >= 0; --i) { - buf1[i] = (char)(t % 85 + 0x21); - t /= 85; - } - for (i = 0; i <= n; ++i) { - *bufEnd++ = buf1[i]; - if (++lineLen == 65) { - *bufEnd++ = '\n'; - lineLen = 0; - } - } - } - } - if (n < 4) { - *bufEnd++ = '~'; - *bufEnd++ = '>'; - eof = gTrue; - } - return bufPtr < bufEnd; -} - -//------------------------------------------------------------------------ -// RunLengthEncoder -//------------------------------------------------------------------------ - -RunLengthEncoder::RunLengthEncoder(Stream *strA): - FilterStream(strA) { - bufPtr = bufEnd = nextEnd = buf; - eof = gFalse; -} - -RunLengthEncoder::~RunLengthEncoder() { - if (str->isEncoder()) - delete str; -} - -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] = 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] = c1; - bufEnd = &buf[2]; - if (c == EOF) { - eof = gTrue; - } else if (n < 128) { - buf[2] = c; - nextEnd = &buf[3]; - } else { - nextEnd = bufEnd; - } - - // get up to 128 chars - } else { - buf[1] = c1; - buf[2] = c2; - n = 2; - while (n < 128) { - if ((c = str->getChar()) == EOF) { - eof = gTrue; - break; - } - ++n; - buf[n] = 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; -} diff --git a/pdf2swf/xpdf/Stream.h b/pdf2swf/xpdf/Stream.h deleted file mode 100644 index e1e7bae..0000000 --- a/pdf2swf/xpdf/Stream.h +++ /dev/null @@ -1,846 +0,0 @@ -//======================================================================== -// -// Stream.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef STREAM_H -#define STREAM_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include -#include "gtypes.h" -#include "Object.h" - -class Decrypt; -class BaseStream; - -//------------------------------------------------------------------------ - -enum StreamKind { - strFile, - strASCIIHex, - strASCII85, - strLZW, - strRunLength, - strCCITTFax, - strDCT, - strFlate, - strJBIG2, - strJPX, - strWeird // internal-use stream types -}; - -enum StreamColorSpaceMode { - streamCSNone, - streamCSDeviceGray, - streamCSDeviceRGB, - streamCSDeviceCMYK -}; - -//------------------------------------------------------------------------ -// Stream (base class) -//------------------------------------------------------------------------ - -class Stream { -public: - - // Constructor. - Stream(); - - // Destructor. - virtual ~Stream(); - - // Reference counting. - int incRef() { return ++ref; } - int decRef() { return --ref; } - - // Get kind of stream. - virtual StreamKind getKind() = 0; - - // 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 next line from stream. - virtual char *getLine(char *buf, int size); - - // Get current position in file. - virtual int getPos() = 0; - - // Go to a position in the stream. If is negative, the - // position is from the end of the file; otherwise the position is - // from the start of the file. - virtual void setPos(Guint pos, int dir = 0) = 0; - - // Get PostScript command for the filter(s). - virtual GString *getPSFilter(int psLevel, char *indent); - - // 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 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) {} - - // Add filters to this stream according to the parameters in . - // Returns the new stream. - Stream *addFilters(Object *dict); - -private: - - Stream *makeFilter(char *name, Stream *str, Object *params); - - int ref; // reference count -}; - -//------------------------------------------------------------------------ -// 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(Guint start, GBool limited, - Guint length, Object *dict) = 0; - virtual void setPos(Guint pos, int dir = 0) = 0; - virtual GBool isBinary(GBool last = gTrue) { return last; } - virtual BaseStream *getBaseStream() { return this; } - virtual Dict *getDict() { return dict.getDict(); } - - // Get/set position of first byte of stream within the file. - virtual Guint getStart() = 0; - virtual void moveStart(int delta) = 0; - - // Set decryption for this stream. - virtual void doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen); - -protected: - - Decrypt *decrypt; - -private: - - Object dict; -}; - -//------------------------------------------------------------------------ -// 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 close(); - virtual int getPos() { return str->getPos(); } - virtual void setPos(Guint pos, int dir = 0); - virtual BaseStream *getBaseStream() { return str->getBaseStream(); } - virtual Dict *getDict() { return str->getDict(); } - -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(); - - // Gets the next pixel from the stream. should be able to hold - // at least nComps elements. Returns false at end of file. - GBool getPixel(Guchar *pix); - - // Returns a pointer to the next line of pixels. Returns NULL at - // end of file. - Guchar *getLine(); - - // Skip an entire line from the image. - void skipLine(); - -private: - - Stream *str; // base stream - int width; // pixels per line - int nComps; // components per pixel - int nBits; // bits per component - int nVals; // components per line - 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; } - - int lookChar(); - int getChar(); - -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, Guint startA, GBool limitedA, - Guint lengthA, Object *dictA); - virtual ~FileStream(); - virtual Stream *makeSubStream(Guint startA, GBool limitedA, - Guint lengthA, Object *dictA); - virtual StreamKind getKind() { return strFile; } - virtual void reset(); - virtual void close(); - virtual int getChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr++ & 0xff); } - virtual int lookChar() - { return (bufPtr >= bufEnd && !fillBuf()) ? EOF : (*bufPtr & 0xff); } - virtual int getPos() { return bufPos + (bufPtr - buf); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart() { return start; } - virtual void moveStart(int delta); - -private: - - GBool fillBuf(); - - FILE *f; - Guint start; - GBool limited; - Guint length; - char buf[fileStreamBufSize]; - char *bufPtr; - char *bufEnd; - Guint bufPos; - int savePos; - GBool saved; -}; - -//------------------------------------------------------------------------ -// MemStream -//------------------------------------------------------------------------ - -class MemStream: public BaseStream { -public: - - MemStream(char *bufA, Guint startA, Guint lengthA, Object *dictA); - virtual ~MemStream(); - virtual Stream *makeSubStream(Guint start, GBool limited, - Guint 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 getPos() { return (int)(bufPtr - buf); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart() { return start; } - virtual void moveStart(int delta); - virtual void doDecryption(Guchar *fileKey, int keyLength, - int objNum, int objGen); - -private: - - 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, Guint lengthA); - virtual ~EmbedStream(); - virtual Stream *makeSubStream(Guint start, GBool limitedA, - Guint lengthA, Object *dictA); - virtual StreamKind getKind() { return str->getKind(); } - virtual void reset() {} - virtual int getChar(); - virtual int lookChar(); - virtual int getPos() { return str->getPos(); } - virtual void setPos(Guint pos, int dir = 0); - virtual Guint getStart(); - virtual void moveStart(int delta); - -private: - - Stream *str; - GBool limited; - Guint length; -}; - -//------------------------------------------------------------------------ -// ASCIIHexStream -//------------------------------------------------------------------------ - -class ASCIIHexStream: public FilterStream { -public: - - ASCIIHexStream(Stream *strA); - virtual ~ASCIIHexStream(); - 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, char *indent); - virtual GBool isBinary(GBool last = gTrue); - -private: - - int buf; - GBool eof; -}; - -//------------------------------------------------------------------------ -// ASCII85Stream -//------------------------------------------------------------------------ - -class ASCII85Stream: public FilterStream { -public: - - ASCII85Stream(Stream *strA); - virtual ~ASCII85Stream(); - 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, char *indent); - 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 StreamKind getKind() { return strLZW; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - 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 processNextCode(); - void clearTable(); - int getCode(); -}; - -//------------------------------------------------------------------------ -// RunLengthStream -//------------------------------------------------------------------------ - -class RunLengthStream: public FilterStream { -public: - - RunLengthStream(Stream *strA); - virtual ~RunLengthStream(); - 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 GString *getPSFilter(int psLevel, char *indent); - 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 StreamKind getKind() { return strCCITTFax; } - virtual void reset(); - virtual int getChar() - { int c = lookChar(); buf = EOF; return c; } - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - 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 - GBool eof; // true if at eof - GBool nextLine2D; // true if next line uses 2D encoding - int row; // current row - int inputBuf; // input buffer - int inputBits; // number of bits in input buffer - short *refLine; // reference line changing elements - int b1; // index into refLine - short *codingLine; // coding line changing elements - int a0; // index into codingLine - int outputBits; // remaining ouput bits - int buf; // character buffer - - short getTwoDimCode(); - short getWhiteCode(); - short getBlackCode(); - short lookBits(int n); - void eatBits(int n) { inputBits -= n; } -}; - -//------------------------------------------------------------------------ -// DCTStream -//------------------------------------------------------------------------ - -// 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 -}; - -class DCTStream: public FilterStream { -public: - - DCTStream(Stream *strA); - virtual ~DCTStream(); - virtual StreamKind getKind() { return strDCT; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - virtual GBool isBinary(GBool last = gTrue); - Stream *getRawStream() { return str; } - -private: - - 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; // need YCbCr-to-RGB transform? - 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[4][32]; // buffer for one MCU (non-progressive mode) - int *frameBuf[4]; // buffer for frame (progressive mode) - int comp, x, y, dy; // 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 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 readBaselineSOF(); - GBool readProgressiveSOF(); - GBool readScanInfo(); - GBool readQuantTables(); - GBool readHuffmanTables(); - GBool readRestartInterval(); - GBool readJFIFMarker(); - GBool readAdobeMarker(); - GBool readTrailer(); - int readMarker(); - int read16(); -}; - -//------------------------------------------------------------------------ -// 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 StreamKind getKind() { return strFlate; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual int getRawChar(); - virtual GString *getPSFilter(int psLevel, char *indent); - 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 - - 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 StreamKind getKind() { return strWeird; } - virtual void reset() {} - virtual int getChar() { return EOF; } - virtual int lookChar() { return EOF; } - virtual GString *getPSFilter(int psLevel, char *indent) { return NULL; } - virtual GBool isBinary(GBool last = gTrue) { return gFalse; } -}; - -//------------------------------------------------------------------------ -// FixedLengthEncoder -//------------------------------------------------------------------------ - -class FixedLengthEncoder: public FilterStream { -public: - - FixedLengthEncoder(Stream *strA, int lengthA); - ~FixedLengthEncoder(); - virtual StreamKind getKind() { return strWeird; } - virtual void reset(); - virtual int getChar(); - virtual int lookChar(); - virtual GString *getPSFilter(int psLevel, char *indent) { 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 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, char *indent) { 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 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, char *indent) { 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 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, char *indent) { 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(); -}; - -#endif diff --git a/pdf2swf/xpdf/UTF8.h b/pdf2swf/xpdf/UTF8.h deleted file mode 100644 index 8536dbf..0000000 --- a/pdf2swf/xpdf/UTF8.h +++ /dev/null @@ -1,56 +0,0 @@ -//======================================================================== -// -// UTF8.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -static 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; - } -} - -static 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; - } -} diff --git a/pdf2swf/xpdf/UnicodeMap.cc b/pdf2swf/xpdf/UnicodeMap.cc deleted file mode 100644 index 2b8cb1f..0000000 --- a/pdf2swf/xpdf/UnicodeMap.cc +++ /dev/null @@ -1,293 +0,0 @@ -//======================================================================== -// -// UnicodeMap.cc -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include "gmem.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(-1, "Couldn't find unicodeMap file for the '%s' encoding", - encodingNameA->getCString()); - 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 = 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(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding", - line, encodingNameA->getCString()); - } - } else { - error(-1, "Bad line (%d) in unicodeMap file for the '%s' encoding", - line, encodingNameA->getCString()); - } - ++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; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -UnicodeMap::UnicodeMap(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; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -UnicodeMap::UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapFunc funcA) { - encodingName = new GString(encodingNameA); - unicodeOut = unicodeOutA; - kind = unicodeMapFunc; - func = funcA; - eMaps = NULL; - eMapsLen = 0; - refCnt = 1; -#if MULTITHREADED - gInitMutex(&mutex); -#endif -} - -UnicodeMap::~UnicodeMap() { - delete encodingName; - if (kind == unicodeMapUser && ranges) { - gfree(ranges); - } - if (eMaps) { - gfree(eMaps); - } -#if MULTITHREADED - gDestroyMutex(&mutex); -#endif -} - -void UnicodeMap::incRefCnt() { -#if MULTITHREADED - gLockMutex(&mutex); -#endif - ++refCnt; -#if MULTITHREADED - gUnlockMutex(&mutex); -#endif -} - -void UnicodeMap::decRefCnt() { - GBool done; - -#if MULTITHREADED - gLockMutex(&mutex); -#endif - done = --refCnt == 0; -#if MULTITHREADED - gUnlockMutex(&mutex); -#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/pdf2swf/xpdf/UnicodeMap.h b/pdf2swf/xpdf/UnicodeMap.h deleted file mode 100644 index 0f86101..0000000 --- a/pdf2swf/xpdf/UnicodeMap.h +++ /dev/null @@ -1,123 +0,0 @@ -//======================================================================== -// -// UnicodeMap.h -// -// Mapping from Unicode to an encoding. -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef UNICODEMAP_H -#define UNICODEMAP_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "CharTypes.h" - -#if MULTITHREADED -#include "GMutex.h" -#endif - -class GString; - -//------------------------------------------------------------------------ - -enum UnicodeMapKind { - unicodeMapUser, // read from a file - unicodeMapResident, // static list of ranges - unicodeMapFunc // function pointer -}; - -typedef int (*UnicodeMapFunc)(Unicode u, char *buf, int bufSize); - -struct UnicodeMapRange { - Unicode start, end; // range of Unicode chars - Guint code, nBytes; // first output code -}; - -struct UnicodeMapExt; - -//------------------------------------------------------------------------ - -class UnicodeMap { -public: - - // Create the UnicodeMap specified by . Sets the - // initial reference count to 1. Returns NULL on failure. - static UnicodeMap *parse(GString *encodingNameA); - - // Create a resident UnicodeMap. - UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapRange *rangesA, int lenA); - - // Create a resident UnicodeMap that uses a function instead of a - // list of ranges. - UnicodeMap(char *encodingNameA, GBool unicodeOutA, - UnicodeMapFunc funcA); - - ~UnicodeMap(); - - void incRefCnt(); - void decRefCnt(); - - GString *getEncodingName() { return encodingName; } - - GBool isUnicode() { return unicodeOut; } - - // Return true if this UnicodeMap matches the specified - // . - GBool match(GString *encodingNameA); - - // Map Unicode to the target encoding. Fills in with the - // output and returns the number of bytes used. Output will be - // truncated at bytes. No string terminator is written. - // Returns 0 if no mapping is found. - int mapUnicode(Unicode u, char *buf, int bufSize); - -private: - - UnicodeMap(GString *encodingNameA); - - GString *encodingName; - UnicodeMapKind kind; - GBool unicodeOut; - union { - UnicodeMapRange *ranges; // (user, resident) - UnicodeMapFunc func; // (func) - }; - int len; // (user, resident) - UnicodeMapExt *eMaps; // (user) - int eMapsLen; // (user) - int refCnt; -#if MULTITHREADED - GMutex mutex; -#endif -}; - -//------------------------------------------------------------------------ - -#define unicodeMapCacheSize 4 - -class UnicodeMapCache { -public: - - UnicodeMapCache(); - ~UnicodeMapCache(); - - // Get the UnicodeMap for . Increments its reference - // count; there will be one reference for the cache plus one for the - // caller of this function. Returns NULL on failure. - UnicodeMap *getUnicodeMap(GString *encodingName); - -private: - - UnicodeMap *cache[unicodeMapCacheSize]; -}; - -#endif diff --git a/pdf2swf/xpdf/UnicodeMapTables.h b/pdf2swf/xpdf/UnicodeMapTables.h deleted file mode 100644 index 9c51034..0000000 --- a/pdf2swf/xpdf/UnicodeMapTables.h +++ /dev/null @@ -1,361 +0,0 @@ -//======================================================================== -// -// UnicodeMapTables.h -// -// Copyright 2001-2003 Glyph & Cog, LLC -// -//======================================================================== - -static UnicodeMapRange latin1UnicodeMapRanges[] = { - { 0x000a, 0x000a, 0x0a, 1 }, - { 0x000c, 0x000d, 0x0c, 1 }, - { 0x0020, 0x007e, 0x20, 1 }, - { 0x00a0, 0x00a0, 0x20, 1 }, - { 0x00a1, 0x00ac, 0xa1, 1 }, - { 0x00ae, 0x00ff, 0xae, 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 }, - { 0x2013, 0x2013, 0xad, 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 } -}; -#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 }, - { 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 } -}; -#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/pdf2swf/xpdf/XRef.cc b/pdf2swf/xpdf/XRef.cc deleted file mode 100644 index b371541..0000000 --- a/pdf2swf/xpdf/XRef.cc +++ /dev/null @@ -1,888 +0,0 @@ -//======================================================================== -// -// XRef.cc -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma implementation -#endif - -#include -#include -#include -#include -#include "gmem.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 - -//------------------------------------------------------------------------ -// ObjectStream -//------------------------------------------------------------------------ - -class ObjectStream { -public: - - // Create an object stream, using object number , - // generation 0. - ObjectStream(XRef *xref, int objStrNumA); - - ~ObjectStream(); - - // Return the object number of this object stream. - int getObjStrNum() { return objStrNum; } - - // Get the th object from this stream, which should be - // object number , generation 0. - Object *getObject(int objIdx, int objNum, Object *obj); - -private: - - int objStrNum; // object number of the object stream - int nObjects; // number of objects in the stream - Object *objs; // the objects (length = nObjects) - int *objNums; // the object numbers (length = nObjects) -}; - -ObjectStream::ObjectStream(XRef *xref, int objStrNumA) { - Stream *str; - Parser *parser; - int *offsets; - Object objStr, obj1, obj2; - int first, i; - - objStrNum = objStrNumA; - nObjects = 0; - objs = NULL; - objNums = NULL; - - 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; - } - - 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); - parser = new Parser(xref, new Lexer(xref, str)); - for (i = 0; i < nObjects; ++i) { - parser->getObj(&obj1); - parser->getObj(&obj2); - if (!obj1.isInt() || !obj2.isInt()) { - obj1.free(); - obj2.free(); - delete parser; - gfree(offsets); - goto err1; - } - 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 err1; - } - } - while (str->getChar() != EOF) ; - 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... - for (i = first; i < offsets[0]; ++i) { - objStr.getStream()->getChar(); - } - - // 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]); - } - parser = new Parser(xref, new Lexer(xref, str)); - parser->getObj(&objs[i]); - while (str->getChar() != EOF) ; - delete parser; - } - - gfree(offsets); - - err1: - objStr.free(); - return; -} - -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]) { - return obj->initNull(); - } - return objs[objIdx].copy(obj); -} - -//------------------------------------------------------------------------ -// XRef -//------------------------------------------------------------------------ - -XRef::XRef(BaseStream *strA) { - Guint pos; - Object obj; - - ok = gTrue; - errCode = errNone; - size = 0; - entries = NULL; - streamEnds = NULL; - streamEndsLen = 0; - objStr = NULL; - - encrypted = gFalse; - permFlags = defPermFlags; - ownerPasswordOk = gFalse; - - // read the trailer - str = strA; - start = str->getStart(); - pos = getStartXref(); - - // if there was a problem with the 'startxref' position, try to - // reconstruct the xref table - if (pos == 0) { - if (!(ok = constructXRef())) { - errCode = errDamaged; - return; - } - - // read the xref table - } else { - while (readXRef(&pos)) ; - - // if there was a problem with the xref table, - // try to reconstruct it - if (!ok) { - if (!(ok = constructXRef())) { - 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() { - gfree(entries); - trailerDict.free(); - if (streamEnds) { - gfree(streamEnds); - } - if (objStr) { - delete objStr; - } -} - -// Read the 'startxref' position. -Guint XRef::getStartXref() { - char buf[xrefSearchSize+1]; - char *p; - int c, n, i; - - // read last xrefSearchSize bytes - str->setPos(xrefSearchSize, -1); - for (n = 0; n < xrefSearchSize; ++n) { - if ((c = str->getChar()) == EOF) { - break; - } - buf[n] = c; - } - 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); ++p) ; - lastXRefPos = strToUnsigned(p); - - return lastXRefPos; -} - -// Read one xref table section. Also reads the associated trailer -// dictionary, and returns the prev pointer (if any). -GBool XRef::readXRef(Guint *pos) { - Parser *parser; - Object obj; - GBool more; - - // start up a parser, parse one token - obj.initNull(); - parser = new Parser(NULL, - new Lexer(NULL, - str->makeSubStream(start + *pos, gFalse, 0, &obj))); - parser->getObj(&obj); - - // parse an old-style xref table - if (obj.isCmd("xref")) { - obj.free(); - more = readXRefTable(parser, pos); - - // parse an xref stream - } else if (obj.isInt()) { - obj.free(); - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - obj.free(); - if (!parser->getObj(&obj)->isCmd("obj")) { - goto err1; - } - obj.free(); - if (!parser->getObj(&obj)->isStream()) { - goto err1; - } - more = readXRefStream(obj.getStream(), pos); - obj.free(); - - } else { - goto err1; - } - - delete parser; - return more; - - err1: - obj.free(); - delete parser; - ok = gFalse; - return gFalse; -} - -GBool XRef::readXRefTable(Parser *parser, Guint *pos) { - XRefEntry entry; - GBool more; - Object obj, obj2; - Guint pos2; - int first, n, newSize, i; - - while (1) { - parser->getObj(&obj); - if (obj.isCmd("trailer")) { - obj.free(); - break; - } - if (!obj.isInt()) { - goto err1; - } - first = obj.getInt(); - obj.free(); - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - n = obj.getInt(); - obj.free(); - if (first < 0 || n < 0 || first + n < 0) { - 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 = 0xffffffff; - entries[i].type = xrefEntryFree; - } - size = newSize; - } - for (i = first; i < first + n; ++i) { - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - entry.offset = (Guint)obj.getInt(); - obj.free(); - if (!parser->getObj(&obj)->isInt()) { - goto err1; - } - entry.gen = obj.getInt(); - obj.free(); - parser->getObj(&obj); - if (obj.isCmd("n")) { - entry.type = xrefEntryUncompressed; - } else if (obj.isCmd("f")) { - entry.type = xrefEntryFree; - } else { - goto err1; - } - obj.free(); - if (entries[i].offset == 0xffffffff) { - 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 = 0xffffffff; - } - } - } - } - - // read the trailer dictionary - if (!parser->getObj(&obj)->isDict()) { - goto err1; - } - - // get the 'Prev' pointer - obj.getDict()->lookupNF("Prev", &obj2); - if (obj2.isInt()) { - *pos = (Guint)obj2.getInt(); - more = gTrue; - } else if (obj2.isRef()) { - // certain buggy PDF generators generate "/Prev NNN 0 R" instead - // of "/Prev NNN" - *pos = (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 - if (obj.getDict()->lookup("XRefStm", &obj2)->isInt()) { - pos2 = (Guint)obj2.getInt(); - readXRef(&pos2); - if (!ok) { - obj2.free(); - goto err1; - } - } - obj2.free(); - - obj.free(); - return more; - - err1: - obj.free(); - ok = gFalse; - return gFalse; -} - -GBool XRef::readXRefStream(Stream *xrefStr, Guint *pos) { - 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 = 0xffffffff; - 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(); - if (w[i] < 0 || w[i] > 4) { - goto err1; - } - } - obj.free(); - - 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(); - - dict->lookupNF("Prev", &obj); - if (obj.isInt()) { - *pos = (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) { - Guint offset; - int type, gen, 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 = 0xffffffff; - 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; - } - for (gen = 0, j = 0; j < w[2]; ++j) { - if ((c = xrefStr->getChar()) == EOF) { - return gFalse; - } - gen = (gen << 8) + c; - } - if (entries[i].offset == 0xffffffff) { - switch (type) { - case 0: - entries[i].offset = offset; - entries[i].gen = gen; - entries[i].type = xrefEntryFree; - break; - case 1: - entries[i].offset = offset; - entries[i].gen = gen; - entries[i].type = xrefEntryUncompressed; - break; - case 2: - entries[i].offset = offset; - entries[i].gen = gen; - entries[i].type = xrefEntryCompressed; - break; - default: - return gFalse; - } - } - } - - return gTrue; -} - -// Attempt to construct an xref table for a damaged file. -GBool XRef::constructXRef() { - Parser *parser; - Object newTrailerDict, obj; - char buf[256]; - Guint pos; - int num, gen; - int newSize; - int streamEndsSize; - char *p; - int i; - GBool gotRoot; - - gfree(entries); - size = 0; - entries = NULL; - - error(0, "PDF file is damaged - attempting to reconstruct xref table..."); - gotRoot = gFalse; - streamEndsLen = streamEndsSize = 0; - - str->reset(); - while (1) { - pos = str->getPos(); - if (!str->getLine(buf, 256)) { - break; - } - p = buf; - - // got trailer dictionary - if (!strncmp(p, "trailer", 7)) { - obj.initNull(); - parser = new Parser(NULL, - new Lexer(NULL, - str->makeSubStream(pos + 7, gFalse, 0, &obj))); - parser->getObj(&newTrailerDict); - if (newTrailerDict.isDict()) { - newTrailerDict.dictLookupNF("Root", &obj); - if (obj.isRef()) { - rootNum = obj.getRefNum(); - rootGen = obj.getRefGen(); - if (!trailerDict.isNone()) { - trailerDict.free(); - } - newTrailerDict.copy(&trailerDict); - gotRoot = gTrue; - } - obj.free(); - } - newTrailerDict.free(); - delete parser; - - // look for object - } else if (isdigit(*p)) { - num = atoi(p); - if (num > 0) { - do { - ++p; - } while (*p && isdigit(*p)); - if (isspace(*p)) { - do { - ++p; - } while (*p && isspace(*p)); - if (isdigit(*p)) { - gen = atoi(p); - do { - ++p; - } while (*p && isdigit(*p)); - if (isspace(*p)) { - do { - ++p; - } while (*p && isspace(*p)); - if (!strncmp(p, "obj", 3)) { - if (num >= size) { - newSize = (num + 1 + 255) & ~255; - if (newSize < 0) { - error(-1, "Bad object number"); - return gFalse; - } - entries = (XRefEntry *) - greallocn(entries, newSize, sizeof(XRefEntry)); - for (i = size; i < newSize; ++i) { - entries[i].offset = 0xffffffff; - entries[i].type = xrefEntryFree; - } - size = newSize; - } - if (entries[num].type == xrefEntryFree || - gen >= entries[num].gen) { - entries[num].offset = pos - start; - entries[num].gen = gen; - entries[num].type = xrefEntryUncompressed; - } - } - } - } - } - } - - } else if (!strncmp(p, "endstream", 9)) { - if (streamEndsLen == streamEndsSize) { - streamEndsSize += 64; - streamEnds = (Guint *)greallocn(streamEnds, - streamEndsSize, sizeof(int)); - } - streamEnds[streamEndsLen++] = pos; - } - } - - if (gotRoot) - return gTrue; - - error(-1, "Couldn't find trailer dictionary"); - return gFalse; -} - -void XRef::setEncryption(int permFlagsA, GBool ownerPasswordOkA, - Guchar *fileKeyA, int keyLengthA, int encVersionA) { - int i; - - encrypted = gTrue; - permFlags = permFlagsA; - ownerPasswordOk = ownerPasswordOkA; - if (keyLengthA <= 16) { - keyLength = keyLengthA; - } else { - keyLength = 16; - } - for (i = 0; i < keyLength; ++i) { - fileKey[i] = fileKeyA[i]; - } - encVersion = encVersionA; -} - -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) { - XRefEntry *e; - Parser *parser; - Object obj1, obj2, obj3; - - // check for bogus ref - this can happen in corrupted PDF files - if (num < 0 || num >= size) { - goto err; - } - - 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))); - parser->getObj(&obj1); - parser->getObj(&obj2); - parser->getObj(&obj3); - 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, encrypted ? fileKey : (Guchar *)NULL, keyLength, - num, gen); - obj1.free(); - obj2.free(); - obj3.free(); - delete parser; - break; - - case xrefEntryCompressed: - if (gen != 0) { - goto err; - } - if (!objStr || objStr->getObjStrNum() != (int)e->offset) { - if (objStr) { - delete objStr; - } - objStr = new ObjectStream(this, e->offset); - } - objStr->getObject(e->gen, num, obj); - break; - - default: - goto err; - } - - return obj; - - err: - return obj->initNull(); -} - -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(Guint streamStart, Guint *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; -} - -Guint XRef::strToUnsigned(char *s) { - Guint x; - char *p; - int i; - - x = 0; - for (p = s, i = 0; *p && isdigit(*p) && i < 10; ++p, ++i) { - x = 10 * x + (*p - '0'); - } - return x; -} diff --git a/pdf2swf/xpdf/XRef.h b/pdf2swf/xpdf/XRef.h deleted file mode 100644 index f9dede3..0000000 --- a/pdf2swf/xpdf/XRef.h +++ /dev/null @@ -1,131 +0,0 @@ -//======================================================================== -// -// XRef.h -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef XREF_H -#define XREF_H - -#include - -#ifdef USE_GCC_PRAGMAS -#pragma interface -#endif - -#include "gtypes.h" -#include "Object.h" - -class Dict; -class Stream; -class Parser; -class ObjectStream; - -//------------------------------------------------------------------------ -// XRef -//------------------------------------------------------------------------ - -enum XRefEntryType { - xrefEntryFree, - xrefEntryUncompressed, - xrefEntryCompressed -}; - -struct XRefEntry { - Guint offset; - int gen; - XRefEntryType type; -}; - -class XRef { -public: - - // Constructor. Read xref table from stream. - XRef(BaseStream *strA); - - // Destructor. - ~XRef(); - - // Is xref table valid? - GBool isOk() { return ok; } - - // Get the error code (if isOk() returns false). - int getErrorCode() { return errCode; } - - // Set the encryption parameters. - void setEncryption(int permFlagsA, GBool ownerPasswordOkA, - Guchar *fileKeyA, int keyLengthA, int encVersionA); - - // Is the file encrypted? - GBool isEncrypted() { return encrypted; } - - // Check various permissions. - GBool okToPrint(GBool ignoreOwnerPW = gFalse); - GBool okToChange(GBool ignoreOwnerPW = gFalse); - GBool okToCopy(GBool ignoreOwnerPW = gFalse); - GBool okToAddNotes(GBool ignoreOwnerPW = gFalse); - - // Get catalog object. - Object *getCatalog(Object *obj) { return fetch(rootNum, rootGen, obj); } - - // Fetch an indirect reference. - Object *fetch(int num, int gen, Object *obj); - - // Return the document's Info dictionary (if any). - Object *getDocInfo(Object *obj); - Object *getDocInfoNF(Object *obj); - - // Return the number of objects in the xref table. - int getNumObjects() { return size; } - - // Return the offset of the last xref table. - Guint getLastXRefPos() { return lastXRefPos; } - - // Return the catalog object reference. - int getRootNum() { return rootNum; } - int getRootGen() { return rootGen; } - - // Get end position for a stream in a damaged file. - // Returns false if unknown or file is not damaged. - GBool getStreamEnd(Guint streamStart, Guint *streamEnd); - - // Direct access. - int getSize() { return size; } - XRefEntry *getEntry(int i) { return &entries[i]; } - Object *getTrailerDict() { return &trailerDict; } - -private: - - BaseStream *str; // input stream - Guint start; // offset in file (to allow for garbage - // at beginning of file) - XRefEntry *entries; // xref entries - int size; // size of array - int rootNum, rootGen; // catalog dict - GBool ok; // true if xref table is valid - int errCode; // error code (if is false) - Object trailerDict; // trailer dictionary - Guint lastXRefPos; // offset of last xref table - Guint *streamEnds; // 'endstream' positions - only used in - // damaged files - int streamEndsLen; // number of valid entries in streamEnds - ObjectStream *objStr; // cached object stream - GBool encrypted; // true if file is encrypted - int permFlags; // permission bits - GBool ownerPasswordOk; // true if owner password is correct - Guchar fileKey[16]; // file decryption key - int keyLength; // length of key, in bytes - int encVersion; // encryption algorithm - - Guint getStartXref(); - GBool readXRef(Guint *pos); - GBool readXRefTable(Parser *parser, Guint *pos); - GBool readXRefStreamSection(Stream *xrefStr, int *w, int first, int n); - GBool readXRefStream(Stream *xrefStr, Guint *pos); - GBool constructXRef(); - Guint strToUnsigned(char *s); -}; - -#endif diff --git a/pdf2swf/xpdf/aconf.h b/pdf2swf/xpdf/aconf.h deleted file mode 100644 index 524ccee..0000000 --- a/pdf2swf/xpdf/aconf.h +++ /dev/null @@ -1,24 +0,0 @@ -/* aconf.h. Generated by configure. */ -/* - * aconf.h - * - * Copyright 2002 Glyph & Cog, LLC - */ - -#ifndef ACONF_H -#define ACONF_H -#include "../../config.h" - -#define HAVE_STRINGS_H 1 - -// todo: -// -// HAVE_STRINGS_H -// HAVE_BSTRING_H -// HAVE_SYS_SELECT_H -// SELECT_TAKES_INT -// HAVE_FSEEK64 -// HAVE_MKSTEMPS -// HAVE_FSEEKO 1 - -#endif diff --git a/pdf2swf/xpdf/cmyk.cc b/pdf2swf/xpdf/cmyk.cc deleted file mode 100644 index c74f743..0000000 --- a/pdf2swf/xpdf/cmyk.cc +++ /dev/null @@ -1,661 +0,0 @@ -#include -#include -#include -#include "GfxState.h" -static struct _rgb {unsigned char r,g,b;} -cmyk2rgb[8*16*16*8] = { -{255,255,255},{222,223,225},{191,192,195},{162,164,167},{133,135,138},{106,107,110},{73,74,75},{34,30,31},{255,254,241},{223,222,212},{192,191,184},{163,163,157},{134,134,129},{107,106,103},{74,73,70},{33,29,27},{255,253,227},{223,221,199},{192,191,174},{163,163,147},{135,134,121},{107,106,96},{74,73,65},{33,29,23},{255,252,214},{224,220,188},{193,190,164},{164,162,140},{135,133,115},{107,105,90},{74,72,61},{32,28,19}, -{255,251,201},{225,220,177},{193,190,154},{164,162,132},{135,133,108},{107,105,85},{74,72,56},{32,28,15},{255,250,187},{226,219,165},{194,189,144},{164,161,122},{135,132,100},{107,104,79},{74,72,52},{31,28,9},{255,249,173},{227,219,154},{195,189,134},{164,160,113},{135,132,92},{107,104,72},{74,72,47},{31,28,5},{255,248,160},{226,218,142},{195,188,123},{165,159,104},{135,131,85},{107,103,65},{74,71,41},{30,27,2}, -{255,247,147},{227,216,130},{196,187,112},{165,158,95},{135,131,77},{107,103,59},{74,71,35},{29,26,0},{255,246,133},{228,215,117},{197,186,101},{165,157,86},{135,130,69},{107,103,52},{74,70,29},{28,26,0},{255,245,117},{228,214,103},{196,186,90},{165,157,76},{135,130,60},{107,103,44},{74,70,21},{27,26,0},{255,244,100},{227,214,89},{195,185,78},{165,157,65},{135,129,50},{107,102,35},{73,70,12},{26,26,0}, -{255,244,78},{227,213,72},{195,184,62},{165,156,51},{135,129,38},{107,102,22},{73,70,6},{25,26,0},{255,243,54},{228,212,52},{196,183,44},{165,155,36},{135,128,24},{107,101,7},{72,69,1},{24,25,0},{255,242,27},{228,212,27},{196,183,22},{165,155,18},{135,128,12},{107,101,3},{72,69,0},{24,25,0},{255,241,0},{227,212,0},{195,182,0},{165,154,0},{136,127,0},{107,100,0},{72,69,0},{24,25,0}, -{253,241,246},{220,210,216},{190,182,189},{161,154,161},{133,127,133},{106,101,105},{74,69,72},{34,26,28},{254,240,232},{221,209,204},{191,181,178},{162,154,152},{133,127,125},{106,100,99},{74,68,67},{33,25,24},{254,239,219},{222,209,193},{191,181,168},{162,154,143},{134,127,117},{106,100,92},{74,68,62},{33,25,20},{254,238,207},{222,208,182},{192,180,159},{163,153,135},{134,126,111},{106,99,87},{74,67,58},{32,24,16}, -{254,237,194},{223,207,172},{192,179,149},{163,153,127},{134,126,104},{106,99,82},{74,67,53},{32,24,11},{255,236,181},{224,206,160},{193,178,140},{163,152,118},{134,125,97},{106,98,76},{73,67,49},{31,24,6},{255,235,168},{225,206,149},{193,178,130},{163,151,110},{134,124,89},{106,98,69},{73,67,44},{31,23,2},{255,234,155},{225,205,137},{194,177,119},{164,150,101},{134,124,82},{106,97,62},{73,66,38},{30,23,1}, -{255,233,143},{225,204,126},{194,176,108},{164,149,92},{134,124,74},{106,97,56},{73,66,32},{29,22,0},{255,232,129},{226,203,114},{195,176,98},{164,148,83},{134,123,66},{106,97,49},{73,65,26},{28,22,0},{255,231,114},{226,202,100},{194,176,88},{164,148,73},{134,123,57},{106,97,41},{73,65,19},{27,22,0},{255,230,98},{226,202,86},{194,175,76},{164,148,63},{134,122,48},{106,96,32},{72,65,10},{26,22,0}, -{255,230,77},{226,201,70},{194,174,61},{164,147,49},{134,122,36},{106,96,20},{72,65,5},{26,22,0},{255,229,56},{226,200,53},{194,173,45},{164,146,35},{134,121,22},{106,95,6},{72,64,0},{25,21,0},{255,229,28},{226,200,28},{194,173,23},{164,146,17},{134,121,11},{106,95,2},{72,64,0},{25,21,0},{255,228,0},{226,200,1},{194,172,2},{164,146,0},{135,120,0},{106,94,0},{72,64,0},{24,21,0}, -{252,226,237},{219,197,207},{189,172,182},{161,145,155},{133,119,128},{106,94,101},{75,63,70},{34,21,26},{253,225,224},{220,197,196},{190,171,172},{162,145,146},{133,119,121},{105,93,95},{74,62,65},{33,20,22},{254,224,211},{221,197,186},{191,171,162},{162,145,138},{133,119,114},{105,93,89},{74,62,59},{33,20,16},{254,223,199},{221,196,176},{192,170,153},{162,144,130},{133,118,108},{105,92,84},{74,61,55},{32,20,12}, -{254,222,187},{221,195,166},{192,169,144},{162,144,122},{133,118,101},{105,92,79},{74,61,51},{32,20,8},{255,221,175},{223,194,154},{192,168,135},{163,143,115},{133,117,94},{105,91,73},{73,61,46},{31,19,3},{255,220,162},{224,194,144},{192,168,126},{163,142,107},{133,116,86},{105,91,67},{73,61,41},{31,18,0},{255,219,150},{224,193,133},{193,167,115},{163,141,98},{134,116,79},{106,91,60},{73,60,36},{30,18,0}, -{255,219,138},{224,192,122},{193,166,105},{163,141,89},{134,116,72},{106,91,54},{73,60,30},{29,18,0},{255,218,126},{224,191,111},{193,166,96},{163,140,81},{134,115,64},{106,90,47},{73,60,24},{28,17,0},{255,218,111},{225,191,98},{193,166,86},{163,140,71},{134,115,55},{106,90,39},{73,60,17},{27,17,0},{255,217,96},{226,190,84},{194,165,75},{164,140,61},{134,114,46},{106,89,30},{72,59,8},{26,17,0}, -{255,217,77},{226,190,69},{194,165,60},{164,139,48},{134,114,34},{106,89,18},{72,59,4},{26,17,0},{255,216,57},{225,189,53},{193,164,45},{163,138,34},{133,113,21},{105,88,6},{72,59,0},{25,17,0},{255,216,30},{225,189,28},{193,164,24},{163,138,17},{133,113,10},{105,88,2},{72,59,0},{25,17,0},{255,215,1},{226,188,3},{194,163,3},{163,138,0},{134,113,0},{106,88,0},{72,59,0},{24,16,0}, -{250,214,229},{217,186,201},{188,162,176},{160,137,151},{133,112,124},{105,88,97},{74,59,66},{34,15,22},{251,212,217},{218,185,190},{189,161,167},{161,137,142},{133,112,117},{105,87,91},{73,58,61},{34,15,18},{252,211,204},{219,185,180},{190,161,158},{161,137,134},{133,112,110},{105,87,85},{73,58,56},{34,15,12},{252,211,193},{220,184,170},{190,160,149},{161,136,126},{132,111,104},{105,86,81},{73,57,52},{33,15,8}, -{253,210,181},{220,184,161},{190,160,140},{161,135,118},{132,111,97},{105,86,75},{73,57,48},{32,15,4},{253,209,169},{221,183,150},{191,159,131},{162,135,111},{132,110,90},{104,85,69},{73,57,44},{32,14,2},{253,208,158},{221,183,140},{191,159,122},{162,135,103},{132,110,83},{104,85,63},{73,57,39},{32,14,0},{254,207,146},{222,182,129},{191,158,112},{162,134,95},{133,109,76},{105,85,57},{73,56,33},{31,14,0}, -{254,207,134},{222,182,118},{191,157,103},{162,134,87},{133,109,70},{105,85,51},{73,56,27},{30,14,0},{254,206,122},{223,181,108},{191,157,94},{162,133,79},{133,108,62},{105,84,45},{73,56,22},{29,13,0},{254,206,108},{223,181,96},{191,156,83},{162,133,69},{133,108,53},{105,84,37},{73,56,15},{28,13,0},{254,205,94},{223,180,83},{192,155,72},{162,132,59},{133,108,44},{105,84,28},{72,55,6},{27,13,0}, -{254,205,76},{223,180,68},{192,155,58},{162,132,46},{133,108,33},{105,84,17},{72,55,3},{27,13,0},{255,204,58},{223,179,53},{191,155,44},{162,131,33},{133,107,20},{105,84,5},{72,55,0},{26,13,0},{255,204,34},{223,179,30},{191,155,25},{162,131,18},{133,107,10},{105,84,2},{72,55,0},{26,13,0},{254,203,9},{224,178,7},{192,154,5},{162,130,1},{133,106,0},{105,83,0},{72,55,0},{25,12,0}, -{249,201,221},{216,175,194},{188,151,170},{160,129,146},{133,105,120},{105,81,94},{74,54,63},{34,10,19},{250,199,209},{217,174,183},{189,150,161},{161,129,137},{133,105,113},{105,81,88},{73,53,58},{34,10,14},{250,198,197},{218,174,173},{189,150,152},{161,129,129},{133,105,106},{105,81,82},{73,53,53},{34,10,8},{251,198,186},{219,173,164},{189,150,144},{160,128,122},{132,104,100},{105,81,78},{73,52,49},{33,10,5}, -{252,198,175},{220,173,156},{189,150,135},{160,127,114},{132,103,94},{105,81,72},{73,52,45},{32,10,2},{252,197,164},{219,172,146},{190,149,126},{161,127,107},{132,103,87},{104,80,66},{73,52,41},{32,9,1},{252,196,153},{219,172,136},{191,149,118},{161,127,99},{132,103,80},{104,80,60},{73,52,36},{32,9,0},{252,195,142},{220,171,125},{190,148,109},{161,126,92},{132,102,73},{104,80,54},{73,52,30},{31,9,0}, -{252,195,130},{221,171,115},{190,148,100},{161,126,84},{132,102,67},{104,80,48},{73,52,24},{30,9,0},{253,194,118},{221,170,105},{190,147,91},{162,125,76},{133,101,60},{105,79,42},{73,51,19},{29,9,0},{253,194,105},{221,170,93},{190,147,80},{162,125,66},{133,101,51},{105,79,35},{73,51,13},{28,9,0},{253,193,91},{221,169,81},{191,146,69},{161,124,56},{132,101,43},{104,79,27},{72,51,5},{27,8,0}, -{253,193,76},{221,169,68},{191,146,57},{161,124,45},{132,101,32},{104,79,17},{72,51,2},{27,8,0},{254,192,59},{222,168,53},{190,146,44},{162,123,33},{133,100,20},{105,78,5},{72,51,0},{26,9,0},{254,192,38},{222,168,32},{190,146,25},{162,123,18},{133,100,10},{105,78,2},{72,51,0},{26,9,0},{253,191,16},{222,167,12},{190,145,7},{161,122,2},{133,99,0},{105,78,0},{72,51,0},{26,8,0}, -{247,187,214},{215,164,187},{187,141,164},{159,120,140},{132,98,115},{104,75,90},{73,48,60},{34,4,15},{248,185,202},{216,163,177},{188,140,155},{159,119,132},{132,98,108},{104,75,84},{73,47,55},{34,4,10},{249,184,190},{217,162,167},{188,140,146},{159,119,124},{132,98,101},{104,75,78},{73,47,51},{34,4,6},{250,184,179},{218,161,158},{188,140,138},{159,119,117},{131,97,96},{105,75,74},{74,47,47},{33,4,3}, -{250,184,169},{218,161,150},{188,140,130},{159,118,110},{131,96,90},{105,75,70},{74,47,43},{33,4,1},{250,183,158},{218,160,140},{189,139,122},{160,118,103},{131,96,84},{104,74,64},{73,47,39},{32,3,0},{250,183,147},{218,160,130},{189,139,114},{160,118,95},{131,96,77},{104,74,58},{73,47,34},{32,3,0},{250,182,136},{219,159,121},{189,138,105},{160,117,88},{132,95,70},{104,74,52},{72,46,28},{31,3,0}, -{250,181,126},{220,159,111},{189,138,96},{160,117,80},{132,95,64},{104,74,46},{72,46,22},{29,3,0},{251,180,114},{219,159,101},{189,137,87},{161,116,73},{132,94,57},{104,73,40},{73,46,17},{28,3,0},{251,180,102},{219,159,91},{189,137,78},{161,116,64},{132,94,49},{104,73,33},{73,46,11},{28,3,0},{251,179,89},{219,158,79},{189,136,67},{160,115,54},{131,94,41},{104,73,25},{72,46,4},{28,3,0}, -{251,179,75},{219,158,66},{189,136,55},{160,115,44},{131,94,30},{104,73,15},{72,46,1},{28,3,0},{252,179,60},{220,157,52},{189,136,43},{160,114,32},{132,93,18},{104,72,4},{72,46,0},{27,3,0},{252,179,41},{220,157,34},{189,136,26},{160,114,17},{132,93,9},{104,72,2},{72,46,0},{27,3,0},{251,178,22},{220,156,16},{189,135,9},{160,114,2},{132,93,0},{104,72,0},{71,46,0},{27,3,0}, -{246,173,206},{214,152,181},{186,131,158},{158,111,135},{131,90,110},{104,69,86},{73,42,57},{34,0,11},{247,172,194},{215,152,171},{187,130,149},{158,110,127},{131,90,104},{104,69,81},{73,42,52},{34,0,7},{247,171,182},{215,151,161},{187,130,140},{158,110,119},{131,90,97},{104,69,75},{73,42,48},{34,0,3},{248,170,173},{216,150,152},{187,130,133},{159,110,112},{131,89,93},{105,69,71},{74,42,44},{33,0,2}, -{248,170,163},{216,150,144},{187,130,125},{159,110,106},{131,89,87},{105,69,67},{74,42,40},{33,0,0},{248,170,153},{217,149,135},{187,129,118},{159,109,99},{131,88,81},{104,68,61},{73,42,36},{32,0,0},{248,170,142},{217,149,126},{187,129,110},{159,109,92},{131,88,74},{104,68,56},{73,42,31},{32,0,0},{248,169,132},{217,148,117},{188,128,101},{160,108,85},{132,88,67},{104,68,50},{72,41,25},{31,0,0}, -{249,169,122},{218,148,107},{188,128,93},{160,108,77},{132,88,61},{104,68,44},{72,41,20},{29,0,0},{250,168,111},{217,148,98},{188,127,84},{160,107,70},{132,87,54},{104,67,38},{73,41,15},{28,0,0},{250,168,99},{217,148,88},{188,127,75},{160,107,61},{132,87,47},{104,67,31},{73,41,9},{28,0,0},{249,167,87},{217,147,77},{188,126,65},{160,106,52},{131,87,39},{104,67,23},{72,41,4},{28,0,0}, -{249,167,73},{217,147,64},{188,126,53},{160,106,42},{131,87,28},{104,67,14},{72,41,1},{28,0,0},{250,166,59},{218,146,51},{188,126,42},{159,106,31},{131,86,17},{103,66,4},{72,41,0},{27,0,0},{250,166,43},{218,146,35},{188,126,27},{159,106,17},{131,86,9},{103,66,2},{72,41,0},{27,0,0},{249,165,27},{218,145,19},{188,125,11},{159,106,3},{132,86,0},{104,66,0},{71,41,0},{27,0,0}, -{245,160,198},{213,140,174},{185,121,152},{157,102,130},{130,83,106},{104,62,83},{73,37,54},{34,0,8},{246,159,187},{214,140,164},{186,120,143},{157,101,122},{131,82,100},{104,62,78},{73,37,49},{34,0,4},{246,159,175},{214,140,155},{186,120,135},{157,101,114},{131,82,94},{104,62,72},{73,37,46},{34,0,1},{247,158,166},{215,139,147},{186,120,128},{158,101,108},{130,82,89},{104,62,68},{73,37,42},{33,0,1}, -{247,158,158},{215,139,139},{186,120,121},{158,101,102},{130,82,84},{104,62,64},{73,37,38},{33,0,0},{246,157,148},{216,138,130},{186,119,114},{158,100,95},{131,81,78},{103,61,58},{72,37,33},{32,0,0},{246,157,138},{216,138,122},{186,119,106},{158,100,88},{131,81,71},{103,61,53},{72,37,28},{32,0,0},{247,157,129},{216,137,113},{187,118,98},{159,99,81},{131,81,65},{103,61,48},{71,36,23},{31,0,0}, -{248,157,119},{216,137,104},{187,118,90},{159,99,74},{131,81,59},{103,61,42},{71,36,18},{30,0,0},{249,156,108},{216,137,95},{187,118,82},{159,99,67},{131,80,52},{103,61,35},{72,36,12},{29,0,0},{249,156,97},{216,137,85},{187,118,73},{159,99,60},{131,80,44},{103,61,28},{72,36,8},{29,0,0},{248,155,85},{216,136,75},{187,117,63},{159,99,51},{131,80,37},{103,61,21},{72,36,3},{28,0,0}, -{248,155,72},{216,136,63},{187,117,52},{159,99,41},{131,80,27},{103,61,13},{72,36,1},{28,0,0},{248,154,58},{217,135,50},{187,117,41},{158,98,30},{130,79,16},{103,60,3},{71,36,0},{27,0,0},{248,154,43},{217,135,36},{187,117,28},{158,98,18},{130,79,8},{103,60,1},{71,36,0},{27,0,0},{248,153,28},{216,134,22},{187,116,15},{158,98,5},{131,79,0},{103,60,0},{71,36,0},{26,0,0}, -{243,147,190},{212,128,168},{184,111,146},{157,93,124},{130,75,102},{104,56,79},{73,30,51},{34,0,4},{244,147,179},{213,128,158},{185,110,138},{157,93,118},{131,74,96},{104,56,74},{73,31,47},{34,0,2},{244,147,169},{213,128,149},{185,110,130},{157,93,110},{131,74,90},{104,56,69},{73,31,43},{34,0,0},{245,146,160},{214,127,141},{185,110,124},{157,93,104},{130,75,85},{104,56,65},{73,31,39},{33,0,0}, -{245,146,152},{214,127,133},{185,110,117},{157,93,98},{130,75,80},{104,56,60},{73,31,35},{33,0,0},{244,145,142},{214,127,125},{184,109,110},{156,92,91},{130,74,74},{103,55,55},{72,31,31},{32,0,0},{244,144,133},{214,127,117},{184,109,102},{156,92,84},{130,74,68},{103,55,50},{72,31,26},{31,0,0},{245,145,124},{215,126,109},{185,108,94},{157,91,77},{130,73,62},{102,55,45},{71,30,21},{31,0,0}, -{246,145,115},{215,126,100},{185,108,86},{157,91,71},{130,73,56},{102,55,40},{71,30,16},{30,0,0},{247,144,105},{214,125,92},{185,108,79},{157,91,65},{130,73,50},{103,55,33},{72,31,10},{29,0,0},{247,144,94},{214,125,83},{185,108,71},{157,91,58},{130,73,42},{103,55,26},{72,31,6},{29,0,0},{246,143,83},{214,125,73},{185,108,61},{157,91,49},{130,73,35},{103,55,19},{72,31,2},{28,0,0}, -{246,143,70},{214,125,61},{185,108,50},{157,91,39},{130,73,25},{103,55,11},{72,31,1},{28,0,0},{246,142,57},{215,124,49},{185,107,40},{157,90,28},{130,73,14},{103,54,3},{71,30,0},{27,0,0},{246,142,44},{215,124,37},{185,107,29},{157,90,18},{130,73,7},{103,54,1},{71,30,0},{27,0,0},{246,141,30},{215,124,24},{185,107,18},{157,90,6},{130,72,0},{103,54,0},{71,30,0},{26,0,0}, -{242,135,182},{211,116,161},{183,101,140},{156,84,119},{130,67,98},{103,49,75},{72,23,48},{35,0,1},{243,134,172},{212,116,151},{184,101,133},{156,84,113},{130,67,92},{103,49,71},{72,24,44},{34,0,1},{243,134,162},{212,116,142},{184,101,125},{156,84,106},{130,67,86},{103,49,66},{72,24,40},{33,0,0},{244,134,154},{213,116,135},{184,101,119},{156,84,100},{130,67,81},{103,49,62},{72,24,36},{32,0,0}, -{244,134,146},{213,116,128},{184,101,112},{156,84,94},{130,67,76},{103,49,57},{72,24,32},{32,0,0},{243,133,137},{213,116,120},{183,100,105},{155,83,88},{129,67,70},{102,49,52},{71,24,28},{31,0,0},{243,132,128},{213,116,112},{183,100,97},{155,83,81},{129,67,65},{102,49,47},{71,24,23},{30,0,0},{244,132,119},{214,115,105},{184,99,90},{156,83,74},{129,66,59},{103,48,42},{72,24,19},{30,0,0}, -{245,132,110},{214,115,96},{184,99,83},{156,83,68},{129,66,53},{103,48,37},{72,24,14},{30,0,0},{245,132,101},{213,114,89},{184,99,76},{156,83,62},{130,66,48},{102,48,32},{71,25,7},{29,0,0},{245,132,91},{213,114,80},{184,99,68},{156,83,55},{130,66,41},{102,48,25},{71,25,4},{29,0,0},{245,131,81},{213,115,70},{184,99,59},{156,82,47},{129,66,34},{102,48,18},{71,25,1},{28,0,0}, -{245,131,69},{213,115,60},{184,99,49},{156,82,38},{129,66,24},{102,48,10},{71,25,1},{28,0,0},{245,130,56},{214,114,48},{184,98,39},{156,82,27},{129,66,13},{102,48,3},{71,25,0},{28,0,0},{245,130,45},{214,114,37},{184,98,29},{156,82,17},{129,66,6},{102,48,1},{71,25,0},{28,0,0},{245,130,32},{214,114,25},{184,98,19},{156,81,6},{129,65,0},{102,48,0},{70,25,0},{27,0,0}, -{242,121,175},{211,104,154},{183,90,135},{156,74,114},{129,58,93},{103,41,72},{72,14,45},{33,0,0},{242,120,165},{211,104,145},{183,90,128},{156,74,108},{130,58,88},{103,41,68},{72,15,41},{32,0,0},{242,120,156},{211,104,137},{183,90,120},{156,74,102},{130,58,82},{103,41,63},{72,15,37},{31,0,0},{242,120,148},{212,104,130},{184,90,114},{156,74,96},{129,58,78},{103,42,59},{72,15,33},{31,0,0}, -{242,120,140},{212,104,123},{184,90,107},{156,74,90},{129,58,73},{103,42,54},{72,15,29},{31,0,0},{242,119,132},{212,104,115},{183,90,101},{155,74,85},{129,58,67},{102,42,49},{71,16,25},{30,0,0},{242,119,123},{212,104,107},{183,90,93},{155,74,78},{129,58,62},{102,42,44},{71,16,20},{29,0,0},{243,119,115},{213,103,100},{183,89,86},{155,74,71},{129,58,56},{102,41,39},{71,16,16},{29,0,0}, -{243,119,106},{213,103,93},{183,88,80},{156,74,65},{129,58,50},{102,41,34},{71,16,11},{29,0,0},{243,118,97},{212,103,86},{184,89,73},{156,74,59},{129,58,45},{102,41,29},{71,17,5},{28,0,0},{243,118,88},{212,103,77},{184,89,65},{156,74,52},{129,58,39},{102,41,23},{71,17,3},{28,0,0},{244,118,78},{212,103,67},{184,89,57},{155,73,45},{129,58,32},{102,41,16},{71,17,1},{27,0,0}, -{244,118,67},{212,103,58},{184,89,47},{155,73,36},{129,58,22},{102,41,9},{71,17,1},{27,0,0},{243,117,55},{212,103,47},{183,88,38},{155,73,27},{129,58,12},{102,41,3},{71,18,0},{27,0,0},{243,117,44},{212,103,37},{183,88,29},{155,73,17},{129,58,6},{102,41,1},{71,18,0},{27,0,0},{244,117,33},{213,103,25},{184,88,19},{156,73,7},{129,57,0},{102,42,0},{70,18,0},{27,0,0}, -{241,106,169},{210,92,148},{182,78,129},{155,64,109},{128,48,89},{103,32,69},{72,5,42},{31,0,0},{241,106,159},{210,92,139},{182,78,122},{155,64,103},{129,49,84},{103,32,64},{72,5,38},{30,0,0},{241,106,150},{210,92,131},{182,78,114},{155,64,97},{129,49,78},{103,32,59},{72,5,35},{29,0,0},{241,106,142},{211,92,125},{183,78,108},{155,64,91},{128,49,74},{103,33,55},{72,5,31},{29,0,0}, -{241,106,134},{211,92,118},{183,78,103},{155,64,86},{128,49,69},{103,33,51},{72,5,27},{29,0,0},{241,105,126},{211,92,111},{182,79,97},{155,64,81},{128,48,64},{102,33,47},{71,6,23},{28,0,0},{241,105,118},{211,92,103},{182,79,90},{155,64,76},{128,48,59},{102,33,42},{71,6,18},{27,0,0},{241,105,111},{211,91,96},{182,78,83},{154,64,69},{128,49,54},{101,33,37},{70,6,13},{27,0,0}, -{241,105,103},{211,91,89},{182,78,77},{155,64,63},{128,49,48},{101,33,32},{70,7,8},{27,0,0},{242,104,94},{211,91,82},{183,79,70},{156,64,57},{128,49,43},{102,33,27},{71,8,3},{26,0,0},{242,104,85},{211,91,74},{183,79,63},{155,64,50},{128,49,37},{102,33,21},{71,8,2},{26,0,0},{242,105,75},{210,91,65},{183,79,55},{154,64,43},{128,49,30},{101,34,14},{70,8,1},{26,0,0}, -{242,104,65},{210,91,56},{183,79,46},{154,64,34},{128,49,20},{101,34,7},{70,8,1},{26,0,0},{242,103,53},{211,91,45},{182,78,37},{154,64,26},{128,49,10},{102,34,2},{70,9,0},{26,0,0},{242,103,43},{211,91,36},{182,78,28},{154,64,17},{128,49,5},{102,34,1},{70,9,0},{26,0,0},{243,103,33},{211,91,26},{183,78,19},{155,64,8},{128,50,0},{101,35,0},{70,10,0},{26,0,0}, -{239,89,161},{209,76,141},{181,64,123},{155,51,104},{128,36,85},{103,20,65},{72,2,39},{28,0,0},{240,88,152},{210,77,134},{182,64,117},{155,51,98},{129,37,80},{103,20,61},{72,2,35},{27,0,0},{240,88,143},{210,77,126},{182,64,109},{155,51,92},{129,37,74},{103,20,56},{72,2,32},{27,0,0},{241,88,136},{210,77,120},{182,64,103},{155,51,87},{128,37,70},{102,21,52},{72,2,28},{27,0,0}, -{241,89,129},{210,77,113},{182,64,98},{155,51,83},{128,37,66},{102,21,48},{72,2,24},{27,0,0},{241,89,121},{210,77,106},{182,65,92},{154,52,77},{128,37,61},{102,21,44},{71,2,20},{26,0,0},{241,89,114},{210,77,99},{182,65,86},{154,52,72},{128,38,56},{102,21,39},{71,2,15},{26,0,0},{240,89,107},{210,77,92},{182,65,80},{154,52,66},{128,38,51},{101,22,34},{70,2,10},{25,0,0}, -{240,89,99},{210,77,86},{182,65,74},{155,53,60},{128,39,45},{101,22,29},{70,3,6},{25,0,0},{241,89,91},{210,77,79},{182,66,67},{155,53,54},{128,39,40},{102,22,24},{71,4,3},{25,0,0},{241,89,82},{210,77,71},{182,66,60},{154,53,47},{128,39,34},{102,22,18},{71,4,2},{25,0,0},{241,89,72},{210,77,62},{182,66,53},{154,53,41},{128,39,27},{101,23,11},{70,4,1},{25,0,0}, -{241,89,62},{210,77,54},{182,66,44},{154,53,33},{128,39,19},{101,23,6},{70,4,1},{25,0,0},{241,88,52},{211,77,44},{182,65,36},{154,53,25},{127,39,10},{102,24,2},{70,5,0},{25,0,0},{241,88,43},{211,77,36},{182,65,28},{154,54,17},{127,39,5},{102,24,1},{70,5,0},{25,0,0},{242,88,33},{210,78,27},{182,66,20},{154,54,9},{127,41,0},{101,25,0},{70,5,0},{25,0,0}, -{237,71,154},{208,59,134},{180,50,117},{154,38,100},{128,22,81},{102,6,61},{72,0,36},{25,0,0},{238,70,145},{209,60,128},{181,49,111},{154,38,94},{128,23,76},{102,7,57},{72,0,32},{25,0,0},{239,69,137},{209,61,121},{181,49,105},{154,38,88},{128,24,70},{102,7,53},{72,0,29},{25,0,0},{240,70,130},{208,61,115},{181,50,99},{154,39,83},{128,25,66},{101,7,49},{71,0,25},{25,0,0}, -{240,71,123},{208,61,108},{181,50,94},{154,39,79},{128,25,62},{101,7,45},{71,0,21},{25,0,0},{240,72,117},{209,62,102},{181,51,88},{153,39,73},{127,25,57},{101,8,40},{71,0,17},{24,0,0},{240,72,110},{209,62,95},{181,51,82},{153,39,68},{127,26,52},{101,9,35},{71,0,12},{24,0,0},{239,72,103},{209,63,88},{181,52,76},{154,40,62},{127,26,47},{101,10,31},{70,0,8},{23,0,0}, -{239,72,95},{209,63,82},{181,52,70},{154,41,56},{127,27,42},{101,10,26},{70,0,5},{23,0,0},{239,73,88},{209,62,75},{180,52,64},{153,41,51},{127,28,37},{102,10,21},{71,0,3},{23,0,0},{239,73,79},{209,62,68},{180,52,57},{153,41,45},{127,28,31},{102,10,15},{71,0,1},{23,0,0},{239,72,69},{209,63,60},{181,53,50},{154,41,39},{127,28,25},{101,11,8},{70,1,0},{23,0,0}, -{239,72,60},{209,63,52},{181,53,42},{154,41,31},{127,28,17},{101,11,4},{70,1,0},{23,0,0},{239,73,51},{210,63,43},{181,53,35},{154,41,24},{126,28,9},{101,12,1},{69,1,0},{23,0,0},{239,73,43},{210,63,35},{181,53,28},{154,42,17},{126,29,5},{101,13,1},{69,1,0},{23,0,0},{240,73,34},{209,64,28},{181,54,21},{153,43,10},{126,31,1},{101,14,0},{70,1,0},{23,0,0}, -{237,37,147},{207,30,128},{180,26,112},{154,19,95},{128,11,77},{102,2,58},{72,0,33},{23,0,0},{238,36,139},{208,31,122},{181,25,106},{154,19,89},{128,11,72},{102,3,54},{72,0,29},{23,0,0},{238,36,131},{208,31,115},{181,25,99},{154,19,83},{128,12,67},{102,3,50},{72,0,26},{23,0,0},{239,37,124},{207,32,109},{181,26,94},{154,20,79},{128,12,63},{101,3,46},{71,0,22},{23,0,0}, -{239,38,117},{207,32,103},{181,26,90},{154,20,75},{128,12,59},{101,3,42},{71,0,18},{23,0,0},{238,42,111},{208,34,97},{180,26,84},{153,20,70},{127,13,54},{101,3,37},{71,0,14},{22,0,0},{238,45,104},{208,35,92},{180,27,78},{153,20,64},{127,13,49},{101,4,33},{71,0,10},{22,0,0},{238,44,97},{208,37,85},{180,28,73},{153,20,59},{127,13,44},{101,4,29},{70,0,7},{22,0,0}, -{239,45,91},{208,38,79},{180,29,67},{153,21,54},{127,14,40},{101,4,24},{70,0,4},{22,0,0},{238,47,84},{208,37,72},{180,28,61},{153,21,49},{127,14,35},{101,5,19},{71,0,3},{22,0,0},{238,48,76},{208,38,66},{180,29,55},{153,22,43},{127,14,29},{101,5,13},{71,0,1},{22,0,0},{238,49,68},{208,40,59},{180,31,48},{153,22,37},{127,14,23},{101,5,7},{70,1,0},{22,0,0}, -{238,49,59},{208,41,51},{180,32,41},{153,23,30},{127,14,16},{101,5,3},{70,1,0},{22,0,0},{239,50,50},{209,42,43},{180,33,34},{154,24,23},{126,14,8},{101,6,1},{69,1,0},{22,0,0},{239,50,43},{209,42,35},{180,33,28},{154,24,17},{126,15,5},{101,6,1},{69,1,0},{22,0,0},{239,51,34},{208,42,28},{181,34,21},{153,25,10},{126,16,1},{101,7,0},{70,1,0},{23,0,0}, -{237,0,140},{206,0,122},{179,0,108},{153,0,91},{128,0,73},{102,0,54},{71,0,30},{20,0,0},{237,0,133},{207,0,116},{180,0,101},{153,0,85},{127,0,68},{102,0,50},{71,0,26},{20,0,0},{237,0,125},{207,0,110},{180,0,94},{153,0,79},{127,0,63},{102,0,46},{71,0,23},{20,0,0},{237,1,119},{206,1,104},{180,0,90},{153,0,75},{127,0,59},{102,0,42},{71,0,19},{20,0,0}, -{237,3,112},{206,2,99},{180,0,86},{153,0,71},{127,0,55},{102,0,38},{71,0,15},{20,0,0},{236,11,106},{206,4,93},{179,0,80},{152,0,66},{126,0,51},{101,0,34},{70,0,11},{20,0,0},{236,16,99},{206,7,88},{179,1,75},{152,0,61},{126,0,46},{101,0,30},{70,0,8},{20,0,0},{237,15,92},{206,10,81},{179,3,69},{152,0,56},{126,0,41},{100,0,26},{69,0,5},{20,0,0}, -{238,16,86},{206,12,75},{179,4,63},{152,0,51},{126,0,37},{100,0,22},{69,0,3},{20,0,0},{237,19,80},{207,11,69},{180,3,58},{153,0,46},{126,0,33},{100,0,17},{70,0,2},{20,0,0},{237,22,73},{207,13,63},{180,5,52},{153,1,41},{126,0,27},{100,0,11},{70,0,1},{20,0,0},{237,24,66},{207,16,57},{179,8,46},{152,2,35},{126,0,21},{100,0,5},{69,0,0},{20,0,0}, -{237,25,58},{207,19,50},{179,11,40},{152,3,29},{126,0,14},{100,0,2},{69,0,0},{20,0,0},{238,25,49},{207,21,43},{179,13,33},{153,5,22},{127,0,7},{100,0,0},{69,0,0},{20,0,0},{238,26,42},{207,21,36},{179,13,27},{153,5,16},{127,0,4},{100,0,0},{69,0,0},{21,0,0},{238,28,35},{207,20,29},{180,13,22},{152,5,10},{126,0,1},{100,0,0},{69,0,0},{22,0,0}, -{215,240,252},{188,210,222},{162,182,193},{136,154,165},{113,128,136},{88,101,108},{59,69,76},{22,27,32},{217,238,238},{189,209,210},{163,181,183},{137,154,156},{114,127,129},{89,100,102},{59,69,71},{20,26,28},{218,237,224},{189,209,198},{163,181,173},{138,154,147},{114,127,121},{89,100,96},{59,69,65},{19,26,24},{219,236,212},{191,208,188},{164,180,164},{139,153,139},{114,126,114},{89,99,90},{59,68,61},{19,26,20}, -{219,236,200},{192,207,177},{165,180,154},{139,153,131},{114,126,107},{89,99,85},{59,68,56},{19,26,17},{221,235,187},{193,206,165},{166,179,144},{140,152,122},{115,125,100},{90,98,79},{59,67,51},{18,25,11},{222,234,174},{194,206,154},{167,179,134},{141,151,114},{115,125,93},{90,98,73},{59,67,46},{17,25,6},{223,233,160},{195,205,143},{168,178,124},{141,150,105},{116,124,86},{90,97,66},{60,66,41},{16,25,2}, -{224,232,147},{195,204,131},{168,177,114},{141,150,96},{116,124,78},{90,97,60},{60,66,35},{15,25,0},{225,231,135},{196,203,119},{168,176,104},{142,149,87},{116,123,71},{90,96,53},{59,66,30},{14,24,0},{225,231,120},{196,202,106},{168,176,92},{142,149,77},{116,123,62},{90,96,46},{59,66,23},{13,24,0},{226,230,105},{196,201,93},{169,175,81},{142,148,67},{116,122,53},{91,96,38},{60,65,15},{12,24,0}, -{226,230,87},{197,201,77},{169,175,67},{142,148,55},{116,122,42},{91,96,27},{60,65,8},{11,24,0},{226,229,68},{198,200,60},{170,174,53},{143,147,43},{117,121,31},{91,95,16},{60,65,2},{10,24,0},{227,229,46},{198,200,41},{170,174,35},{143,147,26},{117,121,17},{91,95,8},{60,65,1},{10,24,0},{228,229,22},{198,200,21},{170,173,17},{143,146,9},{116,120,2},{90,95,0},{59,64,0},{9,23,0}, -{214,226,243},{187,198,215},{162,172,187},{137,146,159},{113,121,132},{88,95,104},{60,64,73},{23,22,29},{216,225,230},{189,197,203},{163,171,177},{138,145,151},{114,120,125},{89,94,98},{60,64,68},{21,21,25},{217,225,217},{190,197,192},{164,171,168},{139,145,142},{114,120,117},{89,94,92},{60,64,62},{20,21,21},{218,224,205},{191,196,182},{165,170,159},{140,144,135},{115,119,110},{90,93,87},{60,63,58},{20,21,17}, -{218,223,193},{191,195,171},{165,170,149},{140,144,127},{115,119,103},{90,93,82},{60,63,53},{20,21,13},{220,222,181},{193,194,160},{165,169,140},{140,143,118},{114,118,96},{89,92,76},{60,63,49},{19,21,7},{221,222,168},{194,194,149},{166,169,130},{140,143,110},{114,118,90},{89,92,70},{60,63,44},{18,21,3},{221,221,155},{194,193,138},{167,168,120},{141,142,102},{115,117,83},{89,91,63},{60,62,39},{17,21,1}, -{222,220,143},{194,193,127},{167,167,110},{141,141,93},{115,117,75},{89,91,57},{60,62,33},{16,21,0},{223,219,131},{195,192,115},{167,166,101},{141,140,84},{115,116,68},{90,91,50},{60,61,27},{15,20,0},{224,218,117},{196,191,103},{167,166,89},{141,140,74},{115,116,59},{90,91,43},{60,61,21},{14,20,0},{224,218,103},{196,190,90},{168,165,78},{141,140,64},{115,115,51},{90,90,35},{60,61,13},{13,20,0}, -{224,217,86},{196,190,76},{168,165,65},{141,140,53},{115,115,40},{90,90,25},{60,61,7},{12,20,0},{225,216,68},{197,189,60},{169,164,52},{142,139,41},{116,114,29},{91,90,14},{60,61,2},{10,20,0},{225,216,48},{197,189,42},{169,164,35},{142,139,26},{116,114,16},{91,90,6},{60,61,1},{10,20,0},{226,216,27},{197,189,24},{169,164,19},{142,139,11},{116,114,3},{90,89,0},{59,60,0},{10,19,0}, -{214,213,235},{187,187,207},{162,163,180},{137,138,153},{113,113,127},{88,88,101},{61,59,70},{23,17,26},{216,212,222},{189,186,196},{163,162,171},{139,137,145},{114,112,121},{89,87,95},{61,58,65},{22,16,22},{217,211,209},{190,186,185},{164,162,162},{139,137,137},{114,112,114},{89,87,89},{61,58,60},{21,16,18},{218,211,197},{191,185,175},{165,161,153},{140,136,130},{115,112,107},{90,87,84},{61,58,56},{20,16,14}, -{218,211,186},{191,184,164},{165,161,144},{140,136,122},{115,112,100},{90,87,79},{61,58,51},{20,16,10},{219,210,174},{192,183,154},{165,160,135},{140,135,114},{114,111,93},{89,86,73},{61,57,47},{19,16,4},{220,209,162},{193,183,144},{165,160,126},{140,135,106},{114,110,87},{89,86,67},{61,57,42},{19,16,1},{220,208,151},{193,182,133},{166,159,117},{140,134,99},{114,109,80},{89,85,61},{60,57,37},{18,16,0}, -{221,207,139},{193,182,123},{166,158,107},{140,133,90},{114,109,73},{89,85,55},{60,57,31},{17,16,0},{222,206,127},{194,181,112},{167,157,98},{141,132,81},{115,108,65},{90,85,48},{60,57,25},{16,15,0},{223,206,114},{195,181,100},{167,157,87},{141,132,72},{115,108,57},{90,85,41},{60,57,19},{15,15,0},{223,206,101},{196,180,88},{167,156,77},{141,132,62},{115,108,49},{90,84,33},{60,56,12},{14,15,0}, -{223,205,85},{196,180,75},{167,156,64},{141,132,52},{115,108,39},{90,84,23},{60,56,6},{13,15,0},{224,204,68},{196,179,60},{168,155,51},{142,131,40},{116,107,28},{91,84,12},{60,56,2},{11,15,0},{224,204,49},{196,179,43},{168,155,35},{142,131,26},{116,107,16},{91,84,5},{60,56,1},{11,15,0},{225,204,31},{196,178,26},{168,155,20},{142,131,12},{116,107,3},{90,83,0},{59,56,0},{11,15,0}, -{213,201,227},{187,177,200},{162,153,175},{138,130,149},{114,106,123},{89,83,97},{61,55,67},{24,11,24},{215,200,215},{188,176,190},{163,153,165},{138,129,141},{114,106,117},{89,83,92},{61,54,62},{23,11,20},{216,199,202},{189,176,179},{163,153,156},{138,129,133},{114,106,110},{89,83,86},{61,54,57},{23,11,15},{217,199,191},{190,175,169},{164,152,148},{139,129,126},{114,105,103},{89,83,81},{61,54,53},{22,11,10}, -{217,199,181},{190,174,160},{164,152,140},{139,129,118},{114,105,97},{89,83,76},{61,54,49},{22,11,6},{218,198,170},{191,173,150},{164,151,131},{140,128,110},{115,105,91},{90,82,70},{60,53,45},{21,11,2},{219,197,158},{192,173,140},{164,151,122},{140,128,102},{115,104,84},{90,82,65},{60,53,40},{20,11,0},{219,196,147},{192,172,129},{165,150,113},{140,127,95},{115,103,77},{90,81,59},{61,53,35},{19,11,0}, -{220,195,135},{192,172,119},{165,149,103},{140,126,87},{115,103,71},{90,81,53},{61,53,29},{18,11,0},{221,194,124},{193,171,109},{166,148,94},{141,125,79},{115,102,63},{90,81,46},{61,53,23},{17,11,0},{221,194,112},{193,171,98},{166,148,85},{141,125,70},{115,102,56},{90,81,39},{61,53,17},{15,11,0},{222,194,98},{194,170,86},{166,147,75},{140,125,60},{115,102,47},{90,80,32},{60,52,10},{14,11,0}, -{222,194,83},{194,170,73},{166,147,62},{140,125,50},{115,102,37},{90,80,21},{60,52,5},{14,11,0},{223,193,67},{195,169,59},{167,146,50},{141,124,39},{115,101,26},{90,80,10},{60,52,1},{13,11,0},{223,193,50},{195,169,44},{167,146,36},{141,124,26},{115,101,15},{90,80,4},{60,52,0},{12,11,0},{224,192,35},{195,169,28},{167,146,22},{141,124,13},{115,101,4},{90,79,0},{60,52,0},{12,11,0}, -{213,189,219},{187,166,193},{162,144,169},{138,122,144},{114,99,119},{89,78,94},{61,51,64},{24,6,21},{214,188,207},{188,165,183},{163,144,160},{138,121,137},{114,99,113},{89,78,89},{61,50,59},{24,6,17},{215,187,195},{189,165,173},{163,144,151},{138,121,129},{114,99,106},{89,78,83},{61,50,54},{24,6,12},{216,187,185},{190,164,164},{164,143,143},{139,121,122},{114,98,100},{89,77,78},{61,50,50},{23,6,7}, -{217,187,175},{190,164,155},{164,143,135},{139,121,114},{114,98,94},{89,77,73},{61,50,46},{22,6,3},{218,186,165},{191,163,145},{164,142,126},{140,120,107},{115,98,88},{90,77,67},{60,49,42},{21,6,1},{219,185,154},{191,163,135},{164,142,118},{140,120,99},{115,98,81},{90,77,62},{60,49,37},{21,6,0},{219,184,143},{191,162,125},{165,141,109},{140,119,92},{115,97,74},{90,76,56},{61,49,32},{20,6,0}, -{219,184,132},{191,162,115},{165,141,100},{140,119,84},{115,97,68},{90,76,50},{61,49,26},{18,6,0},{220,183,121},{192,161,106},{166,140,91},{141,118,76},{115,96,61},{90,76,44},{61,49,21},{17,6,0},{220,183,109},{192,161,95},{166,140,82},{141,118,68},{115,96,54},{90,76,37},{61,49,14},{15,6,0},{221,183,95},{193,160,84},{166,139,72},{140,117,59},{115,96,45},{90,75,30},{60,48,8},{14,7,0}, -{222,183,82},{193,160,71},{166,139,61},{140,117,49},{115,96,35},{90,75,20},{60,48,4},{14,7,0},{223,182,67},{194,159,59},{167,138,49},{141,116,38},{115,95,25},{90,75,9},{60,48,0},{14,7,0},{223,182,51},{194,159,44},{167,138,37},{141,116,26},{115,95,15},{90,75,4},{60,48,0},{13,7,0},{223,181,36},{194,159,30},{167,137,24},{141,116,14},{115,95,4},{90,75,0},{60,48,0},{12,6,0}, -{212,176,210},{186,154,186},{162,134,162},{138,113,139},{114,92,115},{90,72,90},{62,45,60},{25,3,17},{213,175,200},{187,154,176},{163,134,154},{139,113,132},{114,92,109},{89,72,85},{61,45,56},{24,2,13},{214,175,189},{188,154,166},{163,134,145},{139,113,124},{114,92,102},{89,72,79},{61,45,51},{24,2,8},{215,175,179},{189,153,158},{163,133,138},{139,112,117},{114,91,96},{90,71,75},{61,44,47},{23,2,4}, -{216,175,169},{189,153,149},{164,133,131},{139,112,110},{114,91,90},{90,71,70},{61,44,43},{23,2,1},{217,174,159},{190,153,140},{164,133,122},{139,112,103},{114,91,84},{89,71,64},{61,44,39},{22,2,0},{217,173,148},{190,153,131},{164,133,114},{139,112,96},{114,91,78},{89,71,59},{61,44,35},{21,2,0},{218,172,137},{190,152,121},{164,132,105},{140,111,89},{114,90,71},{90,70,54},{61,44,30},{20,2,0}, -{219,172,127},{190,152,111},{165,132,97},{140,111,82},{114,90,65},{90,70,48},{61,44,24},{18,2,0},{220,171,117},{191,151,102},{166,131,89},{140,110,74},{114,90,59},{90,70,42},{60,44,19},{17,2,0},{220,171,105},{191,151,93},{166,131,80},{140,110,66},{114,90,52},{90,70,35},{60,44,12},{16,2,0},{220,171,93},{192,150,82},{165,130,70},{140,109,57},{114,89,43},{89,69,28},{60,44,6},{15,3,0}, -{220,171,80},{192,150,69},{165,130,59},{140,109,47},{114,89,34},{89,69,18},{60,44,3},{15,3,0},{221,170,66},{193,149,57},{166,129,47},{140,109,36},{114,89,24},{89,69,8},{60,44,0},{15,3,0},{221,170,51},{193,149,44},{166,129,36},{140,109,26},{114,89,14},{89,69,3},{60,44,0},{14,3,0},{221,169,37},{193,149,31},{166,128,24},{140,108,14},{114,89,4},{89,69,0},{59,43,0},{13,2,0}, -{212,164,202},{186,143,179},{162,124,156},{138,105,134},{114,86,110},{90,66,86},{62,40,57},{25,0,14},{213,163,192},{187,143,169},{163,124,148},{139,105,127},{114,85,104},{90,66,81},{61,40,53},{24,0,9},{214,163,182},{187,143,160},{163,124,140},{139,105,119},{114,85,98},{90,66,76},{61,40,48},{24,0,5},{215,162,173},{188,142,152},{163,124,133},{139,104,112},{114,85,92},{90,65,72},{61,39,44},{23,0,2}, -{216,162,163},{188,142,144},{164,124,126},{139,104,106},{114,85,87},{90,65,67},{61,39,40},{23,0,0},{216,162,153},{189,142,135},{164,123,117},{139,104,100},{114,84,81},{89,65,61},{61,39,36},{22,0,0},{216,161,142},{189,142,126},{164,123,109},{139,104,93},{114,84,75},{89,65,56},{61,39,32},{21,0,0},{217,161,132},{190,141,117},{164,122,102},{140,103,86},{114,84,68},{90,64,51},{61,39,27},{20,0,0}, -{218,160,122},{190,141,108},{165,122,94},{140,103,79},{114,84,62},{90,64,45},{61,39,21},{18,0,0},{219,159,113},{191,140,99},{166,122,86},{140,102,72},{114,83,56},{90,64,39},{60,39,16},{17,0,0},{219,159,102},{191,140,90},{166,122,77},{140,102,64},{114,83,49},{90,64,32},{60,39,10},{17,0,0},{219,159,91},{191,139,80},{165,121,67},{140,101,55},{114,83,41},{89,63,25},{60,39,5},{16,0,0}, -{219,159,78},{191,139,67},{165,121,57},{140,101,45},{114,83,32},{89,63,16},{60,39,2},{16,0,0},{220,159,66},{192,138,56},{166,120,46},{140,101,35},{114,83,23},{89,63,7},{60,39,0},{15,0,0},{220,159,51},{192,138,44},{166,120,36},{140,101,26},{114,83,14},{89,63,3},{60,39,0},{14,0,0},{220,158,37},{192,138,32},{165,120,24},{140,100,14},{114,83,4},{89,63,0},{59,38,0},{13,0,0}, -{212,152,195},{185,132,173},{161,115,150},{137,98,128},{113,79,106},{90,59,83},{62,34,54},{23,0,10},{213,151,185},{186,132,163},{162,115,143},{138,97,122},{114,78,100},{90,59,78},{62,34,50},{23,0,6},{214,151,175},{186,132,154},{162,115,135},{138,97,114},{114,78,94},{90,59,73},{62,34,46},{23,0,2},{214,150,166},{187,131,147},{163,115,128},{138,97,108},{114,78,89},{90,59,69},{61,34,42},{22,0,1}, -{215,150,158},{187,131,139},{163,115,121},{138,97,102},{114,78,84},{90,59,64},{61,34,38},{21,0,0},{215,150,148},{188,131,130},{163,114,113},{138,96,96},{114,77,78},{90,59,58},{61,34,34},{20,0,0},{215,150,138},{188,131,122},{163,114,105},{138,96,89},{114,77,72},{90,59,53},{61,34,29},{20,0,0},{216,149,128},{189,130,113},{164,113,98},{139,96,82},{114,77,65},{90,58,48},{61,34,24},{19,0,0}, -{217,149,118},{189,130,104},{164,113,90},{139,96,76},{114,77,59},{90,58,42},{61,34,19},{18,0,0},{218,148,109},{190,130,96},{165,113,83},{139,95,69},{113,76,53},{90,58,37},{61,34,13},{17,0,0},{218,148,99},{190,130,87},{165,113,74},{139,95,61},{113,76,47},{90,58,31},{61,34,8},{17,0,0},{218,148,88},{190,129,77},{164,112,65},{139,94,53},{113,76,40},{89,58,24},{60,34,4},{16,0,0}, -{218,148,76},{190,129,66},{164,112,55},{139,94,44},{113,76,31},{89,58,15},{60,34,1},{15,0,0},{219,147,64},{191,128,55},{165,111,45},{139,94,34},{114,76,22},{90,58,6},{60,34,0},{14,0,0},{219,147,52},{191,128,44},{165,111,35},{139,94,25},{114,76,13},{90,58,2},{60,34,0},{14,0,0},{219,147,38},{191,128,33},{165,111,25},{139,93,13},{113,76,3},{89,58,0},{59,34,0},{14,0,0}, -{212,140,189},{185,122,167},{161,106,144},{137,90,123},{113,72,102},{90,53,79},{62,27,52},{22,0,6},{213,139,179},{186,122,157},{162,105,137},{138,89,117},{114,71,96},{90,53,74},{62,28,48},{22,0,3},{214,139,169},{186,122,148},{162,105,130},{138,89,110},{114,71,90},{90,53,69},{62,28,44},{22,0,0},{214,138,160},{187,121,141},{163,105,123},{138,89,104},{114,71,85},{90,53,65},{61,28,40},{21,0,0}, -{214,138,152},{187,121,133},{163,105,116},{138,89,98},{114,71,80},{90,53,61},{61,28,36},{20,0,0},{215,138,143},{187,121,126},{163,105,109},{138,88,92},{114,71,74},{90,53,56},{61,29,32},{19,0,0},{215,138,134},{187,121,118},{163,105,101},{138,88,85},{114,71,68},{90,53,51},{61,29,27},{19,0,0},{215,137,124},{188,120,109},{163,104,94},{138,88,79},{114,71,63},{90,52,46},{61,28,22},{18,0,0}, -{215,137,114},{188,120,100},{163,104,87},{138,88,73},{114,71,57},{90,52,40},{61,28,17},{17,0,0},{216,136,105},{189,120,93},{163,104,80},{138,87,66},{113,70,51},{90,52,35},{61,28,11},{16,0,0},{216,136,96},{189,120,84},{163,104,72},{138,87,58},{113,70,45},{90,52,29},{61,28,6},{16,0,0},{217,136,86},{188,119,75},{164,103,63},{138,87,51},{113,70,38},{89,52,22},{60,28,3},{15,0,0}, -{217,136,74},{188,119,64},{164,103,53},{138,87,42},{113,70,29},{89,52,13},{60,28,1},{14,0,0},{217,135,62},{189,118,53},{164,103,43},{139,87,32},{114,70,20},{90,52,5},{60,28,0},{13,0,0},{217,135,52},{189,118,44},{164,103,35},{139,87,24},{114,70,11},{90,52,2},{60,28,0},{13,0,0},{218,135,40},{189,118,34},{164,103,25},{139,86,14},{113,70,3},{89,52,0},{59,29,0},{13,0,0}, -{211,127,182},{185,111,160},{161,97,139},{136,81,118},{113,64,98},{90,46,76},{61,20,49},{21,0,3},{212,127,172},{186,111,151},{162,96,132},{137,81,112},{113,64,92},{90,46,71},{62,21,45},{20,0,2},{213,127,162},{186,111,143},{162,96,125},{137,81,106},{113,64,86},{90,46,66},{62,21,41},{19,0,0},{214,126,153},{186,111,136},{162,96,119},{138,81,100},{113,64,81},{90,46,62},{61,21,37},{18,0,0}, -{214,126,145},{186,111,128},{162,96,112},{138,81,94},{113,64,76},{90,46,58},{61,21,33},{18,0,0},{214,126,138},{186,111,121},{163,96,105},{138,81,88},{113,64,70},{90,46,53},{61,22,29},{17,0,0},{214,126,130},{186,111,113},{163,96,98},{138,81,82},{113,64,65},{90,46,48},{61,22,25},{16,0,0},{214,125,120},{187,110,105},{163,95,91},{138,80,76},{113,64,60},{89,46,43},{61,22,20},{16,0,0}, -{214,125,111},{187,110,97},{163,95,85},{138,80,70},{113,64,54},{89,46,37},{61,22,15},{15,0,0},{215,125,102},{188,110,90},{162,95,78},{137,80,63},{113,63,48},{89,46,32},{61,23,9},{14,0,0},{215,125,93},{188,110,81},{162,95,70},{137,80,56},{113,63,42},{89,46,26},{61,23,5},{13,0,0},{216,125,83},{187,109,72},{163,94,61},{138,80,49},{113,63,36},{89,46,20},{60,22,3},{12,0,0}, -{216,125,73},{187,109,63},{163,94,52},{138,80,41},{113,63,27},{89,46,12},{60,22,1},{12,0,0},{216,124,61},{188,109,52},{163,95,42},{138,79,31},{113,63,19},{89,46,4},{59,23,0},{12,0,0},{216,124,51},{188,109,43},{163,95,34},{138,79,23},{113,63,10},{89,46,2},{59,23,0},{12,0,0},{217,124,41},{188,109,33},{163,94,25},{138,79,15},{113,63,3},{89,45,0},{59,23,0},{12,0,0}, -{211,114,174},{184,100,153},{161,87,134},{136,72,113},{113,55,93},{90,39,73},{61,13,46},{19,0,1},{212,114,165},{185,100,145},{162,87,127},{137,72,107},{113,56,88},{90,39,68},{62,13,42},{17,0,1},{212,114,156},{186,100,137},{162,87,120},{137,72,101},{113,56,83},{90,39,63},{62,13,38},{16,0,0},{213,114,148},{186,100,131},{162,87,114},{138,72,96},{113,56,78},{90,39,59},{61,14,34},{15,0,0}, -{213,114,140},{186,100,123},{162,87,107},{138,72,91},{113,56,73},{90,39,55},{61,14,30},{15,0,0},{213,114,133},{186,100,116},{163,86,101},{138,72,85},{113,56,67},{90,39,50},{61,14,26},{14,0,0},{213,114,125},{186,100,108},{163,86,95},{138,72,79},{113,56,62},{90,39,45},{61,14,22},{14,0,0},{214,114,116},{186,100,101},{163,86,88},{138,71,73},{113,56,57},{89,39,40},{61,14,17},{13,0,0}, -{214,114,107},{186,100,94},{163,86,82},{138,71,67},{113,56,51},{89,39,35},{61,14,12},{12,0,0},{214,114,99},{187,100,87},{162,86,75},{137,71,60},{113,56,46},{89,39,30},{61,15,7},{12,0,0},{214,114,90},{187,100,79},{162,86,67},{137,71,54},{113,56,40},{89,39,24},{61,16,4},{11,0,0},{215,114,80},{187,99,70},{163,85,59},{138,71,47},{113,56,34},{89,39,18},{60,15,2},{10,0,0}, -{215,114,71},{187,99,61},{163,85,50},{138,71,39},{113,56,25},{89,39,10},{60,15,1},{10,0,0},{215,113,60},{188,99,51},{163,86,41},{137,71,30},{113,55,17},{89,40,4},{59,16,0},{10,0,0},{215,113,51},{188,99,43},{163,86,33},{137,71,22},{113,55,9},{89,40,2},{59,16,0},{10,0,0},{215,113,41},{188,99,33},{163,85,25},{138,71,15},{113,55,3},{89,39,0},{59,16,0},{10,0,0}, -{210,102,167},{183,89,147},{161,76,128},{136,62,109},{112,46,89},{90,30,69},{62,5,43},{15,0,0},{211,101,158},{184,89,139},{162,76,121},{137,62,103},{113,47,84},{90,30,65},{62,5,39},{14,0,0},{211,101,150},{185,89,131},{162,76,114},{137,62,97},{113,47,79},{90,30,60},{62,5,36},{14,0,0},{212,102,142},{185,89,125},{162,77,109},{137,62,92},{112,47,75},{90,31,56},{61,5,32},{13,0,0}, -{212,102,135},{185,89,118},{162,77,103},{137,62,87},{112,47,70},{90,31,52},{61,5,28},{13,0,0},{212,102,127},{186,89,111},{162,76,97},{137,62,81},{112,47,65},{90,31,48},{61,5,24},{12,0,0},{212,102,119},{186,89,104},{162,76,91},{137,62,76},{112,47,60},{90,31,43},{61,5,20},{12,0,0},{213,102,111},{186,89,97},{162,76,84},{137,62,70},{112,48,54},{90,32,38},{61,5,15},{11,0,0}, -{213,102,103},{186,89,91},{162,76,78},{137,62,64},{112,48,49},{89,32,33},{61,5,10},{10,0,0},{213,101,95},{186,90,84},{162,76,71},{137,62,58},{112,48,44},{88,32,28},{60,6,5},{10,0,0},{213,101,87},{186,90,77},{162,76,64},{137,62,52},{112,48,38},{88,32,22},{60,7,3},{10,0,0},{214,102,78},{186,89,68},{162,75,57},{137,62,45},{112,48,32},{88,32,16},{59,8,1},{9,0,0}, -{214,102,69},{186,89,59},{162,75,48},{137,62,37},{112,48,23},{88,32,9},{59,8,1},{9,0,0},{214,101,58},{187,89,49},{162,76,39},{136,62,29},{112,48,15},{89,33,3},{59,8,0},{9,0,0},{214,101,50},{187,89,41},{162,76,32},{136,62,21},{112,48,8},{89,33,1},{59,8,0},{9,0,0},{214,101,41},{188,89,34},{162,75,25},{137,62,14},{112,48,3},{88,33,0},{59,9,0},{9,0,0}, -{209,86,160},{183,74,141},{161,63,123},{136,49,104},{112,34,85},{90,18,65},{62,2,40},{11,0,0},{210,86,152},{184,75,134},{162,63,116},{137,50,98},{113,35,80},{90,19,61},{62,2,36},{11,0,0},{211,86,144},{185,75,126},{162,63,109},{137,50,93},{113,36,75},{90,19,57},{62,2,33},{11,0,0},{212,87,137},{185,75,120},{161,64,104},{137,51,88},{112,36,71},{90,19,53},{61,2,29},{10,0,0}, -{212,87,130},{185,75,113},{161,64,99},{137,51,83},{112,36,67},{90,19,49},{61,2,25},{10,0,0},{212,87,122},{186,75,107},{162,63,93},{137,51,78},{112,37,62},{90,20,45},{61,2,21},{10,0,0},{212,87,114},{186,76,100},{162,63,87},{137,51,73},{112,37,57},{90,20,40},{61,2,17},{10,0,0},{212,87,107},{186,76,94},{162,64,81},{137,51,67},{112,38,51},{90,21,35},{61,2,12},{9,0,0}, -{212,87,100},{186,76,88},{162,64,75},{137,51,61},{112,38,46},{89,21,30},{61,2,8},{8,0,0},{212,87,92},{186,76,81},{161,64,68},{137,52,55},{112,38,41},{88,22,25},{60,3,4},{8,0,0},{212,87,84},{186,76,74},{161,64,61},{137,52,49},{112,38,35},{88,22,19},{60,3,3},{8,0,0},{213,88,75},{186,76,65},{162,64,54},{137,52,42},{112,38,29},{88,22,13},{59,4,1},{7,0,0}, -{213,88,67},{186,76,57},{162,64,46},{137,52,35},{112,38,22},{88,22,8},{59,4,1},{7,0,0},{213,87,57},{187,76,48},{162,65,38},{136,52,28},{112,39,14},{89,23,3},{59,4,0},{6,0,0},{213,87,50},{187,76,41},{162,65,32},{136,52,20},{112,39,8},{89,23,1},{59,4,0},{6,0,0},{213,87,41},{187,76,34},{162,64,25},{137,52,14},{112,39,3},{88,23,0},{59,5,0},{6,0,0}, -{208,69,153},{183,59,135},{160,49,118},{137,36,99},{113,22,81},{90,6,61},{61,0,36},{8,0,0},{209,70,146},{184,60,128},{161,50,112},{137,37,94},{112,23,76},{90,7,57},{61,0,33},{8,0,0},{210,70,138},{185,60,121},{161,50,105},{137,38,89},{112,24,71},{90,7,53},{61,0,30},{8,0,0},{211,71,131},{185,60,115},{160,50,100},{137,39,84},{113,24,67},{90,7,49},{61,0,26},{7,0,0}, -{211,71,124},{185,60,109},{160,50,95},{137,39,79},{113,24,63},{90,7,45},{61,0,22},{6,0,0},{212,72,117},{185,61,103},{161,51,89},{136,39,74},{112,25,58},{89,8,41},{60,0,18},{6,0,0},{212,72,110},{185,62,96},{161,51,83},{136,39,69},{112,25,53},{89,8,36},{60,0,14},{6,0,0},{211,72,103},{185,63,90},{161,52,77},{136,39,63},{112,26,48},{89,9,32},{60,0,9},{6,0,0}, -{211,72,96},{185,63,84},{161,52,71},{136,39,57},{112,26,43},{89,9,28},{60,0,6},{6,0,0},{211,73,89},{185,62,77},{160,52,64},{136,40,52},{112,27,38},{88,10,23},{59,1,3},{6,0,0},{211,73,81},{185,62,70},{160,52,58},{136,40,46},{112,27,32},{88,10,17},{59,1,2},{6,0,0},{212,73,73},{186,63,63},{161,52,52},{136,41,40},{112,28,26},{88,11,11},{59,1,1},{6,0,0}, -{212,73,65},{186,63,55},{161,52,44},{136,41,34},{112,28,20},{88,12,6},{59,1,1},{5,0,0},{212,73,56},{186,63,47},{161,53,37},{136,41,27},{112,29,13},{88,13,2},{58,1,0},{4,0,0},{212,73,49},{186,63,40},{161,53,31},{136,41,19},{112,29,8},{88,13,1},{58,1,0},{4,0,0},{212,73,42},{186,64,34},{161,52,25},{136,42,13},{112,29,3},{88,13,0},{58,1,0},{4,0,0}, -{208,43,146},{183,32,129},{160,25,112},{137,18,94},{113,11,77},{90,2,59},{61,0,34},{6,0,0},{209,45,139},{184,34,122},{161,26,106},{137,19,89},{112,11,72},{90,3,55},{61,0,31},{6,0,0},{210,46,131},{185,35,115},{161,26,100},{137,19,84},{112,12,68},{90,3,51},{61,0,28},{6,0,0},{210,47,125},{185,37,110},{160,26,95},{136,20,80},{113,12,64},{90,3,47},{61,0,24},{5,0,0}, -{210,48,118},{185,38,104},{160,27,90},{136,20,76},{113,12,60},{90,3,43},{61,0,20},{5,0,0},{211,49,112},{185,40,98},{161,29,85},{136,20,71},{112,13,55},{89,3,39},{60,0,16},{5,0,0},{211,50,105},{185,41,92},{161,30,80},{136,20,66},{112,13,50},{89,3,34},{60,0,12},{5,0,0},{211,50,99},{184,42,87},{161,31,74},{136,21,60},{112,13,46},{89,4,30},{60,0,8},{5,0,0}, -{211,51,93},{184,42,81},{161,32,68},{136,21,55},{112,13,41},{89,4,26},{60,0,6},{5,0,0},{211,52,86},{185,42,74},{160,33,62},{136,22,50},{112,14,36},{88,5,21},{59,1,3},{5,0,0},{211,52,79},{185,43,67},{160,34,56},{136,23,44},{112,14,31},{88,5,15},{59,1,2},{5,0,0},{212,53,71},{185,44,61},{161,35,50},{136,24,38},{112,14,25},{88,5,9},{59,1,1},{5,0,0}, -{212,53,63},{185,44,53},{161,35,43},{136,24,32},{112,14,19},{88,6,5},{59,1,1},{4,0,0},{212,53,55},{185,45,46},{161,36,37},{136,25,26},{111,15,12},{88,6,2},{58,1,0},{4,0,0},{212,53,49},{185,45,39},{161,36,30},{136,25,19},{111,15,7},{88,6,1},{58,1,0},{4,0,0},{212,53,42},{186,45,33},{161,37,25},{136,26,13},{112,15,3},{88,6,0},{58,1,0},{4,0,0}, -{207,15,140},{184,3,123},{159,0,106},{136,0,90},{112,0,73},{90,0,56},{61,0,31},{3,0,0},{208,17,133},{185,5,117},{160,1,101},{136,0,85},{112,0,69},{89,0,52},{61,0,28},{3,0,0},{209,19,125},{185,7,110},{160,1,95},{136,0,80},{112,0,64},{89,0,48},{61,0,25},{3,0,0},{209,21,119},{185,11,105},{160,2,91},{135,0,76},{112,0,60},{89,0,44},{60,0,21},{3,0,0}, -{209,22,113},{185,14,100},{160,4,86},{135,0,72},{112,0,56},{89,0,40},{60,0,18},{3,0,0},{210,24,107},{184,17,94},{160,6,81},{135,0,67},{112,0,52},{89,0,36},{60,0,13},{3,0,0},{210,26,101},{184,19,88},{160,8,76},{135,0,62},{112,0,47},{89,0,31},{60,0,9},{3,0,0},{210,27,95},{183,20,83},{160,10,71},{135,1,57},{112,0,43},{89,0,27},{60,0,7},{3,0,0}, -{210,29,89},{183,21,77},{160,12,65},{135,2,52},{112,0,39},{89,0,23},{60,0,5},{3,0,0},{210,30,82},{184,22,70},{160,14,60},{135,3,47},{111,0,34},{88,0,18},{59,0,3},{3,0,0},{210,31,76},{184,23,64},{160,16,54},{135,4,42},{111,0,29},{88,0,13},{59,0,1},{3,0,0},{211,31,69},{184,25,58},{160,18,48},{135,6,36},{111,0,23},{88,0,7},{58,0,0},{3,0,0}, -{211,32,61},{184,26,51},{160,18,42},{135,7,30},{111,0,17},{88,0,4},{58,0,0},{3,0,0},{211,33,54},{184,27,44},{160,19,36},{135,9,24},{111,1,10},{88,0,1},{58,0,0},{3,0,0},{211,33,48},{184,27,38},{160,20,30},{135,9,18},{111,1,6},{88,0,1},{58,0,0},{3,0,0},{211,34,42},{185,27,32},{160,21,24},{135,10,13},{111,1,2},{88,0,0},{58,0,0},{3,0,0}, -{175,226,249},{153,198,220},{132,173,192},{112,147,164},{91,121,135},{71,96,107},{45,65,75},{7,24,33},{177,225,236},{155,197,208},{134,172,181},{113,146,155},{92,120,128},{71,95,102},{45,64,70},{6,23,29},{179,224,223},{156,196,197},{135,172,171},{115,146,146},{93,120,121},{71,95,96},{45,64,65},{6,23,25},{181,223,211},{158,196,187},{137,171,162},{116,145,139},{94,120,114},{72,95,90},{45,64,61},{5,23,21}, -{182,223,199},{160,196,176},{138,170,154},{116,144,131},{94,120,107},{72,95,85},{45,64,56},{5,23,18},{183,222,187},{161,195,165},{139,169,144},{117,144,122},{95,119,101},{72,94,79},{45,63,52},{4,22,13},{184,221,174},{162,194,154},{139,169,134},{118,144,114},{95,119,94},{72,94,73},{45,63,47},{4,22,8},{185,220,161},{163,193,143},{140,168,124},{118,143,105},{96,118,86},{73,93,66},{46,62,42},{4,22,3}, -{187,219,149},{163,192,131},{141,167,114},{118,142,96},{96,118,79},{73,93,60},{46,62,37},{3,22,0},{189,218,137},{164,191,120},{142,166,105},{119,141,88},{96,117,72},{74,92,54},{45,62,31},{2,22,0},{190,218,123},{164,191,109},{142,166,94},{119,141,79},{96,117,64},{74,92,47},{45,62,25},{1,22,0},{191,217,109},{165,190,97},{143,166,84},{119,140,70},{96,116,55},{74,91,40},{45,61,19},{0,22,0}, -{191,217,93},{166,190,82},{143,165,71},{119,140,59},{96,116,45},{74,91,31},{45,61,11},{0,22,0},{192,216,77},{168,189,68},{144,164,57},{120,139,47},{97,115,35},{74,91,21},{46,61,3},{0,22,0},{193,216,62},{168,189,54},{144,164,45},{120,139,36},{97,115,24},{74,91,12},{46,61,1},{0,22,0},{194,216,46},{168,189,39},{144,164,33},{120,139,24},{97,114,13},{75,90,3},{45,60,0},{0,22,0}, -{176,213,240},{154,187,212},{134,163,186},{113,139,158},{92,115,131},{72,90,104},{46,60,72},{8,19,30},{178,212,228},{156,186,201},{136,163,176},{115,138,150},{93,114,124},{72,89,98},{46,60,67},{7,18,26},{179,212,216},{158,186,190},{137,163,166},{116,138,141},{94,114,117},{72,89,92},{46,60,62},{7,18,22},{182,211,204},{160,185,181},{138,162,157},{117,137,134},{95,113,110},{73,89,87},{46,59,58},{6,18,18}, -{183,210,193},{161,185,170},{139,161,149},{117,137,127},{95,113,103},{74,89,82},{46,59,54},{6,18,14},{185,209,181},{162,184,160},{140,160,139},{118,136,118},{96,112,97},{73,88,76},{46,59,49},{6,17,10},{186,209,169},{162,183,149},{140,160,130},{118,136,110},{96,112,90},{73,88,70},{46,59,44},{6,17,5},{186,208,156},{163,182,138},{141,159,120},{119,135,102},{96,111,83},{74,87,63},{47,58,39},{5,18,2}, -{187,207,144},{163,182,127},{141,158,111},{119,135,93},{96,111,76},{74,87,57},{47,58,34},{4,18,0},{188,206,133},{164,181,117},{142,157,102},{119,134,85},{96,110,69},{74,87,51},{46,58,29},{4,17,0},{189,206,120},{165,181,106},{142,157,92},{119,134,76},{96,110,61},{74,87,45},{46,58,23},{2,17,0},{191,205,107},{166,180,94},{142,157,82},{119,133,67},{97,110,53},{75,86,38},{46,57,17},{1,18,0}, -{191,205,91},{167,180,80},{143,156,69},{119,133,57},{97,110,44},{75,86,29},{46,57,9},{1,18,0},{192,204,76},{168,180,66},{144,155,56},{120,132,45},{97,109,34},{75,86,19},{46,57,2},{0,17,0},{193,204,61},{168,180,52},{144,155,44},{120,132,35},{97,109,23},{75,86,10},{46,57,1},{0,17,0},{194,204,47},{167,179,40},{144,155,32},{120,132,24},{97,109,12},{75,85,2},{46,56,0},{0,17,0}, -{177,201,232},{155,177,204},{135,154,179},{114,131,152},{93,107,127},{72,84,101},{47,55,70},{9,13,27},{179,200,220},{157,177,193},{137,154,169},{116,130,144},{94,107,120},{73,83,95},{47,55,65},{8,13,23},{180,200,208},{159,177,183},{138,154,160},{117,130,136},{95,107,113},{73,83,89},{47,55,60},{8,13,19},{182,199,197},{160,176,174},{139,153,151},{117,129,129},{96,106,107},{74,83,84},{47,54,56},{7,13,15}, -{183,198,186},{161,175,164},{139,152,143},{117,129,122},{96,106,100},{74,83,79},{47,54,52},{7,13,11},{185,197,175},{162,174,154},{140,151,134},{118,128,115},{96,105,94},{74,82,73},{48,54,47},{6,12,7},{186,197,163},{162,174,144},{140,151,126},{118,128,107},{96,105,87},{74,82,67},{48,54,42},{6,12,3},{186,196,151},{163,173,134},{141,150,117},{119,127,99},{96,104,80},{75,81,61},{47,53,37},{6,13,1}, -{187,196,140},{163,173,124},{141,150,108},{119,127,91},{96,104,73},{75,81,55},{47,53,32},{5,13,0},{188,195,129},{164,172,114},{142,149,99},{119,126,83},{96,103,66},{74,81,49},{47,53,27},{4,12,0},{189,195,118},{165,172,103},{142,149,90},{119,126,74},{96,103,59},{74,81,43},{47,53,21},{3,12,0},{191,194,105},{166,171,92},{143,148,80},{119,125,65},{97,103,52},{75,80,36},{47,53,15},{1,13,0}, -{191,194,90},{167,171,79},{143,148,68},{119,125,56},{97,103,43},{75,80,27},{47,53,8},{1,13,0},{192,193,76},{168,170,65},{144,147,56},{120,125,44},{97,102,33},{75,80,17},{47,53,2},{0,12,0},{192,193,61},{168,170,52},{144,147,44},{120,125,34},{97,102,23},{75,80,9},{47,53,1},{0,12,0},{193,193,48},{167,169,40},{144,146,31},{120,124,24},{98,102,12},{75,79,2},{46,53,0},{0,13,0}, -{178,189,224},{156,168,198},{136,145,173},{115,124,148},{95,101,123},{74,79,97},{48,51,67},{10,7,24},{180,188,213},{158,167,188},{137,145,164},{116,123,140},{96,101,116},{74,79,91},{48,51,62},{9,7,20},{181,188,201},{160,167,178},{138,145,156},{116,123,132},{96,101,109},{74,79,85},{48,51,57},{9,7,16},{182,188,191},{161,166,169},{139,144,147},{117,122,125},{96,100,103},{75,79,81},{48,50,53},{9,8,12}, -{183,188,180},{161,166,160},{140,144,139},{118,122,118},{96,100,96},{75,79,76},{48,50,49},{9,8,7},{185,187,170},{162,165,150},{140,143,130},{118,122,111},{96,99,90},{75,78,70},{48,50,45},{8,8,4},{186,187,159},{162,165,140},{140,143,122},{118,122,103},{96,99,84},{75,78,64},{48,50,40},{7,8,1},{187,186,147},{163,164,130},{141,142,113},{119,121,96},{97,99,77},{75,77,59},{48,49,35},{6,9,0}, -{187,185,136},{163,164,120},{141,142,104},{119,121,88},{97,99,71},{75,77,53},{48,49,30},{6,9,0},{188,184,125},{164,163,110},{142,141,95},{120,120,80},{97,98,64},{75,77,47},{48,49,25},{4,8,0},{189,184,114},{165,163,100},{142,141,86},{120,120,72},{97,98,57},{75,77,41},{48,49,19},{3,8,0},{190,184,102},{166,162,90},{143,140,77},{120,119,63},{98,98,50},{75,76,34},{48,49,13},{1,9,0}, -{190,184,88},{166,162,77},{143,140,66},{120,119,54},{98,98,41},{75,76,25},{48,49,7},{1,9,0},{191,183,74},{167,161,64},{144,139,54},{120,119,43},{98,97,31},{75,76,15},{47,49,2},{1,8,0},{191,183,60},{167,161,52},{144,139,43},{120,119,33},{98,97,21},{75,76,8},{47,49,1},{1,8,0},{192,182,48},{168,160,40},{144,139,32},{121,118,24},{98,97,11},{76,75,2},{47,49,0},{0,9,0}, -{178,178,216},{157,158,192},{136,137,168},{115,116,143},{95,95,119},{75,74,94},{49,47,64},{11,2,21},{180,177,205},{159,157,182},{137,136,159},{116,116,136},{96,95,112},{74,74,88},{49,46,59},{10,3,17},{182,177,194},{160,157,172},{138,136,151},{116,116,128},{96,95,105},{74,74,82},{49,46,54},{10,3,13},{183,177,184},{161,156,164},{140,136,143},{117,115,121},{96,94,99},{75,73,78},{49,46,50},{9,3,9}, -{184,177,175},{162,156,155},{141,136,135},{118,115,114},{96,94,93},{75,73,73},{49,46,46},{9,3,4},{186,176,165},{162,155,145},{140,135,126},{119,114,107},{97,93,87},{75,73,67},{48,46,42},{9,3,2},{187,176,154},{162,155,135},{140,135,118},{119,114,100},{97,93,81},{75,73,61},{48,46,37},{8,3,0},{187,175,143},{163,154,126},{141,134,109},{119,114,93},{97,93,74},{75,72,56},{49,45,32},{7,4,0}, -{187,175,132},{163,154,116},{141,134,101},{119,114,85},{97,93,68},{75,72,50},{49,45,28},{6,4,0},{188,174,122},{164,153,107},{142,133,92},{120,113,78},{98,92,61},{75,72,45},{48,45,23},{4,4,0},{188,174,111},{165,153,97},{142,133,83},{120,113,69},{98,92,55},{75,72,39},{48,45,17},{3,4,0},{189,173,99},{166,153,87},{143,133,74},{120,112,61},{98,92,48},{75,72,32},{48,45,10},{1,4,0}, -{190,173,86},{166,153,75},{143,133,64},{120,112,52},{98,92,39},{75,72,24},{48,45,6},{1,4,0},{191,173,73},{166,152,63},{144,132,53},{120,111,42},{98,91,30},{75,71,14},{47,45,2},{1,4,0},{191,173,60},{167,152,52},{144,132,43},{120,111,33},{98,91,20},{75,71,8},{47,45,1},{1,4,0},{191,172,48},{168,152,41},{144,131,32},{121,111,23},{98,91,11},{76,71,2},{47,45,0},{0,5,0}, -{180,166,209},{158,147,185},{137,128,162},{116,109,138},{96,88,114},{76,68,90},{50,41,61},{12,1,19},{181,166,198},{160,147,175},{138,127,153},{117,108,131},{96,88,108},{75,68,84},{50,41,57},{11,1,14},{182,166,188},{161,147,166},{139,127,145},{118,108,124},{96,88,101},{75,68,79},{50,41,52},{11,1,9},{183,165,178},{162,146,158},{140,127,138},{118,108,117},{97,87,96},{76,67,75},{50,41,48},{10,2,5}, -{184,165,169},{162,146,149},{141,127,130},{119,108,110},{97,87,90},{76,67,70},{50,41,44},{10,2,2},{185,164,159},{163,145,140},{141,126,122},{120,107,103},{97,87,84},{75,67,64},{49,41,40},{10,2,1},{186,164,148},{163,145,131},{141,126,114},{120,107,96},{97,87,78},{75,67,59},{49,41,35},{8,2,0},{186,164,139},{163,144,122},{141,126,106},{119,107,89},{97,86,72},{76,66,54},{49,41,30},{7,2,0}, -{187,164,128},{164,144,113},{142,126,98},{119,107,83},{97,86,66},{76,66,48},{49,41,26},{6,2,0},{188,163,119},{165,143,104},{143,125,90},{120,106,76},{98,86,59},{76,66,43},{49,41,21},{5,2,0},{188,163,108},{165,143,95},{143,125,81},{120,106,67},{98,86,53},{76,66,37},{49,41,15},{4,2,0},{189,162,97},{165,143,85},{142,124,72},{121,105,59},{98,85,46},{76,66,30},{48,41,8},{3,2,0}, -{189,162,84},{166,143,73},{142,124,62},{121,105,50},{98,85,38},{76,66,22},{48,41,4},{3,2,0},{190,162,72},{166,142,61},{143,123,51},{120,104,40},{98,85,29},{76,65,13},{48,41,1},{3,2,0},{190,162,60},{167,142,51},{143,123,42},{120,104,31},{98,85,19},{76,65,7},{48,41,1},{2,2,0},{190,161,48},{167,142,41},{143,123,32},{121,104,22},{98,85,10},{76,65,1},{48,41,0},{1,2,0}, -{180,155,201},{159,137,179},{137,120,156},{117,101,133},{96,82,110},{76,62,86},{50,36,58},{11,0,16},{181,154,191},{160,136,169},{138,119,148},{118,100,126},{97,81,104},{76,62,81},{50,36,54},{11,0,11},{182,154,182},{161,136,160},{139,119,140},{119,100,119},{97,81,98},{76,62,76},{50,36,49},{11,0,6},{183,154,172},{162,136,152},{140,118,133},{119,100,113},{97,81,93},{76,61,72},{50,36,45},{11,0,2}, -{184,154,163},{162,136,144},{141,118,125},{119,100,106},{97,81,87},{76,61,67},{50,36,41},{10,0,0},{185,153,153},{163,135,135},{141,118,117},{120,99,100},{97,80,81},{75,61,61},{50,36,37},{9,0,0},{185,153,143},{163,135,127},{141,118,110},{120,99,93},{97,80,75},{75,61,56},{50,36,32},{7,0,0},{186,153,134},{163,135,118},{141,118,103},{119,99,86},{97,80,69},{76,61,51},{49,36,28},{6,0,0}, -{187,153,124},{164,135,109},{142,118,95},{119,99,80},{97,80,63},{76,61,46},{49,36,24},{5,0,0},{188,152,115},{165,134,101},{143,117,87},{120,98,73},{98,79,57},{76,60,41},{49,36,19},{4,0,0},{188,152,105},{165,134,92},{143,117,79},{120,98,65},{98,79,51},{76,60,34},{49,36,13},{4,0,0},{189,151,95},{165,134,82},{142,116,70},{121,97,57},{98,79,44},{76,60,28},{48,36,6},{4,0,0}, -{189,151,82},{165,134,71},{142,116,60},{121,97,48},{98,79,36},{76,60,20},{48,36,3},{4,0,0},{190,151,70},{166,133,60},{143,115,50},{120,97,39},{98,79,27},{76,59,11},{48,36,1},{3,0,0},{190,151,60},{166,133,50},{143,115,41},{120,97,30},{98,79,18},{76,59,7},{48,36,1},{3,0,0},{190,150,48},{167,133,41},{143,115,32},{121,96,22},{98,79,9},{76,59,1},{48,36,0},{2,0,0}, -{181,144,194},{159,127,173},{138,111,151},{118,94,128},{97,75,106},{76,56,83},{51,30,55},{9,0,12},{182,143,184},{160,127,163},{139,110,143},{119,93,121},{98,74,100},{76,55,78},{50,31,51},{10,0,7},{183,143,175},{161,127,154},{139,110,135},{119,93,114},{98,74,94},{76,55,73},{50,31,46},{10,0,3},{184,143,166},{162,127,147},{140,110,128},{119,93,108},{98,74,89},{76,55,69},{50,31,42},{8,0,1}, -{184,143,158},{162,127,139},{140,110,120},{119,93,102},{98,74,84},{76,55,64},{50,31,38},{7,0,0},{185,142,148},{163,126,130},{141,109,113},{120,92,96},{98,73,78},{76,56,59},{50,31,34},{6,0,0},{185,142,139},{163,126,122},{141,109,106},{120,92,90},{98,73,72},{76,56,54},{50,31,30},{6,0,0},{186,142,130},{164,125,113},{141,109,99},{120,92,83},{98,73,66},{76,55,49},{50,31,26},{5,0,0}, -{186,142,120},{164,125,105},{141,109,91},{120,92,77},{98,73,60},{76,55,43},{50,31,21},{4,0,0},{187,141,111},{164,125,98},{142,108,84},{119,91,70},{98,72,54},{76,55,38},{50,31,16},{4,0,0},{188,141,102},{165,125,89},{142,108,76},{119,91,62},{98,72,48},{76,55,32},{50,31,10},{4,0,0},{189,141,92},{165,124,80},{142,107,68},{120,90,55},{98,72,42},{76,55,26},{49,31,4},{3,0,0}, -{189,141,80},{165,124,70},{142,107,59},{120,90,47},{98,72,35},{76,55,19},{49,31,2},{3,0,0},{189,141,68},{165,124,59},{142,107,49},{120,90,38},{98,72,26},{77,54,10},{49,31,0},{2,0,0},{189,141,59},{165,124,49},{142,107,40},{120,90,29},{98,72,17},{77,54,6},{49,31,0},{2,0,0},{190,141,49},{166,124,41},{143,107,31},{120,89,21},{98,72,8},{76,54,1},{48,31,0},{1,0,0}, -{181,133,187},{159,117,167},{138,102,145},{118,86,124},{98,68,102},{76,50,79},{51,23,52},{7,0,8},{182,133,178},{160,117,157},{139,101,137},{119,85,117},{98,68,96},{76,49,74},{50,24,48},{7,0,4},{183,133,169},{161,117,148},{139,101,130},{119,85,110},{98,68,90},{76,49,69},{50,25,44},{7,0,1},{184,133,160},{162,117,141},{140,101,123},{119,85,104},{98,68,85},{77,49,65},{50,25,40},{6,0,0}, -{184,133,152},{163,117,134},{140,101,116},{119,85,98},{98,68,80},{77,49,61},{50,25,36},{6,0,0},{185,132,143},{163,116,126},{141,101,109},{120,84,92},{98,67,74},{77,50,57},{50,25,32},{5,0,0},{186,132,135},{163,116,118},{141,101,102},{120,84,86},{98,67,69},{77,50,52},{50,25,28},{4,0,0},{186,132,126},{164,115,109},{141,100,95},{120,84,80},{98,67,64},{77,49,47},{50,25,24},{4,0,0}, -{186,132,116},{164,115,101},{141,100,88},{120,84,74},{98,67,58},{77,49,41},{50,25,19},{3,0,0},{187,131,107},{164,115,94},{141,100,81},{119,84,67},{98,66,52},{76,49,36},{50,26,14},{2,0,0},{188,131,98},{164,115,86},{141,100,74},{119,84,60},{98,66,46},{76,49,30},{50,26,8},{2,0,0},{188,131,89},{165,114,78},{142,99,66},{120,83,53},{98,66,40},{76,49,24},{49,26,3},{2,0,0}, -{188,131,78},{165,114,68},{142,99,57},{120,83,45},{98,66,33},{76,49,17},{49,26,1},{1,0,0},{189,131,66},{165,114,57},{142,99,47},{120,83,36},{98,66,24},{77,49,8},{49,27,0},{1,0,0},{189,131,57},{165,114,49},{142,99,39},{120,83,28},{98,66,15},{77,49,4},{49,27,0},{1,0,0},{189,131,49},{166,114,40},{143,99,31},{120,83,20},{98,66,7},{76,49,1},{48,27,0},{1,0,0}, -{182,122,180},{160,107,160},{138,93,139},{118,77,119},{98,61,98},{77,43,76},{51,16,49},{5,0,4},{183,122,171},{161,107,151},{139,92,132},{119,77,113},{98,61,92},{77,43,71},{51,17,45},{5,0,2},{184,122,162},{162,107,143},{140,92,125},{119,77,106},{98,61,86},{77,43,66},{51,18,42},{5,0,0},{185,122,154},{162,107,136},{140,92,119},{119,77,100},{98,61,81},{77,43,62},{50,18,38},{4,0,0}, -{185,122,146},{162,107,129},{140,92,112},{119,77,94},{98,61,76},{77,43,58},{50,18,34},{4,0,0},{185,122,138},{163,107,122},{141,92,105},{119,77,88},{98,60,71},{77,44,54},{51,19,30},{3,0,0},{185,122,130},{163,107,114},{141,92,98},{119,77,83},{98,60,66},{77,44,49},{51,19,26},{3,0,0},{186,121,121},{163,106,105},{142,91,91},{119,77,77},{98,60,61},{77,43,44},{50,20,22},{2,0,0}, -{186,121,112},{163,106,98},{142,91,85},{119,77,71},{98,60,56},{77,43,40},{50,20,17},{1,0,0},{187,121,104},{164,106,91},{142,91,78},{119,77,64},{98,60,51},{77,43,35},{50,21,12},{1,0,0},{187,121,95},{164,106,83},{142,91,71},{119,77,58},{98,60,45},{77,43,29},{50,21,7},{1,0,0},{187,121,86},{164,105,75},{142,91,64},{119,76,52},{98,60,39},{77,43,23},{49,21,3},{1,0,0}, -{187,121,76},{164,105,66},{142,91,56},{119,76,44},{98,60,31},{77,43,15},{49,21,1},{1,0,0},{188,120,65},{165,105,56},{142,91,46},{120,76,35},{98,59,23},{76,43,7},{48,21,0},{0,0,0},{188,120,56},{165,105,48},{142,91,38},{120,76,27},{98,59,14},{76,43,3},{48,21,0},{0,0,0},{188,120,48},{165,105,39},{143,90,30},{120,76,20},{98,59,6},{76,43,0},{48,22,0},{0,0,0}, -{182,110,173},{160,96,153},{139,83,134},{118,68,114},{98,53,94},{77,36,73},{51,10,46},{3,0,2},{183,110,164},{161,96,145},{140,83,127},{119,69,108},{98,53,89},{77,36,68},{51,11,42},{3,0,1},{184,110,156},{162,96,137},{140,83,120},{119,69,101},{98,53,83},{77,36,63},{51,11,39},{3,0,0},{185,110,149},{162,96,131},{141,83,114},{119,69,96},{98,53,78},{77,36,59},{50,12,35},{2,0,0}, -{185,110,141},{162,96,124},{141,83,107},{119,69,91},{98,53,73},{77,36,55},{50,12,31},{2,0,0},{185,110,133},{163,97,117},{141,83,101},{119,68,85},{98,53,68},{77,37,51},{51,12,27},{1,0,0},{185,110,125},{163,97,109},{141,83,95},{119,68,80},{98,53,63},{77,37,46},{51,12,23},{1,0,0},{186,110,117},{163,96,102},{142,82,88},{119,69,74},{98,53,58},{77,37,41},{50,13,19},{1,0,0}, -{186,110,109},{163,96,95},{142,82,82},{119,69,68},{98,53,53},{77,37,37},{50,13,14},{1,0,0},{187,110,101},{164,96,88},{142,82,75},{119,68,61},{98,53,48},{77,37,32},{50,14,10},{1,0,0},{187,110,92},{164,96,80},{142,82,69},{119,68,55},{98,53,42},{77,37,27},{50,14,5},{1,0,0},{187,110,84},{164,96,73},{142,82,62},{119,68,49},{98,53,36},{77,37,21},{49,15,3},{0,0,0}, -{187,110,74},{164,96,64},{142,82,54},{119,68,42},{98,53,29},{77,37,13},{49,15,1},{0,0,0},{188,109,64},{165,96,55},{142,82,45},{120,68,34},{98,53,21},{76,37,6},{48,15,0},{0,0,0},{188,109,55},{165,96,47},{142,82,37},{120,68,26},{98,53,13},{76,37,3},{48,15,0},{0,0,0},{188,109,47},{165,95,39},{143,82,30},{120,68,19},{98,53,6},{76,37,0},{48,16,0},{0,0,0}, -{182,98,167},{160,86,147},{139,73,128},{119,59,109},{98,44,90},{77,27,70},{51,4,44},{1,0,0},{183,98,158},{161,86,139},{140,73,122},{120,60,103},{98,44,85},{78,28,65},{51,5,40},{1,0,0},{183,98,150},{162,86,131},{141,73,115},{120,60,97},{98,44,79},{78,28,61},{51,5,37},{1,0,0},{184,98,143},{162,86,125},{141,73,109},{120,60,93},{98,45,75},{77,29,57},{50,5,33},{1,0,0}, -{185,98,136},{162,86,118},{141,73,103},{120,60,88},{98,45,70},{77,29,53},{50,5,29},{1,0,0},{185,98,128},{163,87,112},{141,73,97},{120,59,82},{98,46,65},{77,30,49},{50,5,25},{0,0,0},{185,98,120},{163,87,105},{141,73,91},{120,59,76},{98,46,60},{77,30,44},{50,5,21},{0,0,0},{186,98,113},{163,86,98},{141,73,85},{120,60,71},{98,46,55},{77,30,39},{50,6,16},{0,0,0}, -{186,98,105},{163,86,92},{141,73,79},{120,60,65},{98,46,51},{77,30,35},{50,6,12},{0,0,0},{186,98,98},{163,86,85},{141,73,73},{120,59,59},{98,46,46},{76,30,30},{49,7,8},{0,0,0},{186,98,90},{163,86,78},{141,73,67},{120,59,53},{98,46,40},{76,30,25},{49,7,4},{0,0,0},{187,98,81},{163,86,71},{141,73,60},{119,60,47},{98,46,34},{76,31,19},{48,8,2},{0,0,0}, -{187,98,72},{163,86,62},{141,73,52},{119,60,40},{98,46,27},{76,31,11},{48,8,1},{0,0,0},{187,98,62},{164,86,53},{142,73,43},{119,60,33},{98,46,19},{76,31,5},{48,9,0},{0,0,0},{187,98,54},{164,86,45},{142,73,36},{119,60,25},{98,46,12},{76,31,2},{48,9,0},{0,0,0},{188,98,47},{165,85,38},{143,73,29},{120,60,18},{98,47,6},{76,31,0},{47,10,0},{0,0,0}, -{182,84,161},{160,73,141},{139,61,123},{119,48,104},{98,33,86},{77,17,66},{51,2,41},{1,0,0},{183,84,152},{161,73,134},{140,62,117},{120,49,99},{98,34,81},{78,18,62},{51,2,37},{1,0,0},{183,84,144},{162,73,126},{141,62,110},{120,49,93},{98,34,75},{78,18,58},{51,2,34},{1,0,0},{184,84,138},{162,73,120},{141,62,105},{120,49,89},{98,35,71},{77,19,54},{50,2,30},{0,0,0}, -{185,84,131},{162,73,114},{141,62,99},{120,49,84},{98,35,67},{77,19,50},{50,2,26},{0,0,0},{185,85,123},{163,74,108},{141,63,93},{120,50,79},{98,36,62},{77,19,46},{50,2,22},{0,0,0},{185,85,116},{163,74,101},{141,63,88},{120,50,73},{98,36,57},{77,19,41},{50,2,18},{0,0,0},{186,85,109},{163,75,95},{141,63,82},{120,50,68},{98,36,52},{77,20,36},{50,2,13},{0,0,0}, -{186,85,102},{163,75,89},{141,63,76},{120,50,62},{98,36,48},{77,20,32},{50,2,9},{0,0,0},{186,85,95},{163,74,82},{141,63,70},{120,50,56},{98,37,43},{76,20,27},{49,3,6},{0,0,0},{186,85,87},{163,74,75},{141,63,64},{120,50,50},{98,37,37},{76,21,22},{49,3,3},{0,0,0},{187,85,79},{163,74,68},{141,63,57},{119,51,44},{98,38,31},{76,21,16},{48,4,2},{0,0,0}, -{187,85,71},{163,74,60},{141,63,50},{119,51,38},{98,38,25},{76,21,10},{48,4,1},{0,0,0},{187,85,61},{164,75,52},{142,63,42},{119,51,32},{98,38,18},{76,22,4},{48,5,0},{0,0,0},{187,85,54},{164,75,45},{142,63,36},{119,51,24},{98,38,12},{76,22,2},{48,5,0},{0,0,0},{188,85,47},{165,74,38},{143,63,29},{120,51,18},{98,38,6},{76,23,0},{47,5,0},{0,0,0}, -{182,69,154},{160,59,136},{140,48,118},{119,36,100},{98,21,82},{78,5,62},{51,0,38},{0,0,0},{183,70,146},{161,60,129},{141,49,112},{120,37,95},{98,22,77},{78,6,58},{50,0,34},{0,0,0},{184,70,138},{162,60,121},{141,49,106},{120,37,89},{98,22,71},{78,6,54},{50,0,31},{0,0,0},{185,71,132},{162,60,115},{140,50,101},{120,38,85},{99,23,67},{78,7,50},{50,0,27},{0,0,0}, -{185,71,125},{162,60,110},{140,50,95},{120,38,80},{99,23,63},{78,7,46},{50,0,24},{0,0,0},{185,72,119},{162,61,104},{140,51,89},{120,38,75},{98,24,59},{77,7,42},{50,0,20},{0,0,0},{185,72,112},{162,62,97},{140,51,84},{120,38,70},{98,25,54},{77,7,38},{50,0,15},{0,0,0},{185,72,105},{162,63,91},{140,51,78},{119,39,64},{98,26,49},{77,8,33},{50,0,10},{0,0,0}, -{185,72,98},{162,63,85},{140,51,72},{119,39,59},{98,26,45},{77,9,29},{50,0,7},{0,0,0},{186,73,91},{163,62,79},{141,51,67},{119,40,54},{98,27,40},{77,10,25},{50,1,4},{0,0,0},{186,73,84},{163,62,73},{141,51,61},{119,40,48},{98,27,35},{77,10,20},{50,1,2},{0,0,0},{186,73,77},{163,63,66},{141,51,55},{120,41,42},{98,28,29},{76,11,14},{49,1,1},{0,0,0}, -{186,73,69},{163,63,58},{141,51,48},{120,41,36},{98,28,23},{76,11,9},{49,1,1},{0,0,0},{187,72,60},{163,63,51},{141,52,41},{120,41,30},{98,29,17},{76,12,4},{48,1,0},{0,0,0},{187,72,53},{163,63,44},{141,52,35},{120,41,23},{98,29,10},{76,12,2},{48,1,0},{0,0,0},{187,72,46},{164,63,38},{142,52,29},{119,41,17},{98,29,4},{76,13,0},{48,1,0},{0,0,0}, -{182,49,147},{160,37,130},{140,26,113},{119,18,95},{98,10,77},{78,2,59},{51,0,35},{0,0,0},{183,50,140},{161,39,123},{141,28,107},{120,19,90},{98,11,73},{78,3,55},{50,0,32},{0,0,0},{184,50,132},{162,40,116},{141,29,101},{120,19,85},{98,11,69},{78,3,52},{50,0,29},{0,0,0},{185,51,126},{162,41,110},{140,30,96},{120,20,81},{99,12,65},{78,3,48},{50,0,25},{0,0,0}, -{185,52,120},{162,42,105},{140,31,91},{120,21,77},{99,12,61},{78,3,44},{50,0,21},{0,0,0},{185,53,114},{162,44,99},{140,33,86},{120,22,72},{98,12,56},{77,3,40},{50,0,17},{0,0,0},{185,54,108},{162,45,94},{140,34,81},{120,22,67},{98,13,52},{77,3,36},{50,0,13},{0,0,0},{185,54,101},{162,45,88},{140,34,75},{119,23,61},{98,13,47},{77,4,31},{50,0,9},{0,0,0}, -{185,55,94},{162,45,82},{140,35,70},{119,24,57},{98,13,43},{77,4,27},{50,0,6},{0,0,0},{186,55,87},{163,46,76},{141,36,65},{119,25,52},{98,14,38},{77,5,23},{50,1,4},{0,0,0},{186,55,81},{163,46,70},{141,37,59},{119,25,47},{98,14,33},{77,5,18},{50,1,2},{0,0,0},{186,56,75},{163,47,64},{141,37,53},{120,26,41},{98,15,28},{76,5,12},{49,1,1},{0,0,0}, -{186,56,67},{163,47,57},{141,38,47},{120,27,35},{98,15,22},{76,5,8},{49,1,1},{0,0,0},{187,56,59},{163,47,50},{141,38,40},{120,28,29},{98,16,16},{76,6,3},{48,1,0},{0,0,0},{187,56,53},{163,47,43},{141,38,34},{120,28,23},{98,16,10},{76,6,2},{48,1,0},{0,0,0},{187,56,46},{164,48,37},{142,39,29},{119,28,17},{98,16,4},{76,6,0},{48,1,0},{0,0,0}, -{183,28,141},{161,16,124},{140,3,108},{119,0,91},{99,0,73},{78,0,56},{50,0,32},{0,0,0},{184,29,134},{162,18,118},{140,6,102},{120,0,86},{99,0,69},{78,0,52},{50,0,29},{0,0,0},{184,29,127},{162,19,111},{140,8,96},{120,1,81},{99,0,66},{78,0,49},{50,0,26},{0,0,0},{185,31,121},{162,21,106},{141,9,92},{120,2,77},{99,0,62},{78,0,45},{50,0,22},{0,0,0}, -{185,32,116},{162,23,101},{141,11,87},{120,2,73},{99,0,58},{78,0,41},{50,0,19},{0,0,0},{185,34,110},{162,25,95},{140,14,82},{120,3,68},{99,0,53},{78,0,37},{49,0,14},{0,0,0},{185,35,104},{162,26,90},{140,16,77},{120,4,63},{99,0,49},{78,0,33},{49,0,10},{0,0,0},{185,35,97},{162,27,84},{140,17,72},{119,5,58},{99,0,45},{77,0,29},{49,0,7},{0,0,0}, -{185,36,91},{162,28,78},{140,19,67},{119,6,54},{99,0,41},{77,0,25},{49,0,5},{0,0,0},{185,37,84},{162,29,73},{140,20,62},{119,7,50},{98,1,36},{77,0,21},{49,0,4},{0,0,0},{185,38,78},{162,30,67},{140,21,56},{119,9,45},{98,1,31},{77,0,15},{49,0,2},{0,0,0},{185,39,72},{163,31,61},{140,22,50},{119,10,39},{98,1,26},{76,0,9},{48,0,0},{0,0,0}, -{185,39,65},{163,31,55},{140,23,45},{119,11,33},{98,2,20},{76,0,6},{48,0,0},{0,0,0},{186,38,58},{163,31,48},{141,24,39},{119,13,27},{98,3,14},{76,0,2},{47,0,0},{0,0,0},{186,38,52},{163,32,42},{141,24,33},{119,13,22},{98,3,9},{76,0,1},{47,0,0},{0,0,0},{186,39,46},{163,33,36},{141,25,28},{119,14,17},{98,3,4},{76,0,0},{47,0,0},{0,0,0}, -{132,213,247},{116,187,218},{101,164,190},{84,139,162},{67,114,135},{49,90,107},{25,61,75},{0,21,33},{135,212,234},{119,186,206},{103,163,180},{86,138,153},{69,114,128},{50,89,101},{25,61,70},{0,21,29},{138,212,221},{122,186,195},{105,163,171},{88,138,145},{70,114,120},{52,89,95},{25,61,65},{0,21,26},{141,211,209},{124,185,186},{107,162,162},{90,137,138},{72,113,114},{53,89,90},{26,60,61},{0,21,22}, -{144,210,198},{126,185,175},{109,162,153},{90,137,131},{72,113,107},{53,89,85},{26,60,57},{0,21,18},{145,209,187},{128,184,165},{109,161,144},{91,136,122},{73,112,101},{53,88,79},{27,60,52},{0,20,14},{147,209,174},{129,184,154},{110,161,134},{92,136,114},{73,112,94},{53,88,73},{27,60,47},{0,20,9},{148,208,162},{129,183,143},{112,160,125},{93,135,105},{74,111,87},{54,87,66},{28,60,42},{0,21,4}, -{150,207,150},{130,182,132},{113,159,115},{94,135,97},{75,111,80},{55,87,60},{28,60,37},{0,21,1},{152,206,138},{132,181,122},{114,158,105},{94,134,89},{75,111,73},{56,87,55},{28,59,32},{0,20,0},{154,206,126},{134,181,111},{114,158,95},{94,134,81},{75,111,65},{56,87,49},{28,59,26},{0,20,0},{155,206,112},{135,180,99},{115,157,85},{95,133,72},{76,110,57},{56,86,42},{29,59,20},{0,20,0}, -{155,206,99},{136,180,86},{116,157,74},{96,133,62},{76,110,48},{56,86,33},{29,59,13},{0,20,0},{157,205,84},{137,180,74},{117,156,62},{97,132,51},{77,109,39},{57,86,25},{29,58,4},{0,20,0},{158,205,71},{137,180,62},{117,156,52},{97,132,42},{77,109,30},{57,86,16},{29,58,2},{0,20,0},{160,204,58},{139,180,51},{118,156,42},{97,132,33},{77,108,22},{57,86,7},{29,58,0},{0,20,0}, -{136,202,239},{120,178,211},{104,155,184},{87,132,157},{69,108,131},{52,85,104},{28,57,72},{0,16,30},{138,201,226},{122,177,200},{106,154,174},{89,131,149},{71,108,124},{53,84,98},{28,56,67},{0,16,26},{141,200,214},{124,177,189},{108,154,165},{90,131,140},{72,108,116},{53,84,91},{28,56,62},{0,16,23},{144,199,203},{126,176,180},{110,153,156},{91,130,133},{73,107,110},{54,84,87},{29,56,58},{0,16,19}, -{146,199,192},{128,176,170},{111,153,148},{92,130,126},{74,107,103},{55,84,82},{29,56,54},{0,16,15},{148,198,181},{129,175,160},{112,152,139},{93,129,118},{75,106,97},{55,83,76},{30,56,50},{0,15,11},{149,198,169},{130,174,149},{113,152,130},{94,129,110},{75,106,90},{55,83,70},{30,56,45},{0,15,6},{150,197,157},{131,173,138},{114,151,121},{95,128,102},{76,106,83},{56,83,64},{30,56,40},{0,16,2}, -{152,196,145},{132,173,128},{114,150,112},{95,128,94},{76,106,77},{56,83,58},{30,56,35},{0,16,0},{154,195,134},{134,172,118},{115,149,102},{96,127,86},{76,105,70},{57,82,52},{30,55,30},{0,15,0},{155,195,123},{135,172,108},{115,149,93},{96,127,78},{76,105,62},{57,82,46},{30,55,24},{0,15,0},{157,195,110},{136,171,96},{116,148,83},{97,126,69},{77,104,55},{58,82,40},{30,55,18},{0,15,0}, -{157,195,96},{137,171,84},{117,148,72},{97,126,60},{77,104,46},{58,82,31},{30,55,11},{0,15,0},{158,194,83},{138,171,72},{118,147,60},{98,125,50},{78,103,37},{58,81,23},{30,54,3},{0,15,0},{159,194,70},{139,171,61},{118,147,51},{98,125,41},{78,103,29},{58,81,15},{30,54,1},{0,15,0},{160,193,58},{140,170,50},{118,147,41},{98,125,32},{78,103,21},{58,81,6},{30,54,0},{0,15,0}, -{139,190,231},{122,168,203},{106,146,177},{88,124,152},{71,102,126},{53,79,101},{30,52,70},{0,11,28},{142,189,218},{124,168,192},{108,145,168},{90,123,143},{73,101,119},{54,79,95},{31,52,65},{0,10,24},{144,189,206},{126,168,182},{109,145,159},{92,123,135},{74,101,112},{55,79,88},{31,52,60},{0,10,21},{146,188,196},{128,167,173},{111,144,150},{93,122,128},{75,100,106},{56,78,84},{31,51,56},{0,10,17}, -{148,188,185},{129,167,164},{113,144,142},{94,122,121},{76,100,100},{57,78,79},{31,51,52},{0,10,13},{150,187,174},{131,166,154},{114,143,134},{95,121,115},{76,100,94},{56,78,73},{32,52,48},{0,10,8},{151,187,163},{132,165,144},{114,143,126},{95,121,107},{76,100,87},{56,78,67},{32,52,43},{0,10,4},{152,186,152},{133,164,134},{115,142,117},{96,120,99},{77,99,80},{57,78,62},{31,51,38},{0,10,1}, -{153,186,141},{134,164,124},{115,142,109},{96,120,91},{77,99,74},{57,78,56},{31,51,33},{0,10,0},{154,185,131},{135,163,115},{116,141,100},{97,119,84},{77,98,67},{58,77,50},{32,51,28},{0,9,0},{155,185,120},{136,163,105},{116,141,91},{97,119,76},{77,98,60},{58,77,44},{32,51,22},{0,9,0},{157,184,108},{137,162,94},{117,140,81},{98,119,67},{78,98,53},{58,77,38},{32,51,16},{0,10,0}, -{158,184,95},{138,162,82},{118,140,71},{98,119,58},{78,98,45},{58,77,30},{32,51,9},{0,10,0},{159,183,82},{139,162,70},{119,139,59},{99,118,49},{78,97,36},{58,76,21},{32,51,3},{0,9,0},{159,183,70},{139,162,60},{119,139,50},{99,118,40},{78,97,28},{58,76,13},{32,51,1},{0,9,0},{160,183,58},{140,161,49},{119,139,40},{99,118,32},{79,97,20},{59,76,5},{32,50,0},{0,9,0}, -{142,180,223},{124,159,197},{109,138,173},{91,118,148},{74,96,122},{55,75,97},{33,48,66},{1,5,25},{145,179,211},{127,158,187},{110,137,164},{93,117,139},{75,95,115},{56,75,91},{33,48,62},{0,5,21},{147,179,200},{129,158,177},{111,137,155},{93,117,131},{75,95,108},{56,75,85},{33,48,58},{0,5,17},{148,178,190},{130,158,168},{113,137,146},{95,116,124},{76,95,102},{57,74,81},{33,47,54},{0,5,13}, -{149,178,179},{131,158,160},{114,137,138},{95,116,117},{77,95,97},{58,74,76},{33,47,50},{0,5,9},{151,178,169},{132,157,150},{115,136,130},{96,115,111},{77,94,91},{58,74,70},{34,48,45},{0,5,4},{152,178,159},{133,156,140},{115,136,122},{96,115,103},{77,94,84},{58,74,64},{34,48,40},{0,5,2},{153,177,148},{134,155,130},{116,135,113},{97,114,96},{78,94,77},{59,73,59},{33,47,36},{0,6,0}, -{154,176,137},{135,155,120},{116,135,105},{98,114,89},{78,94,71},{59,73,54},{33,47,31},{0,6,0},{155,175,127},{136,154,111},{117,134,96},{99,114,82},{79,93,65},{59,73,48},{33,47,26},{0,5,0},{156,175,116},{137,154,102},{117,134,88},{99,114,74},{79,93,58},{59,73,42},{33,47,20},{0,5,0},{158,175,105},{138,153,92},{118,133,79},{99,113,65},{79,93,51},{60,73,36},{33,47,14},{0,5,0}, -{159,175,92},{138,153,80},{119,133,69},{99,113,56},{79,93,43},{60,73,28},{33,47,8},{0,5,0},{160,174,80},{139,153,69},{119,132,57},{99,112,47},{79,92,35},{60,72,19},{33,47,3},{0,5,0},{160,174,68},{140,153,59},{119,132,49},{99,112,39},{79,92,27},{60,72,12},{33,47,1},{0,5,0},{160,173,58},{141,152,48},{120,132,41},{100,112,31},{80,92,19},{60,72,4},{33,46,0},{0,5,0}, -{144,169,215},{127,150,190},{110,130,167},{94,110,143},{75,90,118},{57,70,93},{34,44,63},{1,1,22},{146,168,204},{129,149,181},{112,130,159},{95,110,135},{76,90,111},{58,70,88},{34,44,59},{0,1,18},{148,168,193},{131,149,172},{113,130,150},{95,110,127},{76,90,104},{58,70,82},{34,44,55},{0,1,14},{150,168,184},{132,148,163},{114,129,142},{96,109,120},{77,89,99},{59,69,78},{35,43,51},{0,1,10}, -{151,168,174},{133,148,155},{115,129,134},{97,109,113},{77,89,94},{59,69,73},{35,43,47},{0,1,6},{153,167,164},{134,148,145},{115,128,126},{97,109,107},{78,89,88},{59,69,67},{35,44,42},{0,1,2},{153,167,154},{134,147,136},{116,128,118},{98,109,100},{78,89,81},{59,69,61},{35,44,37},{0,1,0},{154,166,143},{135,147,127},{117,127,110},{98,108,93},{79,89,74},{59,68,56},{35,43,33},{0,2,0}, -{155,166,133},{136,147,117},{117,127,102},{98,108,86},{79,89,68},{59,68,51},{35,43,29},{0,2,0},{156,165,124},{137,146,108},{118,127,93},{99,107,79},{80,88,62},{60,68,46},{35,43,24},{0,2,0},{156,165,113},{138,146,99},{118,127,85},{99,107,71},{80,88,56},{60,68,40},{35,43,18},{0,2,0},{158,164,102},{139,145,89},{119,126,76},{99,107,63},{80,88,49},{60,68,34},{34,43,12},{0,2,0}, -{159,164,89},{139,145,78},{119,126,67},{99,107,55},{80,88,42},{60,68,26},{34,43,8},{0,2,0},{160,164,78},{140,144,67},{119,125,56},{99,106,46},{80,87,34},{60,67,18},{34,43,3},{0,2,0},{160,164,68},{141,144,58},{119,125,48},{99,106,38},{80,87,26},{60,67,11},{34,43,1},{0,2,0},{161,163,57},{142,144,48},{120,125,40},{100,105,30},{80,87,18},{61,67,4},{34,42,0},{0,2,0}, -{146,158,208},{129,140,184},{112,122,161},{95,103,137},{77,84,114},{59,64,89},{36,38,61},{1,0,20},{148,158,197},{131,139,175},{114,121,153},{96,103,130},{78,84,107},{59,64,84},{36,39,57},{1,1,15},{150,158,187},{132,139,166},{115,121,144},{97,103,123},{78,84,101},{59,64,79},{36,39,52},{1,1,10},{151,158,178},{134,138,157},{116,121,137},{97,102,116},{79,83,96},{60,64,75},{36,38,48},{1,1,6}, -{152,158,168},{135,138,149},{116,121,130},{98,102,110},{79,83,91},{60,64,70},{36,38,44},{1,1,3},{154,157,159},{136,138,139},{117,120,122},{99,102,103},{79,83,85},{60,63,65},{36,39,40},{1,1,1},{154,157,149},{136,138,131},{117,120,114},{99,102,96},{79,83,79},{60,63,59},{36,39,35},{0,1,0},{155,156,139},{137,137,122},{118,120,106},{99,101,89},{80,83,72},{60,63,54},{36,39,31},{0,1,0}, -{156,156,129},{137,137,113},{118,120,98},{99,101,83},{80,83,66},{60,63,49},{36,39,27},{0,1,0},{157,155,120},{138,136,105},{118,119,91},{99,100,76},{80,82,60},{61,63,44},{36,39,22},{0,1,0},{158,155,110},{138,136,96},{118,119,83},{99,100,69},{80,82,54},{61,63,38},{36,39,16},{0,1,0},{159,154,100},{139,136,87},{119,118,74},{100,100,61},{81,82,47},{61,63,32},{36,39,10},{0,1,0}, -{160,154,87},{140,136,76},{119,118,65},{100,100,53},{81,82,40},{61,63,24},{36,39,6},{0,1,0},{161,154,76},{141,135,66},{120,117,55},{100,99,44},{81,81,32},{61,62,16},{35,39,2},{0,1,0},{161,154,67},{141,135,57},{120,117,47},{100,99,37},{81,81,24},{61,62,10},{35,39,1},{0,1,0},{161,153,56},{141,135,48},{121,117,39},{100,99,29},{81,81,16},{61,62,3},{35,38,0},{0,1,0}, -{148,147,200},{131,130,178},{113,114,155},{96,95,132},{78,78,110},{59,59,86},{37,33,58},{1,0,17},{150,147,190},{133,130,169},{115,113,147},{97,95,125},{79,78,104},{60,58,81},{37,34,54},{1,0,12},{152,147,181},{134,130,160},{116,113,139},{98,95,118},{79,78,98},{61,58,76},{37,34,49},{1,0,7},{153,147,172},{135,129,151},{117,112,132},{98,95,112},{80,77,93},{61,58,72},{37,33,45},{1,0,3}, -{154,147,163},{135,129,143},{117,112,125},{98,95,107},{80,77,88},{61,58,67},{37,33,41},{1,0,1},{155,146,154},{136,129,134},{118,112,118},{99,94,100},{80,77,82},{61,58,62},{37,34,37},{1,0,0},{155,146,144},{137,129,126},{118,112,111},{99,94,93},{80,77,76},{61,58,57},{37,34,33},{0,0,0},{156,145,135},{137,129,118},{119,112,103},{99,94,86},{80,77,70},{61,58,52},{36,34,29},{0,0,0}, -{157,145,125},{137,129,110},{119,112,95},{99,94,80},{80,77,64},{61,58,47},{36,34,25},{0,0,0},{158,144,116},{138,128,102},{119,111,88},{99,94,73},{80,76,58},{62,58,41},{36,34,20},{0,0,0},{158,144,107},{138,128,93},{119,111,80},{99,94,66},{80,76,52},{62,58,35},{36,34,14},{0,0,0},{159,144,97},{139,127,84},{120,110,72},{100,93,59},{81,76,45},{62,58,29},{36,34,8},{0,0,0}, -{160,144,85},{140,127,74},{120,110,63},{100,93,51},{81,76,38},{62,58,22},{36,34,4},{0,0,0},{161,144,74},{141,127,64},{121,109,53},{101,93,42},{82,75,30},{62,57,15},{36,34,1},{0,0,0},{161,144,66},{141,127,56},{121,109,46},{101,93,35},{82,75,22},{62,57,9},{36,34,1},{0,0,0},{161,144,56},{141,126,48},{121,109,38},{101,93,28},{82,75,15},{62,57,3},{35,34,0},{0,0,0}, -{150,137,193},{132,121,172},{114,106,150},{97,88,128},{79,71,106},{60,53,83},{38,28,55},{0,0,13},{152,137,183},{134,121,163},{116,105,142},{98,88,121},{80,71,100},{61,53,78},{38,28,51},{1,0,8},{153,137,174},{135,121,154},{117,105,134},{99,88,114},{80,71,94},{62,53,73},{38,28,47},{1,0,4},{154,137,166},{136,120,146},{118,105,127},{99,88,108},{81,71,90},{62,53,69},{38,28,43},{1,0,2}, -{155,137,158},{136,120,138},{118,105,120},{99,88,103},{81,71,85},{62,53,64},{38,28,39},{1,0,0},{156,136,149},{137,120,130},{119,104,114},{100,87,97},{81,70,79},{62,53,59},{38,29,35},{0,0,0},{156,136,139},{137,120,122},{119,104,107},{100,87,90},{81,70,73},{62,53,54},{38,29,31},{0,0,0},{157,136,130},{138,120,114},{120,104,99},{100,87,83},{81,70,67},{62,53,49},{37,29,26},{0,0,0}, -{158,136,121},{138,120,106},{120,104,92},{100,87,77},{81,70,61},{62,53,44},{37,29,22},{0,0,0},{159,135,112},{138,119,98},{120,103,85},{100,87,70},{81,70,55},{62,53,39},{37,29,17},{0,0,0},{159,135,103},{139,119,90},{120,103,77},{100,87,64},{81,70,49},{62,53,33},{37,29,11},{0,0,0},{160,135,94},{140,119,82},{121,103,70},{101,86,57},{82,70,43},{62,53,27},{37,29,5},{0,0,0}, -{161,135,83},{140,119,72},{121,103,61},{101,86,49},{82,70,37},{62,53,21},{37,29,3},{0,0,0},{161,135,73},{141,118,62},{121,102,52},{101,86,41},{82,69,29},{63,52,14},{36,30,1},{0,0,0},{161,135,65},{141,118,54},{121,102,45},{101,86,34},{82,69,21},{63,52,8},{36,30,1},{0,0,0},{162,135,56},{142,118,47},{121,102,37},{101,86,27},{82,69,14},{63,52,2},{36,30,0},{0,0,0}, -{152,127,187},{134,111,166},{116,97,145},{99,82,124},{80,65,102},{62,47,79},{39,21,53},{0,0,9},{153,127,177},{135,111,157},{117,97,138},{100,82,117},{81,65,96},{62,47,74},{38,22,49},{0,0,5},{154,127,168},{136,111,148},{118,97,130},{100,82,110},{81,65,90},{62,47,70},{38,22,45},{0,0,1},{155,127,160},{137,111,141},{119,97,123},{100,82,104},{82,65,86},{63,47,66},{38,23,41},{0,0,1}, -{156,127,152},{137,111,134},{119,97,116},{100,82,99},{82,65,81},{63,47,62},{38,23,37},{0,0,0},{157,126,144},{138,111,126},{119,96,110},{101,81,93},{82,64,75},{63,47,57},{38,23,33},{0,0,0},{158,126,135},{138,111,118},{119,96,103},{101,81,87},{82,64,69},{63,47,52},{38,23,29},{0,0,0},{158,126,126},{139,110,110},{120,96,95},{101,81,80},{82,64,64},{63,47,47},{38,24,24},{0,0,0}, -{158,126,117},{139,110,102},{120,96,89},{101,81,74},{82,64,58},{63,47,42},{38,24,20},{0,0,0},{159,125,109},{139,110,95},{120,96,82},{101,81,68},{82,64,53},{62,47,37},{38,25,15},{0,0,0},{159,125,100},{140,110,88},{120,96,75},{101,81,62},{82,64,47},{62,47,31},{38,25,9},{0,0,0},{160,125,91},{140,110,80},{121,96,68},{101,80,55},{82,64,41},{62,47,25},{38,25,4},{0,0,0}, -{161,125,81},{140,110,70},{121,96,59},{101,80,47},{82,64,35},{62,47,19},{38,25,2},{0,0,0},{161,125,71},{141,109,60},{121,95,50},{101,80,39},{82,63,27},{63,47,12},{37,26,1},{0,0,0},{161,125,63},{141,109,52},{121,95,43},{101,80,32},{82,63,19},{63,47,6},{37,26,1},{0,0,0},{162,125,55},{142,109,46},{121,95,36},{101,80,26},{82,63,13},{63,47,2},{36,26,0},{0,0,0}, -{153,117,180},{135,103,159},{117,89,140},{100,75,119},{81,58,98},{63,40,76},{39,14,50},{0,0,5},{154,117,171},{136,103,151},{118,89,133},{101,75,113},{82,58,92},{63,41,71},{39,15,46},{0,0,3},{156,117,162},{137,103,143},{119,89,125},{101,75,106},{82,58,86},{63,41,67},{39,16,42},{0,0,0},{157,117,154},{138,103,136},{119,89,119},{101,75,100},{82,58,82},{63,41,63},{39,17,38},{0,0,0}, -{157,117,146},{138,103,129},{119,89,112},{101,75,95},{82,58,77},{63,41,59},{39,17,35},{0,0,0},{158,116,139},{139,103,122},{120,89,106},{101,74,89},{83,57,71},{64,41,54},{39,18,31},{0,0,0},{158,116,131},{139,103,114},{120,89,99},{101,74,84},{83,57,66},{64,41,49},{39,18,27},{0,0,0},{159,116,122},{139,102,106},{121,88,92},{101,74,78},{82,58,61},{63,41,45},{39,19,23},{0,0,0}, -{159,116,113},{139,102,99},{121,88,86},{101,74,72},{82,58,57},{63,41,41},{39,19,18},{0,0,0},{159,116,106},{140,102,92},{121,88,79},{101,74,65},{82,58,52},{63,42,36},{39,20,13},{0,0,0},{159,116,98},{140,102,85},{121,88,73},{101,74,59},{82,58,46},{63,42,30},{39,20,8},{0,0,0},{160,116,89},{141,102,77},{121,88,66},{101,73,53},{82,57,40},{63,42,24},{38,20,4},{0,0,0}, -{161,116,79},{141,102,69},{121,88,58},{101,73,46},{82,57,33},{63,42,17},{38,20,2},{0,0,0},{162,115,70},{141,101,59},{121,88,49},{102,73,38},{83,57,26},{63,42,10},{37,21,0},{0,0,0},{162,115,62},{141,101,51},{121,88,42},{102,73,31},{83,57,18},{63,42,5},{37,21,0},{0,0,0},{161,115,54},{142,101,45},{122,88,35},{102,73,25},{83,57,12},{63,42,2},{37,21,0},{0,0,0}, -{154,106,173},{135,93,153},{118,80,134},{100,66,114},{82,51,94},{63,33,73},{40,9,47},{0,0,3},{155,106,164},{137,94,145},{119,80,128},{101,67,108},{83,51,89},{63,34,68},{40,10,43},{0,0,1},{156,106,156},{138,94,138},{119,80,120},{101,67,101},{83,51,83},{63,34,64},{40,10,39},{0,0,0},{157,106,149},{138,94,131},{120,80,114},{102,66,97},{83,51,79},{63,34,60},{40,11,35},{0,0,0}, -{158,106,141},{139,94,124},{120,80,108},{102,66,92},{83,51,74},{63,34,56},{40,11,32},{0,0,0},{158,106,134},{139,94,117},{120,80,102},{102,66,86},{83,51,68},{64,35,52},{40,12,28},{0,0,0},{158,106,126},{139,94,110},{120,80,96},{102,66,81},{83,51,63},{64,35,47},{40,12,24},{0,0,0},{159,106,118},{139,93,103},{121,80,89},{101,66,75},{82,51,58},{63,35,42},{39,13,20},{0,0,0}, -{159,106,110},{139,93,96},{121,80,83},{101,66,69},{82,51,54},{63,35,38},{39,13,16},{0,0,0},{159,106,103},{140,93,89},{121,80,76},{102,66,62},{83,52,49},{63,36,34},{39,14,11},{0,0,0},{159,106,95},{140,93,82},{121,80,70},{102,66,57},{83,52,44},{63,36,28},{39,14,7},{0,0,0},{160,106,86},{141,93,74},{121,80,63},{101,66,51},{82,51,38},{63,36,22},{38,14,3},{0,0,0}, -{161,106,77},{141,93,66},{121,80,56},{101,66,44},{82,51,31},{63,36,15},{38,14,1},{0,0,0},{162,106,68},{141,92,58},{121,80,47},{102,66,37},{83,51,24},{63,36,8},{37,15,0},{0,0,0},{162,106,60},{141,92,50},{121,80,40},{102,66,30},{83,51,17},{63,36,5},{37,15,0},{0,0,0},{161,105,53},{142,92,44},{122,80,35},{102,66,24},{83,51,11},{63,36,2},{37,15,0},{0,0,0}, -{155,96,167},{136,83,147},{119,71,128},{101,57,109},{83,42,90},{64,25,70},{41,3,45},{0,0,1},{156,95,158},{138,84,139},{120,71,122},{102,58,103},{84,43,85},{64,26,65},{40,4,41},{0,0,0},{157,95,150},{139,84,132},{120,71,115},{102,58,97},{84,43,79},{64,27,61},{40,4,37},{0,0,0},{158,95,143},{139,84,126},{121,71,110},{103,58,93},{84,43,75},{64,27,57},{40,5,33},{0,0,0}, -{159,95,136},{139,84,119},{121,71,104},{103,58,88},{84,43,71},{64,27,54},{40,5,30},{0,0,0},{159,96,129},{140,84,113},{121,71,98},{103,58,82},{84,44,66},{64,28,50},{40,5,26},{0,0,0},{159,96,121},{140,84,106},{121,71,92},{103,58,77},{84,44,61},{64,28,45},{40,5,22},{0,0,0},{160,96,114},{140,84,99},{121,71,86},{102,58,72},{83,44,56},{64,29,40},{40,6,18},{0,0,0}, -{160,96,107},{140,84,93},{121,71,80},{102,58,66},{83,44,52},{64,29,36},{40,6,14},{0,0,0},{160,96,100},{140,83,86},{121,72,74},{103,58,60},{84,45,47},{64,29,32},{39,7,9},{0,0,0},{160,96,92},{140,83,79},{121,72,68},{103,58,55},{84,45,42},{64,29,26},{39,7,5},{0,0,0},{161,95,83},{141,83,72},{121,71,61},{102,58,49},{83,45,36},{63,30,20},{39,8,3},{0,0,0}, -{161,95,75},{141,83,64},{121,71,54},{102,58,42},{83,45,29},{63,30,14},{39,8,1},{0,0,0},{161,96,66},{142,83,56},{122,71,46},{102,58,35},{83,45,22},{63,30,7},{38,8,0},{0,0,0},{161,96,59},{142,83,49},{122,71,39},{102,58,29},{83,45,15},{63,30,4},{38,8,0},{0,0,0},{162,95,52},{142,83,43},{123,71,34},{103,58,23},{84,45,9},{63,30,1},{37,9,0},{0,0,0}, -{155,83,161},{137,72,141},{119,60,123},{101,47,105},{83,32,86},{64,16,67},{41,1,42},{0,0,0},{157,83,153},{138,72,134},{120,61,117},{102,48,99},{84,33,81},{64,16,62},{40,2,38},{0,0,0},{157,83,145},{139,72,127},{120,61,110},{102,48,93},{84,33,76},{64,17,58},{40,2,34},{0,0,0},{158,83,138},{140,72,121},{121,61,106},{103,48,89},{84,34,72},{64,17,54},{40,2,30},{0,0,0}, -{159,83,131},{140,72,115},{121,61,100},{103,48,84},{84,34,68},{64,17,51},{40,2,27},{0,0,0},{159,84,124},{140,73,109},{121,61,94},{103,49,79},{84,35,63},{64,18,47},{40,2,23},{0,0,0},{159,84,117},{140,73,102},{121,61,88},{103,49,74},{84,35,58},{64,18,42},{40,2,19},{0,0,0},{160,84,110},{140,73,96},{121,62,83},{103,49,69},{84,36,53},{64,19,37},{40,2,15},{0,0,0}, -{160,84,103},{140,73,90},{121,62,77},{103,49,63},{84,36,49},{64,19,33},{40,3,11},{0,0,0},{160,84,96},{140,73,83},{121,62,71},{103,49,57},{84,36,44},{64,19,29},{39,4,7},{0,0,0},{160,84,89},{141,73,76},{121,62,65},{103,49,52},{84,36,39},{64,20,24},{39,4,4},{0,0,0},{161,84,81},{141,73,70},{121,62,58},{102,50,46},{83,37,33},{63,21,18},{39,4,2},{0,0,0}, -{161,84,73},{141,73,62},{121,62,51},{102,50,40},{83,37,27},{63,21,13},{39,4,1},{0,0,0},{161,84,65},{142,73,55},{122,62,45},{102,50,34},{83,37,21},{63,21,6},{38,4,0},{0,0,0},{161,84,58},{142,73,48},{122,62,38},{102,50,28},{83,37,14},{63,21,3},{38,4,0},{0,0,0},{162,84,52},{143,73,42},{123,62,33},{103,50,22},{84,37,8},{63,22,1},{37,5,0},{0,0,0}, -{156,70,154},{138,60,136},{120,48,118},{102,35,101},{84,20,82},{65,5,63},{41,0,39},{0,0,0},{158,70,147},{139,60,129},{121,49,112},{103,36,95},{84,22,77},{65,6,59},{40,0,35},{0,0,0},{159,70,139},{140,60,122},{121,49,106},{103,37,89},{84,23,72},{65,6,55},{40,0,32},{0,0,0},{160,71,132},{140,60,116},{122,49,102},{104,38,85},{85,23,68},{65,6,51},{40,0,28},{0,0,0}, -{160,71,126},{140,60,111},{122,49,96},{104,38,80},{85,23,64},{65,6,47},{40,0,25},{0,0,0},{160,72,120},{140,61,105},{121,50,90},{103,39,75},{84,24,60},{65,7,43},{40,0,21},{0,0,0},{160,72,113},{140,61,98},{121,50,84},{103,39,70},{84,25,55},{65,7,39},{40,0,17},{0,0,0},{160,72,106},{140,62,92},{122,50,79},{103,39,65},{84,26,50},{65,8,35},{40,0,12},{0,0,0}, -{160,72,99},{140,62,86},{122,50,74},{103,39,60},{84,27,46},{65,9,31},{40,0,8},{0,0,0},{161,72,92},{141,62,80},{122,51,68},{103,40,55},{84,27,42},{64,9,27},{40,0,5},{0,0,0},{161,72,86},{141,62,74},{122,51,62},{103,40,50},{84,27,37},{64,10,22},{40,0,3},{0,0,0},{161,72,79},{142,62,68},{122,51,56},{103,40,44},{84,28,31},{64,11,16},{39,1,1},{0,0,0}, -{161,72,71},{142,62,60},{122,51,49},{103,40,38},{84,28,25},{64,11,11},{39,1,1},{0,0,0},{162,72,63},{142,62,53},{122,51,43},{103,41,32},{84,28,19},{64,12,5},{38,1,0},{0,0,0},{162,72,57},{142,62,47},{122,51,37},{103,41,26},{84,28,13},{64,12,2},{38,1,0},{0,0,0},{162,72,51},{143,62,41},{122,52,32},{102,41,21},{83,29,7},{63,13,0},{38,1,0},{0,0,0}, -{157,53,148},{138,42,130},{121,29,113},{102,18,96},{84,10,78},{65,2,60},{40,0,36},{0,0,0},{158,53,141},{139,43,124},{121,31,107},{103,20,91},{84,11,74},{65,3,56},{40,0,33},{0,0,0},{159,53,133},{140,43,117},{121,32,101},{103,20,86},{84,12,69},{65,3,52},{40,0,30},{0,0,0},{160,53,127},{140,44,111},{122,33,97},{104,21,82},{85,12,65},{65,3,48},{40,0,26},{0,0,0}, -{160,54,121},{140,44,106},{122,34,92},{104,22,77},{85,12,61},{65,3,45},{40,0,22},{0,0,0},{160,55,115},{140,45,101},{122,35,87},{103,23,73},{84,12,57},{65,3,41},{40,0,18},{0,0,0},{160,56,109},{140,46,95},{122,36,82},{103,24,68},{84,13,53},{65,3,37},{40,0,15},{0,0,0},{160,56,102},{140,47,89},{122,36,77},{103,25,63},{84,13,48},{65,4,33},{40,0,11},{0,0,0}, -{160,56,96},{140,47,83},{122,37,72},{103,26,58},{84,14,44},{65,4,29},{40,0,7},{0,0,0},{161,57,89},{141,47,78},{122,37,66},{103,27,53},{84,15,40},{64,4,25},{40,0,5},{0,0,0},{161,57,83},{141,47,72},{122,38,60},{103,27,48},{84,15,35},{64,5,20},{40,0,3},{0,0,0},{161,57,77},{142,48,66},{122,39,54},{103,27,42},{84,16,29},{64,5,14},{39,1,1},{0,0,0}, -{161,57,69},{142,49,59},{122,39,48},{103,28,37},{84,16,24},{64,5,9},{39,1,1},{0,0,0},{162,58,62},{142,49,52},{122,40,42},{103,29,31},{84,16,18},{64,6,4},{38,1,0},{0,0,0},{162,58,56},{142,49,46},{122,40,36},{103,29,25},{84,16,12},{64,6,2},{38,1,0},{0,0,0},{162,58,50},{143,49,41},{122,40,31},{102,29,20},{83,17,6},{63,6,0},{38,1,0},{0,0,0}, -{158,35,142},{139,25,125},{122,10,108},{103,1,91},{85,0,74},{65,0,57},{39,0,33},{0,0,0},{159,35,135},{140,26,119},{122,13,103},{103,2,87},{85,0,70},{65,0,53},{39,0,30},{0,0,0},{160,35,128},{140,27,112},{122,15,97},{103,3,82},{85,0,66},{65,0,50},{39,0,27},{0,0,0},{160,37,122},{141,28,107},{122,17,93},{103,5,78},{85,0,62},{65,0,46},{39,0,23},{0,0,0}, -{160,38,117},{141,28,102},{122,18,88},{103,6,74},{85,0,58},{65,0,42},{39,0,19},{0,0,0},{160,39,111},{140,30,97},{122,19,84},{103,7,70},{85,0,54},{65,0,38},{39,0,15},{0,0,0},{160,40,105},{140,31,92},{122,21,79},{103,9,65},{85,0,50},{65,0,34},{39,0,12},{0,0,0},{160,41,98},{141,32,86},{122,22,74},{104,10,60},{85,1,46},{65,0,30},{39,0,9},{0,0,0}, -{160,41,92},{141,32,80},{122,23,69},{104,12,56},{85,1,42},{65,0,26},{39,0,6},{0,0,0},{161,42,86},{141,33,75},{122,24,64},{103,13,51},{84,2,38},{64,0,22},{38,0,4},{0,0,0},{161,42,80},{141,33,69},{122,25,58},{103,14,46},{84,2,33},{64,0,17},{38,0,2},{0,0,0},{161,43,74},{142,34,63},{122,26,52},{103,15,40},{84,3,27},{64,0,11},{37,0,1},{0,0,0}, -{161,43,67},{142,35,57},{122,27,47},{103,16,35},{84,3,22},{64,0,7},{37,0,1},{0,0,0},{162,44,61},{142,36,51},{122,28,41},{103,17,30},{84,4,16},{64,0,3},{37,0,0},{0,0,0},{162,44,55},{142,36,45},{122,28,35},{103,17,24},{84,4,11},{64,0,2},{37,0,0},{0,0,0},{163,44,49},{142,37,40},{123,28,30},{103,17,19},{84,4,5},{64,0,0},{36,0,0},{0,0,0}, -{76,202,245},{68,178,216},{56,155,188},{45,132,161},{32,108,134},{17,86,107},{5,58,75},{0,19,34},{82,201,232},{74,177,204},{62,154,178},{50,132,152},{35,108,127},{19,85,101},{5,57,70},{0,18,30},{89,200,219},{80,176,193},{67,154,169},{54,132,144},{38,108,119},{20,85,94},{5,57,65},{0,18,27},{94,199,207},{82,176,184},{70,153,160},{56,131,137},{41,108,113},{22,85,90},{6,57,61},{0,18,23}, -{98,199,196},{85,176,174},{72,153,152},{59,131,129},{43,108,107},{24,85,85},{6,57,57},{0,18,20},{100,198,185},{88,175,164},{74,152,142},{61,130,122},{44,107,101},{25,84,79},{7,57,53},{0,18,14},{102,197,173},{90,174,153},{76,152,134},{62,130,114},{45,107,94},{27,84,74},{8,57,48},{0,18,10},{104,197,162},{91,173,143},{78,151,125},{63,129,106},{47,106,87},{29,83,67},{8,56,44},{0,18,6}, -{107,196,151},{93,173,133},{80,150,116},{65,129,98},{48,106,80},{30,83,61},{8,56,39},{0,18,3},{109,195,139},{96,172,123},{81,149,107},{66,128,91},{49,105,73},{31,83,56},{9,56,34},{0,17,1},{111,195,128},{98,172,112},{82,149,97},{67,128,83},{49,105,66},{31,83,50},{9,56,28},{0,17,0},{113,194,115},{99,171,101},{84,149,87},{68,127,74},{51,105,59},{33,82,43},{9,56,22},{0,17,0}, -{115,194,102},{100,171,90},{85,149,77},{68,127,64},{52,105,51},{33,82,36},{9,56,15},{0,17,0},{118,194,89},{101,170,78},{86,148,66},{69,126,55},{53,104,43},{34,82,29},{10,56,8},{0,17,0},{119,194,77},{102,170,68},{87,148,58},{69,126,47},{53,104,35},{34,82,21},{10,56,4},{0,17,0},{121,193,66},{104,170,57},{88,148,48},{70,126,39},{53,104,28},{34,82,13},{9,55,1},{0,16,0}, -{85,191,237},{76,168,209},{64,147,182},{52,125,156},{38,103,129},{23,81,103},{7,53,72},{0,13,31},{91,190,224},{81,167,198},{68,146,172},{55,125,148},{41,103,123},{24,80,97},{8,53,67},{0,13,27},{96,190,212},{85,167,187},{72,146,164},{59,125,140},{43,103,115},{26,80,91},{8,53,63},{0,13,24},{100,189,201},{88,167,178},{75,145,155},{61,124,133},{45,102,109},{27,80,87},{9,53,59},{0,12,20}, -{103,188,190},{90,167,168},{77,145,147},{63,124,125},{46,102,103},{29,80,82},{9,53,55},{0,12,17},{105,187,179},{92,166,159},{79,144,138},{64,123,118},{48,101,97},{30,79,76},{10,53,50},{0,12,11},{107,187,168},{94,165,148},{80,144,130},{65,123,110},{49,101,91},{31,79,71},{10,53,45},{0,12,7},{109,186,158},{95,164,139},{82,143,121},{66,122,103},{50,101,84},{33,79,65},{10,52,41},{0,12,4}, -{112,186,147},{97,164,129},{83,143,112},{68,122,95},{51,101,77},{34,79,59},{10,52,37},{0,12,1},{114,185,136},{99,163,119},{84,142,104},{69,121,88},{52,100,71},{35,78,54},{11,52,32},{0,11,0},{115,185,125},{101,163,109},{85,142,95},{70,121,80},{53,100,64},{35,78,48},{11,52,26},{0,11,0},{117,184,112},{103,162,99},{87,142,85},{71,120,71},{54,99,57},{36,78,41},{11,52,20},{0,11,0}, -{119,184,100},{104,162,88},{88,142,75},{71,120,62},{54,99,49},{36,78,34},{11,52,13},{0,11,0},{121,183,87},{105,161,76},{89,141,64},{72,120,53},{55,99,41},{36,77,27},{11,52,6},{0,11,0},{122,183,76},{105,161,66},{89,141,56},{72,120,46},{55,99,33},{36,77,19},{11,52,3},{0,11,0},{123,183,65},{107,161,56},{90,141,48},{73,119,38},{56,99,26},{37,77,11},{11,51,1},{0,11,0}, -{94,180,229},{84,159,201},{72,139,175},{59,118,150},{44,97,125},{28,75,100},{10,49,69},{0,7,29},{99,179,216},{87,158,191},{75,138,166},{61,117,143},{46,97,119},{30,75,94},{10,49,65},{0,7,25},{103,179,205},{91,158,181},{77,138,158},{63,117,135},{48,97,112},{31,75,88},{10,49,61},{0,7,22},{106,178,194},{93,158,171},{79,137,150},{65,116,129},{49,96,106},{33,74,84},{11,49,57},{0,6,18}, -{109,178,183},{94,158,163},{81,137,142},{66,116,121},{50,96,100},{34,74,79},{11,49,53},{0,6,15},{111,177,173},{96,157,153},{83,136,134},{67,115,114},{51,95,94},{34,74,73},{11,49,48},{0,6,9},{113,177,163},{97,157,144},{84,136,126},{68,115,107},{52,95,88},{35,74,68},{11,49,43},{0,6,5},{114,176,153},{99,156,135},{85,135,117},{69,115,100},{53,95,81},{36,74,63},{11,48,39},{0,6,2}, -{116,176,143},{101,155,125},{86,135,109},{71,115,93},{54,95,75},{36,74,57},{11,48,35},{0,6,0},{117,175,133},{102,155,116},{87,134,101},{72,114,86},{54,94,69},{37,73,52},{11,49,30},{0,5,0},{118,175,122},{104,155,107},{88,134,93},{72,114,78},{55,94,62},{37,73,46},{11,49,24},{0,5,0},{120,174,110},{105,154,97},{89,134,83},{73,113,69},{56,93,55},{38,73,40},{11,49,18},{0,5,0}, -{122,174,98},{106,154,86},{90,134,74},{73,113,61},{56,93,47},{38,73,32},{11,49,11},{0,5,0},{123,174,86},{107,153,74},{91,133,63},{74,113,52},{56,93,40},{39,72,25},{11,48,4},{0,5,0},{124,174,75},{107,153,65},{91,133,55},{74,113,45},{57,93,32},{39,72,17},{11,48,2},{0,5,0},{125,173,65},{108,153,56},{92,133,48},{75,113,38},{58,93,25},{40,72,9},{11,48,1},{0,5,0}, -{100,170,221},{89,151,195},{76,132,171},{63,112,146},{48,92,121},{32,71,96},{12,45,66},{0,3,27},{104,170,209},{92,150,185},{79,131,162},{65,111,139},{50,91,115},{33,71,90},{12,45,62},{0,3,23},{107,170,198},{95,150,175},{81,131,154},{66,111,131},{51,91,108},{34,71,85},{12,45,58},{0,3,18},{110,169,188},{97,150,167},{82,130,146},{68,110,125},{52,91,103},{36,70,81},{13,45,54},{0,3,14}, -{112,169,179},{98,150,159},{84,130,138},{69,110,117},{53,91,97},{37,70,77},{13,45,50},{0,3,11},{114,168,169},{99,149,149},{86,129,130},{71,109,110},{54,90,91},{37,70,71},{13,45,46},{0,3,6},{116,168,159},{101,149,140},{87,129,122},{71,109,103},{55,90,85},{38,70,65},{13,45,41},{0,3,3},{117,167,149},{102,148,131},{88,128,114},{72,109,96},{56,90,78},{39,69,60},{13,44,37},{0,3,1}, -{118,167,139},{103,148,121},{88,128,106},{73,109,90},{57,90,72},{40,69,55},{13,44,33},{0,3,0},{119,166,129},{104,147,112},{89,128,98},{74,108,83},{57,89,67},{40,69,50},{14,45,28},{0,2,0},{121,166,118},{106,147,103},{90,128,90},{74,108,75},{57,89,60},{40,69,44},{14,45,22},{0,2,0},{122,165,107},{107,146,94},{91,127,81},{75,107,67},{58,89,53},{41,69,38},{14,45,16},{0,2,0}, -{124,165,96},{107,146,84},{92,127,72},{75,107,59},{58,89,45},{41,69,30},{14,45,10},{0,2,0},{126,165,84},{108,146,73},{93,126,61},{75,107,50},{58,88,38},{41,68,23},{15,44,4},{0,2,0},{126,165,73},{109,146,64},{93,126,53},{76,107,43},{59,88,31},{41,68,15},{15,44,2},{0,2,0},{127,164,64},{110,146,55},{94,126,46},{76,107,36},{60,88,24},{41,68,8},{14,44,1},{0,2,0}, -{106,160,213},{94,143,189},{80,124,166},{67,105,142},{52,86,117},{36,66,92},{13,41,63},{0,0,24},{109,160,202},{96,142,179},{83,124,157},{69,105,135},{54,86,111},{37,66,87},{13,41,59},{0,0,20},{111,160,191},{98,142,170},{84,124,149},{71,105,127},{54,86,104},{38,66,82},{13,41,55},{0,0,15},{113,160,182},{100,142,162},{86,123,142},{72,104,121},{55,85,100},{39,65,78},{14,41,51},{0,0,11}, -{115,160,174},{101,142,154},{87,123,134},{72,104,114},{56,85,94},{40,65,74},{15,41,47},{0,0,7},{117,159,164},{103,141,145},{88,122,126},{73,103,107},{57,85,88},{41,65,68},{15,41,43},{0,0,4},{119,159,154},{103,141,136},{89,122,118},{74,103,100},{58,85,82},{41,65,62},{15,41,38},{0,0,1},{120,158,144},{104,140,127},{90,121,111},{75,103,93},{59,85,75},{41,64,57},{15,40,34},{0,0,0}, -{122,158,134},{105,140,118},{91,121,103},{75,103,87},{59,85,69},{42,64,52},{16,40,30},{0,0,0},{123,157,125},{106,139,109},{92,121,95},{76,102,80},{59,84,64},{42,65,47},{17,41,26},{0,0,0},{123,157,115},{108,139,100},{92,121,87},{76,102,72},{59,84,58},{42,65,41},{17,41,20},{0,0,0},{124,157,104},{109,138,91},{93,120,78},{77,102,65},{60,84,51},{42,64,35},{16,41,14},{0,0,0}, -{126,157,93},{109,138,81},{93,120,69},{77,102,57},{60,84,44},{42,64,28},{16,41,9},{0,0,0},{128,157,81},{110,138,71},{94,119,60},{77,101,49},{60,83,37},{43,64,22},{17,40,3},{0,0,0},{128,157,72},{111,138,63},{94,119,52},{77,101,42},{60,83,30},{43,64,14},{17,40,2},{0,0,0},{129,156,63},{112,138,54},{95,119,45},{78,101,35},{60,83,23},{43,64,7},{16,40,1},{0,0,0}, -{110,150,206},{97,134,183},{84,117,160},{71,98,137},{55,80,113},{39,60,89},{16,35,61},{0,0,21},{113,150,195},{99,133,173},{86,116,151},{72,98,130},{56,80,107},{41,60,84},{17,35,57},{0,0,17},{115,150,185},{101,133,164},{87,116,143},{73,98,122},{57,80,100},{41,60,79},{18,35,53},{0,0,12},{117,150,176},{103,132,156},{89,116,136},{74,97,116},{58,79,96},{42,60,75},{19,36,49},{0,0,8}, -{119,150,168},{104,132,148},{90,116,129},{75,97,110},{58,79,90},{42,60,70},{19,36,45},{0,0,4},{121,150,158},{105,132,140},{91,115,122},{75,97,103},{59,79,84},{42,60,66},{19,36,41},{0,0,2},{121,150,149},{106,132,132},{92,115,114},{75,97,97},{59,79,79},{42,60,60},{19,36,36},{0,0,0},{122,149,140},{107,131,123},{92,114,107},{76,97,90},{60,79,73},{43,60,55},{19,36,32},{0,0,0}, -{124,149,130},{107,131,114},{92,114,99},{77,97,84},{61,79,67},{43,60,50},{19,36,28},{0,0,0},{125,148,121},{108,130,106},{93,113,92},{77,96,77},{61,78,61},{44,60,45},{20,36,24},{0,0,0},{126,148,112},{109,130,98},{94,113,85},{78,96,70},{61,78,55},{44,60,39},{20,36,18},{0,0,0},{127,147,102},{110,129,89},{95,113,76},{79,96,63},{61,78,49},{44,60,33},{19,36,12},{0,0,0}, -{128,147,90},{111,129,79},{95,113,67},{79,96,55},{61,78,42},{44,60,26},{19,36,8},{0,0,0},{129,147,79},{112,129,69},{96,112,58},{79,95,47},{62,77,35},{44,60,20},{20,36,3},{0,0,0},{129,147,71},{112,129,61},{96,112,51},{79,95,40},{62,77,28},{44,60,13},{20,36,1},{0,0,0},{130,147,62},{113,129,52},{97,112,44},{80,95,34},{62,77,21},{44,59,6},{19,36,0},{0,0,0}, -{114,140,199},{100,124,177},{87,109,154},{74,91,132},{58,74,109},{42,55,86},{19,30,58},{0,0,18},{117,140,189},{102,124,167},{89,108,146},{75,91,125},{59,74,103},{43,55,81},{20,30,54},{0,0,14},{119,140,179},{104,124,158},{91,108,138},{75,91,118},{60,74,97},{43,55,76},{20,30,50},{0,0,9},{120,140,170},{106,124,151},{92,108,131},{76,91,112},{61,73,92},{44,55,72},{21,31,46},{0,0,5}, -{121,140,162},{106,124,143},{92,108,124},{77,91,106},{61,73,87},{44,55,67},{21,31,42},{0,0,2},{123,140,153},{107,123,135},{93,107,118},{78,90,100},{61,73,81},{44,55,63},{21,31,38},{0,0,1},{124,140,144},{108,123,127},{94,107,110},{78,90,94},{61,73,76},{44,55,58},{21,31,34},{0,0,0},{124,139,135},{109,123,119},{95,107,103},{79,90,87},{62,73,70},{45,55,53},{22,31,30},{0,0,0}, -{126,139,127},{110,123,111},{95,107,96},{79,90,81},{62,73,64},{45,55,48},{22,31,26},{0,0,0},{127,139,118},{111,122,103},{95,106,89},{79,90,74},{62,72,58},{45,55,43},{22,32,22},{0,0,0},{128,139,109},{111,122,95},{95,106,82},{79,90,68},{62,72,52},{45,55,37},{22,32,16},{0,0,0},{129,138,99},{112,121,86},{96,106,74},{80,89,61},{63,72,46},{45,55,31},{22,31,10},{0,0,0}, -{129,138,88},{113,121,77},{96,106,65},{80,89,53},{63,72,40},{45,55,24},{22,31,6},{0,0,0},{130,138,77},{114,121,67},{97,105,57},{81,89,45},{63,72,33},{45,55,18},{22,32,3},{0,0,0},{130,138,70},{114,121,59},{97,105,50},{81,89,39},{63,72,26},{45,55,11},{22,32,1},{0,0,0},{131,138,62},{114,121,52},{97,105,43},{81,89,33},{63,71,19},{45,54,5},{21,32,0},{0,0,0}, -{117,131,192},{104,115,170},{89,101,149},{75,84,127},{59,67,105},{43,50,83},{22,25,55},{0,0,15},{119,131,182},{105,115,161},{91,101,141},{76,84,120},{60,67,100},{44,50,78},{22,25,51},{0,0,10},{121,131,173},{107,115,153},{92,101,133},{77,84,114},{61,67,94},{45,50,73},{22,25,47},{0,0,6},{122,131,165},{108,115,146},{93,101,127},{78,84,108},{62,67,89},{45,50,69},{23,26,43},{0,0,3}, -{123,131,157},{109,115,138},{94,101,120},{79,84,103},{62,67,84},{45,50,64},{23,26,40},{0,0,1},{124,131,148},{110,115,130},{95,100,114},{79,83,97},{63,67,78},{46,50,60},{23,26,36},{0,0,0},{125,131,139},{110,115,122},{95,100,107},{79,83,91},{63,67,73},{46,50,55},{23,26,32},{0,0,0},{126,130,131},{111,114,115},{96,100,100},{80,83,84},{63,67,67},{46,50,51},{24,26,28},{0,0,0}, -{127,130,123},{111,114,108},{96,100,93},{80,83,78},{63,67,62},{46,50,46},{24,26,24},{0,0,0},{128,130,114},{112,114,100},{96,99,86},{80,83,72},{63,67,57},{46,50,41},{24,27,19},{0,0,0},{129,130,105},{112,114,92},{96,99,79},{80,83,66},{63,67,51},{46,50,35},{24,27,13},{0,0,0},{130,129,96},{113,113,84},{97,99,72},{81,83,59},{64,67,45},{46,50,29},{24,27,7},{0,0,0}, -{130,129,86},{114,113,75},{97,99,64},{81,83,51},{64,67,39},{46,50,23},{24,27,5},{0,0,0},{131,129,76},{115,113,66},{98,98,56},{82,83,44},{64,67,32},{46,50,17},{23,28,2},{0,0,0},{131,129,69},{115,113,58},{98,98,49},{82,83,38},{64,67,25},{46,50,10},{23,28,1},{0,0,0},{132,129,61},{115,113,51},{98,98,42},{82,82,32},{64,66,18},{46,49,4},{22,28,0},{0,0,0}, -{120,121,186},{106,107,164},{92,93,143},{77,78,122},{61,61,101},{45,44,80},{24,19,53},{0,0,11},{122,121,176},{108,107,156},{93,93,137},{78,78,116},{62,61,96},{46,44,75},{24,20,49},{0,0,7},{123,121,167},{109,107,148},{94,93,129},{79,78,110},{63,61,90},{47,44,70},{24,20,45},{0,0,3},{124,121,159},{110,107,141},{95,93,123},{80,78,104},{64,61,86},{47,44,66},{25,21,41},{0,0,1}, -{125,121,152},{111,107,133},{96,93,116},{81,78,99},{64,61,81},{47,44,62},{25,21,38},{0,0,0},{126,121,143},{112,107,126},{96,93,110},{81,77,93},{64,61,76},{48,44,57},{25,21,34},{0,0,0},{127,121,135},{112,107,118},{96,93,103},{81,77,87},{64,61,70},{48,44,53},{25,21,30},{0,0,0},{128,121,127},{113,106,111},{97,92,96},{81,77,82},{64,61,65},{47,45,49},{26,22,26},{0,0,0}, -{128,121,119},{113,106,104},{97,92,90},{81,77,76},{64,61,60},{47,45,44},{26,22,22},{0,0,0},{129,121,111},{114,106,97},{98,92,83},{81,77,70},{65,61,55},{47,45,39},{26,23,17},{0,0,0},{130,121,102},{114,106,89},{98,92,77},{81,77,64},{65,61,49},{47,45,33},{26,23,11},{0,0,0},{131,120,93},{114,106,82},{99,92,70},{82,77,57},{65,61,43},{48,45,27},{26,23,6},{0,0,0}, -{131,120,84},{115,106,73},{99,92,62},{82,77,49},{65,61,37},{48,45,21},{26,23,4},{0,0,0},{132,120,74},{116,105,64},{99,91,54},{82,77,42},{65,61,30},{48,45,15},{25,24,2},{0,0,0},{132,120,67},{116,105,56},{100,91,47},{82,77,36},{65,61,23},{48,45,9},{25,24,1},{0,0,0},{133,120,59},{116,105,49},{100,91,40},{83,76,30},{65,61,17},{47,45,4},{24,24,0},{0,0,0}, -{122,112,179},{109,99,159},{93,85,138},{80,71,118},{63,55,98},{46,38,77},{25,12,50},{0,0,7},{124,112,170},{110,99,151},{95,85,132},{81,71,112},{64,55,93},{47,39,72},{25,13,46},{0,0,4},{126,112,161},{111,99,143},{96,85,125},{81,71,106},{65,55,87},{48,39,67},{25,13,43},{0,0,1},{127,112,154},{112,99,136},{97,85,119},{82,71,100},{65,55,83},{48,39,63},{26,14,39},{0,0,0}, -{127,112,147},{112,99,129},{97,85,113},{82,71,95},{65,55,78},{48,39,59},{26,14,35},{0,0,0},{128,112,139},{113,99,122},{97,86,107},{82,71,89},{65,55,73},{49,39,55},{26,15,31},{0,0,0},{129,112,131},{113,99,114},{97,86,100},{82,71,84},{65,55,68},{49,39,51},{26,15,28},{0,0,0},{129,112,123},{114,98,107},{98,85,93},{82,70,79},{65,55,63},{48,39,46},{27,16,24},{0,0,0}, -{129,112,115},{114,98,101},{98,85,87},{82,70,73},{65,55,59},{48,39,42},{27,17,20},{0,0,0},{130,112,108},{115,98,94},{99,85,80},{82,70,67},{66,56,54},{48,40,38},{27,18,15},{0,0,0},{131,112,100},{115,98,86},{99,85,74},{82,70,61},{66,56,48},{48,40,32},{27,18,10},{0,0,0},{132,111,91},{115,98,79},{100,85,68},{83,70,55},{66,55,42},{49,40,26},{27,19,5},{0,0,0}, -{132,111,82},{116,98,71},{100,85,60},{83,70,48},{66,55,35},{49,40,20},{27,19,3},{0,0,0},{133,111,73},{117,98,63},{100,84,52},{83,70,41},{66,55,29},{49,40,14},{26,19,1},{0,0,0},{133,111,66},{117,98,55},{101,84,46},{83,70,35},{66,55,22},{49,40,8},{26,19,1},{0,0,0},{134,111,58},{117,97,48},{101,84,39},{84,70,29},{66,55,16},{48,40,3},{25,19,0},{0,0,0}, -{125,102,173},{110,90,153},{95,77,133},{81,63,114},{65,48,94},{48,31,74},{26,7,47},{0,0,4},{126,102,164},{111,90,146},{97,77,127},{82,63,108},{66,48,89},{49,32,69},{27,8,43},{0,0,2},{127,102,156},{112,90,138},{98,77,120},{83,63,102},{66,48,84},{49,32,64},{27,8,40},{0,0,0},{128,102,149},{113,90,131},{98,77,114},{83,63,97},{66,48,80},{49,32,60},{28,9,36},{0,0,0}, -{129,102,142},{113,90,124},{98,77,109},{83,63,92},{66,48,75},{49,32,56},{28,9,33},{0,0,0},{130,103,134},{114,90,118},{99,78,103},{83,64,86},{66,49,70},{49,33,52},{28,10,29},{0,0,0},{130,103,126},{114,90,111},{99,78,97},{83,64,81},{66,49,65},{49,33,48},{28,10,26},{0,0,0},{130,102,119},{114,90,104},{99,77,90},{83,64,76},{66,49,60},{49,33,44},{28,11,22},{0,0,0}, -{131,102,112},{114,90,98},{99,77,84},{83,64,70},{66,49,56},{49,33,40},{28,11,18},{0,0,0},{132,103,105},{115,90,91},{100,77,78},{84,64,64},{67,50,51},{49,34,35},{27,12,13},{0,0,0},{133,103,97},{115,90,84},{100,77,72},{84,64,59},{67,50,46},{49,34,30},{27,12,8},{0,0,0},{134,102,88},{116,90,76},{100,77,65},{83,64,53},{66,49,40},{49,34,24},{27,13,5},{0,0,0}, -{134,102,80},{116,90,68},{100,77,58},{83,64,46},{66,49,33},{49,34,18},{27,13,3},{0,0,0},{134,102,71},{117,90,61},{101,77,50},{84,63,40},{67,49,27},{49,34,12},{26,13,1},{0,0,0},{134,102,64},{117,90,54},{101,77,44},{84,63,34},{67,49,21},{49,34,7},{26,13,1},{0,0,0},{135,102,57},{118,89,48},{102,77,38},{84,64,28},{67,49,15},{49,34,3},{25,13,0},{0,0,0}, -{127,92,167},{112,81,147},{97,69,128},{83,55,109},{66,40,90},{50,23,70},{28,3,45},{0,0,1},{128,92,158},{113,81,140},{99,69,122},{84,56,104},{67,41,85},{50,24,66},{29,3,41},{0,0,0},{129,92,150},{114,81,133},{100,69,116},{84,56,98},{68,41,80},{50,25,62},{29,3,38},{0,0,0},{130,92,143},{115,81,127},{100,69,110},{84,56,94},{68,41,76},{50,25,58},{29,3,34},{0,0,0}, -{131,92,136},{115,81,120},{100,69,105},{84,56,89},{68,41,72},{50,25,54},{29,3,31},{0,0,0},{132,93,129},{116,81,114},{100,69,99},{85,56,84},{68,42,68},{50,26,50},{29,4,27},{0,0,0},{132,93,122},{116,81,108},{100,69,94},{85,56,79},{68,42,63},{50,26,46},{29,4,24},{0,0,0},{132,93,115},{116,81,101},{101,69,88},{84,56,74},{67,42,58},{50,27,42},{29,4,20},{0,0,0}, -{133,93,109},{116,81,95},{101,69,82},{84,56,68},{67,42,54},{50,27,38},{29,4,16},{0,0,0},{133,93,102},{116,81,88},{101,70,76},{85,56,62},{68,43,49},{50,27,33},{28,5,11},{0,0,0},{134,93,94},{116,81,81},{101,70,70},{85,56,57},{68,43,44},{50,27,28},{28,5,6},{0,0,0},{135,92,86},{117,81,74},{101,69,63},{84,56,51},{67,43,38},{50,28,22},{28,6,4},{0,0,0}, -{135,92,78},{117,81,66},{101,69,56},{84,56,44},{67,43,31},{50,28,16},{28,6,2},{0,0,0},{135,92,69},{118,81,59},{102,69,48},{84,56,38},{67,43,25},{50,28,10},{27,6,1},{0,0,0},{135,92,62},{118,81,53},{102,69,42},{84,56,32},{67,43,19},{50,28,6},{27,6,1},{0,0,0},{136,92,56},{118,81,47},{103,69,37},{85,56,27},{68,43,13},{50,28,3},{26,7,0},{0,0,0}, -{129,81,161},{113,70,142},{99,58,124},{83,45,105},{67,30,87},{51,14,67},{29,1,42},{0,0,0},{131,81,153},{114,70,135},{100,59,118},{84,46,100},{68,31,82},{51,14,63},{29,1,38},{0,0,0},{131,81,145},{115,70,128},{100,59,112},{84,46,95},{68,32,77},{51,15,59},{29,1,35},{0,0,0},{132,81,138},{116,70,122},{101,59,106},{85,46,91},{68,32,73},{51,16,55},{29,1,31},{0,0,0}, -{132,81,132},{116,70,116},{101,59,101},{85,46,86},{68,32,69},{51,16,51},{29,1,28},{0,0,0},{133,82,125},{116,71,110},{101,59,95},{85,47,81},{68,33,65},{51,17,47},{29,1,25},{0,0,0},{133,82,118},{116,71,104},{101,59,90},{85,47,76},{68,34,60},{51,18,43},{29,1,21},{0,0,0},{134,82,111},{116,71,98},{101,60,85},{85,48,71},{68,34,55},{51,18,39},{29,2,17},{0,0,0}, -{134,82,105},{116,71,92},{101,60,79},{85,48,65},{68,34,51},{51,18,35},{29,2,13},{0,0,0},{134,82,98},{117,71,85},{101,60,73},{85,48,59},{68,35,46},{50,19,31},{28,2,9},{0,0,0},{134,82,91},{117,71,78},{101,60,67},{85,48,54},{68,35,41},{50,19,26},{28,2,6},{0,0,0},{135,82,83},{117,71,72},{101,60,60},{84,48,48},{67,35,35},{50,20,20},{28,3,4},{0,0,0}, -{135,82,75},{117,71,64},{101,60,53},{84,48,43},{67,35,30},{50,20,15},{28,3,2},{0,0,0},{135,82,68},{118,71,57},{102,60,47},{85,48,37},{67,36,24},{50,20,8},{27,3,1},{0,0,0},{135,82,61},{118,71,51},{102,60,41},{85,48,31},{67,36,18},{50,20,5},{27,3,1},{0,0,0},{136,82,55},{119,71,46},{103,61,36},{85,48,26},{68,36,12},{50,21,3},{26,3,0},{0,0,0}, -{130,69,155},{115,58,137},{100,48,120},{85,35,101},{68,20,83},{52,4,64},{28,0,40},{0,0,0},{132,69,148},{116,59,131},{101,48,114},{85,36,96},{68,21,78},{52,5,60},{28,0,36},{0,0,0},{133,69,140},{117,59,124},{101,48,108},{85,36,91},{68,22,73},{52,5,56},{28,0,33},{0,0,0},{134,69,134},{117,59,118},{102,49,102},{86,37,87},{69,23,69},{52,6,52},{28,0,29},{0,0,0}, -{134,69,127},{117,59,112},{102,49,97},{86,37,82},{69,23,65},{52,6,48},{28,0,26},{0,0,0},{134,70,121},{117,60,106},{102,49,91},{85,38,77},{68,24,61},{52,8,44},{28,0,22},{0,0,0},{134,71,114},{117,60,100},{102,49,86},{85,38,72},{68,25,56},{52,8,41},{28,0,18},{0,0,0},{134,71,107},{117,61,94},{102,50,81},{86,39,67},{69,26,52},{52,9,37},{28,1,13},{0,0,0}, -{134,71,101},{117,61,88},{102,50,75},{86,39,62},{69,26,48},{52,10,33},{28,1,10},{0,0,0},{135,71,94},{118,61,82},{102,50,70},{85,39,57},{68,27,44},{51,11,29},{28,1,7},{0,0,0},{135,71,88},{118,61,76},{102,50,64},{85,39,52},{68,27,39},{51,11,24},{28,1,5},{0,0,0},{135,71,81},{118,61,70},{102,51,58},{85,40,46},{68,28,33},{51,12,18},{27,1,3},{0,0,0}, -{135,71,73},{118,61,62},{102,51,51},{85,40,41},{68,28,28},{51,12,13},{27,1,1},{0,0,0},{136,72,66},{119,62,55},{103,51,45},{86,41,35},{68,29,23},{51,13,7},{26,1,0},{0,0,0},{136,72,60},{119,62,49},{103,51,40},{86,41,30},{68,29,17},{51,13,4},{26,1,0},{0,0,0},{137,71,54},{120,62,44},{103,52,35},{86,41,25},{68,29,11},{51,14,2},{26,1,0},{0,0,0}, -{131,55,149},{116,45,131},{101,33,115},{86,20,97},{69,10,80},{52,2,62},{27,0,38},{0,0,0},{133,55,142},{117,45,125},{102,34,109},{86,22,93},{69,11,75},{53,2,58},{27,0,34},{0,0,0},{134,55,135},{118,45,119},{102,35,103},{86,22,88},{69,11,71},{53,2,54},{27,0,31},{0,0,0},{134,55,129},{118,46,113},{103,35,99},{86,23,84},{69,12,67},{52,3,50},{27,0,27},{0,0,0}, -{134,56,123},{118,46,108},{103,36,94},{86,24,79},{69,12,63},{52,3,46},{27,0,24},{0,0,0},{135,57,117},{118,47,102},{103,37,88},{86,25,75},{69,13,59},{52,4,42},{28,0,20},{0,0,0},{135,58,111},{118,48,97},{103,37,83},{86,26,70},{69,14,54},{52,4,39},{28,0,16},{0,0,0},{135,58,104},{118,49,91},{102,38,78},{86,27,65},{69,15,50},{52,5,35},{27,1,12},{0,0,0}, -{135,58,98},{118,49,85},{102,39,73},{86,28,60},{69,15,46},{52,5,31},{27,1,9},{0,0,0},{135,59,91},{118,49,80},{103,39,68},{85,28,55},{68,16,42},{52,5,27},{27,1,6},{0,0,0},{135,59,85},{118,49,74},{103,40,62},{85,28,50},{68,16,37},{52,5,22},{27,1,4},{0,0,0},{136,59,79},{119,50,68},{103,41,56},{85,29,44},{68,17,31},{51,6,16},{26,1,2},{0,0,0}, -{136,59,72},{119,50,61},{103,41,50},{85,30,39},{68,17,26},{51,6,11},{26,1,1},{0,0,0},{137,60,65},{119,51,54},{104,41,44},{86,31,34},{68,18,21},{51,6,6},{25,1,0},{0,0,0},{137,60,59},{119,51,48},{104,41,39},{86,31,29},{68,18,15},{51,6,4},{25,1,0},{0,0,0},{137,60,53},{120,51,43},{104,42,34},{86,31,24},{68,18,10},{51,7,2},{25,1,0},{0,0,0}, -{133,40,144},{117,30,126},{102,17,110},{87,4,93},{70,0,76},{53,0,59},{25,0,35},{0,0,0},{134,40,137},{118,31,120},{103,19,105},{87,6,89},{70,0,72},{53,0,55},{26,0,31},{0,0,0},{135,40,130},{119,31,114},{103,20,99},{87,7,84},{70,0,68},{53,0,52},{26,0,28},{0,0,0},{136,41,124},{119,32,109},{103,21,95},{87,9,80},{70,1,64},{53,0,48},{26,0,24},{0,0,0}, -{136,42,119},{119,32,104},{103,22,90},{87,10,76},{70,1,60},{53,0,44},{26,0,21},{0,0,0},{136,43,113},{119,34,98},{104,23,85},{87,11,72},{70,2,56},{53,0,40},{27,0,17},{0,0,0},{136,44,107},{119,35,93},{104,24,80},{87,13,67},{70,2,52},{53,0,36},{27,0,13},{0,0,0},{136,45,100},{120,36,88},{103,25,75},{87,14,62},{70,3,48},{53,0,32},{26,0,10},{0,0,0}, -{136,45,94},{120,36,82},{103,26,71},{87,15,58},{70,3,44},{53,0,28},{26,0,7},{0,0,0},{136,46,88},{119,37,77},{104,27,66},{86,16,53},{69,4,40},{52,0,24},{26,0,5},{0,0,0},{136,46,82},{119,37,71},{104,28,60},{86,16,48},{69,4,35},{52,0,19},{26,0,3},{0,0,0},{137,47,76},{120,37,65},{104,29,54},{86,17,42},{69,5,29},{52,0,13},{25,0,1},{0,0,0}, -{137,47,70},{120,38,59},{104,29,49},{86,18,37},{69,5,24},{52,0,9},{25,0,1},{0,0,0},{138,47,63},{120,39,53},{104,30,43},{87,19,32},{69,6,19},{51,0,5},{24,0,0},{0,0,0},{138,47,57},{120,39,47},{104,30,38},{87,19,27},{69,6,13},{51,0,3},{24,0,0},{0,0,0},{137,47,52},{120,40,42},{105,31,33},{87,20,22},{69,6,8},{51,0,1},{23,0,0},{0,0,0}, -{15,192,243},{14,169,214},{11,147,187},{8,126,160},{5,103,133},{1,81,106},{0,55,75},{0,16,34},{18,191,230},{16,168,202},{13,146,177},{10,125,151},{6,103,126},{1,81,100},{0,54,70},{0,15,31},{20,190,218},{18,167,191},{15,146,168},{12,125,143},{7,103,119},{2,81,94},{0,54,65},{0,14,28},{22,189,206},{19,167,182},{16,145,159},{12,124,136},{8,102,113},{2,81,90},{0,54,61},{0,14,24}, -{23,189,195},{20,167,173},{17,145,150},{13,124,129},{9,102,106},{3,81,85},{0,54,57},{0,14,21},{24,188,183},{21,166,163},{17,144,141},{14,123,121},{9,102,100},{4,80,79},{0,54,53},{0,14,15},{24,187,172},{22,165,153},{18,144,133},{15,123,113},{10,102,94},{4,80,74},{0,54,48},{0,14,11},{25,187,162},{22,164,144},{19,143,125},{15,122,106},{10,101,87},{5,80,68},{1,54,44},{0,13,7}, -{30,186,152},{27,164,134},{22,143,117},{15,122,99},{11,101,81},{6,80,62},{1,54,40},{0,12,4},{40,185,140},{37,163,124},{27,142,108},{16,121,92},{11,101,74},{6,80,57},{1,54,35},{0,12,1},{49,185,129},{44,163,113},{32,142,99},{18,121,84},{11,101,67},{6,80,51},{1,54,29},{0,12,0},{57,184,117},{48,163,103},{38,142,89},{22,120,76},{12,100,60},{7,79,44},{1,54,23},{0,11,0}, -{62,184,104},{52,163,92},{40,142,80},{24,120,67},{12,100,52},{7,79,37},{1,54,16},{0,11,0},{66,184,92},{55,162,82},{41,141,70},{25,120,58},{12,99,45},{7,78,31},{1,54,10},{0,11,0},{69,184,83},{57,162,73},{43,141,62},{27,120,51},{13,99,39},{7,78,24},{1,54,6},{0,11,0},{71,183,73},{60,162,64},{45,141,54},{29,119,44},{15,99,33},{7,78,18},{1,53,2},{0,11,0}, -{19,181,235},{17,160,207},{14,140,181},{11,119,155},{7,97,128},{3,76,102},{0,51,72},{0,9,31},{21,180,223},{19,159,196},{15,139,171},{12,118,147},{8,98,122},{3,76,97},{0,50,67},{0,8,28},{23,180,211},{21,159,186},{18,139,163},{13,118,139},{9,98,115},{4,76,91},{0,50,63},{0,7,25},{30,179,200},{25,158,177},{21,138,154},{15,117,132},{10,97,109},{4,76,87},{1,50,59},{0,7,21}, -{37,179,189},{30,158,168},{24,138,146},{16,117,125},{10,97,103},{5,76,82},{1,50,55},{0,7,18},{40,178,178},{33,157,158},{28,137,137},{19,116,117},{11,96,97},{6,75,76},{1,50,51},{0,7,13},{42,177,167},{36,157,149},{30,137,129},{21,116,110},{13,96,91},{6,75,71},{1,50,46},{0,7,8},{45,177,158},{38,156,140},{31,136,121},{23,116,103},{13,96,84},{7,75,65},{1,50,42},{0,7,4}, -{49,176,148},{42,156,130},{34,136,113},{25,116,96},{14,96,78},{7,75,60},{1,50,38},{0,6,2},{56,175,137},{48,155,120},{38,135,105},{26,115,89},{15,95,71},{7,75,54},{1,50,33},{0,6,0},{61,175,126},{53,155,110},{42,135,96},{29,115,81},{16,95,65},{7,75,49},{1,50,27},{0,6,0},{66,174,114},{57,154,100},{46,135,87},{31,114,73},{17,95,58},{9,74,42},{1,50,21},{0,6,0}, -{70,174,102},{60,154,90},{48,135,78},{33,114,65},{18,95,50},{9,74,35},{1,50,14},{0,6,0},{74,174,90},{63,154,79},{50,134,68},{34,114,56},{20,94,43},{10,74,29},{1,50,8},{0,6,0},{76,174,81},{64,154,71},{50,134,60},{35,114,49},{20,94,37},{10,74,22},{1,50,5},{0,6,0},{77,174,71},{66,154,62},{53,134,53},{37,113,43},{22,94,31},{10,74,16},{1,49,2},{0,6,0}, -{23,171,227},{21,151,200},{18,132,174},{14,111,149},{10,91,124},{5,71,99},{1,46,69},{0,2,29},{26,170,215},{23,151,189},{19,131,165},{15,111,142},{10,92,118},{6,71,94},{1,46,65},{0,2,25},{29,170,204},{25,151,180},{21,131,157},{16,111,134},{11,92,112},{6,71,88},{1,46,61},{0,2,22},{40,169,193},{33,150,171},{26,131,149},{18,111,128},{12,91,106},{7,70,84},{1,46,57},{0,1,18}, -{50,169,182},{41,150,162},{31,131,142},{20,111,121},{12,91,100},{7,70,80},{1,46,53},{0,1,15},{55,168,172},{45,149,153},{37,130,134},{24,110,114},{13,90,94},{7,70,74},{1,46,49},{0,1,11},{59,168,162},{49,149,145},{42,130,126},{27,110,107},{15,90,88},{8,70,68},{1,46,44},{0,1,6},{62,168,153},{53,148,136},{43,129,118},{31,109,100},{16,90,82},{8,70,63},{1,46,40},{0,1,2}, -{66,167,143},{56,148,126},{46,129,110},{34,109,93},{18,90,76},{8,70,58},{1,46,36},{0,1,0},{70,166,134},{59,147,117},{49,128,102},{36,108,86},{19,89,69},{8,70,52},{1,46,31},{0,1,0},{73,166,123},{63,147,107},{52,128,94},{38,108,79},{20,89,63},{8,70,47},{1,46,25},{0,1,0},{75,165,112},{65,146,98},{53,127,85},{40,108,71},{22,89,57},{9,70,41},{1,46,19},{0,1,0}, -{78,165,101},{68,146,88},{55,127,76},{41,108,63},{24,89,49},{10,70,34},{1,46,13},{0,1,0},{82,165,89},{70,146,77},{57,127,67},{42,107,55},{27,88,42},{11,70,28},{1,46,7},{0,1,0},{83,165,80},{71,146,69},{58,127,59},{43,107,48},{28,88,36},{11,70,21},{1,46,4},{0,1,0},{84,165,70},{72,146,61},{59,127,52},{45,107,42},{29,88,30},{12,69,15},{1,46,2},{0,1,0}, -{36,162,220},{32,144,194},{28,125,170},{19,105,145},{11,87,120},{6,67,95},{1,42,66},{0,1,27},{42,161,208},{37,143,184},{31,124,161},{23,105,138},{13,87,114},{7,67,90},{1,42,62},{0,1,23},{48,161,198},{41,143,175},{34,124,153},{25,105,130},{15,87,108},{7,67,85},{1,42,58},{0,1,18},{55,161,188},{46,143,166},{38,124,145},{28,105,124},{17,87,102},{9,66,81},{1,42,54},{0,1,14}, -{61,161,178},{51,143,158},{42,124,138},{30,105,117},{18,87,97},{9,66,76},{1,42,50},{0,1,11},{65,160,168},{55,142,149},{45,123,130},{33,104,110},{19,86,91},{10,66,71},{1,42,46},{0,1,7},{68,160,158},{57,142,141},{48,123,122},{36,104,104},{21,86,85},{10,66,66},{1,42,42},{0,1,4},{70,159,149},{61,141,132},{50,122,114},{38,104,97},{23,86,79},{10,66,61},{1,42,38},{0,1,1}, -{74,159,139},{63,141,122},{52,122,106},{40,104,91},{25,86,73},{11,66,56},{1,42,34},{0,1,0},{76,158,130},{65,140,113},{55,121,99},{41,103,84},{25,85,67},{11,66,50},{2,42,29},{0,0,0},{79,158,119},{68,140,104},{57,121,91},{43,103,76},{26,85,61},{11,66,45},{2,42,23},{0,0,0},{81,158,109},{69,139,95},{58,121,83},{45,103,69},{28,85,55},{12,66,39},{2,42,17},{0,0,0}, -{83,158,98},{71,139,86},{59,121,74},{45,103,61},{29,85,47},{12,66,32},{2,42,11},{0,0,0},{85,157,86},{74,139,75},{61,120,65},{46,102,53},{31,84,40},{13,66,26},{2,42,5},{0,0,0},{86,157,78},{74,139,67},{61,120,57},{47,102,46},{31,84,34},{13,66,19},{2,42,3},{0,0,0},{87,157,69},{75,139,60},{63,120,50},{48,102,40},{32,84,29},{14,65,14},{2,42,1},{0,0,0}, -{49,153,212},{43,136,188},{37,118,165},{25,99,141},{15,82,117},{9,63,92},{1,38,63},{0,0,24},{57,153,201},{50,135,179},{42,117,156},{31,99,134},{18,82,111},{9,62,87},{1,38,59},{0,0,20},{64,153,191},{55,135,170},{45,117,148},{35,99,126},{20,82,104},{9,62,82},{1,38,55},{0,0,15},{67,153,182},{58,135,161},{49,117,141},{38,99,120},{23,82,99},{10,62,78},{1,38,51},{0,0,11}, -{71,153,173},{61,135,153},{51,117,134},{40,99,113},{25,82,94},{11,62,73},{2,38,47},{0,0,7},{73,152,163},{63,134,145},{53,116,126},{41,99,107},{26,81,88},{12,62,68},{2,38,43},{0,0,4},{76,152,154},{66,134,137},{55,116,118},{42,99,101},{28,81,82},{12,62,63},{2,38,39},{0,0,2},{79,151,145},{67,133,128},{56,115,111},{44,98,94},{29,81,76},{13,62,58},{2,38,35},{0,0,1}, -{81,151,135},{70,133,119},{58,115,103},{46,98,88},{30,81,70},{14,62,53},{2,38,31},{0,0,0},{82,150,126},{71,132,110},{60,115,96},{46,98,81},{31,80,64},{14,62,48},{3,38,26},{0,0,0},{84,150,116},{73,132,101},{61,115,88},{47,98,73},{32,80,58},{14,62,42},{3,38,21},{0,0,0},{86,150,106},{74,131,92},{62,114,80},{49,97,66},{34,80,52},{15,62,36},{3,38,15},{0,0,0}, -{88,150,95},{76,131,83},{63,114,71},{50,97,58},{34,80,45},{15,62,30},{3,38,10},{0,0,0},{90,149,84},{78,132,74},{65,114,62},{51,97,51},{35,79,39},{16,62,24},{3,38,4},{0,0,0},{90,149,76},{78,132,66},{65,114,56},{51,97,45},{35,79,33},{16,62,18},{3,38,2},{0,0,0},{91,149,68},{79,131,59},{66,113,49},{52,97,39},{36,79,27},{17,61,12},{3,38,1},{0,0,0}, -{62,143,205},{54,127,182},{47,111,159},{35,93,136},{23,76,113},{11,57,89},{2,33,61},{0,0,21},{67,143,194},{59,126,173},{50,110,151},{39,93,129},{26,76,107},{12,57,84},{3,33,57},{0,0,17},{72,143,185},{63,126,164},{53,110,143},{42,93,122},{28,76,100},{13,57,79},{3,33,53},{0,0,12},{75,143,176},{66,126,156},{56,110,136},{44,93,116},{30,76,95},{14,58,75},{4,33,49},{0,0,8}, -{78,143,167},{67,126,148},{57,110,129},{45,93,109},{30,76,90},{15,58,70},{4,33,45},{0,0,5},{80,143,157},{69,125,139},{59,109,122},{46,93,103},{32,75,84},{16,58,66},{4,34,41},{0,0,2},{82,143,149},{72,125,131},{60,109,114},{47,93,97},{33,75,79},{17,58,61},{4,34,37},{0,0,1},{84,142,140},{73,124,123},{61,108,107},{49,92,91},{34,75,74},{18,58,56},{4,34,33},{0,0,0}, -{85,142,131},{75,124,115},{62,108,100},{50,92,85},{35,75,68},{19,58,51},{4,34,29},{0,0,0},{87,141,122},{76,124,107},{64,108,93},{51,92,78},{36,74,62},{19,57,46},{4,34,24},{0,0,0},{89,141,113},{77,124,99},{65,108,85},{52,92,71},{37,74,56},{19,57,40},{4,34,19},{0,0,0},{91,141,103},{78,123,90},{66,107,78},{53,91,64},{38,74,50},{20,57,34},{4,34,13},{0,0,0}, -{92,141,93},{79,123,81},{67,107,69},{53,91,56},{38,74,43},{20,57,28},{4,34,8},{0,0,0},{94,140,82},{81,123,72},{69,107,60},{54,91,49},{39,74,37},{21,57,22},{5,34,3},{0,0,0},{94,140,74},{81,123,64},{69,107,54},{55,91,43},{39,74,31},{21,57,16},{5,34,2},{0,0,0},{95,140,67},{82,123,57},{70,107,48},{56,91,38},{39,74,25},{21,57,10},{4,34,1},{0,0,0}, -{73,134,198},{63,118,176},{54,103,154},{44,87,131},{30,70,109},{14,52,86},{3,28,58},{0,0,18},{76,134,188},{66,118,167},{57,103,146},{46,87,124},{33,70,103},{16,52,81},{4,28,54},{0,0,14},{79,134,179},{70,118,158},{60,103,138},{48,87,117},{35,70,97},{18,52,76},{4,28,50},{0,0,9},{81,134,170},{72,118,151},{61,102,131},{49,87,112},{36,70,92},{19,53,72},{5,28,46},{0,0,5}, -{83,134,161},{73,118,143},{62,102,124},{50,87,106},{36,70,87},{19,53,67},{5,28,42},{0,0,2},{86,134,152},{75,117,135},{64,102,118},{51,87,100},{37,70,81},{20,53,63},{5,29,38},{0,0,1},{88,134,144},{76,117,127},{64,102,111},{52,87,94},{38,70,76},{21,53,58},{5,29,34},{0,0,0},{89,133,136},{77,116,119},{65,102,104},{53,86,88},{39,70,71},{22,53,53},{5,29,30},{0,0,0}, -{91,133,128},{79,116,111},{67,102,97},{53,86,82},{39,70,65},{23,53,49},{5,29,26},{0,0,0},{92,133,119},{80,116,104},{68,101,90},{54,86,75},{39,69,59},{23,52,44},{6,30,22},{0,0,0},{94,133,110},{80,116,96},{69,101,82},{55,86,69},{40,69,53},{23,52,38},{6,30,17},{0,0,0},{95,132,100},{81,115,87},{70,101,75},{56,85,62},{41,69,47},{23,52,32},{5,30,11},{0,0,0}, -{95,132,90},{82,115,79},{70,101,67},{56,85,54},{41,69,41},{23,52,26},{5,30,7},{0,0,0},{97,131,80},{84,115,70},{71,101,59},{57,85,47},{42,69,35},{24,52,20},{6,30,3},{0,0,0},{97,131,73},{84,115,62},{72,101,52},{57,85,41},{42,69,29},{24,52,14},{6,30,2},{0,0,0},{98,132,66},{85,115,55},{73,101,46},{58,85,36},{43,69,24},{24,52,8},{6,30,1},{0,0,0}, -{79,125,192},{69,111,169},{59,96,149},{48,81,127},{35,65,105},{19,47,83},{5,23,55},{0,0,15},{82,125,182},{72,110,161},{62,96,141},{50,81,120},{37,65,99},{21,47,78},{5,23,51},{0,0,11},{85,125,173},{74,110,153},{64,96,133},{51,81,113},{38,65,93},{23,47,73},{6,23,48},{0,0,6},{87,125,165},{76,110,146},{66,95,127},{52,81,108},{39,65,89},{23,48,69},{7,24,44},{0,0,3}, -{89,125,156},{77,110,138},{67,95,120},{53,81,103},{40,65,84},{23,48,64},{7,24,40},{0,0,1},{90,125,148},{79,110,131},{68,95,114},{54,81,97},{41,65,78},{24,48,60},{7,24,36},{0,0,0},{92,125,140},{79,110,123},{68,95,108},{54,81,91},{41,65,73},{25,48,55},{7,24,32},{0,0,0},{93,124,132},{80,109,116},{69,95,101},{55,80,85},{42,65,68},{26,48,51},{7,25,28},{0,0,0}, -{94,124,124},{82,109,108},{69,95,94},{56,80,79},{42,65,62},{26,48,47},{7,25,24},{0,0,0},{95,124,115},{83,109,101},{70,94,87},{56,80,73},{42,64,57},{26,47,42},{7,26,20},{0,0,0},{96,124,107},{84,109,93},{71,94,80},{57,80,67},{43,64,52},{26,47,37},{7,26,15},{0,0,0},{97,124,97},{85,108,85},{72,94,73},{58,80,60},{44,64,46},{27,47,31},{7,26,9},{0,0,0}, -{98,124,88},{85,108,77},{73,94,65},{58,80,53},{44,64,40},{27,47,25},{7,26,6},{0,0,0},{99,123,79},{87,108,68},{73,94,58},{59,80,46},{44,64,34},{27,47,19},{7,26,2},{0,0,0},{99,123,72},{87,108,61},{74,94,51},{59,80,40},{44,64,28},{27,47,13},{7,26,1},{0,0,0},{100,123,65},{87,108,54},{74,94,45},{60,80,35},{44,64,23},{27,47,7},{7,26,0},{0,0,0}, -{86,117,186},{75,103,164},{64,90,144},{52,75,123},{39,59,101},{23,42,80},{7,17,53},{0,0,12},{88,117,176},{77,103,156},{66,89,137},{54,75,116},{41,59,95},{25,42,75},{8,18,49},{0,0,8},{89,117,167},{78,103,148},{68,89,129},{55,75,109},{42,59,90},{27,42,70},{8,18,46},{0,0,3},{91,117,160},{79,103,141},{69,89,123},{56,75,104},{43,59,86},{28,42,66},{8,19,42},{0,0,1}, -{93,117,152},{80,103,134},{69,89,116},{57,75,99},{43,59,81},{28,42,62},{8,19,38},{0,0,0},{94,117,144},{82,103,127},{70,89,110},{57,75,93},{44,59,75},{29,42,58},{8,19,34},{0,0,0},{95,117,136},{83,103,119},{71,89,104},{57,75,87},{44,59,70},{29,42,53},{8,19,30},{0,0,0},{96,116,128},{84,103,112},{72,89,97},{58,74,82},{45,59,65},{29,42,49},{8,20,26},{0,0,0}, -{97,116,120},{85,103,105},{72,89,91},{58,74,76},{45,59,60},{29,42,45},{8,20,22},{0,0,0},{98,116,112},{86,102,98},{73,88,84},{59,74,71},{45,59,55},{29,43,40},{9,21,18},{0,0,0},{99,116,104},{86,102,90},{74,88,78},{59,74,65},{45,59,50},{29,43,35},{8,21,13},{0,0,0},{100,116,95},{87,102,83},{75,88,71},{60,74,58},{46,59,44},{29,43,29},{8,22,7},{0,0,0}, -{100,116,86},{88,102,75},{75,88,63},{60,74,51},{46,59,38},{29,43,23},{8,22,4},{0,0,0},{101,115,77},{89,102,66},{75,88,56},{61,74,44},{46,59,32},{29,43,17},{8,22,2},{0,0,0},{101,115,70},{89,102,59},{76,88,49},{61,74,38},{46,59,26},{29,43,11},{8,22,1},{0,0,0},{102,115,63},{89,101,52},{76,88,43},{62,74,33},{46,59,21},{30,43,5},{8,22,0},{0,0,0}, -{90,108,179},{79,96,159},{67,83,139},{56,68,118},{43,52,97},{27,36,77},{8,10,50},{0,0,8},{92,108,170},{81,96,152},{70,82,132},{57,68,112},{44,53,92},{28,37,72},{9,11,46},{0,0,5},{93,108,162},{83,96,144},{71,82,124},{58,68,105},{45,53,87},{29,37,68},{9,11,43},{0,0,1},{95,108,155},{84,96,137},{72,82,119},{59,68,101},{45,53,83},{30,37,64},{9,12,39},{0,0,0}, -{96,108,147},{84,96,129},{72,82,113},{59,68,96},{45,53,78},{31,37,60},{10,12,36},{0,0,0},{97,108,139},{85,96,123},{73,82,107},{60,68,90},{46,53,72},{31,37,55},{10,13,32},{0,0,0},{97,108,131},{85,96,115},{73,82,100},{60,68,84},{46,53,67},{31,37,51},{10,13,28},{0,0,0},{98,108,124},{86,96,108},{74,82,93},{61,67,79},{46,53,63},{31,37,47},{10,14,24},{0,0,0}, -{100,108,116},{87,96,101},{74,82,87},{61,67,73},{46,53,59},{31,37,43},{11,15,20},{0,0,0},{101,108,109},{87,95,95},{75,82,81},{61,68,68},{47,54,54},{31,38,38},{11,16,16},{0,0,0},{101,108,101},{88,95,87},{75,82,75},{61,68,62},{47,54,49},{31,38,33},{11,16,11},{0,0,0},{102,108,92},{89,95,80},{76,82,69},{62,68,56},{47,53,43},{31,38,27},{10,17,6},{0,0,0}, -{102,108,84},{89,95,72},{76,82,61},{62,68,50},{47,53,37},{31,38,22},{10,17,3},{0,0,0},{103,107,75},{90,95,65},{77,81,54},{63,68,43},{47,54,31},{32,38,16},{10,17,1},{0,0,0},{103,107,68},{90,95,58},{77,81,48},{63,68,37},{47,54,25},{32,38,10},{10,17,1},{0,0,0},{104,107,62},{91,94,51},{77,81,42},{63,67,32},{47,54,20},{31,38,4},{9,17,0},{0,0,0}, -{94,99,173},{83,88,153},{71,75,134},{59,61,114},{45,46,94},{31,29,74},{8,5,48},{0,0,5},{95,99,164},{84,88,146},{73,75,127},{61,61,108},{46,46,89},{31,30,69},{9,6,44},{0,0,3},{96,99,156},{86,88,139},{74,75,120},{61,61,102},{47,47,84},{31,30,65},{10,7,41},{0,0,0},{98,99,150},{87,88,132},{74,75,114},{62,61,98},{48,47,80},{32,31,61},{11,7,37},{0,0,0}, -{99,99,142},{87,88,124},{74,75,109},{62,61,93},{48,47,75},{33,31,57},{11,7,33},{0,0,0},{100,100,134},{88,88,118},{75,75,103},{62,62,87},{48,47,70},{33,31,53},{12,8,30},{0,0,0},{100,100,127},{88,88,112},{75,75,97},{62,62,81},{48,47,65},{33,31,48},{12,8,26},{0,0,0},{101,100,120},{89,88,105},{76,75,91},{63,61,76},{48,47,60},{33,31,44},{12,9,22},{0,0,0}, -{103,100,113},{89,88,98},{76,75,85},{63,61,71},{48,47,56},{33,31,40},{12,9,18},{0,0,0},{104,99,106},{90,87,92},{76,75,79},{63,62,65},{49,48,52},{33,32,36},{12,10,13},{0,0,0},{104,99,98},{90,87,85},{77,75,73},{63,62,60},{49,48,47},{33,32,31},{12,10,9},{0,0,0},{105,99,90},{91,87,78},{78,75,67},{64,62,54},{48,47,41},{33,32,25},{11,11,6},{0,0,0}, -{105,99,82},{91,87,70},{78,75,59},{64,62,48},{48,47,35},{33,32,20},{11,11,3},{0,0,0},{105,99,73},{92,87,63},{79,75,52},{64,62,42},{49,48,29},{33,32,14},{11,11,1},{0,0,0},{105,99,66},{92,87,56},{79,75,46},{64,62,36},{49,48,23},{33,32,8},{11,11,1},{0,0,0},{106,99,60},{93,87,51},{79,75,41},{64,61,30},{49,48,18},{33,32,4},{11,11,0},{0,0,0}, -{97,90,167},{86,79,147},{74,67,128},{62,53,110},{48,38,90},{33,21,70},{10,3,46},{0,0,2},{99,90,158},{87,79,140},{75,67,122},{63,54,105},{49,39,86},{33,22,66},{11,3,42},{0,0,1},{100,90,150},{88,79,133},{76,67,116},{63,54,99},{49,40,81},{33,23,63},{11,3,39},{0,0,0},{101,90,144},{89,79,127},{77,67,110},{64,54,94},{50,40,77},{34,24,59},{12,3,35},{0,0,0}, -{102,90,137},{90,79,120},{77,67,105},{64,54,89},{50,40,72},{34,24,55},{12,3,31},{0,0,0},{102,91,130},{90,79,114},{77,67,99},{64,54,84},{50,41,68},{34,25,51},{13,4,28},{0,0,0},{102,91,123},{90,79,108},{77,67,94},{64,54,79},{50,41,63},{34,25,46},{13,4,24},{0,0,0},{103,91,116},{91,79,102},{78,67,89},{65,55,74},{50,41,58},{34,25,42},{13,5,20},{0,0,0}, -{105,91,110},{91,79,96},{78,67,83},{65,55,69},{50,41,54},{34,25,38},{13,5,16},{0,0,0},{105,90,103},{92,79,90},{78,68,77},{65,55,63},{51,42,50},{34,26,34},{13,5,11},{0,0,0},{106,90,95},{92,79,83},{79,68,71},{65,55,58},{51,42,45},{34,26,29},{13,5,7},{0,0,0},{107,90,88},{93,79,76},{80,67,65},{65,55,52},{50,41,39},{34,26,23},{12,6,5},{0,0,0}, -{107,90,80},{93,79,68},{80,67,57},{65,55,46},{50,41,33},{34,26,18},{12,6,3},{0,0,0},{107,90,71},{94,79,61},{81,68,50},{66,55,40},{51,42,27},{35,26,12},{12,6,1},{0,0,0},{107,90,65},{94,79,55},{81,68,45},{66,55,34},{51,42,22},{35,26,7},{12,6,1},{0,0,0},{108,90,59},{94,79,50},{81,68,40},{66,55,29},{51,42,17},{34,27,4},{12,6,0},{0,0,0}, -{101,79,161},{89,69,142},{77,57,124},{64,44,106},{50,29,87},{35,13,67},{10,1,43},{0,0,1},{102,80,153},{90,69,135},{78,57,118},{65,45,101},{51,30,82},{35,14,63},{11,1,39},{0,0,0},{103,80,145},{91,69,129},{79,57,112},{65,45,95},{51,31,78},{35,14,60},{11,1,36},{0,0,0},{104,80,139},{91,69,123},{80,58,107},{66,46,91},{51,32,74},{36,15,56},{12,1,32},{0,0,0}, -{104,80,133},{92,69,116},{80,58,102},{66,46,86},{51,32,69},{36,15,52},{12,1,28},{0,0,0},{105,81,126},{92,69,110},{80,58,96},{65,46,81},{51,32,65},{35,16,48},{13,2,25},{0,0,0},{105,81,119},{92,69,104},{80,58,90},{65,46,76},{51,33,60},{35,17,43},{13,2,21},{0,0,0},{106,81,112},{93,70,99},{80,58,85},{66,47,71},{52,33,55},{35,17,39},{13,3,17},{0,0,0}, -{106,81,106},{93,70,93},{80,58,80},{66,47,66},{52,33,51},{35,17,35},{13,3,13},{0,0,0},{107,81,99},{93,70,87},{81,59,74},{66,47,60},{51,34,47},{36,18,31},{13,3,9},{0,0,0},{107,81,92},{93,70,80},{81,59,68},{66,47,55},{51,34,42},{36,18,26},{13,3,6},{0,0,0},{108,80,85},{94,70,73},{81,59,62},{66,47,49},{51,34,37},{36,19,21},{13,3,4},{0,0,0}, -{108,80,77},{94,70,66},{81,59,55},{66,47,44},{51,34,32},{36,19,16},{13,3,2},{0,0,0},{108,81,70},{95,70,59},{82,59,49},{67,47,39},{51,35,26},{36,19,10},{13,3,1},{0,0,0},{108,81,64},{95,70,53},{82,59,44},{67,47,33},{51,35,21},{36,19,7},{13,3,1},{0,0,0},{109,80,58},{96,70,48},{82,60,39},{67,47,28},{51,35,16},{35,20,4},{12,3,0},{0,0,0}, -{104,68,156},{91,58,137},{80,48,120},{66,35,102},{52,20,83},{37,4,64},{10,0,40},{0,0,0},{105,68,149},{92,59,131},{81,48,114},{67,36,97},{53,21,78},{37,5,60},{11,0,36},{0,0,0},{106,68,141},{93,59,125},{81,48,108},{68,36,91},{53,22,74},{37,5,57},{11,0,33},{0,0,0},{107,69,135},{94,59,119},{82,49,103},{68,37,87},{53,23,70},{38,6,53},{12,0,29},{0,0,0}, -{107,69,129},{94,59,112},{82,49,98},{68,37,82},{53,23,66},{38,6,49},{12,0,26},{0,0,0},{107,70,122},{95,60,106},{82,49,92},{67,38,77},{53,24,61},{37,7,45},{12,0,23},{0,0,0},{107,70,115},{95,60,100},{82,49,86},{67,38,72},{53,24,57},{37,8,41},{12,0,19},{0,0,0},{108,70,108},{95,61,95},{82,49,81},{67,39,67},{53,25,53},{37,9,37},{12,1,14},{0,0,0}, -{108,70,102},{95,61,89},{82,49,76},{67,39,63},{53,26,49},{37,10,33},{13,1,10},{0,0,0},{109,70,95},{95,61,83},{82,50,71},{68,39,58},{52,26,45},{37,10,29},{14,1,7},{0,0,0},{109,70,89},{95,61,77},{82,50,65},{68,39,53},{52,26,40},{37,10,24},{14,1,5},{0,0,0},{109,71,82},{96,61,71},{82,50,59},{68,39,47},{53,27,35},{37,11,19},{13,1,3},{0,0,0}, -{109,71,75},{96,61,64},{82,50,53},{68,39,42},{53,27,30},{37,11,14},{13,1,1},{0,0,0},{110,71,68},{97,61,57},{83,51,47},{69,40,37},{52,28,25},{37,12,9},{13,1,0},{0,0,0},{110,71,62},{97,61,51},{83,51,42},{69,40,32},{52,28,19},{37,12,6},{13,1,0},{0,0,0},{111,71,56},{97,61,46},{83,51,37},{69,40,27},{52,29,14},{37,13,3},{12,1,0},{0,0,0}, -{106,56,150},{93,46,132},{81,35,116},{68,22,98},{53,10,80},{38,2,62},{10,0,38},{0,0,0},{107,56,143},{94,47,126},{82,36,110},{69,23,93},{54,11,76},{38,2,58},{11,0,34},{0,0,0},{108,56,136},{95,47,120},{82,36,104},{69,23,88},{54,12,72},{38,2,55},{11,0,31},{0,0,0},{109,57,130},{96,47,114},{83,37,100},{69,25,84},{54,13,68},{38,3,51},{11,0,27},{0,0,0}, -{109,57,124},{96,47,109},{83,37,95},{69,25,80},{54,13,64},{38,3,47},{11,0,24},{0,0,0},{109,58,118},{96,49,103},{83,38,89},{68,26,75},{54,14,59},{38,3,43},{12,0,21},{0,0,0},{109,59,112},{96,49,98},{83,38,84},{68,27,70},{54,14,55},{38,4,39},{12,0,17},{0,0,0},{109,59,105},{96,50,92},{82,39,79},{68,28,65},{54,15,51},{38,4,35},{13,1,12},{0,0,0}, -{109,60,99},{96,50,86},{82,40,74},{68,29,61},{54,16,47},{38,5,31},{13,1,9},{0,0,0},{110,60,93},{96,51,81},{83,40,69},{68,29,56},{53,16,43},{38,5,28},{13,1,6},{0,0,0},{110,60,87},{96,51,75},{83,41,63},{68,29,51},{53,16,38},{38,5,23},{13,1,4},{0,0,0},{110,61,80},{97,51,69},{83,41,57},{68,30,46},{53,17,33},{38,6,17},{13,1,2},{0,0,0}, -{110,61,73},{97,51,63},{83,41,52},{68,30,41},{53,18,28},{38,6,13},{13,1,1},{0,0,0},{111,61,67},{98,51,56},{84,42,46},{69,31,36},{53,19,23},{37,6,8},{13,1,0},{0,0,0},{111,61,61},{98,51,50},{84,42,41},{69,31,31},{53,19,18},{37,6,5},{13,1,0},{0,0,0},{112,61,55},{98,51,45},{84,42,36},{69,31,26},{53,19,13},{37,7,3},{12,1,0},{0,0,0}, -{108,44,145},{96,33,127},{82,22,111},{70,8,95},{55,0,77},{39,0,60},{9,0,36},{0,0,0},{109,43,138},{97,34,121},{83,23,106},{70,9,90},{55,1,73},{39,0,56},{10,0,32},{0,0,0},{110,43,131},{97,34,115},{84,24,100},{70,10,85},{55,1,69},{39,0,52},{10,0,29},{0,0,0},{111,44,125},{98,35,110},{84,25,96},{70,12,81},{55,2,65},{39,0,48},{11,0,25},{0,0,0}, -{111,45,120},{98,35,105},{84,26,91},{70,13,77},{55,2,61},{39,0,45},{12,0,22},{0,0,0},{111,46,114},{98,37,99},{84,27,86},{70,15,72},{55,3,57},{39,0,41},{13,0,18},{0,0,0},{111,47,108},{98,38,94},{84,27,81},{70,16,67},{55,3,53},{39,0,37},{13,0,14},{0,0,0},{111,47,102},{97,39,89},{84,28,76},{70,17,62},{55,4,49},{39,0,33},{13,0,10},{0,0,0}, -{111,48,96},{97,39,83},{84,29,72},{70,17,58},{55,5,45},{39,0,29},{13,0,7},{0,0,0},{111,49,90},{98,39,78},{84,30,67},{69,18,54},{54,6,41},{39,0,25},{13,0,5},{0,0,0},{111,49,84},{98,39,72},{84,30,61},{69,19,49},{54,6,36},{39,0,21},{13,0,3},{0,0,0},{112,49,78},{99,39,66},{85,31,55},{70,20,44},{54,6,31},{39,1,15},{13,0,1},{0,0,0}, -{112,49,71},{99,40,61},{85,31,50},{70,20,39},{54,7,26},{39,1,11},{13,0,1},{0,0,0},{113,49,65},{99,41,55},{85,31,45},{70,21,34},{54,8,21},{38,1,7},{13,0,1},{0,0,0},{113,49,59},{99,41,49},{85,31,40},{70,21,29},{54,8,16},{38,1,4},{13,0,1},{0,0,0},{112,50,54},{99,41,44},{85,32,35},{70,22,24},{54,9,11},{37,1,2},{12,0,0},{0,0,0}, -{0,182,240},{0,161,213},{0,140,186},{0,120,159},{0,99,133},{0,77,105},{0,51,74},{0,10,34},{0,181,228},{0,160,202},{0,140,176},{0,119,151},{0,99,126},{0,77,99},{0,51,70},{0,9,31},{0,180,217},{0,160,191},{0,140,167},{0,119,143},{0,99,118},{0,77,93},{0,51,65},{0,9,29},{0,179,205},{0,159,182},{0,139,159},{0,118,136},{0,98,112},{0,77,89},{0,51,61},{0,9,25}, -{0,179,194},{0,158,172},{0,139,151},{0,118,129},{0,98,106},{0,77,84},{0,51,57},{0,9,21},{0,178,184},{0,157,162},{0,138,142},{0,118,121},{0,98,100},{0,76,78},{0,51,53},{0,9,17},{0,178,173},{0,157,153},{0,138,133},{0,118,113},{0,98,94},{0,76,73},{0,51,48},{0,9,12},{0,177,162},{0,157,144},{0,137,125},{0,117,106},{0,97,87},{0,76,68},{0,50,44},{0,8,7}, -{1,177,152},{1,157,134},{0,137,117},{0,117,99},{0,97,81},{0,76,63},{0,50,40},{0,8,4},{2,176,142},{2,156,125},{1,137,109},{0,116,92},{0,96,75},{0,76,58},{0,51,35},{0,7,1},{4,175,130},{3,155,115},{2,137,100},{0,116,85},{0,96,69},{0,76,52},{0,51,30},{0,7,0},{5,174,118},{4,154,105},{3,136,91},{1,116,77},{0,96,62},{0,75,46},{0,50,24},{0,7,0}, -{6,174,107},{5,154,95},{3,136,82},{1,116,69},{0,96,55},{0,75,39},{0,50,18},{0,7,0},{7,174,95},{5,154,85},{4,135,73},{1,115,60},{0,95,48},{0,75,33},{0,50,12},{0,7,0},{7,174,86},{6,154,77},{4,135,66},{2,115,54},{0,95,42},{0,75,27},{0,50,7},{0,7,0},{7,174,76},{6,154,68},{4,134,58},{2,115,48},{0,95,37},{0,74,22},{0,50,2},{0,7,0}, -{0,173,233},{0,153,206},{0,133,180},{0,114,154},{0,93,128},{0,72,102},{0,47,71},{0,5,32},{0,172,221},{0,152,196},{0,133,170},{0,113,146},{0,94,122},{0,72,96},{0,47,67},{0,4,28},{0,171,210},{0,151,185},{0,133,162},{0,113,138},{0,94,114},{0,72,90},{0,47,62},{0,4,26},{1,170,199},{1,151,176},{1,132,154},{0,112,132},{0,93,108},{0,72,86},{0,47,58},{0,4,22}, -{2,170,189},{2,151,167},{1,132,146},{0,112,125},{0,93,103},{0,72,81},{0,47,54},{0,4,18},{3,169,179},{2,150,158},{2,131,138},{1,112,117},{0,92,97},{0,71,75},{0,47,50},{0,4,13},{3,169,168},{2,150,149},{2,131,129},{1,112,110},{0,92,91},{0,71,70},{0,47,46},{0,4,9},{3,168,157},{3,149,140},{2,130,121},{1,111,103},{0,92,84},{0,71,65},{0,46,42},{0,3,4}, -{4,168,147},{3,149,130},{2,130,113},{2,111,96},{0,92,78},{0,71,60},{0,46,38},{0,3,2},{5,167,138},{4,148,121},{3,130,106},{2,110,89},{1,91,72},{0,71,55},{0,47,33},{0,3,0},{6,166,127},{5,148,112},{4,130,97},{2,110,82},{1,91,66},{0,71,50},{0,47,28},{0,3,0},{7,166,116},{6,147,102},{4,129,89},{2,110,75},{1,91,60},{0,71,44},{0,46,22},{0,3,0}, -{7,166,105},{6,147,93},{5,129,80},{3,110,67},{1,91,53},{0,71,37},{0,46,16},{0,3,0},{8,166,93},{7,147,83},{5,128,71},{3,109,59},{1,90,46},{0,71,31},{0,46,10},{0,3,0},{8,166,84},{7,147,75},{5,128,64},{3,109,52},{1,90,40},{0,71,25},{0,46,6},{0,3,0},{8,165,75},{7,147,66},{5,128,57},{3,109,47},{2,90,35},{0,70,20},{0,46,2},{0,3,0}, -{0,164,225},{0,145,199},{0,126,173},{0,107,148},{0,87,124},{0,67,99},{0,42,68},{0,0,30},{0,163,214},{0,144,189},{0,125,164},{0,107,141},{0,88,118},{0,67,94},{0,42,64},{0,0,26},{1,162,203},{1,143,179},{0,125,156},{0,107,134},{0,88,111},{0,67,88},{0,42,60},{0,0,23},{2,162,193},{2,143,170},{1,125,149},{0,106,128},{0,87,105},{0,67,84},{0,43,56},{0,0,19}, -{4,162,183},{3,143,162},{2,125,142},{1,106,121},{0,87,100},{0,67,79},{0,43,52},{0,0,15},{5,161,173},{4,142,153},{3,124,134},{1,105,114},{0,86,94},{0,67,73},{0,43,48},{0,0,10},{6,160,162},{5,142,144},{4,124,126},{2,105,107},{1,86,88},{0,67,68},{0,43,44},{0,0,6},{6,160,152},{5,141,135},{4,123,118},{2,105,100},{1,86,82},{0,67,63},{0,43,40},{0,0,2}, -{7,159,143},{6,141,127},{4,123,110},{3,105,94},{1,86,76},{0,67,58},{0,43,36},{0,0,0},{7,158,134},{6,140,118},{5,122,103},{3,104,87},{1,85,70},{0,67,53},{0,43,31},{0,0,0},{8,158,124},{7,140,109},{5,122,95},{4,104,80},{1,85,64},{0,67,48},{0,43,26},{0,0,0},{8,158,114},{7,139,100},{6,122,87},{4,104,73},{2,85,58},{0,67,42},{0,43,21},{0,0,0}, -{9,158,103},{7,139,91},{6,122,79},{4,104,65},{2,85,51},{0,67,36},{0,43,15},{0,0,0},{9,158,92},{8,139,81},{6,121,70},{4,103,58},{2,84,45},{0,66,30},{0,43,9},{0,0,0},{10,158,83},{8,139,73},{6,121,63},{4,103,51},{2,84,39},{0,66,24},{0,43,5},{0,0,0},{10,157,74},{9,139,65},{6,121,56},{5,103,45},{3,84,34},{1,66,19},{0,43,2},{0,0,0}, -{2,155,219},{2,138,193},{2,120,169},{1,101,144},{0,83,120},{0,63,95},{0,38,66},{0,0,27},{3,154,208},{3,137,183},{2,119,160},{1,101,137},{0,83,114},{0,63,90},{0,38,62},{0,0,23},{4,154,197},{3,136,174},{3,119,152},{2,101,130},{1,83,107},{0,63,85},{0,38,58},{0,0,19},{5,154,187},{4,136,166},{3,119,145},{2,101,124},{1,83,102},{0,63,81},{0,39,54},{0,0,15}, -{6,154,178},{5,136,158},{4,119,138},{2,101,117},{1,83,97},{0,63,76},{0,39,50},{0,0,11},{6,153,169},{5,135,149},{4,118,130},{3,100,110},{1,82,91},{0,63,71},{0,39,46},{0,0,6},{7,153,158},{6,135,140},{5,118,122},{3,100,104},{1,82,86},{0,63,66},{0,39,42},{0,0,4},{7,152,148},{6,134,131},{5,117,114},{4,100,97},{2,82,79},{0,63,61},{0,39,38},{0,0,1}, -{8,152,139},{7,134,123},{5,117,107},{4,100,91},{2,82,73},{0,63,56},{0,39,34},{0,0,0},{8,151,130},{7,134,114},{6,117,100},{4,99,84},{2,81,68},{0,63,51},{0,39,29},{0,0,0},{9,151,120},{7,134,106},{6,117,92},{4,99,77},{2,81,62},{0,63,46},{0,39,24},{0,0,0},{9,151,110},{8,133,97},{6,116,84},{5,99,71},{2,81,56},{1,63,40},{0,39,19},{0,0,0}, -{10,151,100},{8,133,88},{6,116,76},{5,99,63},{3,81,49},{1,63,34},{0,39,13},{0,0,0},{11,150,89},{8,133,79},{7,116,68},{5,98,56},{3,80,43},{1,62,28},{0,39,7},{0,0,0},{15,150,81},{11,133,71},{7,116,61},{5,98,50},{3,80,37},{1,62,23},{0,39,4},{0,0,0},{19,150,73},{15,132,63},{7,116,54},{5,98,44},{3,80,32},{1,62,18},{0,39,2},{0,0,0}, -{4,147,212},{3,130,187},{3,113,164},{2,95,140},{0,78,116},{0,59,91},{0,34,63},{0,0,24},{5,146,201},{5,129,178},{4,113,155},{2,95,133},{1,78,110},{0,59,87},{0,34,59},{0,0,20},{6,146,191},{5,129,169},{4,113,147},{3,95,126},{1,78,104},{0,59,82},{0,34,55},{0,0,15},{7,146,182},{6,129,161},{5,112,141},{4,95,120},{2,78,99},{0,59,78},{0,35,51},{0,0,11}, -{8,146,173},{6,129,153},{5,112,134},{4,95,113},{2,78,94},{0,59,73},{0,35,47},{0,0,7},{8,145,164},{7,128,144},{6,112,126},{4,95,107},{2,77,88},{1,59,68},{0,35,43},{0,0,4},{8,145,154},{7,128,136},{6,112,118},{4,95,101},{2,77,83},{1,59,63},{0,35,39},{0,0,2},{10,144,144},{7,127,127},{6,111,111},{5,94,94},{3,77,76},{1,59,58},{0,35,35},{0,0,1}, -{11,144,135},{9,127,119},{6,111,104},{5,94,88},{3,77,70},{1,59,54},{0,35,31},{0,0,0},{12,143,126},{10,127,111},{7,111,97},{5,94,81},{3,76,65},{1,59,49},{0,35,27},{0,0,0},{12,143,117},{11,127,103},{8,111,89},{5,94,74},{3,76,59},{1,59,44},{0,35,22},{0,0,0},{13,143,107},{11,126,94},{9,110,81},{6,93,68},{3,76,53},{1,59,38},{0,35,17},{0,0,0}, -{15,143,97},{12,126,85},{10,110,73},{6,93,61},{3,76,47},{1,59,32},{0,35,11},{0,0,0},{17,142,87},{12,126,76},{10,110,65},{6,93,55},{4,75,42},{1,58,26},{0,35,6},{0,0,0},{23,142,79},{17,126,69},{10,110,59},{7,93,49},{4,75,36},{1,58,21},{0,35,4},{0,0,0},{29,142,72},{21,125,62},{10,109,53},{7,93,43},{4,75,31},{1,58,16},{0,35,2},{0,0,0}, -{6,138,205},{5,122,181},{5,106,158},{3,89,135},{2,72,112},{0,54,89},{0,30,61},{0,0,21},{7,137,194},{6,122,172},{5,106,151},{4,89,129},{2,72,106},{1,54,84},{0,30,57},{0,0,17},{8,137,185},{7,122,163},{6,106,143},{4,89,122},{3,72,100},{1,54,79},{0,30,53},{0,0,13},{8,137,176},{7,121,156},{6,105,136},{5,89,116},{3,72,95},{1,54,75},{0,31,49},{0,0,9}, -{9,137,167},{7,121,148},{6,105,129},{5,89,110},{3,72,90},{1,54,70},{0,31,45},{0,0,5},{9,137,158},{8,120,140},{6,105,122},{5,89,104},{3,71,85},{1,54,66},{0,31,41},{0,0,2},{10,137,149},{8,120,132},{7,105,114},{5,89,98},{3,71,80},{1,54,61},{0,31,37},{0,0,1},{14,136,140},{9,120,123},{7,104,107},{5,88,91},{3,71,74},{1,54,56},{0,31,33},{0,0,0}, -{18,136,131},{13,120,115},{9,104,101},{6,88,85},{4,71,68},{1,54,52},{0,31,29},{0,0,0},{21,136,123},{18,120,108},{12,104,94},{6,88,78},{4,71,63},{2,54,47},{0,31,25},{0,0,0},{25,136,114},{21,120,100},{14,104,87},{7,88,72},{4,71,57},{2,54,42},{0,31,20},{0,0,0},{29,135,105},{24,119,92},{17,103,79},{8,87,66},{4,70,51},{2,53,36},{0,31,15},{0,0,0}, -{32,135,95},{26,119,83},{19,103,71},{10,87,59},{4,70,45},{2,53,30},{0,31,9},{0,0,0},{35,134,85},{29,119,74},{22,103,63},{11,87,53},{4,71,40},{2,54,24},{0,31,4},{0,0,0},{38,134,77},{31,119,67},{23,103,57},{12,87,47},{4,71,34},{2,54,19},{0,31,3},{0,0,0},{41,135,70},{34,118,61},{23,103,52},{12,87,41},{5,70,29},{2,53,14},{0,31,1},{0,0,0}, -{8,130,198},{7,114,175},{6,99,153},{5,83,130},{3,66,108},{1,49,86},{0,25,58},{0,0,18},{10,129,188},{9,114,166},{7,99,146},{6,83,124},{3,66,103},{1,49,81},{0,26,54},{0,0,14},{12,129,179},{10,114,158},{8,99,138},{6,83,117},{4,66,97},{1,49,76},{0,26,50},{0,0,10},{13,129,170},{12,113,151},{9,98,131},{6,83,112},{4,66,92},{1,49,72},{0,26,46},{0,0,6}, -{15,129,161},{13,113,143},{10,98,124},{7,83,107},{4,66,87},{1,49,67},{0,26,42},{0,0,2},{16,129,152},{14,113,135},{11,98,118},{7,83,101},{4,66,82},{2,49,63},{0,26,38},{0,0,1},{18,129,144},{14,113,127},{12,98,111},{7,83,95},{4,66,77},{2,49,58},{0,26,35},{0,0,0},{22,128,136},{16,112,120},{12,98,104},{8,82,88},{5,66,72},{2,49,54},{0,27,31},{0,0,0}, -{27,128,128},{20,112,112},{15,98,98},{9,82,82},{5,66,66},{2,49,49},{0,27,27},{0,0,0},{32,128,120},{27,112,105},{18,97,91},{10,82,75},{5,66,60},{2,49,44},{0,27,23},{0,0,0},{38,128,111},{31,112,97},{22,97,84},{12,82,69},{5,66,54},{2,49,39},{0,27,18},{0,0,0},{42,127,102},{35,111,89},{25,97,77},{13,81,63},{5,65,48},{2,48,33},{0,27,12},{0,0,0}, -{45,127,93},{37,111,81},{28,97,69},{15,81,57},{6,65,43},{2,48,28},{0,27,8},{0,0,0},{49,126,83},{41,111,72},{32,97,61},{17,82,51},{6,66,38},{2,49,22},{0,27,3},{0,0,0},{51,126,75},{42,111,65},{32,97,55},{18,82,45},{6,66,32},{2,49,17},{0,27,2},{0,0,0},{52,127,68},{44,111,59},{33,97,50},{19,81,39},{7,65,28},{2,48,12},{0,27,1},{0,0,0}, -{9,121,191},{8,107,169},{7,92,148},{5,77,126},{4,61,104},{2,44,83},{0,20,56},{0,0,15},{15,121,182},{14,106,161},{10,92,141},{7,77,120},{4,61,99},{2,44,78},{0,21,52},{0,0,11},{21,121,173},{19,106,153},{15,92,133},{9,77,113},{4,61,93},{2,44,73},{0,21,48},{0,0,6},{26,121,164},{23,106,146},{18,91,127},{10,77,108},{5,61,89},{2,44,69},{0,21,44},{0,0,3}, -{30,121,156},{25,106,138},{21,91,120},{12,77,103},{5,61,84},{2,44,64},{0,21,41},{0,0,1},{33,120,148},{27,106,131},{22,91,114},{12,77,97},{5,61,79},{2,44,60},{0,22,37},{0,0,0},{35,120,140},{28,106,123},{23,91,108},{14,77,92},{5,61,74},{2,44,55},{0,22,33},{0,0,0},{38,120,132},{31,105,116},{25,91,101},{16,77,85},{6,61,69},{3,44,51},{0,22,29},{0,0,0}, -{41,120,124},{35,105,109},{27,91,95},{18,77,79},{8,61,63},{3,44,47},{0,22,25},{0,0,0},{46,120,116},{38,105,102},{29,90,88},{19,76,74},{8,61,58},{3,44,43},{0,23,21},{0,0,0},{49,120,108},{41,105,94},{32,90,81},{21,76,68},{8,61,53},{3,44,38},{0,23,16},{0,0,0},{51,120,99},{44,104,87},{34,90,74},{22,76,61},{9,60,47},{3,44,32},{0,23,10},{0,0,0}, -{53,120,90},{46,104,79},{36,90,66},{23,76,55},{10,60,42},{3,44,27},{0,23,7},{0,0,0},{56,119,82},{48,104,70},{38,90,59},{25,76,49},{11,61,36},{4,44,21},{0,22,2},{0,0,0},{57,119,74},{49,104,64},{38,90,53},{25,76,43},{11,61,31},{4,44,16},{0,22,2},{0,0,0},{58,119,67},{50,104,58},{39,90,48},{26,76,38},{12,60,27},{4,44,11},{0,22,1},{0,0,0}, -{19,113,185},{17,99,164},{13,86,143},{10,71,122},{6,55,100},{2,38,80},{0,14,53},{0,0,12},{26,113,176},{24,99,156},{18,85,136},{13,71,116},{6,56,95},{2,39,75},{0,15,50},{0,0,8},{33,113,167},{29,99,148},{23,85,129},{15,71,109},{7,56,89},{3,39,70},{0,16,46},{0,0,3},{38,113,159},{33,99,141},{26,85,123},{17,71,104},{8,55,85},{4,39,66},{0,16,42},{0,0,1}, -{43,113,151},{36,99,134},{29,85,116},{19,71,99},{8,55,81},{4,39,62},{0,16,39},{0,0,0},{46,112,144},{38,99,127},{31,85,110},{20,71,93},{9,55,76},{4,39,58},{0,17,35},{0,0,0},{48,112,136},{40,99,119},{33,85,104},{21,71,88},{9,55,71},{4,39,53},{0,17,31},{0,0,0},{50,112,128},{43,99,112},{35,85,97},{23,71,82},{10,56,66},{4,40,49},{0,17,27},{0,0,0}, -{52,112,120},{45,99,105},{36,85,91},{25,71,77},{12,56,61},{4,40,45},{0,17,23},{0,0,0},{55,112,112},{47,98,99},{37,84,86},{26,70,72},{13,56,56},{4,40,41},{1,18,19},{0,0,0},{57,112,104},{49,98,92},{39,84,79},{28,70,66},{13,56,51},{4,40,36},{0,18,14},{0,0,0},{59,112,96},{50,98,85},{40,84,72},{29,70,59},{14,56,45},{4,40,30},{0,18,8},{0,0,0}, -{61,112,88},{51,98,77},{41,84,64},{29,70,53},{15,56,40},{4,40,25},{0,18,5},{0,0,0},{62,111,80},{52,98,68},{43,84,57},{31,70,47},{16,56,34},{5,40,19},{0,18,2},{0,0,0},{63,111,72},{53,98,62},{43,84,51},{31,70,41},{16,56,29},{5,40,14},{0,18,2},{0,0,0},{64,111,65},{55,98,56},{44,84,46},{32,70,36},{16,56,25},{5,40,9},{1,18,1},{0,0,0}, -{37,105,180},{34,92,159},{27,79,139},{19,65,118},{9,49,97},{3,33,77},{0,9,50},{0,0,9},{43,105,171},{38,92,152},{30,78,132},{21,65,112},{10,50,92},{4,34,72},{1,10,47},{0,0,5},{47,105,162},{41,92,144},{33,78,124},{23,65,105},{12,50,86},{4,34,68},{1,11,44},{0,0,1},{49,105,155},{43,92,137},{35,78,119},{25,65,101},{13,50,82},{5,34,64},{1,11,40},{0,0,0}, -{51,105,147},{45,92,130},{36,78,113},{27,65,96},{14,50,78},{5,34,60},{1,11,37},{0,0,0},{54,104,140},{47,92,123},{38,78,107},{28,65,90},{15,50,73},{5,34,56},{1,11,33},{0,0,0},{56,104,132},{48,92,115},{39,78,101},{29,65,85},{16,50,68},{5,34,51},{1,11,29},{0,0,0},{58,104,124},{49,92,108},{41,78,94},{30,64,80},{17,51,63},{5,35,47},{1,11,25},{0,0,0}, -{60,104,116},{51,92,102},{43,78,88},{31,64,74},{17,51,59},{5,35,43},{1,11,21},{0,0,0},{62,104,109},{51,91,96},{44,79,83},{32,65,69},{18,51,54},{5,35,39},{1,12,17},{0,0,0},{63,104,101},{53,91,89},{44,79,77},{32,65,63},{18,51,49},{5,35,34},{1,12,13},{0,0,0},{65,104,94},{55,91,82},{45,78,70},{33,65,57},{19,51,44},{6,35,29},{1,13,7},{0,0,0}, -{65,104,86},{56,91,75},{46,78,63},{33,65,51},{20,51,39},{6,35,24},{1,13,4},{0,0,0},{66,104,77},{57,91,67},{47,78,56},{34,65,45},{21,51,33},{6,35,18},{1,13,2},{0,0,0},{67,104,71},{58,91,61},{47,78,50},{34,65,40},{21,51,28},{6,35,13},{1,13,1},{0,0,0},{68,104,64},{59,91,55},{47,78,45},{35,65,35},{20,51,24},{7,36,8},{1,13,0},{0,0,0}, -{50,97,174},{45,84,153},{36,71,134},{27,58,114},{15,43,94},{5,27,74},{0,5,48},{0,0,6},{54,97,165},{47,84,146},{39,72,127},{30,59,108},{17,44,89},{6,28,69},{1,6,44},{0,0,3},{57,97,157},{49,84,139},{40,72,120},{31,59,102},{18,44,83},{6,28,65},{1,7,41},{0,0,0},{58,97,150},{50,84,132},{42,72,115},{32,59,98},{19,44,79},{7,28,61},{1,7,37},{0,0,0}, -{59,97,142},{51,84,125},{43,72,110},{32,59,93},{19,44,75},{7,28,57},{1,7,34},{0,0,0},{61,96,135},{52,84,119},{44,72,104},{33,59,87},{20,44,70},{8,29,53},{1,7,31},{0,0,0},{62,96,128},{54,84,112},{45,72,98},{34,59,82},{20,44,65},{8,29,49},{1,7,27},{0,0,0},{63,96,121},{55,84,105},{46,72,91},{35,58,77},{21,45,61},{8,29,45},{1,7,22},{0,0,0}, -{65,96,113},{56,84,99},{46,72,85},{35,58,72},{21,45,57},{8,29,41},{1,7,18},{0,0,0},{66,95,106},{56,84,93},{47,72,80},{36,59,66},{22,45,52},{9,30,36},{1,8,14},{0,0,0},{68,95,98},{58,84,86},{47,72,74},{36,59,61},{23,45,47},{9,30,32},{1,8,10},{0,0,0},{69,96,91},{59,84,79},{48,72,68},{37,59,55},{24,46,42},{10,30,27},{1,8,6},{0,0,0}, -{69,96,83},{60,84,72},{49,72,61},{37,59,49},{24,46,37},{10,30,22},{1,8,4},{0,0,0},{70,96,75},{61,83,65},{50,72,54},{38,59,43},{25,46,31},{9,30,16},{1,8,2},{0,0,0},{71,96,69},{61,83,59},{50,72,49},{38,59,38},{25,46,26},{9,30,11},{1,8,1},{0,0,0},{72,96,63},{62,83,53},{51,72,44},{39,59,33},{25,46,22},{10,31,6},{1,8,0},{0,0,0}, -{59,88,167},{52,76,147},{44,64,129},{35,51,110},{22,37,91},{7,20,71},{1,3,46},{0,0,4},{61,88,159},{54,76,140},{45,65,123},{36,52,105},{23,38,86},{8,21,67},{1,4,42},{0,0,1},{62,88,151},{56,76,133},{46,65,116},{36,52,99},{24,38,81},{9,22,63},{1,4,39},{0,0,0},{63,88,145},{57,76,127},{47,65,111},{38,52,94},{25,38,77},{10,22,59},{2,4,35},{0,0,0}, -{64,88,138},{57,76,121},{48,65,106},{38,52,89},{25,38,72},{10,22,55},{2,4,32},{0,0,0},{66,88,131},{58,77,115},{48,65,100},{38,52,84},{26,38,68},{11,23,51},{2,4,29},{0,0,0},{68,88,124},{58,77,109},{48,65,94},{38,52,79},{26,38,63},{11,23,47},{2,4,25},{0,0,0},{69,88,117},{59,76,102},{49,65,89},{39,52,75},{27,39,59},{12,23,43},{2,4,20},{0,0,0}, -{71,88,110},{61,76,96},{50,65,83},{39,52,70},{27,39,55},{12,23,39},{2,4,16},{0,0,0},{72,88,103},{61,77,90},{51,65,78},{40,53,64},{27,39,50},{13,24,34},{2,4,12},{0,0,0},{72,88,96},{62,77,84},{51,65,72},{40,53,59},{27,39,45},{13,24,30},{2,4,8},{0,0,0},{72,88,89},{62,77,77},{52,66,66},{41,53,53},{28,40,40},{13,25,25},{2,5,5},{0,0,0}, -{73,88,81},{63,77,70},{52,66,59},{41,53,47},{28,40,35},{13,25,20},{2,5,3},{0,0,0},{74,88,73},{64,76,63},{53,65,53},{42,53,42},{29,40,29},{13,25,14},{2,5,1},{0,0,0},{74,88,67},{64,76,57},{53,65,48},{42,53,37},{29,40,24},{13,25,9},{2,5,1},{0,0,0},{74,88,62},{65,76,52},{54,65,43},{42,53,32},{29,40,20},{13,25,4},{2,5,0},{0,0,0}, -{66,78,161},{58,67,143},{49,56,125},{40,43,106},{27,29,88},{12,12,68},{1,1,43},{0,0,2},{67,79,154},{59,68,136},{50,57,119},{41,44,101},{28,30,83},{13,13,64},{2,2,39},{0,0,1},{68,79,146},{60,68,128},{51,57,112},{41,44,95},{29,30,78},{14,14,60},{2,2,36},{0,0,0},{69,79,140},{61,68,123},{52,57,108},{42,44,91},{30,30,74},{15,15,56},{2,2,32},{0,0,0}, -{70,79,133},{62,68,117},{52,57,103},{42,44,86},{30,30,69},{15,15,52},{2,2,29},{0,0,0},{72,79,127},{62,68,111},{52,57,97},{42,44,81},{30,31,65},{14,16,48},{2,2,26},{0,0,0},{72,79,120},{62,68,105},{52,57,91},{42,44,76},{30,31,60},{14,16,44},{2,2,22},{0,0,0},{73,79,113},{63,68,99},{53,57,86},{43,45,72},{30,32,56},{15,16,40},{2,2,17},{0,0,0}, -{75,79,107},{63,68,93},{53,57,80},{43,45,67},{30,32,52},{15,16,36},{2,2,13},{0,0,0},{76,79,100},{64,69,87},{54,57,75},{43,46,61},{30,33,47},{15,17,32},{2,2,10},{0,0,0},{76,79,93},{65,69,81},{54,57,69},{43,46,56},{30,33,42},{15,17,27},{2,2,7},{0,0,0},{76,79,86},{66,69,75},{55,58,63},{44,46,50},{30,34,38},{16,18,23},{2,3,5},{0,0,0}, -{76,79,78},{66,69,68},{55,58,57},{44,46,45},{30,34,33},{16,18,18},{2,3,3},{0,0,0},{77,79,71},{67,68,61},{56,57,51},{45,46,40},{31,34,28},{16,18,12},{2,3,1},{0,0,0},{77,79,66},{67,68,56},{56,57,46},{45,46,36},{31,34,23},{16,18,8},{2,3,1},{0,0,0},{78,80,61},{68,68,51},{57,57,42},{45,47,31},{31,34,19},{16,19,4},{2,3,0},{0,0,0}, -{72,68,157},{62,58,139},{53,48,121},{44,35,102},{31,20,84},{17,4,64},{2,0,40},{0,0,0},{73,69,150},{63,59,132},{54,48,115},{45,36,97},{32,21,79},{17,5,60},{3,0,36},{0,0,0},{74,69,142},{64,59,124},{55,48,108},{45,36,91},{32,21,74},{17,5,57},{3,0,33},{0,0,0},{75,69,136},{65,59,119},{56,48,104},{46,37,87},{33,22,70},{18,6,53},{3,0,29},{0,0,0}, -{75,69,129},{65,59,113},{56,48,99},{46,37,83},{33,23,66},{18,6,49},{3,0,26},{0,0,0},{76,70,123},{65,59,107},{56,49,93},{45,37,78},{33,24,62},{18,7,45},{3,0,23},{0,0,0},{76,70,116},{66,59,101},{56,49,87},{45,37,73},{33,24,57},{18,7,42},{3,0,19},{0,0,0},{77,70,109},{66,60,95},{57,49,82},{46,38,68},{33,25,53},{19,8,38},{3,0,15},{0,0,0}, -{78,70,103},{67,60,90},{57,49,77},{46,38,63},{33,25,49},{19,9,34},{3,0,11},{0,0,0},{79,70,97},{68,61,85},{58,50,72},{46,39,58},{33,26,45},{19,10,30},{3,1,8},{0,0,0},{79,70,90},{69,61,79},{58,50,66},{46,39,53},{33,26,40},{19,10,25},{3,1,6},{0,0,0},{79,70,83},{70,60,73},{58,50,60},{46,39,48},{34,27,36},{20,10,21},{3,1,4},{0,0,0}, -{79,70,76},{70,60,66},{59,50,55},{46,39,43},{34,27,31},{20,10,16},{3,1,2},{0,0,0},{79,70,69},{70,61,60},{60,50,49},{47,40,38},{34,27,26},{20,11,10},{3,1,1},{0,0,0},{80,70,64},{70,61,54},{60,50,44},{47,40,34},{34,27,22},{20,11,7},{3,1,1},{0,0,0},{81,71,59},{71,61,49},{60,50,40},{47,40,30},{34,28,18},{20,12,4},{3,1,0},{0,0,0}, -{75,57,151},{66,48,134},{57,38,117},{46,24,99},{33,11,81},{19,2,62},{2,0,38},{0,0,0},{76,58,144},{67,49,127},{58,38,111},{47,25,94},{34,12,77},{19,2,58},{3,0,35},{0,0,0},{77,58,136},{68,49,120},{59,38,104},{47,25,89},{35,12,72},{19,2,55},{3,0,32},{0,0,0},{78,59,131},{68,49,114},{59,38,100},{47,27,85},{35,13,68},{20,3,51},{3,0,28},{0,0,0}, -{78,59,125},{68,49,109},{59,39,96},{47,27,81},{35,14,64},{20,3,48},{3,0,24},{0,0,0},{79,60,119},{69,50,104},{59,40,90},{47,28,75},{34,15,60},{19,3,44},{3,0,21},{0,0,0},{79,60,113},{69,50,99},{59,40,85},{47,28,71},{34,15,55},{19,3,40},{3,0,17},{0,0,0},{80,60,106},{69,51,93},{59,40,80},{47,29,66},{35,16,51},{20,4,36},{3,0,13},{0,0,0}, -{80,60,100},{69,51,88},{59,40,75},{47,29,62},{35,16,47},{20,4,32},{3,0,10},{0,0,0},{81,61,94},{70,52,82},{60,41,70},{47,30,57},{35,17,44},{20,5,29},{3,1,7},{0,0,0},{81,61,88},{71,52,77},{60,41,65},{47,30,52},{35,17,39},{20,5,24},{3,1,5},{0,0,0},{81,61,81},{71,52,71},{60,42,59},{48,31,47},{35,18,35},{21,5,19},{3,1,3},{0,0,0}, -{81,61,74},{71,52,64},{61,42,54},{48,31,42},{35,18,30},{21,5,14},{3,1,2},{0,0,0},{81,61,68},{72,52,58},{61,42,48},{48,32,37},{35,18,25},{20,6,9},{3,1,1},{0,0,0},{82,61,62},{72,52,53},{61,42,43},{48,32,33},{35,19,21},{20,6,6},{3,1,1},{0,0,0},{82,62,57},{73,52,48},{62,42,39},{48,32,29},{36,20,16},{20,7,4},{3,1,0},{0,0,0}, -{78,46,146},{70,37,129},{60,26,113},{48,12,96},{36,2,78},{20,0,60},{2,0,36},{0,0,0},{80,47,139},{71,38,123},{61,27,107},{49,13,91},{37,2,74},{20,0,56},{2,0,33},{0,0,0},{81,47,131},{72,38,116},{62,27,100},{50,14,86},{37,2,70},{20,0,53},{3,0,30},{0,0,0},{82,48,126},{72,39,110},{62,28,96},{50,16,82},{37,3,66},{21,0,49},{3,0,26},{0,0,0}, -{82,48,121},{72,39,105},{62,29,92},{50,17,78},{37,4,62},{21,0,46},{3,0,22},{0,0,0},{82,49,115},{72,40,101},{62,30,87},{49,18,72},{36,5,58},{20,0,42},{3,0,19},{0,0,0},{82,50,109},{72,41,96},{62,30,82},{49,18,68},{36,5,53},{20,0,38},{3,0,15},{0,0,0},{83,50,102},{72,41,91},{61,31,77},{49,19,64},{37,6,49},{21,0,34},{3,0,11},{0,0,0}, -{83,50,96},{72,41,85},{61,31,73},{49,20,60},{37,7,45},{21,0,30},{3,0,8},{0,0,0},{84,51,91},{73,42,79},{62,32,68},{50,21,55},{37,8,42},{21,1,27},{3,0,6},{0,0,0},{84,51,85},{73,42,74},{62,32,63},{50,21,50},{37,8,38},{21,1,23},{3,0,4},{0,0,0},{84,51,79},{73,43,68},{63,33,57},{50,22,45},{37,9,33},{22,1,17},{3,0,2},{0,0,0}, -{84,51,72},{73,43,62},{63,33,52},{50,22,40},{37,9,28},{22,1,12},{3,0,1},{0,0,0},{84,52,66},{74,42,56},{63,33,46},{50,23,36},{37,9,24},{21,1,8},{3,0,0},{0,0,0},{84,52,60},{74,42,51},{63,33,41},{50,23,31},{37,10,19},{21,1,5},{3,0,0},{0,0,0},{84,52,55},{75,43,46},{63,34,37},{50,24,27},{38,11,14},{21,2,3},{3,0,0},{0,0,0}, -{0,174,239},{0,154,211},{0,134,185},{0,114,158},{0,95,132},{0,74,105},{0,49,74},{0,3,35},{0,173,227},{0,153,200},{0,134,175},{0,114,150},{0,94,125},{0,74,99},{0,49,70},{0,4,31},{0,172,216},{0,153,190},{0,134,166},{0,114,142},{0,94,117},{0,74,93},{0,49,65},{0,4,28},{0,171,205},{0,152,180},{0,133,158},{0,113,135},{0,93,112},{0,73,89},{0,49,61},{0,4,24}, -{0,171,194},{0,151,171},{0,133,150},{0,113,128},{0,93,106},{0,73,84},{0,49,57},{0,4,21},{0,170,184},{0,150,162},{0,132,141},{0,112,121},{0,93,100},{0,73,78},{0,48,53},{0,3,17},{0,170,173},{0,150,153},{0,131,133},{0,112,113},{0,93,94},{0,73,73},{0,48,48},{0,3,12},{0,169,162},{0,150,144},{0,131,125},{0,112,106},{0,93,88},{0,73,68},{0,49,44},{0,3,7}, -{0,168,152},{0,149,134},{0,131,117},{0,112,100},{0,93,82},{0,73,63},{0,49,40},{0,3,4},{0,167,142},{0,148,125},{0,130,110},{0,111,93},{0,92,76},{0,73,59},{0,49,36},{0,3,1},{0,167,131},{0,148,116},{0,130,101},{0,111,86},{0,92,70},{0,73,53},{0,49,31},{0,3,0},{0,167,121},{0,148,106},{0,130,92},{0,111,78},{0,91,63},{0,72,47},{0,48,25},{0,3,0}, -{0,167,110},{0,148,96},{0,130,84},{0,111,70},{0,91,56},{0,72,41},{0,48,20},{0,3,0},{0,166,98},{0,147,87},{0,129,75},{0,110,63},{0,92,50},{0,72,35},{0,48,14},{0,3,0},{0,166,89},{0,147,79},{0,129,68},{0,110,57},{0,92,44},{0,72,30},{0,48,9},{0,3,0},{0,165,79},{0,147,72},{0,128,62},{0,110,52},{0,92,39},{0,73,25},{0,49,4},{0,3,0}, -{0,165,232},{0,146,204},{0,127,179},{0,108,153},{0,90,127},{0,69,101},{0,45,71},{0,1,32},{0,164,220},{0,145,194},{0,127,170},{0,108,146},{0,89,121},{0,70,96},{0,45,67},{0,2,28},{0,163,209},{0,145,185},{0,127,161},{0,108,138},{0,89,114},{0,70,90},{0,45,62},{0,2,25},{0,163,199},{0,145,175},{0,126,154},{0,107,131},{0,88,108},{0,69,86},{0,45,58},{0,2,21}, -{0,163,188},{0,144,166},{0,126,146},{0,107,124},{0,88,103},{0,69,81},{0,45,54},{0,2,18},{0,162,178},{0,143,157},{0,126,137},{0,107,117},{0,88,97},{0,69,75},{0,44,50},{0,1,14},{0,162,168},{0,143,148},{0,125,129},{0,107,110},{0,88,91},{0,69,70},{0,44,46},{0,1,9},{0,161,157},{0,143,140},{0,125,122},{0,106,103},{0,88,85},{0,69,65},{0,45,42},{0,1,4}, -{0,160,147},{0,142,131},{0,125,114},{0,106,97},{0,88,79},{0,69,61},{0,45,38},{0,1,2},{0,160,138},{0,141,122},{0,124,107},{0,105,90},{0,87,73},{0,69,56},{0,45,34},{0,1,0},{0,160,128},{0,141,113},{0,124,98},{0,105,83},{0,87,67},{0,69,50},{0,45,29},{0,1,0},{0,160,118},{0,141,103},{0,124,90},{0,106,76},{0,87,60},{0,68,44},{0,44,23},{0,1,0}, -{0,160,107},{0,141,94},{0,124,82},{0,106,68},{0,87,54},{0,68,39},{0,44,18},{0,1,0},{0,159,96},{0,140,84},{0,123,73},{0,105,61},{0,87,48},{0,68,33},{0,44,12},{0,1,0},{0,159,87},{0,140,77},{0,123,66},{0,105,55},{0,87,42},{0,68,28},{0,44,7},{0,1,0},{0,158,78},{0,140,70},{0,122,60},{0,105,50},{0,87,38},{0,68,23},{0,45,3},{0,1,0}, -{0,157,224},{0,138,197},{0,120,173},{0,102,148},{0,84,123},{0,64,98},{0,40,69},{0,0,30},{0,156,212},{0,137,188},{0,119,164},{0,102,141},{0,84,117},{0,65,93},{0,41,64},{0,0,26},{0,155,201},{0,137,179},{0,119,156},{0,102,133},{0,84,111},{0,65,88},{0,41,60},{0,0,23},{0,155,192},{0,137,170},{0,119,149},{0,101,126},{0,83,105},{0,65,84},{0,41,56},{0,0,19}, -{0,155,182},{0,137,161},{0,119,141},{0,101,120},{0,83,100},{0,65,79},{0,41,52},{0,0,15},{0,154,172},{0,136,152},{0,119,133},{0,101,114},{0,82,94},{0,65,73},{0,41,48},{0,0,11},{0,154,162},{0,135,144},{0,119,126},{0,101,107},{0,82,88},{0,65,68},{0,41,44},{0,0,7},{0,153,152},{0,135,135},{0,118,119},{0,100,100},{0,82,82},{0,64,63},{0,41,40},{0,0,2}, -{0,152,143},{0,135,127},{0,118,111},{0,100,94},{0,82,76},{0,64,59},{0,41,36},{0,0,0},{0,152,134},{0,134,119},{0,117,104},{0,99,87},{0,81,70},{0,64,54},{0,41,32},{0,0,0},{0,152,125},{0,134,110},{0,117,96},{0,99,80},{0,81,64},{0,64,48},{0,41,27},{0,0,0},{0,152,115},{0,133,101},{0,117,88},{0,100,74},{0,82,58},{0,64,42},{0,41,21},{0,0,0}, -{0,152,104},{0,133,92},{0,117,80},{0,100,66},{0,82,52},{0,64,37},{0,41,16},{0,0,0},{0,151,94},{0,133,82},{0,116,72},{0,99,59},{0,81,46},{0,64,31},{0,41,10},{0,0,0},{0,151,86},{0,133,75},{0,116,65},{0,99,53},{0,81,41},{0,64,26},{0,41,6},{0,0,0},{0,150,78},{0,133,68},{0,116,58},{0,99,48},{0,81,37},{0,64,21},{0,41,2},{0,0,0}, -{0,149,218},{0,131,192},{0,115,169},{0,97,144},{0,79,119},{0,60,94},{0,36,66},{0,0,27},{0,148,206},{0,130,183},{0,114,160},{0,97,137},{0,79,113},{0,61,89},{0,37,62},{0,0,23},{0,148,196},{0,130,174},{0,114,151},{0,97,129},{0,79,107},{0,61,84},{0,37,58},{0,0,19},{0,147,187},{0,130,166},{0,113,144},{0,96,122},{0,79,101},{0,61,80},{0,37,54},{0,0,15}, -{0,147,178},{0,130,157},{0,113,137},{0,96,116},{0,79,96},{0,61,76},{0,37,50},{0,0,11},{0,147,168},{0,129,148},{0,113,129},{0,96,110},{0,78,90},{0,61,71},{0,37,46},{0,0,7},{0,147,158},{0,129,140},{0,113,122},{0,96,104},{0,78,85},{0,61,66},{0,37,42},{0,0,4},{0,146,148},{0,129,131},{0,112,115},{0,96,97},{0,78,80},{0,60,61},{0,37,38},{0,0,1}, -{0,145,139},{0,129,123},{0,112,107},{0,96,91},{0,78,74},{0,60,57},{0,37,34},{0,0,0},{0,145,130},{0,128,115},{0,112,100},{0,95,84},{0,77,68},{0,60,52},{0,37,30},{0,0,0},{0,145,121},{0,128,107},{0,112,93},{0,95,78},{0,77,62},{0,60,46},{0,37,25},{0,0,0},{0,145,111},{0,127,99},{0,111,85},{0,95,72},{0,78,56},{0,60,41},{0,37,20},{0,0,0}, -{0,145,101},{0,127,90},{0,111,77},{0,95,64},{0,78,50},{0,60,36},{0,37,15},{0,0,0},{0,144,91},{0,127,80},{0,111,70},{0,94,57},{0,77,44},{0,60,30},{0,37,9},{0,0,0},{0,144,84},{0,127,73},{0,111,63},{0,94,51},{0,77,39},{0,60,25},{0,37,5},{0,0,0},{0,144,77},{0,127,66},{0,111,57},{0,94,47},{0,77,35},{0,60,20},{0,37,2},{0,0,0}, -{0,141,211},{0,124,187},{0,109,164},{0,92,139},{0,74,115},{0,56,91},{0,32,63},{0,0,24},{0,140,200},{0,123,178},{0,108,155},{0,92,132},{0,74,110},{0,56,86},{0,33,59},{0,0,20},{0,140,190},{0,123,169},{0,108,146},{0,92,124},{0,74,104},{0,56,81},{0,33,55},{0,0,16},{0,139,182},{0,123,161},{0,107,139},{0,91,118},{0,74,98},{0,57,77},{0,33,51},{0,0,12}, -{0,139,173},{0,123,153},{0,107,132},{0,91,113},{0,74,93},{0,57,73},{0,33,47},{0,0,7},{0,139,164},{0,122,144},{0,107,125},{0,91,107},{0,74,87},{0,57,68},{0,34,43},{0,0,4},{0,139,154},{0,122,136},{0,107,118},{0,91,101},{0,74,82},{0,57,63},{0,34,39},{0,0,2},{0,138,144},{0,122,127},{0,106,111},{0,91,94},{0,73,77},{0,56,58},{0,33,35},{0,0,1}, -{0,138,135},{0,122,119},{0,106,104},{0,91,88},{0,73,71},{0,56,54},{0,33,31},{0,0,0},{0,138,126},{0,121,112},{0,106,97},{0,90,81},{0,73,65},{0,56,49},{0,33,27},{0,0,0},{0,138,117},{0,121,104},{0,106,90},{0,90,75},{0,73,60},{0,56,44},{0,33,22},{0,0,0},{0,137,107},{0,121,96},{0,105,82},{0,90,69},{0,73,54},{0,56,39},{0,33,18},{0,0,0}, -{0,137,98},{0,121,87},{0,105,74},{0,90,62},{0,73,49},{0,56,34},{0,33,13},{0,0,0},{0,136,89},{0,120,78},{0,105,67},{0,89,55},{0,73,43},{0,56,28},{0,33,7},{0,0,0},{0,136,82},{0,120,71},{0,105,61},{0,89,50},{0,73,38},{0,56,23},{0,33,5},{0,0,0},{0,137,75},{0,120,64},{0,105,56},{0,89,45},{0,73,33},{0,56,19},{0,33,2},{0,0,0}, -{0,134,204},{0,117,181},{0,102,158},{0,86,134},{0,69,111},{0,52,89},{0,28,61},{0,0,21},{0,133,194},{0,116,172},{0,102,150},{0,86,128},{0,69,106},{0,52,84},{0,29,57},{0,0,17},{0,132,184},{0,116,163},{0,102,142},{0,86,120},{0,69,100},{0,52,79},{0,29,53},{0,0,13},{0,132,176},{0,116,155},{0,101,135},{0,85,114},{0,69,95},{0,52,75},{0,29,49},{0,0,9}, -{0,132,167},{0,116,147},{0,101,128},{0,85,109},{0,69,90},{0,52,70},{0,29,45},{0,0,5},{0,132,158},{0,115,140},{0,101,121},{0,85,103},{0,69,85},{0,52,66},{0,29,41},{0,0,2},{0,132,150},{0,115,132},{0,101,114},{0,85,98},{0,69,80},{0,52,61},{0,29,37},{0,0,1},{0,131,140},{0,115,123},{0,100,107},{0,85,91},{0,68,75},{0,52,56},{0,29,33},{0,0,0}, -{0,130,132},{0,115,115},{0,100,101},{0,85,85},{0,68,69},{0,52,52},{0,29,29},{0,0,0},{0,130,123},{0,114,108},{0,100,94},{0,84,79},{0,68,63},{0,52,47},{0,29,25},{0,0,0},{0,130,114},{0,114,101},{0,100,88},{0,84,73},{0,68,58},{0,52,42},{0,29,20},{0,0,0},{0,130,105},{0,114,93},{0,99,80},{0,84,67},{0,68,52},{0,51,37},{0,29,16},{0,0,0}, -{0,130,96},{0,114,85},{0,99,72},{0,84,60},{0,68,47},{0,51,32},{0,29,11},{0,0,0},{0,129,87},{0,113,76},{0,99,65},{0,84,53},{0,68,41},{0,51,26},{0,29,5},{0,0,0},{0,129,80},{0,113,69},{0,99,59},{0,84,48},{0,68,36},{0,51,21},{0,29,4},{0,0,0},{0,130,73},{0,113,62},{0,99,54},{0,84,43},{0,68,31},{0,52,17},{0,29,2},{0,0,0}, -{0,126,198},{0,109,175},{0,96,152},{0,80,129},{0,64,108},{0,47,86},{0,23,58},{0,0,18},{0,125,188},{0,109,166},{0,96,145},{0,80,123},{0,64,103},{0,47,81},{0,24,54},{0,0,14},{0,124,178},{0,109,158},{0,96,137},{0,80,117},{0,64,97},{0,47,76},{0,24,50},{0,0,10},{0,124,170},{0,109,150},{0,95,131},{0,80,111},{0,64,92},{0,47,72},{0,24,46},{0,0,6}, -{0,124,162},{0,109,142},{0,95,125},{0,80,106},{0,64,87},{0,47,67},{0,24,43},{0,0,2},{0,124,153},{0,109,135},{0,95,118},{0,80,100},{0,64,82},{0,47,63},{0,24,39},{0,0,1},{0,124,145},{0,109,127},{0,95,111},{0,80,95},{0,64,77},{0,47,58},{0,24,35},{0,0,0},{0,123,137},{0,108,119},{0,94,104},{0,79,88},{0,63,72},{0,47,54},{0,24,31},{0,0,0}, -{0,122,129},{0,108,112},{0,94,98},{0,79,82},{0,63,66},{0,47,49},{0,24,27},{0,0,0},{0,122,120},{0,108,105},{0,94,91},{0,79,76},{0,63,61},{0,47,44},{0,24,23},{0,0,0},{0,122,111},{0,108,98},{0,94,85},{0,79,70},{0,63,56},{0,47,40},{0,24,18},{0,0,0},{0,122,102},{0,107,90},{0,93,78},{0,79,64},{0,63,50},{0,46,34},{0,24,13},{0,0,0}, -{0,122,94},{0,107,82},{0,93,70},{0,79,58},{0,63,45},{0,46,29},{0,24,8},{0,0,0},{0,121,85},{0,107,74},{0,93,63},{0,79,51},{0,63,39},{0,46,24},{0,24,4},{0,0,0},{0,121,78},{0,107,67},{0,93,57},{0,79,46},{0,63,34},{0,46,19},{0,24,3},{0,0,0},{0,122,71},{0,107,61},{0,93,52},{0,79,41},{0,63,29},{0,47,15},{0,24,2},{0,0,0}, -{0,118,191},{0,102,168},{0,89,147},{0,75,125},{0,59,105},{0,42,83},{0,18,56},{0,0,15},{0,117,181},{0,102,161},{0,89,140},{0,75,119},{0,59,99},{0,42,78},{0,18,52},{0,0,11},{0,117,172},{0,102,153},{0,89,133},{0,75,113},{0,59,93},{0,42,73},{0,18,48},{0,0,6},{0,117,165},{0,102,145},{0,89,127},{0,75,108},{0,59,89},{0,42,69},{0,18,44},{0,0,3}, -{0,117,157},{0,102,137},{0,89,121},{0,75,103},{0,59,84},{0,42,65},{0,18,41},{0,0,1},{0,116,148},{0,102,130},{0,89,115},{0,75,97},{0,59,79},{0,42,60},{0,18,37},{0,0,0},{0,116,140},{0,102,123},{0,89,108},{0,75,92},{0,59,74},{0,42,55},{0,18,33},{0,0,0},{0,116,133},{0,102,116},{0,88,101},{0,74,86},{0,58,69},{0,42,51},{0,19,30},{0,0,0}, -{0,115,125},{0,102,109},{0,88,95},{0,74,80},{0,58,64},{0,42,47},{0,19,26},{0,0,0},{0,115,116},{0,101,102},{0,88,88},{0,74,74},{0,58,60},{0,42,43},{0,19,22},{0,0,0},{0,115,108},{0,101,95},{0,88,82},{0,74,68},{0,58,54},{0,42,39},{0,19,17},{0,0,0},{0,115,99},{0,101,87},{0,88,76},{0,74,62},{0,58,48},{0,42,33},{0,18,11},{0,0,0}, -{0,115,91},{0,101,79},{0,88,68},{0,74,56},{0,58,43},{0,42,28},{0,18,7},{0,0,0},{0,114,83},{0,101,72},{0,88,61},{0,74,50},{0,58,38},{0,42,23},{0,19,3},{0,0,0},{0,114,76},{0,101,66},{0,88,55},{0,74,45},{0,58,32},{0,42,17},{0,19,2},{0,0,0},{0,115,70},{0,101,60},{0,87,50},{0,73,40},{0,58,27},{0,42,12},{0,19,1},{0,0,0}, -{0,110,185},{0,96,163},{0,83,142},{0,69,121},{0,53,101},{0,36,80},{0,13,54},{0,0,12},{0,109,175},{0,96,156},{0,83,136},{0,69,115},{0,53,95},{0,37,75},{0,13,50},{0,0,8},{0,109,166},{0,96,148},{0,83,129},{0,69,109},{0,53,90},{0,37,71},{0,13,46},{0,0,3},{0,109,159},{0,96,141},{0,83,123},{0,69,104},{0,54,86},{0,38,67},{0,13,42},{0,0,1}, -{0,109,152},{0,96,133},{0,83,117},{0,69,99},{0,54,81},{0,38,63},{0,13,39},{0,0,0},{0,109,144},{0,96,126},{0,83,111},{0,69,93},{0,54,76},{0,38,58},{0,13,35},{0,0,0},{0,109,136},{0,96,119},{0,83,104},{0,69,88},{0,54,71},{0,38,53},{0,13,31},{0,0,0},{0,109,129},{0,96,112},{0,82,97},{0,68,83},{0,54,66},{0,38,49},{0,14,28},{0,0,0}, -{0,109,121},{0,96,106},{0,82,91},{0,68,77},{0,54,62},{0,38,45},{0,14,24},{0,0,0},{0,108,112},{0,95,99},{0,82,86},{0,68,72},{0,54,58},{0,38,41},{0,14,20},{0,0,0},{0,108,105},{0,95,92},{0,82,80},{0,68,66},{0,54,52},{0,38,37},{0,14,15},{0,0,0},{0,108,97},{0,95,85},{0,82,74},{0,68,60},{0,54,46},{0,38,31},{0,13,9},{0,0,0}, -{0,108,89},{0,95,77},{0,82,66},{0,68,54},{0,54,41},{0,38,26},{0,13,6},{0,0,0},{0,108,81},{0,95,70},{0,82,59},{0,68,48},{0,54,36},{0,38,21},{0,14,2},{0,0,0},{0,108,74},{1,95,64},{0,82,53},{0,68,43},{0,54,30},{0,38,15},{0,14,2},{0,0,0},{0,108,68},{2,95,58},{0,81,48},{0,68,38},{0,54,25},{0,38,10},{0,14,1},{0,0,0}, -{0,102,179},{0,89,158},{0,76,138},{0,63,117},{0,47,97},{0,31,77},{0,9,51},{0,0,9},{0,102,170},{0,89,151},{0,76,132},{0,63,112},{0,48,92},{0,32,72},{0,9,47},{0,0,5},{0,102,161},{0,89,143},{0,76,125},{0,63,106},{0,48,87},{0,32,68},{0,9,44},{0,0,1},{0,102,154},{0,89,137},{0,77,119},{0,63,101},{0,49,83},{0,33,64},{0,9,40},{0,0,0}, -{0,102,147},{0,89,129},{0,77,113},{0,63,96},{0,49,78},{0,33,60},{0,9,37},{0,0,0},{0,102,140},{0,89,122},{0,76,107},{0,63,90},{0,49,74},{0,33,56},{0,10,33},{0,0,0},{0,102,132},{0,89,116},{0,76,101},{0,63,85},{0,49,69},{0,33,52},{0,10,30},{0,0,0},{0,102,125},{0,89,109},{0,77,94},{0,63,80},{0,49,64},{0,33,47},{0,10,26},{0,0,0}, -{0,102,117},{0,89,103},{0,77,88},{0,63,74},{0,49,59},{0,33,43},{0,10,22},{0,0,0},{0,101,109},{0,88,96},{0,76,83},{0,63,69},{0,49,55},{0,34,39},{0,10,18},{0,0,0},{0,101,102},{0,88,90},{0,76,77},{0,63,64},{0,49,50},{0,34,35},{0,10,13},{0,0,0},{0,101,96},{0,88,83},{0,76,71},{0,63,58},{0,49,44},{0,34,30},{0,10,8},{0,0,0}, -{0,101,88},{0,88,76},{0,76,65},{0,63,53},{0,49,39},{0,34,25},{0,10,5},{0,0,0},{0,101,79},{0,88,69},{0,76,58},{0,62,47},{0,49,34},{0,34,20},{0,10,2},{0,0,0},{0,101,72},{2,88,62},{0,76,52},{0,62,42},{0,49,29},{0,34,14},{0,10,1},{0,0,0},{1,101,66},{5,88,56},{0,76,47},{0,63,37},{0,49,24},{0,34,9},{0,10,0},{0,0,0}, -{0,94,173},{0,82,153},{0,70,134},{0,57,114},{0,41,94},{0,25,74},{0,6,48},{0,0,6},{0,94,165},{0,82,146},{0,70,127},{0,57,109},{0,42,89},{0,26,69},{0,6,45},{0,0,3},{0,94,156},{0,82,138},{0,70,120},{0,57,103},{0,42,84},{0,26,66},{0,6,42},{0,0,0},{0,94,149},{0,82,132},{0,70,115},{0,57,98},{0,43,80},{0,27,62},{0,6,38},{0,0,0}, -{1,94,142},{0,82,125},{0,70,110},{0,57,93},{0,43,75},{0,27,58},{0,6,34},{0,0,0},{3,94,135},{2,82,119},{0,70,104},{0,57,87},{0,43,71},{0,27,54},{0,7,31},{0,0,0},{5,94,128},{4,82,113},{1,70,98},{0,57,82},{0,43,66},{0,27,49},{0,7,28},{0,0,0},{5,94,121},{4,82,106},{1,71,91},{0,57,77},{0,43,62},{0,28,45},{0,7,24},{0,0,0}, -{6,94,114},{4,82,100},{2,71,86},{0,57,72},{0,43,57},{0,28,41},{0,7,19},{0,0,0},{7,93,106},{5,82,93},{3,70,80},{0,57,67},{0,44,53},{0,29,37},{0,7,15},{0,0,0},{8,93,99},{6,82,87},{4,70,74},{1,57,62},{0,44,48},{0,29,33},{0,7,11},{0,0,0},{9,93,93},{7,82,80},{4,70,68},{1,57,56},{0,44,42},{0,29,28},{0,7,7},{0,0,0}, -{9,93,85},{8,82,73},{5,70,62},{2,57,51},{0,44,37},{0,29,23},{0,7,4},{0,0,0},{10,93,77},{9,82,67},{6,70,56},{2,57,45},{0,44,32},{0,29,17},{0,7,2},{0,0,0},{10,93,70},{11,82,60},{6,70,51},{2,57,40},{0,44,27},{0,29,12},{0,7,1},{0,0,0},{11,93,64},{13,82,54},{6,70,46},{3,57,35},{0,44,23},{0,29,7},{0,7,0},{0,0,0}, -{0,86,167},{0,75,148},{0,63,130},{0,50,111},{0,35,91},{0,18,71},{0,2,46},{0,0,4},{0,86,159},{0,75,141},{0,63,123},{0,50,105},{0,36,86},{0,20,67},{0,3,43},{0,0,1},{0,86,151},{0,75,133},{0,63,116},{0,50,99},{0,36,81},{0,20,64},{0,3,40},{0,0,0},{0,86,144},{0,75,127},{1,63,111},{0,51,94},{0,37,77},{0,21,60},{0,4,36},{0,0,0}, -{2,86,137},{1,75,121},{1,63,106},{0,51,89},{0,37,73},{0,21,56},{0,4,32},{0,0,0},{8,86,131},{6,75,115},{1,64,100},{0,51,84},{0,37,69},{0,21,52},{0,4,29},{0,0,0},{12,86,124},{10,75,109},{2,64,94},{0,51,79},{0,37,64},{0,21,47},{0,4,26},{0,0,0},{13,86,117},{10,75,103},{3,64,89},{0,51,75},{0,37,60},{0,22,43},{0,4,22},{0,0,0}, -{16,86,111},{11,75,97},{5,64,84},{0,51,70},{0,37,55},{0,22,39},{0,4,17},{0,0,0},{19,86,104},{14,75,90},{8,64,78},{1,51,65},{0,38,51},{0,23,35},{0,4,12},{0,0,0},{22,86,97},{16,75,84},{10,64,72},{2,51,60},{0,38,46},{0,23,31},{0,4,9},{0,0,0},{23,86,90},{19,75,78},{11,64,66},{3,51,54},{0,38,41},{0,24,26},{0,5,6},{0,0,0}, -{24,86,83},{22,75,71},{14,64,60},{4,51,49},{0,38,36},{0,24,21},{0,5,3},{0,0,0},{26,86,75},{23,75,65},{16,64,54},{6,51,43},{0,38,30},{0,23,15},{0,4,1},{0,0,0},{27,86,69},{24,75,58},{16,64,49},{6,51,38},{0,38,25},{0,23,10},{0,4,1},{0,0,0},{28,86,63},{24,75,53},{16,64,44},{7,51,34},{0,38,21},{0,23,5},{0,4,0},{0,0,0}, -{12,77,162},{8,67,143},{7,55,126},{3,42,107},{0,27,88},{0,11,68},{0,1,43},{0,0,2},{13,77,154},{10,67,136},{8,55,119},{4,43,102},{1,28,83},{0,12,64},{0,1,40},{0,0,1},{14,77,146},{12,67,128},{8,55,113},{5,43,96},{1,29,78},{0,13,61},{0,1,37},{0,0,0},{14,78,140},{12,67,123},{10,55,108},{5,43,91},{2,30,74},{0,13,57},{0,2,33},{0,0,0}, -{15,78,133},{13,67,117},{10,55,103},{6,43,86},{2,30,70},{0,14,53},{0,2,29},{0,0,0},{20,78,127},{17,67,111},{11,56,97},{6,44,81},{2,31,66},{0,15,49},{0,2,26},{0,0,0},{24,78,121},{20,67,106},{11,56,91},{6,44,76},{2,31,61},{0,15,44},{0,2,23},{0,0,0},{25,78,114},{21,67,100},{12,56,86},{6,45,72},{2,31,57},{0,16,40},{0,2,19},{0,0,0}, -{27,78,108},{22,67,94},{14,56,81},{6,45,68},{2,31,53},{0,16,36},{0,2,14},{0,0,0},{30,78,101},{24,67,87},{16,56,75},{7,45,63},{2,32,48},{0,17,32},{0,2,10},{0,0,0},{32,78,94},{26,67,81},{17,56,69},{8,45,57},{2,32,43},{0,17,28},{0,2,7},{0,0,0},{33,78,87},{28,67,75},{19,56,63},{10,45,51},{2,32,39},{0,17,24},{0,3,5},{0,0,0}, -{34,78,80},{30,67,69},{21,56,57},{10,45,46},{2,32,34},{0,17,19},{0,3,3},{0,0,0},{36,78,73},{31,67,62},{23,56,52},{12,45,41},{2,33,29},{0,17,13},{0,2,1},{0,0,0},{37,78,67},{32,67,57},{23,56,47},{12,45,37},{2,33,24},{0,17,9},{0,2,1},{0,0,0},{38,78,61},{32,67,52},{24,56,43},{12,45,33},{2,33,20},{0,17,5},{0,2,0},{0,0,0}, -{28,68,156},{19,58,138},{17,47,122},{7,35,103},{0,20,84},{0,5,65},{0,0,40},{0,0,0},{31,68,149},{23,58,131},{19,48,115},{9,36,98},{2,21,80},{0,5,61},{0,0,36},{0,0,0},{33,68,142},{27,58,124},{20,48,109},{11,36,92},{3,22,75},{0,5,57},{0,0,33},{0,0,0},{33,69,136},{28,59,119},{22,48,104},{12,36,88},{4,23,71},{0,6,53},{0,0,29},{0,0,0}, -{33,69,129},{28,59,113},{22,48,99},{13,36,83},{4,23,67},{0,7,50},{0,0,26},{0,0,0},{34,70,123},{29,59,107},{23,49,93},{14,37,78},{4,24,62},{0,8,46},{0,0,23},{0,0,0},{36,70,117},{32,59,102},{23,49,88},{15,37,73},{4,24,58},{0,8,42},{0,0,19},{0,0,0},{37,70,110},{33,59,96},{24,49,83},{14,38,69},{4,25,54},{0,9,38},{0,1,15},{0,0,0}, -{39,70,104},{34,59,90},{24,49,78},{14,38,65},{4,25,50},{0,9,34},{0,1,11},{0,0,0},{41,70,97},{34,59,85},{25,49,73},{14,38,60},{4,26,46},{0,10,30},{0,1,8},{0,0,0},{41,70,91},{35,59,79},{26,49,67},{15,38,55},{4,26,41},{0,10,26},{0,1,6},{0,0,0},{42,70,85},{36,60,73},{28,49,61},{17,38,49},{5,26,37},{0,10,22},{0,1,4},{0,0,0}, -{43,70,78},{36,60,67},{28,49,55},{17,38,44},{5,26,32},{0,10,17},{0,1,2},{0,0,0},{44,70,71},{37,60,60},{29,49,50},{18,39,40},{5,27,27},{0,11,11},{0,1,1},{0,0,0},{45,70,65},{38,60,55},{29,49,45},{18,39,35},{5,27,23},{0,11,8},{0,1,1},{0,0,0},{46,70,59},{39,60,50},{30,49,41},{18,39,31},{6,28,19},{0,11,5},{0,1,0},{0,0,0}, -{37,58,151},{30,49,133},{25,38,118},{14,25,100},{5,12,82},{0,2,63},{0,0,38},{0,0,0},{40,58,144},{33,49,127},{27,39,112},{17,26,95},{6,12,78},{1,2,59},{0,0,35},{0,0,0},{41,58,137},{36,49,120},{27,39,106},{18,26,89},{7,13,73},{1,2,56},{0,0,32},{0,0,0},{41,59,131},{36,50,115},{29,39,101},{19,27,85},{8,14,69},{1,3,52},{0,0,28},{0,0,0}, -{41,60,125},{36,50,110},{29,39,96},{20,27,80},{8,14,65},{1,3,48},{0,0,25},{0,0,0},{42,61,119},{37,50,104},{30,40,90},{20,28,76},{8,15,60},{1,4,44},{0,0,21},{0,0,0},{44,61,113},{38,50,99},{30,40,85},{20,29,71},{8,15,56},{1,4,40},{0,0,17},{0,0,0},{45,61,107},{38,51,93},{30,41,81},{20,30,67},{9,16,52},{1,4,36},{0,1,13},{0,0,0}, -{46,61,101},{39,51,88},{30,41,76},{20,30,63},{9,16,48},{1,4,32},{0,1,10},{0,0,0},{47,61,95},{40,51,83},{31,41,71},{20,30,58},{9,17,44},{1,5,29},{0,1,7},{0,0,0},{47,61,89},{41,51,77},{31,41,66},{21,30,53},{9,17,40},{1,5,25},{0,1,5},{0,0,0},{47,62,83},{41,52,71},{33,41,60},{23,30,48},{10,18,36},{1,5,20},{0,1,3},{0,0,0}, -{48,62,76},{41,52,65},{33,41,54},{23,30,43},{10,18,31},{1,5,15},{0,1,2},{0,0,0},{49,62,69},{42,52,59},{34,41,48},{23,31,38},{9,19,26},{1,6,10},{0,1,1},{0,0,0},{49,62,64},{42,52,54},{34,41,44},{23,31,34},{10,19,21},{1,6,7},{0,1,1},{0,0,0},{50,62,58},{43,52,49},{35,41,40},{23,31,30},{11,20,17},{2,6,4},{0,1,0},{0,0,0}, -{46,48,146},{41,39,129},{33,29,114},{23,15,97},{10,3,79},{1,0,60},{0,0,36},{0,0,0},{47,48,139},{42,39,123},{34,29,108},{24,16,92},{11,3,75},{2,0,57},{0,0,33},{0,0,0},{48,48,132},{43,39,116},{34,29,102},{25,16,86},{12,3,70},{2,0,54},{0,0,30},{0,0,0},{48,49,127},{43,40,111},{35,30,97},{26,17,82},{13,4,66},{2,0,50},{0,0,26},{0,0,0}, -{48,50,121},{43,40,106},{35,30,92},{26,18,77},{13,5,62},{2,0,46},{0,0,23},{0,0,0},{49,51,115},{44,41,100},{35,31,87},{25,19,73},{13,5,58},{2,0,42},{0,0,19},{0,0,0},{50,51,109},{44,41,95},{35,31,82},{25,20,69},{13,5,54},{2,0,38},{0,0,15},{0,0,0},{51,52,103},{43,42,90},{35,32,78},{25,21,65},{14,6,50},{3,0,34},{0,0,11},{0,0,0}, -{52,52,97},{44,42,85},{35,32,74},{25,21,61},{14,7,46},{3,0,30},{0,0,8},{0,0,0},{52,52,92},{45,43,80},{36,33,69},{26,22,56},{14,8,42},{3,1,27},{0,0,6},{0,0,0},{52,52,86},{46,43,74},{36,33,64},{27,22,51},{14,8,38},{3,1,23},{0,0,4},{0,0,0},{52,53,80},{45,43,68},{37,34,58},{28,23,46},{15,9,34},{3,1,18},{0,0,2},{0,0,0}, -{52,53,73},{45,43,63},{37,34,52},{28,23,41},{15,9,29},{3,1,13},{0,0,1},{0,0,0},{53,53,67},{46,43,57},{38,33,46},{28,23,36},{14,10,24},{3,1,8},{0,0,0},{0,0,0},{53,53,62},{46,43,52},{38,33,42},{28,23,32},{15,10,19},{3,1,5},{0,0,0},{0,0,0},{54,53,57},{47,44,48},{39,34,38},{28,24,28},{16,11,15},{4,2,3},{0,0,0},{0,0,0}}; -// START - -#define PC (16*16*8) -#define PM ( 16*8) -#define PY ( 8) -#define PK ( 1) -#define RC (7) -#define RM (15) -#define RY (15) -#define RK (7) - -static inline double clip01(double x) { - return (x < 0) ? 0 : ((x > 1) ? 1 : x); -} - -void old_getRGB(GfxColor *color, GfxRGB *rgb) -{ - double c, m, y, aw, ac, am, ay, ar, ag, ab; - - c = clip01(color->c[0] + color->c[3]); - m = clip01(color->c[1] + color->c[3]); - y = clip01(color->c[2] + color->c[3]); - aw = (1-c) * (1-m) * (1-y); - ac = c * (1-m) * (1-y); - am = (1-c) * m * (1-y); - ay = (1-c) * (1-m) * y; - ar = (1-c) * m * y; - ag = c * (1-m) * y; - ab = c * m * (1-y); - rgb->r = clip01(aw + 0.9137*am + 0.9961*ay + 0.9882*ar); - rgb->g = clip01(aw + 0.6196*ac + ay + 0.5176*ag); - rgb->b = clip01(aw + 0.7804*ac + 0.5412*am + 0.0667*ar + 0.2118*ag + 0.4863*ab); -} - -int check(float c, float m, float y, float k, float r, float g, float b) -{ - GfxRGB rgb2; - memset(&rgb2,0,sizeof(GfxRGB)); - GfxColor col; - col.c[0] = c; - col.c[1] = m; - col.c[2] = y; - col.c[3] = k; - old_getRGB(&col, &rgb2); - - double dr = r - rgb2.r; - double dg = g - rgb2.g; - double db = b - rgb2.b; - if(sqrt(dr*dr+dg*dg+db*db) > 0.5) { - printf("%f %f %f %f -> %02x%02x%02x / %02x%02x%02x\n", - c,m,y,k, - (int)(r*255),(int)(g*255),(int)(b*255), - (int)(rgb2.r*255), (int)(rgb2.g*255), (int)(rgb2.b*255)); - return 0; - } - return 1; -} -void convert_cmyk2rgb(float c,float m,float y,float k, unsigned char*r, unsigned char*g, unsigned char*b) -{ - c = c<0?0:(c>1?1:c<=1?c:0.5); - m = m<0?0:(m>1?1:m<=1?m:0.5); - y = y<0?0:(y>1?1:y<=1?y:0.5); - k = k<0?0:(k>1?1:k<=1?k:0.5); - - int cc = (int)(c*7.0); - int mm = (int)(m*15.0); - int yy = (int)(y*15.0); - int kk = (int)(k*7.0); - - float rc = c*7.0 - cc; - float rm = m*15.0 - mm; - float ry = y*15.0 - yy; - float rk = k*7.0 - kk; - - int pp = cc*PC + mm*PM + yy*PY + kk*PK; - int pc = cc>=RC?pp:pp + PC; - int pm = mm>=RM?pp:pp + PM; - int py = yy>=RY?pp:pp + PY; - int pk = kk>=RK?pp:pp + PK; - - int rr = (int)((int)cmyk2rgb[pp].r - + ((int)cmyk2rgb[pc].r - (int)cmyk2rgb[pp].r)*rc - + ((int)cmyk2rgb[pm].r - (int)cmyk2rgb[pp].r)*rm - + ((int)cmyk2rgb[py].r - (int)cmyk2rgb[pp].r)*ry - + ((int)cmyk2rgb[pk].r - (int)cmyk2rgb[pp].r)*rk); - int gg = (int)((int)cmyk2rgb[pp].g - + ((int)cmyk2rgb[pc].g - (int)cmyk2rgb[pp].g)*rc - + ((int)cmyk2rgb[pm].g - (int)cmyk2rgb[pp].g)*rm - + ((int)cmyk2rgb[py].g - (int)cmyk2rgb[pp].g)*ry - + ((int)cmyk2rgb[pk].g - (int)cmyk2rgb[pp].g)*rk); - int bb = (int)((int)cmyk2rgb[pp].b - + ((int)cmyk2rgb[pc].b - (int)cmyk2rgb[pp].b)*rc - + ((int)cmyk2rgb[pm].b - (int)cmyk2rgb[pp].b)*rm - + ((int)cmyk2rgb[py].b - (int)cmyk2rgb[pp].b)*ry - + ((int)cmyk2rgb[pk].b - (int)cmyk2rgb[pp].b)*rk); - *r = rr<0?0:(rr>255?255:rr); - *g = gg<0?0:(gg>255?255:gg); - *b = bb<0?0:(bb>255?255:bb); - - int t; - float r2=0,g2=0,b2=0; - for(t=0;t<16;t++) { - int p2 = pp; - if(t&1) p2+=(pc-pp); - if(t&2) p2+=(pm-pp); - if(t&4) p2+=(py-pp); - if(t&8) p2+=(pk-pp); - float rrc = t&1?rc:1-rc; - float rrm = t&2?rm:1-rm; - float rry = t&4?ry:1-ry; - float rrk = t&8?rk:1-rk; - float f = rrc*rrm*rry*rrk; - r2 += cmyk2rgb[p2].r*f; - g2 += cmyk2rgb[p2].g*f; - b2 += cmyk2rgb[p2].b*f; - } - - if(r2<0)r2=0; if(r2>255)r2=255; - if(g2<0)g2=0; if(g2>255)g2=255; - if(b2<0)b2=0; if(b2>255)b2=255; - - *r = (unsigned char)r2; - *g = (unsigned char)g2; - *b = (unsigned char)b2; - - /*f(!check(c,m,y,k, *r/255.0, *g/255.0, *b/255.0)) { - for(t=0;t<16;t++) { - int p2 = pp; - if(t&1) p2+=(pc-pp); - if(t&2) p2+=(pm-pp); - if(t&4) p2+=(py-pp); - if(t&8) p2+=(pk-pp); - float rrc = t&1?rc:1-rc; - float rrm = t&2?rm:1-rm; - float rry = t&4?ry:1-ry; - float rrk = t&8?rk:1-rk; - float f = rrc*rrm*rry*rrk; - //printf("%d%d%d%d %f %02x%02x%02x\n", !!(t&8),!!(t&4),!!(t&2),!!(t&1), f, cmyk2rgb[p2].r, cmyk2rgb[p2].g, cmyk2rgb[p2].b); - } - }*/ -} - -// END diff --git a/pdf2swf/xpdf/cmyk.h b/pdf2swf/xpdf/cmyk.h deleted file mode 100644 index 1efb467..0000000 --- a/pdf2swf/xpdf/cmyk.h +++ /dev/null @@ -1,4 +0,0 @@ -#ifndef __cmyk_h__ -#define __cmyk_h__ -void convert_cmyk2rgb(float c,float m,float y,float k, unsigned char*r, unsigned char*g, unsigned char*b); -#endif diff --git a/pdf2swf/xpdf/config.h b/pdf2swf/xpdf/config.h deleted file mode 100644 index 4c8f756..0000000 --- a/pdf2swf/xpdf/config.h +++ /dev/null @@ -1,112 +0,0 @@ -//======================================================================== -// -// config.h -// -// Copyright 1996-2005 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef CONFIG_H -#define CONFIG_H - -//------------------------------------------------------------------------ -// version -//------------------------------------------------------------------------ - -// xpdf version -#define xpdfVersion "3.01" -#define xpdfVersionNum 3.01 -#define xpdfMajorVersion 3 -#define xpdfMinorVersion 1 -#define xpdfUpdateVersion 0 -#define xpdfMajorVersionStr "3" -#define xpdfMinorVersionStr "1" -#define xpdfUpdateVersionStr "0" - -// supported PDF version -#define supportedPDFVersionStr "1.5" -#define supportedPDFVersionNum 1.5 - -// copyright notice -#define xpdfCopyright "Copyright 1996-2005 Glyph & Cog, LLC" - -// Windows resource file stuff -#define winxpdfVersion "WinXpdf 3.01" -#define xpdfCopyrightAmp "Copyright 1996-2005 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) && !defined(__CYGWIN32__)) -#define xpdfUserConfigFile "xpdfrc" -#else -#define xpdfUserConfigFile ".xpdfrc" -#endif - -// system config file name (set via the configure script) -#ifdef SYSTEM_XPDFRC -#define xpdfSysConfigFile SYSTEM_XPDFRC -#else -// under Windows, we get the directory with the executable and then -// append this file name -#define xpdfSysConfigFile "xpdfrc" -#endif - -//------------------------------------------------------------------------ -// X-related constants -//------------------------------------------------------------------------ - -// default maximum size of color cube to allocate -#define defaultRGBCube 5 - -// number of fonts (combined t1lib, FreeType, X server) to cache -#define xOutFontCacheSize 64 - -// number of Type 3 fonts to cache -#define xOutT3FontCacheSize 8 - -//------------------------------------------------------------------------ -// popen -//------------------------------------------------------------------------ - -#if defined(_MSC_VER) || defined(__BORLANDC__) -#define popen _popen -#define pclose _pclose -#endif - -#if defined(VMS) || defined(VMCMS) || defined(DOS) || defined(OS2) || defined(__EMX__) || defined(WIN32) || defined(__DJGPP__) || defined(MACOS) -#define POPEN_READ_MODE "rb" -#else -#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/pdf2swf/xpdf/gfile.cc b/pdf2swf/xpdf/gfile.cc deleted file mode 100644 index 11f5cf6..0000000 --- a/pdf2swf/xpdf/gfile.cc +++ /dev/null @@ -1,705 +0,0 @@ -//======================================================================== -// -// gfile.cc -// -// Miscellaneous file and directory name manipulation. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#include - -#ifndef WIN32 -# if defined(MACOS) -# include -# elif !defined(ACORN) -# include -# include -# include -# endif -# include -# include -# if !defined(VMS) && !defined(ACORN) && !defined(MACOS) -# include -# endif -# if defined(VMS) && (__DECCXX_VER < 50200000) -# include -# endif -#endif // WIN32 -#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(__EMX__) || defined(WIN32) - //---------- OS/2+EMX and Win32 ---------- - 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("@"); - -#elif defined(MACOS) - //---------- MacOS ---------- - 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 (GetCurrentDirectory(sizeof(buf), buf)) -#elif defined(ACORN) - if (strcpy(buf, "@")) -#elif defined(MACOS) - if (strcpy(buf, ":")) -#else - if (getcwd(buf, sizeof(buf))) -#endif - return new GString(buf); - return new GString(); -} - -GString *appendToPath(GString *path, 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); - GetFullPathName(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(MACOS) - //---------- MacOS ---------- - 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, p - fileName); - if ((p = strrchr(fileName, '\\'))) - return new GString(fileName, p - fileName); - if ((p = strrchr(fileName, ':'))) - return new GString(fileName, 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(); - -#elif defined(MACOS) - //---------- MacOS ---------- - 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, 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] == '$'; - -#elif defined(MACOS) - //---------- MacOS ---------- - 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 (!GetFullPathName(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; - -#elif defined(MACOS) - //---------- MacOS ---------- - path->del(0, 1); - 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 = p2 - p1) > PATH_MAX) - n = PATH_MAX; - strncpy(buf, p1, n); - buf[n] = '\0'; - if ((pw = getpwnam(buf))) { - path->del(0, 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 -} - -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, char *mode, char *ext) { -#if defined(WIN32) - //---------- Win32 ---------- - char *s; - - if (!(s = _tempnam(getenv("TEMP"), NULL))) { - return gFalse; - } - *name = new GString(s); - free(s); - if (ext) { - (*name)->append(ext); - } - if (!(*f = fopen((*name)->getCString(), mode))) { - delete (*name); - return gFalse; - } - return gTrue; -#elif defined(VMS) || defined(__EMX__) || defined(ACORN) || defined(MACOS) - //---------- 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); - 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(), 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; - return gFalse; - } - return gTrue; -#endif -} - -GBool executeCommand(char *cmd) { -#ifdef VMS - return system(cmd) ? gTrue : gFalse; -#else - return system(cmd) ? gFalse : gTrue; -#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; -} - -//------------------------------------------------------------------------ -// GDir and GDirEntry -//------------------------------------------------------------------------ - -GDirEntry::GDirEntry(char *dirPath, char *nameA, GBool doStat) { -#ifdef VMS - char *p; -#elif defined(WIN32) - int fa; - GString *s; -#elif defined(ACORN) -#else - struct stat st; - GString *s; -#endif - - name = new GString(nameA); - dir = gFalse; - if (doStat) { -#ifdef VMS - if (!strcmp(nameA, "-") || - ((p = strrchr(nameA, '.')) && !strncmp(p, ".DIR;", 5))) - dir = gTrue; -#elif defined(ACORN) -#else - s = new GString(dirPath); - appendToPath(s, nameA); -#ifdef WIN32 - fa = GetFileAttributes(s->getCString()); - dir = (fa != 0xFFFFFFFF && (fa & FILE_ATTRIBUTE_DIRECTORY)); -#else - if (stat(s->getCString(), &st) == 0) - dir = S_ISDIR(st.st_mode); -#endif - delete s; -#endif - } -} - -GDirEntry::~GDirEntry() { - delete name; -} - -GDir::GDir(char *name, GBool doStatA) { - path = new GString(name); - doStat = doStatA; -#if defined(WIN32) - GString *tmp; - - tmp = path->copy(); - tmp->append("/*.*"); - hnd = FindFirstFile(tmp->getCString(), &ffd); - delete tmp; -#elif defined(ACORN) -#elif defined(MACOS) -#else - dir = opendir(name); -#ifdef VMS - needParent = strchr(name, '[') != NULL; -#endif -#endif -} - -GDir::~GDir() { - delete path; -#if defined(WIN32) - if (hnd) { - FindClose(hnd); - hnd = NULL; - } -#elif defined(ACORN) -#elif defined(MACOS) -#else - if (dir) - closedir(dir); -#endif -} - -GDirEntry *GDir::getNextEntry() { - GDirEntry *e; - -#if defined(WIN32) - if (hnd) { - e = new GDirEntry(path->getCString(), ffd.cFileName, doStat); - if (hnd && !FindNextFile(hnd, &ffd)) { - FindClose(hnd); - hnd = NULL; - } - } else { - e = NULL; - } -#elif defined(ACORN) -#elif defined(MACOS) -#elif defined(VMS) - struct dirent *ent; - e = NULL; - if (dir) { - if (needParent) { - e = new GDirEntry(path->getCString(), "-", doStat); - needParent = gFalse; - return e; - } - ent = readdir(dir); - if (ent) { - e = new GDirEntry(path->getCString(), ent->d_name, doStat); - } - } -#else - struct dirent *ent; - e = NULL; - if (dir) { - ent = readdir(dir); - if (ent && !strcmp(ent->d_name, ".")) { - ent = readdir(dir); - } - if (ent) { - e = new GDirEntry(path->getCString(), ent->d_name, doStat); - } - } -#endif - - return e; -} - -void GDir::rewind() { -#ifdef WIN32 - GString *tmp; - - if (hnd) - FindClose(hnd); - tmp = path->copy(); - tmp->append("/*.*"); - hnd = FindFirstFile(tmp->getCString(), &ffd); - delete tmp; -#elif defined(ACORN) -#elif defined(MACOS) -#else - if (dir) - rewinddir(dir); -#ifdef VMS - needParent = strchr(path->getCString(), '[') != NULL; -#endif -#endif -} diff --git a/pdf2swf/xpdf/gfile.h b/pdf2swf/xpdf/gfile.h deleted file mode 100644 index 82f1d7a..0000000 --- a/pdf2swf/xpdf/gfile.h +++ /dev/null @@ -1,138 +0,0 @@ -//======================================================================== -// -// gfile.h -// -// Miscellaneous file and directory name manipulation. -// -// Copyright 1996-2003 Glyph & Cog, LLC -// -//======================================================================== - -#ifndef GFILE_H -#define GFILE_H - -#include -#include -#include -#if defined(WIN32) -# include -# ifdef FPTEX -# include -# else -# include -# endif -#elif defined(ACORN) -#elif defined(MACOS) -# include -#else -# include -# include -# ifdef VMS -# include "vms_dirent.h" -# elif HAVE_DIRENT_H -# include -# define NAMLEN(d) strlen((d)->d_name) -# else -# define dirent direct -# define NAMLEN(d) (d)->d_namlen -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -# endif -#endif -#include "gtypes.h" - -class GString; - -//------------------------------------------------------------------------ - -// Get home directory path. -extern GString *getHomeDir(); - -// Get current directory. -extern GString *getCurrentDir(); - -// Append a file name to a path string. may be an empty -// string, denoting the current directory). Returns . -extern GString *appendToPath(GString *path, char *fileName); - -// Grab the path from the front of the file name. If there is no -// directory component in , 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); - -// Get the modification time for . Returns 0 if there is an -// error. -extern time_t getModTime(char *fileName); - -// Create a temporary file and open it for writing. If 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 string -// should be "w" or "wb". Returns true on success. -extern GBool openTempFile(GString **name, FILE **f, char *mode, char *ext); - -// Execute . Returns true on success. -extern GBool executeCommand(char *cmd); - -// Just like fgets, but handles Unix, Mac, and/or DOS end-of-line -// conventions. -extern char *getLine(char *buf, int size, FILE *f); - -//------------------------------------------------------------------------ -// GDir and GDirEntry -//------------------------------------------------------------------------ - -class GDirEntry { -public: - - GDirEntry(char *dirPath, char *nameA, GBool doStat); - ~GDirEntry(); - GString *getName() { return name; } - GBool isDir() { return dir; } - -private: - - GString *name; // dir/file name - GBool dir; // is it a directory? -}; - -class GDir { -public: - - GDir(char *name, GBool doStatA = gTrue); - ~GDir(); - GDirEntry *getNextEntry(); - void rewind(); - -private: - - GString *path; // directory path - GBool doStat; // call stat() for each entry? -#if defined(WIN32) - WIN32_FIND_DATA ffd; - HANDLE hnd; -#elif defined(ACORN) -#elif defined(MACOS) -#else - DIR *dir; // the DIR structure from opendir() -#ifdef VMS - GBool needParent; // need to return an entry for [-] -#endif -#endif -}; - -#endif diff --git a/pdf2swf/xpdf/gmem.c b/pdf2swf/xpdf/gmem.c deleted file mode 100644 index a0f2cf5..0000000 --- a/pdf2swf/xpdf/gmem.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * gmem.c - * - * Memory routines with out-of-memory checking. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#include -#include -#include -#include -#include -#include "gmem.h" - -#ifdef DEBUG_MEM - -typedef struct _GMemHdr { - int size; - int index; - struct _GMemHdr *next; -} GMemHdr; - -#define gMemHdrSize ((sizeof(GMemHdr) + 7) & ~7) -#define gMemTrlSize (sizeof(long)) - -#if gmemTrlSize==8 -#define gMemDeadVal 0xdeadbeefdeadbeefUL -#else -#define gMemDeadVal 0xdeadbeefUL -#endif - -/* round data size so trailer will be aligned */ -#define gMemDataSize(size) \ - ((((size) + gMemTrlSize - 1) / gMemTrlSize) * gMemTrlSize) - -#define gMemNLists 64 -#define gMemListShift 4 -#define gMemListMask (gMemNLists - 1) -static GMemHdr *gMemList[gMemNLists] = { - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, - NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL -}; - -static int gMemIndex = 0; -static int gMemAlloc = 0; -static int gMemInUse = 0; - -#endif /* DEBUG_MEM */ - -void *gmalloc(int size) { -#ifdef DEBUG_MEM - int size1; - char *mem; - GMemHdr *hdr; - void *data; - int lst; - unsigned long *trl, *p; - - if (size == 0) - return NULL; - size1 = gMemDataSize(size); - if (!(mem = (char *)malloc(size1 + gMemHdrSize + gMemTrlSize))) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - hdr = (GMemHdr *)mem; - data = (void *)(mem + gMemHdrSize); - trl = (unsigned long *)(mem + gMemHdrSize + size1); - hdr->size = size; - hdr->index = gMemIndex++; - lst = ((int)hdr >> gMemListShift) & gMemListMask; - hdr->next = gMemList[lst]; - gMemList[lst] = hdr; - ++gMemAlloc; - gMemInUse += size; - for (p = (unsigned long *)data; p <= trl; ++p) - *p = gMemDeadVal; - return data; -#else - void *p; - - if (size == 0) - return NULL; - if (!(p = malloc(size))) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - return p; -#endif -} - -void *grealloc(void *p, int size) { -#ifdef DEBUG_MEM - GMemHdr *hdr; - void *q; - int oldSize; - - if (size == 0) { - if (p) - gfree(p); - return NULL; - } - if (p) { - hdr = (GMemHdr *)((char *)p - gMemHdrSize); - oldSize = 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) { - if (p) - free(p); - return NULL; - } - if (p) - q = realloc(p, size); - else - q = malloc(size); - if (!q) { - fprintf(stderr, "Out of memory\n"); - exit(1); - } - return q; -#endif -} - -void *gmallocn(int nObjs, int objSize) { - int n; - - n = nObjs * objSize; - if (objSize == 0 || n / objSize != nObjs) { - fprintf(stderr, "Bogus memory allocation size\n"); - exit(1); - } - return gmalloc(n); -} - -void *greallocn(void *p, int nObjs, int objSize) { - int n; - - n = nObjs * objSize; - if (objSize == 0 || n / objSize != nObjs) { - fprintf(stderr, "Bogus memory allocation size\n"); - exit(1); - } - return grealloc(p, n); -} - -void gfree(void *p) { -#ifdef DEBUG_MEM - int size; - GMemHdr *hdr; - GMemHdr *prevHdr, *q; - int lst; - unsigned long *trl, *clr; - - if (p) { - hdr = (GMemHdr *)((char *)p - gMemHdrSize); - lst = ((int)hdr >> gMemListShift) & gMemListMask; - for (prevHdr = NULL, q = gMemList[lst]; q; prevHdr = q, q = q->next) { - if (q == hdr) - break; - } - if (q) { - if (prevHdr) - prevHdr->next = hdr->next; - else - gMemList[lst] = hdr->next; - --gMemAlloc; - gMemInUse -= hdr->size; - size = gMemDataSize(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 { - fprintf(stderr, "Attempted to free bad address %p\n", p); - } - } -#else - if (p) - free(p); -#endif -} - -#ifdef DEBUG_MEM -void gMemReport(FILE *f) { - GMemHdr *p; - int lst; - - fprintf(f, "%d memory allocations in all\n", gMemIndex); - if (gMemAlloc > 0) { - fprintf(f, "%d memory blocks left allocated:\n", gMemAlloc); - fprintf(f, " index size\n"); - fprintf(f, "-------- --------\n"); - for (lst = 0; lst < gMemNLists; ++lst) { - for (p = gMemList[lst]; p; p = p->next) - fprintf(f, "%8d %8d\n", p->index, p->size); - } - } else { - fprintf(f, "No memory blocks left allocated\n"); - } -} -#endif - -char *copyString(char *s) { - char *s1; - - s1 = (char *)gmalloc(strlen(s) + 1); - strcpy(s1, s); - return s1; -} diff --git a/pdf2swf/xpdf/gmem.h b/pdf2swf/xpdf/gmem.h deleted file mode 100644 index e74d182..0000000 --- a/pdf2swf/xpdf/gmem.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * gmem.h - * - * Memory routines with out-of-memory checking. - * - * Copyright 1996-2003 Glyph & Cog, LLC - */ - -#ifndef GMEM_H -#define GMEM_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Same as malloc, but prints error message and exits if malloc() - * returns NULL. - */ -extern void *gmalloc(int size); - -/* - * Same as realloc, but prints error message and exits if realloc() - * returns NULL. If

is NULL, calls malloc instead of realloc(). - */ -extern void *grealloc(void *p, int size); - -/* - * 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); -extern void *greallocn(void *p, int nObjs, int objSize); - -/* - * Same as free, but checks for and ignores NULL pointers. - */ -extern void gfree(void *p); - -#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(char *s); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/pdf2swf/xpdf/gtypes.h b/pdf2swf/xpdf/gtypes.h deleted file mode 100644 index 9f64f57..0000000 --- a/pdf2swf/xpdf/gtypes.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * 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 , - * 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 -- 1.7.10.4