diff options
author | Ray Johnston <ray.johnston@artifex.com> | 2008-08-08 04:22:38 +0000 |
---|---|---|
committer | Ray Johnston <ray.johnston@artifex.com> | 2008-08-08 04:22:38 +0000 |
commit | 34f0b7f064072fabdbe47ab1a15d4f1341a0417d (patch) | |
tree | 5079325b87674bd54b7f244203f2364817a6ce1f /gs/Resource | |
parent | 7a31db6d4142087d29c17e875ef2de1727b9f8b2 (diff) |
Massive commit discussed before the freeze to move the PostScript initialization
files to Resource/Init. This obviates the need for geninit when COMPILE_INITS=1.
A followup change will enhance mkromfs to allow it to 'strip' comments and white
space from PostScript input files somewhat reducing the compressed storage needed
for the files in Resource/Init. All files mentioned in int.mak with 'ADDMOD ...
-ps ...' are included as well as those that would have been included via gs_init.ps
%% Replace lines.
Builds tested on Windows and Cygwin for the various executables (gs, pcl6, pspcl6
and gxps).
The default LIBPATH and GenericResourceDir are adjusted accordingly.
git-svn-id: http://svn.ghostscript.com/ghostscript/trunk@8954 a1074d23-0009-0410-80fe-cf8c14f379e6
Diffstat (limited to 'gs/Resource')
69 files changed, 29385 insertions, 0 deletions
diff --git a/gs/Resource/Init/FCOfontmap-PCLPS2 b/gs/Resource/Init/FCOfontmap-PCLPS2 new file mode 100644 index 000000000..d0e5ce11e --- /dev/null +++ b/gs/Resource/Init/FCOfontmap-PCLPS2 @@ -0,0 +1,107 @@ +% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ + +% May add general FAPIfontmap records here like this : +/Wingdings-Regular << /Path FCOfontfile2 /FontType 1 /FAPI /UFST /SubfontId 0 /Encoding /Wingdings /Decoding /FCO_Wingdings>> ; + +% Mapping Postscript fonts to pclp2_xj.fco FCO members : +FCOfontfile ReadFCOfontmap: +0 Albertus-Medium +1 Albertus-ExtraBold +2 AntiqueOlive +3 AntiqueOlive-Italic +4 AntiqueOlive-Bold +5 Arial +6 Arial-Italic +7 Arial-Bold +8 Arial-BoldItalic +9 Clarendon-Condensed-Bold +10 Coronet +11 CourierHP +12 CourierHP-Italic +13 CourierHP-Bold +14 CourierHP-BoldItalic +15 Garamond-Antiqua +16 Garamond-Kursiv +17 Garamond-Halbfett +18 Garamond-KursivHalbfett +19 LetterGothic +20 LetterGothic-Italic +21 LetterGothic-Bold +22 Marigold +23 CGOmega +24 CGOmega-Italic +25 CGOmega-Bold +26 CGOmega-BoldItalic +27 SymbolMT SymbolEncoding FCO_Symbol +28 CGTimes +29 CGTimes-Italic +30 CGTimes-Bold +31 CGTimes-BoldItalic +32 TimesNewRoman +33 TimesNewRoman-Italic +34 TimesNewRoman-Bold +35 TimesNewRoman-BoldItalic +36 UniversMedium +37 UniversMedium-Italic +38 Univers-Bold +39 Univers-BoldItalic +40 Univers-Condensed-Medium +41 Univers-Condensed-MediumItalic +42 Univers-Condensed-Bold +43 Univers-Condensed-BoldItalic +44 Courier- +45 Courier-Italic +46 Courier-Bold- +47 Courier-BoldItalic +48 AvantGarde-Book +49 AvantGarde-BookOblique +50 AvantGarde-Demi +51 AvantGarde-DemiOblique +52 Bookman-Light +53 Bookman-LightItalic +54 Bookman-Demi +55 Bookman-DemiItalic +56 Courier +57 Courier-Oblique +58 Courier-Bold +59 Courier-BoldOblique +60 Helvetica +61 Helvetica-Oblique +62 Helvetica-Bold +63 Helvetica-BoldOblique +64 Helvetica-Narrow +65 Helvetica-Narrow-Oblique +66 Helvetica-Narrow-Bold +67 Helvetica-Narrow-BoldOblique +68 NewCenturySchlbk-Roman +69 NewCenturySchlbk-Italic +70 NewCenturySchlbk-Bold +71 NewCenturySchlbk-BoldItalic +72 Palatino-Roman +73 Palatino-Italic +74 Palatino-Bold +75 Palatino-BoldItalic +76 Symbol SymbolEncoding FCO_Symbol +77 Times-Roman +78 Times-Italic +79 Times-Bold +80 Times-BoldItalic +81 ZapfChancery-MediumItalic +82 ZapfDingbats DingbatsEncoding FCO_Dingbats +EndFCOfontmap +%EOF diff --git a/gs/Resource/Init/Fontmap b/gs/Resource/Init/Fontmap new file mode 100644 index 000000000..ae5af96e0 --- /dev/null +++ b/gs/Resource/Init/Fontmap @@ -0,0 +1,4 @@ +%! +% See Fontmap.GS for the syntax of real Fontmap files. +%% Replace 1 (Fontmap.GS) +(Fontmap.GS) .runlibfile diff --git a/gs/Resource/Init/Fontmap.GS b/gs/Resource/Init/Fontmap.GS new file mode 100644 index 000000000..f281d19a8 --- /dev/null +++ b/gs/Resource/Init/Fontmap.GS @@ -0,0 +1,402 @@ +% Copyright (C) 1996, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Fontmap - standard font catalog for Ghostscript. + +% ---------------------------------------------------------------- + +% This file is a catalog of fonts known to Ghostscript. Any font +% that is to be loaded automatically when named must be in this catalog, +% except for fonts that Ghostscript finds automatically in directories +% named in the GS_FONTPATH environment variable. + +% Each font has an entry consisting of three items: +% +% - The name by which the font is known inside Ghostscript +% (a Ghostscript name preceded by a `/', or a string enclosed +% in parentheses). This is used to find the file from which +% a font of a given name should be loaded. +% +% - Information depending on whether this is a real font or a +% font alias: +% +% - For real fonts, the name of the Ghostscript font +% file (a Ghostscript string, enclosed in parentheses). +% The filename should include the extension, which (by +% convention) is `.gsf'. `.pfa' and `.pfb' files are +% also usable as fonts for Ghostscript. +% +% - For font aliases, the name of the font which should +% be used when this one is requested, preceded by a +% `/'. See the entry for Charter below for an example. +% Note that an alias name cannot be enclosed in parentheses. +% +% - At least one space or tab, and a terminating semicolon. + +% The following table is executed as a PostScript file. +% If you add new entries, be sure to copy the punctuation accurately; +% in particular, you must leave at least one space or tab between each +% field in the entry. Also, please read fonts.doc for important information +% about font names. + +% PDF interpreter evaluates hexadecimal escapes in PDF font names before +% looking up the font. When the resulting name cannot be represented using +% PostScript name syntax, the string can be used instead of the name. + +% Note that .pfa and .pfb fonts are compatible with Adobe Type Manager +% and other programs that don't include full PostScript interpreters, +% as well as with PostScript interpreters; .gsf fonts are compatible with +% PostScript interpreters, but not with ATM or similar programs. + +% +% +% Fonts contributed by: +% URW++ Design and Development Incorporated +% Poppenbuetteler Bogen 29A +% D-22399 Hamburg +% Germany +% tel. +49 (40) 60 60 50 +% fax +49 (40) 60 60 51 11 +% http://www.urwpp.de +% for distribution under the GNU License and Aladdin Free Public License. +% See the notice at the head of this Fontmap file for licensing terms. +% Each of these fonts is individually covered by the license: +% for licensing purposes, they are not "part of" any larger entity. +% The following notice applies to these fonts: +% +% Copyright URW Software, Copyright 1994 by URW. +% + +% Actual fonts + +/URWBookmanL-DemiBold (b018015l.pfb) ; +/URWBookmanL-DemiBoldItal (b018035l.pfb) ; +/URWBookmanL-Ligh (b018012l.pfb) ; +/URWBookmanL-LighItal (b018032l.pfb) ; + +/NimbusMonL-Regu (n022003l.pfb) ; +/NimbusMonL-ReguObli (n022023l.pfb) ; +/NimbusMonL-Bold (n022004l.pfb) ; +/NimbusMonL-BoldObli (n022024l.pfb) ; + +/URWGothicL-Book (a010013l.pfb) ; +/URWGothicL-BookObli (a010033l.pfb) ; +/URWGothicL-Demi (a010015l.pfb) ; +/URWGothicL-DemiObli (a010035l.pfb) ; + +/NimbusSanL-Regu (n019003l.pfb) ; +/NimbusSanL-ReguItal (n019023l.pfb) ; +/NimbusSanL-Bold (n019004l.pfb) ; +/NimbusSanL-BoldItal (n019024l.pfb) ; + +/NimbusSanL-ReguCond (n019043l.pfb) ; +/NimbusSanL-ReguCondItal (n019063l.pfb) ; +/NimbusSanL-BoldCond (n019044l.pfb) ; +/NimbusSanL-BoldCondItal (n019064l.pfb) ; + +/URWPalladioL-Roma (p052003l.pfb) ; +/URWPalladioL-Ital (p052023l.pfb) ; +/URWPalladioL-Bold (p052004l.pfb) ; +/URWPalladioL-BoldItal (p052024l.pfb) ; + +/CenturySchL-Roma (c059013l.pfb) ; +/CenturySchL-Ital (c059033l.pfb) ; +/CenturySchL-Bold (c059016l.pfb) ; +/CenturySchL-BoldItal (c059036l.pfb) ; + +/NimbusRomNo9L-Regu (n021003l.pfb) ; +/NimbusRomNo9L-ReguItal (n021023l.pfb) ; +/NimbusRomNo9L-Medi (n021004l.pfb) ; +/NimbusRomNo9L-MediItal (n021024l.pfb) ; + +/StandardSymL (s050000l.pfb) ; + +/URWChanceryL-MediItal (z003034l.pfb) ; + +/Dingbats (d050000l.pfb) ; + +% Aliases + +/Bookman-Demi /URWBookmanL-DemiBold ; +/Bookman-DemiItalic /URWBookmanL-DemiBoldItal ; +/Bookman-Light /URWBookmanL-Ligh ; +/Bookman-LightItalic /URWBookmanL-LighItal ; + +/Courier /NimbusMonL-Regu ; +/Courier-Oblique /NimbusMonL-ReguObli ; +/Courier-Bold /NimbusMonL-Bold ; +/Courier-BoldOblique /NimbusMonL-BoldObli ; + +/AvantGarde-Book /URWGothicL-Book ; +/AvantGarde-BookOblique /URWGothicL-BookObli ; +/AvantGarde-Demi /URWGothicL-Demi ; +/AvantGarde-DemiOblique /URWGothicL-DemiObli ; + +/Helvetica /NimbusSanL-Regu ; +/Helvetica-Oblique /NimbusSanL-ReguItal ; +/Helvetica-Bold /NimbusSanL-Bold ; +/Helvetica-BoldOblique /NimbusSanL-BoldItal ; + +/Helvetica-Narrow /NimbusSanL-ReguCond ; +/Helvetica-Narrow-Oblique /NimbusSanL-ReguCondItal ; +/Helvetica-Narrow-Bold /NimbusSanL-BoldCond ; +/Helvetica-Narrow-BoldOblique /NimbusSanL-BoldCondItal ; + +/Palatino-Roman /URWPalladioL-Roma ; +/Palatino-Italic /URWPalladioL-Ital ; +/Palatino-Bold /URWPalladioL-Bold ; +/Palatino-BoldItalic /URWPalladioL-BoldItal ; + +/NewCenturySchlbk-Roman /CenturySchL-Roma ; +/NewCenturySchlbk-Italic /CenturySchL-Ital ; +/NewCenturySchlbk-Bold /CenturySchL-Bold ; +/NewCenturySchlbk-BoldItalic /CenturySchL-BoldItal ; + +/Times-Roman /NimbusRomNo9L-Regu ; +/Times-Italic /NimbusRomNo9L-ReguItal ; +/Times-Bold /NimbusRomNo9L-Medi ; +/Times-BoldItalic /NimbusRomNo9L-MediItal ; + +/Symbol /StandardSymL ; + +/ZapfChancery-MediumItalic /URWChanceryL-MediItal ; + +/ZapfDingbats /Dingbats ; + +% +% +% Type 1 fonts contributed to the X11R5 distribution. +% + +% The following notice accompanied the Charter fonts. +% +% (c) Copyright 1989-1992, Bitstream Inc., Cambridge, MA. +% +% You are hereby granted permission under all Bitstream propriety rights +% to use, copy, modify, sublicense, sell, and redistribute the 4 Bitstream +% Charter (r) Type 1 outline fonts and the 4 Courier Type 1 outline fonts +% for any purpose and without restriction; provided, that this notice is +% left intact on all copies of such fonts and that Bitstream's trademark +% is acknowledged as shown below on all unmodified copies of the 4 Charter +% Type 1 fonts. +% +% BITSTREAM CHARTER is a registered trademark of Bitstream Inc. + +/CharterBT-Roman (bchr.pfa) ; +/CharterBT-Italic (bchri.pfa) ; +/CharterBT-Bold (bchb.pfa) ; +/CharterBT-BoldItalic (bchbi.pfa) ; + +% Aliases + +/Charter-Roman /CharterBT-Roman ; +/Charter-Italic /CharterBT-Italic ; +/Charter-Bold /CharterBT-Bold ; +/Charter-BoldItalic /CharterBT-BoldItalic ; + +% The following notice accompanied the Utopia font: +% +% Permission to use, reproduce, display and distribute the listed +% typefaces is hereby granted, provided that the Adobe Copyright notice +% appears in all whole and partial copies of the software and that the +% following trademark symbol and attribution appear in all unmodified +% copies of the software: +% +% Copyright (c) 1989 Adobe Systems Incorporated +% Utopia (R) +% Utopia is a registered trademark of Adobe Systems Incorporated +% +% The Adobe typefaces (Type 1 font program, bitmaps and Adobe Font +% Metric files) donated are: +% +% Utopia Regular +% Utopia Italic +% Utopia Bold +% Utopia Bold Italic + +/Utopia-Regular (putr.pfa) ; +/Utopia-Italic (putri.pfa) ; +/Utopia-Bold (putb.pfa) ; +/Utopia-BoldItalic (putbi.pfa) ; + +% +% +% Fonts contributed by URW GmbH for distribution under the GNU License. +% The following notice accompanied these fonts: +% +% U004006T URW Grotesk 2031 Bold PostScript Type 1 Font Program +% U003043T URW Antiqua 2051 Regular Condensed PostScript Type 1 Font Program +% +% Copyright (c) 1992 URW GmbH, Hamburg, Germany +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation; either version 2 of the License, or +% (at your option) later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; wihtout even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +% See the GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program; if not, write to the Free Software +% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 U.S.A. +% +% Address: +% URW GmbH +% PC Support +% Harksheider Strasse 102 +% 2000 Hamburg 65 +% Germany +% Phone: +49 40 60 60 50 (Reception) +% Phone: +49 40 60 60 52 30 (PC Support) +% Fax : +49 40 60 60 52 52 +% + +/URWAntiquaT-RegularCondensed (u003043t.gsf) ; +/URWGroteskT-Bold (u004006t.gsf) ; + +% +% +% Calligraphic Kana fonts. These are distributed under the OFL 1.1: +% +% Copyright (c) 1993, Kevin Hartig (kevin.hartig@gmail.com), +% with Reserved Font Name Calligraphic-Hiragana and Calligraphic-Katakana. +% This Font Software is licensed under the SIL Open Font License, Version 1.1. +% This license is available with an FAQ at: http://scripts.sil.org/OFL + +% Hiragana and Katakana fonts. The character names are inappropriate, +% and the encoding is probably not related to any known standard. + +/Calligraphic-Hiragana (fhirw.gsf) ; +/Calligraphic-Katakana (fkarw.gsf) ; + +% +% +% Public-domain fonts. These have no copyright, and are of unknown quality. + +% Cyrillic fonts. The character names are inappropriate, +% and the encoding is probably not related to any known standard. + +/Shareware-Cyrillic-Regular (fcyr.gsf) ; +/Shareware-Cyrillic-Italic (fcyri.gsf) ; + +% Aliases +/Cyrillic /Cyrillic-Regular ; +/Cyrillic-Regular /Shareware-Cyrillic-Regular ; +/Cyrillic-Italic /Shareware-Cyrillic-Italic ; + +% +% +% Fonts converted from Hershey outlines. These are constructed and +% maintained manually. These are also in the public domain. +% +% The suggested UniqueID's and filenames are constructed differently for +% these than for the ones above, because of the strange way that the Hershey +% fonts were constructed. The scheme for these looks like: +% +% 42TTXY0 +% +% TT = typeface, X = ``class'', Y = variation +% +% The typeface names and numbers are listed in fonts.mak. +% +% class: +% 0 = normal = r +% 1 = simplex = s +% 2 = complex = c +% 3 = triplex = t +% 4 = duplex = d +% +% variation: +% 0 = normal (omitted) +% 1 = oblique = o +% 2 = italic = i +% 3 = bold = b +% 4 = bold oblique = bo +% 5 = bold italic = bi +% + +% Fonts created by Thomas Wolff <wolff@inf.fu-berlin.de>, by adding +% accents, accented characters, and various other non-alphabetics +% to the original Hershey fonts. These are "freeware", not to be sold. + +/Hershey-Gothic-English (hrger.pfa) ; % 5066533 +/Hershey-Gothic-German (hrgrr.pfa) ; +/Hershey-Gothic-Italian (hritr.pfa) ; + +/Hershey-Plain-Duplex (hrpld.pfa) ; +/Hershey-Plain-Duplex-Italic (hrpldi.pfa) ; +/Hershey-Plain-Triplex (hrplt.pfa) ; +/Hershey-Plain-Triplex-Italic (hrplti.pfa) ; + +/Hershey-Script-Complex (hrscc.pfa) ; +/Hershey-Script-Simplex (hrscs.pfa) ; % 5066541 + +% Fonts created algorithmically from the above. + +/Hershey-Gothic-English-Bold (hrgerb.gsf) ; % 5066542 +/Hershey-Gothic-English-Oblique (hrgero.gsf) ; +/Hershey-Gothic-English-SemiBold (hrgerd.gsf) ; +/Hershey-Gothic-German-Bold (hrgrrb.gsf) ; +/Hershey-Gothic-German-Oblique (hrgrro.gsf) ; +/Hershey-Gothic-Italian-Bold (hritrb.gsf) ; +/Hershey-Gothic-Italian-Oblique (hritro.gsf) ; + +/Hershey-Plain-Duplex-Bold (hrpldb.gsf) ; +/Hershey-Plain-Duplex-Bold-Italic (hrpldbi.gsf) ; +/Hershey-Plain-Triplex-Bold (hrpltb.gsf) ; +/Hershey-Plain-Triplex-Bold-Italic (hrpltbi.gsf) ; + +/Hershey-Script-Complex-Bold (hrsccb.gsf) ; +/Hershey-Script-Complex-Oblique (hrscco.gsf) ; +/Hershey-Script-Simplex-Bold (hrscsb.gsf) ; +/Hershey-Script-Simplex-Oblique (hrscso.gsf) ; % 5066556 + +% Fonts consisting only of characters from the original Hershey +% distribution. These are Type 3 fonts. + +/Hershey-Greek-Complex (hrgkc.gsf) ; % 5066557 +/Hershey-Greek-Simplex (hrgks.gsf) ; + +/Hershey-Plain (hrplr.gsf) ; +/Hershey-Plain-Simplex (hrpls.gsf) ; % 5066560 + +% Fonts created algorithmically from the above. + +/Hershey-Plain-Bold (hrplrb.gsf) ; % 5066561 +/Hershey-Plain-Bold-Oblique (hrplrbo.gsf) ; +/Hershey-Plain-Oblique (hrplro.gsf) ; +/Hershey-Plain-Simplex-Bold (hrplsb.gsf) ; +/Hershey-Plain-Simplex-Bold-Oblique (hrplsbo.gsf) ; +/Hershey-Plain-Simplex-Oblique (hrplso.gsf) ; % 5066566 + +% This font, and only this font among the Hershey fonts, uses +% the SymbolEncoding. + +/Hershey-Symbol (hrsyr.gsf) ; % 5066567 + +/Arial /ArialMT ; +/Arial,Bold /Arial-BoldMT ; +/Arial,Italic /Arial-ItalicMT ; +/Arial,BoldItalic /Arial-BoldItalicMT ; + +/TimesNewRoman /TimesNewRomanPSMT ; +/TimesNewRoman,Bold /TimesNewRomanPS-BoldMT ; +/TimesNewRoman,Italic /TimesNewRomanPS-ItalicMT ; +/TimesNewRoman,BoldItalic /TimesNewRomanPS-BoldItalicMT ; + diff --git a/gs/Resource/Init/cidfmap b/gs/Resource/Init/cidfmap new file mode 100644 index 000000000..491bee8f6 --- /dev/null +++ b/gs/Resource/Init/cidfmap @@ -0,0 +1,28 @@ +%! +% $Id$ +% This is a sample map file for CIDFont category. + +% +% The map is a set of records, which must use one of the two formats : +% +% 1. A substutution of a CIF font with another CID font : +% +% /substituted /original ; +% +% Where 'substituted' is a name being used in a document, +% 'original' is a name of an available resource. +% +% 2. A substutution of a CIF font with a True Type font : +% +% /substituted << /FileType /TrueType /Path (path) /SunfontID 1 /CSI [(ordering) supplement] >> ; +% +% Where 'substituted' is a name being used in a document, +% 'path' is a path to a True Type font file, +% 'ordering' is a value of Ordering required for CIDSystemInfo dictionary, +% 'supplement' is a value of Supplement required for CIDSystemInfo dictionary. +% +% Examples : +% +% /ShinGo-Bold /HeiseiKakuGo-W5 ; +% /Ryumin-Medium << /FileType /TrueType /Path (H:/AuxFiles/Fonts/BATANG.TTC) /SubfontID 3 /CSI [(Japan1) 2] >> ; +% diff --git a/gs/Resource/Init/gs_agl.ps b/gs/Resource/Init/gs_agl.ps new file mode 100644 index 000000000..c2f6268af --- /dev/null +++ b/gs/Resource/Init/gs_agl.ps @@ -0,0 +1,1069 @@ +% Copyright (C) 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ + +% This file was derived from the Adobe Glyph List, version 1.2, dated +% 22 Oct 1998, at +% http://partners.adobe.com/asn/developer/typeforum/glyphlist.txt +% That file does not contain any copyright notice. + +% The AdobeGlyphList dictionary maps glyph names to Unicode values. +% Nearly all names map to a single value; however, a few names map to +% multiple values. See the above file, and also +% http://www.adobe.com/devnet/opentype/archives/glyph.html +% for more details. + +/AdobeGlyphList 1500 dict +dup /A 16#0041 put +dup /AE 16#00C6 put +dup /AEacute 16#01FC put +dup /AEsmall 16#F7E6 put +dup /Aacute 16#00C1 put +dup /Aacutesmall 16#F7E1 put +dup /Abreve 16#0102 put +dup /Acircumflex 16#00C2 put +dup /Acircumflexsmall 16#F7E2 put +dup /Acute 16#F6C9 put +dup /Acutesmall 16#F7B4 put +dup /Adieresis 16#00C4 put +dup /Adieresissmall 16#F7E4 put +dup /Agrave 16#00C0 put +dup /Agravesmall 16#F7E0 put +dup /Alpha 16#0391 put +dup /Alphatonos 16#0386 put +dup /Amacron 16#0100 put +dup /Aogonek 16#0104 put +dup /Aring 16#00C5 put +dup /Aringacute 16#01FA put +dup /Aringsmall 16#F7E5 put +dup /Asmall 16#F761 put +dup /Atilde 16#00C3 put +dup /Atildesmall 16#F7E3 put +dup /B 16#0042 put +dup /Beta 16#0392 put +dup /Brevesmall 16#F6F4 put +dup /Bsmall 16#F762 put +dup /C 16#0043 put +dup /Cacute 16#0106 put +dup /Caron 16#F6CA put +dup /Caronsmall 16#F6F5 put +dup /Ccaron 16#010C put +dup /Ccedilla 16#00C7 put +dup /Ccedillasmall 16#F7E7 put +dup /Ccircumflex 16#0108 put +dup /Cdotaccent 16#010A put +dup /Cedillasmall 16#F7B8 put +dup /Chi 16#03A7 put +dup /Circumflexsmall 16#F6F6 put +dup /Csmall 16#F763 put +dup /D 16#0044 put +dup /Dcaron 16#010E put +dup /Dcroat 16#0110 put +dup /Delta [16#2206 16#0394] put +dup /Dieresis 16#F6CB put +dup /DieresisAcute 16#F6CC put +dup /DieresisGrave 16#F6CD put +dup /Dieresissmall 16#F7A8 put +dup /Dotaccentsmall 16#F6F7 put +dup /Dsmall 16#F764 put +dup /E 16#0045 put +dup /Eacute 16#00C9 put +dup /Eacutesmall 16#F7E9 put +dup /Ebreve 16#0114 put +dup /Ecaron 16#011A put +dup /Ecircumflex 16#00CA put +dup /Ecircumflexsmall 16#F7EA put +dup /Edieresis 16#00CB put +dup /Edieresissmall 16#F7EB put +dup /Edotaccent 16#0116 put +dup /Egrave 16#00C8 put +dup /Egravesmall 16#F7E8 put +dup /Emacron 16#0112 put +dup /Eng 16#014A put +dup /Eogonek 16#0118 put +dup /Epsilon 16#0395 put +dup /Epsilontonos 16#0388 put +dup /Esmall 16#F765 put +dup /Eta 16#0397 put +dup /Etatonos 16#0389 put +dup /Eth 16#00D0 put +dup /Ethsmall 16#F7F0 put +dup /Euro 16#20AC put +dup /F 16#0046 put +dup /Fsmall 16#F766 put +dup /G 16#0047 put +dup /Gamma 16#0393 put +dup /Gbreve 16#011E put +dup /Gcaron 16#01E6 put +dup /Gcircumflex 16#011C put +dup /Gcommaaccent 16#0122 put +dup /Gdotaccent 16#0120 put +dup /Grave 16#F6CE put +dup /Gravesmall 16#F760 put +dup /Gsmall 16#F767 put +dup /H 16#0048 put +dup /H18533 16#25CF put +dup /H18543 16#25AA put +dup /H18551 16#25AB put +dup /H22073 16#25A1 put +dup /Hbar 16#0126 put +dup /Hcircumflex 16#0124 put +dup /Hsmall 16#F768 put +dup /Hungarumlaut 16#F6CF put +dup /Hungarumlautsmall 16#F6F8 put +dup /I 16#0049 put +dup /IJ 16#0132 put +dup /Iacute 16#00CD put +dup /Iacutesmall 16#F7ED put +dup /Ibreve 16#012C put +dup /Icircumflex 16#00CE put +dup /Icircumflexsmall 16#F7EE put +dup /Idieresis 16#00CF put +dup /Idieresissmall 16#F7EF put +dup /Idotaccent 16#0130 put +dup /Ifraktur 16#2111 put +dup /Igrave 16#00CC put +dup /Igravesmall 16#F7EC put +dup /Imacron 16#012A put +dup /Iogonek 16#012E put +dup /Iota 16#0399 put +dup /Iotadieresis 16#03AA put +dup /Iotatonos 16#038A put +dup /Ismall 16#F769 put +dup /Itilde 16#0128 put +dup /J 16#004A put +dup /Jcircumflex 16#0134 put +dup /Jsmall 16#F76A put +dup /K 16#004B put +dup /Kappa 16#039A put +dup /Kcommaaccent 16#0136 put +dup /Ksmall 16#F76B put +dup /L 16#004C put +dup /LL 16#F6BF put +dup /Lacute 16#0139 put +dup /Lambda 16#039B put +dup /Lcaron 16#013D put +dup /Lcommaaccent 16#013B put +dup /Ldot 16#013F put +dup /Lslash 16#0141 put +dup /Lslashsmall 16#F6F9 put +dup /Lsmall 16#F76C put +dup /M 16#004D put +dup /Macron 16#F6D0 put +dup /Macronsmall 16#F7AF put +dup /Msmall 16#F76D put +dup /Mu 16#039C put +dup /N 16#004E put +dup /Nacute 16#0143 put +dup /Ncaron 16#0147 put +dup /Ncommaaccent 16#0145 put +dup /Nsmall 16#F76E put +dup /Ntilde 16#00D1 put +dup /Ntildesmall 16#F7F1 put +dup /Nu 16#039D put +dup /O 16#004F put +dup /OE 16#0152 put +dup /OEsmall 16#F6FA put +dup /Oacute 16#00D3 put +dup /Oacutesmall 16#F7F3 put +dup /Obreve 16#014E put +dup /Ocircumflex 16#00D4 put +dup /Ocircumflexsmall 16#F7F4 put +dup /Odieresis 16#00D6 put +dup /Odieresissmall 16#F7F6 put +dup /Ogoneksmall 16#F6FB put +dup /Ograve 16#00D2 put +dup /Ogravesmall 16#F7F2 put +dup /Ohorn 16#01A0 put +dup /Ohungarumlaut 16#0150 put +dup /Omacron 16#014C put +dup /Omega [16#2126 16#03A9] put +dup /Omegatonos 16#038F put +dup /Omicron 16#039F put +dup /Omicrontonos 16#038C put +dup /Oslash 16#00D8 put +dup /Oslashacute 16#01FE put +dup /Oslashsmall 16#F7F8 put +dup /Osmall 16#F76F put +dup /Otilde 16#00D5 put +dup /Otildesmall 16#F7F5 put +dup /P 16#0050 put +dup /Phi 16#03A6 put +dup /Pi 16#03A0 put +dup /Psi 16#03A8 put +dup /Psmall 16#F770 put +dup /Q 16#0051 put +dup /Qsmall 16#F771 put +dup /R 16#0052 put +dup /Racute 16#0154 put +dup /Rcaron 16#0158 put +dup /Rcommaaccent 16#0156 put +dup /Rfraktur 16#211C put +dup /Rho 16#03A1 put +dup /Ringsmall 16#F6FC put +dup /Rsmall 16#F772 put +dup /S 16#0053 put +dup /SF010000 16#250C put +dup /SF020000 16#2514 put +dup /SF030000 16#2510 put +dup /SF040000 16#2518 put +dup /SF050000 16#253C put +dup /SF060000 16#252C put +dup /SF070000 16#2534 put +dup /SF080000 16#251C put +dup /SF090000 16#2524 put +dup /SF100000 16#2500 put +dup /SF110000 16#2502 put +dup /SF190000 16#2561 put +dup /SF200000 16#2562 put +dup /SF210000 16#2556 put +dup /SF220000 16#2555 put +dup /SF230000 16#2563 put +dup /SF240000 16#2551 put +dup /SF250000 16#2557 put +dup /SF260000 16#255D put +dup /SF270000 16#255C put +dup /SF280000 16#255B put +dup /SF360000 16#255E put +dup /SF370000 16#255F put +dup /SF380000 16#255A put +dup /SF390000 16#2554 put +dup /SF400000 16#2569 put +dup /SF410000 16#2566 put +dup /SF420000 16#2560 put +dup /SF430000 16#2550 put +dup /SF440000 16#256C put +dup /SF450000 16#2567 put +dup /SF460000 16#2568 put +dup /SF470000 16#2564 put +dup /SF480000 16#2565 put +dup /SF490000 16#2559 put +dup /SF500000 16#2558 put +dup /SF510000 16#2552 put +dup /SF520000 16#2553 put +dup /SF530000 16#256B put +dup /SF540000 16#256A put +dup /Sacute 16#015A put +dup /Scaron 16#0160 put +dup /Scaronsmall 16#F6FD put +dup /Scedilla [16#015E 16#F6C1] put +dup /Scircumflex 16#015C put +dup /Scommaaccent 16#0218 put +dup /Sigma 16#03A3 put +dup /Ssmall 16#F773 put +dup /T 16#0054 put +dup /Tau 16#03A4 put +dup /Tbar 16#0166 put +dup /Tcaron 16#0164 put +dup /Tcommaaccent [16#0162 16#021A] put +dup /Theta 16#0398 put +dup /Thorn 16#00DE put +dup /Thornsmall 16#F7FE put +dup /Tildesmall 16#F6FE put +dup /Tsmall 16#F774 put +dup /U 16#0055 put +dup /Uacute 16#00DA put +dup /Uacutesmall 16#F7FA put +dup /Ubreve 16#016C put +dup /Ucircumflex 16#00DB put +dup /Ucircumflexsmall 16#F7FB put +dup /Udieresis 16#00DC put +dup /Udieresissmall 16#F7FC put +dup /Ugrave 16#00D9 put +dup /Ugravesmall 16#F7F9 put +dup /Uhorn 16#01AF put +dup /Uhungarumlaut 16#0170 put +dup /Umacron 16#016A put +dup /Uogonek 16#0172 put +dup /Upsilon 16#03A5 put +dup /Upsilon1 16#03D2 put +dup /Upsilondieresis 16#03AB put +dup /Upsilontonos 16#038E put +dup /Uring 16#016E put +dup /Usmall 16#F775 put +dup /Utilde 16#0168 put +dup /V 16#0056 put +dup /Vsmall 16#F776 put +dup /W 16#0057 put +dup /Wacute 16#1E82 put +dup /Wcircumflex 16#0174 put +dup /Wdieresis 16#1E84 put +dup /Wgrave 16#1E80 put +dup /Wsmall 16#F777 put +dup /X 16#0058 put +dup /Xi 16#039E put +dup /Xsmall 16#F778 put +dup /Y 16#0059 put +dup /Yacute 16#00DD put +dup /Yacutesmall 16#F7FD put +dup /Ycircumflex 16#0176 put +dup /Ydieresis 16#0178 put +dup /Ydieresissmall 16#F7FF put +dup /Ygrave 16#1EF2 put +dup /Ysmall 16#F779 put +dup /Z 16#005A put +dup /Zacute 16#0179 put +dup /Zcaron 16#017D put +dup /Zcaronsmall 16#F6FF put +dup /Zdotaccent 16#017B put +dup /Zeta 16#0396 put +dup /Zsmall 16#F77A put +dup /a 16#0061 put +dup /aacute 16#00E1 put +dup /abreve 16#0103 put +dup /acircumflex 16#00E2 put +dup /acute 16#00B4 put +dup /acutecomb 16#0301 put +dup /adieresis 16#00E4 put +dup /ae 16#00E6 put +dup /aeacute 16#01FD put +dup /afii00208 16#2015 put +dup /afii10017 16#0410 put +dup /afii10018 16#0411 put +dup /afii10019 16#0412 put +dup /afii10020 16#0413 put +dup /afii10021 16#0414 put +dup /afii10022 16#0415 put +dup /afii10023 16#0401 put +dup /afii10024 16#0416 put +dup /afii10025 16#0417 put +dup /afii10026 16#0418 put +dup /afii10027 16#0419 put +dup /afii10028 16#041A put +dup /afii10029 16#041B put +dup /afii10030 16#041C put +dup /afii10031 16#041D put +dup /afii10032 16#041E put +dup /afii10033 16#041F put +dup /afii10034 16#0420 put +dup /afii10035 16#0421 put +dup /afii10036 16#0422 put +dup /afii10037 16#0423 put +dup /afii10038 16#0424 put +dup /afii10039 16#0425 put +dup /afii10040 16#0426 put +dup /afii10041 16#0427 put +dup /afii10042 16#0428 put +dup /afii10043 16#0429 put +dup /afii10044 16#042A put +dup /afii10045 16#042B put +dup /afii10046 16#042C put +dup /afii10047 16#042D put +dup /afii10048 16#042E put +dup /afii10049 16#042F put +dup /afii10050 16#0490 put +dup /afii10051 16#0402 put +dup /afii10052 16#0403 put +dup /afii10053 16#0404 put +dup /afii10054 16#0405 put +dup /afii10055 16#0406 put +dup /afii10056 16#0407 put +dup /afii10057 16#0408 put +dup /afii10058 16#0409 put +dup /afii10059 16#040A put +dup /afii10060 16#040B put +dup /afii10061 16#040C put +dup /afii10062 16#040E put +dup /afii10063 16#F6C4 put +dup /afii10064 16#F6C5 put +dup /afii10065 16#0430 put +dup /afii10066 16#0431 put +dup /afii10067 16#0432 put +dup /afii10068 16#0433 put +dup /afii10069 16#0434 put +dup /afii10070 16#0435 put +dup /afii10071 16#0451 put +dup /afii10072 16#0436 put +dup /afii10073 16#0437 put +dup /afii10074 16#0438 put +dup /afii10075 16#0439 put +dup /afii10076 16#043A put +dup /afii10077 16#043B put +dup /afii10078 16#043C put +dup /afii10079 16#043D put +dup /afii10080 16#043E put +dup /afii10081 16#043F put +dup /afii10082 16#0440 put +dup /afii10083 16#0441 put +dup /afii10084 16#0442 put +dup /afii10085 16#0443 put +dup /afii10086 16#0444 put +dup /afii10087 16#0445 put +dup /afii10088 16#0446 put +dup /afii10089 16#0447 put +dup /afii10090 16#0448 put +dup /afii10091 16#0449 put +dup /afii10092 16#044A put +dup /afii10093 16#044B put +dup /afii10094 16#044C put +dup /afii10095 16#044D put +dup /afii10096 16#044E put +dup /afii10097 16#044F put +dup /afii10098 16#0491 put +dup /afii10099 16#0452 put +dup /afii10100 16#0453 put +dup /afii10101 16#0454 put +dup /afii10102 16#0455 put +dup /afii10103 16#0456 put +dup /afii10104 16#0457 put +dup /afii10105 16#0458 put +dup /afii10106 16#0459 put +dup /afii10107 16#045A put +dup /afii10108 16#045B put +dup /afii10109 16#045C put +dup /afii10110 16#045E put +dup /afii10145 16#040F put +dup /afii10146 16#0462 put +dup /afii10147 16#0472 put +dup /afii10148 16#0474 put +dup /afii10192 16#F6C6 put +dup /afii10193 16#045F put +dup /afii10194 16#0463 put +dup /afii10195 16#0473 put +dup /afii10196 16#0475 put +dup /afii10831 16#F6C7 put +dup /afii10832 16#F6C8 put +dup /afii10846 16#04D9 put +dup /afii299 16#200E put +dup /afii300 16#200F put +dup /afii301 16#200D put +dup /afii57381 16#066A put +dup /afii57388 16#060C put +dup /afii57392 16#0660 put +dup /afii57393 16#0661 put +dup /afii57394 16#0662 put +dup /afii57395 16#0663 put +dup /afii57396 16#0664 put +dup /afii57397 16#0665 put +dup /afii57398 16#0666 put +dup /afii57399 16#0667 put +dup /afii57400 16#0668 put +dup /afii57401 16#0669 put +dup /afii57403 16#061B put +dup /afii57407 16#061F put +dup /afii57409 16#0621 put +dup /afii57410 16#0622 put +dup /afii57411 16#0623 put +dup /afii57412 16#0624 put +dup /afii57413 16#0625 put +dup /afii57414 16#0626 put +dup /afii57415 16#0627 put +dup /afii57416 16#0628 put +dup /afii57417 16#0629 put +dup /afii57418 16#062A put +dup /afii57419 16#062B put +dup /afii57420 16#062C put +dup /afii57421 16#062D put +dup /afii57422 16#062E put +dup /afii57423 16#062F put +dup /afii57424 16#0630 put +dup /afii57425 16#0631 put +dup /afii57426 16#0632 put +dup /afii57427 16#0633 put +dup /afii57428 16#0634 put +dup /afii57429 16#0635 put +dup /afii57430 16#0636 put +dup /afii57431 16#0637 put +dup /afii57432 16#0638 put +dup /afii57433 16#0639 put +dup /afii57434 16#063A put +dup /afii57440 16#0640 put +dup /afii57441 16#0641 put +dup /afii57442 16#0642 put +dup /afii57443 16#0643 put +dup /afii57444 16#0644 put +dup /afii57445 16#0645 put +dup /afii57446 16#0646 put +dup /afii57448 16#0648 put +dup /afii57449 16#0649 put +dup /afii57450 16#064A put +dup /afii57451 16#064B put +dup /afii57452 16#064C put +dup /afii57453 16#064D put +dup /afii57454 16#064E put +dup /afii57455 16#064F put +dup /afii57456 16#0650 put +dup /afii57457 16#0651 put +dup /afii57458 16#0652 put +dup /afii57470 16#0647 put +dup /afii57505 16#06A4 put +dup /afii57506 16#067E put +dup /afii57507 16#0686 put +dup /afii57508 16#0698 put +dup /afii57509 16#06AF put +dup /afii57511 16#0679 put +dup /afii57512 16#0688 put +dup /afii57513 16#0691 put +dup /afii57514 16#06BA put +dup /afii57519 16#06D2 put +dup /afii57534 16#06D5 put +dup /afii57636 16#20AA put +dup /afii57645 16#05BE put +dup /afii57658 16#05C3 put +dup /afii57664 16#05D0 put +dup /afii57665 16#05D1 put +dup /afii57666 16#05D2 put +dup /afii57667 16#05D3 put +dup /afii57668 16#05D4 put +dup /afii57669 16#05D5 put +dup /afii57670 16#05D6 put +dup /afii57671 16#05D7 put +dup /afii57672 16#05D8 put +dup /afii57673 16#05D9 put +dup /afii57674 16#05DA put +dup /afii57675 16#05DB put +dup /afii57676 16#05DC put +dup /afii57677 16#05DD put +dup /afii57678 16#05DE put +dup /afii57679 16#05DF put +dup /afii57680 16#05E0 put +dup /afii57681 16#05E1 put +dup /afii57682 16#05E2 put +dup /afii57683 16#05E3 put +dup /afii57684 16#05E4 put +dup /afii57685 16#05E5 put +dup /afii57686 16#05E6 put +dup /afii57687 16#05E7 put +dup /afii57688 16#05E8 put +dup /afii57689 16#05E9 put +dup /afii57690 16#05EA put +dup /afii57694 16#FB2A put +dup /afii57695 16#FB2B put +dup /afii57700 16#FB4B put +dup /afii57705 16#FB1F put +dup /afii57716 16#05F0 put +dup /afii57717 16#05F1 put +dup /afii57718 16#05F2 put +dup /afii57723 16#FB35 put +dup /afii57793 16#05B4 put +dup /afii57794 16#05B5 put +dup /afii57795 16#05B6 put +dup /afii57796 16#05BB put +dup /afii57797 16#05B8 put +dup /afii57798 16#05B7 put +dup /afii57799 16#05B0 put +dup /afii57800 16#05B2 put +dup /afii57801 16#05B1 put +dup /afii57802 16#05B3 put +dup /afii57803 16#05C2 put +dup /afii57804 16#05C1 put +dup /afii57806 16#05B9 put +dup /afii57807 16#05BC put +dup /afii57839 16#05BD put +dup /afii57841 16#05BF put +dup /afii57842 16#05C0 put +dup /afii57929 16#02BC put +dup /afii61248 16#2105 put +dup /afii61289 16#2113 put +dup /afii61352 16#2116 put +dup /afii61573 16#202C put +dup /afii61574 16#202D put +dup /afii61575 16#202E put +dup /afii61664 16#200C put +dup /afii63167 16#066D put +dup /afii64937 16#02BD put +dup /agrave 16#00E0 put +dup /aleph 16#2135 put +dup /alpha 16#03B1 put +dup /alphatonos 16#03AC put +dup /amacron 16#0101 put +dup /ampersand 16#0026 put +dup /ampersandsmall 16#F726 put +dup /angle 16#2220 put +dup /angleleft 16#2329 put +dup /angleright 16#232A put +dup /anoteleia 16#0387 put +dup /aogonek 16#0105 put +dup /approxequal 16#2248 put +dup /aring 16#00E5 put +dup /aringacute 16#01FB put +dup /arrowboth 16#2194 put +dup /arrowdblboth 16#21D4 put +dup /arrowdbldown 16#21D3 put +dup /arrowdblleft 16#21D0 put +dup /arrowdblright 16#21D2 put +dup /arrowdblup 16#21D1 put +dup /arrowdown 16#2193 put +dup /arrowhorizex 16#F8E7 put +dup /arrowleft 16#2190 put +dup /arrowright 16#2192 put +dup /arrowup 16#2191 put +dup /arrowupdn 16#2195 put +dup /arrowupdnbse 16#21A8 put +dup /arrowvertex 16#F8E6 put +dup /asciicircum 16#005E put +dup /asciitilde 16#007E put +dup /asterisk 16#002A put +dup /asteriskmath 16#2217 put +dup /asuperior 16#F6E9 put +dup /at 16#0040 put +dup /atilde 16#00E3 put +dup /b 16#0062 put +dup /backslash 16#005C put +dup /bar 16#007C put +dup /beta 16#03B2 put +dup /block 16#2588 put +dup /braceex 16#F8F4 put +dup /braceleft 16#007B put +dup /braceleftbt 16#F8F3 put +dup /braceleftmid 16#F8F2 put +dup /bracelefttp 16#F8F1 put +dup /braceright 16#007D put +dup /bracerightbt 16#F8FE put +dup /bracerightmid 16#F8FD put +dup /bracerighttp 16#F8FC put +dup /bracketleft 16#005B put +dup /bracketleftbt 16#F8F0 put +dup /bracketleftex 16#F8EF put +dup /bracketlefttp 16#F8EE put +dup /bracketright 16#005D put +dup /bracketrightbt 16#F8FB put +dup /bracketrightex 16#F8FA put +dup /bracketrighttp 16#F8F9 put +dup /breve 16#02D8 put +dup /brokenbar 16#00A6 put +dup /bsuperior 16#F6EA put +dup /bullet 16#2022 put +dup /c 16#0063 put +dup /cacute 16#0107 put +dup /caron 16#02C7 put +dup /carriagereturn 16#21B5 put +dup /ccaron 16#010D put +dup /ccedilla 16#00E7 put +dup /ccircumflex 16#0109 put +dup /cdotaccent 16#010B put +dup /cedilla 16#00B8 put +dup /cent 16#00A2 put +dup /centinferior 16#F6DF put +dup /centoldstyle 16#F7A2 put +dup /centsuperior 16#F6E0 put +dup /chi 16#03C7 put +dup /circle 16#25CB put +dup /circlemultiply 16#2297 put +dup /circleplus 16#2295 put +dup /circumflex 16#02C6 put +dup /club 16#2663 put +dup /colon 16#003A put +dup /colonmonetary 16#20A1 put +dup /comma 16#002C put +dup /commaaccent 16#F6C3 put +dup /commainferior 16#F6E1 put +dup /commasuperior 16#F6E2 put +dup /congruent 16#2245 put +dup /copyright 16#00A9 put +dup /copyrightsans 16#F8E9 put +dup /copyrightserif 16#F6D9 put +dup /currency 16#00A4 put +dup /cyrBreve 16#F6D1 put +dup /cyrFlex 16#F6D2 put +dup /cyrbreve 16#F6D4 put +dup /cyrflex 16#F6D5 put +dup /d 16#0064 put +dup /dagger 16#2020 put +dup /daggerdbl 16#2021 put +dup /dblGrave 16#F6D3 put +dup /dblgrave 16#F6D6 put +dup /dcaron 16#010F put +dup /dcroat 16#0111 put +dup /degree 16#00B0 put +dup /delta 16#03B4 put +dup /diamond 16#2666 put +dup /dieresis 16#00A8 put +dup /dieresisacute 16#F6D7 put +dup /dieresisgrave 16#F6D8 put +dup /dieresistonos 16#0385 put +dup /divide 16#00F7 put +dup /dkshade 16#2593 put +dup /dnblock 16#2584 put +dup /dollar 16#0024 put +dup /dollarinferior 16#F6E3 put +dup /dollaroldstyle 16#F724 put +dup /dollarsuperior 16#F6E4 put +dup /dong 16#20AB put +dup /dotaccent 16#02D9 put +dup /dotbelowcomb 16#0323 put +dup /dotlessi 16#0131 put +dup /dotlessj 16#F6BE put +dup /dotmath 16#22C5 put +dup /dsuperior 16#F6EB put +dup /e 16#0065 put +dup /eacute 16#00E9 put +dup /ebreve 16#0115 put +dup /ecaron 16#011B put +dup /ecircumflex 16#00EA put +dup /edieresis 16#00EB put +dup /edotaccent 16#0117 put +dup /egrave 16#00E8 put +dup /eight 16#0038 put +dup /eightinferior 16#2088 put +dup /eightoldstyle 16#F738 put +dup /eightsuperior 16#2078 put +dup /element 16#2208 put +dup /ellipsis 16#2026 put +dup /emacron 16#0113 put +dup /emdash 16#2014 put +dup /emptyset 16#2205 put +dup /endash 16#2013 put +dup /eng 16#014B put +dup /eogonek 16#0119 put +dup /epsilon 16#03B5 put +dup /epsilontonos 16#03AD put +dup /equal 16#003D put +dup /equivalence 16#2261 put +dup /estimated 16#212E put +dup /esuperior 16#F6EC put +dup /eta 16#03B7 put +dup /etatonos 16#03AE put +dup /eth 16#00F0 put +dup /exclam 16#0021 put +dup /exclamdbl 16#203C put +dup /exclamdown 16#00A1 put +dup /exclamdownsmall 16#F7A1 put +dup /exclamsmall 16#F721 put +dup /existential 16#2203 put +dup /f 16#0066 put +dup /female 16#2640 put +dup /ff 16#FB00 put +dup /ffi 16#FB03 put +dup /ffl 16#FB04 put +dup /fi 16#FB01 put +dup /figuredash 16#2012 put +dup /filledbox 16#25A0 put +dup /filledrect 16#25AC put +dup /five 16#0035 put +dup /fiveeighths 16#215D put +dup /fiveinferior 16#2085 put +dup /fiveoldstyle 16#F735 put +dup /fivesuperior 16#2075 put +dup /fl 16#FB02 put +dup /florin 16#0192 put +dup /four 16#0034 put +dup /fourinferior 16#2084 put +dup /fouroldstyle 16#F734 put +dup /foursuperior 16#2074 put +dup /fraction [16#2044 16#2215] put +dup /franc 16#20A3 put +dup /g 16#0067 put +dup /gamma 16#03B3 put +dup /gbreve 16#011F put +dup /gcaron 16#01E7 put +dup /gcircumflex 16#011D put +dup /gcommaaccent 16#0123 put +dup /gdotaccent 16#0121 put +dup /germandbls 16#00DF put +dup /gradient 16#2207 put +dup /grave 16#0060 put +dup /gravecomb 16#0300 put +dup /greater 16#003E put +dup /greaterequal 16#2265 put +dup /guillemotleft 16#00AB put +dup /guillemotright 16#00BB put +dup /guilsinglleft 16#2039 put +dup /guilsinglright 16#203A put +dup /h 16#0068 put +dup /hbar 16#0127 put +dup /hcircumflex 16#0125 put +dup /heart 16#2665 put +dup /hookabovecomb 16#0309 put +dup /house 16#2302 put +dup /hungarumlaut 16#02DD put +dup /hyphen [16#002D 16#00AD] put +dup /hypheninferior 16#F6E5 put +dup /hyphensuperior 16#F6E6 put +dup /i 16#0069 put +dup /iacute 16#00ED put +dup /ibreve 16#012D put +dup /icircumflex 16#00EE put +dup /idieresis 16#00EF put +dup /igrave 16#00EC put +dup /ij 16#0133 put +dup /imacron 16#012B put +dup /infinity 16#221E put +dup /integral 16#222B put +dup /integralbt 16#2321 put +dup /integralex 16#F8F5 put +dup /integraltp 16#2320 put +dup /intersection 16#2229 put +dup /invbullet 16#25D8 put +dup /invcircle 16#25D9 put +dup /invsmileface 16#263B put +dup /iogonek 16#012F put +dup /iota 16#03B9 put +dup /iotadieresis 16#03CA put +dup /iotadieresistonos 16#0390 put +dup /iotatonos 16#03AF put +dup /isuperior 16#F6ED put +dup /itilde 16#0129 put +dup /j 16#006A put +dup /jcircumflex 16#0135 put +dup /k 16#006B put +dup /kappa 16#03BA put +dup /kcommaaccent 16#0137 put +dup /kgreenlandic 16#0138 put +dup /l 16#006C put +dup /lacute 16#013A put +dup /lambda 16#03BB put +dup /lcaron 16#013E put +dup /lcommaaccent 16#013C put +dup /ldot 16#0140 put +dup /less 16#003C put +dup /lessequal 16#2264 put +dup /lfblock 16#258C put +dup /lira 16#20A4 put +dup /ll 16#F6C0 put +dup /logicaland 16#2227 put +dup /logicalnot 16#00AC put +dup /logicalor 16#2228 put +dup /longs 16#017F put +dup /lozenge 16#25CA put +dup /lslash 16#0142 put +dup /lsuperior 16#F6EE put +dup /ltshade 16#2591 put +dup /m 16#006D put +dup /macron [16#00AF 16#02C9] put +dup /male 16#2642 put +dup /minus 16#2212 put +dup /minute 16#2032 put +dup /msuperior 16#F6EF put +dup /mu [16#00B5 16#03BC] put +dup /multiply 16#00D7 put +dup /musicalnote 16#266A put +dup /musicalnotedbl 16#266B put +dup /n 16#006E put +dup /nacute 16#0144 put +dup /napostrophe 16#0149 put +dup /ncaron 16#0148 put +dup /ncommaaccent 16#0146 put +dup /nine 16#0039 put +dup /nineinferior 16#2089 put +dup /nineoldstyle 16#F739 put +dup /ninesuperior 16#2079 put +dup /notelement 16#2209 put +dup /notequal 16#2260 put +dup /notsubset 16#2284 put +dup /nsuperior 16#207F put +dup /ntilde 16#00F1 put +dup /nu 16#03BD put +dup /numbersign 16#0023 put +dup /o 16#006F put +dup /oacute 16#00F3 put +dup /obreve 16#014F put +dup /ocircumflex 16#00F4 put +dup /odieresis 16#00F6 put +dup /oe 16#0153 put +dup /ogonek 16#02DB put +dup /ograve 16#00F2 put +dup /ohorn 16#01A1 put +dup /ohungarumlaut 16#0151 put +dup /omacron 16#014D put +dup /omega 16#03C9 put +dup /omega1 16#03D6 put +dup /omegatonos 16#03CE put +dup /omicron 16#03BF put +dup /omicrontonos 16#03CC put +dup /one 16#0031 put +dup /onedotenleader 16#2024 put +dup /oneeighth 16#215B put +dup /onefitted 16#F6DC put +dup /onehalf 16#00BD put +dup /oneinferior 16#2081 put +dup /oneoldstyle 16#F731 put +dup /onequarter 16#00BC put +dup /onesuperior 16#00B9 put +dup /onethird 16#2153 put +dup /openbullet 16#25E6 put +dup /ordfeminine 16#00AA put +dup /ordmasculine 16#00BA put +dup /orthogonal 16#221F put +dup /oslash 16#00F8 put +dup /oslashacute 16#01FF put +dup /osuperior 16#F6F0 put +dup /otilde 16#00F5 put +dup /p 16#0070 put +dup /paragraph 16#00B6 put +dup /parenleft 16#0028 put +dup /parenleftbt 16#F8ED put +dup /parenleftex 16#F8EC put +dup /parenleftinferior 16#208D put +dup /parenleftsuperior 16#207D put +dup /parenlefttp 16#F8EB put +dup /parenright 16#0029 put +dup /parenrightbt 16#F8F8 put +dup /parenrightex 16#F8F7 put +dup /parenrightinferior 16#208E put +dup /parenrightsuperior 16#207E put +dup /parenrighttp 16#F8F6 put +dup /partialdiff 16#2202 put +dup /percent 16#0025 put +dup /period 16#002E put +dup /periodcentered [16#00B7 16#2219] put +dup /periodinferior 16#F6E7 put +dup /periodsuperior 16#F6E8 put +dup /perpendicular 16#22A5 put +dup /perthousand 16#2030 put +dup /peseta 16#20A7 put +dup /phi 16#03C6 put +dup /phi1 16#03D5 put +dup /pi 16#03C0 put +dup /plus 16#002B put +dup /plusminus 16#00B1 put +dup /prescription 16#211E put +dup /product 16#220F put +dup /propersubset 16#2282 put +dup /propersuperset 16#2283 put +dup /proportional 16#221D put +dup /psi 16#03C8 put +dup /q 16#0071 put +dup /question 16#003F put +dup /questiondown 16#00BF put +dup /questiondownsmall 16#F7BF put +dup /questionsmall 16#F73F put +dup /quotedbl 16#0022 put +dup /quotedblbase 16#201E put +dup /quotedblleft 16#201C put +dup /quotedblright 16#201D put +dup /quoteleft 16#2018 put +dup /quotereversed 16#201B put +dup /quoteright 16#2019 put +dup /quotesinglbase 16#201A put +dup /quotesingle 16#0027 put +dup /r 16#0072 put +dup /racute 16#0155 put +dup /radical 16#221A put +dup /radicalex 16#F8E5 put +dup /rcaron 16#0159 put +dup /rcommaaccent 16#0157 put +dup /reflexsubset 16#2286 put +dup /reflexsuperset 16#2287 put +dup /registered 16#00AE put +dup /registersans 16#F8E8 put +dup /registerserif 16#F6DA put +dup /revlogicalnot 16#2310 put +dup /rho 16#03C1 put +dup /ring 16#02DA put +dup /rsuperior 16#F6F1 put +dup /rtblock 16#2590 put +dup /rupiah 16#F6DD put +dup /s 16#0073 put +dup /sacute 16#015B put +dup /scaron 16#0161 put +dup /scedilla [16#015F 16#F6C2] put +dup /scircumflex 16#015D put +dup /scommaaccent 16#0219 put +dup /second 16#2033 put +dup /section 16#00A7 put +dup /semicolon 16#003B put +dup /seven 16#0037 put +dup /seveneighths 16#215E put +dup /seveninferior 16#2087 put +dup /sevenoldstyle 16#F737 put +dup /sevensuperior 16#2077 put +dup /shade 16#2592 put +dup /sigma 16#03C3 put +dup /sigma1 16#03C2 put +dup /similar 16#223C put +dup /six 16#0036 put +dup /sixinferior 16#2086 put +dup /sixoldstyle 16#F736 put +dup /sixsuperior 16#2076 put +dup /slash 16#002F put +dup /smileface 16#263A put +dup /space [16#0020 16#00A0] put +dup /spade 16#2660 put +dup /ssuperior 16#F6F2 put +dup /sterling 16#00A3 put +dup /suchthat 16#220B put +dup /summation 16#2211 put +dup /sun 16#263C put +dup /t 16#0074 put +dup /tau 16#03C4 put +dup /tbar 16#0167 put +dup /tcaron 16#0165 put +dup /tcommaaccent [16#0163 16#021B] put +dup /therefore 16#2234 put +dup /theta 16#03B8 put +dup /theta1 16#03D1 put +dup /thorn 16#00FE put +dup /three 16#0033 put +dup /threeeighths 16#215C put +dup /threeinferior 16#2083 put +dup /threeoldstyle 16#F733 put +dup /threequarters 16#00BE put +dup /threequartersemdash 16#F6DE put +dup /threesuperior 16#00B3 put +dup /tilde 16#02DC put +dup /tildecomb 16#0303 put +dup /tonos 16#0384 put +dup /trademark 16#2122 put +dup /trademarksans 16#F8EA put +dup /trademarkserif 16#F6DB put +dup /triagdn 16#25BC put +dup /triaglf 16#25C4 put +dup /triagrt 16#25BA put +dup /triagup 16#25B2 put +dup /tsuperior 16#F6F3 put +dup /two 16#0032 put +dup /twodotenleader 16#2025 put +dup /twoinferior 16#2082 put +dup /twooldstyle 16#F732 put +dup /twosuperior 16#00B2 put +dup /twothirds 16#2154 put +dup /u 16#0075 put +dup /uacute 16#00FA put +dup /ubreve 16#016D put +dup /ucircumflex 16#00FB put +dup /udieresis 16#00FC put +dup /ugrave 16#00F9 put +dup /uhorn 16#01B0 put +dup /uhungarumlaut 16#0171 put +dup /umacron 16#016B put +dup /underscore 16#005F put +dup /underscoredbl 16#2017 put +dup /union 16#222A put +dup /universal 16#2200 put +dup /uogonek 16#0173 put +dup /upblock 16#2580 put +dup /upsilon 16#03C5 put +dup /upsilondieresis 16#03CB put +dup /upsilondieresistonos 16#03B0 put +dup /upsilontonos 16#03CD put +dup /uring 16#016F put +dup /utilde 16#0169 put +dup /v 16#0076 put +dup /w 16#0077 put +dup /wacute 16#1E83 put +dup /wcircumflex 16#0175 put +dup /wdieresis 16#1E85 put +dup /weierstrass 16#2118 put +dup /wgrave 16#1E81 put +dup /x 16#0078 put +dup /xi 16#03BE put +dup /y 16#0079 put +dup /yacute 16#00FD put +dup /ycircumflex 16#0177 put +dup /ydieresis 16#00FF put +dup /yen 16#00A5 put +dup /ygrave 16#1EF3 put +dup /z 16#007A put +dup /zacute 16#017A put +dup /zcaron 16#017E put +dup /zdotaccent 16#017C put +dup /zero 16#0030 put +dup /zeroinferior 16#2080 put +dup /zerooldstyle 16#F730 put +dup /zerosuperior 16#2070 put +dup /zeta 16#03B6 put +def diff --git a/gs/Resource/Init/gs_btokn.ps b/gs/Resource/Init/gs_btokn.ps new file mode 100644 index 000000000..8ae575081 --- /dev/null +++ b/gs/Resource/Init/gs_btokn.ps @@ -0,0 +1,331 @@ +% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for binary tokens. +% When this is run, systemdict is still writable, +% but everything defined here goes into level2dict. + +% Define whether or not to allow writing dictionaries. +% This is a non-standard feature! +/WRITEDICTS false def + +languagelevel 1 .setlanguagelevel +level2dict begin + +% Initialization for the system name table. + +mark +% 0 + /abs /add /aload /anchorsearch /and + /arc /arcn /arct /arcto /array + /ashow /astore /awidthshow /begin /bind + /bitshift /ceiling /charpath /clear /cleartomark +% 20 + /clip /clippath /closepath /concat /concatmatrix + /copy /count /counttomark /currentcmykcolor /currentdash + /currentdict /currentfile /currentfont /currentgray /currentgstate + /currenthsbcolor /currentlinecap /currentlinejoin /currentlinewidth /currentmatrix +% 40 + /currentpoint /currentrgbcolor /currentshared /curveto /cvi + /cvlit /cvn /cvr /cvrs /cvs + /cvx /def /defineusername /dict /div + /dtransform /dup /end /eoclip /eofill +% 60 + /eoviewclip /eq /exch /exec /exit + /file /fill /findfont /flattenpath /floor + /flush /flushfile /for /forall /ge + /get /getinterval /grestore /gsave /gstate +% 80 + /gt /identmatrix /idiv /idtransform /if + /ifelse /image /imagemask /index /ineofill + /infill /initviewclip /inueofill /inufill /invertmatrix + /itransform /known /le /length /lineto +% 100 + /load /loop /lt /makefont /matrix + /maxlength /mod /moveto /mul /ne + /neg /newpath /not /null /or + /pathbbox /pathforall /pop /print /printobject +% 120 + /put /putinterval /rcurveto /read /readhexstring + /readline /readstring /rectclip /rectfill /rectstroke + /rectviewclip /repeat /restore /rlineto /rmoveto + /roll /rotate /round /save /scale +% 140 + /scalefont /search /selectfont /setbbox /setcachedevice + /setcachedevice2 /setcharwidth /setcmykcolor /setdash /setfont + /setgray /setgstate /sethsbcolor /setlinecap /setlinejoin + /setlinewidth /setmatrix /setrgbcolor /setshared /shareddict +% 160 + /show /showpage /stop /stopped /store + /string /stringwidth /stroke /strokepath /sub + /systemdict /token /transform /translate /truncate + /type /uappend /ucache /ueofill /ufill +% 180 + /undef /upath /userdict /ustroke /viewclip + /viewclippath /where /widthshow /write /writehexstring + /writeobject /writestring /wtranslation /xor /xshow + /xyshow /yshow /FontDirectory /SharedFontDirectory /Courier +% 200 + /Courier-Bold /Courier-BoldOblique /Courier-Oblique /Helvetica /Helvetica-Bold + /Helvetica-BoldOblique /Helvetica-Oblique /Symbol /Times-Bold /Times-BoldItalic + /Times-Italic /Times-Roman /execuserobject /currentcolor /currentcolorspace + /currentglobal /execform /filter /findresource /globaldict +% 220 + /makepattern /setcolor /setcolorspace /setglobal /setpagedevice + /setpattern +% pad to 256 + counttomark 256 exch sub { 0 } repeat +% 256 + /= /== /ISOLatin1Encoding /StandardEncoding +% 260 + ([) cvn (]) cvn /atan /banddevice /bytesavailable + /cachestatus /closefile /colorimage /condition /copypage + /cos /countdictstack /countexecstack /cshow /currentblackgeneration + /currentcacheparams /currentcolorscreen /currentcolortransfer /currentcontext /currentflat +% 280 + /currenthalftone /currenthalftonephase /currentmiterlimit /currentobjectformat /currentpacking + /currentscreen /currentstrokeadjust /currenttransfer /currentundercolorremoval /defaultmatrix + /definefont /deletefile /detach /deviceinfo /dictstack + /echo /erasepage /errordict /execstack /executeonly +% 300 + /exp /false /filenameforall /fileposition /fork + /framedevice /grestoreall /handleerror /initclip /initgraphics + /initmatrix /instroke /inustroke /join /kshow + /ln /lock /log /mark /monitor +% 320 + /noaccess /notify /nulldevice /packedarray /quit + /rand /rcheck /readonly /realtime /renamefile + /renderbands /resetfile /reversepath /rootfont /rrand + /run /scheck /setblackgeneration /setcachelimit /setcacheparams +% 340 + /setcolorscreen /setcolortransfer /setfileposition /setflat /sethalftone + /sethalftonephase /setmiterlimit /setobjectformat /setpacking /setscreen + /setstrokeadjust /settransfer /setucacheparams /setundercolorremoval /sin + /sqrt /srand /stack /status /statusdict +% 360 + /true /ucachestatus /undefinefont /usertime /ustrokepath + /version /vmreclaim /vmstatus /wait /wcheck + /xcheck /yield /defineuserobject /undefineuserobject /UserObjects + /cleardictstack +% 376 + /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 + /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 +% 428 + /setvmthreshold (<<) cvn + (>>) cvn /currentcolorrendering /currentdevparams /currentoverprint /currentpagedevice + /currentsystemparams /currentuserparams /defineresource /findencoding /gcheck +% 440 + /glyphshow /languagelevel /product /pstack /resourceforall + /resourcestatus /revision /serialnumber /setcolorrendering /setdevparams + /setoverprint /setsystemparams /setuserparams /startjob /undefineresource + /GlobalFontDirectory /ASCII85Decode /ASCII85Encode /ASCIIHexDecode /ASCIIHexEncode +% 460 + /CCITTFaxDecode /CCITTFaxEncode /DCTDecode /DCTEncode /LZWDecode + /LZWEncode /NullEncode /RunLengthDecode /RunLengthEncode /SubFileDecode + /CIEBasedA /CIEBasedABC /DeviceCMYK /DeviceGray /DeviceRGB + /Indexed /Pattern /Separation /CIEBasedDEF /CIEBasedDEFG +% 480 + /DeviceN +% 481 -- end +.packtomark .installsystemnames + +% Define printobject and writeobject. +% These are mostly implemented in PostScript, so that we don't have to +% worry about interrupts or callbacks when writing to the output file. + +% Define procedures for accumulating the space required to represent +% an object in binary form. The procedures for composite objects (arrays +% and dictionaries) leave different results on the stack: +% <#refs> <#chars> <simple_obj> -proc- <#refs> <#chars> +% <#refs> <#chars> <array|dict> -proc- <array|dict> <#refs> <#chars> +% This is required so that .writeobjects can also accumulate the actual +% list of composite objects to write in the binary object sequence. +/cntdict mark + /integertype /pop load + /realtype 1 index + /marktype 1 index + /nulltype 1 index + /booleantype 1 index + /nametype { length add } bind + /stringtype 1 index + /arraytype null + /dicttype null +.dicttomark def +/.cntobj { % <<arguments and results as for procedures in cntdict>> + dup type //cntdict exch get exec +} .bind def +cntdict /arraytype { + dup dup length 5 -1 roll add 4 2 roll { .cntobj } forall +} bind put +cntdict /dicttype { + WRITEDICTS { + dup dup length 2 mul 5 -1 roll add 4 2 roll { + % We have to use .execn here, rather than simply rolling the + % value under the top elements, because key might involve arrays + % or dictionaries. + cvlit {.cntobj} exch 2 .execn .cntobj + } forall + } { + /writeobject .systemvar /typecheck signalerror + } ifelse +} bind put + +/w2dict mark + /nametype { 2 copy .writecvs pop } bind + /stringtype 1 index +.dicttomark def + +/.bosheader { % <top_length> <total_length> <string8> .bosheader + % <string4|8> + dup 0 currentobjectformat 127 add put % object format => BOS tag + 2 index 255 le 2 index 65531 le and { + % Use the short header format: tag toplen(1) totlen(2) + exch 4 add exch + 0 4 getinterval + dup 1 5 -1 roll put + } { + % Use the long header format: tag 0(1) toplen(2) totlen(4) + exch 8 add exch + 0 0 4 2 roll .bosobject exch pop exch pop % store with byte swapping + } ifelse % Stack: shortlen str + exch dup -8 bitshift exch 255 and % str hibyte lobyte + currentobjectformat 1 and 0 eq { % lsb first + exch + } if + 2 index 3 3 -1 roll put + 1 index 2 3 -1 roll put +} .bind def + +/.writeobjects { % <file> <tag> <array> .writeobjects - + mark exch + + % Count the space required for refs and strings. + + dup length 0 3 -1 roll + % Stack: file tag -mark- #refs #chars array + dup 4 1 roll { .cntobj } forall + + % Write the header. + + % Stack: file tag -mark- array1 ... (array|dict)N #refs #chars + counttomark 3 add -2 roll 4 1 roll + % Stack: -mark- array1 ... (array|dict)N tag #refs #chars file + dup counttomark 1 sub index length + 4 index 3 bitshift 4 index add + (xxxxxxxx) .bosheader writestring + + % Write the objects per se. + + 3 1 roll pop + counttomark 1 sub index length 3 bitshift exch + 3 bitshift + % Stack: -mark- array1 ... (array|dict)N tag file ref# char# + counttomark 4 sub { + counttomark -1 roll dup 6 1 roll + % Stack: ... objN tag file ref# char# objN + dup type /dicttype eq { % can't be first object + { 5 1 roll (x\000xxxxxx) .bosobject + 3 index exch writestring + 4 -1 roll (x\000xxxxxx) .bosobject + 3 index exch writestring + } forall + } { + { (x\000xxxxxx) .bosobject + dup 1 6 index put + 3 index exch writestring + 4 -1 roll pop 0 4 1 roll % clear tag + } forall + } ifelse + } repeat + + % Write the strings and names. + + pop pop exch pop + % Stack: -mark- array1 ... array|dictN file + counttomark 1 sub { + counttomark -1 roll { + % The counting pass ensured that the keys and values + % of any dictionary must be writable objects. + % Hence, we are processing a dictionary iff + % the next-to-top stack element is not a file. + 1 index type /filetype ne { + exch 2 index exch dup type //w2dict exch .knownget + { exec } { pop } ifelse pop + } if + dup type //w2dict exch .knownget { exec } { pop } ifelse + } forall + } repeat + + % Clean up. + + % Stack: -mark- file + pop pop + +} .bind def + +/printobject { % <obj> <tag> printobject - + currentobjectformat 0 eq { + /printobject .systemvar /undefined signalerror + } if + (%stdout) (w) file 2 index 2 index .writeobject pop pop +} odef +/writeobject { % <file> <obj> <tag> writeobject - + currentobjectformat 0 eq { + /writeobject .systemvar /undefined signalerror + } if + 2 .argindex pop % check # of args + .writeobject +} odef +/.writeobject { + 3 copy exch + % We must allocate the array in local VM + % to avoid a possible invalidaccess. + .currentglobal false .setglobal exch 1 array astore exch .setglobal + .writeobjects pop pop pop +} .bind def + +% Implement binary error message output. +/.objectprinttest { % <obj> .objectprinttest - + % This is a pseudo-operator so it will restore the stack + % if it gets an error. + mark 0 0 3 .argindex .cntobj cleartomark pop +} bind odef +/.printerror { + $error /binary get .languagelevel 2 ge and { + currentobjectformat 0 ne { + [ /Error $error /errorname get $error /command get + % Convert the object with cvs if it isn't printable. + dup { .objectprinttest } .internalstopped { + pop 100 string cvs + } if + false ] 250 printobject + } + //.printerror % known to be a procedure + ifelse + } + //.printerror % known to be a procedure + ifelse +} bind def + +currentdict /cntdict .undef +currentdict /w2dict .undef + +% End of level2dict + +end +.setlanguagelevel diff --git a/gs/Resource/Init/gs_cet.ps b/gs/Resource/Init/gs_cet.ps new file mode 100644 index 000000000..01225e9f2 --- /dev/null +++ b/gs/Resource/Init/gs_cet.ps @@ -0,0 +1,61 @@ +%!PS +% Set defaults for Ghostscript to match Adobe CPSI behaviour for CET +% $Id$ + +% do this in the server level so it is persistent across jobs +true 0 startjob not { + (*** Warning: CET startup is not in server default) = flush +} if + +300 .sethiresscreen % needed for language switch build since it + % processes gs_init.ps BEFORE setting the resolution + +0 array 0 setdash % CET 09-08 wants local setdash + +currentglobal true setglobal + +{ + systemdict dup dup dup + /version (3017.102) put % match CPSI 3017.102 + /product (PhotoPRINT SE 5.0v2) put % match CPSI 3017.102 + /revision 0 put % match CPSI 3017.103 Tek shows revision 5 + /serialnumber 233640 put % match CPSI 3017.102 Tek shows serialnumber 1401788461 + systemdict /deviceinfo undef % for CET 20-23-1 +} superexec + +{ } bind dup +setblackgeneration +setundercolorremoval +0 array cvx readonly dup dup dup setcolortransfer + +% CPSI doesn't define "Localization" resource. +/Localization /Category undefineresource + +% Some previously compile time options such as USE_ADOBE_CMYK_RGB +% and GS_CHAR_FILL are now dynamic. Force CPSI compatibility. +true .setCPSImode + +setglobal + +% Remove all but 'letter' page size +<< +currentpagedevice /InputAttributes get +1 1 2 index length 1 sub { + 1 index exch undef +} for +/InputAttributes exch +>> +setpagedevice + +% Patch setsmoothness, currentsmoothness for a better view of shadings : +userdict /.smoothness currentsmoothness put +/setsmoothness { + dup type dup /integertype eq exch /realtype eq or { + userdict /.smoothness 3 2 roll cvr put + } { + /setsmoothness .systemvar /typecheck signalerror + } ifelse +} bind odef +/currentsmoothness { userdict /.smoothness get } bind odef % for 09-55.PS, 09-57.PS . + +false 0 startjob pop % re-enter encapsulated mode diff --git a/gs/Resource/Init/gs_cff.ps b/gs/Resource/Init/gs_cff.ps new file mode 100644 index 000000000..89058f3f0 --- /dev/null +++ b/gs/Resource/Init/gs_cff.ps @@ -0,0 +1,848 @@ +% Copyright (C) 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Loader for CFF (compressed) fonts, including OpenType CFFs. +% The following are not implemented yet: +% Deleted entries in the Name Index +% Embedded PostScript +% Multiple Master fonts +% Chameleon fonts +% Synthetic fonts + +% ---------------- Font loading machinery ---------------- % + +% Augment the FONTPATH machinery so it recognizes OpenType CFF font sets. + +/.scanfontheaders where { + pop /.scanfontheaders [ + .scanfontheaders aload pop (OTTO*) + ] def +} if + +% Load a font file that might be an OpenType CFF font set. + +% <file> .loadfontfile - +/.loadnonottofontfile /.loadfontfile load def +/.loadfontfile { + dup 4 string .peekstring pop (OTTO) eq { + % If this is a font at all, it's an OpenType CFF font set. + .init_otto_font_file + % Use a random FontSet resource name. ****** WRONG ****** + realtime rand xor =string cvs exch //false //false + ReadData pop + } { + % Not a TrueType font. + .loadnonottofontfile + } ifelse +} bind def + +% <file> .init_otto_font_file <file> +/.init_otto_font_file { + /FontSetInit /ProcSet findresource begin + 2 dict begin + /f exch def /cff null def + card32 pop card16 6 { next pop } repeat dup { + % Stack: numtables tablesleft + dup 0 eq { + pop pop /.loadottofontfile cvx /invalidfont signalerror + } if + f 4 string readstring pop (CFF ) eq { sub exit } if + f 12 string readstring pop pop 1 sub % skip to next table + } loop + % Stack: tablesread + card32 pop card32 card32 + % Stack: tablesread start length + exch 3 -1 roll 1 add 16 mul 12 add sub + f exch subfilefilter flushfile % skip to start + f exch subfilefilter end +} bind def + +30 dict begin + +% ---------------- Standard strings (actually names) ---------------- % + +/StandardStrings mark + % The initial StandardStrings that that denote characters are + % defined as a pseudo-Encoding. +% 0 + /CFFStandardStrings .findencoding aload pop +% 379 + (001.000) +% 380 + (001.001) (001.002) (001.003) /Black /Bold + /Book /Light /Medium /Regular /Roman + /Semibold +.packtomark def + +% ---------------- Standard encodings ---------------- % + +/StandardEncodings [ + +% StandardEncoding +mark + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 1 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 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 + 0 111 112 113 114 0 115 116 117 118 119 120 121 122 0 123 + 0 124 125 126 127 128 129 130 131 0 132 133 0 134 135 136 + 137 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 138 0 139 0 0 0 0 140 141 142 143 0 0 0 0 + 0 144 0 0 0 145 0 0 146 147 148 149 0 0 0 0 +.packtomark + +% ExpertEncoding +mark + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 1 229 230 0 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 + 0 253 254 255 256 257 0 0 0 258 0 0 259 260 261 262 + 0 0 263 264 265 0 266 109 110 267 268 269 0 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 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 304 305 306 0 0 307 308 309 310 311 0 312 0 0 313 + 0 0 314 315 0 0 316 317 318 0 0 0 158 155 163 319 + 320 321 322 323 324 325 0 0 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 +.packtomark + +] readonly def + +% ---------------- Standard Charsets ---------------- % + +% We include an explicit 0 at the beginning of each charset. + +/StandardCharsets [ + +% ISOAdobe +mark + 0 + 1 1 228 { } for +.packtomark + +% Expert +mark + 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 +.packtomark + +% ExpertSubset +mark + 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 +.packtomark + +] readonly def + +% ---------------- Font loading ---------------- % + +% ------ Utilities ------ % + +/advance { % <n> advance - + f cff eq { pos add /pos exch store } { pop } ifelse +} bind def +/next { % - next <byte> + f read { + 1 advance + CFFDEBUG { ( ) print dup = } if + } if +} bind def +/next2 { % - next2 <byte1> <byte2> + f read { + f read { + 2 advance + CFFDEBUG { ( ) print 1 index =only (,) print dup = } if + } { + 1 advance + CFFDEBUG { ( ) print dup = } if + } ifelse + } if +} bind def +/nextstring { % <length> nextstring <string> + dup 0 eq { + pop () + } { + string f exch readstring pop dup length advance + CFFDEBUG { ( ) print dup == } if + } ifelse +} bind def +/card8 % - card8 <card8> + /next load +def +/card16 { % - card16 <card16> + next2 exch 8 bitshift add +} bind def +/card32 { % - card32 <card32> + card16 16 bitshift card16 add +} bind def +/offsetprocs [ + /card8 load + /card16 load + { card8 16 bitshift card16 add } bind + /card32 load +] readonly def +/offsetproc { % <offsize> offsetproc <proc> + 1 sub //offsetprocs exch get +} bind def +/offset { % <offsize> offset <offset> + offsetproc exec +} bind def +/sid % - <sid> sid + /card16 load +def +/Index { % <name> Index <name> <array> + CFFDEBUG { (% reading Index: ) print dup = } if + mark card16 + dup 0 ne { + 1 exch next + dup 0 eq { + pop % skip incorrect index, bug 689854 + } { + offsetproc dup exec pop exch { + dup exec dup 4 -1 roll sub 3 1 roll exch + } repeat + } ifelse pop + } if pop .packtomark + CFFDEBUG { (% Index lengths = ) print dup === } if + [ exch { nextstring } forall ] readonly +} bind def +/tokens { % - tokens <num1> ... <op#> (op# = 12 means EOF) + { + f read not { 12 exit } if + CFFDEBUG { (..) print dup = } if + 1 advance + dup 12 eq { pop next 32 add exit } if + dup 28 lt { exit } if + dup 32 lt { + 28 sub { + { card16 32768 xor 32768 sub } + { 4 offset dup 16#7fffffff gt { -1 32 bitshift add } if } + { tokenreal } + { 31 exit } + } exch get exec + } { + dup 247 lt { + 139 sub + } { + 247 sub { + { next 108 add } + { next 364 add } + { next 620 add } + { next 876 add } + { next 108 add neg } + { next 364 add neg } + { next 620 add neg } + { next 876 add neg } + % 255 is deliberately omitted and will cause a rangecheck + } exch get exec + } ifelse + } ifelse + } loop +} bind def +/tokenbuf 100 string def +/tokenput { % <index> <str> tokenput <index+length> + dup length 3 1 roll + tokenbuf 2 index 3 -1 roll putinterval add +} bind def +/tokenrealarray [ + (0)(1)(2)(3)(4)(5)(6)(7)(8)(9)(.)(E) + (E-) + () % ignore the invalid value + (-) + { exit } bind +] readonly def +/tokenreal { % - tokenreal <float> + 0 { + next exch 1 index -4 bitshift tokenrealarray exch get exec tokenput + % We must leave the byte on the stack temporarily so that + % the exit will see a consistent stack state. + 1 index 15 and tokenrealarray exch get exec tokenput exch pop + } loop + tokenbuf 0 3 -1 roll getinterval cvr exch pop +} bind def +/Dict { % <opsdict> Dict - + /opdict exch store { + mark tokens + CFFDEBUG { (tokens: ) print ] dup === mark exch aload pop } if + opdict exch .knownget { exec } if cleartomark + } loop cleartomark +} bind def +/idstring { % <sid> idstring <string|name> + dup 391 lt { //StandardStrings } { 391 sub strings } ifelse exch get +} bind def +/idname { % <sid> idname <name> + idstring dup type /nametype ne { cvn } if +} bind def +/subfilefilter { % <file> <length> subfilefilter <filter> + % SubFileDecode interprets a length of 0 as infinite. + dup 0 le { pop pop () 0 } if () /SubFileDecode filter +} bind def + +% ------ Top dictionary ------ % + +/offput { % <offset> <proc> offput - + 1 index 0 le + CFFDEBUG { dup { (not ) print } if (queued: ) print 2 index =only ( ) print 1 index === } if + { pop pop + } + { currentdict exch aload length 1 add packedarray cvx + offsets 3 1 roll put + } + ifelse +} bind def +/queueput { % <font> <proc> queueput - + 16#7fffffff offsets { pop .min } forall + pos sub nextstring + 3 1 roll aload length 2 add packedarray cvx + [ queued aload pop counttomark 2 add -1 roll ] + /queued exch store +} bind def +/printvk { % <value> <key> printvk <value> <key> + CFFDEBUG { (\t% ) print dup =only ( = ) print 1 index === } if +} bind def +/xxput { % <value> <key> <dict> xxput - + 3 1 roll exch put +} bind def +/putfi { % <value> <key> putfi - + printvk FontInfo xxput +} bind def +/xdef { % <value> <key> xdef - + exch def +} bind def +/pxdef { % <value> <key> pxdef - + printvk xdef +} bind def +/topdictops mark + 12 { CFFDEBUG { (\t% EOD) = } if exit } + 0 { idstring /version putfi } + 1 { idstring /Notice putfi } + 32 { idstring /Copyright putfi } + 2 { idstring /FullName putfi } + 3 { idstring /FamilyName putfi } + 4 { idstring /Weight putfi } + 33 { 0 ne /isFixedPitch putfi } + 34 { /ItalicAngle putfi } + 35 { /UnderlinePosition putfi } + 36 { /UnderlineThickness putfi } + 37 { /PaintType pxdef } + 38 { /FontType pxdef } % actually CharstringType + 39 { counttomark array astore /FontMatrix pxdef } + 13 { /UniqueID pxdef } + 5 { counttomark array astore /FontBBox pxdef } + 40 { /StrokeWidth pxdef } + 14 { counttomark array astore /XUID pxdef } + 15 { + /charset printvk pop + dup StandardCharsets length lt { + StandardCharsets exch get /charset xdef + } { + { queuecharset } offput + } ifelse + } + 16 { + /Encoding printvk pop + dup StandardEncodings length lt { + /Encoding xdef + } { + { queueEncoding } offput + } ifelse + } + 17 { { readCharStrings } offput } + 18 { exch /readPrivate cvx 2 packedarray offput } + % CIDFont operators + 62 { % ROS, must be first in a CIDFont + currentdict /FontType undef + currentdict /Encoding undef + currentdict /FontMatrix undef + /CIDFontVersion 0 def + /CIDFontRevision 0 def + /CIDFontType 0 def + /CIDCount 8720 def % Default value defined in CFF spec. + 3 dict begin + /Supplement pxdef + idstring dup type /nametype eq { .namestring } if /Ordering pxdef + idstring dup type /nametype eq { .namestring } if /Registry pxdef + /CIDSystemInfo currentdict end def + } + 63 { /CIDFontVersion pxdef } + 64 { /CIDFontRevision pxdef } + 65 { /CIDFontType pxdef } + 66 { /CIDCount pxdef } + 67 { /UIDBase pxdef } + 68 { { readFDArray } offput } + 69 { { readFDSelect } offput } + % This operator only appears in a FDArray element. + % We don't really need it, so ignore an error. + 70 { { idstring } .internalstopped { pop pop } { /FontName pxdef } ifelse } +.dicttomark readonly def + +% readcharset and readFDSelect may require the length of CharStringArray, +% but these structures may occur in the file before the CharStrings. +% If that happens, use a hack: assume that all the data up to the next +% queued read should be read. + +/charstringcount { % <font> charstringcount <count> true + % <font> charstringcount <length> false + /CharStringArray .knownget { + length true + } { + % Hack: look for the next queued read. + 16#7fffffff offsets { pop .min } forall + pos sub false + } ifelse +} bind def + +/readCharStrings { % <font> readCharStrings - + /CharStringArray Index put +} bind def + +% ------ Charsets and encodings ------ % + +% Note: formats 1 and 2 can overflow the operand stack. +% We'll fix this if it ever becomes necessary. +/charsetcount { + charstringcount { 1 sub } { 2 idiv } ifelse +} bind def +/charsetformats [ +{ [ 0 3 -1 roll charsetcount { sid } repeat ] +} bind +{ [ 0 3 -1 roll charsetcount { + dup 0 eq { pop exit } if + sid card8 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop + } loop ] +} bind +{ [ 0 3 -1 roll charsetcount { + dup 0 eq { pop exit } if + sid card16 1 add 2 index .min { exch 1 sub 1 index 1 add } repeat pop + } loop ] +} bind +] readonly def +/queuecharset { % <font> queuecharset - + { readcharset } queueput +} bind def +/readcharset { % <data> <font> readcharset - + begin 0 () /SubFileDecode filter /f exch store + charsetformats next get currentdict exch exec /charset exch def end +} bind def + +/encodingformats [ +{ 1 1 next { next exch Encoding 3 1 roll put } for +} bind +{ 1 next { + next next 1 add { + % Stack: gid code + Encoding 1 index 3 index put + exch 1 add exch 1 add + } repeat pop + } repeat pop +} bind +] readonly def +/queueEncoding { % <font> queueEncoding - + { readEncoding } queueput +} bind def +/readEncoding { % <data> <font> readEncoding - + begin 0 () /SubFileDecode filter /f exch store + /Encoding [ 256 { /.notdef } repeat ] def + next encodingformats 1 index 127 and get exec + 128 ge { + % Read supplementary encodings. + next { + Encoding next sid idname put + } repeat + } if end +} bind def + +% ------ FDArray and FDSelect ------ % + +/readFDArray { % <font> readFDArray - + /FDarray Index exch pop exch + 2 dict begin /f null def begin + [ exch { + dup length subfilefilter /f exch store + 10 dict begin + /FontType 2 def + /PaintType 0 def + /FontMatrix [0.001 0 0 0.001 0 0] def + /Private 20 dict def + //topdictops Dict currentdict end + } forall ] /FDArray xdef end end +} bind def + +/fdselectformats [ +% Note: this procedure can overflow the operand stack. +% We'll fix this if it ever becomes necessary. +{ [ exch charstringcount pop { card8 } repeat ] } bind % Format 0 +{ /FDSelect cvx /invalidfont signalerror } bind % Format 1 +dup % Format 2 +% The following procedure does not use excessive op-stack space. +{ pop 65535 array card16 card16 exch % Format 3 + { % Stack: array previndex + card8 card16 + exch 1 index 4 -1 roll + exch 1 exch 1 sub + { 3 index exch 2 index put } for pop + } repeat + % now resize the array to the final index. + 0 exch getinterval +} bind +] readonly def + +/readFDSelect { % <font> readFDSelect - + begin fdselectformats next get currentdict exch exec /FDSelect exch def end +} bind def + + +% ------ Private dictionary ------ % + +/deltarray { % -mark- <num1> ... deltarray <num1'> ... + 0 counttomark 1 sub { counttomark -1 roll add dup } repeat pop + counttomark array astore +} bind def + +/privatedictops mark + 12 { CFFDEBUG { (\t% EOD) = } if exit } + 6 { deltarray /BlueValues pxdef } + 7 { deltarray /OtherBlues pxdef } + 8 { deltarray /FamilyBlues pxdef } + 9 { deltarray /FamilyOtherBlues pxdef } + 41 { /BlueScale pxdef } + 42 { /BlueShift pxdef } + 43 { /BlueFuzz pxdef } + 10 { 1 array astore /StdHW pxdef } + 11 { 1 array astore /StdVW pxdef } + 44 { deltarray /StemSnapH pxdef } + 45 { deltarray /StemSnapV pxdef } + 46 { 0 ne /ForceBold pxdef } + 47 { /ForceBoldThreshold pxdef } + 48 { /lenIV pxdef } + 49 { /LanguageGroup pxdef } + 50 { /ExpansionFactor pxdef } + 51 { /initialRandomSeed pxdef } + 19 { PrivateStart add { readSubrs } offput } + 20 { /defaultWidthX pxdef } + 21 { /nominalWidthX pxdef } + % Multiple Master fonts only + 59 { /NDV pxdef } + 60 { /CDV pxdef } + 61 { /lenBuildCharArray pxdef } +.dicttomark readonly def + +/readPrivate { % <font> <size> readPrivate - + 2 dict begin + f 3 1 roll exch % f <size> <font> + StringCache queued_offset known { + /PrivateStart queued_offset def + } { + /PrivateStart pos def + 1 index 0 gt { + f 2 index string readstring pop + } { + () + } ifelse + StringCache queued_offset 2 index put + 0 () /SubFileDecode filter + /f exch store + } ifelse + dup /FontType .knownget not { 2 } if exch + /Private get begin + % Default lenIV to -1 even for Type 1 CharStrings. + 2 ne { /lenIV -1 def } if + //privatedictops Dict end + exch /f exch store advance + end +} bind def + +/readSubrs { % <font> readSubrs - + /Subrs Index put +} bind def + +% ------ Main program ------ % + +% Clean up after finishing a font. +/cleanupFont { % (currentdict) cleanupFont - + % Remove unwanted entries. + currentdict /charset undef + currentdict /CharStringArray undef +} bind def + +% Update the Encoding and CharStrings for a real font. +/finishFont { % (currentdict) finishFont - + % Construct the real Encoding. + % The value of Encoding is either a number, for predefined + % encodings, or an array of mixed GIDs and names. + /Encoding mark Encoding + CFFDEBUG { (Encoding: ) print dup === flush } if + dup type /integertype eq { + StandardEncodings exch get { idname } forall + } { + { + dup type /integertype eq { charset exch get idname } if + } forall + } ifelse .packtomark def + % Construct the CharStrings. + % Note that they may only correspond to an initial + % subset of the charset. + /CharStrings charset length CharStringArray length .min dict def + CFFDEBUG { + charset length =only ( charset ) print + CharStringArray length =only ( CharStringArray) = + charset == flush + } if + 0 1 CharStrings maxlength 1 sub { + dup CharStringArray exch get + exch charset exch get idstring CharStrings xxput + } for + cleanupFont +} bind def + +% Replace CharStrings with GlyphDirectory for a CIDFont; +% Move GlobalSubrs to descendent fonts. +/finishCIDFont { % (currentdict) finishCIDFont - + % Construct the GlyphDirectory, similar to CharStrings. + /FDBytes FDArray length 1 gt { 1 } { 0 } ifelse def + /GlyphDirectory charset length CharStringArray length .min dict def + CFFDEBUG { + charset length =only ( charset ) print + CharStringArray length =only ( CharStringArray) = + charset == flush + } if + 0 1 GlyphDirectory maxlength 1 sub { + dup CharStringArray exch get + % If there is more than one FDArray entry, add the font + % index to the beginning of each charstring. + FDBytes 1 eq { + FDSelect 2 index get + 1 string dup 0 4 -1 roll put exch concatstrings + } if + exch charset exch get GlyphDirectory xxput + } for + + Private /GlobalSubrs .knownget { + FDArray { + /Private get /GlobalSubrs 2 index put + } forall + pop + Private /GlobalSubrs undef + } if + + % Clean up. + currentdict /FDSelect undef + cleanupFont +} bind def + +% PDF may load OpenType font containing ordinary CFF data as a CIDFont. +% Convert the ordinary font to a CIDFont. +/makeCIDFont { % (currentdict) finishCIDFont - + /CIDFontType 0 def + /FDBytes 0 def + /GDBytes 0 def + /CIDMapOffset 0 def + + /CIDSystemInfo 3 dict begin % bogus + /Registry (Adobe) def + /Ordering (Identity) def + /Supplement 0 def + currentdict end def + + /FDArray 4 dict begin + /FontMatrix dup load { 1000 0 0 1000 0 0 } matrix concatmatrix def + /Private dup load def + /FontType dup load def + /PaintType dup load def + currentdict end 1 array astore def + + /FontType 9 def + + /GlyphDirectory CharStringArray def + /CIDCount GlyphDirectory length def + + Private /GlobalSubrs undef + currentdict /Encoding undef + currentdict /CharStrings undef + currentdict /UniqueID undef + currentdict /XUID undef + cleanupFont +} bind def + +% We need to pass the file as a parameter for the sake of the PDF +% interpreter. Also for the sake of PDF, a flag forces the font +% to be defined as <resname> instead of the name embedded in the data. +% This is needed for subsetted fonts; it is valid if the CFF +% contains only a single font. +% Finally, PDF interpreter may request creation of CIDFont out of an +% ordinary CFF font. +/StartData { % <resname> <nbytes> StartData - + currentfile exch subfilefilter //false //false ReadData pop +} bind def +/ReadData { % <resname> <file> <forceresname> <forcecid> ReadData <fontset> + % Initialize. + + 30 dict begin + /forcecidfont exch def + /forceresname exch def + /cff exch def + /pos 0 def + /resname exch cvlit def + /DEBUG CFFDEBUG def % bring the binding closer + /StringCache 1 dict def % Private DICT may be reused. + + % Read the header. + + /f cff def + /vmajor next def + /vminor next def + /hdrsize next def + /aoffsize next def + hdrsize 4 gt { + hdrsize 4 sub dup advance + f exch () /SubFileDecode filter flushfile + } if + + % Read the Indexes. + + /names Index def + /topdicts Index def + /strings Index def + /gsubrs Index def + + % Read the top Dicts. + + /offsets 50 dict def + /queued [] def + /opdict null def % reserve a slot + /fonts [ topdicts { + 0 () /SubFileDecode filter /f exch def + 40 dict begin + % Preload defaults that differ from PostScript defaults, + % or that are required. + /FontType 2 def + /PaintType 0 def + /FontMatrix [0.001 0 0 0.001 0 0] def + /charset StandardCharsets 0 get def + /Encoding 0 def + /FontInfo 10 dict + dup /UnderlinePosition -100 put + dup /UnderlineThickness 50 put + def + /Private 20 dict + gsubrs length 0 ne { dup /GlobalSubrs gsubrs put } if + def + //topdictops Dict + currentdict end + } forall ] def + + % Read other tables with queued offsets. + % We process these in order so we can advance if needed. + % The CFF file may not be positionable. + { % outer loop since offsets may be updated when processing + CFFDEBUG { (offsets: ) print [ offsets { pop } forall ] == } if + [ offsets { pop } forall ] { lt } .sort % process in order of appearance + { + CFFDEBUG { (queued offset: ) print dup =print flush (, current pos=) print pos = } if + /queued_offset 1 index def + StringCache 1 index .knownget { + /f exch 0 () /SubFileDecode filter def + } { + /f cff def + dup pos ne { dup pos sub nextstring pop } if % negative advance will cause error + } ifelse + offsets exch 2 copy get 3 1 roll undef + CFFDEBUG { (exec queued: ) print dup == } if + exec + } forall + offsets length 0 eq { exit } if + } loop + + % Process out-of-order tables. + + CFFDEBUG { queued length =only ( queued) = flush } if + queued { exec } forall + + % Update Encoding and CharStrings. + + fonts { + begin + currentdict /CIDFontType known { + finishCIDFont + } { + forcecidfont //makeCIDFont //finishFont ifelse + } ifelse + end + } forall + + % Wrap up. + + resname mark 0 1 fonts length 1 sub { + CFFDEBUG { dup =only ( ) print flush } if + dup names exch get + forceresname { pop resname } if + CFFDEBUG { dup == flush } if + exch fonts exch get + dup /CIDFontType known { + % This is a CIDFont. + dup /CIDFontName 3 index put + 1 index exch /CIDFont defineresource + } { + % This is a font. + dup /FontName 3 index put + 1 index exch definefont + } ifelse + } for .dicttomark + end % temporary dict + end % FontSetInit ProcSet + /FontSet defineresource + +} bind def + +% ---------------- Resource category definition ---------------- % + +currentdict end readonly + +languagelevel exch 2 .setlanguagelevel + +/FontSet /Generic /Category findresource dup length dict .copydict +/Category defineresource pop + +/FontSetInit exch /ProcSet defineresource pop + +.setlanguagelevel diff --git a/gs/Resource/Init/gs_cidcm.ps b/gs/Resource/Init/gs_cidcm.ps new file mode 100644 index 000000000..0f5e5a026 --- /dev/null +++ b/gs/Resource/Init/gs_cidcm.ps @@ -0,0 +1,446 @@ +% Copyright (C) 2000 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Extending Font resource category with CIDFont-CMap fonts. + +languagelevel 2 .setlanguagelevel currentglobal true setglobal + + +% In the comments below, 'CSI' is an abbreviation/acronym for CIDSystemInfo. +% We pre-scan resource files to retrieve the CSI from them. +% First we define a hidden procset .prs_dict containing +% necessary variables and procedures. +% Then we redefine the old /Font category using this procset. + +% We maintain internal caches for the CSI values retrieved from +% resource files. This supposes that document doesn't uninstall +% resource files. To disable caching, set enable_cache to false. + +% We assume that names starting with '.prs' do not appear in resource files. +% If this causes any problem, this prefix should be systematically changed +% in this file. ('prs' is an abbreviation for 'prescan'.) + +25 dict begin + +% Define local variables : + +/.prs_dict currentdict def % self-reference (constant) +/.prs_empty 0 dict readonly def +/path_buffer 8192 string def +/name_buffer 1024 string def +/minus (-) 0 get def % character code constant for '-' +/period (.) 0 get def % character code constant for '.' +/CMap 10 dict def % CSI cache for CMaps +/CIDFont 10 dict def % CSI cache for CIDFonts +/enable_cache true def % set false to disable cache + +% The folloving variables are just placeholders for ones to be set +% dynamically : +/.prsFile 0 def % file to prescan +/.prsResult 0 def % result of prescan +/.prsDictCount 0 def % save the dictionary stack depth + +% Define a dummy CIDInit procset to use while pre-scanning : + +/DummyCIDInit 15 dict +begin + + /begincmap {} def + /usecmap {pop} bind def + + {stop} bind + [ /begincodespacerange /endcodespacerange /beginnotdefchar /endnotdefchar + /beginnotdefrange /endnotdefrange /begincidchar /endcidchar /begincidrange + /endcidrange /endcmap /usefont /StartData + ] { + 1 index def + } bind forall + pop + +currentdict end def + +% Define a local 'findresource' for pre-scanning : +% (it returns the dummy CIDInit instead of the regular CIDInit ProcSet) + +/findresource { % <InstName> <CatName> findresource <inst> + 2 copy /ProcSet eq exch % /InstName /CatName bool /InstName + /CIDInit eq and { + pop pop //DummyCIDInit + } { + //findresource exec + } ifelse +} bind def + +% Define procedures for pre-scanning : + +/StopIfCSIDefined { % - StopIfCSIDefined - + + % Check if the dictionary stack contains a dictionary containing /CIDSystemInfo. + % The search is limited to the top .prsDictCount dictionaries in the stack. + % If so, retrieve the CSI, and execute stop to terminate the pre-scanning of the file. + % Otherwise, do nothing, so the pre-scanning continues. + + countdictstack //.prs_dict /.prsDictCount get sub dup { + currentdict /CIDSystemInfo .knownget { + //.prs_dict exch /.prsResult exch put + stop + } if + currentdict exch end + } repeat { + begin + } repeat +} bind def + +/PrescanFile { % - PrescanFile - + { //.prs_dict /.prsFile get token { + dup type % token type + dup /nametype eq exch /operatortype eq or { + dup xcheck { + exec + //StopIfCSIDefined exec + } if + } if + } { + stop + } ifelse + } loop +} bind odef + +/GetCIDSystemInfoFromFile { % <file> GetCIDSystemInfoFromFile <CSI> + + % This procedure reads resource files with 'token', + % executing the tokens untill /CIDSystemInfo appears to be defined. + % Normally the resource file creates a new dictionary on + % dictionary stack and defines /CIDSystemInfo in it. + % + % Returns an empty dictionary if no CIDSystemInfo is found. + + RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile beg) = } if + //.prs_dict begin + /.prsFile exch def + /.prsResult //.prs_empty def + /.prsDictCount countdictstack def + RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile will PrescanFile.) = } if + { //PrescanFile } stopped pop + //.prs_dict /.prsResult get + end + RESMPDEBUG { (cidcm GetCIDSystemInfoFromFile end) = } if +} bind def + +/GetCIDSystemInfo { % <InstName> <CatName> GetCIDSystemInfo <CSI> + + % Retrieve CSI, using caches. + + RESMPDEBUG { (cidcm GetCIDSystemInfo beg) = } if + /Category findresource begin % /InstName + dup ResourceStatus + { + pop 2 lt { + FindResource /CIDSystemInfo .knownget not { + //.prs_empty + } if % CSI + } { % /InstName + currentdict /GetCIDSystemInfoFromMap .knownget { + exec + } if + dup type /nametype eq + { + RESMPDEBUG { (cidcm GetCIDSystemInfo got a name.) = } if + //.prs_dict Category get % /InstName CSIs + dup 2 index known + //enable_cache and { + RESMPDEBUG { (cidcm GetCIDSystemInfo from cache.) = } if + exch get % CSI + } { + RESMPDEBUG { (cidcm GetCIDSystemInfo from file.) = } if + exch % CSIs /InstName + dup //path_buffer ResourceFileName % CSIs /InstName (path) + RESMPDEBUG { (cidcm GetCIDSystemInfo from file ) print dup = } if + currentglobal exch true setglobal % CSIs /InstName g (path) + mark exch % CSIs /InstName g [ (path) + { (r) file } stopped { + cleartomark //.prs_empty + } { + exch 1 index % CSIs /InstName g file [ file + //GetCIDSystemInfoFromFile stopped { + cleartomark closefile //.prs_empty + } { + exch pop exch closefile + } ifelse + } ifelse % CSIs /InstName g CSI + exch setglobal % CSIs /InstName CSI + dup 4 1 roll % CSI CSIs /InstName CSI + put % CSI + RESMPDEBUG { + (cidcm GetCIDSystemInfo got from file : <<) print + dup { exch //=string cvs print ( ) print + //=string cvs print ( ) print + } forall + (>>) = + } if + } ifelse + } if + } ifelse + } { + pop //.prs_empty + } ifelse + end + RESMPDEBUG { (cidcm GetCIDSystemInfo end) = } if +} bind def + +/IsCompatibleCSI { % <CSI-M> <CSI-F> IsCompatibleCSI <bool> + + % The CSI in a CIDFont may be an array, a dict, or null. + % If it is an array, it must be of 1 element, which is a dict. + % In this case the dict is used for testing the compatibility. + % Two dicts are compatible iff they contain same /Ordering and /Registry. + + exch % CSI-F CSI-M + { dup type /arraytype eq { + dup length 1 ne { + pop pop false exit + } if + 0 get + } if % CSI-F CSI-M + dup type /dicttype ne { + pop pop false exit + } if % CSI-F <<CSI-M>> + exch % <<CSI-M>> CSI-F + dup type /dicttype ne { + pop pop false exit + } if % <<CSI-M>> <<CSI-F>> + true % <<CSI-M>> <<CSI-F>> bEQ + [/Registry /Ordering] { + 2 index 1 index .knownget not { + 1234567 + } if % <<CSI-M>> <<CSI-F>> bEQ /key vF + exch % <<CSI-M>> <<CSI-F>> bEQ vF /key + 4 index exch .knownget not { + 7654321 + } if % <<CSI-M>> <<CSI-F>> bEQ vF vM + eq and % <<CSI-M>> <<CSI-F>> bEQ + } forall + exch pop exch pop % bEQ + exit + } loop +} bind def + +/IsWellComposed { % <CIDFontName> <CMapName> IsWellComposed <bool> + + % Check if the given CIDFont and CMap have compatible CSIs. + exch % /CMapName /CIDFontName + /CIDFont //GetCIDSystemInfo exec % /CMapName CSI-F + dup type /dicttype eq { + dup length 0 ne { + exch % CSI-F /CMapName + /CMap //GetCIDSystemInfo exec % CSI-F CSI-M + //IsCompatibleCSI exec % bool + } { + pop pop false + } ifelse + } { + pop pop false + } ifelse +} bind def + +/IsComposedFont { % <FontName> IsComposedFont <CIDFontName> <CMapName> true + % <FontName> IsComposedFont false + + % Check if the given font name may be decomposed into CIDFont.CMap, CIDFont-CMap + % or into CIDFont--CMap, such that CIDFont and CMap have compatible CSIs. + % FontName + dup type /stringtype ne { + //name_buffer cvs + } if % (FontName) + { dup length 2 sub -1 1 { + % (FontName) i + 2 copy get dup //minus eq exch //period eq or { + 2 copy 2 copy % (FontName) i (FontName) i (FontName) i + 2 copy get //minus eq { + 2 copy 1 sub get //minus eq { + 1 sub + } if + } if % (FontName) i (FontName) i (FontName) i0 + 0 exch getinterval cvn % (FontName) i (FontName) i /CIDFontName + 3 1 roll % (FontName) i /CIDFontName (FontName) i + 1 add dup % (FontName) i /CIDFontName (FontName) i1 i1 + 5 index length % (FontName) i /CIDFontName (FontName) i1 i1 l + exch sub getinterval cvn % (FontName) i /CIDFontName /CMapName + 2 copy //IsWellComposed exec { % (FontName) i /CIDFontName /CMapName + 4 2 roll pop pop % /CIDFontName /CMapName + stop + } if + pop pop pop + } { + pop + } ifelse % (FontName) + } for + pop + } stopped +} bind def + +/ComposeName { % <CIDFont> <CMap> <scr> ComposeName <CIDFont-CMap> + dup dup 5 2 roll % (scr) (scr) /CIDFont /CMap (scr) + 3 2 roll exch cvs length dup % (scr) (scr) /CMap l0 l0 + 4 -1 roll exch //minus put % (scr) /CMap l0 + 1 add dup % (scr) /CMap l1 l1 + 3 index dup length % (scr) /CMap l1 l1 (scr) L + 2 index sub % (scr) /CMap l1 l1 (scr) LT + 3 2 roll % (scr) /CMap l1 (scr) LT l1 + exch getinterval % (scr) /CMap l1 (scrT) + 3 2 roll exch cvs length % (scr) l1 l2 + add 0 exch getinterval % (CIDFont-CMap) +} bind def + +% Redefine the /Font category with CIDFont-CMap construction : + +% The following code supposes that the following names are not +% defined in the old /Font category dictionary : +% /IsComposedFont, /IsWellComposed . + + +/Font /Category findresource dup length dict copy begin + +/FindResource { % <InstName> FindResource <inst> + dup //ResourceStatus exec { + pop pop //FindResource exec + } { + dup //IsComposedFont exec { % /FontName /CIDFontName /CMapName + exch [ exch ] composefont % inst + } { + //FindResource exec + } ifelse + } ifelse +} bind def + +/ResourceStatus { % <InstName> ResourceStatus <nStatus> <nSize> true + % <InstName> ResourceStatus false + dup //ResourceStatus exec { + 3 2 roll pop true % nStatus nSize true + } { + //IsComposedFont exec { % /CIDFontName /CMapName + /CMap resourcestatus { % /CIDFontName nStatusM nSizeM + exch pop exch % nSizeM /CIDFontName + /CIDFont resourcestatus { % nSizeM nStatusF nSizeF + exch pop % nSizeF nSizeM + dup 0 ge { + exch dup 0 ge { + add + } { + exch pop + } ifelse + } { + pop + } ifelse % nSize + 2 exch true % nStatus nSize true + } { + pop pop pop false % work around buggy resource file + } ifelse + } { + pop pop pop false % work around buggy resource file + } ifelse + } { + false + } ifelse + } ifelse +} bind def + +/ResourceForAll { % <template> <proc> <scratch> ResourceForAll - + + % We suppose that the resourceforall procedure does not + % define or install new fonts, CMaps, and/or CIDFonts. + + % First we create 3 temporary dictionaries to store temporary data + % about fonts, CMaps and CIDFonts. + % These dictionaries must be created dynamically, to allow for a possible + % recursive call to resourceforall from the resourceforall procedure. + currentglobal false setglobal + 20 dict 20 dict 20 dict % (templ) proc (scr) g <<CIDFont>> <<CMap>> <<Fonts>> + + + % Store resource identifiers into local dictionaries + % A resource instance can have a key that is not a name or a string. In this + % case, resourceforall passes the key directly to proc instead of copying it + % into the scratch string. This case can arise only for a resource instance + % defined in virtual memory by a previous defineresource + + % Discard non-string keys of CIDFont and CMap because <CIDFontName>-<CMapName> + % is only defined for names. + + { /.DisableResourceOrdering pop % gs_resmp accesses this through execstack - don't remove ! + + 6 index [ 2 index {exch //null put} aload pop ] cvx bind 6 index //ResourceForAll exec + + (*) [ 3 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop + ] cvx bind 6 index /CMap resourceforall + + (*) [ 4 index {exch dup type /stringtype eq { cvn dup put } { pop pop } ifelse } aload pop + ] cvx bind 6 index /CIDFont resourceforall + + exit + } loop % This loop is a pattern for execstack_lookup - don't remove ! + 4 -1 roll setglobal % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> + + %% Make the list of fonts in the form (/Name status) : + + % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> + dup { + pop dup + //ResourceStatus exec { + pop 2 index % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> /Name nStatus <<Font>> + 3 1 roll put % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> + } { + pop + } ifelse + } forall % (templ) proc (scr) <<CIDFont>> <<CMap>> <<Fonts>> + + %% Add CIDFont-CMap to it (filtering duplicates) : + + 3 2 roll { + 3 index { + 3 1 roll % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /CIDFont /CMap + 6 index //ComposeName exec % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap (Font) + dup 8 index .stringmatch { + cvn % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font + dup 4 index exch known { + pop pop + } { + 2 index % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CMap /Font /CIDFont + 4 2 roll % (templ) proc (scr) <<CMap>> <<Font>> /Font /CIDFont /CIDFont /CMap + //IsWellComposed exec { + exch 2 index exch 2 put % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont + } { + exch pop + } ifelse + } ifelse + } { + pop pop + } ifelse + dup % (templ) proc (scr) <<CMap>> <<Font>> /CIDFont /CIDFont + } forall + pop pop % (templ) proc (scr) <<CMap>> <<Font>> + } forall % (templ) proc (scr) <<CMap>> <<Font>> + exch pop % (templ) proc (scr) <<Font>> + 4 3 roll pop % proc (scr) <<Font>> + + % Make the enumerator and apply it : + /MappedCategoryRedefiner /ProcSet findresource /MakeResourceEnumerator get exec exec +} bind def + + +currentdict end /Font exch /Category defineresource pop +end +setglobal .setlanguagelevel diff --git a/gs/Resource/Init/gs_ciddc.ps b/gs/Resource/Init/gs_ciddc.ps new file mode 100644 index 000000000..ecfeb26a4 --- /dev/null +++ b/gs/Resource/Init/gs_ciddc.ps @@ -0,0 +1,214 @@ +% Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define Decoding and CIDDecoding resource categories and related procsets. + +languagelevel 2 .setlanguagelevel +currentglobal true setglobal + +%----------------ParseDecoding procset---------------------------- + +/ParseDecoding << + +/Parse % <resource_name> <num_tokens> Parse - +{ dict begin % /ResName + 0 % /ResName nCode + { currentfile token not { + exit + } if % /ResName nCode token + dup type /integertype eq { % /ResName nCode + exch pop + } { + 1 index def % /ResName nCode + } ifelse + } loop % /ResName nCode + pop % /ResName + currentdict end /Decoding % /ResName <<inst>> /Decoding + defineresource pop +} bind + +>> /ProcSet defineresource pop + +%----------------Decoding category---------------------------- + +/Generic /Category findresource dup length dict copy +dup /InstanceType /dicttype put +/Decoding exch /Category defineresource pop + +%----------------ParseCMap_Inverse procset---------------------------- + +/ParseCMap_Inverse << + /findresource { pop } bind + /defineresource { pop pop } bind + /dict {} + /def { pop pop } bind + /dup null + /begin { pop } bind + /end {} + /currentdict null + /CMapName null + /usecmap { pop } bind + /begincmap {} + /endcmap {} + /begincodespacerange { pop mark } bind + /endcodespacerange { cleartomark } bind + /beginnotdefrange { pop mark } bind + /endnotdefrange { cleartomark } bind + /beginbfchar { pop mark } bind + /endbfchar { pop mark } bind + /beginbfrange { begincidrange } + /endbfrange { endcidrange } + /begincidchar { beginbfchar } + /endcidchar { endbfchar } + /begincidrange { pop mark } bind + /endcidrange { cleartomark } bind +>> % Just keep it on stack for a while. + +% Now we define another dict for local binding, than merge it with the previous one : +dup length 5 add dict begin + + /.Ranges 40 dict def % Key = CID/256, value = array of 256 integer codes. + //.Ranges /CIDCount 0 put + + /.StringToInt % <string> .StringToInt <integer> + { 0 exch { exch 8 bitshift add } forall + } bind def + + /.SetCouple % <I> <b> .SetCouple - + { exch % b I + dup 256 idiv % b I I0 + dup //.Ranges exch known not { + dup //.Ranges exch 256 array put + } if % b I I0 + //.Ranges exch get % b I [Range] + exch 256 mod % b [Range] I1 + 2 copy get % b [Range] I1 e + dup //null ne { + % We've got char code duplicates for same CID. + dup type /integertype eq { + 4 3 roll % [Range] I1 e b + 2 array astore put % + } { + dup length 1 add dup dup array dup % b [Range] I1 D l l D' D' + 3 2 roll 0 exch getinterval % b [Range] I1 D l D' D'' + 4 3 roll exch copy pop % b [Range] I1 l D' + dup 3 2 roll 1 sub % b [Range] I1 D' D' l-1 + 6 5 roll % [Range] I1 D' D' l-1 b + put put % + } ifelse + } { + pop 3 2 roll put % + } ifelse + } bind def + + /endcidrange + { % Writes the inversed CMap to .Ranges + counttomark 3 idiv { % (b) (e) I + exch .StringToInt % (b) I e + 3 2 roll .StringToInt % I e b + % Note : this code does't handle multidimentional CID ranges. + % fixme : optimize below. + dup 3 2 roll exch sub 1 add % I b d + { 2 copy //.SetCouple exec % I b + 1 add exch 1 add exch + } repeat % I b + pop % I + dup //.Ranges /CIDCount get gt { % I + dup //.Ranges exch /CIDCount exch put + } if % I + pop + } repeat + pop % mark + } bind def + + /.GetCIDDecoding % - .GetCIDDEcoding <dict> + { //.Ranges dup length dict copy + //.Ranges //.PurgeDict exec + //.Ranges /CIDCount 0 put + } bind def + +currentdict end +exch copy % Merge the dicts - see above. +/ProcSet defineresource pop + +%----------------CIDDecoding category---------------------------- +% Note that we put all instances in global memory - see FindResource. + +/Generic /Category findresource dup length dict copy +begin + /Category /CIDDecoding def + /InstanceType /dicttype def + + /.CMapChooser << + % This lists CMaps to inverse and unite for creating a CIDDecoding. + % Choose by FAPIcidfmap.Registry concatenated with TrueType encoding ID. + % Font renderer must provide the glyph substitution internally. + + /CNS1.Big5 [ /ETen-B5-H /ETen-B5-V ] + /CNS1.Unicode [ /UniCNS-UCS2-H /UniCNS-UCS2-V] + /GB1.GB2312 [ /GBK-EUC-H /GBK-EUC-V ] + /GB1.Unicode [ /UniGB-UCS2-H /UniGB-UCS2-V ] + /Japan1.ShiftJIS [ /90ms-RKSJ-H /90ms-RKSJ-V ] + /Japan1.Unicode [ /UniJIS-UCS2-H /UniJIS-UCS2-V] + /Japan2.ShiftJIS [ /90ms-RKSJ-H /90ms-RKSJ-V ] + /Japan2.Unicode [ /UniHojo-UCS2-H ] + /Korea1.Johab [ /KSC-Johab-V /KSC-Johab-H ] + /Korea1.Wansung [ /KSCms-UHC-V /KSCms-UHC-H ] + /Korea1.Unicode [ /UniKS-UCS2-H /UniKS-UCS2-V ] + /Identity.Symbol [ /Identity-H /Identity-V ] + /Unicode.Unicode [ /Identity-UTF16-H ] + >> def + + /.MakeInstance % <name> .MakeInstance <inst> + { dup % /Name /Name + //.CMapChooser exch .knownget not { + (Can't build /) print =string cvs print ( /CIDDecoding resource. See gs_ciddc.ps . ) = + /findresource cvx /undefinedresource signalerror + } if % /Name [CMaps] + exch pop % [CMaps] + /CMap /Category findresource % [CMaps] <CMapCategory> + /ParseCMap_Inverse /ProcSet findresource % [CMaps] <CMapCategory> <PCI> + 3 2 roll { % <CMapCategory> <PCI> /CMapName + 3 2 roll begin % <PCI> /CMapName + dup .ResourceFile not { + (Can't find CMap ) print =string cvs print ( building a CIDDecoding resource. ) = + /findresource cvx /undefinedresource signalerror + } if + currentdict end exch % <PCI> /CMapName <CMapCategory> file + + 3 index begin + cvx exec % <PCI> /CMapName <CMapCategory> + end + exch pop exch % <CMapCategory> <PCI> + } forall + exch pop begin % + .GetCIDDecoding + end + } bind def + + /FindResource % <name> FindResource <dict> + { currentglobal exch % bGlobal /InstName + true setglobal + dup //.MakeInstance exec % bGlobal /InstName <Inst> + DefineResource % bGlobal <Inst> + exch setglobal % <Inst> + } bind def + +currentdict end +/CIDDecoding exch /Category defineresource pop + +setglobal +.setlanguagelevel diff --git a/gs/Resource/Init/gs_cidfm.ps b/gs/Resource/Init/gs_cidfm.ps new file mode 100644 index 000000000..0433fa4fb --- /dev/null +++ b/gs/Resource/Init/gs_cidfm.ps @@ -0,0 +1,129 @@ +% Copyright (C) 2000 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Redefine CIDFont category with cidfmap . + +languagelevel 2 .setlanguagelevel + +4 dict begin +/CategoryName /CIDFont def + +/MapFileName (cidfmap) def + +/IsMyRecord % <raw_record> -> <raw_record> bool +{ % Only for client's needs. + dup type /nametype eq +} bind def + +/RecordVirtualMethods 3 dict begin + + /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> + { % We know that currentdict is the category. + /Substitute get FindResource % /Name <<CIDFont>> + dup length dict copy % /Name <<CIDFont>> + 1 index ResourceStatus pop exch pop % /Name <<CIDFont>> size + } bind def + + /GetFilePath % <scratch> <Name> <record> GetFilePath <filepath> + { % We know that currentdict is the category. + exch pop + /Substitute get exch ResourceFileName + } bind def + + /GetSize % <Name> <record> GetSize <size> + { % We know that currentdict is the category. + /Substitute get ResourceStatus { + exch pop exch pop + } { + /undefinedresource signalerror + } ifelse + } bind def + + /GetCSI % <record> GetCSI null + % <record> GetCSI dict + { % We know that currentdict is the category. + RESMPDEBUG { (cidfm GetCSI beg ) = } if + /Substitute get % /Name + GetCIDSystemInfoFromMap + RESMPDEBUG { (cidfm GetCSI end ) print dup = } if + } bind def + + /IsActive % <record> IsActive <bool> + { pop true + } bind def + +currentdict end def + +/VerifyMap % <raw_map> VerifyMap - +{ % Checks for vicious substitution cycles. + dup length dict copy % <<map>> + dup length dict % <<map>> <<temp>> + { % Choose a random record : + true 2 index { % <<map>> <<temp>> true /Name /Subs + 3 2 roll pop false exit % <<map>> <<temp>> /Name /Subs false + } forall + { exit % <<map>> <<temp>> + } if % <<map>> <<temp>> /Name /Subs + % Move the substitution chain to <<temp>>, checking for a cycle : + 3 index 2 index undef % <<map>> <<temp>> /Name /Subs + exch 2 index exch 0 put % <<map>> <<temp>> /Subs + { //IsMyRecord exec not { + % Not a substitution, the chain terminates. + pop exit % <<map>> <<temp>> + } if % <<map>> <<temp>> /Subs + 1 index 1 index known { + (Vicious substitution cycle in map file with the entry ) print =string cvs print ( .) = + /VerifyMap cvx /undefinedresource signalerror + } if % <<map>> <<temp>> /Subs + 1 index 1 index 0 put + dup 3 index exch .knownget not { % <<map>> <<temp>> /Subs + % No more substitutions, the chain terminates. + pop exit % <<map>> <<temp>> + } if % <<map>> <<temp>> /Subs /Subs1 + exch % <<map>> <<temp>> /Subs1 /Subs + 3 index exch undef % <<map>> <<temp>> /Subs1 + } loop + % Not cycled, now purge the <<temp>> : + { % Choose a random record : + true 1 index { % <<map>> <<temp>> true /Name /Subs + 3 2 roll pop false exit % <<map>> <<temp>> /Name /Subs false + } forall + { exit % <<map>> <<temp>> + } if % <<map>> <<temp>> /Name /Subs + % Remove it : + pop 1 index exch undef % <<map>> <<temp>> + } loop + } loop + pop pop % +} bind def + +/PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> +{ //IsMyRecord exec { + 1 dict begin + /Substitute exch def + /RecordVirtualMethods //RecordVirtualMethods def + currentdict end + true + } { + false + } ifelse +} bind def + +currentdict end + +/MappedCategoryRedefiner /ProcSet findresource /Redefine get exec + +.setlanguagelevel diff --git a/gs/Resource/Init/gs_cidfn.ps b/gs/Resource/Init/gs_cidfn.ps new file mode 100644 index 000000000..91bd95b6d --- /dev/null +++ b/gs/Resource/Init/gs_cidfn.ps @@ -0,0 +1,412 @@ +% Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% ProcSet for implementing CIDFont and CIDMap resources. +% When this is run, systemdict is still writable. + +% ---------------- Defining CIDFont resources ---------------- % + +% Define a CIDFont resource. This is the defineresource implementation for +% the CIDFont resource category. + +/.checkfonttype { % <cidfont> <fonttype> .checkfonttype <cidfont> <new?> + 1 index /FID known { + 1 index /FontType get ne { + /definefont cvx /invalidfont signalerror + } if false + } { + 1 index /FontType 3 -1 roll put true + } ifelse +} bind def + +/.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse +.cidfonttypes + +30 dict begin + +% The key in .cidfonttypes is the CIDFontType value; +% the value is a procedure that takes a font name and the CIDFont dictionary +% and replaces the latter with a real font. + +% ------ CIDFontType 0 (FontType 9) ------ % + +% We add the following entries to the CIDFont dictionary, in addition to +% the ones documented by Adobe: +% SubrCache - dictionary for caching Subr arrays +% For CIDFonts where we read the data from disk incrementally: +% GlyphData is 0 (arbitrary) +% DataSource - a ReusableStreamDecode filter for the data +% We also add a FID entry, and possibly a Subrs entry, to each element of +% FDArray. + +dup 0 { + 9 .checkfonttype { + /CIDInit /ProcSet findresource begin + .completefont9 + end + } if + 1 index exch .buildfont9 exch pop +} put % Don't bind it here, because gs_fapi.ps redefines .buildfont9 + +% Add entries to a new CIDFontType 0 font per documentation (FontMatrix) +% or for .buildfont9 (FDArray.Private.Subrs). +/.completefont9 { % <cidfont0> .completefont9 <cidfont0> + currentglobal 3 1 roll dup gcheck setglobal + dup /FontMatrix known { + dup /FDArray get { + dup /FontMatrix get 0 get 1000000 ge { + /FontMatrix matrix put % Bug 688517 + } { + pop + } ifelse + } forall + } { + dup /FontMatrix [0.001 0 0 0.001 0 0] put + dup /FDArray get { + currentglobal exch dup gcheck setglobal + dup /FontMatrix get {1000 0 0 1000 0 0} matrix concatmatrix + /FontMatrix exch put + setglobal + } forall + } ifelse + dup /FDArray get { + % Read the Subrs if necessary. + dup /Private get dup /Subrs known not { + dup /SubrCount .knownget { + % Stack: font Private SubrCount + currentglobal 3 1 roll 1 index gcheck setglobal + array 1 index /Subrs 3 -1 roll put + % Stack: font global Private + 2 index begin begin .loadsubrs end end + setglobal + } { + pop + } ifelse readonly pop + } { + pop pop + } ifelse + } forall + 3 -1 roll setglobal +} bind def + +% Read some Subrs for the current Type 1 subfont. +% The subfont's Private dict is currentdict; the CIDFont itself is the +% next dictionary on the stack. +/.readsubrs { % <Subrs> <start> .readsubrs <Subrs> + 1 SubrCount 1 sub { + dup SDBytes mul SubrMapOffset add + dup SDBytes .readint exch SDBytes add SDBytes .readint + 1 index sub string ReadString 2 index 3 1 roll put + } for +} bind def + +% Ensure that all the Subrs for the current Type 1 subfont are loaded. +% The subfont's Private dict is currentdict; the CIDFont itself is the +% next dictionary on the stack. +/.loadsubrs { + Subrs length 0 ne { + SubrCache SubrMapOffset .knownget { + % We've already loaded some Subrs at this offset. + % Make sure we've got as many as we need. + dup length SubrCount lt { + % We need to load more. + SubrCount array exch 1 index copy length .readsubrs + SubrCache SubrMapOffset 2 index put + } if + } { + % We haven't loaded any Subrs at this offset yet. + SubrCount array 0 .readsubrs + SubrCache SubrMapOffset 2 index put + } ifelse + Subrs copy pop + } if +} bind def + +% ------ CIDFontType 1 (FontType 10) ------ % + +dup 1 { + 10 .checkfonttype pop + 1 index exch .buildfont10 exch pop +} put % Don't bind it here because gs_fapi.ps redefines .buildfont10 + +% ------ CIDFontType 2 (FontType 11) ------ % + +dup 2 { + 11 .checkfonttype pop + 1 index exch .buildfont11 exch pop +} put % Don't bind it here because gs_fapi.ps redefines .buildfont11 + +pop % .cidfonttypes + +% ---------------- Reading CIDFontType 0 files ---------------- % + +/StartData { % <(Binary)|(Hex)> <datalength> StartData - + % (currentdict is CID font dict) + % If we're loading a resource file and the data format is + % binary, we can just save a pointer to the data and load it + % incrementally. + mark { + % Previous versions of this code made provisions for + % reading hex-encoded data incrementally. Since hex data + % doesn't seem to be used in practice, we no longer bother. + 2 index (Binary) ne { stop } if + currentfile .currentresourcefile ne { stop } if + % Hack: the pdfwrite driver relies on finalization to write + % out fonts. However, the font may be finalized after the + % resource file, in which case the resource file will be + % closed. So if the current output device is pdfwrite, + % don't use incremental loading. + currentdevice .devicename /pdfwrite eq { stop } if + currentfile fileposition + } .internalstopped { + % File is not positionable, or uses hex data. + % Load the data now. + cleartomark exch + currentfile exch + (Hex) eq { /ASCIIHexDecode filter } if + exch + % Stack: file length + dup 65400 le { + % readstring with a 0-length string causes a rangecheck, + % but a data length of 0 is allowed. + string dup () ne { 1 index exch readstring pop } if + } { + mark 3 1 roll { + % Stack: mark str ... file length + dup 0 eq { pop exit } if + dup 65400 .min dup string 3 index exch readstring pop + % Stack: mark str ... file length newstrlen newstr + 4 1 roll sub + } loop + counttomark 1 add 1 roll ] + } ifelse + /GlyphData exch def + dup currentfile eq { pop } { closefile } ifelse + } { + % File is positionable and binary, just save a pointer. + % Stack: (Binary) length -mark- pos + /GlyphData 0 def + exch pop 3 -1 roll pop exch + % Stack: pos length + /DataSource currentfile 2 index () .subfiledecode true .reusablestream def + currentfile 3 1 roll add setfileposition + } ifelse + /SubrCache 10 dict def + CIDFontName currentdict /CIDFont defineresource pop + end % CID font dict + end % resource category dict +} bind def + +% Some Adobe fonts include the line +% /Setup /cid_Setup load def +% This is apparently included only to prevent proper, conforming PostScript +% interpreters (as opposed to ATM or a special Adobe font loader) from +% loading the font, since Setup is not referenced anywhere else in the file. +/cid_Setup { } def + +% ------ Generic ------ % + +% Read a string at a given offset in a "file" (binary file or +% GlyphData in RAM). +/ReadString { % <pos> <string> ReadString <string> + GlyphData 0 eq { + % Read from the file. + DataSource 3 -1 roll setfileposition + DataSource exch readstring pop + } { + % Read from a string or an array of strings. + GlyphData .stringsreadstring + } ifelse +} bind def +/.stringsreadstring % <pos> <string> <strings> .stringsreadstring + % <vmstring> +{ dup type /stringtype eq + { 3 1 roll length getinterval + } + { { % Stack: pos string glyphdata + dup 0 get length dup 4 index gt { exit } if + 4 -1 roll exch sub 3 1 roll + dup length 1 sub 1 exch getinterval + } + loop + % Stack: pos string glyphdata glyphdata[0]length + % We know no request can span more than 2 strings. + 3 index 3 index length add 1 index le + { % Request fits in a single string: just return a substring. + pop 0 get 3 1 roll length getinterval + } + { % Request spans 2 strings. Copy the first part. + 1 index 0 get 4 index 3 -1 roll 1 index sub getinterval + 2 index copy + % Copy the second part. + % Stack: pos str glyphdata str1 + length exch 1 get 0 3 index length + 3 index sub getinterval 2 index 3 1 roll putinterval + exch pop + } + ifelse + } + ifelse +} bind def + +% Interpret a byte string as a (big-endian) integer. +/.cvbsi % <bytes> .cvbsi <int> +{ 0 exch { exch 8 bitshift add } forall +} bind def + +% Read an integer from binary data. +/.readint % <pos> <nbytes> .readint <int> +{ string ReadString .cvbsi +} bind def + +currentdict end + +% ---------------- Rendering ---------------- % + +% ------ CIDFontType 0 ------ % + +/.readglyphdata { + currentfont exch .type9mapcid + FDArray exch get exch +} bind def + +% BuildGlyph procedure for CIDFontType 0. +% The name %Type9BuildGlyph is known to the interpreter. +/.cid0buildstring 10 string def +(%Type9BuildGlyph) cvn { % <cidfont> <cid> %Type9BuildGlyph - + .currentglobal 3 1 roll 1 index gcheck .setglobal + 1 index begin + dup .readglyphdata dup null eq { + % Substitute CID 0. **** WRONG **** + pop pop 0 .readglyphdata + } if + % Stack: cidfont cid subfont charstring + dup null eq { pop pop pop pop } { %**** WRONG **** + 4 -1 roll pop + 3 1 roll exch dup 4 -1 roll 0 0 moveto + 3 index /FontType get 2 eq { .type2execchar } { .type1execchar } ifelse + } ifelse %**** WRONG **** + end + .setglobal +} bind def + +% ------ CIDFontType 2 ------ % + +% BuildGlyph procedure for CIDFontType 2. +% The name %Type11BuildGlyph is known to the interpreter. +(%Type11BuildGlyph) cvn { % <cidfont> <cid> %Type11BuildGlyph - + % We must be prepared for out-of-range CIDs. + 2 copy { .type11mapcid } .internalstopped { + pop /CharStrings get /.notdef get + } if + % Stack: cidfont cid glyphindex + 1 index exch .type42execchar +} bind def + +% ---------------- Define resources ---------------- % + +languagelevel exch 2 .setlanguagelevel + +% Define the CIDInit ProcSet resource. +% The ProcSet dictionary is still on the stack. + +% We might have loaded CMap support already. However, Adobe's +% protected font downloader defines a CIDInit ProcSet that will be +% loaded from the filesystem later, so we must check specifically +% for the ProcSet being defined in VM. +/CIDInit /ProcSet 2 copy resourcestatus { pop 0 eq } { false } ifelse { + pop pop findresource dup length 4 index length add dict .copydict + 4 -1 roll exch .copydict +} { + 3 -1 roll +} ifelse exch defineresource pop + +% Define the CIDFont resource category. +% We break out .buildcidfont because it appears that at least for +% Type 32 (CIDFontType 4) fonts, the font can be registered in the Font +% category with only a CIDFontType and no FontType. +/.buildcidfont { % <name> <fontdict> .buildcidfont + % <name> <cidfont> + systemdict /ProvideUnicode .knownget not { false } if { + /FontEmulationProcs /ProcSet findresource + /ProvideUnicodeDecoding get exec + } if + dup /CIDFontType get //.cidfonttypes exch get exec +} odef + +/CIDFont /Generic /Category findresource dup length dict .copydict +dup /InstanceType /dicttype put +dup /DefineResource { + .buildcidfont + dup /OrigFont known not { + dup dup /OrigFont exch .growput % CPSI does it. Adding just for CET 33_all.PS conformity. + } if + dup /PaintType known not { + dup /PaintType 0 .growput % CPSI does it. Adding just for CET 33_all.PS conformity. + } if + /Generic /Category findresource /DefineResource get exec +} put +% CIDFonts may be defined in CFF OpenType files. +% Check for this here. +/.loadcidfontresource { + dup .ResourceFile { + {.loadfont} .execasresource + } { + dup /undefinedresource signalerror + } ifelse +} bind def +dup /.LoadResource { + currentglobal { + .loadcidfontresource + } { + true setglobal {.loadcidfontresource} stopped false setglobal {stop} if + } ifelse +} bind put + +/Category defineresource pop + +% Add the new FontType resources. + +9 1 11 { dup /FontType defineresource pop } for + +% Add the new FMapType resource. + +9 dup /FMapType defineresource pop + +% Define the CIDMap resource category. +% These aren't documented, but it's clear what they are for: +% to give names to CIDMaps for CIDFontType 2 fonts. + +/CIDMap /Generic /Category findresource dup length dict .copydict +dup /.CheckResource { + % Allow a string, an array of strings, or (as of Adobe release 3011) + % a dictionary. + dup type dup dup /stringtype eq exch /dicttype eq or { + pop true + } { + dup /arraytype eq exch /packedarraytype eq or { + true exch { type /stringtype eq and } forall + } { + false + } ifelse + } ifelse +} bind put +/Category defineresource pop + +.setlanguagelevel + +%% Replace 1 (gs_ciddc.ps) +(gs_ciddc.ps) runlibfile diff --git a/gs/Resource/Init/gs_cidtt.ps b/gs/Resource/Init/gs_cidtt.ps new file mode 100644 index 000000000..0c8d8fb41 --- /dev/null +++ b/gs/Resource/Init/gs_cidtt.ps @@ -0,0 +1,141 @@ +% Copyright (C) 2000 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Redefine CIDFont category with an emulation with True Type fonts. + +languagelevel 2 .setlanguagelevel + +15 dict begin % a temporary dictionary for local binding. + +%------------------Copy the FontEmulationProcs here : ------------------- + +/FontEmulationProcs /ProcSet findresource { + def +} forall + +currentdict /super.complete_instance currentdict /complete_instance get put + +%-------Auxiliary procedures for building CIDFontType 2 from TT file ----------- + +/GenerateCIDMap % <font> GenerateCIDMap <font> +{ begin + % Obtain the maximal CID : + % This implementation doesn't check whether glyphs really present. + Decoding /CIDCount get /CIDCount exch def + % Prepare the CIDMap structure : + /CIDMap [ + CIDCount 22000 le { + CIDCount 2 mul string + } { + 44000 string + CIDCount 44000 gt { + % need three strings + 44000 string % 22000 2 mul string + CIDCount 44000 sub 2 mul string + } { + CIDCount 22000 sub 2 mul string + } ifelse + } ifelse + ] def + % Now fill it : + Decoding TT_cmap SubstNWP GDBytes CIDMap .fillCIDMap + currentdict end +} bind def + +/load_sfnts % <FontDict> load_sfnts <FontDict> +{ % Read the True Type file from the path /Path, and buld /sfnts, + % skipping glyf and loca. + dup /Path get % <font> (path) + QUIET not { + (Loading a TT font from ) print dup print + ( to emulate a CID font ) print 1 index /CIDFontName get =only ( ... ) print + } if + (r) file dup % <font> file file + 3 1 roll % file <font> file + 1 index /SubfontID .knownget not { 0 } if % file <font> file SubfontID + .load_tt_font_stripped exch copy % file <font> + QUIET not { + (Done.) = + } if + dup 3 1 roll % <font> file <font> + exch /File exch put % <font> + dup dup /CIDSystemInfo get /Ordering get (.) % <font> () () + 2 index /Decoding get =string cvs % <font> () () () + concatstrings concatstrings cvn /Decoding exch put % <font> + //ChooseDecoding exec % <font> + //GenerateCIDMap exec % <font> +} bind def + +%-----------TrueType-specific methods for category redefinition : ----------- + +/RefinePath % <FontDict> RefinePath <FontDict> +{ dup begin + Path .libfile { + dup .filename { + currentdict exch /Path exch put + } if + closefile + } { + (Can't find the font file ) print = + /findfont cvx /undefinedfilename signalerror + } ifelse + end +} bind def + +/complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict> +{ 1 index /CIDFontType 2 put % Other types are not emulated yet. + //super.complete_instance exec + //RefinePath exec + //load_sfnts exec +} bind def + +/IsMyRecord % <raw_record> -> <raw_record> bool +{ dup type /dicttype eq { dup /FileType .knownget { /TrueType eq } { false } ifelse } { false } ifelse +} bind def + +/IsActive % <record> IsActive <bool> +{ pop true +} bind def + +/CIDFontRecordVirtualMethods //RecordVirtualMethodsStub dup length 3 add dict copy begin + /GetCSI //TranslateCSI def + /IsActive //IsActive def + /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> + { currentglobal 3 1 roll true setglobal + //CIDFontOptions //complete_instance exec + 2 copy //GetSize exec + 4 3 roll setglobal + } bind def +currentdict end def + +% Redefine the /CIDFont category : +4 dict begin + /CategoryName /CIDFont def + /IsMapFileOptional true def + /VerifyMap { pop } bind def + /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> + { //IsMyRecord exec dup { + pop dup /RecordVirtualMethods //CIDFontRecordVirtualMethods put + true + } if + } bind def +currentdict end + +/MappedCategoryRedefiner /ProcSet findresource /Redefine get exec + +end % the temporary dictionary for local binding. + +.setlanguagelevel diff --git a/gs/Resource/Init/gs_ciecs2.ps b/gs/Resource/Init/gs_ciecs2.ps new file mode 100644 index 000000000..6c1756d83 --- /dev/null +++ b/gs/Resource/Init/gs_ciecs2.ps @@ -0,0 +1,147 @@ +% Copyright (C) 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Level 2 CIEBased color space method dictionaries. + +% +% The validation routines in these method dictionaries perform only +% partial validations; the .setcie* operators will perform the rest. +% + +% verify that at least one of the CIEBased color spaces is supported +true + { /.setcieaspace /.setcieabcspace /.setciedefspace /.setciedefgspace } + { + where + { pop not exit } + if + } +forall + { currentfile closefile } +if + + +.currentglobal true .setglobal +.cspace_util begin + +% +% <obj> check_cie_cspace <obj> +% +% Perform a very basic check that an object is a CIEBased color space +% array. +% +/check_cie_cspace + { + //check_array exec + dup 1 get type /dicttype ne + //setcspace_typecheck + if + } +bind def + + + +/.setcieaspace where + { + pop + colorspacedict + /CIEBasedA + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_1 + + /cs_get_range + { + 1 get /RangeA .knownget not + { //dflt_range_1 } + if + } + bind + + /cs_get_default_color { pop 0 } bind + /cs_get_currentgray //no_currentgray + /cs_get_currentrgb //no_currentrgb + /cs_get_currentcmyk //no_currentcmyk + /cs_validate //check_cie_cspace + /cs_substitute //dup_1 + /cs_prepare {} + + /cs_install + { + NOCIE + { pop /DeviceGray //.cs_install exec } + { 1 get .setcieaspace } + ifelse + } + bind + + /cs_prepare_color //validate_1 + /cs_complete_setcolor //pop_1 + .dicttomark + put + } +if + +/.setcieabcspace where + { + pop + colorspacedict + /CIEBasedABC + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_3 + + /cs_get_range + { + 1 get /RangeABC .knownget not + { //dflt_range_3 } + if + } + bind + + /cs_get_default_color { pop 0 0 0 } bind + /cs_get_currentgray //no_currentgray + /cs_get_currentrgb //no_currentrgb + /cs_get_currentcmyk //no_currentcmyk + /cs_validate //check_cie_cspace + /cs_substitute //dup_1 + /cs_prepare {} + + /cs_install + { + NOCIE + { pop /DeviceRGB //.cs_install exec } + { 1 get .setcieabcspace } + ifelse + } + bind + + /cs_prepare_color //validate_3 + /cs_complete_setcolor //pop_1 + .dicttomark + put + } +if + + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_ciecs3.ps b/gs/Resource/Init/gs_ciecs3.ps new file mode 100644 index 000000000..f713825e5 --- /dev/null +++ b/gs/Resource/Init/gs_ciecs3.ps @@ -0,0 +1,137 @@ +% Copyright (C) 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Level 3 CIEBased color space method dictionaries. +% This assumes gs_ciecs2.ps has already been processed. + +% +% The validation routines in these method dictionaries perform only +% partial validations; the .setcie* operators will perform the rest. +% + + +.currentglobal true .setglobal +.cspace_util begin + + +/.setciedefspace where + { + pop + colorspacedict + /CIEBasedDEF + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_3 + + /cs_get_range + { + 1 get /RangeDEF .knownget not + { //dflt_range_3 } + if + } + bind + + % per Page 233 of the PLRM, default color should be as close to 0.0 as possible + % within the RangeDEF + /cs_get_default_color { 1 get /RangeDEF .knownget { + aload pop pop 5 1 roll pop 4 1 roll pop 3 1 roll + } { + 0.0 0.0 0.0 + } ifelse + } bind + /cs_get_currentgray //no_currentgray + /cs_get_currentrgb //no_currentrgb + /cs_get_currentcmyk //no_currentcmyk + /cs_validate //check_cie_cspace + /cs_substitute //dup_1 + /cs_prepare {} + + /cs_install + { + NOCIE + { pop /DeviceRGB //.cs_install exec } + { 1 get .setciedefspace } + ifelse + } + bind + + /cs_prepare_color //validate_3 + /cs_complete_setcolor //pop_1 + .dicttomark + put + } +if + + +/.setciedefgspace where + { + pop + colorspacedict + /CIEBasedDEFG + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_4 + + /cs_get_range + { + 1 get /RangeDEFG .knownget not + { //dflt_range_4 } + if + } + bind + + % per Page 233 of the PLRM, default color should be as close to 0.0 as possible + % within the RangeDEFG + /cs_get_default_color { 1 get /RangeDEFG .knownget { + aload pop pop 7 1 roll pop 6 1 roll pop 5 1 roll pop 4 1 roll + } { + 0.0 0.0 0.0 0.0 + } ifelse + } bind + /cs_get_currentgray //no_currentgray + /cs_get_currentrgb //no_currentrgb + /cs_get_currentcmyk //no_currentcmyk + /cs_validate //check_cie_cspace + /cs_substitute //dup_1 + /cs_prepare {} + + % the use of the DeviceCMYK color space is questionable: + % it will likely have the wrong polarity + /cs_install + { + NOCIE + { pop /DeviceCMYK //.cs_install exec } + { 1 get .setciedefgspace } + ifelse + } + bind + + /cs_prepare_color //validate_4 + /cs_complete_setcolor //pop_1 + .dicttomark + put + } +if + + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_cmap.ps b/gs/Resource/Init/gs_cmap.ps new file mode 100644 index 000000000..1a6e68823 --- /dev/null +++ b/gs/Resource/Init/gs_cmap.ps @@ -0,0 +1,549 @@ +% Copyright (C) 1995, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% ProcSet for implementing CMap resources. +% When this is run, systemdict is still writable. + +% NOTE: Rearranged fonts are not implemented yet. + +[ + /CMERGE_DEBUG + /USE_CIDCHAR_AS_RANGE +] {dup where {pop pop} { currentdict exch //false def pop } ifelse} forall + +% ---------------- Public operators ---------------- % + +/.rewriteTempMapsNotDef { + % + % Before building .CodeMapData from .TempMaps, + % we need to replace dst type codes in the notdef map with the value 3, + % which corresponds to CODE_VALUE_NOTDEF, see gxfcmap.h . + % + CMAPDEBUG { (rewriting TempMapsNotDef\n) print flush } if + .TempMaps 2 get + dup length 0 gt { + 0 get + CMAPDEBUG { (...original...\n) print flush } if + 1 5 2 index length 1 sub { + { 1 index exch get 2 3 put } stopped + { CMAPDEBUG { (cannot rewrite\n) print flush } if } + { CMAPDEBUG { (rewrite\n) print flush } if } ifelse + } for + } if + pop + CMAPDEBUG { (...FINISHED...\n) print } if +} bind def + +/.composefontdict { % <name> <cmap|cmapname> <fonts> composefont <name> <font_dict> + 10 dict begin + /CMap 2 index dup type /dicttype ne { /CMap findresource } if def + /FDepVector 1 index cvlit def % temporarily + /Encoding [ 0 1 FDepVector length 1 sub { } for ] def + /FontInfo 1 dict def % for .processToUnicode in pdf_font.ps . + /FDepVector [ 0 1 FDepVector length 1 sub { + % Stack: name cmap[name] fonts /FDepVector [ fonts... i + FDepVector 1 index get + dup type /dicttype ne { + dup /CIDFont resourcestatus { + pop pop /CIDFont + } { + /Font + } ifelse findresource + } if + exch CMap /FontMatrices get dup length 2 index gt { + exch get dup //null eq { pop } { makefont } ifelse + } { + pop pop + } ifelse + } for ] readonly def + /FMapType 9 def + /FontMatrix matrix def + /FontName 3 index def + CMap /WMode .knownget { /WMode exch def } if + /FontType 0 def + pop pop currentdict end +} bind odef + +% composefont doesn't appear in CMap files -- it's documented in +% the "PostScript Language Reference Manual Supplement". +/composefont { % <name> <cmap|cmapname> <fonts> composefont <font> + .composefontdict /Font defineresource +} bind def + +% ---------------- CMap operators ---------------- % + +40 dict begin + +% Our internal .CodeMapData structure closely mirrors the structures +% defined in gxfcmap.h (q.v.). () indicate a string, [] indicate an array, +% ? indicates a Boolean, # indicates an integer, {} for grouping. +% [[[(first) (last) ...]+] % code space ranges +% [[(prefix) (key_size,?is_range,value_type,value_size) (keys...) +% {(values...) | [value ...]} #font_index ]+] % code mappings +% ...] +% <<same>> % notdef mappings +% ] +% FontMatrices is the array of matrices defined by begin/endusematrix. +% All of the arrays and strings are read-only after they have been built. +% +% Note that the code in zfcmap.c that constructs the C structures from +% the PostScript structures has intimate knowledge of the above format. + +% ****** NOTE: The code currently only handles "well-behaved" CMaps: +% - CID values only (no bfchars), 16-bit +% - Entries (both code space and map) must be sorted +% - Only the last byte must vary in each map range, except for +% the identity mapping + +% ------ Font-level operators ------ % + +/begincmap { % - begincmap - + /.CodeMapData [[[]] [[]] [[]]] def + /FontMatrices [] def + /.FontIndex 0 def + /.TempMaps [20 dict 50 dict 50 dict] def + /CodeMap //null def % for .buildcmap +} bind def + +/endcmap { % - endcmap - + .rewriteTempMapsNotDef + + CMAPDEBUG { + 2 (*** undefined charmap ***) + 1 (*** defined charmap ***) + 0 (*** code space ranges ***) + 3 { = + .TempMaps exch get + 0 1 2 index length 1 sub { + dup == (\t) print + 1 index exch get == + } for + pop + } repeat + } if + + /.CodeMapData dup load [ exch + .TempMaps aload pop begin begin begin + { + [ exch aload pop + 0 1 currentdict length 1 sub { + currentdict exch get + } for + ] + end + } forall + ] .endmap def + + CMAPDEBUG { + (*** Content of .CodeMapData ***) = + 0 .CodeMapData { exch dup == 1 add exch (\t) print == } forall + pop + } if + + currentdict /.TempMaps undef + /FontMatrices FontMatrices .endmap def +} bind def + +/.endmap { % <map> .endmap <map> + dup type /arraytype eq { + % This might be a shared read-only array inherited via usecmap. + % Don't try to update its elements if this is the case. + dup wcheck { + 0 1 2 index length 1 sub { + 2 copy 2 copy get .endmap put pop + } for readonly + } if + } { + dup type /stringtype eq { readonly } if + } ifelse +} bind def + +/.appendmap { % -mark- <elt> ... <array#> .appendmap - + .TempMaps exch get counttomark 1 add 1 roll + ] 1 index length exch put +} bind def + +/begincodespacerange { % <count> begincodespacerange - + pop mark +} bind def + +/endcodespacerange { % <code_lo> <code_hi> ... endcodespacerange - + 0 .appendmap +} bind def + +/usecmap { % <CMap_name> usecmap - + /CMap findresource dup + % Copy the top level of .CodeMapData + /.CodeMapData exch /.CodeMapData get copyarray def + /FontMatrices exch /FontMatrices get copyarray def +} bind def + +/usefont { % <fontID> usefont - + /.FontIndex exch def +} bind def + +/beginusematrix { % <fontID> beginusematrix - + FontMatrices wcheck not FontMatrices length 2 index le or { + FontMatrices length 1 index 1 add .max array + dup 0 FontMatrices putinterval + /FontMatrices exch def + } if +} bind def + +/endusematrix { % <matrix> endusematrix - + FontMatrices 3 1 roll put +} bind def + +% ------ Rearranged font operators ------ % + +/beginrearrangedfont { % <font_name> <font*> beginrearrangedfont - + 10 dict begin + /.FontNames exch def + /.FontName exch def + begincmap +} bind def +/endrearrangedfont { % - endrearrangedfont - + (REARRANGED FONTS NOT IMPLEMENTED YET.) = flush + FontName .FontNames 0 get findfont end definefont pop +} bind def + +% ------ Character name/code selector operators ------ % + +/beginbfchar { % <count> beginbfchar - + pop mark +} bind def +/endbfchar { % <code> <to_code|charname> ... endbfchar + counttomark 2 idiv { + counttomark -2 roll % process in correct order + .addbfchar + } repeat 1 .appendmap +} bind def + +/beginbfrange { % <count> beginbfrange - + pop mark +} bind def +/endbfrange { % <code_lo> <code_hi> <to_code|(charname*)> ... + % endbfrange - + counttomark 3 idiv { + counttomark -3 roll % process in correct order + dup type dup /arraytype eq exch /packedarraytype eq or { + % Array value, split up. + exch pop { + % Stack: code to_code|charname + 1 index exch .addbfchar + % Increment the code. As noted above, we require + % that only the last byte vary, but we still must + % mask it after incrementing, in case the last + % value was 0xff. + % Stack: code prefix params key value fontindex + 6 -1 roll dup length string copy + dup dup length 1 sub 2 copy get 1 add 255 and put + } forall pop + } { + % Single value, handle directly. + .addbfrange + } ifelse + } repeat 1 .appendmap +} bind def + +/.addbfchar { % <code> <to_code|charname> .addbfchar + % <prefix> <params> <key> <value> <font_index> + 1 index exch .addbfrange +} bind def +/.addbfrange { % <code_lo> <code_hi> <to_code|charname> + % .addbfrange <<same as .addbfchar>> + 4 string dup 3 + 3 index type /nametype eq { + 2 index 2 1 put % dst = CODE_VALUE_GLYPH, see gxfcmap.h . + 4 -1 roll 1 array astore 4 1 roll 4 + } { + 2 index 2 2 put % dst = CODE_VALUE_CHARS, see gxfcmap.h . + 3 index length + } ifelse put + % Stack: code_lo code_hi value params + 3 index 3 index eq { + % Single value. + 3 -1 roll pop exch () exch + } { + % Range. + dup 0 1 put dup 1 1 put + 4 2 roll + dup dup length 1 sub 0 exch getinterval 5 1 roll % prefix + % Stack: prefix value params code_lo code_hi + 2 { exch dup length 1 sub 1 getinterval } repeat concatstrings + 3 -1 roll + } ifelse + .FontIndex +} bind def + +% ------ CID selector operators ------ % + +/begincidchar { % <count> begincidchar - + pop mark +} bind def +/endcidchar { % <code> <cid> ... endcidchar - + 1 .endmapchars +} bind def + +/begincidrange { % <count> begincidrange - + pop mark +} bind def +/endcidrange { % <code_lo> <code_hi> <cid_base> ... endcidrange - + 1 .endmapranges +} bind def + +/.endmapchars { % -mark- <code> <cid> ... <map#> .endmapchars - + counttomark 1 add 1 roll + counttomark 2 idiv { + counttomark -2 roll % process in correct order + exch % <cid> <code> + % Construct prefix, params, key, value, font_index + dup length 1 eq { % 1-byte + <00 00 00 02> () % <prefix> <param> <null_key> + } { % N-byte + dup 0 1 getinterval exch % make 1-byte prefix + 4 string dup 0 + USE_CIDCHAR_AS_RANGE { + <00 01 00 02> % skelton for param + } { + <00 00 00 02> % skelton for param + } ifelse + putinterval + exch % <prefix> <param> <code> + dup length % <prefix> <param> <code> N + 1 sub % <prefix> <param> <code> N-1 + dup % <prefix> <param> <code> N-1 N-1 + 3 index % <prefix> <param> <code> N-1 N-1 <param> + exch % <prefix> <param> <code> N-1 <param> N-1 + 0 exch % <prefix> <param> <code> N-1 <param> 0 N-1 + put % <prefix> <param'> <code> N-1 + 1 exch % <prefix> <param'> <code> 1 N-1 + getinterval % <prefix> <param'> <key> + + USE_CIDCHAR_AS_RANGE { + dup length 2 mul string % <key> <dkey> + dup % <key> <dkey> <dkey> + 2 index % <key> <dkey> <dkey> <key> + 0 exch putinterval % <key> <dkey'> + dup % <key> <dkey'> <dkey'> + 3 -1 roll % <dkey'> <dkey'> <key> + dup length % <dkey'> <dkey'> <key> N-1 + exch putinterval % <dkey''> + } if + + } ifelse + + 4 -1 roll % <prefix> <param'> <key> <cid> + .endmapvalue % <prefix> <param'> <key> <hex_cid> <font_idx> + % prefix params keys value fontindex + counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item) + 4 index 10 index eq % compare prefix + 4 index 10 index eq and % compare params + 1 index 7 index eq and % compare fontindex + { + CMAPDEBUG { (merge! char\n) print } if + pop 4 2 roll pop pop + % prefix params keys value fontindex keys2 value2 + 5 -1 roll 3 -1 roll concatstrings + % prefix params value fontindex value2 keys' + 4 -1 roll 3 -1 roll concatstrings + % prefix params fontindex keys' values' + 3 -1 roll + } if + } if % end of 2 (or more) ranges + CMERGE_DEBUG { + ( prefix:) print 4 index =only + ( param:) print 3 index =only + ( key:) print 2 index =only + ( hex_cid:) print 1 index =only + ( font_idx:) print 0 index == flush + } if + } repeat + counttomark 2 add -1 roll .appendmap +} bind def + +/.endmapranges { % -mark- <code_lo> <code_hi> <cid_base> ... <map#> + % .endmapranges - + counttomark 1 add 1 roll + counttomark 3 idiv { + counttomark -3 roll % process in correct order + % Construct prefix, params, key_lo, key_hi, value, font_index + 3 1 roll % <cid_base> <code_lo> <code_hi> + % prefix key + % 1-byte code: () . + % 1-byte range: () . + % N-byte code: . (*) + % N-byte range: (*) (*) + dup 2 index eq { % <code_lo> == <code_hi> + % 0: prefix_len for 1-byte code + % 1: prefix_len for N-byte code + dup length 1 eq { 0 } { 1 } ifelse + } { % <code_lo> != <code_hi> + % calculate prefix_len for *-byte range + dup length 1 sub % <cid_base> <code_lo> <code_hi> <code_len-1> + 0 % initial value for N + { % <cid_base> <code_lo> <code_hi> (code_len-1) N + dup 2 index ge { exit } if % if (N >= len - 1) exit + 3 index 1 index get % N-th byte of code_lo + 3 index 2 index get % N-th byte of code_hi + eq { 1 add } { exit } ifelse + } loop + exch pop % discard <code_len-1> + } ifelse + % cid_base code_lo code_hi prefix_len + + % Althogh Adobe CPSI with native CID/CMap support accept + % multi-dimensional range specification in notdef & cidrange + % (and CID is calculated as relative position in multi-dimensional + % range), but older CPSI & ATM cannot handle it. + % + % GS accepts such specification, but it's recommended to keep + % from using this feature for notdef & cidrange. + % Following is a disabler of this feature. + % ------------------------------------------------------------- + % counttomark 1 add index % get map# + % 0 ne { % if not codespacerange + % 1 index length % get code length + % 1 index % get prefix length + % sub % calculate key length + % 1 gt { % if (key_len > 1), + % (.endmapranges error) = flush + % (multi-dimensional range specification is used out of codespacerange) + % = flush + % (/) =only + % CMapName CMapName length string cvs =only + % (: <) =only + % 2 index (%stdout) (w) file exch writehexstring + % (> <) =only + % 1 index (%stdout) (w) file exch writehexstring + % (>\n) =only flush + % quit + % } if + % } if + % ------------------------------------------------------------- + + 1 index exch 0 exch getinterval + % cid_base code_lo code_hi prefix + dup length 3 index length exch sub + % cid_base code_lo code_hi prefix range_len + dup 255 gt { + (too long coderange specification for current GS\n) print + /.endmapranges cvx /rangecheck signalerror + } if + <00 01 00 02> 4 string copy % create initialized param + dup 0 4 -1 roll put % put range_len into param + + % get key_hi + 3 -1 roll dup length 3 index length dup 3 1 roll sub getinterval + + % get key_lo + 4 -1 roll dup length 4 index length dup 3 1 roll sub getinterval + + % make "keys" (concatenated key_lo + key_hi) + exch concatstrings + + % + 4 -1 roll + .endmapvalue + + % See if we can merge with the previous value. + % The prefix, params, and font index must match. + % prefix params keys value fontindex + counttomark 5 gt { % 2 (or more) ranges (1 range = 5 item) + 4 index 10 index eq % compare prefix + 4 index 10 index eq and % compare params + 1 index 7 index eq and % compare fontindex + { + CMAPDEBUG { (merge!\n) print } if + pop 4 2 roll pop pop + % prefix params keys value fontindex keys2 value2 + 5 -1 roll 3 -1 roll concatstrings + % prefix params value fontindex value2 keys' + 4 -1 roll 3 -1 roll concatstrings + % prefix params fontindex keys' values' + 3 -1 roll + } if + } if % end of 2 (or more) ranges + } repeat + counttomark 2 add -1 roll .appendmap +} bind def + +/.endmapvalue { % <cid> .endmapvalue (hi,lo) .FontIndex + 2 string dup 0 3 index -8 bitshift put % value + dup 1 4 -1 roll 255 and put + .FontIndex % font_index +} bind def + +% ------ notdef operators ------ % + +/beginnotdefchar { % <count> beginnotdefchar - + pop mark +} bind def +/endnotdefchar { % <code> <cid> ... endnotdefchar - + 2 .endmapchars +} bind def + +/beginnotdefrange { % <count> beginnotdefrange - + pop mark +} bind def +/endnotdefrange { % <code_lo> <code_hi> <cid> ... endnotdefrange - + 2 .endmapranges +} bind def + +% ---------------- Resource category definition ---------------- % + +currentdict end + +languagelevel exch 2 .setlanguagelevel + +/CMap /Generic /Category findresource dup length dict .copydict +dup /InstanceType /dicttype put +dup /DefineResource { + % The AdobePS5 Windows driver emits code that attempts to + % create CMaps without the required CMapName entry. + % Work around this here. + dup /CMapName known not { + dup wcheck not { + .currentglobal exch dup wcheck .setglobal + dup length dict .copydict exch .setglobal + } if + dup gcheck 2 index gcheck not and { + exch .currentglobal exch //true .setglobal + dup length string copy exch .setglobal exch + } if dup /CMapName 3 index put + } if + % Adobe PS CET 23-25 and others define an almost empty CMap. Tolerate this. + % With the above, we can actually tolerate: /name << >> defineresource + dup /CIDSystemInfo known not { + dup wcheck not { + .currentglobal exch dup wcheck .setglobal + dup length dict .copydict exch .setglobal + } if + dup /CIDSystemInfo [ //null ] put + } if + dup /CodeMap .knownget { //null eq { .buildcmap } if } if + /Generic /Category findresource /DefineResource get exec +} bind put +/Category defineresource pop + % We might have loaded CID font support already. +/CIDInit /ProcSet 2 copy { findresource } .internalstopped + % An interior `stopped' might have reset VM allocation to local. +//true .setglobal + { pop pop 3 -1 roll } + { dup length 4 index length add dict .copydict 4 -1 roll exch .copydict } +ifelse exch defineresource pop + +.setlanguagelevel diff --git a/gs/Resource/Init/gs_cspace.ps b/gs/Resource/Init/gs_cspace.ps new file mode 100644 index 000000000..8199f3389 --- /dev/null +++ b/gs/Resource/Init/gs_cspace.ps @@ -0,0 +1,1022 @@ +% Copyright (C) 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% basic colorspace mechanism + +% +% This new implementation of color spaces extends the color space +% formalism to all PostScript levels. Level specific features and +% operators continue to be accessible only in the appropriate level, +% but the colorspace concept and associated mechanisms are used +% throughout. +% +% The color space mechanism is built around two dictionaries: +% +% .cspace_util +% A dictionary in global VM that is accessible in userdict only +% during initialization. This dictionary is intended for various +% utility procedures that are used in implementing the individual +% color spaces. +% +% colorspacedict +% A dictionary of methods for each color space type. The keys +% in this dictionary are color space type names (e.g.: /DeviceGray, +% /Separation, etc.), and the values are dictionaries of methods. +% The set of methods is the same for each color space type, and +% provides a complete implementation for the corresponding color +% space type. This dictionary is in global VM. +% +% The information specific to a color space type is created in a file +% for that type or group of types (e.g.: gs_csdev.ps, gs_csindx.ps, +% etc.). These files will generally adhere to the template: +% +% .currentglobal true .setglobal +% <level-specific dictionary> begin +% ... +% .cspace_util begin +% colorspacedict +% /<color space type name> +% mark +% /cs_validate +% { +% ... +% } +% bind +% ... +% .dicttomark +% put +% end % .cspace_util +% end ... % level-specific dictionary +% .setglobal +% +% The methods associated with a color space are listed below (along with +% their stack handling), followed by descriptions. +% +% - cs_potential_indexed_base <bool> +% +% - cs_potential_pattern_base <bool> +% +% - cs_potential_alternate <bool> +% +% - cs_potential_icc_alternate <bool> +% +% +% <name | array> cs_get_ncomps <int> +% +% <name | array> cs_get_range <range_array> +% +% <name | array> cs_get_default_color <c1> ... <cn> +% +% +% <c1> ... <cn> <name | array> cs_get_currentgray <gray> +% +% <c1> ... <cn> <name | array> cs_get_currentrgb <red> <green> <blue> +% +% <c1> ... <cn> <name | array> cs_get_currentcmyk +% <cyan> <magenta> <yellow> <black> +% +% +% <name | array> cs_validate <name | array> +% +% <name1 | array1> cs_substitute <name1 | array1> <array2> +% +% <name1 | array1> <array2> cs_prepare <name1 | array1> <array2> +% +% <name | array> cs_install - +% +% +% <c1> ... <cn> <array> cs_verify_color <c1> ... <cn> +% +% <array> cs_complete_color - +% +% +% cs_potential_indexed_base, cs_potential_pattern_base, +% cs_potential_alternate, cs_potential_icc_alternate +% These are booleans rather than procedures. They indicate if the color +% space can be a base space of an Indexed color space (anything except +% Indexed and Pattern), a Pattern color space (anything except Pattern), +% the alternative color space of a Separation or DeviceN color space, or +% the alternative color space of an ICCBased color space. The two +% parameters are distinct only because of a Ghostscript-specific +% implementation problem; in principle, there is nothing special about +% ICCBased color spaces in this regard. +% +% cs_get_ncomps +% Return the number of color components for the color spaces. For Pattern +% color spaces, the value is -1 if there is no base space, or -(n + 1) if +% the base space has n components. +% +% cs_get_range +% Return the input Range array appropriate for this color space. This is +% defined for all color spaces, though it is of interest primarily for +% CIEBased and ICCBased color spaces. For Indexed color spaces this is +% [ 0 hival ], where hival is the maximum support index value. For all +% other non-CIEBased, non-ICCBased color spaces, the range is an array +% of ncomps elements, all of which are [ 0 1 ], where ncomps is the +% number of color space components. +% +% cs_get_default_color +% Generates the default color for the current color space. Under normal +% circumstances this is done internally. It is provided in PostScript +% only to support an optimization that doesn't change the current color +% space more often than necessary. +% +% cs_get_currentgray, cs_get_currentrgb, cs_get_currentcmyk +% These procedures are used to implement the currentgray, currentrgb, +% and currentcmyk operators (which are pseudo-operators in the current +% implementation). +% +% cs_validate +% Validate the operand color space. Because color spaces are extensively +% manipulated in PostScript in this implementation, error handling can +% become burdensome. To make the code somewhat simpler, it is useful to +% be able to validate a color space prior to manipulation, so as to +% ensure that errors are not discovered in awkward places. +% +% cs_substitute +% Substitute a device-independent color space for device specific color +% space. This applies directly to the device-specific color spaces +% (DeviceGray, DeviceRGB, DeviceCMYK), and indirectly when these color +% spaces are used as base/alternative color spaces. The mechanism for +% color substitution is included in all language levels, though it may +% only be accessed for Language Level 3. +% +% The substituted color space is the topmost of the operands pushed. +% this may or may not be the same as the original color space, which +% is immediately below it on the operand stack. If the two differ, +% the substituted space will always be in local VM (and will be +% writable). +% +% Substitution is applied recursively to the base/alternate color +% space of ICCBased, Indexed, Separation, DeviceN, or Pattern +% color spaces. Because Ghostscript currently requires that any +% base or alternative color space be the current color space when +% the enclosing color space is set, this substitution effectively +% occurs twice: once in the original color space, and once when the +% base/alternative color space is made the current color space. +% We retain the first substitution as we would eventually like to +% remove the restriction on making the base/alternative color space +% the current color space. +% +% cs_prepare +% Perform any operations required on the color space for installation. +% This method exists primarily to allow conversion of PostScript +% procedures to functions for CIEBased color spaces. Two operands are +% provided: the original and the substituted color space. If the two +% differ and the latter is writable, required modifications can +% be made "in place". Otherwise, a new instance of the second color +% space must be built. +% +% Currently, cs_prepare is not explicitly recursive. Because +% Ghostscript requires a base/alternate color space to be installed +% as the current color space prior to installing the enclosing color +% space, the cs_prepare method will implicitly be called recursively. +% The reason for not making this explicit is that color space +% preparation may involve a considerable amount of work, which could +% be avoided if, for example, an alternative color space will not +% be used because the enclosing Separation/DeviceN color space is +% supported in native mode by the process color model. We would +% eventually like to remove the need to prepare color spaces that +% will not be used. +% +% cs_install +% This method actually installs the color space in the graphic state. +% Only the substituted/prepared space (which may be the same as the +% original space) is passed as an operand; the original space is handled +% directly by the .setcolorspace operator. +% +% The provision of a separate method for this tasks reflects the +% historical implementation of color spaces in the Ghostscript +% interpreter. This implementation provides a unique operator for each +% color space type. +% +% cs_prepare_color +% Modify a set of color operands as required by a color space. This +% is used primarily to verify the color operands, as this is most +% conveniently done in PostScript. +% +% cs_complete_setcolor +% This method is invoked immediately after a (successful) invocation +% of setcolor. Ii is provided as a separate method for compatibility +% with Adobe implementations. These implementations invoke the lookup +% (Indexed) or tint procedure each time setcolor is invoked (only if +% the alternative color space is used in the case of the tint +% transform). Because Ghostscript may convert these procedures to +% functions (or pre-sample them), the procedures may not always be +% called when expected. There are applications that depend on this +% behavior (e.g.: Adobe PhotoShop 5+), so this method provides a way +% to emulate it. +% +% In principle, a cs_complete_setcolor procedure for an Indexed color +% space whose base space should invoke cs_complete_setcolor on its +% base space. Currently we don't do this, because it has not been +% shown to be necessary. It would be simple to add if it is every +% needed. +% +% All of these methods are procedures. +% +% For each of these methods, there is a procedure in .cspace_util with +% a dot ('.') prefix that will invoke the appropriate procedure for the +% operand array. +% + +.currentglobal true .setglobal +userdict /.cspace_util 80 dict put +.cspace_util begin + + +% Global, read-only, unpacked, array-form device color spaces +% +/DeviceGray_array /DeviceGray 1 array astore readonly def +/DeviceRGB_array /DeviceRGB 1 array astore readonly def +/DeviceCMYK_array /DeviceCMYK 1 array astore readonly def + +% +% Colorspacedict is initially in .cspace_util; it is copied to level2dict +% in the Level 2 initialization code to retain compatibility with +% earlier implementations. +% +/colorspacedict 20 dict def + + +% +% <obj> make_array1 <array> +% +% procedure for conditionally converting a named color space to a +% 1-element array. Since names are always global, the array will be +% as well. +% +/make_array1 + { + dup type /nametype eq + { currentglobal true setglobal exch 1 array astore exch setglobal } + if + } +bind def + +% +% <name|array> .get_cspace_type name +% +% Provide generic routine for retrieving the color space type. +% +/.get_cspace_type + { + dup type dup /arraytype eq exch /packedarraytype eq or + { 0 get } + if + } +bind def + +% +% <name|array> .get_method_dict <dict> +% +% Get the method dictionary for a specific color space. Note that the +% color space is left on the stack. +% +/.get_method_dict + { //colorspacedict exch //.get_cspace_type exec get } +bind def + +% +% <name|array> <proc_name> .get_method <name|array> <proc | bool> +% +% Get the named method for the operand color space. +% +/.get_method + { exch //.get_method_dict exec exch get } +bind def + + +% +% <name_array> .cs_potential_indexed_base <bool> +% <name_array> .cs_potential_pattern_base <bool> +% <name_array> .cs_potential_alternate <bool> +% <name_array> .cs_potential_icc_alternate <bool> +% <name | array> .cs_get_ncomps <int> +% <name | array> .cs_get_range <range_array> +% <name | array> .cs_get_default_color <c1> ... <cn> +% <c1> ... <cn> <name | array> .cs_get_currentgray <gray> +% <c1> ... <cn> <name | array> .cs_get_currentrgb <r> <g> <b> +% <c1> ... <cn> <name | array> .cs_get_currentcmyk <c> <m> <y> <k> +% <name | array> .cs_validate <name | array> +% <name1 | array1> .cs_substitute <name1 | array1> <array2> +% <name1 | array1> <array2> .cs_prepare <name1 | array1> <array2> +% <name | array> .cs_install - +% <c1> ... <cn> <array> .cs_prepare_color <c1> ... <cn> +% <array> .cs_complete_setcolor - +% +% These procedures provide access to the corresponding methods of the +% operand color space. +% +/.cs_potential_indexed_base + { /cs_potential_indexed_base //.get_method exec } +bind def + +/.cs_potential_pattern_base + { /cs_potential_pattern_base //.get_method exec } +bind def + +/.cs_potential_alternate + { /cs_potential_alternate //.get_method exec } +bind def + +/.cs_potential_icc_alternate + { /cs_potential_icc_alternate //.get_method exec } +bind def + +/.cs_get_ncomps + { dup /cs_get_ncomps //.get_method exec exec } +bind def + +/.cs_get_range + { dup /cs_get_range //.get_method exec exec } +bind def + +/.cs_get_default_color + { dup /cs_get_default_color //.get_method exec exec } +bind def + +/.cs_get_currentgray + { dup /cs_get_currentgray //.get_method exec exec } +bind def + +/.cs_get_currentrgb + { dup /cs_get_currentrgb //.get_method exec exec } +bind def + +/.cs_get_currentcmyk + { dup /cs_get_currentcmyk //.get_method exec exec } +bind def + +/.cs_validate + { dup /cs_validate //.get_method exec exec } +bind def + +/.cs_substitute + { dup /cs_substitute //.get_method exec exec } +bind def + +/.cs_prepare + { dup /cs_prepare //.get_method exec exec } +bind def + +/.cs_install + { dup /cs_install //.get_method exec exec } +bind def + +/.cs_prepare_color + { dup /cs_prepare_color //.get_method exec exec } +bind def + +/.cs_complete_setcolor + { dup /cs_complete_setcolor //.get_method exec exec } +bind def + + +% +% Make sure we have an interpreter color space before redefining +% setcolorspace. The interpreter internal code only sets the effective +% color space; the interpreters color spaces begins as a null object. +% +% NB: This should come prior to the redefinition of setcolorspace, and +% must use an array operand. +% +//DeviceGray_array setcolorspace + +% +% <c1> ... <cn> setcolor - +% +% As with setcolorspace, setcolor is initially placed in .cspace_util, +% and is copied to level2dict by the Level 2 initialization code. The +% internal definition of setcolor is removed from systemdict as soon +% as this procedure is defined. +% +/setcolor + { + { + currentcolorspace //.cs_prepare_color exec //setcolor + currentcolorspace //.cs_complete_setcolor exec + } + stopped + { //.cspace_util /setcolor get $error /errorname get signalerror } + if + } +bind odef + +systemdict /setcolor .undef + + +% +% <name|array> <bool> _setcolorspace - +% <name|array> _setcolorspace_nosub - +% +% <name|array> setcolorspace - +% <name|array> forcesetcolorspace - +% +% setcolorspace is initially placed in .cspace_util. It is copied to +% level2dict by the Level 2 initialization code. The internal +% setcolorspace operator is removed from systemdict as soon as this +% procedure is defined. +% +% Because some jobs, in particular PDF jobs, repeatedly set the same +% color space, this procedure will check if the operand and current +% color spaces are the same. The check is absolute for parameterless +% color spaces, conservative for others. For PostScript, this +% optimization can only be employed if color space substitution is +% disabled, as otherwise there is no way to account for possible changes +% in the /Default* instances of the ColorSpace resource category. For PDF +% jobs, resource category instances can only be changed at very specific +% times (typically page boundaries), so the "operand color space is the +% same as current color space" optimization may be used even if color +% space substitution is in effect. The optimization is also highly +% desirable in such cases, as it greatly improves performance. +% +% In certain situations, it is critical that a color space be set, +% even if it is the same as the current color space. This is the case +% when a CIEBased color space is used as a base or alternative color +% space, due to some long-standing problems with the graphics libraries +% handling of sampled information from the procedures in CIE color +% spaces and the color rendering dictionary. The forcesetcolorspace +% operator is provided for those situations. +% +% Note also that, if the current color space is not reset, at least +% the current color must be reset to its default value. +% +% Another problem arises in the case of ICCBased color spaces. These +% color spaces may be used to substitute for a DeviceGray/DeviceRGB/ +% DeviceCMYK color space, and may themselves require such a color +% space as an alternate. Obviously, when this is the case the normal +% setcolorspace mechanism would encounter and infinite loop if the +% alternate colro space needed to be used. For this particular case, +% the special _setcolorspace_nosub is provided, which suppresses +% color space substitution. This routine does not bother to check if +% the operand and current color space are the same. +% +/_setcolorspace + { + { % Early validation the argument. The code below fails in unpredictable ways + % when it is exposed to the garbage. + 1 index + dup type dup /arraytype eq exch /packedarraytype eq or { 0 get } if + dup type /nametype ne { + //.cspace_util /setcolorspace get /typecheck signalerror + } if + //colorspacedict exch known not { + //.cspace_util /setcolorspace get /undefined signalerror + } if + + % See if the operand space is the same as the current space. + % The test is intentionaly conservative to meet CET 09-06. + 1 index % [/new] bool [/new] + type /nametype eq + { currentcolorspace 0 get % [/new] bool /old + 2 index eq % [/new] bool bool + } + { currentcolorspace % [/new] bool [/old] + 2 index eq % [/new] bool eq + } + ifelse + and dup + { + % + % If PDFfile is defined on the dictionary stack, this is a + % PDF job. No additional check is required in this case (see + % comment above). + % + /PDFfile where + { pop } + { .getuseciecolor not and } % check that UseCIEColor is off + ifelse + } + if + { + % Some versions of PhotoShop generate documents + % that place an extra value on the operand stack + % and tintTransform replaces it - see bug 549307 + % for details. Also see the test case of bug 689263. + % Here we use mark...cleartomark to restore the stack + % to its normal state. + mark + true % An extra value for bogus Adobe tintTransform + 3 -1 roll + //.cs_get_default_color exec setcolor + cleartomark + } + { + //.cs_validate exec + //.cs_substitute exec + //.cs_prepare exec + //.cs_install exec + dup //make_array1 exec //setcolorspace + mark %See comments above + true + 3 -1 roll + //.cs_get_default_color exec setcolor + cleartomark + } + ifelse + } + stopped + { //.cspace_util /setcolorspace get $error /errorname get signalerror } + if + } +bind def + +/_setcolorspace_nosub + { + { + //.cs_validate exec + dup + //.cs_prepare exec + //.cs_install exec + //make_array1 exec //setcolorspace + } + stopped + { //.cspace_util /setcolorspace get $error /errorname get signalerror } + if + } +bind def + +/setcolorspace { //true //_setcolorspace exec } bind odef +/forcesetcolorspace { //false //_setcolorspace exec } bind odef + +% +% - initgraphics - +% +% The initgraphics operator must be redefined create a real color space. +% Previously this was unnecessary, as .currentcolorspace could return +% an integer. +% +% +/initgraphics + { initgraphics //DeviceGray_array forcesetcolorspace } +.bind systemdict begin odef end + +systemdict /setcolorspace .undef + + +% +% <gray> setgray - +% +% <r> <g> <b> setrgbcolor - +% +% <c> <m> <y> <b> setcmykcolor - +% +% The Level 1 color setting operators. setcmykcolor is created only if +% setcolorscreen is present. These operators are always defined in +% systemdict. +% +/setgray + { + { //DeviceGray_array //setcolorspace //setcolor } + stopped + { /setgray .systemvar $error /errorname get signalerror } + if + } +bind systemdict begin odef end + +/setrgbcolor + { + { //DeviceRGB_array //setcolorspace //setcolor } + stopped + { /setrgbcolor .systemvar $error /errorname get signalerror } + if + } +bind systemdict begin odef end + +/setcolorscreen where + { + pop + /setcmykcolor + { + { //DeviceCMYK_array //setcolorspace //setcolor } + stopped + { /setcmykcolor .systemvar $error /errorname get signalerror } + if + } + bind systemdict begin odef end + } +if + + +% +% - currentgray <gray> +% +% - currentrgbcolor <r> <g> <b> +% +% - currentcmykcolor <c> <m> <y> <k> +% +% Return the current color, mapped to a DeviceGray, DeviceRGB, or +% DeviceCMYK color space. The latter is only created if setcolorscreen +% is present. +/currentgray + { currentcolor currentcolorspace //.cs_get_currentgray exec } +bind systemdict begin odef end + +/currentrgbcolor + { currentcolor currentcolorspace //.cs_get_currentrgb exec } +bind systemdict begin odef end + +/setcolorscreen where + { + pop + /currentcmykcolor + { currentcolor currentcolorspace //.cs_get_currentcmyk exec } + bind systemdict begin odef end + } +if + + + +% +% Add some generically useful structures and procedures to .cspace_util. +% + +% +% Some common errors. The command for these errors will normally be +% overwritten by the invoking operator. We cannot "load" the secolorspace +% or setcolor operators, as they are not present in Level 1 systems. +% +/setcspace_typecheck + { /setcolorspace cvx /typecheck signalerror } +bind def + +/setcspace_rangecheck + { /setcolorspace cvx /rangecheck signalerror } +bind def + +/setcspace_invalidaccess + { /setcolorspace cvx /invalidaccess signalerror } +bind def + +/setcspace_undefined + { /setcolorspace cvx /undefined signalerror } +bind def + +/setcolor_typecheck + { /setcolor cvx /typecheck signalerror } +bind def + +/setcolor_invalidaccess + { /setcolor cvx /invalidaccess signalerror } +bind def + + +% +% <obj> check_array <obj> +% +% Check that an object is an array. Currently we don't check for +% readability, as a failing get or length operator should generate +% the appropriate invalidaccess error. +/check_array + { + dup type dup /arraytype ne exch /packedarraytype ne and + { /setcolorspace cvx /typecheck signalerror } + if + } +bind def + + +% pre-defined procedures for cs_ncomps and cs_get_range +/ncomps_1 { pop 1 } bind def +/ncomps_3 { pop 3 } bind def +/ncomps_4 { pop 4 } bind def + +/dflt_range_4 [ 0 1 0 1 0 1 0 1 ] readonly def +/dflt_range_3 dflt_range_4 0 6 getinterval def +/dflt_range_1 dflt_range_4 0 2 getinterval def + +% <obj> get_range_[1|3|4] <range> +/get_range_1 { pop //dflt_range_1 } bind def +/get_range_3 { pop //dflt_range_3 } bind def +/get_range_4 { pop //dflt_range_4 } bind def + + +% +% <c1> ... <cn> <name | array> <n> +% check_num_stack +% <c1> ... <cn> <array | array> +% +% <c1> <array> validate_color_1 <c1> +% <c1> <c2> <c3> <arraY> validate_color_3 <c1> <c2> <c3> +% <c1> <c2> <c3> <c4> <arraY> validate_color_4 <c1> <c2> <c3> <c4> +% +% check_num_stack verifies that the stack consists of a color space array and +% n numbers. This is used by most of the cs_prepare_color procedures. The +% validate_color_[1|3|4] procedures can be used as the cs_prepare_color +% procedure for Device specific, CIEBased, and Indexed color spaces. +% +% Note that the pseudo-operator that (indirectly) invokes this routine will +% handle resetting the stacks. +% +/check_num_stack + { % c1 .. cn [] n + 1 1 3 2 roll % c1 .. cn [] 1 1 n + { index + type dup /integertype ne exch /realtype ne and + //setcolor_typecheck + if + } + for + } bind def + +% <c1> <array> validate_1 <c1> +/validate_1 { 1 //check_num_stack exec pop } bind def + +% <c1> <c2> <c3> <array> validate_3 <c1> <c2> <c3> +/validate_3 { 3 //check_num_stack exec pop } bind def + +% <c1> <c2> <c3> <c4> <array> validate_4 <c1> <c2> <c3> <c4> +/validate_4 { 4 //check_num_stack exec pop } bind def + + +% +% <obj> pop_1 - +% +% This is a procedure form of pop. It may be used where a procedure is +% expected, but the function of the procedure is the same as the pop +% operator. +/pop_1 { pop } bind def + +% +% <obj> dup_1 <obj> <obj> +% +% An analog to pop_1, this one for dup. +% +/dup_1 { dup } bind def + +% +% <obj1> ... <objn> <n> clear_n_objs - +% +% Clear n objects from the operand stack. +% +/clear_n_objs { //pop_1 repeat } bind def + +% +% <obj1> ... <objn> <array> clear_setcolor_operands - +% +% Clear the setcolor operands for a color space. +% +/clear_setcolor_operands + { //.cs_get_ncomps exec //clear_n_objs exec } +bind def + +% +% Return 1, 3, or 4 zeros. These routines are used primarily for the +% CIEBased color spaces, for which currentgray and currentrgb +% should return 0 for all components, and currentcmyk should return +% 0 0 0 1.0 (this varies from Adobe's documentation but is consistent +% with their impelementations). +% +/no_currentgray { //.cs_get_ncomps exec //clear_n_objs exec 0. } bind def +/no_currentrgb { //.cs_get_ncomps exec //clear_n_objs exec 0. 0. 0. } bind def +/no_currentcmyk { //.cs_get_ncomps exec //clear_n_objs exec 0. 0. 0. 1.} bind def + + +% +% <num> bound_0_1 <num> +% +% Bound a number to the range [0.0, 1.0] +% +/bound_0_1 + { + dup 0 lt + { pop 0.0 } + { + dup 1 gt + { pop 1.0 } + if + } + ifelse + } +bind def + + +% +% Provide pseudo-operators for sethsbcolor and currenthsbcolor. These are +% alternate versions of the setrgbcolor and currentrgbcolor operators, which +% make use of a hue/staturation/brightness color description. +% + +% +% <num_1> ... <num_n> n max_n <num> +% <num_1> ... <num_n> n min_n <num> +% +% Find the maximum and minum of 3 color component intensities. +% +/max_n + { + 1 sub + { 2 copy lt { exch } if pop } + repeat + } +bind def + +/min_n + { + 1 sub + { 2 copy gt { exch } if pop } + repeat + } +bind def + + +% +% <r> <g> <b> .rgb_2_hsb <h> <s> <br> +% <h> <s> <br> .hsb_2_rgb <r> <g> <b> +% +% Convert between RGB and HSB colors, using the hexcone approach (see +% Rogers, David, "Procedureal Elements For Computer Graphics", +% (McGraw-Hill, 1985), pp. 402 - 3). +% +% The rgb ==> hsb calculation is: +% +% br = max(r, g, b) +% +% if (br == 0) +% h = 0, s = 0; +% else { +% v = min(r, g, b) +% diff = br - v; +% sat = diff / br; +% if (r == br) +% h = (g - b) / (6 * diff) + (b > g ? 1 : 0); +% else if (g == br) +% h = 1/3 + (b - r) / (6 * diff); +% else /* b == br */ +% h = 2/3 + (r - g) / (6 * diff); +% } +% +% The hsb ==> rgb conversion is: +% +% mn = (1 - s) * br, md = 6 * s * br; +% +% switch ((int)floor(6 * h)) { +% case 0: /* r >= g >= b */ +% r = br; +% g = mn + h * md; +% b = mn; +% break; +% +% case 1: /* g >= r >= b */ +% r = mn + md * (1/3 - h); +% g = br; +% b = mn; +% break; +% +% case 2: /* g >= b >= r */ +% r = mn; +% g = br; +% b = mn + (h - 1/3) * md; +% break; +% +% case 3: /* b >= g >= r */ +% r = mn; +% g = mn + (2/3 - h) * md; +% b = br; +% break; +% +% case 4: /* b >= r >= g */ +% r = mn + (h - 2/3) * md; +% g = mn; +% b = br; +% break; +% +% case 5: /* r >= b >= g */ +% r = br; +% g = mn; +% b = mn + (1 - h) * md; +% break; +% +% case 6: /* We have wrapped around the hexcone. Thus this case is +% the same as case 0 with h = 0 */ +% h = 0; +% r = br; +% g = mn + h * md = mn; +% b = mn; +% break; +% } +% + + +% Define 1/3 and 2/3 accurately (don't use literals like 0.333333). +/.f1_3 1.0 3 div def +/.f2_3 2.0 3 div def + +/.rgb_2_hsb + { + % find the largest and smallest components + 3 copy 3 //max_n exec dup 5 1 roll + dup 0.0 eq + { pop pop pop pop 0.0 0.0 } + { + 4 copy pop 3 //min_n exec 1 index exch sub + dup 2 index div 7 1 roll + dup 0.0 eq + { 5 { pop } repeat 0.0 3 1 roll } + { + 6.0 mul 5 1 roll + 2 copy eq % blue == brightness + { pop pop sub exch div //.f2_3 add } + { + 2 index eq % green == brightness + { exch pop exch sub exch div //.f1_3 add } + { + % red == brightness + sub exch pop exch div + dup 0.0 lt + { 1.0 add } + if + } + ifelse + } + ifelse + 3 1 roll + } + ifelse + } + ifelse + } +bind def + + +/.hsb_2_rgb + { + 3 { 0.0 max 1.0 min 3 1 roll } repeat % h s b + 1.0 2 index sub 1 index mul % h s b (1-s)*b + 3 -1 roll 2 index mul 6.0 mul % h b (1-s)*b 6*s*b + 4 -1 roll % b (1-s)*b=nm 6*s*b=md h + + % array of procedures for the 7 hue cases + { + % 0 ==> r >= g >= b % b nm md h + { mul 1 index add exch } + + % 1 ==> g >= r >= b + { //.f1_3 exch sub mul 1 index add 3 1 roll } + + % 2 ==> g >= b >= r + { //.f1_3 sub mul 1 index add 3 1 roll exch 3 -1 roll } + + % 3 ==> b >= g >= r + { //.f2_3 exch sub mul 1 index add 3 -1 roll } + + % 4 ==> b >= r >= g + { //.f2_3 sub mul 1 index add 3 1 roll exch } + + % 5 ==> r >= b >= g + { 1.0 exch sub mul 1 index add } + + % 6 ==> r = br, g = b = mn + % Case 6 is the same as case 0 with h = 0. This also simplifies + % the calculations. + { pop pop dup } + } + 1 index 6.0 mul cvi % b (1-s)*b 6*s*b h {} int(6*h) + get exec + } +bind def + + +% +% <hue> <saturation> <brightness sethsbcolor - +% +% - currenthsbcolor <hue> <saturation> <brightness> +% +/sethsbcolor + { + { //.hsb_2_rgb exec setrgbcolor } + stopped + { /sethsbcolor .systemvar $error /errorname get signalerror } + if + } +bind systemdict begin odef end + +/currenthsbcolor + { + { currentrgbcolor //.rgb_2_hsb exec } + stopped + { /currenthsbcolor .systemvar $error /errorname get signalerror } + if + } +bind systemdict begin odef end + +currentdict /DeviceGray_array .undef +currentdict /DeviceRGB_array .undef +currentdict /DeviceCMYK_array .undef + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_css_e.ps b/gs/Resource/Init/gs_css_e.ps new file mode 100644 index 000000000..fc5ae58a7 --- /dev/null +++ b/gs/Resource/Init/gs_css_e.ps @@ -0,0 +1,114 @@ +% Copyright (C) 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the CFF StandardStrings that represent characters. +% This is a pseudo-encoding. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/CFFStandardStrings mark + +% 0 + /.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 +% 50 + /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 +% 100 + /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 +% 150 + /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 +% 200 + /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 +% 250 + /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 +% 300 + /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 +% 350 + /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 +% 379 = end + +counttomark packedarray exch pop +10 1 index .registerencoding +.defineencoding +exec diff --git a/gs/Resource/Init/gs_dbt_e.ps b/gs/Resource/Init/gs_dbt_e.ps new file mode 100644 index 000000000..14a66c0ff --- /dev/null +++ b/gs/Resource/Init/gs_dbt_e.ps @@ -0,0 +1,59 @@ +% Copyright (C) 1993, 1994 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the Dingbats encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/DingbatsEncoding +% \000 + StandardEncoding 0 32 getinterval aload pop % /.notdef +% \040 + /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 +% \100 + /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 +% \140 + /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 /.notdef +% \200 + StandardEncoding 0 32 getinterval aload pop % /.notdef +% \240 + /.notdef /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 +% \300 + /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 +% \340 + /a171 /a172 /a173 /a162 /a174 /a175 /a176 /a177 + /a178 /a179 /a193 /a180 /a199 /a181 /a200 /a182 + /.notdef /a201 /a183 /a184 /a197 /a185 /a194 /a198 + /a186 /a195 /a187 /a188 /a189 /a190 /a191 /.notdef +256 packedarray .defineencoding +3 DingbatsEncoding .registerencoding +exec diff --git a/gs/Resource/Init/gs_devcs.ps b/gs/Resource/Init/gs_devcs.ps new file mode 100644 index 000000000..1d7557942 --- /dev/null +++ b/gs/Resource/Init/gs_devcs.ps @@ -0,0 +1,250 @@ +% Copyright (C) 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Device-specific color space method dictionaries. + +% +% This file implements the method dictionaries for the Device-specific +% color spaces. See gs_cspace.ps for information. +% +% Note that, because these color spaces are parameter-less, no color +% space validation is required: if we can get to the color space methods, +% we know the color space is legitimate. +% +% The colorspace substitution routines for these color spaces +% (cs_substitute) will fail in a Level 1 system, but this is not a +% problem as .getuseciecolor will always return false for such systems. +% +.currentglobal true .setglobal +.cspace_util begin + +% +% <r> <g> <b> rgb_2_gray <gray> +% +% Convert RGB colors to gray. This includes a special check for +% r == g == b, and avoids roundoff error if this is the case. +% +/rgb_2_gray + { + 3 copy 1 index eq 3 1 roll eq and + { pop pop } + { .11 mul exch .59 mul add exch .3 mul add } + ifelse + } +bind def + +systemdict /..page_default_spaces 3 dict put + +% <color_space_name> ..includecolorspace - +/..includecolorspace +{ % Only includes ones explicitly defined by the document. + systemdict /..page_default_spaces get 1 index known { + pop + } { + mark exch + { dup /ColorSpace resourcestatus { + pop 0 eq { + systemdict /..page_default_spaces get 1 index //true put + gsave + { dup /ColorSpace findresource //_setcolorspace_nosub exec .includecolorspace + } stopped pop + grestore + } if + } if + } stopped pop + cleartomark + } ifelse +} bind def + +% <color_space> <color_space_name> cs_substitute_generic <color_space1> <color_space2> +/cs_substitute_generic +{ .getuseciecolor + { NOSUBSTDEVICECOLORS + { //..includecolorspace exec dup } + { /ColorSpace findresource } + ifelse + } + { pop dup } + ifelse +} +bind def + +% <color_space> <color_space_name> cs_substitute_DeviceRGB_for_PDFX_or_PDFA <color_space1> <color_space2> +/cs_substitute_DeviceRGB_for_PDFX_or_PDFA +{ systemdict /PDFX .knownget not { false } if + systemdict /PDFA .knownget not { false } if + or { + dup /ColorSpace resourcestatus { + pop pop + } { + (Error: Need a /DefaultRGB /ColorSpace resource for generating a PDF/X or PDF/A document.) = + /cs_substitute_DeviceRGB_for_PDFX_or_PDFA cvx /undefined signalerror + } ifelse + /ColorSpace findresource + } { + //cs_substitute_generic exec + } ifelse +} bind def + +colorspacedict + +dup +/DeviceGray + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_1 + /cs_get_range //get_range_1 + /cs_get_default_color { pop 0.0 } bind + /cs_get_currentgray //pop_1 + /cs_get_currentrgb { pop dup dup } bind + /cs_get_currentcmyk { pop 1.0 exch sub 0.0 0.0 0.0 4 -1 roll } bind + /cs_validate {} + + /cs_substitute + { /DefaultGray //cs_substitute_generic exec + } + bind + + /cs_prepare {} + /cs_install { pop 0 .setdevcspace } bind + /cs_prepare_color //validate_1 + /cs_complete_setcolor //pop_1 + .dicttomark +put + + +/DeviceRGB + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_3 + /cs_get_range //get_range_3 + /cs_get_default_color { pop 0.0 0.0 0.0 } bind + /cs_get_currentgray { pop //rgb_2_gray exec } bind + /cs_get_currentrgb //pop_1 + + % to convert to cmyk use blackgeneration and undercolorremoval + /cs_get_currentcmyk + { + pop + + % convert to subtractive (CMY) color space + 3 + { 1.0 exch sub 3 1 roll } + repeat + + % find the minimum (initial k component) + 3 copy + 2 + { + 2 copy gt + { exch } + if + pop + } + repeat + + % apply undercolorremoval + dup 5 1 roll currentundercolorremoval exec cvr 4 1 roll + 3 + { 3 index sub //bound_0_1 exec 3 1 roll } + repeat + + % apply blackgeneration + 5 3 roll pop currentblackgeneration exec cvr //bound_0_1 exec + } + bind + + /cs_validate {} + + /cs_substitute + { /DefaultRGB //cs_substitute_DeviceRGB_for_PDFX_or_PDFA exec + } + bind + + /cs_prepare {} + /cs_install { pop 1 .setdevcspace } bind + /cs_prepare_color //validate_3 + /cs_complete_setcolor //pop_1 + .dicttomark +put + +end % .cspace_util +.setglobal + + +% Only create the DeviceCMYK color space if setcolorscreen is present +/setcolorscreen where + { pop } + { currentfile closefile } +ifelse + + +.currentglobal true .setglobal +.cspace_util begin + +colorspacedict +/DeviceCMYK + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_4 + /cs_get_range //get_range_4 + /cs_get_default_color { pop 0.0 0.0 0.0 1.0 } bind + + /cs_get_currentgray + { pop 4 1 roll //rgb_2_gray exec add 1.0 exch sub //bound_0_1 exec } + bind + + /cs_get_currentrgb + { + pop + 4 1 roll 3 + { 3 index add 1.0 exch sub //bound_0_1 exec 3 1 roll } + repeat + 4 -1 roll pop + } + bind + + /cs_get_currentcmyk //pop_1 + + /cs_validate {} + + /cs_substitute + { /DefaultCMYK //cs_substitute_generic exec + } + bind + + /cs_prepare {} + /cs_install { pop 2 .setdevcspace } bind + /cs_prepare_color //validate_4 + /cs_complete_setcolor //pop_1 + .dicttomark +put + +currentdict /..includecolorspace .undef +currentdict /cs_substitute_generic .undef + +end % .cspace_util +.setglobal + diff --git a/gs/Resource/Init/gs_devn.ps b/gs/Resource/Init/gs_devn.ps new file mode 100644 index 000000000..5b679aedd --- /dev/null +++ b/gs/Resource/Init/gs_devn.ps @@ -0,0 +1,218 @@ +% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% DeviceN color space method dictionary; this depends on gs_sepr.ps + + +% verify that DeviceN and Separation color spaces are supported +/.setdevicenspace where + { + pop + /.setseparationspace where + { pop //false } + { //true } + ifelse + } + { //true } +ifelse + { currentfile closefile } +if + +.currentglobal true .setglobal +.cspace_util begin + + +% +% <c1> ... <cm> <array> apply_devn_tint_xform <c1>' ... <cn>' <array> +% +% Apply the tint transformation for the DeviceN color intensity values. +/apply_devn_tint_xform + { + dup 1 get length 1 add exch + mark 2 index 2 add 2 roll + index 3 get exec + counttomark 2 add -2 roll pop + } +bind def + + + +colorspacedict +/DeviceN + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate false + /cs_potential_icc_alternate false + /cs_get_ncomps { 1 get length } bind + /cs_get_range { 1 get length [ exch { 0 1 } repeat ] } bind + /cs_get_default_color { 1 get length { 1 } repeat } bind + + /cs_get_currentgray + { //apply_devn_tint_xform exec 2 get //.cs_get_currentgray exec } + bind + /cs_get_currentrgb + { //apply_devn_tint_xform exec 2 get //.cs_get_currentrgb exec } + bind + /cs_get_currentcmyk + { //apply_devn_tint_xform exec 2 get //.cs_get_currentcmyk exec } + bind + + % a lot of validation is done by the cs_validate method + /cs_validate + { + //check_array exec + dup 1 get //check_array exec + { + type dup /nametype ne exch /stringtype ne and + //setcspace_typecheck + if + } + forall + dup 2 get //.cs_validate exec //.cs_potential_alternate exec not + //setcspace_rangecheck + if + dup 3 get //check_array exec xcheck not + //setcspace_typecheck + if + } + bind + + % substitute the base space if appropriate + /cs_substitute + { + dup 2 get //.cs_substitute exec 2 copy eq + { pop pop dup } + { + % retain only the new alternate space + exch pop + + % build all new structures in local VM + .currentglobal 3 1 roll //false .setglobal + + % construct a new array and insert the new base color space + 1 index dup length array copy dup 2 4 -1 roll put + + % restore VM mode + 3 -1 roll .setglobal + } + ifelse + } + bind + + % + % The Ghostscript interpreter works better when tinttransform procedures + % are translated into functions. Attempt to do that here. + % + /cs_prepare //converttinttransform + + % + % Install the current color space. + % + % The current Ghostscript color space implementation requires that + % color spaces that provide a base or alternative color space set + % that base/alternative color space to be the current color space + % before attempting to set the original color space. + % + % Beginning with Acrobat 5, PDF apparently supports 1-component + % DeviceN color spaces with the single component "All" (the "PDF + % Reference", 3rd ed., p. 206 still describes this as illegal). + % We translate such calls to Separation color spaces. + % + /cs_install + { + % save the current color space + currentcolorspace + + % set the base color space as the current color space + 1 index 2 get //forcesetcolorspace + + % set the indexed color space; restore the earlier space on error + mark 2 index + dup 1 get dup length 1 eq exch 0 get /All eq and + { + dup length array copy + dup 0 /Separation put + dup 1 /All put + { .setseparationspace } + } { + { + dup .setdevicenspace + % Check if the DeviceN color space includes an 'attributes' + % dict with a Colorants dict. If present then we want to + % attach the separation colorspace in the Colorants dict to + % the DeviceN color space description within the graphics + % library. To do this we are creating a temp gstate, building + % each of the Colorants color spaces in the temp gstate and + % then attaching the temp color space to the DeviceN color + % space. This round about procedure is done to create + % descriptions of the Colorants color spaces which are + % equivalent to any other color space (i.e. with color space + % substitution performed on the alternate color space and the + % tint transform function sampled). + dup length 4 gt { + dup 4 get /Colorants .knownget { + { gsave + { % Ignore any problems with the Colorants color spaces + //forcesetcolorspace .attachdevicenattributespace + } stopped pop + grestore + } forall + } if + } if + pop + } + } + ifelse + stopped + { cleartomark setcolorspace stop } + { pop pop pop } + ifelse + } + bind + + /cs_prepare_color { dup 1 get length //check_num_stack exec pop } bind + + % + % If a DeviceN color space is not supported in native mode by + % the current process color model, Adobe implementations will always + % execute the tint transform procedure when setcolor is invoked. + % Ghostscript may have turned this transform into a sampled function, + % and even if this is not the case, will have sampled the transform + % when the color space is first set. Some applications depend on + % the Adobe behavior, so we implement it via the cs_complete_setcolor + % method. + % + /cs_complete_setcolor + { + .usealternate + { + pop + currentcolor + currentcolorspace 3 get exec + currentcolorspace 2 get + //clear_setcolor_operands exec + } + { pop } + ifelse + } + bind + + .dicttomark +put + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_devpxl.ps b/gs/Resource/Init/gs_devpxl.ps new file mode 100644 index 000000000..0bc0cee12 --- /dev/null +++ b/gs/Resource/Init/gs_devpxl.ps @@ -0,0 +1,78 @@ +% Copyright (C) 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% DevicePixel color space method dictionaries. + +% +% This file implements the DevicePixel color space. See gs_cspace.ps +% for information. +% +% The DevicePixel color space includes a single parameter, the bit +% depth of the device color representation. Color is expressed as +% single integers in an opaque, device-specific format. +% + +% verify that the DevicePixel color space is supported +/.setdevicepixelspace where + { pop } + { currentfile closefile } +ifelse + + +.currentglobal true .setglobal + +.cspace_util begin + + +colorspacedict +/DevicePixel + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate true + /cs_get_ncomps //ncomps_1 + /cs_get_range { [ exch 1 get 1 exch bitshift 1 sub ] } bind + /cs_get_default_color { pop 0 } bind % no good default + /cs_get_currentgray //no_currentgray + /cs_get_currentrgb //no_currentrgb + /cs_get_currentcmyk //no_currentcmyk + + /cs_validate + { + //check_array exec + dup 1 get dup type /integertype ne + //setcspace_typecheck + if + dup 0 lt + //setcspace_rangecheck + if + 31 gt % 31 bits is an implementation limit + { /setcolorspace .systemvar /limitcheck signalerror } + if + } + bind + + /cs_substitute //dup_1 + /cs_prepare {} + /cs_install { .setdevicepixelspace } bind + /cs_prepare_color //validate_1 + /cs_complete_setcolor //pop_1 + .dicttomark +put + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_diskf.ps b/gs/Resource/Init/gs_diskf.ps new file mode 100644 index 000000000..cfe48abb5 --- /dev/null +++ b/gs/Resource/Init/gs_diskf.ps @@ -0,0 +1,224 @@ +% Copyright (C) 1996 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Support for converting Type 1 fonts without eexec encryption to +% Type 4 fonts that load individual character outlines on demand. + +% If DISKFONTS is true, we load individual CharStrings as they are needed. +% (This is intended primarily for machines with very small memories.) +% Initially, the character definition is the file position of the definition; +% this gets replaced with the actual CharString. +% Note that if we are loading characters lazily, CharStrings is writable. + +% _Cstring must be long enough to hold the longest CharString for +% a character defined using seac. This is lenIV + 4 * 5 (for the operands +% of sbw, assuming div is not used) + 2 (for sbw) + 3 * 5 (for the operands +% of seac other than the character codes) + 2 * 2 (for the character codes) +% + 2 (for seac), i.e., lenIV + 43. + +/_Cstring 60 string def + +% When we initially load the font, we call +% <index|charname> <length> <readproc> cskip_C +% to skip over each character definition and return the file position instead. +% This substitutes for the procedure +% <index|charname> <length> string currentfile exch read[hex]string pop +% [encrypt] +% What we actually store in the CharString is fileposition * 1000 + length, +% negated if the string is stored in binary form. + +/cskip_C + { exch dup 1000 ge 3 index type /nametype ne or + { % This is a Subrs string, or the string is so long we can't represent + % its length. Load it now. + exch exec + } + { % Record the position and length, and skip the string. + dup currentfile fileposition 1000 mul add + 2 index 3 get /readstring cvx eq { neg } if + 3 1 roll + dup _Cstring length idiv + { currentfile _Cstring 3 index 3 get exec pop pop + } repeat + _Cstring length mod _Cstring exch 0 exch getinterval + currentfile exch 3 -1 roll 3 get exec pop pop + } + ifelse + } bind def + +% Load a CharString from the file. The font is the top entry +% on the dictionary stack. +/load_C % <charname> <fileposandlength> load_C - + { dup abs 1000 idiv FontFile exch setfileposition + CharStrings 3 1 roll + .currentglobal CharStrings .gcheck .setglobal exch + dup 0 lt + { neg 1000 mod string FontFile exch readstring } + { 1000 mod string FontFile exch readhexstring } + ifelse pop + exch .setglobal +% If the CharStrings aren't encrypted on the file, encrypt now. + Private /-| get 0 get + dup type /nametype ne + { dup length 5 sub 5 exch getinterval exec } + { pop } + ifelse dup 4 1 roll put +% If the character is defined with seac, load its components now. + mark exch seac_C + counttomark + { StandardEncoding exch get dup CharStrings exch get + dup type /integertype eq { load_C } { pop pop } ifelse + } repeat + pop % the mark + } bind def + +/seac_C % <charstring> seac_C <achar> <bchar> ..or nothing.. + { dup length _Cstring length le + { 4330 exch _Cstring .type1decrypt exch pop + dup dup length 2 sub 2 getinterval <0c06> eq % seac + { dup length + Private /lenIV known { Private /lenIV get } { 4 } ifelse + exch 1 index sub getinterval +% Parse the string just enough to extract the seac information. +% We assume that the only possible operators are hsbw, sbw, and seac, +% and that there are no 5-byte numbers. + mark 0 3 -1 roll + { exch + { { dup 32 lt + { pop 0 } + { dup 247 lt + { 139 sub 0 } + { dup 251 lt + { 247 sub 256 mul 108 add 1 1 } + { 251 sub -256 mul -108 add -1 1 } + ifelse + } + ifelse + } + ifelse + } % 0 + { mul add 0 } % 1 + } + exch get exec + } + forall pop + counttomark 1 add 2 roll cleartomark % pop all but achar bchar + } + { pop % not seac + } + ifelse + } + { pop % punt + } + ifelse + } bind def + +% Define replacement procedures for loading fonts. +% If DISKFONTS is true and the body of the font is not encrypted with eexec: +% - Prevent the CharStrings from being made read-only. +% - Substitute a different CharString-reading procedure. +% (eexec disables this because the implicit 'systemdict begin' hides +% the redefinitions that make the scheme work.) +% We assume that: +% - The magic procedures (-|, -!, |-, and |) are defined with +% executeonly or readonly; +% - The contents of the reading procedures are as defined in bdftops.ps; +% - The font includes the code +% <font> /CharStrings <CharStrings> readonly put +/.loadfontdict 6 dict def mark + /begin % push this dict after systemdict + { dup begin + //systemdict eq { //.loadfontdict begin } if + } bind + /end % match begin + { currentdict end + //.loadfontdict eq currentdict //systemdict eq and { end } if + } bind + /dict % leave room for FontFile, BuildChar, BuildGlyph + { 3 add dict + } bind + /executeonly % for reading procedures + { readonly + } + /noaccess % for Subrs strings and Private dictionary + { readonly + } + /readonly % for procedures and CharStrings dictionary + { % We want to take the following non-standard actions here: + % - If the operand is the CharStrings dictionary, do nothing; + % - If the operand is a number (a file position replacing the + % actual CharString), do nothing; + % - If the operand is either of the reading procedures (-| or -!), + % substitute a different one. + dup type /dicttype eq % CharStrings or Private + count 2 gt and + { 1 index /CharStrings ne { readonly } if } + { dup type /arraytype eq % procedure or data array + { dup length 5 ge 1 index xcheck and + { dup 0 get /string eq + 1 index 1 get /currentfile eq and + 1 index 2 get /exch eq and + 1 index 3 get dup /readstring eq exch /readhexstring eq or and + 1 index 4 get /pop eq and + { /cskip_C cvx 2 packedarray cvx + } + { readonly + } + ifelse + } + { readonly + } + ifelse + } + { dup type /stringtype eq % must be a Subr string + { readonly } + if + } + ifelse + } + ifelse + } bind + /definefont % to insert BuildChar/Glyph and change FontType + { dup /FontType get 1 eq + { dup /FontType 4 put + dup /BuildChar /build_C load put + dup /BuildGlyph /build_C load put + } + if definefont + } bind +counttomark 2 idiv { .loadfontdict 3 1 roll put } repeat pop +.loadfontdict readonly pop + +% Define the BuildChar and BuildGlyph procedures for modified fonts. +% A single procedure serves for both. +/build_C % <font> <code|name> build_C - + { 1 index begin + dup dup type /integertype eq { Encoding exch get } if + % Stack: font code|name name + dup CharStrings exch .knownget not + { 2 copy eq { exch pop /.notdef exch } if + QUIET not + { (Substituting .notdef for ) print = flush } + { pop } + ifelse + /.notdef CharStrings /.notdef get + } if + % Stack: font code|name name charstring + dup type /integertype eq + { load_C end build_C } + { end .type1execchar } + ifelse + } bind def diff --git a/gs/Resource/Init/gs_diskn.ps b/gs/Resource/Init/gs_diskn.ps new file mode 100644 index 000000000..a2475a3b2 --- /dev/null +++ b/gs/Resource/Init/gs_diskn.ps @@ -0,0 +1,214 @@ +% Copyright (C) 1990, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for %disk device modifications +% When this is run, systemdict is still writable, + +systemdict begin + +% Collect the list of searchable IODevices in SearchOrder +% Efficiency here doesn't matter since we run this at the end +% of gs_init and convert it to a static array. +/.getsearchabledevs { % - .getsearchabledevs [ list_of_strings ] + //systemdict /.searchabledevs .knownget not { + .currentglobal true .setglobal + mark (*) { + dup length string copy dup currentdevparams /Searchable + .knownget { not { pop } if } { pop } ifelse + } 8192 string /IODevice resourceforall + ] + % now process the array into correct SearchOrder + 0 1 2 { + mark exch 2 index { + dup currentdevparams /SearchOrder get 2 index eq + { exch } { pop } ifelse + } forall % devices on the old list + pop + % make the array and sort it by name + ] { lt } bind .sort + exch + } for + % collect all devices with SearchOrder > 2 + mark 2 index { + dup currentdevparams /SearchOrder get 2 gt + { exch } { pop } ifelse + } forall + ] exch pop + % We now have 4 arrays on the stack, SO=0 SO=1 SO=2 SO>2 + % make them into a single array + mark 5 1 roll ] mark exch { { } forall } forall ] + //systemdict /.searchabledevs 2 index .forceput + exch .setglobal + } + if +} .bind executeonly def % must be bound and hidden for .forceput + +% Modify .putdevparams to force regeneration of .searchabledevs list +/.putdevparams { + % We could be smarter and check for %disk* device, but this + % doesn't get run enough to justify the complication + //.putdevparams + //systemdict /.searchabledevs .forceundef +} .bind odef % must be bound and hidden for .forceundef + +% ------ extend filenameforall to handle wildcards in %dev% part of pattern -------% +/filenameforall { + count 3 ge { + 2 index (%) search { + pop pop + } { + % no device specified, so search them all + pop (*%) 3 index concatstrings + % we need to suppress the device when we return the string + % in order to match Adobe's behaviour with %disk devices. + 4 -2 roll % the callers procedure + [ { (%) search { pop pop (%) search { pop pop } if } if } /exec load + 4 -1 roll % the callers procedure + /exec load + ] cvx + 4 2 roll % put the modified procedure where it belongs + } ifelse + % extract device portion (up to end of string or next %) + (%) search { exch pop } if % stack: opat proc scratch npat device + dup (*) search { pop pop pop true } { pop false } ifelse + 1 index (?) search { pop pop pop true } { pop false } ifelse + or not { + pop pop //filenameforall % device with no wildcard + } { + (%) concatstrings (%) exch concatstrings + .getsearchabledevs + % find all matching devices and add the rest of the search string + mark exch { + dup counttomark 1 add index .stringmatch { + counttomark 2 add index concatstrings + } { + pop + } ifelse + } forall + ] + 3 1 roll pop pop + 4 -1 roll pop + % now we need to invoke filenameforall for each of the strings + % in the array. We do this by building a procedure that is like + % an unrolled 'forall' loop. We do this to get the parameters + % for each filenameforall, since each execution will pop its + % parameters, but we can't use the operand stack for storage + % since each invocation must have the same operand stack. + mark exch { + counttomark dup 3 add index exch + 2 add index + /filenameforall load + } forall + ] cvx + 3 1 roll pop pop + exec % run our unrolled loop + } + ifelse + } { + //filenameforall % not enough parameters -- just let it fail + } + ifelse +} odef + +% redefine file to search all devices in order +/file { + dup 0 get (r) 0 get eq dup { + pop false % success code + 2 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse + { 3 index concatstrings % prepend the device + { + 2 index //file } .internalstopped not { + 4 1 roll pop pop pop true + exit % exit with success + } { + pop pop + } + ifelse + } + forall + } + if + not { % just let standard file operator handle things + //file + } + if +} bind odef + +% redefine deletefile to search all devices in order +/deletefile { + false % success code + 1 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse + { 2 index concatstrings % prepend the device + { //deletefile } .internalstopped exch pop not { + pop true exit % exit with success + } + if + } + forall + not { $error /errorname get /deletefile .systemvar exch signalerror } if +} bind odef + +% redefine status to search all devices in order +/status { + dup type /stringtype eq { + false % success code + 1 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse + { 2 index concatstrings % prepend the device + { //status } .internalstopped not { + { true 7 -2 roll pop pop true exit } % exit with success + if + } + if + } + forall + % If we made it this far, no devices were found to status the file + % clean up to return 'false' + exch pop + } { + //status + } + ifelse +} bind odef + +% Also redefine renamefile to search all devices in order +/renamefile { + false % success code + 2 index 0 get 37 eq { [ () ] } { .getsearchabledevs } ifelse + { dup 4 index concatstrings % prepend the device + { (r) //file } .internalstopped + not { + closefile exch pop true exit % exit with success + } { + pop pop + } ifelse + } + forall + not { $error /errorname get /renamefile .systemvar exch signalerror } if + 3 -1 roll concatstrings exch + //renamefile +} bind odef + +% redefine devforall to process devices in numeric order +% Spec's for 'devforall' are unclear, but font downloaders may expect this +/devforall { % <proc> <scratch> devforall - + [ { dup length string copy } 2 index //devforall ] + % stack: proc scratch array_of_device_names + { lt } .sort + % We don't really invoke the procedure with the scratch string + % but rather with the strings from our array + exch pop exch forall +} odef +end % systemdict diff --git a/gs/Resource/Init/gs_dpnxt.ps b/gs/Resource/Init/gs_dpnxt.ps new file mode 100644 index 000000000..90c0437ec --- /dev/null +++ b/gs/Resource/Init/gs_dpnxt.ps @@ -0,0 +1,134 @@ +% Copyright (C) 1997, 1998 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% gs_dpnxt.ps +% NeXT Display PostScript extensions + +% Define the operation values for compositing. These must match the values +% in gsdpnext.h, which also are the ones from the NeXT documentation. +% We put them in systemdict, which seems like as good a place as any. +mark + /Clear /Copy /Sover /Sin /Sout /Satop /Dover /Din /Dout /Datop /Xor + /PlusD /PlusL /Highlight % not sure about Highlight +counttomark { counttomark 1 sub def } repeat pop + +% We implement readimage and sizeimage using the following 3 otherwise +% undocumented lower-level operators: +% +% <x> <y> <width> <height> <matrix> .sizeimagebox +% <dev_x> <dev_y> <dev_width> <dev_height> <matrix> +% +% - .sizeimageparams <bits/sample> <multiproc> <ncolors> +% +% <device> <x> <y> <width> <max_height> <alpha?> <std_depth|null> +% <string> .getbitsrect <height> <substring> +% +% NOTE: These operators are subject to change without notice! + +% Implement readimage using .getbitsrect. Experimentation on a NeXT system +% shows that the data is always returned in order of increasing device Y, +% regardless of the CTM. +% +% Note that we can't make stack protection work for this operator, +% because it must remove its operands from the stack before calling +% the supplied procedure(s). + +/readimage { % <x> <y> <width> <height> <proc> [... <procN-1>] + % <string> <alpha?> readimage - + .sizeimageparams exch { + % multiproc = true. If N > 1, store the procedures in an array. + exch pop 1 index { 1 add } if + % Stack: ... string alpha? nprocs + dup 1 eq { + pop false % only 1 procedure, multiproc is irrelevant + } { + dup array 4 1 roll 3 add 2 roll astore 3 1 roll true + } ifelse + } { + % multiproc = false. + pop pop false + } ifelse + % Map the rectangle to device coordinates. + % Stack: x y w h proc(s) str alpha? multi? + 8 -4 roll matrix .sizeimagebox pop 8 4 roll + % Make sure we allocate the operand array in local VM + % to avoid a possible invalidaccess. + .currentglobal false .setglobal 9 1 roll + exch { 1 } { 0 } ifelse exch % alpha is last, if present + exch 4 1 roll 8 array astore exch .setglobal + { % Read out a block of scan lines and pass them to the procedure. + % Stack: [x y w h alpha? proc(s) str multi?] -- we must consume this. + dup 3 get 0 eq { pop exit } if + aload 9 1 roll pop exch pop currentdevice 7 1 roll + % Always read out the data as standard (not native) pixels. + .sizeimageparams pop pop exch .getbitsrect + % Stack: [x y w h alpha? proc(s) str multi?] hread substr + 3 -1 roll + % Stack: hread substr [x y w h alpha? proc(s) str multi?] + dup 1 2 copy get 5 index add put + % Stack: hread substr [x y' w h alpha? proc(s) str multi?] + dup 3 2 copy get 6 -1 roll sub put + % Stack: substr [x y' w h' alpha? proc(s) str multi?] + dup 5 get exch 7 get { + % multiproc = true, pass each plane to a different procedure. + % Stack: substr procs + 0 1 2 index length 1 sub { + % Push 1 plane and its procedure under the top 2 elements. + % Stack: ... substr procs plane# + 2 index length 2 index length idiv % bytes per plane + dup 2 index mul exch + % Stack: ... substr procs plane# start length + 4 index 3 1 roll getinterval 4 1 roll + 2 copy get 4 1 roll pop + } for + exch pop length 2 mul .execn + } { + % multiproc = false, just call the procedure. + exec + } ifelse + } //systemdict /exec get 3 packedarray cvx loop +} bind odef + +% +% <w> <h> <bpc> <mtx> <dsrc0> ... <multi> <ncomp> alphaimage - +% +img_utils_dict begin +/.alphaimage where + { + pop + currentglobal true setglobal + /alphaimage + { + //true + //.colorimage + stopped + { /alphaimage .systemvar $error /errorname get signalerror } + if + } + .bind systemdict begin odef end + setglobal + } +if +end + +% Implement sizeimage using lower-level operators. + +/sizeimage { % <x> <y> <width> <height> <matrix> sizeimage + % <devwidth> <devheight> <bits/sample> <matrix> + % <multiproc> <ncolors> + .sizeimagebox 5 -2 roll pop pop + .sizeimageparams 3 -1 roll 4 1 roll +} bind odef diff --git a/gs/Resource/Init/gs_dps.ps b/gs/Resource/Init/gs_dps.ps new file mode 100644 index 000000000..b3e761a3e --- /dev/null +++ b/gs/Resource/Init/gs_dps.ps @@ -0,0 +1,224 @@ +% Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for Display PostScript functions. + +% ------ Errors ------ % + +% These errors are only defined in DPS. +{ /invalidcontext /invalidid } { .registererror } forall + +% ------ Contexts ------ % + +% To create a context with private local VM, we use the .localfork +% operator to actually create the context, the new VM, and an empty +% userdict, and then we call the .initlocaldicts procedure to make +% local copies of the initial contents of the dictionaries in local VM. +% savedlocaldicts in systemdict is a global read-only dictionary whose +% elements are global read-only copies of these initial contents; +% we just copy its elements into local VM and install them in systemdict. +% userdict and internaldict require special handling. + +% Switching between contexts with different local VMs requires +% changing the bindings in systemdict that reference local objects. +% For this purpose, each userdict has an entry called localdicts +% which holds the local copies of the elements of savedlocaldicts, +% plus internaldict. The context switching code in the interpreter +% effectively copies this dictionary into systemdict. +% NOTE: the name localdicts is known to the interpreter. + +% Switching between contexts also requires resetting the user parameters. +% The interpreter records the value of userparams (a local dictionary +% referenced from systemdict) for each context, and uses it for this. +% See gs_lev2.ps for more details. +% NOTE: the name userparams is known to the interpreter. + +% Save copies of local dictionaries at the end of system initialization. +% Also save the initial gstate. +/.savelocalstate { + .currentglobal true .setglobal + //systemdict /savedlocaldicts mark //systemdict { + dup gcheck { + pop pop + } { + dup type /dicttype eq { + % Save a copy of this dictionary in global VM. + dup maxlength dict .copydict readonly + } { + pop pop + } ifelse + } ifelse + } forall .dicttomark readonly put + % Create localdicts for the current context. + false .setglobal + userdict /localdicts mark savedlocaldicts { + pop dup load + } forall /internaldict dup load + .dicttomark readonly put + % Save a copy of the initial gstate. + true .setglobal + //systemdict /savedinitialgstate gstate readonly put + .setglobal +} .bind def + +% Initialize local dictionaries and gstate when creating a new context. +% Note that until this completes, we are in the anomalous situation of +% having systemdict point to dictionaries that are in a non-current +% local VM. Because of this, we turn off garbage collection temporarily. +/.copylocal { % <name> <dict> .copylocal <name> <dict'> + % Copy a dictionary to the current (local) VM, + % and make it read-only if its current definition is. + dup maxlength dict .copydict + 1 index load wcheck not { readonly } if +} .bind def +% When this is called, the dictionary stack is in its initial state, +% and there is (anomalously) only one gstate on the gstate stack. +/.initlocaldicts { % - .initlocaldicts - + -2 vmreclaim + .currentglobal //systemdict begin + false .setglobal + % Since localdicts doesn't exist yet, references from + % systemdict to local objects won't get restored if + % a context switch happens in this code. Therefore, + % until localdicts is defined, we have to keep all our + % state on the operand stack. + + % Acquire userdict. + %****** WRONG IF NON-STANDARD INITIAL DSTACK ****** + countdictstack array dictstack + { dup gcheck not { exit } if pop } forall + % Create localdicts with a local copy of each dictionary, + % except for userdict and userparams, which just need + % to be filled in. + mark savedlocaldicts { + 1 index /userdict eq { + % Stack: userdict mark ... /userdict inituserdict + counttomark 1 add index .copydict + } { + 1 index /userparams eq { + % Stack: userdict mark ... /userparams inituserparams + userparams .copydict + } { + .copylocal + } ifelse + } ifelse + } forall /internaldict dup .makeinternaldict .makeoperator + .dicttomark readonly /localdicts exch put + % localdicts is now defined in userdict. + % Copy the definitions into systemdict. + localdicts { .forcedef } forall + % Set the user parameters. + userparams readonly .setuserparams + % Establish the initial gstate(s). + /savedinitialgstate .systemvar setgstate gsave + % Wrap up. + end .setglobal +} odef + +% Check whether an object is a procedure. +/.proccheck { % <obj> .proccheck <bool> + dup xcheck + exch type dup /arraytype eq exch /packedarraytype eq or and +} bind def + +% Create a context with private local VM. +% The .localfork operator does all the work, but we must ensure that +% .initlocaldicts gets called when the new context starts up. +/localfork { % <mark> <obj1> ... <objN> <proc> + % <stdin|null> <stdout|null> + % localfork <context> + .currentglobal true .setglobal 3 index + dup .proccheck not { + pop .setglobal /localfork .systemvar /typecheck signalerror + } if + {exec .initlocaldicts} aload pop + 3 1 roll 3 packedarray cvx + 4 1 roll 5 -1 roll pop .setglobal .localfork +} odef + +% Fork a context that shares VM. The .fork operator creates an empty +% userparams dictionary for the context, but we still need to initialize +% this dictionary when the new context starts up. +/.postfork { % - .postfork - + % Initialize the user parameters. + savedlocaldicts /userparams get userparams .copydict readonly pop +} odef +/fork { % <mark> <obj1> ... <objN> <proc> fork <context> + .currentglobal false .setglobal 1 index + dup .proccheck not { + pop .setglobal /fork .systemvar /typecheck signalerror + } if + {exec .postfork} aload pop + 3 1 roll 3 packedarray cvx + 3 1 roll exch pop .setglobal .fork +} odef + +% ------ Halftone phase ------ % + +/sethalftonephase { % <x> <y> sethalftonephase - + -1 2 index 2 index .setscreenphase pop pop +} odef +/currenthalftonephase { % - currenthalftonephase <x> <y> + 0 .currentscreenphase +} odef + +% ------ Device-source images ------ */ + +.imagetypes 2 /.image2 load put + +% ------ Device information ------ % + +/.deviceinfodict mark + /Colors null /GrayValues null /RedValues null /GreenValues null + /BlueValues null /ColorValues null +.dicttomark readonly def +/deviceinfo { % - deviceinfo <dict> + currentdevice //.deviceinfodict .getdeviceparams .dicttomark + dup begin + /ColorValues .knownget { + 0 le + { currentdict /ColorValues undef } + { + % hack around devices that incorrect set GrayValues + Colors 3 eq { 1 } { GrayValues } ifelse + RedValues mul GreenValues mul BlueValues mul ColorValues ne + { currentdict /GrayValues undef + currentdict /RedValues undef + currentdict /GreenValues undef + currentdict /BlueValues undef + } if + } + ifelse + } if + currentdict end readonly +} odef + +% The current implementation allocates a 2-element array each time. +% Perhaps we should change this to 2 separate parameters for X and Y? +/.wtdict mark + /wtranslation null +.dicttomark readonly def +/wtranslation { % - wtranslation <x> <y> + currentdevice //.wtdict .getdeviceparams exch pop exch pop aload pop +} odef +currentdict /.wtdict .undef + +% ------ View clipping ------ % + +/rectviewclip { % <x> <y> <width> <height> rectviewclip - + % <numarray|numstring> rectviewclip - + newpath .rectappend viewclip +} odef diff --git a/gs/Resource/Init/gs_dps1.ps b/gs/Resource/Init/gs_dps1.ps new file mode 100644 index 000000000..6b157ee63 --- /dev/null +++ b/gs/Resource/Init/gs_dps1.ps @@ -0,0 +1,139 @@ +% Copyright (C) 1997, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for most of the Display PostScript functions +% that are also included in Level 2. + +level2dict begin + +% ------ Virtual memory ------ % + +/currentshared /.currentglobal load def +/scheck /.gcheck load def +%****** FOLLOWING IS WRONG ****** +/shareddict currentdict /globaldict .knownget not { 20 dict } if def + +% Global and LocalFontDirectory must remain in systemdict +% even if we temporarily exit Level 2 mode. + +end % level2dict +systemdict begin + +/SharedFontDirectory .FontDirectory .gcheck + { .currentglobal false .setglobal + /LocalFontDirectory .FontDirectory dup maxlength dict copy + .forcedef % LocalFontDirectory is local, systemdict is global + .setglobal .FontDirectory + } + { /LocalFontDirectory .FontDirectory + .forcedef % LocalFontDirectory is local, systemdict is global + 50 dict + } +ifelse def + +end % systemdict +level2dict begin + +% setshared must rebind FontDirectory to the appropriate one of +% Local or SharedFontDirectory. + +/.setglobal % <bool> .setglobal - + { dup .setglobal + //systemdict /FontDirectory .currentglobal + { //SharedFontDirectory } + { /LocalFontDirectory .systemvar } % can't embed ref to local VM + ifelse .forceput pop % LocalFontDirectory is local, systemdict is global + } .bind odef % must bind .forceput and .setglobal + % even if NOBIND in effect +% Don't just copy (load) the definition of .setglobal: +% it gets redefined for LL3. +/setshared { /.setglobal .systemvar exec } odef +.currentglobal setshared + +% See below for changes in save and restore. + +% ------ Fonts ------ % + +/selectfont % <fontname> <size> selectfont - + { + { 1 .argindex findfont + 1 index dup type /arraytype eq { makefont } { scalefont } ifelse + setfont pop pop + } stopped { /selectfont .systemvar $error /errorname get signalerror } if + } odef +% undefinefont has to take local/global VM into account. +/undefinefont % <fontname> undefinefont - + { .FontDirectory 1 .argindex .forceundef % FontDirectory is readonly + .currentglobal + { % Current mode is global; delete from local directory too. + //systemdict /LocalFontDirectory .knownget + { 1 index .forceundef } % LocalFontDirectory is readonly + if + } + { % Current mode is local; if there was a shadowed global + % definition, copy it into the local directory. + //systemdict /SharedFontDirectory .knownget + { 1 index .knownget + { .FontDirectory 2 index 3 -1 roll { put } //superexec } % readonly + if + } + if + } + ifelse pop + } odef + +% If we load a font into global VM within an inner save, the restore +% will delete it from FontDirectory but not from SharedFontDirectory. +% We have to handle this by making restore copy missing entries from +% SharedFontDirectory to FontDirectory. Since this could slow down restore +% considerably, we define a new operator .forcecopynew for this purpose. +% Furthermore, if FAKEFONTS is in effect, we want global real fonts to +% override fake local ones. We handle this by brute force. +/restore % <save> restore - + { dup //restore % bind even if NOBIND + /LocalFontDirectory .systemvar + FAKEFONTS + { mark + % We want to delete a fake font from the local directory + % iff the global directory now has no definition for it, + % or a non-fake definition. + 1 index dup + { % Stack: lfd mark lfd key ... lfd key value + length 1 gt + { % This is a real local definition; don't do anything. + pop + } + { % This is a fake local definition, check for global. + //SharedFontDirectory 1 index .knownget + { % A global definition exists, check for fake. + length 1 eq { pop } { 1 index } ifelse + } + { % No global definition, delete the local one. + 1 index + } + ifelse + } + ifelse + } forall + pop counttomark 2 idiv { .forceundef } repeat pop % readonly + } + if + //SharedFontDirectory exch .forcecopynew pop + .currentglobal .setglobal % Rebind FontDirectory according to current VM. + pop + } .bind odef + +end % level2dict diff --git a/gs/Resource/Init/gs_dps2.ps b/gs/Resource/Init/gs_dps2.ps new file mode 100644 index 000000000..e8df335e1 --- /dev/null +++ b/gs/Resource/Init/gs_dps2.ps @@ -0,0 +1,247 @@ +% Copyright (C) 1990, 1996, 1997, 1998, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for basic Display PostScript functions +% that are also included in Level 2. + +level2dict begin + +% ------ Errors ------ % + +% These errors are only defined in Level 2 and DPS. +{ /configurationerror /undefinedresource /unregistered } +{ .registererror } forall + +% ------ Halftones ------ % + +/.makestackdict + { { counttomark -1 roll } forall .dicttomark + } bind def +/currenthalftone % - currenthalftone <dict> + { mark .currenthalftone + { { exch pop } % halftone + { /HalftoneType 1 % screen + { /Frequency /Angle /SpotFunction } + .makestackdict readonly + } + { /HalftoneType 2 % colorscreen + { /RedFrequency /RedAngle /RedSpotFunction + /GreenFrequency /GreenAngle /GreenSpotFunction + /BlueFrequency /BlueAngle /BlueSpotFunction + /GrayFrequency /GrayAngle /GraySpotFunction + } + .makestackdict readonly + } + } + exch get exec + } odef +% Define sethalftone so it converts types 1-4 to type 5. +/.makehalftoneRGBV { % <dict> <type> <keys> <keysRGBV> + 4 -1 roll exch { 1 index exch get exch } forall 15 1 roll + 14 -2 roll mark 15 1 roll { /Gray /Blue /Green /Red } { + % stack: v0 v1 v2 type keys comp + mark + 2 index 0 get 8 -1 roll + 4 index 1 get 9 -1 roll + 6 index 2 get 10 -1 roll + % stack: type keys comp mark k0 v0 k1 v1 k2 v2 + /HalftoneType 10 index .dicttomark + counttomark 2 roll + } forall pop pop + /Default 1 index .dicttomark exch pop { .sethalftone5 } +} bind def + +% The value of each entry in .halftonetypes is a procedure: +% <setdict> <htdict> <<proc>> <setdict'> <htdict'> <sethalftoneproc> +% This allows us to use these procedures both for actually implementing +% sethalftone and for converting subsidiary dictionaries of HalftoneType 5 +% halftones. +systemdict begin +15 dict /.halftonetypes 1 index def begin + 1 { + mark exch /Default exch .dicttomark { .sethalftone5 } + } bind def + 2 { + 1 { /Frequency /Angle /SpotFunction } { + /RedFrequency /RedAngle /RedSpotFunction + /GreenFrequency /GreenAngle /GreenSpotFunction + /BlueFrequency /BlueAngle /BlueSpotFunction + /GrayFrequency /GrayAngle /GraySpotFunction + } .makehalftoneRGBV + } bind def + 3 { + mark exch /Default exch .dicttomark { .sethalftone5 } + } bind def + 4 { + 3 { /Width /Height /Thresholds } { + /RedWidth /RedHeight /RedThresholds + /GreenWidth /GreenHeight /GreenThresholds + /BlueWidth /BlueHeight /BlueThresholds + /GrayWidth /GrayHeight /GrayThresholds + } .makehalftoneRGBV + } bind def + 5 { + pop dup length dict copy + mark 1 index { + % Even HalftoneType 5 dictionaries have entries other than + % subsidiary halftone dictionaries. + dup type /dicttype ne { + 0 + } { + dup /HalftoneType .knownget not { 0 } if + } ifelse dup 5 gt { + % Stack: dict mark ... keyN dictN httypeN + % Assume that all HalftoneTypes > 5 convert to 5. + 1 index 3 1 roll + //.halftonetypes exch get exec pop /Default get + % Stack: dict mark ... keyN setdict'N htdict'N + counttomark 1 add index 3 index 4 -1 roll put + } { + pop + } ifelse + } forall .dicttomark { .sethalftone5 } + } bind def +end +end +/sethalftone { % <dict> sethalftone - + % We must create the new dictionary in the same VM as the + % operand; otherwise, invalidaccess errors may occur. + .currentglobal 1 .argindex dup gcheck .setglobal + dup //.halftonetypes 1 index /HalftoneType get + dup type /integertype ne { + /sethalftone .systemvar /typecheck signalerror + } if + .knownget not { + /sethalftone .systemvar /rangecheck signalerror + } if + exec exec + .setglobal pop +} .bind odef +% Redefine setscreen and setcolorscreen to recognize halftone dictionaries, +% and to insert the Frequency and Angle into Type 1 halftones, per +% Adobe TN 5085. +/.fixsethalftonescreen % <freq> <angle> <dict> .fix...screen + % <freq> <angle> <dict> <dict'> + { dup dup /HalftoneType get 1 eq + { dup wcheck not { dup length .copydict } if + dup /Frequency 5 index put + dup /Angle 4 index put + languagelevel 3 ge { dup /AccurateScreens dup getuserparam put } if + } + if + } bind def +/setscreen % <ignore*2> <dict> setscreen - + { dup type /dicttype eq + { .fixsethalftonescreen sethalftone pop pop pop } + { //setscreen } + ifelse + } .bind odef +/setcolorscreen % <ignore*11> <dict> setcolorscreen - + { dup type /dicttype eq + { .fixsethalftonescreen sethalftone 12 { pop } repeat } + { //setcolorscreen } + ifelse + } .bind odef +% Redefine currentscreen and currentcolorscreen to extract the Frequency +% and Angle from Type 1 halftones, per Adobe TN 5085. +/.fixcurrenthalftonescreen % <dict> .fix... <freq> <angle> <proc> + { dup /HalftoneType get 1 eq + { dup /Frequency get 1 index /Angle get } + { 60.0 0.0 } % Adobe returns these as reals + ifelse 3 2 roll + } bind def +/currentscreen % - currentscreen 60 0 <dict> + { .currenthalftone + { { .fixcurrenthalftonescreen } % halftone + { } % screen + { 12 3 roll 9 { pop } repeat % colorscreen + dup type /dicttype eq { .fixcurrenthalftonescreen } if + } + } + exch get exec + } odef +/currentcolorscreen % - currentcolorscreen (60 0 <dict>)*4 +{ .currenthalftone + { { .fixcurrenthalftonescreen 3 copy 6 copy } % halftone + { % screen + % The procedure might not be readable.... + dup rcheck { dup length array copy cvx } if + 3 copy 6 copy + } + { } % colorscreen + } + exch get exec +} odef + +% ------ User objects ------ % + +/.UserObjects { + .userdict /UserObjects +} odef +% In order to get proper error recovery behavior, we need to be careful +% not to pop any operands from the stack until we're done. +% The code below faithfully duplicates the apparent array-growing +% behavior of Adobe interpreters. +/defineuserobject { % <index> <value> defineuserobject - + 1 index 65535 gt { + % .localvmarray throws limitcheck but CET 31-02 wants rangecheck + /defineuserobject .systemvar /rangecheck signalerror + } if + .UserObjects .knownget { + length dup 3 .argindex le { + % Stack: index value len + 2 index eq { 1 index 2 mul } { 1 index 1 add } ifelse + .localvmarray .UserObjects get + 1 index copy pop + .UserObjects 3 -1 roll put + } { + pop + } ifelse + } { + .UserObjects 3 .argindex 1 add 10 .max .localvmarray put + } ifelse + .UserObjects get 2 .argindex 2 index put pop pop +} odef +/execuserobject { % <index> execuserobject - + dup type /integertype ne { + % Adobe validates the argument before accessing UserObjects - CET 31-03 + /execuserobject .systemvar /typecheck signalerror + } if + .UserObjects get 1 .argindex get exch pop exec +} odef +/undefineuserobject { % <index> undefineuserobject - + dup type /integertype ne { + % Adobe validates the argument before accessing UserObjects - CET 31-11 + /undefineuserobject .systemvar /typecheck signalerror + } if + .UserObjects get 1 .argindex //null put pop +} odef + +% ------ Cache control ------ % + +% Dummy definitions for cache control operators + +/ucachestatus { % - ucachestatus -mark- ? ? ? ? <size> + mark 0 0 0 0 /MaxUPathItem getuserparam +} odef +/setucacheparams { % -mark- ... <size> setucacheparams - + % Provoke an appropriate error if needed. + counttomark 1 lt { () 0 get } if + dup 0 or /MaxUPathItem getuserparam .max + 1 dict dup /MaxUPathItem 4 -1 roll put setuserparams cleartomark +} odef + +end % level2dict diff --git a/gs/Resource/Init/gs_dscp.ps b/gs/Resource/Init/gs_dscp.ps new file mode 100644 index 000000000..fdc893221 --- /dev/null +++ b/gs/Resource/Init/gs_dscp.ps @@ -0,0 +1,118 @@ +% Copyright (C) 2000 Artifex Software Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Postscript interface routines to DSC parser + +/send_orientation { % <orientation> send_orientation - + % .parse_dsc_comments returns -1 for an Orientation key with an + % unrecognized value. + dup 0 ge { + << /Orientation 2 index >> setpagedevice + } if pop +} bind def + +% This dictionary contains local handlers for DSC comments. +% See header in zdscpars.c for more information. +% <dsc_dict> handler <dsc_dict> +/DSCparseprocs mark + /Orientation { dup /Orientation get send_orientation } bind + /PageOrientation { dup /PageOrientation .knownget { send_orientation } + { dup /Orientation .knownget { send_orientation } if } + ifelse } bind + /Page { dup /Orientation .knownget { send_orientation } if } bind + /NOP { } bind +.dicttomark readonly def + +% This procedure is called whenever a DSC comment is found by the interpreter +/do_parse_dsc false def +/parse_dsc { % <file> <DSC string> [<prev proc>] + % parse_dsc - + % Run any previously installed parser. + 0 get dup null eq { pop } { 3 copy exec pop } ifelse + + do_parse_dsc { % Check if this parser is enabled + currentglobal true setglobal % Go to global VM, save old state + 3 1 roll % Put old VM state under <file> <string> + dsc_dict exch % <VM state> <file> <dict> <string> + .parse_dsc_comments % <VM state> <file> <dict> <DSC name> + 4 -1 roll % Get old VM state from under <file> <dict> <DSC name> + setglobal % restore previous VM state + //DSCparseprocs exch .knownget { % Check DSC name against local handler list + exec % execute any local handler + } if + } if + pop pop % remove file, dict +} bind def + + +% Check whether the currently installed parser is the one defined in this file. +/.using_parse_dsc { % - .using_parse_dsc <proc> <using?> + currentuserparams /ProcessDSCComment get + dup null eq { pop {{//null} //parse_dsc exec} } if + dup length 3 eq { + dup dup length 1 sub get /parse_dsc load eq + } { + false + } ifelse +} bind def + +% Establish a binding for dsc_dict. +userdict /dsc_dict null put + +% - dsc_init - +/dsc_init { % Initialize DSC parser + currentglobal true setglobal + /dsc_dict 50 dict store % Size must be large enough for all DSC values + dsc_dict .initialize_dsc_parser + .using_parse_dsc { + % Already using this parser. + pop + } { + % Encapsulate the previous parser. We know it is in global VM: + % allocate the new one in global VM as well. + 1 array astore + /parse_dsc load /exec load 3 array astore cvx readonly + << /ProcessDSCComment 3 -1 roll >> + setuserparams + } ifelse + setglobal + /do_parse_dsc true def +} bind def + + +% Enable the DSC parser defined in this file. +% - enable_dsc - +/enable_dsc { + dsc_init +} bind def + +% Disable the DSC parser defined in this file. +% - disable_dsc - +/disable_dsc { + % There might be another parser installed: if so, restore it. + % (If it has encapsulated our parser, we can't.) + .using_parse_dsc { + % Restore the parser we encapsulated. + 0 get 0 get + currentglobal true setglobal exch + << /ProcessDSCComment 3 -1 roll >> + exch setglobal setuserparams + } { + pop + } ifelse + % If we couldn't restore the old parser, at least disable ours. + /do_parse_dsc false def +} bind def diff --git a/gs/Resource/Init/gs_epsf.ps b/gs/Resource/Init/gs_epsf.ps new file mode 100644 index 000000000..fccd05cab --- /dev/null +++ b/gs/Resource/Init/gs_epsf.ps @@ -0,0 +1,243 @@ +% Copyright (C) 1989, 1996, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Allow the interpreter to encapsulate EPS files, to recognize MS-DOS +% EPSF file headers, and skip to the PostScript section of the file. + +% Encapsulate EPS files and optionally resize page or rescale image. +% To display an EPS file cropped to the bounding box: +% gs -dEPSCrop file.eps +% To display an EPS file scaled to fit the page: +% gs -dEPSFitPage file.eps +% To display a file without EPS encapsulation: +% gs -dNOEPS file.ps + +% When starting to process an EPS file, state is 0. +% After %%BoundingBox processed, state is 1 if OK or 2 if cropped. +% After %%HiResBoundingBox processed, state is 3 if OK or 4 if cropped. +% After %%EndComments processed, state is 5. +/EPSBoundingBoxState 5 def +/EPSBoundingBoxSetState { + //systemdict /EPSBoundingBoxState 3 -1 roll .forceput +} .bind odef % .forceput must be bound and hidden + +% Parse 4 numbers for a bounding box +/EPSBoundingBoxParse { % (llx lly urx ury) -- llx lly urx ury true OR false + mark exch + token {exch token {exch token {exch token {exch pop} if} if} if} if + counttomark + 4 eq { + 5 -1 roll pop % remove mark + true + } { + cleartomark false + } ifelse +} bind def + +% Rescale and translate to fit the BoundingBox on the page +/EPSBoundingBoxFitPage { % llx lly urx ury -- + EPSDEBUG { (gs_epsf.ps: Rescaling EPS to fit page\n) print flush } if + clippath pathbbox newpath + % translate to new origin at lower left of clippath + 3 index 3 index translate + % calculate scale to fit smaller of width or height + exch 4 -1 roll sub 3 1 roll exch sub + 4 2 roll 5 index 5 index 4 2 roll + exch 4 -1 roll sub 3 1 roll exch sub + 4 2 roll + exch 4 -1 roll div 3 1 roll exch div + 1 index 1 index lt {pop}{exch pop} ifelse + dup scale + % translate to EPS -llx,-lly + exch neg exch neg translate +} bind def + +% Crop the page to the BoundingBox +/EPSBoundingBoxCrop { % llx lly urx ury -- + EPSDEBUG { + (gs_epsf.ps: Setting pagesize from EPS bounding box\n) print flush + } if + exch 3 index sub exch 2 index sub % stack: llx lly urx-llx ury-lly + << /PageSize [ 5 -2 roll ] >> setpagedevice + neg exch neg exch translate +} bind def + + +/EPSBoundingBoxProcess { % (llx lly urx ury) state -- + //systemdict /EPSBoundingBoxState get 1 index lt { + exch EPSBoundingBoxParse + { + //systemdict /EPSCrop known { + EPSBoundingBoxCrop + } { + //systemdict /EPSFitPage known { + EPSBoundingBoxFitPage + } { + % Warn if some of the EPS file will be clipped + clippath pathbbox newpath + { % context for exit + 5 -1 roll lt { 6 { pop } repeat true exit } if + 4 -1 roll lt { 4 { pop } repeat true exit } if + 3 -1 roll gt { 2 { pop } repeat true exit } if + exch gt { true exit } if + false exit + } loop + QUIET not and /EPSBoundingBoxState .systemvar 1 and 1 eq and { + (\n **** Warning: Some of the BoundingBox for the EPS file will be clipped.) = + ( Use -dEPSCrop or -dEPSFitPage to avoid clipping.\n) = + flush + 1 add + } if + } ifelse + } ifelse + EPSBoundingBoxSetState + } { + pop % state + } ifelse + } { + pop pop + } ifelse +} bind def + +/ProcessEPSComment { % file comment -- file comment + //systemdict /EPSBoundingBoxState get 3 lt { + dup + (%%EndComments) anchorsearch { + pop pop + % ignore any following bounding boxes + 5 EPSBoundingBoxSetState + } { + (%%BoundingBox:) anchorsearch { + pop + EPSDEBUG { (gs_epsf.ps: found %%BoundingBox\n) print flush } if + 1 EPSBoundingBoxProcess + } { + (%%HiResBoundingBox:) anchorsearch { + pop + EPSDEBUG { (gs_epsf.ps: found %%HiResBoundingBox\n) print flush } if + 3 EPSBoundingBoxProcess + } { + pop % Not interested in this DSC comment + } ifelse + } ifelse + } ifelse + } if +} bind def + +% Install EPS handler for DSC comments, which we do later +/EPSBoundingBoxInit { + systemdict /NOEPS known not { + % Merge ProcessEPSComment with existing handler + /ProcessEPSComment load /exec load + currentuserparams /ProcessDSCComment get + dup null eq {pop {pop pop}} if /exec load + 4 array astore cvx readonly + << /ProcessDSCComment 3 -1 roll >> setuserparams + } if +} bind def + +/.runNoEPS /run load def + +/.runEPS { % file OR string -- + /runEPS_save save def + /runEPS_dict_count countdictstack def + /runEPS_op_count count 2 sub def + /runEPS_page_count currentpagedevice /PageCount get def + 0 EPSBoundingBoxSetState + .runNoEPS + currentpagedevice /PageCount get runEPS_page_count sub 0 eq + { /showpage load exec } if + count runEPS_op_count sub {pop} repeat + countdictstack runEPS_dict_count sub {end} repeat + runEPS_save restore +} bind def + +/run { % file OR string -- + dup type /filetype ne { (r) file } if + dup (%!PS-Adobe-) .peekstring { + (%!PS-Adobe-) eq { + dup (%!PS-Adobe-X.X EPSF-X.X) .peekstring { + (EPSF) search { + pop pop pop + EPSDEBUG {(runEPS: Found EPS\n) print flush} if + systemdict /NOEPS known { + cvx .runNoEPS + } { + cvx .runEPS + } ifelse + } { + EPSDEBUG {(runEPS: Normal DSC\n) print flush} if + pop + cvx .runNoEPS + + } ifelse + } { + EPSDEBUG {(runEPS: Short DSC\n) print flush} if + pop + cvx .runNoEPS + } ifelse + } { + EPSDEBUG {(runEPS: Not DSC\n) print flush} if + cvx .runNoEPS + } ifelse + } { + EPSDEBUG {(runEPS: Short non-DSC\n) print flush} if + pop + cvx .runNoEPS + } ifelse +} bind odef + + +% Handle DOS EPS files. + +/.runnoepsf /run load def +/.epsfheader <C5D0D3C6> def +/run + { dup type /filetype ne { (r) file } if + % Check for MS-DOS EPSF file (see Red Book p. 729). + dup ( ) .peekstring + { .epsfheader eq { dup ( ) readstring exch pop } { false } ifelse } + { pop false } + ifelse + % Stack: file true/false + { % This block is executed if the file is MS-DOS EPSF. + % Build up the little-endian byte offset and length. + 2 + { 1 0 4 + { 2 index read not { pop exit } if % if EOF, let error happen + 2 index mul add exch 256 mul exch + } + repeat exch pop exch + } + repeat + % Stack: offset length file + % Use flushfile to skip quickly to the start of the + % PostScript section. + dup 4 -1 roll 12 sub () /SubFileDecode filter flushfile + % Now interpret the PostScript. + exch () /SubFileDecode filter cvx run + } + { .runnoepsf + } + ifelse + } odef + +% rebind .runstdin to use redefined run +userdict begin +/.runstdin { + { (%stdin) run } execute0 +} bind def +end diff --git a/gs/Resource/Init/gs_fapi.ps b/gs/Resource/Init/gs_fapi.ps new file mode 100644 index 000000000..56da0fa40 --- /dev/null +++ b/gs/Resource/Init/gs_fapi.ps @@ -0,0 +1,344 @@ +% Copyright (C) 2000 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Redefine Font and CIDFont categories with FAPI-handeled fonts. + +systemdict /.FAPIavailable known { .FAPIavailable } { false } ifelse not { + (%END FAPI) .skipeof +} if + +languagelevel 2 .setlanguagelevel + +%==================================================================== +% Redefine Font category with FAPIfontmap and CIDFont with FAPIfontmap : +15 dict begin % a temporary dictionary for local binding. + +/EmbedFontObjectsQuery mark + /.EmbedFontObjects 0 +.dicttomark def + +/is_device_compatible_to_FAPI % - is_device_compatible_to_FAPI <bool> +{ currentdevice //EmbedFontObjectsQuery .getdeviceparams % <mark> <name> <value> ... + dup mark eq { + pop true + } { + exch pop exch pop 0 eq + } ifelse + % The code above assumes that only the requested parameter is rendered. + % The commented-out code below may be useful for general case. + % Keeping it for a while. + % counttomark 2 idiv { + % exch /.EmbedFontObjects eq { + % counttomark 1 add 1 roll cleartomark + % 0 eq exit + % } if + % } repeat + % dup mark eq { + % pop true + % } if +} bind def + +%----------------------------- Process FAPIconfig ----------------------- + +/Config +<< + systemdict /FAPIconfig known {/FAPIconfig .systemvar} {(FAPIconfig)} ifelse .runlibfile + /ServerOptions 2 dict +>> def +systemdict /.FAPIconfig //Config put + +() +systemdict /UFST_SSdir .knownget { + (UFST_SSdir=) exch concatstrings concatstrings +} if +systemdict /UFST_PlugIn .knownget { + 1 index length 0 ne { + exch .filenamelistseparator concatstrings exch + } if + (UFST_PlugIn=) exch concatstrings concatstrings +} if +dup length 0 ne { + //Config /ServerOptions get exch /UFST exch put +} { + pop +} ifelse + +%------------------Copy the FontEmulationProcs here : ------------------- + +/FontEmulationProcs /ProcSet findresource { + def +} forall + +currentdict /super.complete_instance currentdict /complete_instance get put + +%-----------FAPI-specific methods for category redefinition : ----------- + +/RefinePath % <FontDict> /key RefinePath <FontDict> +{ exch begin + //Config exch get + /Path exch + Path false .file_name_combine not { + exch + (Can't combine paths ) print print ( and ) print = + /RefinePath cvx /configurationerror signalerror + } if + def + currentdict end +} bind def + +/complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict> +{ //super.complete_instance exec + dup /CIDFontName known { /CIDFontPath } { /FontPath } ifelse //RefinePath exec +} bind def + +/IsMyRecord % <raw_record> -> <raw_record> bool +{ dup type /dicttype eq { dup /FAPI known } { false } ifelse +} bind def + +/IsActive % <record> IsActive <bool> +{ pop //is_device_compatible_to_FAPI exec +} bind def + +/FontRecordVirtualMethods //RecordVirtualMethodsStub dup length 2 add dict copy begin + /IsActive //IsActive def + /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> + { currentglobal 3 1 roll true setglobal + //FontOptions //complete_instance exec + 2 copy //GetSize exec + 4 3 roll setglobal + } bind def +currentdict end def + +/CIDFontRecordVirtualMethods //RecordVirtualMethodsStub dup length 3 add dict copy begin + /GetCSI //TranslateCSI def + /IsActive //IsActive def + /MakeInstance % <Name> <record> MakeInstance <Name> <Instance> <size> + { currentglobal 3 1 roll true setglobal + //CIDFontOptions //complete_instance exec + 2 copy //GetSize exec + 4 3 roll setglobal + } bind def +currentdict end def + +/ReadFCOfontmap: % <path> ReadFCOfontmap: name dict ... +{ /fontfile exch def + { + currentfile =string readline not { + pop exit + } if + dup length 0 ne { + 0 () /SubFileDecode filter + dup token not { + % A comment line + closefile + } { + dup /EndFCOfontmap cvx eq { + pop closefile exit + } if + exch dup token not { + /ReadFCOfontmap: cvx /rangecheck signalerror + } if + exch dup token not { + /StandardEncoding + } { + dup type /nametype ne { + /ReadFCOfontmap: cvx /rangecheck signalerror + } if + } ifelse + findencoding + exch dup token not { + null + } { + dup type /nametype ne { + /ReadFCOfontmap: cvx /rangecheck signalerror + } if + /Decoding findresource + } ifelse + exch closefile % index name enc dec|null + 4 3 roll % name enc dec|null index + << /Path fontfile + /FontType 1 + /FAPI /UFST + /SubfontId counttomark 2 add -1 roll + /Decoding counttomark 2 add -1 roll + dup null eq { + pop pop + } if + /Encoding counttomark 2 add -1 roll + >> % dup { exch == = } forall + } ifelse + } { + pop + } ifelse + } loop + currentdict /fontfile undef +} bind def + + +%----------------------------------The Redefintion--------------------- + +/MappedCategoryRedefiner /ProcSet findresource /Redefine get /Redefine exch def + +% Redefine the /Font category : +4 dict begin + /CategoryName /Font def + /MapFileName systemdict /FAPIfontmap known {/FAPIfontmap .systemvar} {(FAPIfontmap)} ifelse def + /VerifyMap { pop } bind def + /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> + { //IsMyRecord exec dup { + pop dup /RecordVirtualMethods //FontRecordVirtualMethods put + true + } if + } bind def +currentdict end Redefine + +% Redefine the /CIDFont category : +4 dict begin + /CategoryName /CIDFont def + /MapFileName systemdict /FAPIcidfmap known {/FAPIcidfmap .systemvar} {(FAPIcidfmap)} ifelse def + /VerifyMap { pop } bind def + /PreprocessRecord % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> <bool> + { //IsMyRecord exec dup { + pop dup /RecordVirtualMethods //CIDFontRecordVirtualMethods put + true + } if + } bind def +currentdict end Redefine + +%==================== A hook for buildfont* operators ==================== + +% The procedure .FAPIhook redirects PS fonts to FAPI on necessity. +% This depends on the following conditions : +% +% 1. If font dictionary has /FAPI entry, it is a font listed in FAPIconfig.FontPath, +% and must be build with .FAPIrebuildfont, or a copy of a font, which was +% built with .FAPIrebuildfont . +% +% 2. If the font dictionary has /PathLoad entry, and has no /FAPI entry, +% it is an installed PS font, which is described in lib/fontmap or +% in GS_FONTPATH. .loadfont inserts /PathLoad entry for this case +% (see gs_fonts.ps). +% +% Installed fonts are being loaded with GS font loader, +% the they are passed to FAPI is same way as embedded fonts are. +% We do so because UFST cannot read fonts, which don't +% follow Type 1/42 file format strongly. +% +% 3. Executing .loadfont, we place /FAPI_hook_disable in the 0th +% element of some procedure on the execution stack - see gs_fonts.ps . +% If FAPI_hook finds /FAPI_hook_disable in there, +% it knows that it is called for a disk font during +% its internal definefont. +% +% 4. If font dictionary has no /FAPI entry, and has no /Path entry, +% and if we are not in .loadfont context, it is an embedded font. +% +% 5. Two entries to be defined in lib/FAPIconfig to control the hooking of PS fonts : +% HookDiskFonts and HookEmbeddedFonts . +% They specify arrays of font types (integers) to be redirected with FAPI. +% HookDiskFonts controls disk PS fonts (which fall into (2) and (3) ). +% HookEmbeddedFonts controls fonts being embedded into documents. +% +% 7. We apply the operator .passtoFAPI for checking whether FAPI can handle a font. +% If so, we insert /FAPI entry into the font dictionary and convert it +% with .FAPIrebuildfont . Otherwise the font is handled with the native GS font renderer. + +/FAPI_hook_debug % <proc> FAPI_hook_debug - +FAPIDEBUG { {exec} } { {pop} } ifelse +bind def + +/FAPI_hook_warn % <proc> FAPI_hook_debug - +QUIET { {pop} } { {exec} } ifelse +bind def + +/FAPI_is_hook_disabled % - FAPI_is_hook_disabled <bool> +{ % checks whether execution stack contains packedarray started with /FAPI_hook_disable . + /FAPI_hook_disable /MappedCategoryRedefiner /ProcSet findresource /execstack_lookup get exec + null ne +} bind def + +/FAPIhook_aux % <string|name> <font_dict> .FAPIhook <string|name> <font> +{ % name <<font>> + { (FAPIhook ) print 1 index = } //FAPI_hook_debug exec + dup /FAPI known { + { //PrintFontRef exec ( is mapped to FAPI=) print dup /FAPI get = } //FAPI_hook_warn exec + true //.FAPIrebuildfont //ChooseDecoding exec + } { + dup /PathLoad known dup { + { (PathLoad known for the font ) print //PrintFontRef exec (.) = } //FAPI_hook_debug exec + } { + pop //FAPI_is_hook_disabled exec dup + { pop + { (FAPIhook is in .loadfont context for the font ) print //PrintFontRef exec (.) = } //FAPI_hook_debug exec + true + } if + } ifelse + { /HookDiskFonts } { /HookEmbeddedFonts } ifelse + //Config exch get % name <<font>> [types] + 1 index //GetFontType exec //FindInArray exec % name <<font>> bHook + { { (Trying to render the font ) print //PrintFontRef exec ( with FAPI...) = } //FAPI_hook_debug exec + //.FAPIpassfont { + { //PrintFontRef exec ( is being rendered with FAPI=) print dup /FAPI get = } //FAPI_hook_warn exec + false //.FAPIrebuildfont //ChooseDecoding exec + } { + { (Can't render ) print //PrintFontRef exec ( with FAPI, will do with native GS renderer.) = } //FAPI_hook_warn exec + } ifelse + } { + { (The font ) print //PrintFontRef exec ( doesn't need to render with FAPI.) = } //FAPI_hook_debug exec + } ifelse + } ifelse +} bind def + +/FAPIhook % <string|name> <font_dict> .FAPIhook <string|name> <font> +{ //is_device_compatible_to_FAPI exec + { //FAPIhook_aux exec + } { + { (FAPIhook is disabled for the current device.) = } //FAPI_hook_debug exec + } ifelse +} bind def + +% ------------------ Redefine .buildfont* with FAPI : ----------------------- + +/.buildfont1 +{ //.buildfont1 exec //FAPIhook exec +} bind % 'odef' is below. + +/.buildfont2 +{ //.buildfont2 exec //FAPIhook exec +} bind % 'odef' is below. + +/.buildfont42 +{ //.buildfont42 exec //FAPIhook exec +} bind % 'odef' is below. + +/.buildfont9 +{ //.buildfont9 exec //FAPIhook exec +} bind % 'odef' is below. + +/.buildfont10 +{ //.buildfont10 exec //FAPIhook exec +} bind % 'odef' is below. + +/.buildfont11 +{ //.buildfont11 exec //FAPIhook exec +} bind % 'odef' is below. + +end % the temporary dictionary for local binding. +odef odef odef odef odef odef + +.setlanguagelevel + +%END FAPI diff --git a/gs/Resource/Init/gs_fntem.ps b/gs/Resource/Init/gs_fntem.ps new file mode 100644 index 000000000..991697679 --- /dev/null +++ b/gs/Resource/Init/gs_fntem.ps @@ -0,0 +1,432 @@ +% Copyright (C) 2000 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% A procset for Postscript font emulation + +% The procedures must not depend on the presence of the +% procset dictionary on the dictionary stack. + +languagelevel 2 .setlanguagelevel + +%========================= Process xlatmap ==================== +mark +%% Replace 1 (xlatmap) +(xlatmap) .runlibfile +.dicttomark dup systemdict exch /.xlatmap_dict exch put + +% Convert it into a plain text to simplify the processing in C : +% *(fontkind\0\0\ *(charmap\0decoding\0) ) \0 + +() exch { + 3 1 roll =string cvs concatstrings (\0\0) concatstrings + exch + { =string cvs concatstrings (\0) concatstrings + } forall +} forall +(\0) concatstrings +systemdict exch /.xlatmap exch put + +/FontEmulationProcs 10 dict begin + +%-------------------------------Font-------------------------------- + + +/FontCommon % - font_common - +{ currentdict /PaintType known not { + /PaintType 0 def + } if + currentdict /Encoding .knownget not { + //StandardEncoding + } if + dup type /nametype eq { + /Encoding findresource + } if + /Encoding exch def +} bind def + +/FontOptions 5 dict begin + /make_procs currentdict def + /NameKey /FontName def + /TypeKey /FontType def + + 1 + { /FontMatrix [0.001 0 0 0.001 0 0] def + /FontBBox [-128 -128 1024 1024] def % zfapi.ps refines it. + /Private 0 dict def + /CharStrings << /.notdef () >> def + //FontCommon exec + } bind def + + 42 + { /FontMatrix [1 0 0 1 0 0] def + /FontBBox [0 0 1 1] def % zfapi.ps refines it. + /CharStrings <<>> def + /sfnts [<00010000 0000 0000 0000 0000 0000>] def + /GlyphDirectory [] def + //FontCommon exec + } bind def + + %fixme : more font types. + +currentdict end def + +%---------------------------CIDFont--------------------------- + +/TranslateCSI % <record> TranslateCSI <CSI> +{ RESMPDEBUG { (fntem TranslateCSI beg ) = } if + begin + CSI length 2 eq { + << /Registry (Adobe) + /Ordering CSI aload pop + /Supplement exch + >> + } { + << /Registry CSI 0 get + /Ordering CSI 1 get + /Supplement CSI 2 get + >> + } ifelse + end + RESMPDEBUG { (fntem TranslateCSI end ) = } if +} bind def + +/CIDFontCommon +{ /CIDSystemInfo currentdict //TranslateCSI exec def + currentdict /CSI undef + /FontBBox [-128 -128 1024 1024] def % zfapi.ps refines it. + /CIDCount 1 def % ChooseDecoding will set a reasonable value. +} bind def + +% GFlyph substitution table for narrow, wide, proportional glyphs - +% used with TrueTypes. + +currentpacking false setpacking +/SubstNWP << + + % Array format : orig_type, beg_CID, end_CID, subst_beg_CID, subst_type + % type = (n==narrow, w==wide, p==proportional). + + /Japan1 + { p 1 94 231 n + + p 17 26 780 w + p 34 59 790 w + p 66 91 816 w + w 842 842 7918 w % fixme: These substitutions require to shift the glyph origin. + w 844 844 7919 w + w 846 846 7920 w + w 848 848 7921 w + w 850 850 7922 w + w 876 876 7923 w + w 908 908 7924 w + w 910 910 7925 w + w 912 912 7926 w + w 914 914 7927 w + w 925 925 7928 w + w 927 927 7929 w + w 929 929 7930 w + w 931 931 7931 w + w 933 933 7932 w + w 959 959 7933 w + w 991 991 7934 w + w 993 993 7935 w + w 995 995 7936 w + w 1002 1002 7937 w + w 1009 1009 7938 w + w 1010 1010 7939 w + } cvlit + + /Japan2 1 index + + /CNS1 + { p 1 94 13648 n + + p 17 26 333 w + p 34 59 365 w + p 66 91 391 w + } cvlit + + /GB1 + { p 2 94 814 n + + p 2 94 262 w + + p 1 1 7716 n + } cvlit + + /Korea1 + { p 1 60 8094 n + p 62 94 8155 n + + p 2 59 264 w + p 63 94 325 w + } cvlit + + /Identity [] + + /Unicode [] + +>> def +setpacking + +/CIDFontOptions 5 dict begin + /make_procs currentdict def + /NameKey /CIDFontName def + /TypeKey /CIDFontType def + + 0 + { //CIDFontCommon exec + /FDArray [ + 14 dict begin + /FontName CIDFontName =string cvs (%) concatstrings cvn def + /FontType 1 def + /FontMatrix [0.001 0 0 0.001 0 0 ] def + /PaintType 0 def + /Private 0 dict def + currentdict + end + ] def + /GlyphDirectory [] def + /GDBytes 1 def + /FDBytes 0 def + } bind def + + 1 + { //CIDFontCommon exec + /FontMatrix [1 0 0 1 0 0] def + /BuildGlyph {} def + } bind def + + 2 + { //CIDFontCommon exec + /FontMatrix [1 0 0 1 0 0] def + /GDBytes 2 def + /CIDMap <0000> def + /sfnts [<00010000 0000 0000 0000 0000 0000>] def + /Encoding [] def + /CharStrings << /.notdef 0 >> def + } bind def + +currentdict end def + +/complete_instance % <font_name> <FontDict> <Options> complete_FAPI_Font <font_name> <FontDict> +{ begin + dup length dict copy + begin + dup type /nametype ne { cvn } if + dup NameKey exch def + currentglobal true setglobal + make_procs TypeKey load .knownget { + exec + } { setglobal + /complete_instance cvx /invalidfont signalerror + } ifelse + setglobal + currentdict end + end +} bind def + +/GetFilePath % <scratch> <Name> <record> GetFilePath <filepath> +{ exch pop % (scratch) <record> + /Path get % (scratch) (path) + exch copy + % What we make here it is not a complete PS resource. + % Unable to provide full conformity : + % the attempt to run this file may fail. +} bind def + +/GetSize % <Name> <record> GetSize <size> +{ pop pop -1 % Unknown size. + % fixme: probably we could provide an estimation size for some fonts. +} bind def + +/RecordVirtualMethodsStub 3 dict begin + /GetFilePath //GetFilePath def + /GetSize //GetSize def +currentdict end def + +% ---------------------- Decoding helpers ---------------------------- + +/encodingnames mark + StandardEncoding /StandardEncoding + ISOLatin1Encoding /ISOLatin1Encoding + SymbolEncoding /SymbolEncoding + DingbatsEncoding /DingbatsEncoding + /resourceforall where { + pop (*) { dup cvn + EncodingDirectory exch .knownget not { + % A work around bug 688710 on Linux : + % findencoding can't load resource files until gs_init.ps executes .fixresources . + % It will happen after gs_init.ps runs INITFILES, + % from which the current file runs. + % Windows build has no such problem. + (.svn) anchorsearch { + % HACK : skip .svn or */* names, which are subdirectories. + pop pop + } { + (/) search { + pop pop pop + } { + cvn dup /Encoding findresource + } ifelse + } ifelse + } { + exch cvn exch + } ifelse + exch + } 1024 string /Encoding resourceforall + } if +.dicttomark def + +/ChooseDecoding % <font> ChooseDecoding <font> +{ { % A loop for 'exit' context. + dup /Decoding .knownget { + dup type /nametype eq { + 1 index /CIDFontType known { /CIDDecoding } { /Decoding } ifelse + findresource 1 index exch /Decoding exch put + } { + pop + } ifelse + dup /CIDFontType known { + dup dup /Decoding get /CIDCount get /CIDCount exch put + } if + exit + } if + dup /CIDFontType known { + % This is a hooked CID font, no need for Decoding. + exit + } if + % This works when the renderer can't choose character by name, + % and we cannot determine the charset. + % Probably this branch is to be removed after UFST problem is fixed. + dup /Encoding get % <<font>> encoding + dup type /nametype eq { + /Decoding findresource 1 index exch /Decoding exch put + } { + dup //encodingnames + exch .knownget { + exch pop + /Decoding findresource 1 index exch /Decoding exch put + } { + % unknown encoding, convert it to decoding : + dup length dict begin + /.notdef 0 def + 0 1 currentdict length 1 sub + { dup 2 index exch get + dup /.notdef ne { + exch def + } { + pop pop + } ifelse + } for + pop + currentdict end + 1 index exch /Decoding exch put + } ifelse + } ifelse + exit + } loop + dup /CIDFontType known { + dup /SubstNWP .knownget not { + dup /CIDSystemInfo get /Ordering get cvn + } if + dup type /nametype eq { + //SubstNWP exch .knownget not { + [] + } if % <<font>> [SubstNWP] + } if + 1 index exch /SubstNWP exch put + } if +} bind def + +/PrintFontRef % <string|name> <font> PrintFontRef <string|name> <font> +{ dup /FontName known { (Font ) } { (CIDFont ) } ifelse print + 1 index =string cvs print + dup /FontName .knownget not { + dup /CIDFontName get + } if % <string|name> <font> <fontname> + dup 3 index ne { + ( \( aliased from ) print + =string cvs print ( \)) print + } { + pop + } ifelse +} bind def + +/GetFontType % <font> GetFontType int +{ dup /CIDFontType .knownget { + exch pop 9 add + } { + /FontType get + } ifelse +} bind def + +/FindInArray % <array> <elem> .array_find <bool> +{ false 3 1 roll + exch { % false elem elem_i + 1 index eq { % false elem + pop true exch + } if + } forall + pop +} bind def + +/ProvideUnicodeDecoding % <font> ProvideUnicodeDecoding <font> +{ + % If the font is maintained by FAPI, or if it is TT-emulated CID font, + % it already has /Decoding. But its value isn't guaranteeed to + % be an Unicode decoding. Since we can't determine whether + % it is an Unicode decoding, we unconditionally load an appropriate Unicode decoding + % and attach it with /GlyphNames2Unicode entry. + % + % Another interesting case is when the font already has /GlyphNames2Unicode. + % The latter to be used instead. Note that /GlyphNames2Unicode + % appears only when type 32 fonts are disable (see .pdf_hook_DSC_Creator), + % but an automatic disabling is not implemented yet. + + currentglobal true setglobal exch + dup /FontInfo known not { + dup /FontInfo 1 dict put + } if + { % A loop just for 'exit' context. + dup /FontInfo get /GlyphNames2Unicode known { + exit + } if + dup /CIDFontType known { + dup mark exch % bool <font> [ <font> + dup /CIDSystemInfo get /Ordering get (.Unicode) % bool <font> [ <font> () () + concatstrings cvn % bool <font> [ <font> /Name + /CIDDecoding { findresource } stopped { + % Can't provide a decoding, giving up without creating /GlyphNames2Unicode. + cleartomark exit + } if % bool <font> [ <font> <D> + exch /FontInfo get exch % bool <font> [ <FI> <D> + /GlyphNames2Unicode exch + .forceput % FontInfo can be read-only. + pop % bool <font> + exit + } if + dup /FontInfo get % bool <font> <FI> + /GlyphNames2Unicode /Unicode /Decoding findresource + .forceput % FontInfo can be read-only. + exit + } loop + exch setglobal +} bind def + +currentdict end /ProcSet defineresource pop + +.setlanguagelevel diff --git a/gs/Resource/Init/gs_fonts.ps b/gs/Resource/Init/gs_fonts.ps new file mode 100644 index 000000000..a41021690 --- /dev/null +++ b/gs/Resource/Init/gs_fonts.ps @@ -0,0 +1,1223 @@ +% Copyright (C) 1990-2003 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Font initialization and management code. + +% Define the default font. +/defaultfontname /Courier def + +% Define the name of the font map file. +% Note that the "%%Replace " comment below provides the font map file name +% for compiling initialization files into executable. Most likely it should be +% consistent with the one specified here. +/defaultfontmap (Fontmap) def + +/defaultfontmap_content 50 dict +1 dict begin +/; { 2 index 3 1 roll .growput } bind def +%% Replace 0 (Fontmap) +end def + +% ------ End of editable parameters ------ % + +% Define the UniqueIDs and organization XUID assigned to Aladdin. +% UniqueIDs 5,066,501 - 5,066,580 are assigned as follows: +% 01 and 02 for shareware Cyrillic +% 33 through 67 for Type 1 versions of the Hershey fonts +% UniqueIDs 5,115,501 - 5,115,600 are currently unassigned. +/AladdinEnterprisesXUID 107 def + +% If SUBSTFONT is defined, make it the default font. +/SUBSTFONT where { pop /defaultfontname /SUBSTFONT load def } if + +% Define a reliable way of accessing FontDirectory in systemdict. +/.FontDirectory +{ /FontDirectory .systemvar +} .bind odef + +% If DISKFONTS is true, we load individual CharStrings as they are needed. +% (This is intended primarily for machines with very small memories.) +% In this case, we define another dictionary, parallel to FontDirectory, +% that retains an open file for every font loaded. +/FontFileDirectory 10 dict def + +% Define a temporary string for local use, since using =string +% interferes with some PostScript programs. +/.fonttempstring 8192 string def + +% Split up a search path into individual directories or files. +/.pathlist % <path> .pathlist <dir1|file1> ... + { { dup length 0 eq { pop exit } if + .filenamelistseparator search not { exit } if + exch pop exch + } + loop + } bind def + +% Load a font name -> font file name map. +userdict /Fontmap .FontDirectory maxlength dict put +/.loadFontmap { % <file> .loadFontmap - + % We would like to simply execute .definefontmap as we read, + % but we have to maintain backward compatibility with an older + % specification that makes later entries override earlier + % ones within the same file. + 50 dict exch .readFontmap + { .definefontmap } forall +} bind def +/.readFontmap { % <dict> <file> .readFontmap <dict> + { dup token not { closefile exit } if + % stack: dict file fontname + % This is a hack to get around the absurd habit of MS-DOS editors + % of adding an EOF character at the end of the file. + dup (\032) eq { pop closefile exit } if + 1 index token not + { (Fontmap entry for ) print dup =only + ( has no associated file or alias name! Giving up.) = flush + {.readFontmap} 0 get 1 .quit + } if + dup type dup /stringtype eq exch /nametype eq or not + { (Fontmap entry for ) print 1 index =only + ( has an invalid file or alias name! Giving up.) = flush + {.readFontmap} 0 get 1 .quit + } if + % stack: dict file fontname filename|aliasname + 1 index type /stringtype eq + 1 index type /nametype eq and 1 index xcheck and + 1 index /run eq 2 index /.runlibfile eq or and { + % This is an inclusion entry. + pop findlibfile { exch pop } { file } ifelse + 2 index exch .readFontmap pop + } { + % This is a real entry. + % Read and pop tokens until a semicolon. + { 2 index token not + { (Fontmap entry for ) print 1 index =only + ( ends prematurely! Giving up.) = flush + {.loadFontmap} 0 get 1 .quit + } if + dup /; eq { pop 3 index 3 1 roll .growput exit } if + pop + } loop + } ifelse + } loop +} bind def +% Add an entry in Fontmap. We redefine this if the Level 2 +% resource machinery is loaded. +/.definefontmap % <fontname> <file|alias> .definefontmap - + { % Since Fontmap is global, make sure the values are storable. + % If the fontname contains Unicode (first byte == \000) and + % this is not an alias definition, define an alias using ASCII + % (stripping out the high \000 bytes). Observed with some TT fonts. + 1 index 100 string cvs + dup length 0 gt { + 0 get 0 eq 1 index type /nametype ne and { + 1 index 100 string cvs dup length 2 div cvi string true exch + 0 1 2 index length 1 sub { + % stack: fontname filename fontnamestring addflag newstring index + dup 4 index exch 2 mul get 0 ne { + % High byte of pair is not \000 + pop pop false exch + exit + } if + dup 4 index exch 2 mul 1 add get 2 index 3 1 roll put + } for + exch { + DEBUG { (\nAdding alias for: ) print 1 index ==only ( as: ) print dup == flush } if + cvn exch cvn .definefontmap % recurse with an alias + } { + pop pop % discard the name + } ifelse + } if + } { + pop + } ifelse + .currentglobal 3 1 roll true .setglobal + dup type /stringtype eq + { dup .gcheck not { dup length string copy } if + } + if + Fontmap 3 -1 roll 2 copy .knownget + { % Add an element to the end of the existing value, + % unless it's the same as the current last element. + mark exch aload pop counttomark 4 add -1 roll + 2 copy eq { cleartomark pop pop } { ] readonly .growput } ifelse + } + { % Make a new entry. + mark 4 -1 roll ] readonly .growput + } + ifelse .setglobal + } bind def + +% Parse a font file just enough to find the FontName or FontType. +/.findfontvalue { % <file> <key> .findfontvalue <value> true + % <file> <key> .findfontvalue false + % Closes the file in either case. + exch dup read { + 2 copy unread 16#80 eq { + dup (xxxxxx) readstring pop pop % skip .PFB header + } if + { % Stack: key file + % Protect ourselves against syntax errors here. + dup { token } stopped { pop false exit } if + not { false exit } if % end of file + dup /eexec eq { pop false exit } if % reached eexec section + dup /Subrs eq { pop false exit } if % Subrs without eexec + dup /CharStrings eq { pop false exit } if % CharStrings without eexec + dup 3 index eq + { xcheck not { dup token exit } if } % found key + { pop } + ifelse + } loop + % Stack: key file value true (or) + % Stack: key file false + dup { 4 } { 3 } ifelse -2 roll closefile pop + } { closefile pop false } ifelse +} bind def +/.findfontname + { /FontName .findfontvalue + } bind def + +% If there is no FONTPATH, try to get one from the environment. +NOFONTPATH { /FONTPATH () def } if +/FONTPATH where + { pop } + { /FONTPATH (GS_FONTPATH) getenv not { () } if def } +ifelse +FONTPATH length 0 eq { (%END FONTPATH) .skipeof } if +/FONTPATH [ FONTPATH .pathlist ] def + +% Scan directories looking for plausible fonts. "Plausible" means that +% the file begins with %!PS-AdobeFont or %!FontType1, or with \200\001 +% followed by four arbitrary bytes and then either of these strings. +% To speed up the search, we skip any file whose name appears in +% the Fontmap (with any extension and upper/lower case variation) already, +% and any file whose extension definitely indicates it is not a font. +% +% NOTE: The current implementation of this procedure is somewhat Unix/DOS- +% specific. It assumes that '/' and '\' are directory separators, and that +% the part of a file name following the last '.' is the extension. +% +/.lowerstring % <string> .lowerstring <lowerstring> + { 0 1 2 index length 1 sub + { 2 copy get dup 65 ge exch 90 le and + { 2 copy 2 copy get 32 add put } + if pop + } + for + } bind def +/.splitfilename { % <dir.../base.extn> .basename <base> <extn> + % Make the file name read-only to detect aliasing bugs. + % We really don't like doing this, but we've had one + % such bug already. + readonly { + (/) search { true } { (\\) search } ifelse { pop pop } { exit } ifelse + } loop + dup { (.) search { pop pop } { exit } ifelse } loop + 2 copy eq { + pop () + } { + exch dup length 2 index length 1 add sub 0 exch getinterval exch + } ifelse +} bind def +/.scanfontdict 1 dict def % establish a binding +/.scanfontbegin + { % Construct the table of all file names already in Fontmap. + currentglobal true setglobal + .scanfontdict dup maxlength Fontmap length 2 add .max .setmaxlength + Fontmap + { exch pop + { dup type /stringtype eq + { .splitfilename pop .fonttempstring copy .lowerstring cvn + .scanfontdict exch true put + } + { pop + } + ifelse + } + forall + } + forall + setglobal + } bind def +/.scanfontskip mark + % Strings are converted to names anyway, so.... + /afm true + /bat true + /c true + /cmd true + /com true + /dir true + /dll true + /doc true + /drv true + /exe true + /fon true + /fot true + /h true + /o true + /obj true + /pfm true + /pss true % Adobe Multiple Master font instances + /txt true +.dicttomark def +/.scan1fontstring 8192 string def +% %%BeginFont: is not per Adobe documentation, but a few fonts have it. +/.scanfontheaders [(%!PS-Adobe*) (%!FontType*) (%%BeginFont:*)] def +0 .scanfontheaders { length .max } forall 6 add % extra for PFB header +/.scan1fontfirst exch string def +/.scanfontdir % <dirname> .scanfontdir - + { currentglobal exch true setglobal + QUIET not { (Scanning ) print dup print ( for fonts...) print flush } if + [ 1 index ] (*) .generate_dir_list_templates + 0 0 0 4 -1 roll % found scanned files + { % stack: <fontcount> <scancount> <filecount> <filename> + exch 1 add exch % increment filecount + dup .splitfilename .fonttempstring copy .lowerstring + % stack: <fontcount> <scancount> <filecount+1> <filename> + % <BASE> <ext> + .scanfontskip exch known exch .scanfontdict exch known or + { pop + % stack: <fontcount> <scancount> <filecount+1> + } + { 3 -1 roll 1 add 3 1 roll + % stack: <fontcount> <scancount+1> <filecount+1> <filename> + dup (r) { file } .internalstopped + { pop pop null () + % stack: <fontcount> <scancount+1> <filecount+1> <filename> + % null () + } + { + % On some platforms, the file operator will open directories, + % but an error will occur if we try to read from one. + % Handle this possibility here. + dup .scan1fontfirst { readstring } .internalstopped + { pop pop () } + { pop } + ifelse + % stack: <fontcount> <scancount+1> <filecount+1> + % <filename> <file> <header> + } + ifelse + % Check for PFB file header. + dup (\200\001????*) .stringmatch + { dup length 6 sub 6 exch getinterval } + if + % Check for font file headers. + false .scanfontheaders + { 2 index exch .stringmatch or + } + forall exch pop + { % stack: <fontcount> <scancount+1> <filecount+1> <filename> + % <file> + dup 0 setfileposition .findfontname + { dup Fontmap exch known + { pop pop + } + { exch copystring exch + DEBUG { ( ) print dup =only flush } if + 1 index .definefontmap + .splitfilename pop true .scanfontdict 3 1 roll .growput + % Increment fontcount. + 3 -1 roll 1 add 3 1 roll + } + ifelse + } + { pop + } + ifelse + } + % .findfontname will have done a closefile in the above case. + { dup null eq { pop } { closefile } ifelse pop + } + ifelse + } + ifelse + } + .scan1fontstring filenameforall + QUIET + { pop pop pop } + { ( ) print =only ( files, ) print =only ( scanned, ) print + =only ( new fonts.) = flush + } + ifelse + pop + setglobal + } bind def + +%END FONTPATH + +% Try to enumerate native fonts registered with the os +% and add them to the fontmap. This relies on a custom +% operator which calls platform-specific C code. It +% returns an array of arrays, each containing a pair +% of strings: what the system thinks is the ps name, +% and the access path. +/.setnativefontmapbuilt { % set whether we've been run + systemdict exch /.nativefontmapbuilt exch .forceput +} .bind executeonly def +false .setnativefontmapbuilt +/.buildnativefontmap { % - .buildnativefontmap <bool> + QUIET not { + (Querying operating system for font files...\n) + print flush + } if + .getnativefonts dup + { + exch + { + % stack: [ (name) (path) ] + % verify the font name ourselves + dup 1 get (r) { file } stopped + { + % skip the entry if we can't open the returned path + pop pop pop + }{ + % we could open the font file + .findfontname + not { dup 0 get } if % stack: (newname) [ (name) (path) ] + % DEBUG { ( found ) print dup print (\n) print flush } if + % add entry to the fontmap + 1 index exch 0 exch dup type /nametype ne {cvn} if put + aload pop .definefontmap + } ifelse + } forall + } if + % record that we've been run + true .setnativefontmapbuilt +} bind def + +% Create the dictionary that registers the .buildfont procedure +% (called by definefont) for each FontType. +/buildfontdict 20 dict def + +% Register Type 3 fonts, which are always supported, for definefont. +buildfontdict 3 /.buildfont3 cvx put + +% Register Type 0 fonts if they are supported. Strictly speaking, +% we should do this in its own file (gs_type0.ps), but since this is +% the only thing that would be in that file, it's simpler to put it here. +/.buildfont0 where { pop buildfontdict 0 /.buildfont0 cvx put } if + +% Define definefont. This is a procedure built on a set of operators +% that do all the error checking and key insertion. +/.growfontdict + { % Grow the font dictionary, if necessary, to ensure room for an + % added entry, making sure there is at least one slot left for FID. + dup maxlength 1 index length sub 2 lt + { dup dup wcheck + { .growdict } + { .growdictlength dict .copydict } + ifelse + } + { dup wcheck not { dup maxlength dict .copydict } if + } + ifelse + } bind def +/.completefont { + { % Check for disabled platform fonts. + NOPLATFONTS + { % Make sure we leave room for FID. + .growfontdict dup /ExactSize 0 put + } + { % Hack: if the Encoding looks like it might be the + % Symbol or Dingbats encoding, load those now (for the + % benefit of platform font matching) just in case + % the font didn't actually reference them. + % Note that some types of font don't have an Encoding. + dup /Encoding .knownget { + dup length 65 ge { + 64 get + dup /congruent eq { SymbolEncoding pop } if + /a9 eq { DingbatsEncoding pop } if + } { + pop + } ifelse + } if + } + ifelse + dup /OrigFont known not { + dup dup /OrigFont exch .growput + } if + true exch + % If this is a CIDFont, CIDFontType takes precedence + % over FontType. + dup /CIDFontType known { + /.buildcidfont where { + pop exch not exch % true => false + } if + } if + exch { + dup /FontType get //buildfontdict exch get + } { + {.buildcidfont} % so it gets bound + } ifelse + } stopped { $error /command get /invalidfont signalerror } if + + % Execute the .buildxxxfontx outside the 'stopped', because we don't + % want its errors converted to invalidfont. + exec + + { + + DISKFONTS { + FontFileDirectory 2 index known { + dup /FontFile FontFileDirectory 4 index get .growput + } if + } if + systemdict /ProvideUnicode .knownget not { false } if { + /FontEmulationProcs /ProcSet findresource + /ProvideUnicodeDecoding get exec + } if + readonly % stack: name fontdict + } stopped { $error /command get /invalidfont signalerror } if +} bind def +/definefont + { dup rcheck not { + /definefont cvx /invalidaccess signalerror + } if + /definefont cvx {.completefont} .errorexec + % If the current allocation mode is global, also enter + % the font in LocalFontDirectory. + .currentglobal + { //systemdict /LocalFontDirectory .knownget + { 2 index 2 index { .growput } //superexec } % readonly + if + } + if + dup .FontDirectory 4 -2 roll { .growput } //superexec % readonly + % If the font originated as a resource, register it. + currentfile .currentresourcefile eq { dup .registerfont } if + readonly + } odef + +% Define a procedure for defining aliased fonts. +% We use this only for explicitly aliased fonts, not substituted fonts: +% we think this matches the observed behavior of Adobe interpreters. +/.aliasfont % <name> <font> .aliasfont <newFont> + { .currentglobal 3 1 roll dup .gcheck .setglobal + % <bool> <name> <font> + dup length 2 add dict % <bool> <name> <font> <dict> + dup 3 -1 roll % <bool> <name> <dict> <dict> <font> + { 1 index /FID eq { pop pop } { put dup } ifelse } forall + % <bool> <name> <dict> <dict> + % Stack: global fontname newfont newfont. + % We might be defining a global font whose FontName + % is a local string. This is weird, but legal, + % and doesn't cause problems anywhere else: + % to avoid any possible problems in this case, do a cvn. + % We might also be defining (as an alias) a global font + % whose FontName is a local non-string, if someone passed a + % garbage value to findfont. In this case, just don't + % call definefont at all. + 2 index dup type /stringtype eq exch .gcheck or 1 index .gcheck not or + { pop % <bool> <name> <dict> + 1 index dup type /stringtype eq { cvn } if + % <bool> <name> <dict> <name1> + % HACK: + % We want to know whether we alias a font, + % because in this case its FontName to be replaced with the alias. + % There is no simple way to know that at this point. + % But if the original font has defaultfontname, + % we probably substitute it rather than alias. + % Using such condition as an approximation to the strong condition. + % + % Note it works wrongly if Fontmap maps something to defaultfontname like this : + % /Courier /NimbusMonL-Regu ; + % /Something /Courier ; + % The FontName of Something will not be /Something. It will be /Courier . + % + 1 index /FontName get defaultfontname ne { + 2 copy /FontName exch put + } if + 1 index exch /.Alias exch put % <bool> <name> <dict> + dup dup /OrigFont exch .growput + % Don't bind in definefont, since Level 2 redefines it. + /definefont .systemvar exec + } + { /findfont cvx {.completefont} .errorexec pop exch pop + } + ifelse + exch .setglobal + } odef % so findfont will bind it + +% Define .loadfontfile for loading a font. If we recognize Type 1 and/or +% TrueType fonts, gs_type1.ps and/or gs_ttf.ps will redefine this. +/.loadfontfile { + % According to Ed Taft, Adobe interpreters push userdict + % before loading a font, and pop it afterwards. + userdict begin + cvx exec + end +} bind def +/.setloadingfont { + //systemdict /.loadingfont 3 -1 roll .forceput +} .bind odef % .forceput must be bound and hidden +/.loadfont + { % Some buggy fonts leave extra junk on the stack, + % so we have to make a closure that records the stack depth + % in a fail-safe way. + true .setloadingfont + { /FAPI_hook_disable pop % gs_fapi accesses this with execstack_lookup - don't remove ! + {{.loadfontfile} .execasresource} count 1 sub 2 .execn + count exch sub { pop } repeat + exit + } loop % this loop is a pattern for execstack_lookup, don't remove ! + false .setloadingfont + } bind def + +% Find an alternate font to substitute for an unknown one. +% We go to some trouble to parse the font name and extract +% properties from it. Later entries take priority over earlier. +/.substitutefaces [ + % Guess at suitable substitutions for random unknown fonts. + [(Book) /NewCenturySchlbk 0] + [(Grot) /Helvetica 0] + [(Roman) /Times 0] + [(Chancery) /ZapfChancery-MediumItalic 0] + % If the family name appears in the font name, + % use a font from that family. + [(Arial) /Helvetica 0] + [(Avant) /AvantGarde 0] + [(Bookman) /Bookman 0] + [(Century) /NewCenturySchlbk 0] + [(Cour) /Courier 0] + [(Frut) /Helvetica 0] + [(Garamond) /Palatino 0] + [(Geneva) /Helvetica 0] + [(Helv) /Helvetica 0] + [(NewYork) /Bookman 0] + [(Pala) /Palatino 0] + [(Schlbk) /NewCenturySchlbk 0] + [(Swiss) /Helvetica 0] + [(Symbol) /Symbol 0] + [(Times) /Times 0] + % Substitute for Adobe Multiple Master fonts. + [(Minion) /Times 0] + [(Myriad) /Helvetica 0] + % If the font wants to be monospace, use Courier. + [(Monospace) /Courier 0] + [(Typewriter) /Courier 0] + % Define substitutes for the other Adobe PostScript 3 fonts. + % For some of them, the substitution is pretty bad! + [(Albertus) /Palatino 0] + [(AntiqueOlive) /Helvetica 0] + [(Bodoni) /NewCenturySchlbk 0] + [(Chicago) /Helvetica 2] + [(Clarendon) /Bookman 0] + [(Cooper) /NewCenturySchlbk 0] + [(Copperplate) /AvantGarde 0] % inappropriate, small-cap font + [(Coronet) /ZapfChancery-MediumItalic 0] + [(Eurostile) /Helvetica 0] + [(Geneva) /Courier 2] % should be fixed-pitch sans demi + [(GillSans) /Helvetica 2] + [(GillSans-Light) /Helvetica 0] + [(Goudy) /Palatino 0] + [(Hoefler) /NewCenturySchlbk 0] + [(Joanna) /Times 0] + [(LetterGothic) /Courier 0] % should be fixed-pitch sans + [(LubalinGraph-Book) /Bookman 2] + [(LubalinGraph-Demi) /Bookman 0] + [(Marigold) /ZapfChancery-MediumItalic 0] + [(MonaLisa-Recut) /Palatino 0] % inappropriate + [(Monaco) /Courier 2] % should be fixed-pitch sans demi + [(Optima) /Helvetica 0] + [(Oxford) /ZapfChancery-MediumItalic 0] + [(Tekton) /Helvetica 0] + [(Univers) /Helvetica 0] +] readonly def +/.substituteproperties [ + [(It) 9] [(Oblique) 1] + [(Black) 2] [(Bd) 2] [(Bold) 2] [(bold) 2] [(Demi) 2] [(Heavy) 2] [(Sb) 2] + [(Cn) 4] [(Cond) 4] [(Narrow) 4] [(Pkg) 4] [(Compr) 4] + [(Serif) 8] [(Sans) -8] +] readonly def +/.fontnameproperties { % <int> <string|name> .fontnameproperties + % <int'> + .fontnamestring + .substituteproperties { + 2 copy 0 get search { + pop pop pop dup length 1 sub 1 exch getinterval 3 -1 roll exch { + dup 0 ge { or } { neg not and } ifelse + } forall exch + } { + pop pop + } ifelse + } forall pop +} bind def +/.substitutefamilies mark + /AvantGarde + {/AvantGarde-Book /AvantGarde-BookOblique + /AvantGarde-Demi /AvantGarde-DemiOblique} + /Bookman + {/Bookman-Demi /Bookman-DemiItalic /Bookman-Light /Bookman-LightItalic} + /Courier + {/Courier /Courier-Oblique /Courier-Bold /Courier-BoldOblique} + /Helvetica + {/Helvetica /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique + /Helvetica-Narrow /Helvetica-Narrow-Oblique + /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique} + /NewCenturySchlbk + {/NewCenturySchlbk-Roman /NewCenturySchlbk-Italic + /NewCenturySchlbk-Bold /NewCenturySchlbk-BoldItalic} + /Palatino + {/Palatino-Roman /Palatino-Italic /Palatino-Bold /Palatino-BoldItalic} + /Symbol + {/Symbol /Symbol /Symbol /Symbol} + /Times + {/Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic} + /ZapfChancery-MediumItalic + {/ZapfChancery-MediumItalic} +.dicttomark readonly def +/.nametostring { % <name> .nametostring <string> + % <other> .nametostring <other> + dup type /nametype eq { .namestring } if +} bind def +/.fontnamestring { % <fontname> .fontnamestring <string|name> + dup type dup /nametype eq { + pop .namestring + } { + /stringtype ne { pop () } if + } ifelse +} bind def +/.substitutefontname { % <fontname> <properties> .substitutefontname + % <altname|null> + % Look for properties and/or a face name in the font name. + % If we find any, use Times (serif) or Helvetica (sans) as the + % base font; otherwise, use the default font. + % Note that the "substituted" font name may be the same as + % the requested one; the caller must check this. + exch .fontnamestring { + defaultfontname /Helvetica-Oblique /Helvetica-Bold /Helvetica-BoldOblique + /Helvetica-Narrow /Helvetica-Narrow-Oblique + /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique + /Times-Roman /Times-Italic /Times-Bold /Times-BoldItalic + /Helvetica-Narrow /Helvetica-Narrow-Oblique + /Helvetica-Narrow-Bold /Helvetica-Narrow-BoldOblique + } 3 1 roll + % Stack: facelist properties fontname + % Look for a face name. + .substitutefaces { + 2 copy 0 get search { + pop pop pop + % Stack: facelist properties fontname [(pattern) family properties] + dup 2 get 4 -1 roll or 3 1 roll + 1 get .substitutefamilies exch get + 4 -1 roll pop 3 1 roll + } { + pop pop + } ifelse + } forall pop + 1 index length mod get exec +} bind def +/.substitutefont { % <fontname> .substitutefont <altname> + dup 0 exch .fontnameproperties .substitutefontname + % Only accept fonts known in the Fontmap. + Fontmap 1 index known not { pop defaultfontname } if +} bind def + +% If requested, make (and recognize) fake entries in FontDirectory for fonts +% present in Fontmap but not actually loaded. Thanks to Ray Johnston for +% the idea behind this code. +FAKEFONTS not { (%END FAKEFONTS) .skipeof } if + +% We use the presence or absence of the FontMatrix key to indicate whether +% a font is real or fake. We must pop the arguments at the very end, +% so that stack protection will be effective. + +/definefont { % <name> <font> definefont <font> + dup /FontMatrix known { + //definefont + } { + 2 copy /FontName get findfont //definefont exch pop exch pop + } ifelse +} bind odef + +/scalefont { % <font> <scale> scalefont <font> + 1 index /FontMatrix known { + //scalefont + } { + 1 index /FontName get findfont 1 index //scalefont + exch pop exch pop + } ifelse +} bind odef + +/makefont { % <font> <matrix> makefont <font> + 1 index /FontMatrix known { + //makefont + } { + 1 index /FontName get findfont 1 index //makefont + exch pop exch pop + } ifelse +} bind odef + +/setfont { % <font> setfont - + dup /FontMatrix known { + //setfont + } { + dup /FontName get findfont //setfont pop + } ifelse +} bind odef + +%END FAKEFONTS + +% Define findfont so it tries to load a font if it's not found. +% The Red Book requires that findfont be a procedure, not an operator, +% but it still needs to restore the stacks reliably if it fails, +% so we do all the work in an operator. +/.findfont { % <fontname> .findfont <font> + mark 1 index % <fontname> mark <fontname> + //systemdict begin .dofindfont + % <fontname> mark <alias> ... <font> + % Define any needed aliases. + counttomark 1 sub { .aliasfont } repeat end + % <fontname> mark <font> + exch pop exch pop +} odef +/findfont { + .findfont +} bind def +% Check whether the font name we are about to look for is already on the list +% of aliases we're accumulating; if so, cause an error. +/.checkalias % -mark- <alias1> ... <name> .checkalias <<same>> + { counttomark 1 sub -1 1 + { index 1 index eq + { pop QUIET not + { (Unable to substitute for font.) = flush + } if + /findfont cvx /invalidfont signalerror + } + if + } + for + } bind def +% Get a (non-fake) font if present in a FontDirectory. +/.fontknownget % <fontdir> <fontname> .fontknownget <font> true + % <fontdir> <fontname> .fontknownget false + { .knownget + { FAKEFONTS + { dup /FontMatrix known { true } { pop false } ifelse } + { true } + ifelse + } + { false + } + ifelse + } bind def +% This is the standard procedure for handling font substitution. +% Its location is per an Adobe newsgroup posting. +% It is called with the font name on the stack, standing in for findfont. +/.stdsubstfont { % mark <alias1> ... <fontname> .stdsubstfont mark <alias1> ... <aliasN> <font> + /SUBSTFONT where { + pop QUIET not { + (Substituting for font ) print dup =only + (.) = flush + } if + % No aliasing. + % This mode is incompatible with high level devices. + cleartomark mark defaultfontname + } { + dup .substitutefont + 2 copy eq { pop defaultfontname } if + .checkalias + QUIET not { + SHORTERRORS { + (%%[) print 1 index =only + ( not found, substituting ) print dup =only (]%%) + } { + (Substituting font ) print dup =only + ( for ) print 1 index =only (.) + } ifelse = flush + } if + } ifelse + /Font findresource +} bind def + +% Default font substitution does {pop /Courier} om many implementations. +% GS post-process font substitution in .stdsubstfont and uses {} for +% backward compatibility +$error /SubstituteFont { } put + +% Scan the next directory on FONTPATH. +/.scannextfontdir { % - .scannextfontdir <bool> + % If we haven't scanned all the directories in + % FONTPATH, scan the next one. + null 0 1 FONTPATH length 1 sub { + FONTPATH 1 index get null ne { exch pop exit } if pop + } for dup null ne { + dup 0 eq { .scanfontbegin } if + FONTPATH 1 index get .scanfontdir + FONTPATH exch null put true + } { + pop false + } ifelse +} bind def +% Do the work of findfont, including substitution, defaulting, and +% scanning of FONTPATH. +/.dofindfont { % mark <fontname> .dofindfont % mark <alias> ... <font> + .tryfindfont not { + % We didn't find the font. If we haven't scanned + % all the directories in FONTPATH, scan the next one + % now and look for the font again. + .scannextfontdir { + % Start over with an empty alias list. + counttomark 1 sub { pop } repeat % mark <fontname> + .dofindfont + } { + % No more directories to scan. Try building the native + % font map entries if we haven't already done so. + systemdict /.nativefontmapbuilt get not { .buildnativefontmap } { false } ifelse { + % Same stack as at the beginning of .dofindfont. + .dofindfont % start over + } { + % No luck. Make sure we're not already + % looking for the default font. + QUIET not { + (Didn't find this font on the system!\n) + print + } if + dup defaultfontname eq { + QUIET not { + (Unable to load default font ) print + dup =only (! Giving up.) = flush + } if + /findfont cvx /invalidfont signalerror + } if + % Substitute for the font. Don't alias. + % Same stack as at the beginning of .dofindfont. + $error /SubstituteFont get exec + % + % igorm: I guess the surrounding code assumes that .stdsubstfont + % must ADD an alias to allow .checkalias and .findfont to work properly. + % Also I guess that a trailing recursion is + % used in .dofindfont and through .stdsubstfont + % just to represent a simple iteration, + % which accumulates the aliases after the mark. + .stdsubstfont + } ifelse + } ifelse + } if +} bind def +% Try to find a font using only the present contents of Fontmap. +/.tryfindfont { % <fontname> .tryfindfont <font> true + % <fontname> .tryfindfont false + .FontDirectory 1 index .fontknownget + { % Already loaded + exch pop true + } + { dup Fontmap exch .knownget not + { % Unknown font name. Look for a file with the + % same name as the requested font. + .tryloadfont + } + { % Try each element of the Fontmap in turn. + false exch % (in case we exhaust the list) + % Stack: fontname false fontmaplist + { exch pop + dup type /nametype eq + { % Font alias + .checkalias .tryfindfont exit + } + { dup dup type dup /arraytype eq exch /packedarraytype eq or exch xcheck and + { % Font with a procedural definition + exec % The procedure will load the font. + % Check to make sure this really happened. + .FontDirectory 1 index .knownget + { exch pop true exit } + if + } + { % Font file name + .loadfontloop { true exit } if + } + ifelse + } + ifelse false + } + forall + % Stack: font true -or- fontname false + { true + } + { % None of the Fontmap entries worked. + % Try loading a file with the same name + % as the requested font. + .tryloadfont + } + ifelse + } + ifelse + } + ifelse + } bind def + +% any user of .putgstringcopy must use bind and executeonly +/.putgstringcopy % <dict> <name> <string> .putgstringcopy - +{ 2 index gcheck currentglobal + 2 copy eq { + pop pop .forceput + } { + 5 1 roll setglobal + dup length string copy + .forceput setglobal + } ifelse +} .bind odef % must be bound and hidden for .forceput + + +% Attempt to load a font from a file. +/.tryloadfont { % <fontname> .tryloadfont <font> true + % <fontname> .tryloadfont false + dup .nametostring + % Hack: check for the presence of the resource machinery. + /.genericrfn where { + pop + pop dup .fonttempstring /FontResourceDir getsystemparam .genericrfn + .loadfontloop { + //true + } { + dup .nametostring .loadfontloop + } ifelse + } { + .loadfontloop + } ifelse +} bind def +/.loadfontloop { % <fontname> <filename> .loadfontloop + % <font> true + % -or- + % <fontname> false + % See above regarding the use of 'loop'. + { % Is the font name a string? + dup type /stringtype ne + { QUIET not + { (Can't find font with non-string name: ) print dup =only (.) = flush + } + if pop false exit + } + if + % Can we open the file? + findlibfile not + { QUIET not + { (Can't find \(or can't open\) font file ) print dup print + (.) = flush + } + if pop false exit + } + if + + % Stack: fontname fontfilename fontfile + DISKFONTS + { .currentglobal true .setglobal + 2 index (r) file + FontFileDirectory exch 5 index exch .growput + .setglobal + } + if + QUIET not + { (Loading ) print 2 index =only + ( font from ) print 1 index print (... ) print flush + } + if + % If LOCALFONTS isn't set, load the font into local or global + % VM according to FontType; if LOCALFONTS is set, load the font + % into the current VM, which is what Adobe printers (but not + % DPS or CPSI) do. + LOCALFONTS { false } { /setglobal where } ifelse + { pop /FontType .findfontvalue { 1 eq } { false } ifelse + % .setglobal, like setglobal, aliases FontDirectory to + % GlobalFontDirectory if appropriate. However, we mustn't + % allow the current version of .setglobal to be bound in, + % because it's different depending on language level. + .currentglobal exch /.setglobal .systemvar exec + % Remove the fake definition, if any. + .FontDirectory 3 index .forceundef % readonly + 1 index (r) file .loadfont .FontDirectory exch + /.setglobal .systemvar exec + } + { .loadfont .FontDirectory + } + ifelse + % Stack: fontname fontfilename fontdirectory + QUIET not + { //systemdict /level2dict known + { .currentglobal false .setglobal vmstatus + true .setglobal vmstatus 3 -1 roll pop + 6 -1 roll .setglobal 5 + } + { vmstatus 3 + } + ifelse { =only ( ) print } repeat + (done.) = flush + } if + + % Check to make sure the font was actually loaded. + dup 3 index .fontknownget + { dup /PathLoad 4 index //.putgstringcopy exec + 4 1 roll pop pop pop true exit + } if + + % Maybe the file had a different FontName. + % See if we can get a FontName from the file, and if so, + % whether a font by that name exists now. + exch dup % Stack: origfontname fontdirectory path path + (r) file .findfontname + { % Stack: origfontname fontdirectory path filefontname + 2 index 1 index .fontknownget + { % Yes. Stack: origfontname fontdirectory path filefontname fontdict + dup 4 -1 roll /PathLoad exch //.putgstringcopy exec + % Stack: origfontname fontdirectory filefontname fontdict + 3 -1 roll pop exch + % Stack: origfontname fontdict filefontname + QUIET + { pop + } + { (Using ) print =only + ( font for ) print 1 index =only + (.) = flush + } + ifelse % Stack: origfontname fontdict + exch pop true exit + % Stack: fontdict + } + if pop % Stack: origfontname fontdirectory path + } + if pop pop % Stack: origfontname + + % The font definitely did not load correctly. + QUIET not + { (Loading ) print dup =only + ( font failed.) = flush + } if + false exit + + } loop % end of loop + + } bind executeonly def % must be bound and hidden for .putgstringcopy + +currentdict /.putgstringcopy .undef + +% Define a procedure to load all known fonts. +% This isn't likely to be very useful. +/loadallfonts + { Fontmap { pop findfont pop } forall + } bind def + +% If requested, load all the fonts defined in the Fontmap into FontDirectory +% as "fake" fonts i.e., font dicts with only FontName and FontType defined. +% (We define FontType only for the sake of some questionable code in the +% Apple Printer Utility 2.0 font inquiry code.) +% +% Note that this procedure only creates fake fonts in the FontDirectory +% associated with the current VM. This is because in multi-context systems, +% creating the fake fonts in local VM leads to undesirable complications. +/.definefakefonts + { + } + { + (gs_fonts FAKEFONTS) VMDEBUG + Fontmap { + pop dup type /stringtype eq { cvn } if + .FontDirectory 1 index known not { + 2 dict dup /FontName 3 index put + dup /FontType 1 put + .FontDirectory 3 1 roll { put } //superexec % readonly + } { + pop + } ifelse + } forall + } +FAKEFONTS { exch } if pop def % don't bind, .current/setglobal get redefined + +% Install initial fonts from Fontmap. +/.loadinitialfonts + { NOFONTMAP not + { /FONTMAP where + { pop [ FONTMAP .pathlist ] + { dup VMDEBUG findlibfile + { exch pop .loadFontmap } + { /undefinedfilename signalerror } + ifelse + } + } + { LIBPATH + { defaultfontmap + false .file_name_combine + { + dup VMDEBUG + (r) { file } .internalstopped { + pop pop + defaultfontmap_content { .definefontmap } forall + } { + .loadFontmap + } ifelse + } { + pop pop + } ifelse + } + } + ifelse forall + } + if + userdict /defaultfontmap_content .undef + .definefakefonts % current VM is global + } def % don't bind, .current/setglobal get redefined + +% ---------------- Synthetic font support ---------------- % + +% Create a new font by modifying an existing one. paramdict contains +% entries with the same keys as the ones found in a Type 1 font; +% it should also contain enough empty entries to allow adding the +% corresponding non-overridden entries from the original font dictionary, +% including FID. If paramdict includes a FontInfo entry, this will +% also override the original font's FontInfo, entry by entry; +% again, it must contain enough empty entries. + +% Note that this procedure does not perform a definefont. + +/.makemodifiedfont % <fontdict> <paramdict> .makemodifiedfont <fontdict'> + { exch + { % Stack: destdict key value + 1 index /FID ne + { 2 index 2 index known + { % Skip fontdict entry supplied in paramdict, but + % handle FontInfo specially. + 1 index /FontInfo eq + { 2 index 2 index get % new FontInfo + 1 index % old FontInfo + { % Stack: destdict key value destinfo key value + 2 index 2 index known + { pop pop } + { 2 index 3 1 roll put } + ifelse + } + forall pop + } + if + } + { % No override, copy the fontdict entry. + 2 index 3 1 roll put + dup dup % to match pop pop below + } + ifelse + } + if + pop pop + } forall + } bind def + +% Make a modified font and define it. Note that unlike definefont, +% this does not leave the font on the operand stack. + +/.definemodifiedfont % <fontdict> <paramdict> .definemodifiedfont - + { .makemodifiedfont + dup /FontName get exch definefont pop + } bind def diff --git a/gs/Resource/Init/gs_frsd.ps b/gs/Resource/Init/gs_frsd.ps new file mode 100644 index 000000000..9ae0a930f --- /dev/null +++ b/gs/Resource/Init/gs_frsd.ps @@ -0,0 +1,81 @@ +% Copyright (C) 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Implementation of ReusableStreamDecode filter. +% This file must be loaded after gs_lev2.ps and gs_res.ps. + +level2dict begin + +% ------ ReusableStreamDecode filter ------ % + +/.reusablestreamdecode { % <source> <dict> .reusablestreamdecode <file> + % <source> .reusablestreamdecode <file> + % Collect the filter parameters. + dup type /dicttype eq { 2 copy } { dup 0 dict } ifelse + dup .rsdparams + % Construct the filter pipeline. + % The very first filter should use the value of CloseSource + % from the RSD dictionary; all the others should have + % CloseSource = true. + % Stack: source dict filters parms + 2 index /CloseSource .knownget not { //false } if 5 -1 roll + % Stack: dict filters parms CloseSource source + 0 1 5 index length 1 sub { + 4 index 1 index get + % Stack: dict filters parms CloseSource source index filtname + 4 index //null eq { + 0 dict + } { + 4 index 2 index get dup //null eq { pop } if + } ifelse + 3 -1 roll pop exch filter + exch pop //true exch % set CloseSource for further filters + } for + % If AsyncRead is true, try to create the filter directly. + % Stack: dict filters parms CloseSource source + 4 index /AsyncRead .knownget not { //false } if { + 1 index { .reusablestream } .internalstopped + } { + //null //true + } ifelse { + pop + % No luck. Read the entire contents of the stream now. + dup type /filetype ne { + % Make a stream from a procedure or string data source. + 0 () .subfiledecode + } if + % We must allocate the string in the same VM space as its + % source, since the reusable stream must be allocated there. + + .currentglobal 1 index gcheck .setglobal exch + currentpacking //false setpacking exch + % Stack: dict filters parms CloseSource oldglobal oldpacking file + [ exch { dup 40000 string readstring not { exit } if exch } loop + exch pop + ] + % Stack: dict filters parms CloseSource oldglobal oldpacking [()...] + 3 1 roll setpacking setglobal + % Stack: dict filters parms CloseSource [()...] + 1 index .reusablestream + } if + % We created the stream successfully: clean up. + 4 { exch pop } repeat + 1 index type /dicttype eq { exch pop } if exch pop +} odef + +filterdict /ReusableStreamDecode /.reusablestreamdecode load put + +end % level2dict diff --git a/gs/Resource/Init/gs_icc.ps b/gs/Resource/Init/gs_icc.ps new file mode 100644 index 000000000..28d345e8a --- /dev/null +++ b/gs/Resource/Init/gs_icc.ps @@ -0,0 +1,340 @@ +% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% ICCBased color space method dictionaries. +% This assumes gs_ciecs2.ps has already been processed. + +% +% Note that the substitution procedure in this routine will dynamically +% check for support of ICCBased color space. If such support is not +% provided, the alternative color space will be used. +% +% The validation routine in dictionary (cs_validate) performs a more +% extensive validation than is done for other color spaces, because +% .seticcspace does less checking than most other color space setting +% operators. +% + + +.currentglobal true .setglobal +.cspace_util begin + +% +% A dictionary for mapping the number of components of an ICCBased color +% space to the appropriate alternative color space. This is used only +% if an alternative color space is not specifically provided. +% +/icc_comp_map_dict + mark 1 /DeviceGray 3 /DeviceRGB 4 /DeviceCMYK .dicttomark +def + +% +% <array1> get_icc_alternative_space <name | array2> +% +% Get the alternative color space for an ICCBased color space. +% +/get_icc_alternative_space + { + 1 get dup /Alternate .knownget + { exch pop } + { /N get //icc_comp_map_dict exch get } + ifelse + } +bind def + + +colorspacedict +/ICCBased + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate true + /cs_potential_icc_alternate false + /cs_get_ncomps { 1 get /N get } bind + + /cs_get_range + { + 1 get dup /Range .knownget + { exch pop } + { /N get 2 mul //dflt_range_4 exch 0 exch getinterval } + ifelse + } + bind + + /cs_get_default_color { 1 get /N get { 0 } repeat } bind + + % + % For generating a gray, RGB, or CMYK equivalent color, we will + % assume that the alternative color space provides reasonable + % mapping. + /cs_get_currentgray + { //get_icc_alternative_space exec //.cs_get_currentgray exec } + bind + /cs_get_currentrgb + { //get_icc_alternative_space exec //.cs_get_currentrgb exec } + bind + /cs_get_currentcmyk + { //get_icc_alternative_space exec //.cs_get_currentcmyk exec } + bind + + % a lot of validation is done by the cs_validate method + /cs_validate + { + //check_cie_cspace exec + dup 1 get + dup /N get + dup type /integertype ne + //setcspace_typecheck + if + //icc_comp_map_dict exch known not + //setcspace_rangecheck + if + dup /DataSource get + dup type dup /stringtype ne exch /filetype ne and + //setcspace_typecheck + if + rcheck not + //setcspace_invalidaccess + if + dup /Range .knownget + { + //check_array exec + { + type dup /integertype ne exch /realtype ne and + //setcspace_typecheck + if + } + forall + } + if + /Alternate .knownget + { + //.cs_validate exec + dup //.cs_potential_icc_alternate exec not + { + 0 get /ICCBased ne + //setcspace_rangecheck + if + } + { pop } + ifelse + } + if + } + bind + + % substitute the Alternate space, if appropriate + /cs_substitute + { + % + % A design problem in the Ghostscript graphic library color + % space code prevents an ICCBased color space from having an + % ICCBased alternative color space. This situation actually + % arises fairly frequently in PDF, as an ICCBased color space + % is used as the substitute color for a Device{Gray|RGB|CMYK} + % color space, which in turn are used as the alternative color + % space to another (or possibly even the same) ICCBased color + % space. + % + % This situation causes no fundamental problems, as + % Ghostscript nominally supports ICCBased color spaces, so the + % Alternate color space is not used. Where this is not true + % (primarily because the NOCIE option is selected), the code + % would (except for the design flaw noted above) select the + % Alternate of the Alternate color space. + % + % The code below works around this problem by suprressing + % color space substitution for alternative color spaces if + % the substituting space is an ICCBased color space. + % + dup //get_icc_alternative_space exec + //.cs_substitute exec + 2 copy eq + 1 index //.cs_potential_icc_alternate exec not + or + { pop pop dup } + { + % retain just the new Alternate space + exch pop + + % build all new structures in local VM + .currentglobal 3 1 roll //false .setglobal + + % copy the original ICCBased color space array + 1 index dup length array copy + + % copy the ICCBased dictionary + dup 1 2 copy get dup length dict copy + + % insert the new alterante color space + dup /Alternate 7 -1 roll put + + % insert the new dictionary into the arra + put + + % restore the VM mode + 3 -1 roll .setglobal + } + ifelse + } + bind + + % + % The current implementation of ICCBased color spaces requires the + % DataSource to be a file. + % + /cs_prepare + { + % make DataSource a file + dup 1 get /DataSource get type /stringtype eq + { + % build all new structures in local VM + .currentglobal exch //false .setglobal + + % check if we need to copy the color space and dictionary + 2 copy eq + { + dup length array copy + dup 1 2 copy get dup length dict copy put + } + if + + % fetch DataSource, setting up stack for multiple puts + dup 1 2 copy get dup /DataSource 2 copy get + + % convert the string into a file + /ReusableStreamDecode filter + + % put the file into the dictioary, the dictionary into the array + put put + + % restore the VM mode + exch .setglobal + } + if + } + bind + + % + % Install the current color space. + % + % The current Ghostscript color space implementation requires that + % color spaces that provide a base or alternative color space set + % that base/alternative color space to be the current color space + % before attempting to set the original color space. This can cause + % difficulty if an ICCBased color space is being used as a substitute + % color space for a device-specific color space, and uses that same + % device-specific color space as an alternative space. For this + % reason, a special _setcolorspace_nosub operator is provided. + % + /cs_install + { + % set the alternative color space to be the current color space + dup //get_icc_alternative_space exec //_setcolorspace_nosub exec + + % check for native support + /.seticcspace where + { pop //false } + { //true } + ifelse + NOCIE or + //pop_1 % do nothing + { + % Acrobat Reader silently ignores errors with ICC profiles + % and uses the alternate color space -- do the same. + mark exch 1 get + { .seticcspace } + .internalstopped + cleartomark + } + ifelse + } + bind + + % for now, the alternative spaces for an ICCBased color space do + % not require special preparation + /cs_prepare_color { dup 1 get /N get //check_num_stack exec pop } bind + /cs_complete_setcolor //pop_1 + + .dicttomark +put + +end % .cspace_util + +NOPSICC { (%END PSICC) .skipeof } if +% Now set up ICC profile loading for PostScript %%BeginICCProfile sections. + +systemdict begin +/.ProcessICCcomment { % file comment -- file comment + dup + (%%BeginICCProfile) anchorsearch { + pop pop + DEBUG { (.ProcessICCcomment found %%BeginICCProfile) print flush } if + + % load an ICC profile defined as comments (hex encoded). + % Ends with %%End at the start of a line. Read the data into + % a bytestring to allow seeking. This string can be used as a + % seekable ReusableStreamDecode filter source by the ICC logic. + % + % Since .bigstring needs to know the size, we first read an array of + % strings each 64000 max length. + % + % stack: --file-- (%%BeginICCProfile: ...) + 1 index 0 (%%EndICCProfile) /SubFileDecode filter + [ { counttomark 1 add index + 64000 string readhexstring + not { exit } if + } loop + ] exch closefile + 0 1 index { length add } forall + .bigstring + exch 0 exch { + % stack: --file-- (%%BeginICCProfile: ...) --bytestring-- cur_index --string-- + 2 copy length add % calculate next string start point + 3 1 roll 3 index 3 1 roll putinterval + } forall + pop % discard length of bytestring + % make a seekable -file- out of the bytestring + mark /AsyncRead true .dicttomark /ReusableStreamDecode filter + % stack: --file-- (%%BeginICCProfile: ...) --icc_subfile-- + /DeviceCMYK setcolorspace + << /DataSource 3 -1 roll + /N 4 % Try CMYK first + >> { .seticcspace } stopped { + /DeviceRGB setcolorspace + dup /N 3 put { .seticcspace } stopped { + /DeviceGray setcolorspace + dup /N 1 put { .seticcspace } stopped { % last choice + QUIET not { ( *** Unable to load ICC profile from PostScript DSC comments ***) = flush } if + pop + } if + } if + } if + } { + pop % Not interested in this DSC comment + } ifelse +} bind def + +% Merge ProcessICCcomment with existing handler +/.ProcessICCcomment load /exec load +currentuserparams /ProcessDSCComment get +dup null eq {pop {pop pop}} if /exec load +4 array astore cvx readonly +<< /ProcessDSCComment 3 -1 roll >> setuserparams + +end % systemdict +%END PSICC +.setglobal diff --git a/gs/Resource/Init/gs_il1_e.ps b/gs/Resource/Init/gs_il1_e.ps new file mode 100644 index 000000000..35eec4515 --- /dev/null +++ b/gs/Resource/Init/gs_il1_e.ps @@ -0,0 +1,66 @@ +% Copyright (C) 1993, 1994, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the ISO Latin-1 encoding vector. +% The first half is the same as the standard encoding, +% except for minus instead of hyphen at code 055. +/ISOLatin1Encoding +StandardEncoding 0 45 getinterval aload pop + /minus +StandardEncoding 46 82 getinterval aload pop +% NOTE: the following are missing in the Adobe documentation, +% but appear in the displayed table: +% macron at 0225, dieresis at 0230, cedilla at 0233, space at 0240. +% This is an error in the Red Book, corrected in Adobe TN 5085. +% \20x + /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef + /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef + /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent + /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron +% \24x + /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 +% \30x + /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 +% \34x + /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 +% Make an array on large systems, a packed array on small ones. +256 +vmstatus exch pop exch pop +100000 ge { array astore readonly } { packedarray } ifelse +def +1 ISOLatin1Encoding .registerencoding +/ISOLatin1Encoding ISOLatin1Encoding .defineencoding diff --git a/gs/Resource/Init/gs_img.ps b/gs/Resource/Init/gs_img.ps new file mode 100644 index 000000000..35a36758d --- /dev/null +++ b/gs/Resource/Init/gs_img.ps @@ -0,0 +1,862 @@ +% (C) 2002 Artifex, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% image, colorimage, and imagemask implementation + +% +% The design of the overprint facility in Ghostscript requires that color +% specifications include the color space from which they were expressed, +% even after conversion to the device color model. Directly including this +% information in color specifications is usually not efficient, and is +% difficult to integrate into the existing code structure. The alternative +% approach taken is to extend a state mechanism through the device +% interface, and make the current color space, or more specifically, +% certain information about the current color space, a property of this +% state. +% +% For such a mechanism to work, it is necessary to identify all changes +% to the current color space. This is accomplished in the graphic library +% by funneling all changes to the current color space through the +% gs_setcolorspace procedure. At the PostScript interpreter level, this +% result is achieved by forcing color space changes through the +% setcolorspace operator. +% +% Aside from explicit use of setcolorspace, PostScript provides a few +% implicit methods of changing the current color space. The setgray, +% setrgbcolor, and setcmykcolor operators implicitly set the color space +% while explicitly setting the current color. Similarly, the colorimage +% operator and the traditional form of the image operator (5 operands) +% both temporarily modify the current color space while an image is +% being processed. The current file is concerned with the implementation +% of these two operators. In addition, the traditional form of the +% imagemask operator (5 operands), while it does not affect the current +% color space, is closely related to the image operator and thus is +% implemented in this file as well. +% +% In this implementation, all sampled objects are passed through one of +% the internal operators .image1, .imagemask1, .image1alpha, .image2, +% .image3, or .image4, each of which handles a specific ImageType value. +% +% The procedures in this file are responsible for constructing +% image dictionaries from a set of stack entries. This is, in principle, +% a trivial exercise. In practice it appears to be far more complex, +% primarily due to the need to reconstruct the original state in the +% event of an error. This is a particular problem for operators such as +% image, which include data source objects that may, directly or +% indirectly, be procedures. When these procedures are executed, the +% image operator's operands must have been cleared from the operand +% stack. Hence, the operand stack cannot be used to store state +% information. Similarly, the dictionary stack also cannot be used to +% store state information, as the data source procedures may depend on +% a particular dictionary being on the top of this stack. +% +% Adobe's PostScript implementations determine the extent to which the +% interpreter state is restored in the event of an error by the point at +% which the error is detected. Errors in the image/colorimage/imagemask +% operators that are detected before the data source procedures are +% executed restore the state in effect before the image was processed. +% Those that are detected as part of running the data source procedures +% only attempt to restore the state to that in effect at the start of +% the operator that failed (or at the conclusion of the data source +% procedure, if this procedure failed to push a string). +% +% The implementation given here follows the Adobe convention. The +% mechanism used is as follows: +% +% 1. Check that the stack has a sufficient number of operands, and +% that enough of them have the proper type to allow construction +% of the image dictionary. Any errors at this point are handled +% in the conventional manner. +% +% 2. Build the image dictionary, in the process clearing the image/ +% colorimage/imagemask operands from the stack. No errors can +% occur during this process. +% +% (Special precautions could be taken during this step to handle +% a limitcheck or VMError during the building of the image +% dictionary, but this essentially never occurs in practice and, if +% it did, is very unlikely to leave a useable state. Hence, we don't +% bother with this possibility.) +% +% 3. The .image operator is executed in a stopped context. If it +% returns abnormally, a check is made to see if the uppermost +% operand on the stack is a color image dictionary. If so, the +% original stack is created anew using this dictionary. (Because +% the image operand works via colorimage, some additional special +% handling is required in this case.) +% + + +% +% Create a dictionary of operators for specific image and image mask types. +% Each of these will always handle ImageType 1. Additional types are added +% as they are supported in specific interpreter levels or versions. +% +% These dictionaries are in systemdict for historical reasons. +% +.currentglobal true .setglobal +systemdict begin +/.imagetypes + 5 dict + dup 1 /.image1 load put +def +/.imagemasktypes + 5 dict + dup 1 /.imagemask1 load put +def +end +.setglobal + +% +% Build a dictionary of utility procedures and constants for use in +% impelementing the image operators. This dictionary is in global VM but +% is maintained (during initialization) in userdict. It should be pushed +% onto the dictionary stack when constructing image-related procedures +% and pseudo-operators. +% +% This dictionary is removed from userdict when initialization is +% completed. +% +.currentglobal true .setglobal +userdict /img_utils_dict 30 dict put +img_utils_dict begin + + +% +% Some useful local data structures: +% +% img_csary maps the number of components in an image to the implied +% color space. +% +% img_decary is a prototype Decode array; subintervals of this array +% may be used for fewer than 4 color components. +% +% img_params_ary is a list of the parameters to be built in the image +% dictionary for a colorimage invocation. ImageType is given a +% fixed value; the other parameters are in stack order (IMG_NComps +% is the number of components). +% +% img_mask_params_ary is the equivalent of img_params_ary for imagemask +% invocations. Polarity is a proxy for Decode, and is replaced +% by the Decode key in the image dictionary. +% +% img_mask_check_ary is the set of parameters that must be present in +% an image dictionary generated by an imagemask invocation. This +% differs from img_mask_params_ary in that Decode replaces Polarity. +% +/img_csary [ null /DeviceGray null /DeviceRGB /DeviceCMYK ] def +/img_decary [ 0 1 0 1 0 1 0 1 ] def + +/img_params_ary + [ + /ImageType /IMG_NComps /MultipleDataSources /DataSource + /ImageMatrix /BitsPerComponent /Height /Width /Decode + ] +def +/img_check_ary //img_params_ary def +/img_unbuild_ary + //img_params_ary 1 1 index length 2 sub getinterval +def + +/img_mask_params_ary + [ /ImageType /DataSource /ImageMatrix /Polarity /Height /Width ] +def +/img_mask_check_ary + [ + /ImageType /BitsPerComponent + /DataSource /ImageMatrix /Decode /Height /Width + ] +def +/img_mask_unbuild_ary + //img_mask_check_ary 2 1 index length 2 sub getinterval +def + + +% +% <?any?> <array> img_check_keys <?any?> <bool> +% +% Verify that: +% that there are at least two entries on the stack, and +% the second (lower) entry is a dictionary, and +% that dictionary contains all of the keys in the array +% +% If any one of these conditions does not hold, pop the array and push +% false; otherwise pop the array and push true. This utility is used by +% the colorimage and imagematrix procedures to determine if .image left +% the image dictionary on the stack after an abnormal return. +% +/img_check_keys + { + count 2 ge + { + 1 index type /dicttype eq + { + true exch + { + 2 index exch known and + dup not + { exit } + if + } + forall + } + { pop //false } + ifelse + } + { pop //false } + ifelse + } +.bind def + +% +% Procedures to convert a set of stack entries to a dictionary. There is +% a procedure associated with each key, though most keys use the same +% procedure. The dictionary to be built is at the top of the dictionary +% stack. Stack handling for the procedures is: +% +% <?val0?> ... <?val(n - 1)?> <key> proc - +% +% Parameters are handle in inverse-stack order, so inter-parameter +% dependencies that on the stack can generally be used here. +% +/img_params_dict + mark + /ImageType { 1 def } .bind + + /IMG_NComps { exch def } .bind % number of components + /MultipleDataSources 1 index + /Width 1 index + /Height 1 index + /ImageMatrix 1 index + /BitsPerComponent 1 index + /DataSource 1 index + + % Polarity is a proxy for Decode; it never appears in a dictionary + /Polarity + { + pop + { { 1 0 } } + { { 0 1 } } + ifelse + /Decode exch cvlit def + } + .bind + + % the definition of Decode is based on the number of components + /Decode { //img_decary 0 IMG_NComps 2 mul getinterval def } .bind + .dicttomark +def + +% +% <oper_0> ... <oper_n> <array> img_build_dict <dict> +% +% Build a dictionary. This will always be done in local VM. The array is +% a list of the keys to be associated with operands on the stack, in +% inverse stack order (topmost element first). The caller should verify +% that the dictionary can be built successfully (except for a possible +% VMerror) before calling this routine. +% +/img_build_dict + { + % build the dictionary in local VM; all for 2 extra entries + .currentglobal false .setglobal + 1 index length 2 add dict + exch .setglobal + begin + + % process all keys in the array + { //img_params_dict 1 index get exec } + forall + + % if BitsPerComponent is not yet defined, define it to be 1 + currentdict /BitsPerComponent known not + { /BitsPerComponent 1 def } + if + + currentdict end + } +.bind def + +% +% <dict> <array> img_unbuild_dict <oper_0> ... <oper_n> +% +% "Unbuild" a dictionary: spread the contents the dictionary back onto the +% stack, in the inverse of the order indicated in the array (inverse is +% used as this order is more convenient for img_build_dict, which is +% expected to be invoked far more frequently). +% +/img_unbuild_dict + { + exch begin + dup length 1 sub -1 0 + { 1 index exch get load exch } + for + pop + end + } +.bind def + +% +% Check the image types that can be used as data sources +% <any> foo <bool> +% +/good_image_types mark + /filetype { pop //true } .bind + /stringtype 1 index + /arraytype //xcheck + /packedarraytype //xcheck +.dicttomark readonly def + +% +% <width> <height> <bits/component> <matrix> <dsrc0> ... +% <multi> <ncomp> <has_alpha> +% img_build_image_dict +% <dict> <has_alpha> +% +% Build the dictionary corresponding to a colorimage operand stack. This +% routine will check just enough of the stack to verify that the +% dictionary can be built, and will generate the appropriate error if this +% is not the case. +% +% The <has_alpha> boolean is used to support the Next alphaimage extension. +% +% At the first level, errors in this procedure are reported as colorimage +% errors. The error actually reported will usually be determined by the +% pseudo-operator which invokes this routine. +% +/img_build_image_dict + { + % Veify that at least 8 operands are available, and that the top three + % operands have the expected types + count 8 lt + { /.colorimage cvx /stackunderflow signalerror } + if + 3 copy + type /booleantype ne exch + type /integertype ne or exch + type /booleantype ne or + { /.colorimage cvx /typecheck signalerror } + if + + % verify that the number of components is 1, 3, or 4 + 1 index 1 lt 2 index 2 eq or 2 index 4 gt or + { /.colorimage cvx /rangecheck signalerror } + if + + % Verify that the required number of operands are present if multiple + % data sources are being used. If this test is successful, convert + % the data sources to an array (in local VM). + 2 index + { + % if an alpha component is present, this adds one more component + 2 copy + { 1 add } + if + dup count 9 sub gt + { + % Adobe interpreters appear to test the arguments sequentially + % starting from the top of the stack and report the 1st error found. + % To satisfy CET test 12-02.PS we emulate this logic. + //true exch -1 1 + { 3 add index + //good_image_types 1 index type .knownget + { exec and + } + { pop pop //false + } + ifelse + } + for + { /stackunderflow + } + { /typecheck + } + ifelse + /.colorimage cvx exch signalerror + } + if + + % build the DataSource array in local VM + dup .currentglobal false .setglobal exch array exch .setglobal + + % stack: <w> <h> <bps> <mtx> <d0> ... <multi> <n> <alpha> <n'> <array> + 5 1 roll 4 add 3 roll astore 4 1 roll + } + if + + % the image dictionary can be built; do so + % stack: <w> <h> <bps> <mtx> <dsrc|dsrc_array> <multi> <n> <alpha> + 8 1 roll //img_params_ary //img_build_dict exec exch + } +.bind def +currentdict /good_image_types .undef + +% +% <?dict?> +% img_unbuild_image_dict +% <width> <height> <bits/component> <matrix> <dsrc0> ... +% <multi> <ncomp> +% +% If the top entry of the stack is a dictionary that has the keys required +% by a colorimage dictionary, unpack that dictionary onto the stack. +% Otherwise just leave things as they are. Note that the <has_alpha> +% parameter is not pushd onto the stack. +% +/img_unbuild_image_dict + { + //img_check_ary //img_check_keys exec + { + //img_unbuild_ary //img_unbuild_dict exec + 1 index type /booleantype eq + { + 1 index + { 3 -1 roll aload length 2 add -2 roll } + if + } + if + } + if + } +.bind def + + +% +% <width> <height> <polarity> <matrix> <dsrc> +% img_unbuild_imagemask_dict +% <dict> +% +% Build the dictionary corresponding to an imagemask stack. This routine +% will verify that the appropriate number of operands are on the stack, +% and that polarity is a boolean. This is all that is necessary to build +% the dictionary. +% +/img_build_imagemask_dict + { + % check for proper number of operands + count 5 lt + { /imagemask .systemvar /stackunderflow signalerror } + if + + % verify that polarity is a boolean + 2 index type /booleantype ne + { /imagemask .systemvar /typecheck signalerror } + if + + % the imagemask dictionary can be built; do so + //img_mask_params_ary //img_build_dict exec + } +.bind def + +% +% <?dict?> +% img_unbuild_imagemask_dict +% <width> <height> <polarity> <matrix> <dsrc> +% +% If the top entry of the stack is a dictionary that has the keys rquired +% by an imagemask dictionary, unpack that dictionary onto the stack. +% Otherwise just leave things as they are. +% +/img_unbuild_imagemask_dict + { + //img_mask_check_ary //img_check_keys exec + { + //img_mask_unbuild_ary //img_unbuild_dict exec + 3 -1 roll + dup type dup /arraytype eq exch /packedarraytype eq or + 1 index rcheck and + { 0 get 1 eq } + if + 3 1 roll + } + if + } +.bind def + + +% +% <width> <height> <bits/component> <matrix> <dsrc_0> ... +% <multi> <ncomp> <has_alpha> +% .colorimage +% - +% +% Convert the image/colorimage operator from their traditional form to +% the dictionary form. The <has_alpha> operand is used ot support the +% Next alphaimage extension. +% +% Error handling for these operators is a bit complex, due to the stack +% handling required of operators that potentially invoke procedures. +% This problem is discussed in the comment above. The facts relevant to +% this particular implementation are: +% +% 1. The .image1 (or .alphaimage) operator is executed in a stopped +% context, so that we can undo the gsave context in the event of +% an error. +% +% 2. In the event of an error, the stack is examined to see if the +% dictionary passed to .image1 (.alphaimage) is still present. +% If so, this dictionary is "unpacked" onto the stack to re- +% create the original stack. The <has_alpha> parameter is not +% pushed onto the stack, as it is not required for any of the +% pseudo-operators than invoke this procedure. +% +% 3. The use of pseudo-operators in this case may yield incorrect +% results for late-detected errors, as the stack depth will be +% restored (even though the stack is not). This is, however, no +% worse than the prior (level >= 2) code, so it should cause no +% new problems. +% +/.colorimage + { + % build the image dictionary + //img_build_image_dict exec + + % execute .image1 in a stopped context + { + gsave + % The CET test file 12-02.ps creates colorimages with a width and + % height of 0. Ignore these since that is what the CET expects. + 1 index dup /Height get 0 eq exch /Width get 0 eq or + { pop pop } % Ignore colorimage. Pop bool and dict + { + 0 .setoverprintmode % disable overprint mode for images + //img_csary 2 index /IMG_NComps get get setcolorspace + { .alphaimage } + { .image1 } + ifelse + } + ifelse + } + stopped + grestore + { + //img_unbuild_image_dict exec + /.colorimage cvx $error /errorname get + signalerror + } + if + } +.bind def + + +% +% <width> <height> <bits/component> <matrix> <dsrc_0> ... +% <multi> <ncomp> +% colorimage +% - +% +% Build the colorimage pseudo-operator only if setcolorscreen is visible. +% +systemdict /setcolorscreen .knownget + { + type /operatortype eq + { + /colorimage + { + //false + //.colorimage + stopped + { /colorimage .systemvar $error /errorname get signalerror } + if + } + .bind systemdict begin odef end + } + if + } +if + + +% +% width height bits_per_component matrix data_src image - +% +% <dict> image - +% +% Some special handling is required for ImageType 2 (Display PostScript +% pixmap images) so as to set the appropriate color space as the current +% color space. +% +/image + { + dup type /dicttype eq .languagelevel 2 ge and + { + dup /ImageType get dup 2 eq + { + % verify the ImageType 2 is supported + //.imagetypes exch known + { + % + % Set either DevicePixel or DeviceRGB as the current + % color space. DevicePixel is used if the image data is + % to be copied directly, with only a geometric + % transformation (PixelCopy true). The use of DeviceRGB + % in the alternate case is not, in general, correct, and + % reflects a current implementation limitation. Ideally, + % an intermediate color space should be used only if + % the source and destination color models vary; otherwise + % the native color space corresponding to the color model + % should be used. + % + % The mechanism to determine depth for the DevicePixel + % color space when BitsPerPixel is not available is + % somewhat of a hack. + % + gsave + 0 .setoverprintmode % disable overprintmode for images + dup /PixelCopy .knownget dup + { pop } + if + { + [ + /DevicePixel + currentpagedevice dup /BitsPerPixel .knownget + { exch pop } + { + /GrayValues .knownget not + { 2 } % try a guess + if + ln 2 ln div round cvi + } + ifelse + ] + } + { /DeviceRGB } + ifelse + setcolorspace + //.imagetypes 2 get + stopped + grestore + { /image .systemvar $error /errorname get signalerror } + if + } + { /image .systemvar /rangecheck signalerror + } + ifelse + } + { + dup //.imagetypes exch .knownget + { + exch pop gsave + 0 .setoverprintmode % disable overprintmode for images + stopped + grestore + { /image .systemvar $error /errorname get signalerror } + if + } + { + /image .systemvar exch type /integertype eq + { /rangecheck } { /typecheck } + ifelse signalerror + } + ifelse + } + ifelse + } + { + //false 1 //false + //.colorimage + stopped + { /image .systemvar $error /errorname get signalerror } + if + } + ifelse + } +.bind systemdict begin odef end + +% An auxiliary function for checking whether an imagemask to be interpolated. +/.is_low_resolution % <image dict> .is_low_resolution <bool> +{ % Checking whether image pixel maps to more than 2 device pixels. + % The threshold 2 is arbitrary. + 1 exch 0 exch + 0 exch 1 exch + /ImageMatrix get dup + 2 { + 4 1 roll + idtransform dtransform dup mul exch dup mul add sqrt + } repeat + max + 2 gt % arbitrary +} .bind def + + +% +% width height polarity matrix datasrc imagemask - +% +% See the comment preceding the definition of .colorimage for information +% as to the handling of error conditions. +% +/imagemask + { + dup type /dicttype eq .languagelevel 2 ge and + { dup /ImageType get + //.imagemasktypes exch .knownget + { 1 index //.is_low_resolution exec + 2 index /ImageType get 1 eq and + 2 index /BitsPerComponent get 1 eq and + 2 index /Interpolate .knownget not { false } if and + //filterdict /ImscaleDecode known and { + % Apply interpolated imagemask scaling filter + exch .currentglobal exch dup .gcheck .setglobal + dup length dict .copydict + dup dup /DataSource get + dup type /stringtype eq { + 1 array astore cvx % image.* operators read strings repeatesly + } if + mark /Width 3 index /Width get /Height 5 index /Height get .dicttomark + /ImscaleDecode filter /DataSource exch put + dup dup /Width get 4 mul /Width exch put + dup dup /Height get 4 mul /Height exch put + dup dup /ImageMatrix get + { 4 0 0 4 0 0 } matrix concatmatrix /ImageMatrix exch put + 3 1 roll .setglobal + } if + exec + } + { % CET 12-08b.ps wants /typecheck + /imagemask .systemvar /typecheck signalerror + } + ifelse + } + { + //img_build_imagemask_dict exec + { .imagemask1 } + stopped + { + //img_unbuild_imagemask_dict exec + /imagemask .systemvar $error /errorname get signalerror + } + if + } + ifelse + } +.bind systemdict begin odef end + +end % img_utils_dict + +% Conditionally turn image interpolation on or off. +% INTERPOLATE is not yet set, handle all cases +currentdict /INTERPOLATE known +currentdict /DOTERPOLATE known or +currentdict /NOTERPOLATE known or not { + currentfile 1 (%END INTERPOLATE) .subfiledecode flushfile +} if + +/.interpolate { + dup /Interpolate .knownget not { //false } if + /INTERPOLATE .systemvar ne { + dup gcheck .currentglobal exch .setglobal + exch dup length dict copy + dup /Interpolate /INTERPOLATE .systemvar put + exch .setglobal + } if +} .bind odef + +/colorimage + { /INTERPOLATE .systemvar + { .currentglobal % w h bit [] {}...{} multi ncomp glob + //false .setglobal + 9 dict begin % w h bit [] {}...{} multi ncomp glob + 2 .argindex { 1 index 7 add } { 8 } ifelse + dup .argindex pop % check # of arguments + copy gsave pop % preserve the arguments + { 0 /DeviceGray 0 /DeviceRGB /DeviceCMYK } + 1 index get setcolorspace % ... glob w h bit [] {}...{} multi ncomp + {0 1 0 1 0 1 0 1} + 1 index 2 mul 0 exch % ... glob w h bit [] {}...{} multi ncomp {0 1 ...} 0 2*ncomp + getinterval /Decode exch def % ... glob w h bit [] {}...{} multi ncomp + exch dup % ... glob w h bit [] {}...{} ncomp multi multi + /MultipleDataSources exch def % ... glob w h bit [] {}...{} ncomp multi + { array astore} { pop } ifelse % ... glob w h bit [] [{}...{}] + /DataSource exch def % ... glob w h bit [] + /ImageMatrix exch def % ... glob w h bit + /BitsPerComponent exch def % ... glob w h + /Height exch def % ... glob w + /Width exch def % ... glob + /ImageType 1 def + /Interpolate //true def + .setglobal currentdict end % ... <<>> + image grestore + exch { 4 add } { 6 } ifelse + { pop } repeat % - + } + { colorimage + } + ifelse + } .bind odef + +/image + { dup type /dicttype eq + { dup /ImageType get 3 eq + { .currentglobal //false .setglobal exch + dup length dict copy begin .setglobal + /DataDict DataDict .interpolate def + /MaskDict MaskDict .interpolate def + currentdict end + } + { .interpolate + } + ifelse + image + } + { /INTERPOLATE .systemvar + { 4 .argindex pop % check # of args + .currentglobal //false .setglobal + 8 dict begin .setglobal + /ImageType 1 def + /DataSource 1 index def + /ImageMatrix 2 index def + /BitsPerComponent 3 index def + /Decode {0 1} def + /Height 4 index def + /Width 5 index def + /Interpolate //true def + currentdict end + gsave /DeviceGray setcolorspace image grestore + 5 { pop } repeat + } + { image + } + ifelse + } + ifelse + } .bind odef + +/imagemask { + dup type /dicttype eq { + .interpolate imagemask + } { + /INTERPOLATE .systemvar { + 4 .argindex pop % check # of args + .currentglobal //false .setglobal + 8 dict begin .setglobal + /ImageType 1 def + /DataSource 1 index def + /ImageMatrix 2 index def + /BitsPerComponent 1 def + 2 index { {1 0} } { {0 1} } ifelse /Decode exch def + /Height 4 index def + /Width 5 index def + /Interpolate //true def + currentdict end imagemask 5 { pop } repeat + } { + imagemask + } ifelse + } ifelse +} .bind odef + +currentdict /.interpolate .undef + +%END INTERPOLATE + +.setglobal % restore VM mode diff --git a/gs/Resource/Init/gs_indxd.ps b/gs/Resource/Init/gs_indxd.ps new file mode 100644 index 000000000..5b93532e4 --- /dev/null +++ b/gs/Resource/Init/gs_indxd.ps @@ -0,0 +1,205 @@ +% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Indexed color space method dictionary + + +% verify that Indexed color spaces are supported +/.setindexedspace where + { pop } + { currentfile closefile } +ifelse + +.currentglobal true .setglobal +.cspace_util begin + +% +% <num> <array> restrict_index <int> <array> +% +% Restrict the operand to setcolor for an Indexed color space to be an +% integer in the applicable range. +% +/restrict_index + { + exch round cvi + dup 0 lt + { pop 0 } + { + 1 index 2 get 2 copy gt + { exch } + if + pop + } + ifelse + exch + } +bind def + +% +% <num> <array> get_indexed_base_color <c1> ... <cn> <array> +% +% Get the base color corresponding to an indexed color value. +% +/get_indexed_base_color + { + % just in case, set the index into the appropriate range + //restrict_index exec + + % lookup in the string or use the lookup proc + mark 1 index 3 get dup type /stringtype eq + { + 2 index 1 get //.cs_get_ncomps exec dup 6 -1 roll mul exch getinterval + { 255 div } + forall + } + { 4 -1 roll exch exec } + ifelse + counttomark 2 add -2 roll pop + } +bind def + + +colorspacedict +/Indexed + mark + /cs_potential_indexed_base false + /cs_potential_pattern_base true + /cs_potential_alternate false + /cs_potential_icc_alternate false + /cs_get_ncomps //ncomps_1 + /cs_get_range { 0 exch 2 get 2 array astore } bind + /cs_get_default_color { pop 0 } bind + + /cs_get_currentgray + { //get_indexed_base_color exec 1 get //.cs_get_currentgray exec } + bind + /cs_get_currentrgb + { //get_indexed_base_color exec 1 get //.cs_get_currentrgb exec } + bind + /cs_get_currentcmyk + { //get_indexed_base_color exec 1 get //.cs_get_currentcmyk exec } + bind + + % a lot of validation is done by the cs_validate method + /cs_validate + { + //check_array exec + dup 1 get //.cs_validate exec //.cs_potential_indexed_base exec not + //setcspace_rangecheck + if + dup 2 get dup type /integertype ne + //setcspace_typecheck + { + dup 0 lt exch 4095 gt or + //setcspace_rangecheck + if + } + ifelse + dup 3 get dup type /stringtype eq + { + length + 1 index dup 2 get 1 add exch 1 get //.cs_get_ncomps exec mul + lt + //setcspace_rangecheck + if + } + { + //check_array exec xcheck not + //setcspace_typecheck + if + } + ifelse + } + bind + + % substitute the base space if appropriate + /cs_substitute + { + dup 1 get //.cs_substitute exec 2 copy eq + { pop pop dup } + { + % retain only the new base space + exch pop + + % build all new structures in local VM + .currentglobal 3 1 roll //false .setglobal + + % construct a new array and insert the new base color space + 1 index dup length array copy dup 1 4 -1 roll put + + % restore VM mode + 3 -1 roll .setglobal + } + ifelse + } + bind + + /cs_prepare {} + + % + % Install the current color space. Note that the alternative color + % space will already have been set as the current color space. + % + % The current Ghostscript color space implementation requires that + % color spaces that provide a base or alternative color space set + % that base/alternative color space to be the current color space + % before attempting to set the original color space. + % + /cs_install + { + % save the current color space + currentcolorspace + + % set the base color space as the current color space + 1 index 1 get //forcesetcolorspace + + % set the indexed color space; restore the earlier space on error + mark 2 index + { .setindexedspace } + stopped + { cleartomark setcolorspace stop } + { pop pop pop } + ifelse + } + bind + + % Adobe implementations accept floating point values + /cs_prepare_color { //validate_1 exec cvi } bind + + % + % Adobe implementations always execute a lookup procedure when setcolor + % is invoked. Ghostscript samples the lookup procedure when + % setcolorspace is invoked, and then does not access it again. In the + % unlikely event that an application depends on the Adobe-specific + % behavior, it is replicated in this method. + % + /cs_complete_setcolor + { + 3 get dup type /stringtype eq + { pop } + { + currentcolor exch exec + currentcolorspace 1 get //clear_setcolor_operands exec + } + ifelse + } + bind + + .dicttomark +put + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_init.ps b/gs/Resource/Init/gs_init.ps new file mode 100644 index 000000000..6c76f5b8b --- /dev/null +++ b/gs/Resource/Init/gs_init.ps @@ -0,0 +1,2192 @@ +% Copyright (C) 1989-2004 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for the interpreter. +% When this is run, systemdict is still writable. + +% Comment lines of the form +% %% Replace <n> <file(s)> +% indicate places where the next <n> lines should be replaced by +% the contents of <file(s)>, when creating a single merged init file. + +% The interpreter can call out to PostScript code. All procedures +% called in this way, and no other procedures defined in these +% initialization files, have names that begin with %, e.g., +% (%Type1BuildChar) cvn. + +% Interpreter library version number +% NOTE: the interpreter code requires that the first non-comment token +% in this file be an integer, and that it match the compiled-in version! +864 + +% Check the interpreter revision. +dup revision ne + { (gs: Interpreter revision \() print revision 10 string cvs print + (\) does not match gs_init.ps revision \() print 10 string cvs print + (\).\n) print flush //null 1 .quit + } +if pop + +% Acquire userdict, and set its length if necessary. +/userdict where + { pop userdict maxlength 0 eq } + { true } +ifelse +systemdict exch + { % userdict wasn't already set up by iinit.c. + dup /userdict + currentdict dup 200 .setmaxlength % userdict + .forceput % userdict is local, systemdict is global + } +if begin + +% Define dummy local/global operators if needed. +systemdict /.setglobal known + { true .setglobal + } + { /.setglobal { pop } bind def + /.currentglobal { false } bind def + /.gcheck { pop false } bind def + } +ifelse + +% Define .languagelevel if needed. +systemdict /.languagelevel known not { /.languagelevel 1 def } if + +% Optionally choose a default paper size other than U.S. letter. +% The default page size for many devices is set at compile time to +% letter, but this can be changed to A4 although this is rarely done. +% Some devices such as bbox have a different default page size, +% and should not be set to A4 or letter. +% When ghostscript is used in countries that use the international +% standard page size A4 rather than US letter, the page size of +% devices that default to letter or A4 can be changed by setting +% DEFAULTPAPERSIZE. +% /DEFAULTPAPERSIZE (a4) def + +% Turn on array packing for the rest of initialization. +true setpacking + +% Define the old MS-DOS EOF character as a no-op. +% This is a hack to get around the absurd habit of MS-DOS editors +% of adding an EOF character at the end of the file. +<1a> cvn { } def + +% Acquire the debugging flags. +currentdict /DEBUG known /DEBUG exch def + +% if DEBUG is set, set ALL of the subset debugging flags +mark % '[' isn't defined yet + /CCFONTDEBUG % Compiled Fonts + /CFFDEBUG % CFF Fonts + /CMAPDEBUG % CMAP + /DOCIEDEBUG % CIE color + /EPSDEBUG % EPS handling + /FAPIDEBUG % Font API + /INITDEBUG % Initialization + /PDFDEBUG % PDF Interpreter + /PDFOPTDEBUG % PDF Optimizer (Linearizer) + /PDFWRDEBUG % PDF Writer + /SETPDDEBUG % setpagedevice + /TTFDEBUG % TTF Fonts + /VGIFDEBUG % ViewGIF + /VJPGDEBUG % ViewJPEG + /RESMPDEBUG % Resource map +counttomark array astore exch pop % ']' isn't defined yet +{ dup currentdict exch known DEBUG or def } forall + +currentdict /PDFSTEP known /PDFSTEP exch def +% if PDFSTEP is on, turn on PDFDEBUG +PDFSTEP { /PDFDEBUG true def } if + + /VMDEBUG + INITDEBUG {{print mark + systemdict /level2dict known + { .currentglobal dup false .setglobal vmstatus + true .setglobal vmstatus 3 -1 roll pop + 6 -2 roll pop .setglobal + } + { vmstatus 3 -1 roll pop + } + ifelse usertime 16#fffff and counttomark + { ( ) print ( ) cvs print } + repeat pop + ( ) print systemdict length ( ) cvs print + ( ) print countdictstack ( ) cvs print + ( <) print count ( ) cvs print (>\n) print flush + }} + {{pop + }} + ifelse + def + +currentdict /BATCH known /BATCH exch def +currentdict /DELAYBIND known /DELAYBIND exch def +currentdict /DISKFONTS known /DISKFONTS exch def +currentdict /DOINTERPOLATE .knownget { /INTERPOLATE exch def } if +currentdict /ESTACKPRINT known /ESTACKPRINT exch def +currentdict /FAKEFONTS known /FAKEFONTS exch def +currentdict /FIXEDMEDIA known /FIXEDMEDIA exch def +currentdict /FIXEDRESOLUTION known /FIXEDRESOLUTION exch def +currentdict /LOCALFONTS known /LOCALFONTS exch def +currentdict /JOBSERVER known /JOBSERVER exch def +currentdict /NOBIND known /NOBIND exch def +/.bind /bind load def +NOBIND { /bind { } def } if +currentdict /NOCACHE known /NOCACHE exch def +currentdict /NOCCFONTS known /NOCCFONTS exch def +currentdict /NOCIE known /NOCIE exch def +currentdict /NOPSICC known /NOPSICC exch def +currentdict /NODISPLAY known not /DISPLAYING exch def +currentdict /NOFONTMAP known /NOFONTMAP exch def +currentdict /NOFONTPATH known /NOFONTPATH exch def +currentdict /NOGC known /NOGC exch def +currentdict /NOINTERPOLATE .knownget { /INTERPOLATE exch not def } if +currentdict /NOMEDIAATTRS known /NOMEDIAATTRS exch def +currentdict /NOOUTERSAVE known /NOOUTERSAVE exch def +currentdict /NOPAGEPROMPT known /NOPAGEPROMPT exch def +currentdict /NOPAUSE known /NOPAUSE exch def +currentdict /NOPLATFONTS known /NOPLATFONTS exch def +currentdict /NOPROMPT known /NOPROMPT exch def +currentdict /NOTRANSPARENCY known /NOTRANSPARENCY exch def +currentdict /DOPS known /DOPS exch def +currentdict /NOSUBSTDEVICECOLORS known /NOSUBSTDEVICECOLORS exch def +% The default value of ORIENT1 is true, not false. +currentdict /ORIENT1 known not { /ORIENT1 true def } if +currentdict /OSTACKPRINT known /OSTACKPRINT exch def +currentdict /OUTPUTFILE known % obsolete + { /OutputFile /OUTPUTFILE load def + currentdict /OUTPUTFILE .undef + } if +currentdict /QUIET known /QUIET exch def +% DELAYSAFER is effectively the same as newer NOSAFER +currentdict /DELAYSAFER known { /DELAYSAFER true def /NOSAFER true def } if +/SAFER currentdict /NOSAFER known { + false +} { + currentdict /SAFER known + currentdict /PARANOIDSAFER known or % PARANOIDSAFER is equivalent +} +ifelse def +currentdict /SHORTERRORS known /SHORTERRORS exch def +currentdict /STRICT known /STRICT exch def +currentdict /TTYPAUSE known /TTYPAUSE exch def +currentdict /WRITESYSTEMDICT known /WRITESYSTEMDICT exch def +currentdict /RENDERTTNOTDEF known /RENDERTTNOTDEF exch def + +% Acquire environment variables. +currentdict /DEVICE known not + { (GS_DEVICE) getenv { /DEVICE exch def } if } if + +(START) VMDEBUG + +% Open the standard files, so they will be open at the outermost save level. +(%stdin) (r) file pop +(%stdout) (w) file pop +(%stderr) (w) file pop + +/.currentuserparams where { + pop mark + % The Adobe implementations appear to have very large maximum + % stack sizes. This turns out to actually make a difference, + % since some badly-behaved files include extremely long procedures, + % or construct huge arrays on the operand stack. + % We reset the stack sizes now so that we don't have to worry + % about overflowing the (rather small) built-in stack sizes + % during initialization. + /MaxDictStack 500 + /MaxExecStack 5000 + /MaxOpStack 65414 + .dicttomark .setuserparams +} if + +% Define a procedure for skipping over an unneeded section of code. +% This avoids allocating space for the skipped procedures. +% We can't use readline, because that imposes a line length limit. +/.skipeof % <string> .skipeof - + { currentfile exch 1 exch .subfiledecode flushfile + } .bind def + +% Define procedures to assist users who don't read the documentation. +userdict begin +/help + { (Enter PostScript commands. '(filename) run' runs a file, 'quit' exits.\n) + print flush + } .bind def +end + +% Define =string, which is used by some PostScript programs even though +% it isn't documented anywhere. +% Put it in userdict so that each context can have its own copy. +userdict /=string 256 string put + +% Print the greeting. + +/printgreeting + { mark + product (Ghostscript) search + { pop pop pop + (This software comes with NO WARRANTY: see the file PUBLIC for details.\n) + } + { pop + } + ifelse + (\n) copyright + (\)\n) revisiondate 10 mod revisiondate 10 idiv 10 mod (-) + revisiondate 100 idiv 10 mod revisiondate 1000 idiv 10 mod (-) + revisiondate 10000 idiv ( \() + revision 10 mod + revision 100 mod 10 idiv (.) + revision 100 idiv ( ) + product + counttomark + { (%stdout) (w) file exch 0 .writecvp + } repeat pop + } .bind def + +QUIET not { printgreeting flush } if + +% Define a special version of def for making operator procedures. +/obind { % <name> <proc> obind <name> <oper> + 1 index exch .makeoperator +} .bind def +/odef { % <name> <proc> odef - + 1 index exch .makeoperator def +} .bind def + +% Define a special version of def for storing local objects into global +% dictionaries. Like .forceput, this exists only during initialization. +/.forcedef { % <key> <value> .forcedef - + 1 .argindex pop % check # of args + currentdict 3 1 roll .forceput +} .bind odef + +% Define procedures for accessing variables in systemdict and userdict +% regardless of the contents of the dictionary stack. +/.systemvar { % <name> .systemvar <value> + //systemdict exch get +} .bind odef +/.userdict { % - .userdict <dict> + /userdict .systemvar +} .bind odef +/.uservar { % <name> .uservar <value> + .userdict exch get +} .bind odef + +% If we're delaying binding, remember everything that needs to be bound later. +DELAYBIND NOBIND not and + { .currentglobal false .setglobal + systemdict /.delaybind 1500 array .forceput + .setglobal + userdict /.delaycount 0 put + % When we've done the delayed bind, we want to stop saving. + % Detect this by the disappearance of .delaybind. + /bind + { /.delaybind .systemvar dup length 0 ne + { .delaycount 2 index put + .userdict /.delaycount .delaycount 1 add put + } + { pop /.bind cvx exec + } + ifelse + } .bind def + } if + +%**************** BACKWARD COMPATIBILITY **************** +/hwsizedict mark /HWSize //null .dicttomark readonly def +/copyscanlines { % <device> <y> <string> copyscanlines <substr> + 0 3 1 roll 3 index //hwsizedict .getdeviceparams + exch pop exch pop aload pop 3 2 roll + 0 exch //null exch .getbitsrect exch pop +} bind odef +currentdict /hwsizedict .undef +/getdeviceprops + { //null .getdeviceparams + } bind odef +/.putdeviceprops + { //null true counttomark 1 add 3 roll .putdeviceparams + dup type /booleantype ne + { dup mark eq { /unknown /rangecheck } if + counttomark 4 add 1 roll cleartomark pop pop pop + /.putdeviceprops .systemvar exch signalerror + } + if + } bind odef +/.currentfilladjust { .currentfilladjust2 pop } bind odef +/.setfilladjust { dup .setfilladjust2 } bind odef +/.writecvs { 0 .writecvp } bind odef +%**************** DEPRECATED PROCEDURES **************** +%**************** DO NOT USE THESE IN NEW CODE **************** +/max { .max } bind def % use .max instead +/min { .min } bind def % use .min instead +/unread /.unread load def % use .peekstring instead +%**************** END OF BACKWARD COMPATIBILITY SECTION **************** + +% Utility for removing all entries from a dictionary +/.PurgeDict % <dict> .PurgeDict - +{ { true + 1 index { pop exch pop false exit + } forall + { exit + } if + 1 index exch undef + } loop + pop +} bind def + +% Define predefined procedures substituting for operators, +% in alphabetical order. + +userdict /#copies 1 put +% Adobe implementations don't accept /[ or /], so we don't either. +([) cvn + /mark load def +(]) cvn + {counttomark array astore exch pop} odef +% .beginpage is redefined if setpagedevice is present. +/.beginpage { } odef +% In LanguageLevel 3, copypage erases the page. +/copypage { + .languagelevel 3 ge + dup { 0 } { 1 } ifelse .endpage .doneshowpage { + .currentnumcopies 1 index .outputpage + (>>copypage, press <return> to continue<<\n) .confirm + dup { erasepage } if + } if pop + systemdict /..page_default_spaces .knownget { //.PurgeDict exec } if + .beginpage +} odef +/currentmatrix { + dup type /arraytype ne + { /currentmatrix load /typecheck signalerror } if + dup length 6 ne + { /currentmatrix load /rangecheck signalerror } if + .currentmatrix 6 .argindex astore pop +} odef +% .currentnumcopies is redefined in Level 2. +/.currentnumcopies { #copies } odef +/setcolorscreen where { pop % not in all Level 1 configurations + /currentcolorscreen + { .currenthalftone + { { 60.0 exch 0.0 exch 3 copy 6 copy } % halftone - not possible + { 3 copy 6 copy } % screen + { } % colorscreen + } + exch get exec + } odef +} if +/currentscreen + { .currenthalftone + { { 60.0 exch 0.0 exch } % halftone - not possible + { } % screen + { 12 3 roll 9 { pop } repeat } % colorscreen + } + exch get exec + } odef +/.echo /echo load def +userdict /.echo.mode true put +/echo {dup /.echo.mode exch store .echo} odef +/.eexec_param_dict mark + /eexec true + /seed 55665 +.dicttomark readonly def +/eexec { + % Rebind .currentresourcefile if it is the source for the eexec. + dup //.eexec_param_dict //filterdict /eexecDecode get exec + cvx exch .currentresourcefile eq + //systemdict begin { {exec} .execasresource } { exec } ifelse + % Only pop systemdict if it is still the top element, + % because this is apparently what Adobe interpreters do. + currentdict //systemdict eq { end } if +} odef +% .endpage is redefined if setpagedevice is present. +/.endpage { 2 ne } odef +% erasepage mustn't use gsave/grestore, because we call it before +% the graphics state stack has been fully initialized. +/erasepage + { /currentcolor where + { pop currentcolor currentcolorspace { setcolorspace setcolor } } + { /currentcmykcolor where + { pop currentcmykcolor { setcmykcolor } } + { currentrgbcolor { setrgbcolor } } + ifelse + } + ifelse + currentoverprint false setoverprint 1 setgray .fillpage setoverprint + exec + } odef +% To satisfy the Genoa FTS, executive must be a procedure, not an operator. +/executive + { { prompt + { (%statementedit) (r) .systemvmfile } stopped + { pop pop $error /errorname get /undefinedfilename eq + { .clearerror exit } if % EOF + /handleerror .systemvar exec //null % ioerror?? + } + if + cvx { .runexec } execute + } loop + } bind def +/filter + { //filterdict 1 .argindex .knownget + { exch pop exec } + { /filter .systemvar /undefined signalerror } + ifelse + } odef +% handleerror procedure as mentioned in the "Operators" section of the PLRM Section 8.2 +% This invokes the handleerror procedure from errordict (unless we are running under a +% JOBSERVER where we want to always use a defined error handler (many error handlers in +% 'wild' PostScript files are broken and don't indicate the error in any useful fashion). +% +% We run the handleerror procedure using .internalstopped so that broken error handlers +% won't cause nested errors (Unexpected Error conditions). +/handleerror + JOBSERVER { + { /.GShandleerror .systemvar .internalstopped pop } bind % always use .GShandleerror. + } { + { /errordict .systemvar /handleerror get .internalstopped pop } bind % PLRM standard errorhandling + } ifelse def +/identmatrix [1.0 0.0 0.0 1.0 0.0 0.0] readonly def +/identmatrix { + dup type /arraytype ne { /identmatrix load /typecheck signalerror } if + dup length 6 ne { /identmatrix load /rangecheck signalerror } if + dup 0 //identmatrix putinterval +} odef +/languagelevel 1 def % gs_lev2.ps may change this +/makeimagedevice { false makewordimagedevice } odef +/matrix { 6 array identmatrix } odef +% .promptmsg is redefined if the interpreter includes readline support. +/.promptmsg { + (GS) print + count 0 ne { (<) print count =only } if + (>) print flush +} bind def +/prompt { flush flushpage NOPROMPT not { .promptmsg } if } bind def +/pstack { 0 1 count 3 sub { index == } for } bind def +/putdeviceprops + { .putdeviceprops { erasepage } if } odef +/quit { /quit load 0 .quit } odef +/run { dup type /filetype ne { (r) .systemvmfile } if + % We must close the file when execution terminates, + % regardless of the state of the stack, + % and then propagate an error, if any. + cvx null {.runexec} .errorexec + } odef +% Execute a file. +% Level 2 uses 2 .stop to clear the e-stack for a successful startjob: +% we detect that here, since we need to handle this even if we start out +% without job control in effect. +% +% What we push on the e-stack is the following to be executed in this order: +% <lit-file|fileproc> .runexec1 <lit-file|fileproc> .runexec2 +/.runexec1 { % <file|fileproc> .runexec1 - + dup type /filetype ne { cvx exec } if + cvx //null 2 .stopped + % If we got back here from a startjob, just keep going. + % startjob replaces the null on the o-stack with a procedure + % to be executed when we get back here. + dup //null ne { exec true } { pop false } ifelse +} bind def +/.runexec2 { % <continue> <file|fileproc> .runexec2 - + exch { + .runexec + } { + dup type /filetype ne { cvx exec } if + closefile + } ifelse +} bind def +/.runexec { % <file|fileproc> .runexec - + cvlit /.runexec1 cvx 1 index /.runexec2 cvx 4 .execn +} bind def +% The following is only for compatibility with Adobe interpreters. +/setdash { + 0 .argindex type dup /integertype eq exch /realtype eq or not { + /setdash .systemvar /typecheck signalerror + } if + 1 .argindex length 11 gt { /setdash .systemvar /limitcheck signalerror } if + //setdash +} odef +/setdevice + { + .setdevice + { + mark + { % Reset the halftone since the device may differ + currenthalftone + dup type /dicttype eq + { sethalftone } + { pop } + ifelse + } + stopped + cleartomark + erasepage + } + if + } +odef +/setlinecap { + dup 2 gt { /setlinecap .systemvar /rangecheck signalerror } if + .setlinecap +} odef +/setlinejoin { + dup 2 gt { /setlinejoin .systemvar /rangecheck signalerror } if + .setlinejoin +} odef +/setmatrix { + dup type /arraytype ne { + dup type /packedarraytype ne { + /setmatrix load /typecheck signalerror + } if + } if + dup length 6 ne { /setmatrix load /rangecheck signalerror } if + dup aload pop .setmatrix pop +} odef +/showpage { + 0 .endpage .doneshowpage { + .currentnumcopies true .outputpage + (>>showpage, press <return> to continue<<\n) .confirm + initgraphics + currentoverprint false setoverprint 1 setcolor + .fillpage + setoverprint 0 setcolor + } + { initgraphics } ifelse + systemdict /..page_default_spaces .knownget { //.PurgeDict exec } if + .beginpage +} odef +% Code output by Adobe Illustrator relies on the fact that +% `stack' is a procedure, not an operator!!! +/stack { 0 1 count 3 sub { index = } for } bind def +/start { BATCH { //null 0 .quit } { executive } ifelse } def +% Internal uses of stopped that aren't going to do a stop if an error occurs +% should use .internalstopped to avoid setting newerror et al. +/.internalstopped { //null 1 .stopped //null ne } bind def +/store { % Don't alter operands before completing. + 1 .argindex where { 2 index 2 index put pop pop } { def } ifelse +} odef +/.typenames mark .typenames counttomark packedarray exch pop def +/type { + //.typenames .type +} odef +currentdict /.typenames .undef +% When running in Level 1 mode, this interpreter is supposed to be +% compatible with PostScript "version" 54.0 (I think). +/version (54.0) readonly def +/.wheredict 10 dict def +/.where /where load def +/where { + //.wheredict 1 .argindex .knownget { exec } { .where } ifelse +} odef + +% internaldict is defined in systemdict, but the dictionary is allocated +% in local VM. However, the procedure must be global, since it is an +% "operator" and must be bind-able into global procedures. +% We make a procedure for creating it, since we must create a new one +% for each context with private local VM. +/.makeinternaldict { + .currentglobal true .setglobal + [ /dup .systemvar 1183615869 /eq .systemvar + [ /pop .systemvar //null ] cvx + false .setglobal + dup 1 10 dict .forceput % proc is global, dict is local + true .setglobal + [ /internaldict /cvx .systemvar /invalidaccess /signalerror cvx ] cvx + /ifelse .systemvar + ] cvx executeonly + exch .setglobal +} odef +systemdict /internaldict dup .makeinternaldict .makeoperator +.forceput % proc is local, systemdict is global + +% Define some additional built-in procedures (beyond the ones defined by +% the PostScript Language Reference Manual). +% Warning: these are not guaranteed to stay the same from one release +% to the next! +/concatstrings % (str1) (str2) concatstrings (str1str2) + { exch dup length 2 index length add string % str2 str1 new + dup dup 4 2 roll copy % str2 new new new1 + length 4 -1 roll putinterval + } bind def +/copyarray + { dup length array copy } bind def +% Copy a dictionary per the Level 2 spec even in Level 1. +/.copydict % <fromdict> <todict> .copydict <todict> + { dup 3 -1 roll { put dup } forall pop } bind def +/copystring + { dup length string copy } bind def +/findlibfile { + .systemvmlibfile { dup .filename pop exch true } { false } ifelse +} odef +/.growdictlength % get size for growing a dictionary + { length 3 mul 2 idiv 1 add + } bind def +/.growdict % grow a dictionary + { dup .growdictlength .setmaxlength + } bind def +/.growput % put, grow the dictionary if needed + { 2 index length 3 index maxlength eq + { 3 copy pop known not { 2 index .growdict } if + } if + put + } bind def +% .localvmarray may be an operator: see zsysvm.c. +/.localvmarray where { + pop +} { + /.localvmarray { + .currentglobal false .setglobal + exch array exch .setglobal + } bind def +} ifelse +/.localvmdict where { + pop +} { + /.localvmdict { + .currentglobal false .setglobal + exch dict exch .setglobal + } bind def +} ifelse +/.packtomark + { counttomark packedarray exch pop } bind def +/ppstack + { 0 1 count 3 sub { index === } for } bind def +/runlibfile + { % We don't want to bind 'run' into this procedure, + % since run may get redefined. + findlibfile + { exch pop /run .systemvar exec } + { /undefinedfilename signalerror } + ifelse + } bind def +/selectdevice + { finddevice setdevice .setdefaultscreen } bind def +/signalerror % <object> <errorname> signalerror - + { /errordict .systemvar exch get exec } bind def +/signaloperror { % <object> <errorname> signaloperror - + % Same as signalerror, except that if we are inside a pseudo-operator + % or .errorexec, we use its error object, just as errors generated by + % real operators do. + /errordict .systemvar exch get + .finderrorobject { 3 -1 roll pop exch } if + exec +} bind def + +% Define the =[only] procedures. Also define =print, +% which is used by some PostScript programs even though +% it isn't documented anywhere. +/write=only { + .writecvs +} bind def +/write= { + 1 index exch write=only (\n) writestring +} bind def +/=only { (%stdout) (w) file exch write=only } bind def +/= { =only (\n) print } bind def +/=print /=only load def +% Temporarily define == as = for the sake of runlibfile0. +/== /= load def + +% The following procedures are documented. +/copydevice { % <device> copydevice <newdevice> + false .copydevice2 +} odef +/finddevice { % <devicename> finddevice <device> + /devicedict .systemvar exch get + dup 1 get //null eq { + % This is the first request for this type of device. + % Create a default instance now. + % Stack: [proto null] + .currentglobal true .setglobal exch + dup dup 0 get copydevice 1 exch put + exch .setglobal + } if 1 get +} bind def +/findprotodevice { % <devicename> findprotodevice <protodevice> + /devicedict .systemvar exch get 0 get +} bind def + +% Run a resource file. This allows us to distinguish resource objects +% from objects coming from input files. +userdict /.currentresourcefile //null put +/.execasresource { % <file> <proc|runfile> .execasresource - + /stopped .systemvar + /.currentresourcefile .uservar + % Stack: file proc -stopped- currfile + .userdict /.currentresourcefile 5 index cvlit put + 2 .execn % stopped <file> + .userdict /.currentresourcefile 3 -1 roll put + { stop } if +} bind def +/.runresource { % <file> .runresource - + { //run } .execasresource % immediately bind run to ignore redefinitions +} bind def + +% Define procedures for getting and setting the current device resolution. + +/gsgetdeviceprop % <device> <propname> gsgetdeviceprop <value> + { 2 copy mark exch //null .dicttomark .getdeviceparams + dup mark eq % if true, not found + { pop dup /undefined signalerror } + { 5 1 roll pop pop pop pop } + ifelse + } bind def +/gscurrentresolution % - gscurrentresolution <[xres yres]> + { currentdevice /HWResolution gsgetdeviceprop + } bind def +/gssetresolution % <[xres yres]> gssetresolution - + { 2 array astore mark exch /HWResolution exch + currentdevice copydevice putdeviceprops setdevice + } bind def + +% Define auxiliary procedures needed for the above. +/shellarguments % -> shell_arguments true (or) false + { /ARGUMENTS where + { /ARGUMENTS get dup type /arraytype eq + { aload pop /ARGUMENTS //null store true } + { pop false } + ifelse } + { false } ifelse + } bind def +/.confirm { + DISPLAYING NOPAUSE not TTYPAUSE or and { + % Print a message (unless NOPAGEPROMPT or NOPROMPT is true) + % and wait for the user to type something. + % If the user just types a newline, flush it. + NOPAGEPROMPT NOPROMPT or { pop } { print flush } ifelse + .confirmread + } { + pop + } ifelse +} bind def +/.confirmread { + TTYPAUSE { + (/dev/tty) (r) file dup read pop pop closefile + } { + .echo.mode false echo + (%stdin) (r) file dup read { + dup (\n) 0 get eq { pop pop } { unread } ifelse + } { + pop + } ifelse echo + } ifelse +} bind def + +% Define the procedure used by .runfile, .runstdin and .runstring +% for executing user input. +% This is called with a procedure or executable file on the operand stack. +/.execute { % <obj> .execute <stopped> + stopped $error /newerror get and + { /handleerror .systemvar exec flush true } { false } ifelse +} bind def +/execute { % <obj> execute - + .execute pop +} odef +% Define an execute analogue of runlibfile0. +/execute0 { % <obj> execute0 - + .execute { /execute0 cvx 1 .quit } if +} bind def +% Define the procedure that the C code uses for running files +% named on the command line. +/.runfile { + { runlibfile } execute0 +} def +% Define the procedure that the C code uses for running piped input. +% We don't use the obvious { (%stdin) run }, because we want the file to be +% reopened if a startjob does a restore. +/.runstdin { + { { (%stdin) (r) file cvx } .runexec } execute0 +} bind def +% Define the procedure that the C code uses for running commands +% given on the command line with -c. We turn the string into a file so that +% .runexec can do the right thing with a startjob. +/.runstring { + 0 0 .systemvmstring .systemvmSFD cvx { .runexec } execute0 +} bind def +% Define the procedure that the C code uses to set up for executing +% a string that may be received in pieces. +/.runstringbegin { + 1 .systemvmarray dup 0 /.needinput load put cvx % { .needinput } in systemvm + 0 0 .systemvmstring .systemvmSFD cvx .runexec +} bind def + +% Define a special version of runlibfile that aborts on errors. +/runlibfile0 + { cvlit dup dup /.currentfilename exch def + { findlibfile not { stop } if } + stopped + { (Can't find \(or open\) initialization file ) print + .currentfilename == flush /runlibfile0 cvx 1 .quit + } if + exch pop cvx + { stopped } 0 get 3 -1 roll 2 array astore cvx exec + /.currentfilename exch store + { (While reading ) print .currentfilename print (:\n) print flush + /handleerror .systemvar exec /runlibfile0 1 .quit + } if + } bind def +% Temporarily substitute it for the real runlibfile. +/.runlibfile /runlibfile load def +/runlibfile /runlibfile0 load def + +% Create the error handling machinery. +% Define the standard error handlers. +% The interpreter has created the ErrorNames array. +/.unstoppederrorhandler % <command> <errorname> .unstoppederrorhandler - + { % This is the handler that gets used for recursive errors, + % or errors outside the scope of a 'stopped'. + 2 copy SHORTERRORS + { (%%[ Error: ) print =only flush + (; OffendingCommand: ) print =only ( ]%%) = + } + { (Unrecoverable error: ) print =only flush + ( in ) print = flush + count 2 gt + { (Operand stack:\n ) print + count 1 sub -1 2 { ( ) print index =only flush } for + () = flush + } if + } + ifelse + -1 0 1 //ErrorNames length 1 sub + { dup //ErrorNames exch get 3 index eq + { not exch pop exit } { pop } ifelse + } + for exch pop .quit + } bind def +/.errorhandler % <command> <errorname> .errorhandler - + { % Detect an internal 'stopped'. + 1 .instopped { //null eq { pop pop stop } if } if + (I) false .setdebug + $error /.inerror get 1 .instopped { pop } { pop true } ifelse + { .unstoppederrorhandler + } if % detect error recursion + $error /globalmode .currentglobal false .setglobal put + $error /.inerror true put + $error /newerror true put + $error exch /errorname exch put + $error exch /command exch put + $error /errorinfo known not { $error /errorinfo //null put } if + $error /recordstacks get $error /errorname get /VMerror ne and + { % Attempt to store the stack contents atomically. + count array astore dup $error /ostack 4 -1 roll + % Grab the execstack, then remove to two elements that are from + % this error handler (not interesting). + countexecstack array execstack dup length 2 sub 0 exch getinterval + $error /estack 3 -1 roll + countdictstack array dictstack $error /dstack 3 -1 roll + put put put aload pop + } + { $error /dstack .undef + $error /estack .undef + $error /ostack .undef + } + ifelse + $error /position currentfile status + { currentfile { fileposition } .internalstopped { pop //null } if + } + { % If this was a scanner error, the file is no longer current, + % but the command holds the file, which may still be open. + $error /command get dup type /filetype eq + { { fileposition } .internalstopped { pop //null } if } + { pop //null } + ifelse + } + ifelse put + % During initialization, we don't reset the allocation + % mode on errors. + $error /globalmode get $error /.nosetlocal get and .setglobal + $error /.inerror false put + stop + } bind def +% Define the standard handleerror. We break out the printing procedure +% (.printerror) so that it can be extended for binary output +% if the Level 2 facilities are present. + /.printerror + { $error begin newerror + { + /command load errorname SHORTERRORS + { (%%[ Error: ) print =only flush + (; OffendingCommand: ) print =only + errorinfo dup //null eq { + pop + } { + (;\nErrorInfo:) print + dup type /arraytype eq + { { ( ) print =only } forall } + { ( ) print =only } + ifelse + } ifelse + ( ]%%) = flush + } + { (Error: ) print ==only flush + ( in ) print ==only flush + errorinfo dup //null eq { + pop + } { + (\nAdditional information: ) print ==only flush + } ifelse + .printerror_long + } + ifelse + .clearerror flush + } + { % newerror is false, test to see if user has set handleerror to a different + % routine, if so execute it, otherwise, just return. This code deals with the + % Genoa issue of setting /handleerror, and then calling it, without an error + % being set. We were erroring in this case, due to /command load failing. + + //JOBSERVER { + /errordict .systemvar /handleerror get /.GShandleerror .systemvar ne + } { + false + } ifelse + { /errordict .systemvar begin /handleerror load .internalstopped pop end + } + if + } + ifelse % newerror + end + flush + } bind def + /.printerror_long % long error printout, + % $error is on the dict stack + { % Push the (anonymous) stack printing procedure. + % <heading> <==flag> <override-name> <stackname> proc + { + currentdict exch .knownget % stackname defined in $error? + { + 4 1 roll % stack: <stack> <head> <==flag> <over> + /errordict .systemvar exch .knownget % overridename defined? + { + exch pop exch pop exec % call override with <stack> + } + { + exch print exch % print heading. stack <==flag> <stack> + 1 index not { () = } if + { 1 index { (\n ) } { ( ) } ifelse print + dup type /dicttype eq + { + (--dict:) print + dup rcheck { + dup length =only (/) print dup maxlength =only + dup wcheck not { ((ro)) print } if + } if + /gcheck where { + pop gcheck { ((G)) } { ((L)) } ifelse print + } { + pop + } ifelse (--) print + } + { + dup type /stringtype eq 2 index or + { ==only } { =only } ifelse + } ifelse + } forall + pop + } + ifelse % overridden + } + { pop pop pop + } + ifelse % stack known + } + + (\nOperand stack:) OSTACKPRINT /.printostack /ostack 4 index exec + (\nExecution stack:) ESTACKPRINT /.printestack /estack 4 index exec + (\nBacktrace:) true /.printbacktrace /backtrace 4 index exec + (\nDictionary stack:) false /.printdstack /dstack 4 index exec + () = + pop % printing procedure + + errorname /VMerror eq + { (VM status:) print mark vmstatus + counttomark { ( ) print counttomark -1 roll dup =only } repeat + cleartomark () = + } if + + .languagelevel 2 ge + { (Current allocation mode is ) print + globalmode { (global\n) } { (local\n) } ifelse print + } if + + .oserrno dup 0 ne + { (Last OS error: ) print + errorname /VMerror ne + { dup .oserrorstring { = pop } { = } ifelse } + { = } + ifelse + } + { pop + } + ifelse + + position //null ne + { (Current file position is ) print position = } + if + + } bind def +% Define a procedure for clearing the error indication. +/.clearerror + { $error /newerror false put + $error /errorname //null put + $error /errorinfo //null put + 0 .setoserrno + } bind def + +% Define $error. This must be in local VM. +.currentglobal false .setglobal +/$error 40 dict .forcedef % $error is local, systemdict is global + % newerror, errorname, command, errorinfo, + % ostack, estack, dstack, recordstacks, + % binary, globalmode, + % .inerror, .nosetlocal, position, + % plus extra space for badly designed error handers. +$error begin + /newerror false def + /recordstacks true def + /binary false def + /globalmode .currentglobal def + /.inerror false def + /.nosetlocal true def + /position //null def + /errorinfo //null def +end +% Define errordict similarly. It has one entry per error name, +% plus handleerror. However, some astonishingly badly written PostScript +% files require it to have at least one empty slot. +/errordict ErrorNames length 3 add dict +.forcedef % errordict is local, systemdict is global +.setglobal % back to global VM +% For greater Adobe compatibility, we put all non-standard errors in a +% separate dictionary, gserrordict. It does not need to be in local VM, +% because PostScript programs do not access it. +% NOTE: the name gserrordict is known to the interpreter. +/gserrordict 5 dict def +% Register an error in errordict. We make this a procedure because we only +% register the Level 1 errors here: the rest are registered by "feature" +% files. However, ErrorNames contains all of the error names regardless of +% what features are included, so we have to "know" that VMerror is the last +% Level 1 error. +/.registererror % <name> .registererror - + { errordict exch .registererror2 + } bind def +/.registererror2 % <dict> <name> .registererror - + { .currentglobal true .setglobal % create procs in global VM + 3 1 roll + mark 1 index systemdict /.errorhandler get /exec load .packtomark cvx put + .setglobal + } bind def +ErrorNames + { dup .registererror /VMerror eq {exit} if + } forall +errordict begin +% The handlers for interrupt and timeout are special; there is no +% 'current object', so they push their own name. + { /interrupt /timeout } + { mark 1 index dup systemdict /.errorhandler get /exec load .packtomark cvx def + } forall +/handleerror % this key is 'well known' and some PS may redefine it + { /.printerror .systemvar exec + } bind def +end % errordict + +% Put non-standard errors in gserrordict. +gserrordict /unknownerror errordict /unknownerror get put +errordict /unknownerror .undef +% Define a stable private copy of handleerror that we will always use under +% JOBSERVER mode. +/.GShandleerror errordict /handleerror get def + +% Define the [write]==[only] procedures. +/.dict 8 dict dup +begin def + /.cvp {1 index exch 1 .writecvp} bind def + /.p {1 index exch writestring} bind def + /.p1 {2 index exch writestring} bind def + /.p2 {3 index exch writestring} bind def + /.print + { dup type .dict exch .knownget { exec } { .cvp } ifelse + } bind def + /arraytype + {dup rcheck + {() exch dup xcheck + {({) .p2 + {exch .p1 + 1 index exch .print pop ( )} forall + (})} + {([) .p2 + {exch .p1 + 1 index exch .print pop ( )} forall + (])} + ifelse exch pop .p} + {.cvp} + ifelse} bind def + /packedarraytype /arraytype load def +{//.dict begin .print pop end} + bind +end + +/write==only exch def +/write== {1 index exch write==only (\n) writestring} bind def +/==only { (%stdout) (w) file exch write==only } bind def +/== {==only (\n) print} bind def + +% Define [write]===[only], an extension that prints dictionaries +% in readable form and doesn't truncate strings. +/.dict /write==only load 0 get dup length 2 add dict .copydict dup +begin def + /dicttype + { dup rcheck + { (<< ) .p1 + { 2 index 3 -1 roll .print pop ( ) .p1 + 1 index exch .print pop ( ) .p + } + forall (>>) .p + } + { .cvp + } + ifelse + } bind def + /stringtype + { 1 index exch 2 .writecvp + } bind def + +{//.dict begin .print pop end} + bind +end + +/write===only exch def +/write=== {1 index exch write===only (\n) writestring} bind def +/===only { (%stdout) (w) file exch write===only } bind def +/=== { ===only (\n) print } bind def + +% Create the initialization queue. + +/.delayed_init_queue 10 dict def + +/.schedule_init % <priority> <proc> .schedule_init - +{ + //.delayed_init_queue 2 index known { + (.delayed_init_queue priority conflict with ) print 1 index = + /.schedule_init cvx /configurationerror signalerror + } if + //.delayed_init_queue 3 1 roll .growput +} bind def + +/.execute_scheduled_inits % - .execute_scheduled_inits - +{ + { 0 //null //.delayed_init_queue { % maxp {} p {} + 3 index 2 index lt { + 4 2 roll + } if + pop pop + } forall + exch //.delayed_init_queue exch undef + dup //null eq { + pop exit + } if + exec + } loop +} bind def + +(END PROCS) VMDEBUG + +% Define the font directory. +/FontDirectory false .setglobal 100 dict true .setglobal +.forcedef % FontDirectory is local, systemdict is global + +% Define the encoding dictionary. +/EncodingDirectory 16 dict def % enough for Level 2 + PDF standard encodings + +% Define .findencoding. (This is redefined in Level 2.) +/.findencoding + { //EncodingDirectory exch get exec + } bind def +/.defineencoding + { //EncodingDirectory 3 1 roll put + } bind def +% If we've got the composite font extensions, define findencoding. +% To satisfy the Genoa FTS, findencoding must be a procedure, not an operator. +/rootfont where { pop /findencoding { .findencoding } def } if + +% Define .registerencoding. +% NOTE: This procedure no longer does anything, but it must continue to +% exist for the sake of toolbin/encs2c.ps. +/.registerencoding { % <index> <array> .registerencoding - + pop pop +} bind odef + +% Load StandardEncoding. +%% Replace 1 (gs_std_e.ps) +(gs_std_e.ps) dup runlibfile VMDEBUG + +% Load ISOLatin1Encoding. +%% Replace 1 (gs_il1_e.ps) +(gs_il1_e.ps) dup runlibfile VMDEBUG + +% Define stubs for the Symbol and Dingbats encodings. +% Note that the first element of the procedure must be the file name, +% since gs_lev2.ps extracts it to set up the Encoding resource category. + + /SymbolEncoding { /SymbolEncoding .findencoding } bind def +%% Replace 3 (gs_sym_e.ps) + EncodingDirectory /SymbolEncoding + { (gs_sym_e.ps) //systemdict begin runlibfile SymbolEncoding end } + bind put + + /DingbatsEncoding { /DingbatsEncoding .findencoding } bind def +%% Replace 3 (gs_dbt_e.ps) + EncodingDirectory /DingbatsEncoding + { (gs_dbt_e.ps) //systemdict begin runlibfile DingbatsEncoding end } + bind put + +(END FONTDIR/ENCS) VMDEBUG + +% Construct a dictionary of all available devices. +% These are (read-only) device prototypes that can't be +% installed or have their parameters changed. For this reason, +% the value in the dictionary is actually a 2-element writable array, +% to allow us to create a default instance of the prototype on demand. + + % Loop until the .getdevice gets a rangecheck. +errordict /rangecheck 2 copy get +errordict /rangecheck { pop stop } put % pop the command + 0 { {dup .getdevice exch 1 add} loop} .internalstopped pop + 1 add dict /devicedict 1 index def + begin % 2nd copy of count is on stack + { dup .devicename exch + dup wcheck { dup } { //null } ifelse 2 array astore def + } repeat + end +put % errordict /rangecheck +.clearerror +/devicenames devicedict { pop } forall devicedict length packedarray def + +% Determine the default device. +/defaultdevice DISPLAYING + { systemdict /DEVICE .knownget + { devicedict 1 index known not + { (Unknown device: ) print = + flush /defaultdevice cvx 1 .quit + } + if + } + { .getdefaultdevice .devicename + } + ifelse + } + { /nullpage + } +ifelse +/.defaultdevicename 1 index def +finddevice % make a copy +def +devicedict /Default devicedict .defaultdevicename get put + +(END DEVS) VMDEBUG + +% Define statusdict, for the benefit of programs +% that think they are running on a LaserWriter or similar printer. +%% Replace 1 (gs_statd.ps) +(gs_statd.ps) runlibfile + +(END STATD) VMDEBUG + +% Load the standard font environment. +%% Replace 1 (gs_fonts.ps) +(gs_fonts.ps) runlibfile + +(END GS_FONTS) VMDEBUG + +% Define the default halftone screen and BG/UCR functions now, so that +% it will bind in the original definitions of set[color]screen. +% We make this a procedure so we can call it again when switching devices. + +% Use an ordered dither for low-resolution devices. +/.setloreshalftone { % <dpi> .setloreshalftone - + % The following 'ordered dither' spot function was contributed by + % Gregg Townsend. Thanks, Gregg! + 16.001 div 0 % not 16: avoids rounding problems + { 1 add 7.9999 mul cvi exch 1 add 7.9999 mul cvi 16 mul add < + 0E 8E 2E AE 06 86 26 A6 0C 8C 2C AC 04 84 24 A4 + CE 4E EE 6E C6 46 E6 66 CC 4C EC 6C C4 44 E4 64 + 3E BE 1E 9E 36 B6 16 96 3C BC 1C 9C 34 B4 14 94 + FE 7E DE 5E F6 76 D6 56 FC 7C DC 5C F4 74 D4 54 + 01 81 21 A1 09 89 29 A9 03 83 23 A3 0B 8B 2B AB + C1 41 E1 61 C9 49 E9 69 C3 43 E3 63 CB 4B EB 6B + 31 B1 11 91 39 B9 19 99 33 B3 13 93 3B BB 1B 9B + F1 71 D1 51 F9 79 D9 59 F3 73 D3 53 FB 7B DB 5B + 0D 8D 2D AD 05 85 25 A5 0F 8F 2F AF 07 87 27 A7 + CD 4D ED 6D C5 45 E5 65 CF 4F EF 6F C7 47 E7 67 + 3D BD 1D 9D 35 B5 15 95 3F BF 1F 9F 37 B7 17 97 + FD 7D DD 5D F5 75 D5 55 FF 7F DF 5F F7 77 D7 57 + 02 82 22 A2 0A 8A 2A AA 00 80 20 A0 08 88 28 A8 + C2 42 E2 62 CA 4A EA 6A C0 40 E0 60 C8 48 E8 68 + 32 B2 12 92 3A BA 1A 9A 30 B0 10 90 38 B8 18 98 + F2 72 D2 52 FA 7A DA 5A F0 70 D0 50 F8 78 D8 58 + > exch get 256 div + } + bind + % Use correct, per-plane screens for CMYK devices only. + //systemdict /setcolorscreen known processcolors 4 eq and + { 3 copy 6 copy //setcolorscreen } + { //setscreen } + ifelse +} bind def +/.setloresscreen { % <dpi> .setloresscreen - + .setloreshalftone + 0 array cvx settransfer % Genoa CET won't accept a packed array! + /setstrokeadjust where { pop true setstrokeadjust } if +} bind def +% Use a 45-degree spot screen for high-resolution devices. +% The PS3 CET insists that the screen be an array and not a packedarray (!). +currentpacking false setpacking +/.linescreen +% The following screen algorithm is used by permission of the author. + { ((C) 1989 Berthold K.P. Horn) pop + 1 add 180 mul cos 1 0.08 add mul exch 2 add 180 mul cos + 1 0.08 sub mul add 2 div + } +bind readonly def +setpacking +/.sethireshalftone { % <dpi> .sethireshalftone <doscreen> + % According to information published by Hewlett-Packard, + % they use a 60 line screen on 300 DPI printers and + % an 85 line screen on 600 DPI printers. + % However, we use a 106 line screen, which produces smoother- + % looking shades but fewer of them (32 vs. 50). + % 46 was suggested as a good frequency value for printers + % between 200 and 400 DPI, so we use it for lower resolutions. + % Imagesetters need even higher frequency screens. + //systemdict /DITHERPPI known + { DITHERPPI + } + { dup cvi 100 idiv 15 .min + {//null 46 46 60 60 60 106 106 106 106 133 133 133 133 133 150} + exch get + } + ifelse + 1 index 4.01 div .min % at least a 4x4 cell + 45 + //.linescreen + % Determine whether we have lots of process colors. + % If so, don't bother with color screening or gamma correction. + % Also don't do gamma correction on very high-resolution devices. + % (This should depend on dot gain, not resolution, but we don't + % currently have a way to determine this.) Ignore missing components + % (*Values = 1). + currentdevice mark + /RedValues 0 /GreenValues 0 /BlueValues 0 /GrayValues 0 + .dicttomark .getdeviceparams + counttomark 2 idiv 1 sub + { exch pop dup 1 le + { pop } + { exch dup 1 le + { pop } + { .min } + ifelse + } + ifelse + } + repeat + exch pop exch pop 32 lt 4 index 800 lt and 5 1 roll + % Stack: doscreen dpi freq angle proc + % Ghostscript currently doesn't use correct, per-plane halftones + % unless setcolorscreen has been executed. Since these are + % computationally much more expensive than binary halftones, + % we check to make sure they are really warranted, i.e., we have + % a high-resolution CMYK device (i.e., not a display) with + % fewer than 5 bits per plane (i.e., not a true-color device). + 4 -1 roll 150 ge + { /setcolorscreen where + { pop //systemdict /COLORSCREEN known + { COLORSCREEN } + { 3 index } + ifelse + dup false ne + { 4 1 roll 3 copy 6 copy 13 -1 roll + % For really high-quality screening on printers, we need to + % give each plane its own screen angle. Unfortunately, + % this currently has very large space and time costs. + true eq % true => different angles, + % 0 => same angles + { { 45 90 15 75 } { 3 1 roll exch pop 12 3 roll } forall + } + if //setcolorscreen + } + { pop //setscreen % false => single binary screen + } + ifelse + } + { //setscreen % setcolorscreen not known + } + ifelse + } + { //setscreen % not high resolution + } + ifelse +} bind def +/.sethiresscreen { % <dpi> .sethiresscreen + .sethireshalftone % pushes true if a screen halftone used + % Stack: doscree + { + % Set the transfer function to lighten up the grays. + % Parameter values closer to 1 are better for devices with + % less dot spreading; lower values are better with more spreading. + % The value 0.8 is a compromise that will probably please no one! + % + % Because of a bug in FrameMaker, we have to accept operands + % outside the valid range of [0..1]. + { + dup dup 0.0 gt exch 1.0 lt and + { + 0.8 exp + } + if + } + } + { + % Set the transfer function to the identity. + 0 array cvx % Genoa CET won't accept a packed array! + } + ifelse + settransfer + /setstrokeadjust where + { pop false setstrokeadjust } + if + + % Increase fill adjustment so that we effectively use Adobe's + % any-part-of-pixel rule. + 0.5 .setfilladjust +} bind def +% Set the default screen and BG/UCR. +/.setdefaultbgucr { + systemdict /setblackgeneration known { + { pop 0 } dup setblackgeneration setundercolorremoval + } if +} bind def +/.useloresscreen { % - .useloresscreen <bool> + % Compute min(|dpi x|,|dpi y|) as the definition of the resolution. + 72 72 matrix defaultmatrix dtransform abs exch abs .min + dup 150 lt //systemdict /DITHERPPI known not and +} bind def + +% The following implementation uses LL2 extensions, but only in stopped +% contexts so that with LL1, the .set??reshalftone will be used. +% +% - .getdefaulthalftone <halftonedict> true if default found +% false +/.getdefaulthalftone { + % try the device to see if it has a default halftone + { currentdevice /HalftoneDefault gsgetdeviceprop } .internalstopped + { pop pop false } % no device property + { dup type /dicttype eq { true } { pop false } ifelse } + ifelse + % stack: <halftonedict> true if default found + % false not found + dup not + { % device did not provide a default, try Resource + pop { /Default /Halftone /findresource .systemvar exec } .internalstopped + { pop pop false } { true } ifelse + } + if +} bind def + +/.setdefaulthalftone { + .getdefaulthalftone + { sethalftone } + { % default not found + .useloresscreen { .setloreshalftone } { .sethireshalftone pop } ifelse + } + ifelse +} bind def + +/.setdefaultscreen { + .useloresscreen { .setloresscreen } { .sethiresscreen } ifelse + .setdefaultbgucr +} bind def + +% Rendering intent mapping for setcolorrendering1 and PDF interpreter +/.renderingintentdict mark + /Perceptual 0 + /RelativeColorimetric 1 + /Saturation 2 + /AbsoluteColorimetric 3 +.dicttomark readonly def + +% Load basic color support +%% Replace 1 (gs_cspace.ps) +(gs_cspace.ps) runlibfile + +(END BASIC COLOR) VMDEBUG + +%% Replace 1 (gs_devcs.ps) +(gs_devcs.ps) runlibfile + +(END LEVEL 1 COLOR) VMDEBUG + +% Load image support +%% Replace 1 (gs_img.ps) +(gs_img.ps) runlibfile + +(END IMAGE) VMDEBUG + +% Auxiliary procedures for generating file name templates. + +% Convert a path name into a string suitable for filenameforall +% For example: (a\\b*?c) to (a\\\\b\\*\\?c) +/.makepathtemplate { % str1 -- str2 + dup length dup add string 0 % result string up to twice the size + 0 1 4 index length 1 sub { + 3 index exch get + dup 92 eq { % \ -> \\ + 2 index 2 index 92 + put + exch 1 add exch + } + if + dup 42 eq { % * -> \* + 2 index 2 index 92 + put + exch 1 add exch + } + if + dup 63 eq { % ? -> \? + 2 index 2 index 92 + put + exch 1 add exch + } + if + 2 index 2 index 3 -1 roll put 1 add + } for + 0 exch getinterval exch pop +} bind def + +% false <dir_list> <template> .generate_dir_list_templates_with_length <t1> ... <tN> +% true <dir_list> <template> .generate_dir_list_templates_with_length <t1> <l1> ... <tN> <ln> +% +% Generates various valid templates combining a directory list with a given template. +% With 'true' operand it also returns lengths of directory pathes. +% +% Example1 (DOS, Windows) : +% false [(/gs/lib) (/gs/Resource/) (\gs8.00\Resource)] (*/*) --> +% (/gs/lib/*/*) (/gs/Resource/*/*) (\\gs8.00\\Resource/*/*) +% +% Example2 (OpenVMS) : +% false [(gs:[lib]) (gs:[Resource]) (gs800:[Resource)] (*]*) --> +% ((gs:[lib.*]*) [gs:[Resource.*]*) ([gs800:[Resource.*]*) +% +/.generate_dir_list_templates_with_length +{ % [dl] (templ) + % We need to convert paths into templates, + % because it can include '\' on DOS. + % In same time, the <template> must not convert, + % because it is already a template. + % Besides that, we cannot combine template using .file_name_combine, + % because template syntax breaks the platform path syntax. + % To resolve this, we first convert the <template> into + % a fake filename, and combine it with path, + % obtaining a correct separator. Then we replace + % the fake file name with the given template. + % + + % Create the fake file name : + dup dup length string copy % b [dl] (templ) (ffn) + (*) 0 get (?) 0 get (\\) 0 get (x) 0 get 0 0 % b [dl] (templ) (ffn) * ? \ x i j + { 1 index 7 index length ge { exit } if + 6 index 2 index get % b [dl] (templ) (ffn) * ? \ x i j c + dup 7 index eq % b [dl] (templ) (ffn) * ? \ x i j c bool + 1 index 7 index eq or { % *? + pop 2 index + } if % b [dl] (templ) (ffn) * ? \ x i j C + dup 5 index eq { % \ + 3 2 roll 1 add 3 1 roll % b [dl] (templ) (ffn) * ? \ x i' j C + 2 index 8 index length ge { pop exit } if + pop 6 index 2 index get % b [dl] (templ) (ffn) * ? \ x i' j C' + } if + 7 index 2 index 3 2 roll put % b [dl] (templ) (ffn) * ? \ x i' j + 1 add exch 1 add exch % b [dl] (templ) (ffn) * ? \ x i'' j' + } loop % b [dl] (templ) (ffn) * ? \ x i j + 6 1 roll pop % b [dl] (templ) (ffn) j * ? \ x + exch pop exch pop exch pop exch % b [dl] (templ) (ffn) x j + { dup 3 index length ge { exit } if + 3 copy exch put + 1 add + } loop + pop pop % b [dl] (templ) (ffn) + + % An internal procedure : + { % {} b [dl] (templ) (ffn) (dffn) + dup length + 1 sub % drop 'x', which was added above. + exch % {} b [dl] (templ) (ffn) ldffn (dffn) + .makepathtemplate % {} b [dl] (templ) (ffn) ldffn (Dffn) + dup % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) + 4 index length dup % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) templL templL + 2 index length % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) templL templL DffnL + exch sub % {} b [dl] (templ) (ffn) ldffn (Dffn) (Dffn) templL i + exch getinterval % {} b [dl] (templ) (ffn) ldffn (Dffn) (suffix) + 4 index exch copy pop % {} b [dl] (templ) (ffn) ldffn (dt) + 5 index { + exch % {} b [dl] (templ) (ffn) (dt) ldffn + 7 2 roll % (dt) ldffn {} b [dl] (templ) (ffn) + } { + exch pop % {} b [dl] (templ) (ffn) (dt) + 6 1 roll % (dt) {} b [dl] (templ) (ffn) + } ifelse + } + 5 1 roll % {} b [dl] (templ) (ffn) + + % Generate templates : + dup .file_name_is_absolute { + dup % {} b [dl] (templ) (ffn) (ffn) + 5 index exec % (t1) {} b [dl] (templ) (ffn) + } { + 2 index { % ... {} b [dl] (templ) (ffn) (d) + 1 index % ... {} b [dl] (templ) (ffn) (d) (ffn) + false .file_name_combine { % ... {} b [dl] (templ) (ffn) (dffn) + 5 index exec % ... (t1) ?l1 {} b [dl] (templ) (ffn) + } { % ... {} b [dl] (templ) (ffn) (d) (ffn) + pop pop % ... {} b [dl] (templ) (ffn) + } ifelse + } forall + } ifelse % (t1) ?l1 (t2) ?l2 ... (tN) ?ln {} b [dl] (templ) (ffn) + pop pop pop pop pop % (t1) ?l1 (t2) ?l2 ... (tN) ?ln +} bind def + +% <dir_list> <template> .generate_dir_list_templates <t1> ... <tN> +% +% Generates various valid templates combining a directory list with a given template. +% It's the 'false' case of the function above. +% +/.generate_dir_list_templates +{ //false 3 1 roll //.generate_dir_list_templates_with_length exec +} bind def + +% Load the initialization files for optional features. +%% Replace 4 INITFILES +systemdict /INITFILES known + { INITFILES { dup runlibfile VMDEBUG } forall + } +if + +% If Level 2 (or higher) functionality is implemented, enable it now. +/.setlanguagelevel where { + pop 2 .setlanguagelevel + % If the resource machinery is loaded, fix up some things now. + /.fixresources where { pop .fixresources } if +} if +/ll3dict where { + pop 3 .setlanguagelevel +} if + +(END INITFILES) VMDEBUG + +% Create a null font. This is the initial font. +8 dict dup begin + /FontMatrix [ 1 0 0 1 0 0 ] readonly def + /FontType 3 def + /FontName () def + /Encoding StandardEncoding def + /FontBBox { 0 0 0 0 } readonly def % executable is bogus, but customary ... + /BuildChar { pop pop 0 0 setcharwidth } bind def + /PaintType 0 def % shouldn't be needed! +end +/NullFont exch definefont setfont + +% Define NullFont as the font. +/NullFont currentfont def + +% Load initial fonts from FONTPATH directories, Fontmap file, +% and/or .getccfont as appropriate. +.loadinitialfonts + +% Remove NullFont from FontDirectory, so it can't be accessed by mistake. +/undefinefont where { + pop /NullFont undefinefont +} { + FontDirectory /NullFont .undef +} ifelse + +(END FONTS) VMDEBUG + +% Restore the real definition of runlibfile. +/runlibfile /.runlibfile load def +currentdict /.runlibfile .undef + +% Bind all the operators defined as procedures. +/.bindoperators % binds operators in currentdict + { % Temporarily disable the typecheck error. + errordict /typecheck 2 copy get + errordict /typecheck { pop } put % pop the command + currentdict + { dup type /operatortype eq + { % This might be a real operator, so bind might cause a typecheck, + % but we've made the error a no-op temporarily. + .bind % do a real bind even if NOBIND is set + } + if pop pop + } forall + put + } def +NOBIND DELAYBIND or not { .bindoperators } if + +% Establish a default environment. + +defaultdevice +% The following line used to skip setting of page size and resolution if +% NODISPLAY was selected. We think this was only to save time and memory, +% and it is a bad idea because it prevents setting the resolution in this +% situation, which pstoedit (among other programs) relies on. +%DISPLAYING not { setdevice (%END DISPLAYING) .skipeof } if + +% If the paper size is not specifed and the device defaults to +% letter or A4 paper, select the DEFAULTPAPERSIZE. +systemdict /DEFAULTPAPERSIZE known +systemdict /PAPERSIZE known not and +systemdict /DEVICEWIDTH known not and +systemdict /DEVICEHEIGHT known not and +systemdict /DEVICEWIDTHPOINTS known not and +systemdict /DEVICEHEIGHTPOINTS known not and + { + defaultdevice mark /PageSize //null .dicttomark .getdeviceparams + .dicttomark /PageSize get + dup 0 get 0.5 add cvi 612 eq 1 index 1 get 0.5 add cvi 792 eq and + 1 index 0 get 0.5 add cvi 595 eq 2 index 1 get 0.5 add cvi 842 eq and + or exch pop + { + % the default paper size was letter, so replace it with DEFAULTPAPERSIZE + /PAPERSIZE DEFAULTPAPERSIZE def + } if + } +if + +systemdict /DEVICEWIDTH known +systemdict /DEVICEHEIGHT known or +systemdict /DEVICEWIDTHPOINTS known or +systemdict /DEVICEHEIGHTPOINTS known or +systemdict /DEVICEXRESOLUTION known or +systemdict /DEVICEYRESOLUTION known or +systemdict /PAPERSIZE known or +not { (%END DEVICE) .skipeof } if +% Let DEVICE{WIDTH,HEIGHT}[POINTS] override PAPERSIZE. +systemdict /PAPERSIZE known +systemdict /DEVICEWIDTH known not and +systemdict /DEVICEHEIGHT known not and +systemdict /DEVICEWIDTHPOINTS known not and +systemdict /DEVICEHEIGHTPOINTS known not and + { % Convert the paper size to device dimensions. + true statusdict /.pagetypenames get + { PAPERSIZE eq + { PAPERSIZE load + dup 0 get /DEVICEWIDTHPOINTS exch def + 1 get /DEVICEHEIGHTPOINTS exch def + pop false exit + } + if + } + forall + { (Unknown paper size: ) print PAPERSIZE ==only (.) = + } + if + } +if +% Adjust the device parameters per the command line. +% It is possible to specify resolution, pixel size, and page size; +% since any two of these determine the third, conflicts are possible. +% We simply pass them to .setdeviceparams and let it sort things out. + mark /HWResolution //null /HWSize //null /PageSize //null .dicttomark + .getdeviceparams .dicttomark begin + mark + % Check for resolution. + /DEVICEXRESOLUTION where dup + { exch pop HWResolution 0 DEVICEXRESOLUTION put } + if + /DEVICEYRESOLUTION where dup + { exch pop HWResolution 1 DEVICEYRESOLUTION put } + if + or { /HWResolution HWResolution } if + % Check for device sizes specified in pixels. + /DEVICEWIDTH where dup + { exch pop HWSize 0 DEVICEWIDTH put } + if + /DEVICEHEIGHT where dup + { exch pop HWSize 1 DEVICEHEIGHT put } + if + or { /HWSize HWSize } if + % Check for device sizes specified in points. + /DEVICEWIDTHPOINTS where dup + { exch pop PageSize 0 DEVICEWIDTHPOINTS put } + if + /DEVICEHEIGHTPOINTS where dup + { exch pop PageSize 1 DEVICEHEIGHTPOINTS put } + if + or { /PageSize PageSize } if + % Check whether any parameters were set. + dup mark eq { pop } { defaultdevice putdeviceprops } ifelse + end +%END DEVICE +% Set any device properties defined on the command line. +% If BufferSpace is defined but not MaxBitmap, set MaxBitmap to BufferSpace. +systemdict /BufferSpace known +systemdict /MaxBitmap known not and + { systemdict /MaxBitmap BufferSpace put + } if +dup getdeviceprops +counttomark 2 idiv + { systemdict 2 index known + { pop dup load counttomark 2 roll } + { pop pop } + ifelse + } repeat +counttomark dup 0 ne + { 2 add -1 roll putdeviceprops } + { pop pop } +ifelse +% If the initial device parameters are invalid, the setdevice may fail. +% Trap this and produce a reasonable error message. +{ setdevice } % does an erasepage +INITDEBUG { exec false } { .internalstopped } ifelse { + (**** Unable to open the initial device, quitting.) = flush 1 .quit +} if + +% If the media size is fixed, update the current page device dictionary. +FIXEDMEDIA +dup { pop systemdict /.currentpagedevice known } if +dup { pop .currentpagedevice exch pop } if +not { (%END MEDIA) .skipeof } if +currentpagedevice dup length dict .copydict +dup /Policies + % Stack: <pagedevice> <pagedevice> /Policies +1 index /InputAttributes +2 copy get dup length dict .copydict + % Stack: <pagedevice> <pagedevice> /Policies <pagedevice> + % /InputAttributes <inputattrs'> +dup 0 2 copy get dup length dict .copydict + % Stack: <pagedevice> <pagedevice> /Policies <pagedevice> + % /InputAttributes <inputattrs'> <inputattrs'> 0 <attrs0'> +dup /PageSize 7 index /PageSize get +put % PageSize in 0 +put % 0 in InputAttributes +put % InputAttributes in pagedevice +% Also change the page size policy so we don't get an error. + % Stack: <pagedevice> <pagedevice> /Policies +2 copy get dup length dict .copydict + % Stack: <pagedevice> <pagedevice> /Policies <policies'> +dup /PageSize 7 put % PageSize in Policies +put % Policies in pagedevice +.setpagedevice +%END MEDIA + +% Set up the interpreter context version of -dUSeCIEColor option +% so that .getuseciecolor has the correct value (see gs_setpd.ps) +/setpagedevice where { + pop systemdict /UseCIEColor known { + mark /UseCIEColor UseCIEColor .dicttomark setpagedevice + } if +} if + +%END DISPLAYING + +(END DEVICE) VMDEBUG + +% Establish a default upper limit in the character cache, +% namely, enough room for a 18-point character at the resolution +% of the default device, or for a character consuming 1% of the +% maximum cache size, whichever is larger. +mark + % Compute limit based on character size. + 18 dup dtransform + exch abs cvi 31 add 32 idiv 4 mul % X raster + exch abs cvi mul % Y + % Compute limit based on allocated space. + cachestatus pop pop pop pop pop exch pop 0.01 mul cvi + .max dup 10 idiv exch +setcacheparams +% Conditionally disable the character cache. +NOCACHE { 0 setcachelimit } if + +(END CONFIG) VMDEBUG + +% Initialize graphics. + +.setdefaultscreen +initgraphics + +% The interpreter relies on there being at least 2 entries +% on the graphics stack. Establish the second one now. +gsave + +% Define some control sequences as no-ops. +% This is a hack to get around problems +% in some common PostScript-generating applications. +<04> cvn JOBSERVER { + { { clear cleardictstack //false 0 .startnewjob } 2 .stop } bind + } { + { } + } ifelse def +<1b> cvn { % UEL is <esc>%-12345X and acts the same as ^D + currentfile (%-12345X) .peekstring pop (%-12345X) eq <04> cvn load if +} bind def +<1b45> cvn { } def % PJL reset prologue (ESC E) +<1b451b> cvn <1b> cvn load def % PJL reset epilogue (ESC E + UEL) +(\001M) cvn % TBCP initiator + { currentfile /TBCPDecode filter cvx exec + } bind def +/@PJL % H-P job control + { + % Windows 2000 driver includes PJL into %%BeginFeature block. + % Identify this from the pattern on the stack: countdictstack lucas mark + % and fail the feature request. + + count 3 ge { + dup mark eq { + 2 index countdictstack eq { + 1 index /lucas where { /lucas get eq } { pop false } ifelse { + stop + } if + } if + } if + } if + currentfile //=string readline pop pop + } bind def + +% Install the EPS handler if needed +systemdict /EPSBoundingBoxInit known { EPSBoundingBoxInit } if + +% If we want a "safer" system, disable some obvious ways to cause havoc. +.currentglobal true .setglobal +/SAFETY 2 dict + dup /safe false put + dup /tempfiles 10 dict readonly put +readonly def +.setglobal + +/.locksafe { + SAFETY /safe get not { + << + /PermitFileReading [ + currentuserparams /PermitFileReading get aload pop + /FONTPATH .systemvar (*) .generate_dir_list_templates + % Library files : + /LIBPATH .systemvar (*) .generate_dir_list_templates + % Resource files on OpenVMS requires a separate template (gs:[dir.*]*) + % because the (gs:[dir]*) doesn't cover them. + /LIBPATH .systemvar (*) .file_name_separator (*) + concatstrings concatstrings .generate_dir_list_templates + .languagelevel 2 ge { + % Default resources : + [ currentsystemparams /GenericResourceDir get] (*) .generate_dir_list_templates + % Default resources (OpenVMS, see comment above.) : + [ currentsystemparams /GenericResourceDir get] (*) .file_name_separator (*) + concatstrings concatstrings .generate_dir_list_templates + } if + ] + /LockFilePermissions true + >> setuserparams + } + if + % setpagedevice has the side effect of clearing the page, but + % we will just document that. Using setpagedevice keeps the device + % properties and pagedevice .LockSafetyParams in agreement even + % after a restore that changes the value to false. + currentglobal currentpagedevice gcheck setglobal % use correct VM space + << /.LockSafetyParams true >> setpagedevice + setglobal + //SAFETY /safe //true .forceput % overrides readonly +} .bind executeonly odef + +/.setsafe +{ + SAFETY /safe get not { + << + /PermitFileReading [ ] + /PermitFileWriting [ ] + /PermitFileControl [ ] + >> setuserparams + } + if + .locksafe +} .bind executeonly odef + +/deletefile { + dup { deletefile } stopped { + pop //deletefile $error /errorname get signalerror + } { + % deletefile succeeded. Remove from tempfile list if present + //SAFETY /tempfiles get exch cvn 2 copy known { + .forceundef + } { + pop pop + } + ifelse + } + ifelse +} .bind executeonly odef + +% If a file is opened with .tempfile with SAFER not (yet) set, +% the file can be deleted later, even if SAFER is set. +/.tempfile { + .tempfile % filename file + //SAFETY /tempfiles get 2 .argindex true .forceput +} .bind executeonly odef + +% If we are running in SAFER mode, lock things down +SAFER { .setsafe } if + +% If we delayed binding, make it possible to do it later. +/.bindnow { + currentuserparams /IdiomRecognition .knownget { + 1 dict dup /IdiomRecognition //false put setuserparams + } if + //systemdict begin .bindoperators end + % Temporarily disable the typecheck error. + errordict /typecheck 2 copy get + errordict /typecheck { pop } put % pop the command + 0 1 .delaycount 1 sub { .delaybind exch get .bind pop } for + //systemdict /.delaybind {} .forceput % reclaim the space + //systemdict /.bindnow .forceundef % ditto + put + //systemdict /.forcecopynew .forceundef % remove temptation + //systemdict /.forcedef .forceundef % ditto + //systemdict /.forceput .forceundef % ditto + //systemdict /.forceundef .forceundef % ditto + currentuserparams /IdiomRecognition known { + 1 dict dup /IdiomRecognition 4 -1 roll put setuserparams + } if +} .bind odef + +% Turn off array packing, since some PostScript code assumes that +% procedures are writable. +false setpacking + +(END INIT) VMDEBUG + +/.currentuserparams where { + pop + % Remove real user params from psuserparams. + mark .currentuserparams counttomark 2 idiv { + pop psuserparams exch undef + } repeat pop + % Update the copy of the user parameters. + mark .currentuserparams counttomark 2 idiv { + userparams 3 1 roll .forceput % userparams is read-only + } repeat pop + % Turn on idiom recognition, if available. + currentuserparams /IdiomRecognition known { + /IdiomRecognition true .definepsuserparam + } if + psuserparams readonly pop + systemdict /.definepsuserparam undef + % Save a copy of userparams for use with save/restore + % (and, if implemented, context switching). + .currentglobal false .setglobal + mark userparams { } forall .dicttomark readonly + /userparams exch .forcedef % systemdict is read-only + .setglobal +} if +/.currentsystemparams where { + pop + % Remove real system params from pssystemparams. + mark .currentsystemparams counttomark 2 idiv { + pop pssystemparams exch .forceundef + } repeat pop +} if + +% Set up AlignToPixels : + +/AlignToPixels where { + mark /AlignToPixels 2 index /AlignToPixels get .dicttomark setuserparams + /AlignToPixels undef +} if + +% Set up GridFitTT : + +/GridFitTT where { + mark /GridFitTT 2 index /GridFitTT get .dicttomark setuserparams + /GridFitTT undef +} if + +% Establish local VM as the default. +false /setglobal where { pop setglobal } { .setglobal } ifelse +$error /.nosetlocal false put + +(END GLOBAL) VMDEBUG + +/.savelocalstate where { + % If we might create new contexts, save away copies of all dictionaries + % referenced from systemdict that are stored in local VM, + % and also save a copy of the initial gstate. + pop .savelocalstate +} { + % If we're *not* running in a multi-context system and FAKEFONTS is + % defined, add the fake fonts to LocalFontDirectory. + .definefakefonts % current VM is local +} ifelse + +% Execute scheduled inits : +//.execute_scheduled_inits exec +currentdict /.execute_scheduled_inits undef +currentdict /.delayed_init_queue undef + +% Make global and local FontDirectory read-only. +FontDirectory readonly pop +/GlobalFontDirectory where { pop GlobalFontDirectory readonly pop } if + +% Remove systemdict entries for things that have been bound in where used +% and that shouldn't be accessible by name, and close up systemdict. +currentdict /filterdict .undef +currentdict /.cidfonttypes .undef +currentdict /.colorrenderingtypes .undef +currentdict /.formtypes .undef +currentdict /.halftonetypes .undef +currentdict /.imagetypes .undef +currentdict /.imagemasktypes .undef +currentdict /.patterntypes .undef +currentdict /.shadingtypes .undef +currentdict /.wheredict .undef +currentdict /.renderingintentdict .undef +end + +% Clean up VM, and enable GC. +/vmreclaim where + { pop NOGC not { 2 vmreclaim 0 vmreclaim } if + } if +DELAYBIND not { + systemdict /.forcecopynew .undef % remove temptation + systemdict /.forcedef .undef % ditto + systemdict /.forceput .undef % ditto + systemdict /.forceundef .undef % ditto +} if +% Move superexec to internaldict if superexec is defined. +currentdict /superexec .knownget { + 1183615869 internaldict /superexec 3 -1 roll put + currentdict /superexec .undef +} if +WRITESYSTEMDICT not { systemdict readonly pop } if +(END GC) VMDEBUG + +% The Adobe AGM_Core used by Illustrator 9 has some code that breaks +% if the 'product' is not (Adobe PostScript Parser). A bug has been +% submitted to Adobe since this also fails with Acrobat Distiller. +% As a temporary work around, the following HACK will work for +% devices without spot color support. Once Ghostscript can +% support DeviceN and spot color separations this will need to +% be 'true' in some cases. +userdict /AGM_preserve_spots false put + +% The interpreter will run the initial procedure (start). diff --git a/gs/Resource/Init/gs_l2img.ps b/gs/Resource/Init/gs_l2img.ps new file mode 100644 index 000000000..a9c3d9eee --- /dev/null +++ b/gs/Resource/Init/gs_l2img.ps @@ -0,0 +1,184 @@ +% Copyright (C) 1995, 1996 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Emulate the Level 2 dictionary-based image operator in Level 1, +% except for Interpolate (ignored) and MultipleDataSources = true; +% also, we require that the data source be either a procedure of a +% particular form or a stream, not a string or a general procedure. + +% pdf2ps copies the portion of this file from %BEGIN to %END if Level 1 +% compatible output is requested. + +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse + +/packedarray where + { pop } + { /packedarray { array astore readonly } bind def } +ifelse + +%BEGIN + +11 dict /.csncompdict 1 index def begin + /DeviceGray { 1 /setgray load } bind def + /DeviceRGB { 3 /setrgbcolor load } bind def + /DeviceCMYK { 4 /setcmykcolor load } bind def + /Indexed + { dup 1 index 1 get //.csncompdict exch get exec + % Stack: [/Indexed base hival map] ncomp basesetcolor + 3 -1 roll 3 get mark 3 1 roll + % Stack: ncomp -mark- basesetcolor map + dup type /stringtype eq + { { - + { exch round cvi get 255 div + } + - + { exch round cvi 3 mul 2 copy 2 copy get 255 div + 3 1 roll 1 add get 255 div + 4 2 roll 2 add get 255 div + } + { exch round cvi 4 mul 2 copy 2 copy 2 copy get 255 div + 3 1 roll 1 add get 255 div + 4 2 roll 2 add get 255 div + 5 3 roll 3 add get 255 div + } + } + 4 index get aload pop counttomark -1 roll + } + { /exec load 3 -1 roll + % Stack: -mark- mapproc --exec-- basesetcolor + } + ifelse .packtomark cvx + exch pop 1 exch + } bind def + /Separation + { dup 2 index //.csncompdict exch get exec + % Stack: [/Separation name alt xform] ncomp altsetcolor + 3 -1 roll 3 get /exec load 3 -1 roll 3 array astore readonly cvx + exch pop 1 exch + } bind def + % Substitute device spaces for CIE spaces. + /CIEBasedA /DeviceGray load def + /CIEBasedABC /DeviceRGB load def + /CIEBasedDEF /DeviceRGB load def + /CIEBasedDEFG /DeviceCMYK load def +end + +/.packtomark { counttomark packedarray exch pop } bind def + +/.csinextbits % - .csinextbits <bits> + % Uses b, nnb, i, row, mask, BitsPerComponent; + % sets b, nnb, i. + { /nnb nnb BitsPerComponent add + { dup 0 le { exit } if + /b b 8 bitshift row i get add def + /i i 1 add def 8 sub + } + loop def + b nnb bitshift mask and + } bind def + +% Note that the ColorSpace key must be present in the image dictionary. +/.colorspaceimage % <imagedict> .colorspaceimage - + { save exch + dup length 15 add dict begin { cvlit def } forall + ColorSpace dup dup type /nametype ne { 0 get } if + .csncompdict exch get exec + /setpixelcolor exch def /ncomp exch def pop + /row ncomp BitsPerComponent mul Width mul 7 add 8 idiv string def + /mask 1 BitsPerComponent bitshift 1 sub def + /nextbits BitsPerComponent 8 eq + { { row i get /i i 1 add def } } + { /.csinextbits load } + ifelse def + /nextpixel mark 0 2 ncomp 1 sub 2 mul + { /nextbits cvx exch + Decode exch 2 getinterval + dup aload pop exch sub + dup mask eq { pop } { mask div /mul load 3 -1 roll } ifelse + 0 get dup 0 eq { pop } { /sub load 3 -1 roll } ifelse + } + for + /setpixelcolor load dup type /operatortype ne { /exec load } if + .packtomark cvx def + /readrow + /DataSource load dup type + dup /arraytype eq exch /packedarraytype eq or + { % Must be { <file> <string> ... } + aload length 1 add array /pop load exch astore + dup 1 row put cvx + } + { pop + % Adobe requires readstring to signal an error if given + % an empty string. Work around this nonsense here. + row length 0 eq + { { } } + { { DataSource row readstring pop pop } } + ifelse + } + ifelse def + ImageMatrix matrix invertmatrix concat + /imat matrix def + 0 1 Height 1 sub + { imat 5 3 -1 roll neg put + readrow + /b 0 def /nnb 0 def /i 0 def + 0 1 Width 1 sub + { imat 4 3 -1 roll neg put nextpixel + 1 1 true imat {<80>} imagemask + } + for + } + for + end restore + } bind def + +%END +exec +currentfile closefile + +% Patch for testing. +/.cincompdict 3 dict begin + 1 { {0 1} {/DeviceGray} } def + 3 { {0 1 0 1 0 1} {/DeviceRGB} } def + 4 { {0 1 0 1 0 1 0 1} {/DeviceCMYK} } def +currentdict end def +/.imagekeys [ + /Decode /DataSource /ImageMatrix /BitsPerComponent /Height /Width +] def +/colorimage % <width> <height> <bits/comp> <matrix> + % <datasrc> false <ncomp> colorimage - + { 1 index { /colorimage .systemvar /rangecheck signalerror } if exch pop + //.cincompdict exch get exec + 7 dict begin /ColorSpace exch cvlit def + .imagekeys { exch cvlit def } forall + currentdict end .colorspaceimage + } bind odef +/image + { dup type /dicttype ne + { 7 dict begin /ColorSpace /DeviceGray def [0 1] + .imagekeys { exch cvlit def } forall + currentdict end + } + { dup length 1 add dict .copydict dup /ColorSpace currentcolorspace put + } + ifelse + .colorspaceimage + } bind odef + +exec diff --git a/gs/Resource/Init/gs_lev2.ps b/gs/Resource/Init/gs_lev2.ps new file mode 100644 index 000000000..4509ad242 --- /dev/null +++ b/gs/Resource/Init/gs_lev2.ps @@ -0,0 +1,1014 @@ +% Copyright (C) 1990, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for Level 2 functions. +% When this is run, systemdict is still writable, +% but (almost) everything defined here goes into level2dict. + +level2dict begin + +% ------ System and user parameters ------ % + +% User parameters must obey save/restore, and must also be maintained +% per-context. We implement the former, and some of the latter, here +% with PostScript code. NOTE: our implementation assumes that user +% parameters change only as a result of setuserparams -- that there are +% no user parameters that are ever changed dynamically by the interpreter +% (although the interpreter may adjust the value presented to setuserparams) +% +% There are two types of user parameters: those which are actually +% maintained in the interpreter, and those which exist only at the +% PostScript level. We maintain the current state of both types in +% a read-only local dictionary named userparams, defined in systemdict. +% In a multi-context system, each context has its own copy of this +% dictionary. In addition, there is a constant dictionary named +% psuserparams where each key is the name of a user parameter that exists +% only in PostScript and the value is a procedure to check that the value +% is legal: setuserparams uses this for checking the values. +% setuserparams updates userparams explicitly, in addition to setting +% any user parameters in the interpreter; thus we can use userparams +% to reset those parameters after a restore or a context switch. +% NOTE: the name userparams is known to the interpreter, and in fact +% the interpreter creates the userparams dictionary. + +% Check parameters that are managed at the PostScript level. +/.checkparamtype { % <newvalue> <type> .checkparamtype <bool> + exch type eq +} .bind def +/.checksetparams { % <newdict> <opname> <checkdict> + % .checksetparams <newdict> + 2 .argindex { + % Stack: newdict opname checkdict key newvalue + 3 copy 3 1 roll .knownget { + exec not { + pop pop pop load /typecheck signalerror + } if + dup type /stringtype eq { + dup rcheck not { + pop pop pop load /invalidaccess signalerror + } if + } if + } { + pop + } ifelse pop pop + } forall pop pop +} .bind def % not odef, shouldn't reset stacks + +% currentuser/systemparams creates and returns a dictionary in the +% current VM. The easiest way to make this work is to copy any composite +% PostScript-level parameters to global VM. Currently we have strings +% as well as arrays. For arrays, we also need to copy any contents that +% are in VM. Also copying string parameters insures the contents won't +% be changed. Also be careful to preserve 'executable' state. +/.copyparam { % <value> .copyparam <value'> + dup type /arraytype eq { + .currentglobal true .setglobal exch + dup wcheck exch dup xcheck exch % original attributes + dup length array exch dup { % stack: destination_array original_array original_array + dup type /arraytype eq { + dup 2 index ne { % avoid recursion + .copyparam % recurse to handle composite array elements + } { + % this array self referenced, do it again (yuk!) + pop 1 index % get copy of destination array + } ifelse + } { + dup type /stringtype eq { + .copyparam + } if + } + ifelse 3 1 roll % keep arrays on top + } forall pop astore + exch { cvx } if % set executable state + exch not { readonly } if % set readonly attribute as original + exch .setglobal + } if + dup type /stringtype eq { + dup wcheck exch % save attr for setting readonly + .currentglobal true .setglobal + 1 index length string exch .setglobal + copy exch not { readonly } if + } if +} .bind def + +% Some user parameters are managed entirely at the PostScript level. +% We take care of that here. +systemdict begin +/psuserparams 48 dict def +/getuserparam { % <name> getuserparam <value> + /userparams .systemvar 1 .argindex get exch pop +} odef +% Fill in userparams (created by the interpreter) with current values. +mark .currentuserparams +counttomark 2 idiv { + userparams 3 1 roll put +} repeat pop +/.definepsuserparam { % <name> <value> .definepsuserparam - + psuserparams 3 copy pop + type cvlit /.checkparamtype cvx 2 packedarray cvx put + userparams 3 1 roll put +} .bind def +end +/currentuserparams { % - currentuserparams <dict> + /userparams .systemvar dup length dict .copydict +} odef +% We break out setuserparams into a separate procedure so that setvmxxx +% can use it without affecting the command in case of an error. +/.setuserparams2 { + % Check that we will be able to set the PostScript-level + % user parameters. + /setuserparams /psuserparams .systemvar .checksetparams + % Set the C-level user params. If this succeeds, we know that + % the password check succeeded. + dup .setuserparams + % Now set the PostScript-level params. + % The interpreter may have adjusted the values of some of the + % parameters, so we have to read them back. + dup { + /userparams .systemvar 2 index known { + psuserparams 2 index known not { + pop dup .getuserparam + } if + .copyparam + % special protection for the security related parameters + [ /PermitFileReading /PermitFileWriting /PermitFileControl ] + { 2 index eq { % force all strings to readonly but make sure the + % array is in the correct VM space (local/global). + currentglobal exch dup gcheck setglobal + dup length array exch { readonly exch } forall astore + exch setglobal + } if + } forall + % protect top level of parameters that we copied + dup type dup /arraytype eq exch /stringtype eq or { readonly } if + /userparams .systemvar 3 1 roll .forceput % userparams is read-only + } { + pop pop + } ifelse + } forall + % A context switch might have occurred during the above loop, + % causing the interpreter-level parameters to be reset. + % Set them again to the new values. From here on, we are safe, + % since a context switch will consult userparams. + .setuserparams +} .bind def +/setuserparams { % <dict> setuserparams - + .setuserparams2 +} .bind odef +% Initialize user parameters managed here. +/JobName () .definepsuserparam + +% Restore must restore the user parameters. +% (Since userparams is in local VM, save takes care of saving them.) +/restore { % <save> restore - + //restore /userparams .systemvar .setuserparams +} .bind odef + +% The pssystemparams dictionary holds some system parameters that +% are managed entirely at the PostScript level. +systemdict begin +currentdict /pssystemparams known not { + /pssystemparams 40 dict readonly def +} if +/getsystemparam { % <name> getsystemparam <value> + //pssystemparams 1 .argindex .knownget { exch pop } { .getsystemparam } ifelse +} odef +end +/currentsystemparams { % - currentsystemparams <dict> + mark .currentsystemparams //pssystemparams { } forall .dicttomark +} odef +/setsystemparams { % <dict> setsystemparams - + % Check that we will be able to set the PostScript-level + % system parameters. + dup pop % check # of args + /SAFETY .systemvar /safe get { + % SAFER mode disallows some changes + [ /GenericResourceDir /FontResourceDir /GenericResourcePathSep ] { + 2 copy .knownget { + exch //pssystemparams exch .knownget { + ne { /setsystemparams /invalidaccess signalerror } if + } { + pop + } ifelse + } { + pop + } ifelse + } forall + } if + /setsystemparams //pssystemparams mark exch { + type cvlit /.checkparamtype cvx 2 packedarray cvx + } forall .dicttomark .checksetparams + % Set the C-level system params. If this succeeds, we know that + % the password check succeeded. + dup .setsystemparams + % Now set the PostScript-level params. We must copy local strings + % into global VM. + dup + { //pssystemparams 2 index known + { % Stack: key newvalue + .copyparam + % protect top level parameters that we copied + dup type dup /arraytype eq exch /stringtype eq or { readonly } if + //pssystemparams 3 1 roll .forceput % pssystemparams is read-only + } + { pop pop + } + ifelse + } + forall pop +} .bind odef + +% Initialize the passwords. +% NOTE: the names StartJobPassword and SystemParamsPassword are known to +% the interpreter, and must be bound to noaccess strings. +% The length of these strings must be max_password (iutil2.h) + 1. +/StartJobPassword 65 string noaccess def +/SystemParamsPassword 65 string noaccess def + +% Redefine cache parameter setting to interact properly with userparams. +/setcachelimit { + { mark /MaxFontItem 2 .argindex .dicttomark setuserparams pop } + stopped + { /setcachelimit .systemvar $error /errorname get signalerror + } if +} .bind odef +/setcacheparams { + % The MaxFontCache parameter is a system parameter, which we might + % not be able to set. Fortunately, this doesn't matter, because + % system parameters don't have to be synchronized between this code + % and the VM. + counttomark 1 add copy setcacheparams + currentcacheparams % mark size lower upper + 3 -1 roll pop + /MinFontCompress 3 1 roll + /MaxFontItem exch + .dicttomark { setuserparams cleartomark } stopped { + /setcacheparams .systemvar $error /errorname get signalerror + } if +} .bind odef + +% Add bogus user and system parameters to satisfy badly written PostScript +% programs that incorrectly assume the existence of all the parameters +% listed in Appendix C of the Red Book. Note that some of these may become +% real parameters later: code near the end of gs_init.ps takes care of +% removing any such parameters from ps{user,system}params. + +% psuserparams + /MaxFormItem 100000 .definepsuserparam + /MaxPatternItem 20000 .definepsuserparam + /MaxScreenItem 48000 .definepsuserparam + /MaxUPathItem 0 .definepsuserparam + +% File Access Permission parameters + .currentglobal true .setglobal + /.checkFilePermitparams { + type /arraytype eq { + currentuserparams /LockFilePermissions get { + 5 { pop } repeat /setuserparams /invalidaccess signalerror + }{ + % in addition to validating the value, ensure the value is read/only + dup { readonly exch } forall + .currentglobal exch dup gcheck .setglobal length array exch .setglobal + astore readonly + } + ifelse + } { + 5 { pop } repeat /setuserparams /typecheck signalerror + } + ifelse + true + } .bind def +% Initialize the File Permission access control to wide open +% These will only be accessed via current/set userparams. +% Values are a string containing multiple nul terminated path strings + /PermitFileReading dup [ (*) ] .definepsuserparam + psuserparams exch /.checkFilePermitparams load put + /PermitFileWriting dup [ (*) ] .definepsuserparam + psuserparams exch /.checkFilePermitparams load put + /PermitFileControl dup [ (*) ] .definepsuserparam + psuserparams exch /.checkFilePermitparams load put + .setglobal + +pssystemparams begin + /CurDisplayList 0 .forcedef + /CurFormCache 0 .forcedef + /CurInputDevice () .forcedef + /CurOutlineCache 0 .forcedef + /CurOutputDevice () .forcedef + /CurPatternCache 0 .forcedef + /CurUPathCache 0 .forcedef + /CurScreenStorage 0 .forcedef + /CurSourceList 0 .forcedef + /DoPrintErrors false .forcedef + /JobTimeout 0 .forcedef + /LicenseID (LN-001) .forcedef % bogus + /MaxDisplayList 140000 .forcedef + /MaxFormCache 100000 .forcedef + /MaxImageBuffer 524288 .forcedef + /MaxOutlineCache 65000 .forcedef + /MaxPatternCache 100000 .forcedef + /MaxUPathCache 300000 .forcedef + /MaxScreenStorage 84000 .forcedef + /MaxSourceList 25000 .forcedef + /PrinterName product .forcedef + /RamSize 4194304 .forcedef + /WaitTimeout 40 .forcedef +end + +% Define the procedures for handling comment scanning. The names +% %ProcessComment and %ProcessDSCComment are known to the interpreter. +% These procedures take the file and comment string and file as operands. +/.checkprocesscomment { + dup null eq { + pop true + } { + dup xcheck { + type dup /arraytype eq exch /packedarraytype eq or + } { + pop false + } ifelse + } ifelse +} .bind def +/ProcessComment null .definepsuserparam +psuserparams /ProcessComment {.checkprocesscomment} put +(%ProcessComment) cvn { + /ProcessComment getuserparam + dup null eq { pop pop pop } { exec } ifelse +} bind def +/ProcessDSCComment null .definepsuserparam +psuserparams /ProcessDSCComment {.checkprocesscomment} put +/.loadingfont false def +(%ProcessDSCComment) cvn { + /ProcessDSCComment getuserparam + dup null eq .loadingfont or { pop pop pop } { exec } ifelse +} bind def + +% ------ Miscellaneous ------ % + +(<<) cvn % - << -mark- + /mark load def +% (>> is defined primitively.) +/languagelevel 2 def +% When running in Level 2 mode, this interpreter is supposed to be +% compatible with Adobe version 2017. +/version (2017) readonly def + +% If binary tokens are supported by this interpreter, +% set an appropriate default binary object format. +/setobjectformat where + { pop + /RealFormat getsystemparam (IEEE) eq { 1 } { 3 } ifelse + /ByteOrder getsystemparam { 1 add } if + setobjectformat + } if + +% Aldus Freehand versions 2.x check for the presence of the +% setcolor operator, and if it is missing, substitute a procedure. +% Unfortunately, the procedure takes different parameters from +% the operator. As a result, files produced by this application +% cause an error if the setcolor operator is actually defined +% and 'bind' is ever used. Aldus fixed this bug in Freehand 3.0, +% but there are a lot of files created by the older versions +% still floating around. Therefore, at Adobe's suggestion, +% we implement the following dreadful hack in the 'where' operator: +% If the key is /setcolor, and +% there is a dictionary named FreeHandDict, and +% currentdict is that dictionary, +% then "where" consults only that dictionary and not any other +% dictionaries on the dictionary stack. +.wheredict /setcolor { + /FreeHandDict .where { + /FreeHandDict get currentdict eq { + pop currentdict /setcolor known { currentdict true } { false } ifelse + } { + .where + } ifelse + } { + .where + } ifelse +} bind put + +% ------ Virtual memory ------ % + +/currentglobal % - currentglobal <bool> + /currentshared load def +/gcheck % <obj> gcheck <bool> + /scheck load def +/setglobal % <bool> setglobal - + /setshared load def +% We can make the global dictionaries very small, because they auto-expand. +/globaldict currentdict /shareddict .knownget not { 4 dict } if def +/GlobalFontDirectory SharedFontDirectory def + +% VMReclaim and VMThreshold are user parameters. +/setvmthreshold { % <int> setvmthreshold - + mark /VMThreshold 2 .argindex .dicttomark .setuserparams2 pop +} odef +/vmreclaim { % <int> vmreclaim - + dup 0 gt { + .vmreclaim + } { + mark /VMReclaim 2 index .dicttomark .setuserparams2 pop + } ifelse +} odef +-1 setvmthreshold + +% ------ IODevices ------ % + +/.getdevparams where { + pop /currentdevparams { % <iodevice> currentdevparams <dict> + .getdevparams .dicttomark + } odef +} if +/.putdevparams where { + pop /setdevparams { % <iodevice> <dict> setdevparams - + dup type /dicttype ne { /setdevparams .systemvar /typecheck signalerror } if + mark 1 index { } forall counttomark 2 add index + .putdevparams pop pop + } odef +} if + +% ------ Job control ------ % + +serverdict begin + +% We could protect the job information better, but we aren't attempting +% (currently) to protect ourselves against maliciousness. + +/.jobsave //null def % top-level save object +/.jobsavelevel 0 def % save depth of job (0 if .jobsave is null, + % 1 otherwise) +/.adminjob //true def % status of current unencapsulated job + +end % serverdict + +% Because there may be objects on the e-stack created since the job save, +% we have to clear the e-stack before doing the end-of-job restore. +% We do this by executing a 2 .stop, which is caught by the 2 .stopped +% in .runexec; we leave on the o-stack a procedure to execute aftewards. +% +%**************** The definition of startjob is not complete yet, since +% it doesn't reset stdin/stdout. +/.startnewjob { % <exit_bool> <password_level> + % .startnewjob - + serverdict /.jobsave get dup //null eq { pop } { restore } ifelse + exch { + % Unencapsulated job + serverdict /.jobsave //null put + serverdict /.jobsavelevel 0 put + serverdict /.adminjob 3 -1 roll 1 gt put + } { + % Encapsulated job + pop + serverdict /.jobsave save put + serverdict /.jobsavelevel 1 put + .userdict /quit { stop } .bind put % CET 28-10 requires a procedure + } ifelse + % Reset the interpreter state. + clear cleardictstack + initgraphics + //false setglobal + 2 vmreclaim % Make sure GC'ed memory is reclaimed and freed. +} bind def +/.startjob { % <exit_bool> <password> <finish_proc> + % .startjob <ok_bool> + vmstatus pop pop serverdict /.jobsavelevel get eq + 2 .argindex .checkpassword 0 gt and { + exch .checkpassword exch count 3 roll count 3 sub { pop } repeat + cleardictstack + % Reset the e-stack back to the 2 .stopped in .runexec, + % passing the finish_proc to be executed afterwards. + 2 .stop + } { % Password check failed + pop pop pop //false + } ifelse +} odef +/startjob { % <exit_bool> <password> startjob <ok_bool> + % This is a hack. We really need some way to indicate explicitly + % to the interpreter that we are under control of a job server. + 1 .argindex type /booleantype ne { + /startjob .systemvar /typecheck signalerror + } if + { .startnewjob //true } .startjob +} odef + +% The procedure to undo the job encapsulation +/.endjob { + clear cleardictstack + serverdict /.jobsave get dup //null eq { pop } { restore } ifelse + serverdict /.jobsave //null put + 2 vmreclaim % recover local and global VM +} odef + +systemdict begin +/quit { % - quit - + //systemdict begin serverdict /.jobsave get null eq + { end //quit } + { /quit .systemvar /invalidaccess /signalerror load end exec } + ifelse +} bind odef +end + +% We would like to define exitserver as a procedure, using the code +% that the Red Book says is equivalent to it. However, since startjob +% resets the exec stack, we can't do this, because control would never +% proceed past the call on startjob if the exitserver is successful. +% Instead, we need to construct exitserver out of pieces of startjob. + +serverdict begin + +/exitserver { % <password> exitserver - + //true exch { .startnewjob } .startjob not { + /exitserver /invalidaccess signalerror + } if +} bind def + +end % serverdict + +% ------ Compatibility ------ % + +% In Level 2 mode, the following replace the definitions that gs_statd.ps +% installs in statusdict and serverdict. +% Note that statusdict must be allocated in local VM. +% We don't bother with many of these yet. + +/.dict1 { exch mark 3 1 roll .dicttomark } bind def + +currentglobal false setglobal 25 dict exch setglobal begin +currentsystemparams + +% The following do not depend on the presence of setpagedevice. +/buildtime 1 index /BuildTime get def +% Also define /buildtime in systemdict because Adobe does so and some fonts use it as ID +systemdict /buildtime dup load put +/byteorder 1 index /ByteOrder get def +/checkpassword { .checkpassword 0 gt } bind def +dup /DoStartPage known + { /dostartpage { /DoStartPage getsystemparam } bind def + /setdostartpage { /DoStartPage .dict1 setsystemparams } bind def + } if +dup /StartupMode known + { /dosysstart { /StartupMode getsystemparam 0 ne } bind def + /setdosysstart { { 1 } { 0 } ifelse /StartupMode .dict1 setsystemparams } bind def + } if +%****** Setting jobname is supposed to set userparams.JobName, too. +/jobname { /JobName getuserparam } bind def +/jobtimeout { /JobTimeout getuserparam } bind def +/ramsize { /RamSize getsystemparam } bind def +/realformat 1 index /RealFormat get def +dup /PrinterName known + { /setprintername { /PrinterName .dict1 setsystemparams } bind def + } if +/printername + { currentsystemparams /PrinterName .knownget not { () } if exch copy + } bind def +currentuserparams /WaitTimeout known + { /waittimeout { /WaitTimeout getuserparam } bind def + } if + +% The following do require setpagedevice. +/.setpagedevice where { pop } { (%END PAGEDEVICE) .skipeof } ifelse +/defaulttimeouts + { currentsystemparams dup + /JobTimeout .knownget not { 0 } if + exch /WaitTimeout .knownget not { 0 } if + currentpagedevice /ManualFeedTimeout .knownget not { 0 } if + } bind def +/margins + { currentpagedevice /Margins .knownget { exch } { [0 0] } ifelse + } bind def +/pagemargin + { currentpagedevice /PageOffset .knownget { 0 get } { 0 } ifelse + } bind def +/pageparams + { currentpagedevice + dup /Orientation .knownget { 1 and ORIENT1 { 1 xor } if } { 0 } ifelse exch + dup /PageSize get aload pop 3 index 0 ne { exch } if 3 2 roll + /PageOffset .knownget { 0 get } { 0 } ifelse 4 -1 roll + } bind def +/setdefaulttimeouts + { exch mark /ManualFeedTimeout 3 -1 roll + /Policies mark /ManualFeedTimeout 1 .dicttomark + .dicttomark setpagedevice + /WaitTimeout exch mark /JobTimeout 5 2 roll .dicttomark setsystemparams + } bind def +/.setpagesize { 2 array astore /PageSize .dict1 setpagedevice } bind def +/setduplexmode { /Duplex .dict1 setpagedevice } bind def +/setmargins + { exch 2 array astore /Margins .dict1 setpagedevice + } bind def +/setpagemargin { 0 2 array astore /PageOffset .dict1 setpagedevice } bind def +/setpageparams + { mark /PageSize 6 -2 roll + 4 index 1 and ORIENT1 { 1 } { 0 } ifelse ne { exch } if 2 array astore + /Orientation 5 -1 roll ORIENT1 { 1 xor } if + /PageOffset counttomark 2 add -1 roll 0 2 array astore + .dicttomark setpagedevice + } bind def +/setresolution + { dup 2 array astore /HWResolution .dict1 setpagedevice + } bind def +%END PAGEDEVICE + +% The following are not implemented yet. +%manualfeed +%manualfeedtimeout +%pagecount +%pagestackorder +%setpagestackorder + +pop % currentsystemparams + +% Flag the current dictionary so it will be swapped when we +% change language levels. (See zmisc2.c for more information.) +/statusdict currentdict def + +currentdict end +/statusdict exch .forcedef % statusdict is local, systemdict is global + +% The following compatibility operators are in systemdict. They are +% defined here, rather than in gs_init.ps, because they require the +% resource machinery. + +/devforall { % <proc> <scratch> devforall - + exch { + 1 index currentdevparams + /Type .knownget { /FileSystem eq } { false } ifelse + { exec } { pop pop } ifelse + } /exec load 3 packedarray cvx exch + (*) 3 1 roll /IODevice resourceforall +} odef +/devstatus { % <(%disk*%)> devstatus <searchable> <writable> + % <hasNames> <mounted> <removable> <searchOrder> + % <freePages> <size> true + % <string> devstatus false + dup length 5 ge { + dup 0 5 getinterval (%disk) eq { + dup /IODevice resourcestatus { + pop pop dup currentdevparams + dup /Searchable get + exch dup /Writeable get + exch dup /HasNames get + exch dup /Mounted get + exch dup /Removable get + exch dup /SearchOrder get + exch dup /Free get + exch /LogicalSize get + 9 -1 roll pop true + } { + pop false + } ifelse + } { + pop false + } ifelse + } { + pop false + } ifelse +} odef + +% ------ Color spaces ------ % + +% Move setcolorspace, setcolor, and colorspacedict to level2dict +level2dict /setcolorspace .cspace_util 1 index get put +level2dict /setcolor .cspace_util 1 index get put +level2dict /colorspacedict .cspace_util 1 index get put + +% Add the level 2 color spaces +% DevicePixel is actually a LanguageLevel 3 feature; it is here for +% historical reasons. +%% Replace 1 (gs_devpxl.ps) +(gs_devpxl.ps) runlibfile + +%% Replace 1 (gs_ciecs2.ps) +(gs_ciecs2.ps) runlibfile + +%% Replace 1 (gs_indxd.ps) +(gs_indxd.ps) runlibfile + +%% Replace 1 (gs_sepr.ps) +(gs_sepr.ps) runlibfile + +%% Replace 1 (gs_patrn.ps) +(gs_patrn.ps) runlibfile + + + +% ------ CIE color rendering ------ % + +% Define findcolorrendering and a default ColorRendering ProcSet. + +/findcolorrendering { % <intentname> findcolorrendering + % <crdname> <found> + % Adobe interpreters report /findcolorrendering (literal name), not the + % operator itself, if an error occurs in findcolorrendering. + /findcolorrendering { + /ColorRendering /ProcSet findresource + 1 .argindex dup type /nametype eq { .namestring } if (.) concatstrings + 1 index /GetPageDeviceName get exec dup type /nametype eq { .namestring } if (.) concatstrings + 2 index /GetHalftoneName get exec dup type /nametype eq { .namestring } if + concatstrings concatstrings cvn % stack: intentname procset crdname + dup /ColorRendering resourcestatus { + pop pop exch pop exch pop true + } { + pop /GetSubstituteCRD get exec false + } ifelse + } .errorexec +} odef + +5 dict dup begin + +/GetPageDeviceName { % - GetPageDeviceName <name> + currentpagedevice dup /PageDeviceName .knownget { + exch pop dup null eq { pop /none } if + } { + pop /none + } ifelse +} bind def + +/GetHalftoneName { % - GetHalftoneName <name> + currenthalftone /HalftoneName .knownget not { /none } if +} bind def + +/GetSubstituteCRD { % <intentname> GetSubstituteCRD <crdname> + pop /DefaultColorRendering +} bind def + +end +% The resource machinery hasn't been activated, so just save the ProcSet +% and let .fixresources finish the installation process. +/ColorRendering exch def + +% Define setcolorrendering. + +/.colorrenderingtypes 5 dict def + +/setcolorrendering { % <crd> setcolorrendering - + dup /ColorRenderingType get + dup type /integertype ne { + /setcolorrendering .systemvar /typecheck signalerror + } if + //.colorrenderingtypes exch .knownget { + exec + } { + /setcolorrendering .systemvar /rangecheck signalerror + } ifelse +} odef + +/.setcolorrendering1 where { pop } { (%END CRD) .skipeof } ifelse + +.colorrenderingtypes 1 { + % Adobe ProcSet "Adobe_AGM_Core 2.0 0" places an /Intent key into CRD's + dup /Intent .knownget { + //.renderingintentdict exch .knownget { .setrenderingintent } if + } if + dup .buildcolorrendering1 .setcolorrendering1 +} .bind put + +% Note: the value 101 in the next line must be the same as the value of +% GX_DEVICE_CRD1_TYPE in gscrdp.h. +.colorrenderingtypes 101 { + dup .builddevicecolorrendering1 .setdevicecolorrendering1 +} .bind put + +% sRGB output CRD, D65 white point +mark +/ColorRenderingType 1 +/RangePQR [ -0.5 2 -0.5 2 -0.5 2 ] readonly + +% Bradford Cone Space +/MatrixPQR [ 0.8951 -0.7502 0.0389 + 0.2664 1.7135 -0.0685 + -0.1614 0.0367 1.0296] readonly + +/MatrixLMN [ 3.240449 -0.969265 0.055643 + -1.537136 1.876011 -0.204026 + -0.498531 0.041556 1.057229 ] readonly + +% Inverse sRGB gamma transform +/EncodeABC [ { dup 0.00304 le + { 12.92321 mul } + { 1 2.4 div exp 1.055 mul 0.055 sub } + ifelse + } bind dup dup + ] readonly + +/WhitePoint [ 0.9505 1 1.0890 ] readonly % D65 +/BlackPoint [ 0 0 0 ] readonly + +% VonKries-like transform in Bradford Cone Space + /TransformPQR + % The implementations have been moved to C for performance. + [ { .TransformPQR_scale_WB0 } bind + { .TransformPQR_scale_WB1 } bind + { .TransformPQR_scale_WB2 } bind + ] readonly +.dicttomark setcolorrendering + +%END CRD + +% Initialize a CIEBased color space for sRGB. +/CIEsRGB [ /CIEBasedABC + mark + /DecodeLMN [ { + dup 0.03928 le { 12.92321 div } { 0.055 add 1.055 div 2.4 exp } ifelse + } bind dup dup ] readonly + /MatrixLMN [ + 0.412457 0.212673 0.019334 + 0.357576 0.715152 0.119192 + 0.180437 0.072175 0.950301 + ] readonly + /WhitePoint [0.9505 1.0 1.0890] readonly + .dicttomark readonly +] readonly def + +% ------ Painting ------ % + +% A straightforward definition of execform that doesn't actually +% do any caching. +/.execform1 { + % This is a separate operator so that the stacks will be restored + % properly if an error occurs. + dup /Matrix get concat + dup /BBox get aload pop + exch 3 index sub exch 2 index sub rectclip + dup /PaintProc get + 1 index /Implementation known not { + 1 index dup /Implementation null .forceput readonly pop + } if + exec +} .bind odef % must bind .forceput + +/.formtypes 5 dict + dup 1 /.execform1 load put +def + +/execform { % <form> execform - + gsave { + dup /FormType get //.formtypes exch get exec + } stopped grestore { stop } if +} odef + +/.patterntypes 5 dict + dup 1 /.buildpattern1 load put +def + +/makepattern { % <proto_dict> <matrix> makepattern <pattern> + dup type /dicttype eq { + % "<dict> makepattern" reports /typecheck on Adobe + /makepattern .systemvar /typecheck signalerror + } if + //.patterntypes 2 .argindex /PatternType get .knownget not { + /makepattern .systemvar /rangecheck signalerror + } if + .currentglobal false .setglobal exch + % Stack: proto matrix global buildproc + 3 index dup length 1 add dict .copydict + % Stack: proto matrix global buildproc newdict + 3 index 3 -1 roll exec + % Stack: proto matrix global newdict instance + % Create an 'Implementation' entry for the pattern dict. The PRLM 3rd says + % this about the contents of Implementation: "The type and value of this + % entry are implementation-dependent." The CET (page 2 of 18-02f) expects + % that this entry be an array and that the second element of the array be a + % gstate. We put our pattern instance struct into the first element of the + % array. + 1 index /Implementation 3 -1 roll + .getCPSImode { gstate } { //null } ifelse 2 array astore + put % put Implementation into the pattern dict. + % Stack: proto matrix global newdict + readonly exch .setglobal exch pop exch pop +} odef + +/setpattern { % [<comp1> ...] <pattern> setpattern - + { currentcolorspace 0 get /Pattern ne { + [ /Pattern currentcolorspace ] setcolorspace + } if setcolor + } stopped { + /setpattern .systemvar $error /errorname get signalerror + } if +} odef + +% The following functions emulate the actions of findcmykcustomcolor and +% setcustomcolor. These functions are described in Adobe's TN 5044. That +% same document also says "The following “operators” are not defined in the +% PostScript Language Reference Manual, but should be used as pseudo-operators +% in your PostScript language output. Separation applications from Adobe +% Systems and other vendors will redefine these convention operators to +% separate your documents. Your application should conditionally define +% procedures with these special names, as shown later in this document." +% +% We are providing these functions because we have found files created by +% "QuarkXPress: pictwpstops filter 1.0" which produce bad shading dictionaries +% if these operators are not defined. + +% Conditionally disable the TN 5044 psuedo-ops if NO_TN5044 specified +/NO_TN5044 where { pop (%END TN 5044 psuedo-ops) .skipeof } if + +% TN 5044 does not define the contents of the array. We are simply putting +% the values given into an array. This is consistent with what we see when +% testing with Adobe Distiller 6.0. +% <cyan> <magenta> <yellow> <black> <key> findcmykcustomcolor <array> +/findcmykcustomcolor { 5 array astore } bind def + +% Build a tint transform function for use by setcustomcolor. This function +% is for a Separation color space which has a DeviceCMYK base color space +% (i.e. 1 input and 4 outputs). The input to buildcustomtinttransform is the +% array created by findcmykcustomcolor. The resulting function is: +% { dup cyan mul exch dup magenta mul exch dup yellow mul exch black mul } +% Where cyan, magenta, yellow, and black are values from the array. +/buildcustomtinttransform % <array> buildcustomtinttransform <function> +{ [ /dup load 2 index 0 get /mul load + /exch load /dup load 6 index 1 get /mul load + /exch load /dup load 10 index 2 get /mul load + /exch load 13 index 3 get /mul load + ] cvx bind + exch pop % Remove the input array +} bind def + +% Set a custom color based upon a tint and array which describes the custom +% color. See findcmykcustomcolor. First we create and then set a Separation +% colorspace. Then we set the specified color. +% Note that older Adobe ProcSets apparently allow for 'null' as the tint +% for some reason, so an alternate operational mode is tolerated: +% null setcustomcolor - +/setcustomcolor % <array> <tint> setcustomcolor - +{ dup //null ne { + % Start building Separation colorspace + [ /Separation 3 index 4 get % Get separation name from array's key + /DeviceCMYK + 5 index //buildcustomtinttransform exec] % build the tint transform function + setcolorspace % Set the Separation color space as current + setcolor % Set the tint as the current color + pop % Remove the input array + } + { pop } % 'null' as the tint is ignored + ifelse +} bind def + +% This proc is supposed to implement a version of overprinting. TN 5044 says +% that this proc is not used by any shipping host-based application. We have +% only found it being used in a proc set in files by Canvas from Deneba Systems. +% Even their proc set does not actually do any overprinting. However their +% files crash if this is not defined. Thus we have a copy of this proc but +% we are simply checking for inputs being -1 and if so then we set the value +% to 0. +/setcmykoverprint { + 4 { dup -1 eq { pop 0 } if 4 1 roll } repeat setcmykcolor +} bind def + +/separation_all [/Separation /All /DeviceCMYK { dup dup dup } bind ] readonly def + +% Collect the arguments into the image dictionary +% <width> <height> <bits/sample> <matrix> <proc> args2dict <dict> +/args2dict { + 10 dict begin + {1 0} 1 + { /ImageType /Decode /DataSource /ImageMatrix /BitsPerComponent /Height /Width + } { exch def } forall + currentdict end +} bind def + +% Prints (1-gray) on all separations. +% <gray> setseparationgray - +/setseparationgray { + //separation_all setcolorspace + 1 exch sub setcolor +} bind def + +% Renders an image whose sample values specify the amount of the custom color. +% <width> <height> <bits/sample> <matrix> <proc> <array> customcolorimage - +/customcolorimage { + gsave + [ /Separation 2 index 4 get /DeviceCMYK 5 -1 roll //buildcustomtinttransform exec] setcolorspace + //args2dict exec image + grestore +} bind def + +% Renders an image on all process and custom color plates. +% <width> <height> <bits/sample> <matrix> <proc> +/separationimage { + gsave + //separation_all setcolorspace + //args2dict exec image + grestore +} bind def + +{ /buildcustomtinttransform /separation_all /args2dict } +{ currentdict exch undef } forall + +%END TN 5044 psuedo-ops + +end % level2dict diff --git a/gs/Resource/Init/gs_ll3.ps b/gs/Resource/Init/gs_ll3.ps new file mode 100644 index 000000000..dba186eb1 --- /dev/null +++ b/gs/Resource/Init/gs_ll3.ps @@ -0,0 +1,379 @@ +% Copyright (C) 1997, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for PostScript LanguageLevel 3 functions. +% This file must be loaded after gs_lev2.ps and gs_res.ps. +% These definitions go into ll3dict or various ProcSets. +% NOTE: the interpreter creates ll3dict. + +ll3dict begin + +% We need LanguageLevel 2 or higher in order to have setuserparams and +% defineresource. +languagelevel dup 2 .max .setlanguagelevel + +% ------ Idiom recognition ------ % + +/IdiomRecognition false .definepsuserparam + +% Modify `bind' to apply idiom recognition afterwards. +/.bindscratch 128 string def +% Note that since this definition of `bind' may get bound in, +% it has to function properly even at lower language levels, +% where IdiomRecognition may not be defined. +/.bind_ { % <proc> .bind <proc'> + //.bind currentuserparams /IdiomRecognition + .knownget not { false } if { + (*) { + /IdiomSet findresource + false exch { + % Stack: proc false dummykey [template substitute] + exch pop dup 1 get exch 0 get + % Stack: proc false substitute template + 3 index .eqproc { + 2 index gcheck 1 index gcheck not and { + pop + } { + 3 -1 roll pop exch not exit + } ifelse + } { + pop + } ifelse + } forall { exit } if + } //.bindscratch /IdiomSet resourceforall + } if +} def +/.bind /.bind_ load odef % note that .bind_ will get bound +currentdict /.bindscratch .undef + +DELAYBIND NOBIND or not { +% We can't just do +% /bind /.bind load def +% because then /bind load == prints --.bind-- . + /bind {//.bind_ exec} odef +} if +currentdict /.bind_ undef + +% ------ HalftoneTypes 6, 10, 16 and HalftoneMode ------ % + +% This code depends on an internal HalftoneType 7 with the following keys: +% Width, Height, Width2, Height2, TransferFunction: +% as for HalftoneType 16. +% Thresholds: a string or bytestring holding the thresholds, +% (Width x Height + Width2 x Height2) x BitsPerSample / 8 bytes, +% as for HalftoneType 16 except that the samples may be either +% 8 or 16 bits wide. +% BitsPerSample: 8 or 16. + +% Note that this HalftoneType never appears in halftone dictionaries given +% to sethalftone, only as a component in those given to .sethalftone5, +% so its numeric value can be chosen ad lib as long as it differs from the +% other values that are legal in component dictionaries for .sethalftone5 +% (currently only 1 and 3). + +/.makehalftone7 { % <dict> <dict> <source> <Width> <Height> + % (<Width2> <Height2> | null) <BPS> .makehalftone7 + % <setdict> <dict5> { .sethalftone5 } + 8 dict begin + /HalftoneType 7 def + /BitsPerSample exch def + dup null eq { + pop 0 + } { + /Height2 1 index def /Width2 2 index def mul + } ifelse 3 1 roll + /Height 1 index def + /Width 2 index def + mul add BitsPerSample 8 idiv mul .bigstring + % Stack: dict dict source str + dup type /stringtype eq { readstring } { .readbytestring } ifelse + not { /sethalftone .systemvar /rangecheck signalerror exit } if + readonly /Thresholds exch def + /TransferFunction .knownget { /TransferFunction exch def } if + % If the original Thresholds was a file, replace it with + % a new one. + dup /Thresholds get type /filetype eq { + dup /Thresholds [ Thresholds ] cvx 0 () .subfiledecode put + } if + mark /HalftoneType 5 /Default currentdict end .dicttomark + { .sethalftone5 } +} bind def + +/.bigstring { % <size> .bigstring <string|bytestring> + dup 65400 gt { .bytestring } { string } ifelse +} bind def + +/.readbytestring { % <source> <bytestring> .readbytestring + % <bytestring> <filled> + % Note that since bytestrings don't implement getinterval, + % if filled is false, there is no way to tell how much + % was read. + true exch 0 1 2 index length 1 sub { + % Stack: source true str index + 3 index read not { pop exch not exch exit } if + 3 copy put pop pop + } for 3 -1 roll pop exch +} bind def + +/.sethalftone6 { % <dict> <dict> .sethalftone6 <setdict> <dict5> + % { .sethalftone5 } + % Keys: Width, Height, Thresholds, T'Function + dup /Thresholds get + 1 index /Width get 2 index /Height get + null 8 .makehalftone7 +} bind def + +/.sethalftone10 { % <dict> <dict> .sethalftone10 <setdict> <dict5> + % { .sethalftone5 } + % Keys: Xsquare, Ysquare, Thresholds, T'Function + % Note that this is the only one of these three HalftoneTypes + % that allows either a file or a string for Thresholds. + dup /Thresholds get dup type /stringtype eq { 0 () .subfiledecode } if + 1 index /Xsquare get dup 3 index /Ysquare get dup + 8 .makehalftone7 +} bind def + +/.sethalftone16 { % <dict> <dict> .sethalftone16 <setdict> <dict5> + % { .sethalftone5 } + % Keys: Width, Height, Width2, Height2, + % Thresholds, T'Function + dup /Thresholds get + 1 index /Width get 2 index /Height get + 3 index /Width2 .knownget { % 2-rectangle case + 4 index /Height2 get + } { % 1-rectangle case + null + } ifelse 16 .makehalftone7 +} bind def + +.halftonetypes begin + 6 /.sethalftone6 load def + 10 /.sethalftone10 load def + 16 /.sethalftone16 load def +end + +% Redefine the halftone-setting operators to honor HalftoneMode. +/setcolorscreen { + /HalftoneMode getuserparam 0 eq { + //setcolorscreen + } { + 12 { pop } repeat .getdefaulthalftone + { //sethalftone } + { .setdefaulthalftone } + ifelse + } ifelse +} odef +/setscreen { + /HalftoneMode getuserparam 0 eq { + //setscreen + } { + pop pop pop .getdefaulthalftone + { //sethalftone } + { .setdefaulthalftone } + ifelse + } ifelse +} odef +/sethalftone { + /HalftoneMode getuserparam 0 eq { + //sethalftone + } { + gsave //sethalftone grestore + .getdefaulthalftone + { //sethalftone } + { .setdefaulthalftone } + ifelse + } ifelse +} odef + +% ------ ImageTypes 3 and 4 (masked images) ------ % + +.imagetypes + dup 3 /.image3 load put + dup 4 /.image4 load put +% We also detect ImageType 103 here: it isn't worth making a separate file +% just for this. + /.image3x where { pop dup 103 /.image3x load put } if +pop + +% ------ Functions ------ % + +% Define the FunctionType resource category. +/Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /integertype def +/FunctionType currentdict end /Category defineresource pop + +{0 2 3} { dup /FunctionType defineresource pop } forall + +% ------ Smooth shading ------ % + +% Define the ShadingType resource category. +/Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /integertype def +/ShadingType currentdict end /Category defineresource pop + +systemdict /.shadingtypes mark % not ll3dict + 1 /.buildshading1 load + 2 /.buildshading2 load + 3 /.buildshading3 load + 4 /.buildshading4 load + 5 /.buildshading5 load + 6 /.buildshading6 load + 7 /.buildshading7 load +.dicttomark put + +systemdict /.reuseparamdict mark + /Intent 2 + /AsyncRead false + /CloseSource true +.dicttomark readonly put +/.buildshading { % <shadingdict> .buildshading <shading> + dup rcheck not { + % Adobe seems to access ColorSpace first and CET 12-14c checks this. + /$error .systemvar /errorinfo [ /ColorSpace null ] put + /shfill .systemvar /invalidaccess signalerror + } if + % Unfortunately, we always need to make the DataSource reusable, + % because if clipping is involved, even shfill may need to read + % the source data multiple times. If it weren't for this, + % we would only need to create a reusable stream if the ultimate + % source of the data is a procedure (since the library can't + % suspend shading to do a procedure callout). + dup /DataSource .knownget { + dup type /filetype eq { + //.reuseparamdict /ReusableStreamDecode filter + % Copy the dictionary to replace the DataSource, but make sure the + % copy is in the same VM as the original. + .currentglobal 2 index gcheck .setglobal + % Stack: shdict rsdfile saveglobal + 2 index dup length dict copy exch .setglobal + dup /DataSource 4 -1 roll put exch pop + } { + pop + } ifelse + } if + % The .buildshading operators use the current color space + % for ColorSpace. + dup /ShadingType .knownget not { % error handling for CET 12-14b conformance + /$error .systemvar /errorinfo [ /ShadingType //null ] put + /shfill .systemvar /undefined signalerror + } if + dup type /integertype ne { + /$error .systemvar /errorinfo [ /ShadingType 4 index ] put + /shfill .systemvar /typecheck signalerror + } if + //.shadingtypes 1 index .knownget not { + /$error .systemvar /errorinfo [ /ShadingType 4 index ] put + /shfill .systemvar /rangecheck signalerror + } if + exch pop 1 index /ColorSpace .knownget { + { setcolorspace } stopped { + /$error .systemvar /errorinfo [ /ColorSpace 4 index ] put + /shfill .systemvar /$error .systemvar /errorname get signalerror + } if + exec + } { + /$error .systemvar /errorinfo [ /ColorSpace //null ] put + /shfill .systemvar /undefined signalerror + } ifelse +} bind def +systemdict /.reuseparamdict undef + +/.buildpattern2 { % <template> <matrix> .buildpattern2 + % <template> <pattern> + % We want to build the pattern without doing gsave/grestore, + % since we want it to load the CIE caches. + 1 index /Shading get + mark currentcolor currentcolorspace + counttomark 4 add -3 roll mark 4 1 roll + % Stack: -mark- ..color.. cspace -mark- template matrix shadingdict + { .buildshading } stopped { + cleartomark setcolorspace setcolor pop stop + } if + .buildshadingpattern + 3 -1 roll pop counttomark 1 add 2 roll setcolorspace setcolor pop +} bind def + +.patterntypes + 2 /.buildpattern2 load put + +/shfill { % <shadingdict> shfill - + % Currently, .shfill requires that the color space + % in the pattern be the current color space. + % Disable overprintmode for shfill + { dup gsave 0 .setoverprintmode .buildshading .shfill } stopped + grestore { + /$error .systemvar /errorinfo 2 copy known { + pop pop + } { + //null put % CET 12-14c + } ifelse + stop + } if + pop +} odef + +% Establish an initial smoothness value that matches Adobe RIPs. +0.02 setsmoothness + +% ------ DeviceN color space ------ % + +%% Replace 1 (gs_ciecs3.ps) +(gs_ciecs3.ps) runlibfile + +%% Replace 1 (gs_devn.ps) +(gs_devn.ps) runlibfile + +% ------ Miscellaneous ------ % + +% Make the setoverprintmode and currentoverprintmode operators visible (3015) +% Because of the requirements of PDF, the .currentoverprintmode and +% .setoverprintmode operators have integer parameters. Thus we need to +% convert the Postscript bool parameters to integers. +% +/setoverprintmode % bool setoverprint - +{ + { 1 } { 0 } ifelse % convert bool to integer + //.setoverprintmode +} odef + +/currentoverprintmode % - currentoverprintmode bool +{ + //.currentoverprintmode + 0 ne % convert integers to bool +} odef + +% Define additional user and system parameters. +/HalftoneMode 0 .definepsuserparam +/MaxSuperScreen 1016 .definepsuserparam +pssystemparams begin % read-only, so use .forcedef + /MaxDisplayAndSourceList 160000 .forcedef +end + +% Define the IdiomSet resource category. +{ /IdiomSet } { + /Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /dicttype def + currentdict end /Category defineresource pop +} forall + +/languagelevel 3 def +% When running in LanguageLevel 3 mode, this interpreter is supposed to be +% compatible with Adobe version 3010. +/version (3010) readonly def + +.setlanguagelevel + +end % ll3dict diff --git a/gs/Resource/Init/gs_mex_e.ps b/gs/Resource/Init/gs_mex_e.ps new file mode 100644 index 000000000..d7edc3f36 --- /dev/null +++ b/gs/Resource/Init/gs_mex_e.ps @@ -0,0 +1,66 @@ +% Copyright (C) 1994, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the MacExpert encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/MacExpertEncoding +% \00x + /.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 +% \04x + /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 /.notdef /threequartersemdash /.notdef /questionsmall +% \10x + /.notdef /.notdef /.notdef /.notdef /Ethsmall /.notdef /.notdef /onequarter + /onehalf /threequarters /oneeighth /threeeighths /fiveeighths /seveneighths /onethird /twothirds + /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /ff /fi + /fl /ffi /ffl /parenleftinferior /.notdef /parenrightinferior /Circumflexsmall /hypheninferior +% \14x + /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 /.notdef +% \20x + /.notdef /asuperior /centsuperior /.notdef /.notdef /.notdef /.notdef /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 +% \24x + /.notdef /eightsuperior /fourinferior /threeinferior /sixinferior /eightinferior /seveninferior /Scaronsmall + /.notdef /centinferior /twoinferior /.notdef /Dieresissmall /.notdef /Caronsmall /osuperior + /fiveinferior /.notdef /commainferior /periodinferior /Yacutesmall /.notdef /dollarinferior /.notdef + /.notdef /Thornsmall /.notdef /nineinferior /zeroinferior /Zcaronsmall /AEsmall /Oslashsmall +% \30x + /questiondownsmall /oneinferior /Lslashsmall /.notdef /.notdef /.notdef /.notdef /.notdef + /.notdef /Cedillasmall /.notdef /.notdef /.notdef /.notdef /.notdef /OEsmall + /figuredash /hyphensuperior /.notdef /.notdef /.notdef /.notdef /exclamdownsmall /.notdef + /Ydieresissmall /.notdef /onesuperior /twosuperior /threesuperior /foursuperior /fivesuperior /sixsuperior +% \34x + /sevensuperior /ninesuperior /zerosuperior /.notdef /esuperior /rsuperior /tsuperior /.notdef + /.notdef /isuperior /ssuperior /dsuperior /.notdef /.notdef /.notdef /.notdef + /.notdef /lsuperior /Ogoneksmall /Brevesmall /Macronsmall /bsuperior /nsuperior /msuperior + /commasuperior /periodsuperior /Dotaccentsmall /Ringsmall /.notdef /.notdef /.notdef /.notdef +256 packedarray +6 1 index .registerencoding +.defineencoding +exec diff --git a/gs/Resource/Init/gs_mgl_e.ps b/gs/Resource/Init/gs_mgl_e.ps new file mode 100644 index 000000000..38cfb5fbf --- /dev/null +++ b/gs/Resource/Init/gs_mgl_e.ps @@ -0,0 +1,64 @@ +% Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the Macintosh standard glyph encoding vector. +% This is not an Encoding strictly speaking, but we treat it like one. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/MacRomanEncoding .findencoding +/MacGlyphEncoding + /.notdef /.null /CR +% 3 +4 index 32 95 getinterval aload pop +% 98 +99 index 128 45 getinterval aload pop +% 143 + /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 +% 173 +174 index 203 12 getinterval aload pop + /lozenge +% 186 +187 index 216 24 getinterval aload pop + /applelogo +% 211 +212 index 241 7 getinterval aload pop + /overscore +% 219 +220 index 249 7 getinterval aload pop +% 226 + /Lslash /lslash /Scaron /scaron + /Zcaron /zcaron /brokenbar /Eth /eth + /Yacute /yacute /Thorn /thorn /minus + /multiply /onesuperior /twosuperior /threesuperior /onehalf + /onequarter /threequarters /franc /Gbreve /gbreve + % The TrueType documentation says the next glyph is named + % Idot, but the Adobe standard name for this glyph is + % Idotaccent. + /Idotaccent /Scedilla /scedilla /Cacute /cacute + /Ccaron /ccaron /dmacron +260 -1 roll pop % delete MacRomanEncoding +258 packedarray +7 1 index .registerencoding +.defineencoding +exec diff --git a/gs/Resource/Init/gs_mro_e.ps b/gs/Resource/Init/gs_mro_e.ps new file mode 100644 index 000000000..dd754c6c4 --- /dev/null +++ b/gs/Resource/Init/gs_mro_e.ps @@ -0,0 +1,61 @@ +% Copyright (C) 1994, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the MacRoman encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/MacRomanEncoding +StandardEncoding 0 39 getinterval aload pop + /quotesingle +StandardEncoding 40 56 getinterval aload pop + /grave +StandardEncoding 97 31 getinterval aload pop +% \20x + /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 +% \24x + /dagger /degree /cent /sterling /section /bullet /paragraph /germandbls + /registered /copyright /trademark /acute /dieresis /.notdef /AE /Oslash + /.notdef /plusminus /.notdef /.notdef /yen /mu /.notdef /.notdef + /.notdef /.notdef /.notdef /ordfeminine /ordmasculine /.notdef /ae /oslash +% \30x + /questiondown /exclamdown /logicalnot /.notdef + /florin /.notdef /.notdef /guillemotleft + /guillemotright /ellipsis /space /Agrave /Atilde /Otilde /OE /oe + /endash /emdash /quotedblleft /quotedblright + /quoteleft /quoteright /divide /.notdef + % NOTE: Euro should replace currency, but the PDF 1.3 documentation + % explicitly says it does not. + /ydieresis /Ydieresis /fraction /currency + /guilsinglleft /guilsinglright /fi /fl +% \34x + /daggerdbl /periodcentered /quotesinglbase /quotedblbase + /perthousand /Acircumflex /Ecircumflex /Aacute + /Edieresis /Egrave /Iacute /Icircumflex + /Idieresis /Igrave /Oacute /Ocircumflex + /.notdef /Ograve /Uacute /Ucircumflex + /Ugrave /dotlessi /circumflex /tilde + /macron /breve /dotaccent /ring /cedilla /hungarumlaut /ogonek /caron +256 packedarray +5 1 index .registerencoding +.defineencoding +exec diff --git a/gs/Resource/Init/gs_patrn.ps b/gs/Resource/Init/gs_patrn.ps new file mode 100644 index 000000000..d41f25573 --- /dev/null +++ b/gs/Resource/Init/gs_patrn.ps @@ -0,0 +1,309 @@ +% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Pattern color space method dictionary. + + +% verify that Pattern color spaces are supported +/.setpatternspace where + { pop } + { currentfile closefile } +ifelse + +.currentglobal true .setglobal +.cspace_util begin + +% +% <name1 | array1> get_pattern_base_cspace <null | name2 | array2> +% +% If the Pattern color space has a base color space, push that base +% color space onto the stack. Otherwise, push a null object. +% +/get_pattern_base_cspace + { + dup type /nametype eq + { pop //null } + { + dup length 1 gt + { 1 get } + { pop //null } + ifelse + } + ifelse + } +bind def + + +% +% <dict> has_base_color <bool> +% +% Determine if a Pattern "color" includes a base color. This is the case +% if the pattern dictionary has PatternType 1 and PaintType 2. +% +/has_base_color + { + dup //null eq + { pop //false } + { + dup /PatternType get 1 eq + { /PaintType get 2 eq } + { pop //false } + ifelse + } + ifelse + } +bind def + +% +% <c1> ... <cn> <pattern_dict> <pattern_cspace> +% get_pattern_base_color +% <c1> ... <cn> <base_cspace> true +% or +% <?c1?> ... <?cn?> <dict> <pattern> +% get_pattern_base_color +% false +% +% If a pattern dictionary has a base color, set up that base color and +% color space, and push true. Otherwise, just push false. It is assumed +% that if the pattern includes a base color, the Pattern color space +% has a base color space. +% +/get_pattern_base_color + { + exch //has_base_color exec + { 1 get //true } + { pop //false } + ifelse + } +bind def + + +colorspacedict +/Pattern + mark + /cs_potential_indexed_base false + /cs_potential_pattern_base false + /cs_potential_alternate false + /cs_potential_icc_alternate false + + % + % We employ the same convention for describing the number of + % components in a Pattern color space as is used by the graphic + % library. For pattern spaces with no underlying color space, + % the result is -1. If a Pattern space has an underlying color + % space with n components, the result is -(n + 1). + % + /cs_get_ncomps + { + //get_pattern_base_cspace exec dup //null eq + { pop 0 } + //.cs_get_ncomps + ifelse + 1 add neg + } + bind + + % there is no "range" for a Pattern color space + /cs_get_range { {} cvlit } bind + + /cs_get_default_color { pop //null } bind + + /cs_get_currentgray + { + //get_pattern_base_color exec + //.cs_get_currentgray + { 0. } + ifelse + } + bind + + /cs_get_currentrgb + { + //get_pattern_base_color exec + //.cs_get_currentrgb + { 0. 0. 0. } + ifelse + } + bind + + /cs_get_currentcmyk + { + //get_pattern_base_color exec + //.cs_get_currentcmyk + { 0. 0. 0. 1. } + ifelse + } + bind + + /cs_validate + { + dup //get_pattern_base_cspace exec dup //null eq + { pop } + { + //.cs_validate exec //.cs_potential_pattern_base exec not + //setcspace_rangecheck + if + } + ifelse + } + bind + + % substitute the base space if appropriate + /cs_substitute + { + dup //get_pattern_base_cspace exec dup //null eq + { pop dup } + { + //.cs_substitute exec 2 copy eq + { pop pop dup } + { + % retain only the new alternate space + exch pop + + % build all new structures in local VM + .currentglobal 3 1 roll //false .setglobal + + % construct a new array and insert the new base color space + 1 index dup length array copy dup 1 4 -1 roll put + + % restore VM mode + 3 -1 roll .setglobal + } + ifelse + } + ifelse + } + bind + + /cs_prepare {} + + % + % Install the current color space. + % + % The current Ghostscript color space implementation requires that + % color spaces that provide a base or alternative color space set + % that base/alternative color space to be the current color space + % before attempting to set the original color space. + % + % In principle, the only errors that are possible for .setpatternspace + % (given that setcolorspace itself is legal) are limitcheck and/or + % VMerror. The Ghostscript implementation allows a few others, so + % we go through the full code to restore the current color space in + % the event of an error. + % + /cs_install + { + dup //get_pattern_base_cspace exec dup //null eq + { + pop + dup type /nametype eq + { pop { /Pattern } cvlit } + if + .setpatternspace + } + { + % save the current color space + currentcolorspace + + % set the base color space as the current color space + exch //forcesetcolorspace + + % set the pattern color space; restore the earlier space on error + mark 2 index + { .setpatternspace } + stopped + { cleartomark setcolorspace stop } + { pop pop pop } + ifelse + } + ifelse + } + bind + + + % + % Pattern dictionaries generated by makepattern will include an + % Implementation entry whose value is an internal data structure. + % Such structures are given executable type names that match their + % internal structure names. The names used for pattern + % implementations are gs_pattern1_instance_t and + % gs_pattern2_instance_t. It is unfortunate to have to expose such + % internal names at this level, but not easily avoided. + % For CPSI/CET compatibility we 'hide' this inside an array + % + /cs_prepare_color + { + % verify that the topmost operand is a pattern dictionary + 1 index dup type /dicttype ne + { + //null ne + //setcspace_typecheck + if + pop + } + { + dup /Implementation .knownget + { 0 get type dup dup + /gs_pattern1_instance_t ne exch /gs_pattern2_instance_t ne and + exch xcheck not + or + //setcspace_typecheck + if + } + //setcspace_typecheck + ifelse + + % check if base color space operands are present + dup /PatternType get 1 eq + { + /PaintType get 2 eq + { + % verify that a base color space exists + //get_pattern_base_cspace exec dup //null eq + //setcspace_rangecheck + if + //.cs_get_ncomps exec + % We cannot use check_num_stack since it does not + % properly clean the stack. The CET test 09-47n.ps has + % a very bad test case with a faulty setpattern call with + % no color values. To properly handle that case and to + % ensure that the stack is properly cleaned, we are + % testing the type of the color values inline. + 1 exch 1 exch + { + index type dup /integertype ne exch /realtype ne and + //setcolor_typecheck + if + } + for + } + { pop } + ifelse + } + { pop pop } + ifelse + } + ifelse + } + bind + + /cs_complete_setcolor //pop_1 + + .dicttomark +put + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_pdf_e.ps b/gs/Resource/Init/gs_pdf_e.ps new file mode 100644 index 000000000..58b722f13 --- /dev/null +++ b/gs/Resource/Init/gs_pdf_e.ps @@ -0,0 +1,44 @@ +% Copyright (C) 1994, 1997, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the PDFDoc encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/PDFDocEncoding +ISOLatin1Encoding 0 24 getinterval aload pop + /breve /caron /circumflex /dotaccent /hungarumlaut /ogonek /ring /tilde +ISOLatin1Encoding 32 7 getinterval aload pop + /quotesingle +ISOLatin1Encoding 40 5 getinterval aload pop + /hyphen +ISOLatin1Encoding 46 50 getinterval aload pop + /grave +ISOLatin1Encoding 97 31 getinterval aload pop +% \20x + /bullet /dagger /daggerdbl /ellipsis /emdash /endash /florin /fraction + /guilsinglleft /guilsinglright /minus /perthousand + /quotedblbase /quotedblleft /quotedblright /quoteleft + /quoteright /quotesinglbase /trademark /fi /fl /Lslash /OE /Scaron + /Ydieresis /Zcaron /dotlessi /lslash /oe /scaron /zcaron /.notdef +% \24x + /Euro +ISOLatin1Encoding 161 12 getinterval aload pop + /.notdef +ISOLatin1Encoding 174 82 getinterval aload pop +256 packedarray .defineencoding +exec diff --git a/gs/Resource/Init/gs_pdfwr.ps b/gs/Resource/Init/gs_pdfwr.ps new file mode 100644 index 000000000..8705fbb69 --- /dev/null +++ b/gs/Resource/Init/gs_pdfwr.ps @@ -0,0 +1,874 @@ +% Copyright (C) 1996, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% PDF writer additions to systemdict. + +% This file should be included iff the pdfwrite "device" is included +% in the executable. + +% ---------------- Predefined configurations ---------------- % + +% These correspond to the 4 predefined settings in Acrobat Distiller 5, +% plus a "default" setting that doesn't downsample images. + +/.a2112 [2 1 1 2] readonly def +/.a1111 [1 1 1 1] readonly def +/.standardfonts [ + /Courier /Courier-Bold /Courier-Oblique /Courier-BoldOblique + /Helvetica /Helvetica-Bold /Helvetica-Oblique /Helvetica-BoldOblique + /Times-Roman /Times-Bold /Times-Italic /Times-BoldItalic + /Symbol /ZapfDingbats +] readonly def + +% Parameters common to all non-default configurations. +% Note that the default configuration overrides a few of these. +/.defaultImageDict mark + /QFactor 0.9 /Blend 1 + /HSamples .a2112 /VSamples .a2112 +.dicttomark readonly def +/.distillercommon mark + /AlwaysEmbed [] + /AntiAliasColorImages false + /AntiAliasGrayImages false + /AntiAliasMonoImages false + /ASCII85EncodePages false + /AutoFilterColorImages true + /AutoFilterGrayImages true + /AutoPositionEPSFiles true + /Binding /Left + /CalCMYKProfile (None) % (U.S. Web Coated (SWOP) v2) + /CalGrayProfile (None) % (Dot Gain 20%) + /CalRGBProfile (None) % (sRGB IEC61966-2.1) + /ColorImageDepth -1 + /ColorImageDict .defaultImageDict + /ColorImageDownsampleThreshold 1.5 + /ColorImageFilter /DCTEncode + /CompressPages true + /ConvertImagesToIndexed true + /DefaultRenderingIntent /Default + /DetectBlends true + /DownsampleColorImages true + /DownsampleGrayImages true + /DownsampleMonoImages true + /EmitDSCWarnings false + /EncodeColorImages true + /EncodeGrayImages true + /EncodeMonoImages true + /EndPage -1 + /GrayImageDepth -1 + /GrayImageDict .defaultImageDict + /GrayImageDownsampleThreshold 1.5 + /GrayImageFilter /DCTEncode + /ImageMemory 524288 + /LockDistillerParams false + /MaxSubsetPct 100 + /MonoImageDepth -1 + /MonoImageDict mark + /K -1 + .dicttomark readonly + /MonoImageDownsampleThreshold 1.5 + /MonoImageFilter /CCITTFaxEncode + /OffOptimizations 0 + /OPM 1 + /Optimize true + /ParseDSCComments true + /ParseDSCCommentsForDocInfo true + /PDFXTrimBoxToMediaBoxOffset [0 0 0 0] + /PDFXSetBleedBoxToMediaBox true + /PDFXBleedBoxToTrimBoxOffset [0 0 0 0] + /PreserveCopyPage true + /PreserveHalftoneInfo false + /sRGBProfile (None) % (sRGB IEC61966-2.1) + /StartPage 1 + /SubsetFonts true + /TransferFunctionInfo /Preserve + /UseFlateCompression true + /UsePrologue false +.dicttomark readonly def + +/.distillersettings mark + +/default mark + /AutoRotatePages /PageByPage + /CannotEmbedFontPolicy /Warning + /ColorACSImageDict .defaultImageDict + /ColorConversionStrategy /LeaveColorUnchanged +% /ColorImageDownsampleType +% /ColorImageResolution +% /CompatibilityLevel + /CreateJobTicket false + /DoThumbnails false + /DownsampleColorImages false % override + /DownsampleGrayImages false % override + /DownsampleMonoImages false % override + /EmbedAllFonts true + /GrayACSImageDict .defaultImageDict +% /GrayImageDownsampleType +% /GrayImageResolution +% /MonoImageDownsampleType +% /MonoImageResolution + /NeverEmbed .standardfonts + /Optimize false % override + /PreserveEPSInfo true + /PreserveOPIComments true + /PreserveOverprintSettings true + /UCRandBGInfo /Preserve +.dicttomark readonly + +/.screenACSImageDict mark + /QFactor 0.76 /Blend 1 /ColorTransform 1 + /HSamples .a2112 /VSamples .a2112 +.dicttomark readonly def +/screen mark + /AutoRotatePages /PageByPage +% /CalGrayProfile (None) + /CannotEmbedFontPolicy /Warning + /ColorACSImageDict .screenACSImageDict + /ColorConversionStrategy /sRGB + /ColorImageDownsampleType /Average + /ColorImageResolution 72 + /CompatibilityLevel 1.3 + /CreateJobTicket false + /DoThumbnails false + /EmbedAllFonts true + /GrayACSImageDict .screenACSImageDict + /GrayImageDownsampleType /Average + /GrayImageResolution 72 + /MonoImageDownsampleType /Average + /MonoImageResolution 300 + /NeverEmbed .standardfonts + /PreserveEPSInfo false + /PreserveOPIComments false + /PreserveOverprintSettings false + /UCRandBGInfo /Remove +.dicttomark readonly + +/ebook mark + /AutoRotatePages /All +% /CalGrayProfile (None) + /CannotEmbedFontPolicy /Warning + /ColorACSImageDict .screenACSImageDict + /ColorConversionStrategy /sRGB + /ColorImageDownsampleType /Bicubic + /ColorImageResolution 150 + /CompatibilityLevel 1.4 + /CreateJobTicket false + /DoThumbnails false + /EmbedAllFonts true + /GrayACSImageDict .screenACSImageDict + /GrayImageDownsampleType /Bicubic + /GrayImageResolution 150 + /MonoImageDownsampleType /Bicubic + /MonoImageResolution 300 + /NeverEmbed .standardfonts + /PreserveEPSInfo false + /PreserveOPIComments false + /PreserveOverprintSettings false + /UCRandBGInfo /Remove +.dicttomark readonly + +/.printerACSImageDict mark + /QFactor 0.4 /Blend 1 /ColorTransform 1 + /HSamples .a1111 /VSamples .a1111 +.dicttomark readonly def +/printer mark + /AutoRotatePages /None +% /CalGrayProfile (None) + /CannotEmbedFontPolicy /Warning + /ColorACSImageDict .printerACSImageDict + /ColorConversionStrategy /UseDeviceIndependentColor + /ColorImageDownsampleType /Bicubic + /ColorImageResolution 300 + /CompatibilityLevel 1.4 + /CreateJobTicket true + /DoThumbnails false + /EmbedAllFonts true + /GrayACSImageDict .printerACSImageDict + /GrayImageDownsampleType /Bicubic + /GrayImageResolution 300 + /MonoImageDownsampleType /Bicubic + /MonoImageResolution 1200 + /NeverEmbed [] + /PreserveEPSInfo true + /PreserveOPIComments true + /PreserveOverprintSettings true + /UCRandBGInfo /Preserve +.dicttomark readonly + +/.prepressACSImageDict mark + /QFactor 0.15 /Blend 1 /ColorTransform 1 + /HSamples .a1111 /VSamples .a1111 +.dicttomark readonly def +/prepress mark + /AutoRotatePages /None + /CannotEmbedFontPolicy /Error + /ColorACSImageDict .prepressACSImageDict + /ColorConversionStrategy /LeaveColorUnchanged + /ColorImageDownsampleType /Bicubic + /ColorImageResolution 300 + /CompatibilityLevel 1.4 + /CreateJobTicket true + /DoThumbnails true + /EmbedAllFonts true + /GrayACSImageDict .prepressACSImageDict + /GrayImageDownsampleType /Bicubic + /GrayImageResolution 300 + /MonoImageDownsampleType /Bicubic + /MonoImageResolution 1200 + /NeverEmbed [] + /PreserveEPSInfo true + /PreserveOPIComments true + /PreserveOverprintSettings true + /UCRandBGInfo /Preserve +.dicttomark readonly + +% Define distiller settings for the ps2write device and for the ps2ps2 script : +/PSL2Printer mark + /AutoRotatePages /None + /CannotEmbedFontPolicy /Error + /ColorACSImageDict .prepressACSImageDict + /ColorConversionStrategy /LeaveColorUnchanged + /ColorImageDownsampleType /Bicubic + /ColorImageResolution 600 + /CompatibilityLevel 1.2 % Always 1.2 with ps2write. + % /CreateJobTicket true % Not sure + /DoThumbnails false + /EmbedAllFonts true + /GrayACSImageDict .prepressACSImageDict + /GrayImageDownsampleType /Bicubic + /GrayImageResolution 600 + /MonoImageDownsampleType /Bicubic + /MonoImageResolution 1200 + /NeverEmbed [] + /PreserveEPSInfo true + /PreserveOPIComments true + /PreserveOverprintSettings true + /UCRandBGInfo /Preserve + + /PreserveHalftoneInfo true + /TransferFunctionInfo /Preserve + /MaxViewerMemorySize 8000000 + /CompressPages false + /CompressFonts false + /ASCII85EncodePages true +.dicttomark readonly + +.dicttomark readonly def + +% ---------------- End of predefined configurations ---------------- % + +% Set optimizations for converting PostScript to PDF. +% The ps2pdf* scripts invoke this. +/.setpdfwrite { % - .setpdfwrite - + % Set a large VM threshold to reduce garbage collection. + currentuserparams /VMThreshold get 3000000 .max setvmthreshold +} bind def + +% ---------------- pdfmark and DSC processing ---------------- % + +/.write_small_positive_real % <file> <real> .write_small_positive_real - +{ % The argument must be grater than 0 and must be strongly samller than 0.1. + % The conversion isn't simple due to the low (24 bits) precision + % of the floating point arithmetics in Postscript. + % For best result we first use the 1e8 factor since its binary + % representation 101111101011110000100000000 well rounds into 14 significant + % bits : 101111101011110000000000000 . + 1 index (.) writestring + { dup 100000000 mul + dup 10 mul 1 ge { + % Will need not greater than 0.1 due to a rounding below. + pop exit + } if + exch pop + 1 index (00000000) writestring + } loop + % Now it is not smaller than 1e-9, use simple digitizing. + { dup 10 mul + dup 10 mul 1 ge { + pop exit + } if + exch pop + 1 index (0) writestring + } loop + % Now 0.01 <= n < 0.1, but rounding may give 0.1 . + % Convert to integer with 7 digits precision : + 100000000 % precision factor 1e8 % f n r + dup 10 idiv 3 1 roll mul 0.5 add cvi % f r' N + 2 copy le { + % The rounding overflows, suppress it. + % Note it carries out an additional digit, + % that's why we needed <0.1 above. + pop pop (1) writestring + } { + % Didn't cary out, put 0. + 2 index (0) writestring + exch % f N r + % Continue the simple digitizing : + { 10 idiv dup % f N r' r' + 2 index exch idiv % f N r' d + (0123456789) exch 1 getinterval % f N r' (d) + 3 index exch writestring % f N r' + dup 3 2 roll exch mod % f r' N' + dup 0 eq { + % Don't write trailing zeros. + exit + } if + exch % f N' r' + } loop + pop pop pop + } ifelse +} bind def + +% Encode values to pass for the /pdfmark or /DSC pseudo-parameter. +/.pdf===dict mark + /arraytype + { dup xcheck { ({) (}) } { ([) (]) } ifelse + % Stack: file obj left right + 4 1 roll 2 index exch writestring () exch + { exch 2 index exch writestring + 1 index exch pdf===only ( ) + } + forall pop exch writestring + } bind + /packedarraytype 1 index + /dicttype + { 1 index (<<\n) writestring + { 2 index 3 -1 roll pdf===only 1 index ( ) writestring + 1 index exch pdf===only dup (\n) writestring + } + forall (>>) writestring + } bind + /nametype { + % If the name string includes any non-regular characters, + % write it with two preceding and one following null character(s). + % (Null characters in the name itself are not allowed.) + % This non-standard escape convention is required for passing names + % that include non-regular characters, because PostScript provides + % no way to do this. The pdf_scan_token procedure in the C code of + % the pdfwrite driver is currently the only place that recognizes + % this convention. + % Note that \004 may be self-delimiting in gs, but is not in standard PS. + dup .namestring (\000\004\011\012\014\015 %()/<>[]{}) .stringbreak null ne { + dup .namestring (\000) .stringbreak null ne { + /rangecheck signalerror + } if + 1 index <0000> writestring 1 index exch write===only 0 write + } { + write===only + } ifelse + } bind + /realtype { + % Prevent using floating point format - see Bug 688167. + dup dup 0 lt { neg } if 0.01 lt { + dup 0 eq { + pop (0) writestring + } { + dup 0 lt { + 1 index (-) writestring neg + } if + .write_small_positive_real + } ifelse + } { + write===only + } ifelse + } bind +.dicttomark readonly def +/pdf===only { % <file> <obj> pdf===only - + .pdf===dict 1 index type .knownget { exec } { write===only } ifelse +} bind def +/.pdfcvbuf 30 string def % enough for most arguments +userdict /.pdfcvstring () put +/.pdfcvs { % <obj> .pdfcvs <string> + currentglobal exch false .setglobal + /.pdfcvstring () store + % We can't handle long values yet. + { pop dup length 0 eq { pop } { + /.pdfcvstring .pdfcvstring 3 -1 roll concatstrings store + } ifelse //.pdfcvbuf + } /NullEncode filter dup 3 -1 roll pdf===only + closefile + .setglobal .pdfcvstring +} bind def + +% Redefine pdfmark to pass the data to the driver. +% We use a pseudo-parameter named /pdfmark whose value is an array: +% /key1 (value1) ... (CTM) /type +/.pdfputparams { % -mark- <key1> <value1> ... .pdfputparams <result...> + currentdevice null false counttomark 1 add 3 roll + % Don't allow the page device to get cleared.... + {.putdeviceparams} .currentpagedevice pop {.setpagedevice} 3 .execn +} bind def +% Convert relevant operands to strings in an array. +/.pdfcvsloop { % -mark- values ... markname start step .pdfcvsloop + % [values ... ctm markname] + matrix currentmatrix .pdfcvs 4 1 roll + counttomark 1 add 2 roll + counttomark .localvmarray astore exch pop + 3 1 roll + % Stack: values start step + 2 index length 3 sub { 2 copy 2 copy get .pdfcvs put pop } for +} bind def +/.pdfcvsall { % -mark- values ... markname .pdfcvsall <<same>> + 0 1 .pdfcvsloop +} bind def +/.pdfcvseven { % -mark- key value ... markname .pdfcvseven <<same>> + 1 2 .pdfcvsloop +} bind def +/.pdfcvsnone { % -mark- values ... markname .pdfcvsnone <<same>> + 100000 1 .pdfcvsloop +} bind def +/.pdfcvsfirst { % -mark- first values ... markname .pdfcvsfirst<<same>> + .pdfcvsnone + dup 0 2 copy get .pdfcvs put +} bind def +% The procedures in the following dictionary are called with the entire +% pdfmark operand list (including the pdfmark name) on the stack; +% they may modify this ad lib. They must call .pdfcvsxxx. +/.pdfmarkparams mark + % Unpack a dictionary for PUT, and don't convert stream data. + /PUT { + counttomark 3 eq { + 1 index type /dicttype eq { + pop { } forall /.PUTDICT .pdfcvsall + } { + pop dup type /filetype eq { + % Read the file into a sequence of strings. + % This isn't great, but it's simple. + { + dup 64000 string readstring not { exch exit } if + exch + } loop closefile + } if + /.PUTSTREAM .pdfcvsfirst + } ifelse + } { + .pdfcvsall + } ifelse + } bind + % Unpack the array for PUTINTERVAL. + /PUTINTERVAL { + pop aload pop /.PUTINTERVAL .pdfcvsall + } bind +.dicttomark readonly def +/.pdfparamerror { % ? ? ? -mark- ... <errname> <opname> .pdfparamerror - + counttomark 4 add 2 roll cleartomark pop pop pop + .systemvar exch signalerror +} bind def +/pdfmark { % -mark- <key> <value> ... <markname> pdfmark - + dup /SP eq { + % A hack for synchronizing the clipping path. + gsave + [1 0 0 1 0 0] setmatrix 0 setlinewidth + newpath -3 -3 moveto closepath stroke % Paints outside the device bbox. + grestore + } if + dup /PS eq systemdict /PDFX .knownget not { false } if + systemdict /PDFA .knownget not { false } if or and { + % Execute it since PDF/X doesn't allow to embed it. + pop + { dup mark eq { + pop exit + } if + 1 index /DataSource eq { + exch pop + cvx exec + } { + pop pop + } ifelse + } loop + } { + counttomark 1 add copy + //.pdfmarkparams 1 index .knownget { exec } { .pdfcvsall } ifelse + mark /pdfmark 3 -1 roll .pdfputparams + dup type /booleantype ne { + /pdfmark .pdfparamerror + } if cleartomark + } ifelse +} odef +userdict /pdfmark .undef +currentdict /.pdfmarkparams .undef + + +% <dict> .hook_DSC_Creator - +/.pdf_hook_DSC_Creator +{ + % If the Creator is PScript5.dll, disable the 32 /FontType resource for + % handling GlyphNames2Unicode. Since /FontType category can't redefine, + % we can do only with redefining the operator 'resourcestatus'. + currentdevice .devicename /pdfwrite eq { + /Creator .knownget { + (PScript5.dll) search { + pop pop + systemdict /resourcestatus dup + { dup /FontType eq 2 index 32 eq and { + pop pop false + } { + resourcestatus + } ifelse + } bind .makeoperator .forceput + } if + pop + } if + } { + pop + } ifelse +} +bind def + +% Use the DSC processing hook to pass DSC comments to the driver. +% We use a pseudo-parameter named DSC whose value is an array: +% /key1 (value1) ... /type +/.pdfdsc_dict 2 dict def +/.pdfdsc { % <file> <DSC string> <dsc dict> [<prev proc>] .pdfdsc - + 0 get dup null ne { 4 copy exch pop exec pop } { pop } ifelse 3 -1 roll pop + % Stack: <dsc string> <dsc dict> + 20 .localvmdict 1 index { 3 copy put pop pop } forall + 3 -1 roll .parse_dsc_comments % <dsc dict> <dict> <type> + 1 index //.pdf_hook_DSC_Creator exec + dup /NOP ne 2 index length 1 gt or { % Skip unparsed comments + PDFWRDEBUG { (**** DSC comment: ) print dup == 1 index === flush } if + exch mark 4 1 roll { + % mark <key1> <value1> ... <dsc dict> <type> <key> <value> + 3 index 2 index known { % Skip the DSC_struct entry + pop pop + } { + .pdfcvs 4 -2 roll + } ifelse + } forall exch pop counttomark .localvmarray astore + mark /DSC 3 -1 roll .pdfputparams + dup type /booleantype ne { + /DSC .pdfparamerror + } { + cleartomark + } ifelse + } { + pop pop pop + } ifelse +} bind def +currentdict /.pdf_hook_DSC_Creator undef +/.initialize_dsc_parser where { + pop + 3000 % priority + { + currentglobal true setglobal + 2 dict dup .initialize_dsc_parser readonly + currentuserparams /ProcessDSCComment get + 1 array astore % in case the value is executable + //.pdfdsc /exec load 4 array astore cvx readonly + << /ProcessDSCComment 3 -1 roll >> setuserparams + setglobal + } bind .schedule_init +} if + +% ---------------- {set,current}distillerparams ---------------- % + +% Define setdistillerparams / currentdistillerparams. +% Distiller parameters are currently treated as device parameters. +/.distillerparamkeys mark + % General parameters -- all distillers + /ASCII85EncodePages { } + /AutoRotatePages { } + /Binding { } + /CompressPages { } + /DefaultRenderingIntent { } + /DetectBlends { } + /DoThumbnails { } + /ImageMemory { } + /LockDistillerParams { } + /LZWEncodePages { } + /OPM { } + /PreserveHalftoneInfo { } + /PreserveOPIComments { } + /PreserveOverprintSettings { } + /TransferFunctionInfo { } + /UCRandBGInfo { } + /UseFlateCompression { } + % General parameters -- PDF writer + % StartPage and EndPage are renamed because EndPage + % clashes with a page device parameter. + /CoreDistVersion { } + /CompatibilityLevel { } + % ****** NOTE: StartPage and EndPage are disabled because + % ****** EndPage clashes with a page device parameter. +% /EndPage { exch pop /PDFEndPage exch } + /PDFEndPage { pop pop } +% /StartPage { exch pop /PDFStartPage exch } + /PDFStartPage { pop pop } + /Optimize { } + /ParseDSCCommentsForDocInfo { } + /ParseDSCComments { } + /EmitDSCWarnings { } + /CreateJobTicket { } + /PreserveEPSInfo { } + /AutoPositionEPSFiles { } + /PreserveCopyPage { } + /UsePrologue { } + /OffOptimizations { } + % PDF/X parameters + /PDFXTrimBoxToMediaBoxOffset { } + /PDFXSetBleedBoxToMediaBox { } + /PDFXBleedBoxToTrimBoxOffset { } + % Color sampled image parameters + /ColorACSImageDict { } + /AntiAliasColorImages { } + /AutoFilterColorImages { } + /ColorImageDepth { } + /ColorImageDict { } + /DownsampleColorImages { } + /ColorImageDownsampleThreshold { } + /ColorImageDownsampleType { } + /EncodeColorImages { } + /ColorImageFilter { } + /ColorImageResolution { } + % Color processing parameters + /CalCMYKProfile { } + /CalGrayProfile { } + /CalRGBProfile { } + /sRGBProfile { } + /ColorConversionStrategy { } + /ConvertCMYKImagesToRGB { } + /ConvertImagesToIndexed { } + % Grayscale sampled image parameters + /GrayACSImageDict { } + /AntiAliasGrayImages { } + /AutoFilterGrayImages { } + /GrayImageDepth { } + /GrayImageDict { } + /DownsampleGrayImages { } + /GrayImageDownsampleThreshold { } + /GrayImageDownsampleType { } + /EncodeGrayImages { } + /GrayImageFilter { } + /GrayImageResolution { } + % Monochrome sampled image parameters + /AntiAliasMonoImages { } + /MonoImageDepth { } + /MonoImageDict { } + /DownsampleMonoImages { } + /MonoImageDownsampleThreshold { } + /MonoImageDownsampleType { } + /EncodeMonoImages { } + /MonoImageFilter { } + /MonoImageResolution { } + % Font embedding parameters + /AlwaysEmbed + { dup length 0 gt + { dup 0 get false eq + { dup length 1 sub 1 exch getinterval exch pop /~AlwaysEmbed exch + } if + } if + } + /NeverEmbed + { dup length 0 gt + { dup 0 get false eq + { dup length 1 sub 1 exch getinterval exch pop /~NeverEmbed exch + } if + } if + } + /CannotEmbedFontPolicy { } + /EmbedAllFonts { } + /MaxSubsetPct { } + /SubsetFonts { } + /DSCEncodingToUnicode { } +.dicttomark readonly def +/.distillerdevice + { currentdevice .devicename dup /pdfwrite eq exch /ps2write eq or + { currentdevice } + { /pdfwrite finddevice } + ifelse + } bind def + +% Some badly designed PostScript files only expect the current/set +% distillerparams operators to exist in a distiller. Since we have +% this as a runtime option, we enable these operators IFF the +% currentdevice is pdfwrite. Also, we mask their existence in +% systemdict so that 'where' and 'known' don't show them unless +% the currentdevice is pdfwrite. +/.setdistillerparams { % <dict> setdistillerparams - + .distillerdevice //null false mark 4 index { + //.distillerparamkeys 2 index .knownget { exec } { pop pop } ifelse + } forall .putdeviceparamsonly + dup type /booleantype ne { + /setdistillerparams .pdfparamerror + } { + pop pop pop + } ifelse +} odef +/.currentdistillerparams { % - currentdistillerparams <dict> + .distillerdevice //.distillerparamkeys .getdeviceparams .dicttomark + % Patch StartPage and EndPage + % ****** NOTE: StartPage and EndPage are disabled because + % ****** EndPage clashes with a page device parameter. +% begin /StartPage PDFStartPage /EndPage PDFEndPage +% currentdict dup /PDFStartPage undef /PDFEndPage undef +% def def currentdict end +} odef +/setdistillerparams { + currentdevice .devicename dup /pdfwrite ne exch /ps2write ne and { + /setdistillerparams /undefined signalerror + } if + .setdistillerparams +} bind odef +/currentdistillerparams { + currentdevice .devicename dup /pdfwrite ne exch /ps2write ne and { + /currentdistillerparams /undefined signalerror + } if + .currentdistillerparams +} bind odef + +% Patch 'where' so that the distiller operators are only visible +% if the pdfwrite device is the current one. +{ currentdevice .devicename dup /pdfwrite eq exch /ps2write eq or{ + .where + } { + .where pop dup //systemdict eq { pop false } { true } ifelse + } ifelse +} bind +{ /currentdistillerparams /setdistillerparams /pdfmark } +{ .wheredict exch 2 index put } forall pop + +% Patch 'known' to hide the systemdict version of distiller operators +% unless the currentdevice is pdfwrite. +/known { + /currentdistillerparams 1 index eq /setdistillerparams 2 index eq or + /pdfmark 2 index eq or { + systemdict 2 index eq { % only mask the operator in systemdict + known currentdevice .devicename dup /pdfwrite ne exch /ps2write ne and { pop false } if + } { + known + } ifelse + } { + known + } ifelse +} .bind odef + +% Create a table for translation DSC comments into Unicode UTF-16 +/.make_DSC_translation_table { % <encoding> .make_DSC_translation_table <array> + dup type /stringtype eq { + cvn + } if + dup type /nametype eq { + /Encoding findresource + } if + dup length array exch % [out] [in] + 0 1 2 index length 1 sub { % [out] [in] i + dup 2 index exch get % [out] [in] i n + dup dup null eq exch /.notdef eq or { + pop -1 + } { + dup //AdobeGlyphList exch .knownget { % [out] [in] i n c + dup type dup /arraytype eq exch /packedarraytype eq or { + 0 get % fixme: using the 1st char + } if + exch pop % [out] [in] i c + } { % [out] [in] i n + (DSCEncoding defines a character that is not in AdobeGlyphList : ) + exch .namestring concatstrings = + /.make_DSC_translation_table cvx /undefined signalerror + } ifelse + } ifelse + 3 index % [out] [in] i c [out] + 3 1 roll put % [out] [in] + } for + pop % [out] +} bind def + +1000 % priority +{ + % Note, this may not work if the initial device is not pdfwrite + % and may require the use of -dProvideUnicode on the command line. + currentdevice .devicename /pdfwrite eq + systemdict /ProvideUnicode .knownget not { false } if or { + currentglobal true setglobal + systemdict /.setupUnicodeDecoder known { + /Unicode /Decoding resourcestatus { + pop pop + /Unicode /Decoding findresource + .setupUnicodeDecoder + } { + QUIET not { + (WARNING: /Unicode /Decoding resource is not accessible but it is useful for generating ToUnicode CMap.) = + } if + } ifelse + } if + setglobal + } if +} bind .schedule_init + +1010 % priority +{ + % Set a predefined configuration in the distiller device (pdfwrite) + /PDFSETTINGS where { + pop /PDFSETTINGS load + } { + currentdevice .devicename /ps2write eq { /PSL2Printer } { /default } ifelse + } ifelse + .distillersettings exch get + % Don't override parameters defined on the command line. + dup length .distillercommon length add dict begin + .distillercommon 2 { + { + systemdict 2 index known { pop pop } { def } ifelse + } forall + } repeat + currentdevice .devicename /pdfwrite eq { + systemdict /PDFX known systemdict /PDFA known or { + /DSCEncoding where { + /DSCEncoding get .make_DSC_translation_table + /DSCEncodingToUnicode exch def + } if + } if + } if + currentdict end .setdistillerparams + .distillerdevice //null false mark .putdeviceparams + dup type /booleantype eq not { cleartomark pop } if pop pop +} bind .schedule_init + +% Set a path to library files (ps2write) +.defaultdevicename /ps2write eq { + mark + /OPDFReadProcsetPath + systemdict /OPDFReadProcsetPath .knownget dup { % check for a value on the command-line + 1 index () eq { + (Configuration warning : empty OPDFReadProcsetPath, will use defaults.) = + systemdict /OPDFReadProcsetPath undef + pop pop false + } if + } if + not { % if necessary, compute a default + mark + (gs_mgl_e.ps) (gs_mro_e.ps) (gs_agl.ps) (opdfread.ps) % Reverse order ! + () counttomark 1 sub { + exch + .libfile { .filename } { false } ifelse not { + (Configuration error : library file opdfread.ps not found !) = + (opdfread.ps) /undefinedfilename signalerror + } if + .filenamelistseparator concatstrings concatstrings + } repeat + exch pop + } if + %stack: mark /OPDFReadProcsetPath <filelist> + /ps2write finddevice putdeviceprops pop % set the default instance's procset path +} if + +2000 % priority +{ % Note, this may not work if the initial device is not pdfwrite + currentdevice .devicename dup /pdfwrite eq exch /ps2write eq or { + % Inform the device with initial graphic state. See gdev_pdf_fill_path. + newpath fill + } if +} bind .schedule_init diff --git a/gs/Resource/Init/gs_res.ps b/gs/Resource/Init/gs_res.ps new file mode 100644 index 000000000..bdae7b979 --- /dev/null +++ b/gs/Resource/Init/gs_res.ps @@ -0,0 +1,1118 @@ +% Copyright (C) 1994, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for Level 2 resource machinery. +% When this is run, systemdict is still writable, +% but (almost) everything defined here goes into level2dict. + +level2dict begin + +(BEGIN RESOURCES) VMDEBUG + +% We keep track of (global) instances with another entry in the resource +% dictionary, an .Instances dictionary. For categories with implicit +% instances, the values in .Instances are the same as the keys; +% for other categories, the values are [instance status size]. + +% Note that the dictionary that defines a resource category is stored +% in global VM. The PostScript manual says that each category must +% manage global and local instances separately. However, objects in +% global VM other than systemdict can't reference objects in local VM. +% This means that the resource category dictionary, which would otherwise be +% the obvious place to keep track of the instances, can't be used to keep +% track of local instances. Instead, we define a dictionary in local VM +% called localinstancedict, in which the key is the category name and +% the value is the analogue of .Instances for local instances. + +% We don't currently implement automatic resource unloading. +% When and if we do, it should be hooked to the garbage collector. +% However, Ed Taft of Adobe says their interpreters don't implement this +% either, so we aren't going to worry about it for a while. + +currentglobal false setglobal systemdict begin + /localinstancedict 5 dict + .forcedef % localinstancedict is local, systemdict is global +end true setglobal +/.emptydict 0 dict readonly def +setglobal + +% Resource category dictionaries have the following keys (those marked with +% * are optional): +% Standard, defined in the Red Book: +% Category (name) +% *InstanceType (name) +% DefineResource +% <key> <instance> DefineResource <instance> +% UndefineResource +% <key> UndefineResource - +% FindResource +% <key> FindResource <instance> +% ResourceStatus +% <key> ResourceStatus <status> <size> true +% <key> ResourceStatus false +% ResourceForAll +% <template> <proc> <scratch> ResourceForAll - +% *ResourceFileName +% <key> <scratch> ResourceFileName <filename> +% Additional, specific to our implementation: +% .Instances (dictionary) +% .LocalInstances +% - .LocalInstances <dict> +% .GetInstance +% <key> .GetInstance <instance> -true- +% <key> .GetInstance -false- +% .CheckResource +% <key> <value> .CheckResource <key> <value> <ok> +% (or may give an error if not OK) +% .DoLoadResource +% <key> .DoLoadResource <key> (may give an error) +% .LoadResource +% <key> .LoadResource - (may give an error) +% .ResourceFile +% <key> .ResourceFile <file> -true- +% <key> .ResourceFile <key> -false- +% .ResourceFileStatus +% <key> .ResourceFileStatus 2 <vmusage> -true- +% <key> .ResourceFileStatus -false- +% All the above procedures expect that the top dictionary on the d-stack +% is the resource dictionary. + +% Define enough of the Category category so we can define other categories. +% The dictionary we're about to create will become the Category +% category definition dictionary. + +% .findcategory and .resourceexec are only called from within the +% implementation of the resource 'operators', so they don't have to worry +% about cleaning up the stack if they fail (the interpreter's stack +% protection machinery for pseudo-operators takes care of this). +% Note that all places that look up categories must use .findcategory +% so that the command in case of error will be correct rather than an +% internal invocation of findresource. +/.findcategory { % <name> .findcategory - + % (pushes the category on the dstack) + /Category .findresource begin % note: *not* findresource +} bind def + +% If an error occurs within the logic of a resource operator (after operand +% acquisition and checking), the Adobe interpreters report the operator name, +% not the operator object, as the command in $error. For this reason, and +% this reason only, all resource operators must wrap their logic code in +% /<opername> cvx { ...logic... } .errorexec + +% The Category resource signals /undefined rather than /undefinedresource, +% both when referenced implicitly (to look up the category for a general +% resource operation) and when it is accessed directly (/Category /xxx +% findresource). Because of this, all resource operators must use +% .undefinedresource rather than signalling undefinedresource directly. +/.undefinedresource { % <command> .undefinedresource - + /Category dup load eq { /undefined } { /undefinedresource } ifelse + signaloperror +} bind def + +/.resourceexec { % <key> /xxxResource .resourceexec - + % (also pops the category from the dstack) + load exec end +} bind def + +% .getvminstance treats instances on disk as undefined. +/.getvminstance { % <key> .getvminstance <instance> -true- + % <key> .getvminstance -false- + .GetInstance { + dup 1 get 2 ne { true } { pop false } ifelse + } { + false + } ifelse +} bind def + +20 dict begin + + % Standard entries + +/Category /Category def +/InstanceType /dicttype def + +/DefineResource { + .CheckResource { + dup /Category 3 index cvlit .growput + dup [ exch 0 -1 ] exch + .Instances 4 2 roll put + % Make the Category dictionary read-only. We will have to + % use .forceput / .forcedef later to replace the dummy, + % empty .Instances dictionary with the real one later. + readonly + } { + /defineresource cvx /typecheck signaloperror + } ifelse +} bind def +/FindResource % (redefined below) + { .Instances exch get 0 get + } bind def + + % Additional entries + +/.Instances 30 dict def +.Instances /Category [currentdict 0 -1] put + +/.LocalInstances 0 dict def +/.GetInstance + { .Instances exch .knownget + } bind def +/.CheckResource + { dup gcheck currentglobal and + { /DefineResource /FindResource /ResourceForAll /ResourceStatus + /UndefineResource } + { 2 index exch known and } + forall + not { /defineresource cvx /invalidaccess signaloperror } if + true + } bind def + +.Instances end begin % for the base case of findresource + +(END CATEGORY) VMDEBUG + +% Define the resource operators. We use the "stack protection" feature of +% odef to make sure the stacks are restored properly on an error. +% This requires that the operators not pop anything from the stack until +% they have executed their logic successfully. We can't make this +% work for resourceforall, because the procedure it executes mustn't see +% the operands of resourceforall on the stack, but we can make it work for +% the others. + +% findresource is the only operator that needs to bind //Category. +% We define its contents as a separate procedure so that .findcategory +% can use it without entering another level of pseudo-operator. +/.findresource { % <key> <category> findresource <instance> + 2 copy dup /Category eq + { pop //Category 0 get begin } { .findcategory } ifelse + /FindResource .resourceexec exch pop exch pop +} bind +end % .Instances of Category +def +/findresource { + % See above re .errorexec. + 1 .argindex % also catch stackunderflow + dup type /stringtype eq { cvn } if % for CET 23-13-04 + 3 1 roll exch pop + dup type /nametype ne { + /findresource .systemvar /typecheck signalerror + } if + /findresource cvx //.findresource .errorexec +} odef + +/defineresource { % <key> <instance> <category> defineresource <instance> + 2 .argindex 2 index 2 index % catch stackunderflow + % See above re .errorexec. + /defineresource cvx { + .findcategory + currentdict /InstanceType known { + dup type InstanceType ne { + dup type /packedarraytype eq InstanceType /arraytype eq and + not { /defineresource cvx /typecheck signaloperror } if + } if + } if + /DefineResource .resourceexec + 4 1 roll pop pop pop + } .errorexec +} bind odef +% We must prevent resourceforall from automatically restoring the stacks, +% because we don't want the stacks restored if proc causes an error or +% executes a 'stop'. On the other hand, resourceforall is defined in the +% PLRM as an operator, so it must have type /operatortype. We hack this +% by taking advantage of the fact that the interpreter optimizes tail +% calls, so stack protection doesn't apply to the very last token of an +% operator procedure. +/resourceforall1 { % <template> <proc> <scratch> <category> resourceforall1 - + dup .findcategory + /ResourceForAll load + % Stack: <template> <proc> <scratch> <category> proc + exch pop % pop the category + exec end +} bind def +/resourceforall { % <template> <proc> <scratch> <category> resourceforall1 - + //resourceforall1 exec % see above +} bind odef +/resourcestatus { % <key> <category> resourcestatus <status> <size> true + % <key> <category> resourcestatus false + { + 0 .argindex type /nametype ne { + % CET 23-26 wants typecheck here, not undefineresource that happens + % without the check. + /resourcestatus cvx /typecheck signalerror + } if + 2 copy .findcategory /ResourceStatus .resourceexec + { 4 2 roll pop pop true } { pop pop false } ifelse + } stopped { + % Although resourcestatus is an operator, Adobe uses executable name + % for error reporting. CET 23-26 + /resourcestatus cvx $error /errorname get signalerror + } if +} bind odef +/undefineresource { % <key> <category> undefineresource - + 0 .argindex type /nametype ne { + /undefinedresource cvx /typecheck signaloperror + } if + 1 .argindex 1 index % catch stackunderflow + + { .findcategory /UndefineResource .resourceexec pop pop + } stopped { + % Although undefineresource is an operator, Adobe uses executable name + % here but uses operator for the errors above. CET 23-33 + /undefineresource cvx $error /errorname get signalerror + } if +} bind odef + +% Define the system parameters used for the Generic implementation of +% ResourceFileName. +systemdict begin + +% - .default_resource_dir <string> +/.default_resource_dir { + /LIBPATH .systemvar { + dup .file_name_current eq { + pop + } { + (Resource) search { + exch concatstrings + exch 0 1 getinterval concatstrings exit + } { + pop + } ifelse + } ifelse + } forall +} bind def + +% <path> <name> <string> .resource_dir_name <path> <name> <string> +/.resource_dir_name +{ systemdict 2 index .knownget { + exch pop + systemdict 1 index undef + } { + dup () ne { + .file_name_directory_separator concatstrings + } if + 2 index exch false .file_name_combine not { + (Error: .default_resource_dir returned ) print exch print ( that can't combine with ) print = + /.default_resource_dir cvx /configurationerror signalerror + } if + } ifelse +} bind def + +currentdict /pssystemparams known not { + /pssystemparams 10 dict readonly def +} if +pssystemparams begin + .default_resource_dir + /FontResourceDir (Font) .resource_dir_name + readonly .forcedef % pssys'params is r-o + /GenericResourceDir () .resource_dir_name + readonly .forcedef % pssys'params is r-o + pop % .default_resource_dir + /GenericResourcePathSep + .file_name_separator readonly .forcedef % pssys'params is r-o + (%diskFontResourceDir) cvn (/Resource/Font/) readonly .forcedef % pssys'params is r-o + (%diskGenericResourceDir) cvn (/Resource/) readonly .forcedef % pssys'params is r-o +end +end + +% Check if GenericResourceDir presents in LIBPATH. + +% The value of GenericResourceDir must end with directory separator. +% We use .file_name_combine to check it. +% Comments use OpenVMS syntax, because it is the most complicated case. +(x) pssystemparams /GenericResourcePathSep get +(y) concatstrings concatstrings dup length % (x]y) l1 +pssystemparams /GenericResourceDir get dup length exch % (x]y) l1 l2 (dir) +3 index true .file_name_combine not { + exch + (File name ) print print ( cant combine with ) print = + /GenericResourceDir cvx /configurationerror signaloperror +} if +dup length % (x]y) l1 l2 (dir.x]y) l +4 2 roll add % (x]y) (dir.x]y) l ll +ne { + (GenericResourceDir value does not end with directory separator.\n) = + /GenericResourceDir cvx /configurationerror signaloperror +} if +pop pop + +% Define the generic algorithm for computing resource file names. +/.rfnstring 8192 string def +/.genericrfn % <key> <scratch> <prefix> .genericrfn <filename> + { 3 -1 roll //.rfnstring cvs concatstrings exch copy + } bind def + +% Define the Generic category. + +/Generic mark + + % Standard entries + +% We're still running in Level 1 mode, so dictionaries won't expand. +% Leave room for the /Category entry. +/Category null + +% Implement the body of Generic resourceforall for local, global, and +% external cases. 'args' is [template proc scratch resdict]. +/.enumerateresource { % <key> [- <proc> <scratch>] .enumerateresource - + 1 index type dup /stringtype eq exch /nametype eq or { + exch 1 index 2 get cvs exch + } if + % Use .setstackprotect to prevent the stacks from being restored if + % an error occurs during execution of proc. + 1 get false .setstackprotect exec true .setstackprotect +} bind def +/.localresourceforall { % <key> <value> <args> .localr'forall - + exch pop + 2 copy 0 get .stringmatch { .enumerateresource } { pop pop } ifelse +} bind def +/.globalresourceforall { % <key> <value> <args> .globalr'forall - + exch pop + 2 copy 0 get .stringmatch { + dup 3 get begin .LocalInstances end 2 index known not { + .enumerateresource + } { + pop pop + } ifelse + } { + pop pop + } ifelse +} bind def +/.externalresourceforall { % <filename> <len> <args> .externalr'forall - + 3 1 roll 1 index length 1 index sub getinterval exch + dup 3 get begin .Instances .LocalInstances end + % Stack: key args insts localinsts + 3 index known { + pop pop pop + } { + 2 index known { pop pop } { .enumerateresource } ifelse + } ifelse +} bind def + +/DefineResource { + .CheckResource + { dup [ exch 0 -1 ] + % Stack: key value instance + currentglobal + { false setglobal 2 index UndefineResource % remove local def if any + true setglobal + .Instances dup //.emptydict eq { + pop 3 dict + % As noted above, Category dictionaries are read-only, + % so we have to use .forcedef here. + /.Instances 1 index .forcedef % Category dict is read-only + } if + } + { .LocalInstances dup //.emptydict eq + { pop 3 dict localinstancedict Category 2 index put + } + if + } + ifelse + % Stack: key value instance instancedict + 3 index 2 index .growput + % Now make the resource value read-only. + 0 2 copy get { readonly } .internalstopped pop + dup 4 1 roll put exch pop exch pop + } + { /defineresource cvx /typecheck signaloperror + } + ifelse +} .bind executeonly % executeonly to prevent access to .forcedef +/UndefineResource + { { dup 2 index .knownget + { dup 1 get 1 ge + { dup 0 null put 1 2 put pop pop } + { pop exch .undef } + ifelse + } + { pop pop + } + ifelse + } + currentglobal + { 2 copy .Instances exch exec + } + if .LocalInstances exch exec + } bind +% Because of some badly designed code in Adobe's CID font downloader that +% makes findresource and resourcestatus deliberately inconsistent with each +% other, the default FindResource must not call ResourceStatus if there is +% an instance of the desired name already defined in VM. +/FindResource { + dup //null eq { + % CET 13-06 wants /typecheck for "null findencoding" but + % .knownget doesn't fail on null + /findresource cvx /typecheck signaloperror + } if + dup .getvminstance { + exch pop 0 get + } { + dup ResourceStatus { + pop 1 gt { + .DoLoadResource .getvminstance not { + /findresource cvx .undefinedresource + } if 0 get + } { + .GetInstance pop 0 get + } ifelse + } { + /findresource cvx .undefinedresource + } ifelse + } ifelse +} bind +% Because of some badly designed code in Adobe's CID font downloader, the +% definition of ResourceStatus for Generic and Font must be the same (!). +% We patch around this by using an intermediate .ResourceFileStatus procedure. +/ResourceStatus { + dup .GetInstance { + exch pop dup 1 get exch 2 get true + } { + .ResourceFileStatus + } ifelse +} bind +/.ResourceFileStatus { + .ResourceFile { closefile 2 -1 true } { pop false } ifelse +} bind +/ResourceForAll { + % Construct a new procedure to hold the arguments. + % All objects constructed here must be in local VM to avoid + % a possible invalidaccess. + currentdict 4 .localvmpackedarray % [template proc scratch resdict] + % We must pop the resource dictionary off the dict stack + % when doing the actual iteration, and restore it afterwards. + .currentglobal not { + .LocalInstances length 0 ne { + % We must do local instances, and do them first. + //.localresourceforall {exec} 0 get 3 .localvmpackedarray cvx + .LocalInstances exch {forall} 0 get 1 index 0 get + currentdict end 3 .execn begin + } if + } if + % Do global instances next. + //.globalresourceforall {exec} 0 get 3 .localvmpackedarray cvx + .Instances exch cvx {forall} 0 get 1 index 0 get + currentdict end 3 .execn begin + mark % args [ + Category .namestring .file_name_separator concatstrings + 2 index 0 get % args [ (c/) (t) + dup length 3 1 roll % args [ l (c/) (t) + concatstrings % args [ l (c/t) + [ + true /LIBPATH .systemvar 3 index + .generate_dir_list_templates_with_length % args (t) [ l [(pt) Lp ...] + % also add on the Resources as specified by the GenericResourceDir + true [ currentsystemparams /GenericResourceDir get] + counttomark 1 add index .generate_dir_list_templates_with_length + % Resource files on OpenVMS require a separate template (gs:[dir.*]*) + true [ currentsystemparams /GenericResourceDir get] + counttomark 1 add index .file_name_separator (*) + concatstrings concatstrings .generate_dir_list_templates_with_length + ] exch pop + dup length 1 sub 0 exch 2 exch { % args [ l [] i + 2 copy get % args [ l [] i (pt) + exch 2 index exch 1 add get % args [ l [] (pt) Lp + exch % args [ l [] Lp (pt) + + { % args [ l [] Lp (pf) + dup length % args [ l [] Lp (pf) Lpf + 2 index sub % args [ l [] Lp (pf) Lf + 2 index exch % args [ l [] Lp (pf) Lp Lf + getinterval cvn dup % args [ l [] Lp /n /n + 5 2 roll % args [ /n /n l [] Lp + } //.rfnstring filenameforall + pop % args [ /n1 /n1 ... /nN /nN l [] + } for % args [ /n1 /n1 ... /nN /nN l [] + pop pop + .dicttomark % An easy way to exclude duplicates. % args <</n/n>> + % { + { pop } 0 get + 2 index 2 get { cvs 0 } aload pop 5 index + //.externalresourceforall {exec} 0 get + % } + 7 .localvmpackedarray cvx + 3 2 roll pop % args + { forall } 0 get + currentdict end 2 .execn begin +} bind +/.file_name_is_iodevice_or_absolute +{ { + dup length 0 gt { + dup 0 get (%) 0 get eq { + pop true exit + } if + } if + .file_name_is_absolute exit + } loop +} bind def +/ResourceFileName + { % /in (scr) + exch //.rfnstring cvs % (scr) (n) + /GenericResourcePathSep getsystemparam exch % (scr) (/) (n) + Category .namestring % (scr) (/) (n) (c) + 3 1 roll % (scr) (c) (/) (n) + concatstrings concatstrings % (scr) (c/n) + /GenericResourceDir getsystemparam //.file_name_is_iodevice_or_absolute exec not { + /GenericResourceDir getsystemparam exch concatstrings + findlibfile + { % (scr) (p/c/n) file + pop exch copy true % (p/c/n) true + } { % (scr) (c/n) + false % (scr) (c/n) false + } ifelse + } { % (scr) (c/n) + false % (scr) (c/n) false + } ifelse + not { % (scr) (c/n) + /GenericResourceDir getsystemparam % (scr) (c/n) (d/) + dup length exch % (scr) (c/n) Ld (d/) + 3 index copy pop % (scr') (c/n) Ld + 1 index length % (scr') (c/n) Ld Lcn + 3 index 3 copy pop % (scr') (c/n) Ld Lcn (scr') Ld Lcn + getinterval % (scr') (c/n) Ld Lcn (scr[Ld:Lcn]) + 4 3 roll exch % (scr') Ld Lcn (c/n) (scr[Ld:Lcn]) + copy pop % (scr'') Ld Lcn + add 0 exch getinterval % (scr''[0:Ld+Lcn]) + } if + } bind + + % Additional entries + +% Unfortunately, we can't create the real .Instances dictionary now, +% because if someone copies the Generic category (which pp. 95-96 of the +% 2nd Edition Red Book says is legitimate), they'll wind up sharing +% the .Instances. Instead, we have to create .Instances on demand, +% just like the entry in localinstancedict. +% We also have to prevent anyone from creating instances of Generic itself. +/.Instances //.emptydict + +/.LocalInstances + { localinstancedict Category .knownget not { //.emptydict } if + } bind +/.GetInstance + { currentglobal + { .Instances exch .knownget } + { .LocalInstances 1 index .knownget + { exch pop true } + { .Instances exch .knownget } + ifelse + } + ifelse + } bind +/.CheckResource + { true + } bind +/.vmused { + % - .vmused <usedvalue> + % usedvalue = vmstatus in global + vmstatus in local. + 0 2 { + .currentglobal not .setglobal + vmstatus pop exch pop add + } repeat +} bind def +/.DoLoadResource { + % .LoadResource may push entries on the operand stack. + % It is an undocumented feature of Adobe implementations, + % which we must match for the sake of some badly written + % font downloading code, that such entries are popped + % automatically. + count 1 index cvlit .vmused + % Stack: key count litkey memused + {.LoadResource} 4 1 roll 4 .execn + % Stack: ... count key memused + .vmused exch sub + 1 index .getvminstance not { + pop dup .undefinedresource % didn't load + } if + dup 1 1 put + 2 3 -1 roll put + % Stack: ... count key + exch count 1 sub exch sub {exch pop} repeat +} bind +/.LoadResource + { dup .ResourceFile + { exch pop currentglobal + { .runresource } + { true setglobal { .runresource } stopped false setglobal { stop } if } + ifelse + } + { dup .undefinedresource + } + ifelse + } bind +/.ResourceFile + { + Category //.rfnstring cvs length % key l + dup //.rfnstring dup length 2 index sub % key l l (buf) L-l + 3 2 roll exch getinterval % key l () + .file_name_directory_separator exch copy length add % key l1 + dup //.rfnstring dup length 2 index sub % key l1 l1 (buf) L-l + 3 2 roll exch getinterval % key l1 () + 2 index exch cvs length add % key l2 + //.rfnstring exch 0 exch getinterval % key (relative_path) + .libfile { + exch pop true + } { + pop + currentdict /ResourceFileName known { + mark 1 index //.rfnstring { ResourceFileName } .internalstopped { + cleartomark false + } { + (r) { file } .internalstopped { + cleartomark false + } { + exch pop exch pop true + } ifelse + } ifelse + } { + pop false + } ifelse + } ifelse + } bind + + + +.dicttomark +/Category defineresource pop + +% Fill in the rest of the Category category. +/Category /Category findresource dup +/Generic /Category findresource begin { + /FindResource /ResourceForAll /ResourceStatus /.ResourceFileStatus + /UndefineResource /ResourceFileName + /.ResourceFile /.LoadResource /.DoLoadResource +} { dup load put dup } forall +pop readonly pop end + +(END GENERIC) VMDEBUG + +% Define the fixed categories. + +mark + % Non-Type categories with existing entries. + /ColorSpaceFamily + { } % These must be deferred, because optional features may add some. + /Emulator + mark EMULATORS { cvn } forall .packtomark + /Filter + { } % These must be deferred, because optional features may add some. + /IODevice + % Loop until the .getiodevice gets a rangecheck. + errordict /rangecheck 2 copy get + errordict /rangecheck { pop stop } put % pop the command + mark 0 { { + dup .getiodevice dup null eq { pop } { exch } ifelse 1 add + } loop} .internalstopped + pop pop pop .packtomark + 4 1 roll put + .clearerror + % Type categories listed in the Red Book. + /ColorRenderingType + { } % These must be deferred, because optional features may add some. + /FMapType + { } % These must be deferred, because optional features may add some. + /FontType + { } % These must be deferred, because optional features may add some. + /FormType + { } % These must be deferred, because optional features may add some. + /HalftoneType + { } % These must be deferred, because optional features may add some. + /ImageType + { } % Deferred, optional features may add some. + /PatternType + { } % Deferred, optional features may add some. + % Type categories added since the Red Book. + /setsmoothness where { + pop /ShadingType { } % Deferred, optional features may add some. + } if +counttomark 2 idiv + { mark + + % Standard entries + + % We'd like to prohibit defineresource, + % but because optional features may add entries, we can't. + % We can at least require that the key and value match. + /DefineResource + { currentglobal not + { /defineresource cvx /invalidaccess signaloperror } + { 2 copy ne + { /defineresource cvx /rangecheck signaloperror } + { dup .Instances 4 -2 roll .growput } + ifelse + } + ifelse + } bind + /UndefineResource + { /undefineresource cvx /invalidaccess signaloperror } bind + /FindResource + { .Instances 1 index .knownget + { exch pop } + { /findresource cvx .undefinedresource } + ifelse + } bind + /ResourceStatus + { .Instances exch known { 0 0 true } { false } ifelse } bind + /ResourceForAll + /Generic .findcategory /ResourceForAll load end + + % Additional entries + + counttomark 2 add -1 roll + dup length dict dup begin exch { dup def } forall end + % We'd like to make the .Instances readonly here, + % but because optional features may add entries, we can't. + /.Instances exch + /.LocalInstances % used by ResourceForAll + 0 dict def + + .dicttomark /Category defineresource pop + } repeat pop + +(END FIXED) VMDEBUG + +% Define the other built-in categories. + +/.definecategory % <name> -mark- <key1> ... <valuen> .definecategory - + { counttomark 2 idiv 2 add % .Instances, Category + /Generic /Category findresource dup maxlength 3 -1 roll add + dict .copydict begin + counttomark 2 idiv { def } repeat pop % pop the mark + currentdict end /Category defineresource pop + } bind def + +/ColorRendering mark /InstanceType /dicttype .definecategory +% ColorSpace is defined below +% Encoding is defined below +% Font is defined below +/Form mark /InstanceType /dicttype .definecategory +/Halftone mark /InstanceType /dicttype .definecategory +/Pattern mark /InstanceType /dicttype .definecategory +/ProcSet mark /InstanceType /dicttype .definecategory +% Added since the Red Book: +/ControlLanguage mark /InstanceType /dicttype .definecategory +/HWOptions mark /InstanceType /dicttype .definecategory +/Localization mark /InstanceType /dicttype .definecategory +/OutputDevice mark /InstanceType /dicttype .definecategory +/PDL mark /InstanceType /dicttype .definecategory +% CIDFont, CIDMap, and CMap are defined in gs_cidfn.ps +% FontSet is defined in gs_cff.ps +% IdiomSet is defined in gs_ll3.ps +% InkParams and TrapParams are defined in gs_trap.ps + +(END MISC) VMDEBUG + +% Define the ColorSpace category. + +/.defaultcsnames mark + /DefaultGray 0 + /DefaultRGB 1 + /DefaultCMYK 2 +.dicttomark readonly def + +% The "hooks" are no-ops here, redefined in LL3. +/.definedefaultcs { % <index> <value> .definedefaultcs - + pop pop +} bind def +/.undefinedefaultcs { % <index> .undefinedefaultcs - + pop +} bind def + +/ColorSpace mark + +/InstanceType /arraytype + +% We keep track of whether there are any local definitions for any of +% the Default keys. This information must get saved and restored in +% parallel with the local instance dictionary, so it must be stored in +% local VM. +userdict /.localcsdefaults false put + +/DefineResource { + 2 copy /Generic /Category findresource /DefineResource get exec + exch pop + exch //.defaultcsnames exch .knownget { + 1 index .definedefaultcs + currentglobal not { .userdict /.localcsdefaults true put } if + } if +} bind + +/UndefineResource { + dup /Generic /Category findresource /UndefineResource get exec + //.defaultcsnames 1 index .knownget { + % Stack: resname index + currentglobal { + .undefinedefaultcs pop + } { + % We removed the local definition, but there might be a global one. + exch .GetInstance { + 0 get .definedefaultcs + } { + .undefinedefaultcs + } ifelse + % Recompute .localcsdefaults by scanning. This is rarely needed. + .userdict /.localcsdefaults false //.defaultcsnames { + pop .LocalInstances exch known { pop true exit } if + } forall put + } ifelse + } { + pop + } ifelse +} bind + +.definecategory % ColorSpace + +% Define the Encoding category. + +/Encoding mark + +/InstanceType /arraytype + +% Handle already-registered encodings, including lazily loaded encodings +% that aren't loaded yet. + +/.Instances mark + EncodingDirectory + { dup length 256 eq { [ exch readonly 0 -1 ] } { pop [null 2 -1] } ifelse + } forall +.dicttomark + +/.ResourceFileDict mark + EncodingDirectory + { dup length 256 eq { pop pop } { 0 get } ifelse + } forall +.dicttomark + +/ResourceFileName + { .ResourceFileDict 2 index .knownget + { exch copy exch pop } + { /Generic /Category findresource /ResourceFileName get exec } + ifelse + } bind + +.definecategory % Encoding + +% Make placeholders in level2dict for the redefined Encoding operators, +% so that they will be swapped properly when we switch language levels. + +/.findencoding /.findencoding load def +/findencoding /findencoding load def +/.defineencoding /.defineencoding load def + +(END ENCODING) VMDEBUG + +% Define the Font category. + +/.fontstatus { % <fontname> .fontstatus <fontname> <found> + { % Create a loop context just so we can exit it early. + % Check Fontmap. + Fontmap 1 index .knownget { + { + dup type /nametype eq { + .fontstatus { pop null exit } if + } { + dup type /stringtype eq { + findlibfile { closefile pop null exit } if pop + } { + % Procedure, assume success. + pop null exit + } ifelse + } ifelse + } forall dup null eq { pop true exit } if + } if + % Convert names to strings; give up on other types. + dup type /nametype eq { .namestring } if + dup type /stringtype ne { false exit } if + % Check the resource directory. + dup .fonttempstring /FontResourceDir getsystemparam .genericrfn + status { + pop pop pop pop true exit + } if + % Check for a file on the search path with the same name + % as the font. + findlibfile { closefile true exit } if + % Scan a FONTPATH directory and try again. + .scannextfontdir not { false exit } if + } loop +} bind def + +/Font mark + +/InstanceType /dicttype + +/DefineResource + { 2 copy //definefont exch pop + /Generic /Category findresource /DefineResource get exec + } bind +/UndefineResource + { dup //undefinefont + /Generic /Category findresource /UndefineResource get exec + } bind +/FindResource { + dup .getvminstance { + exch pop 0 get + } { + dup ResourceStatus { + pop 1 gt { .loadfontresource } { .GetInstance pop 0 get } ifelse + } { + .loadfontresource + } ifelse + } ifelse +} bind +/ResourceForAll { + { .scannextfontdir not { exit } if } loop + /Generic /Category findresource /ResourceForAll get exec +} bind +/.ResourceFileStatus { + .fontstatus { pop 2 -1 true } { pop false } ifelse +} bind + +/.loadfontresource { + dup vmstatus pop exch pop exch + % Hack: rebind .currentresourcefile so that all calls of + % definefont will know these are built-in fonts. + currentfile {pop //findfont exec} .execasresource % (findfont is a procedure) + exch vmstatus pop exch pop exch sub + % stack: name font vmused + % findfont has the prerogative of not calling definefont + % in certain obscure cases of font substitution. + 2 index .getvminstance { + dup 1 1 put + 2 3 -1 roll put + } { + pop + } ifelse exch pop +} bind + +/.Instances FontDirectory length 2 mul dict + +.definecategory % Font + +% Redefine font "operators". +/.definefontmap + { /Font /Category findresource /.Instances get + dup 3 index known + { pop + } + { 2 index + % Make sure we create the array in global VM. + .currentglobal true .setglobal + [null 2 -1] exch .setglobal + .growput + } + ifelse + //.definefontmap exec + } bind def + +% Make sure the old definitions are still in systemdict so that +% they will get bound properly. +systemdict begin + /.origdefinefont /definefont load def + /.origundefinefont /undefinefont load def + /.origfindfont /findfont load def +end +/definefont { + { /Font defineresource } stopped { + /definefont cvx $error /errorname get signalerror + } if +} bind odef +/undefinefont { + /Font undefineresource +} bind odef +% The Red Book requires that findfont be a procedure, not an operator, +% but it still needs to restore the stacks reliably if it fails. +/.findfontop { + { /Font findresource } stopped { + pop /findfont $error /errorname get signalerror + } if +} bind odef +/findfont { + .findfontop +} bind def % Must be a procedure, not an operator + +% Remove initialization utilities. +currentdict /.definecategory .undef +currentdict /.emptydict .undef + +end % level2dict + +% Convert deferred resources after we finally switch to Level 2. + +/.fixresources { + % Encoding resources + EncodingDirectory + { dup length 256 eq + { /Encoding defineresource pop } + { pop pop } + ifelse + } forall + /.findencoding { + { /Encoding findresource } stopped { + pop /findencoding $error /errorname get signalerror + } if + } bind def + /findencoding /.findencoding load def % must be a procedure + /.defineencoding { /Encoding defineresource pop } bind def + % ColorRendering resources and ProcSet + systemdict /ColorRendering .knownget { + /ColorRendering exch /ProcSet defineresource pop + systemdict /ColorRendering undef + /DefaultColorRendering currentcolorrendering /ColorRendering defineresource pop + } if + % ColorSpace resources + systemdict /CIEsRGB .knownget { + /sRGB exch /ColorSpace defineresource pop + systemdict /CIEsRGB undef + } if + % ColorSpaceFamily resources + colorspacedict { pop dup /ColorSpaceFamily defineresource pop } forall + % Filter resources + filterdict { pop dup /Filter defineresource pop } forall + % FontType and FMapType resources + buildfontdict { pop dup /FontType defineresource pop } forall + mark + buildfontdict 0 known { 2 3 4 5 6 7 8 } if + buildfontdict 9 known { 9 } if + counttomark { dup /FMapType defineresource pop } repeat pop + % FormType resources + .formtypes { pop dup /FormType defineresource pop } forall + % HalftoneType resources + .halftonetypes { pop dup /HalftoneType defineresource pop } forall + % ColorRenderingType resources + .colorrenderingtypes {pop dup /ColorRenderingType defineresource pop} forall + % ImageType resources + .imagetypes { pop dup /ImageType defineresource pop } forall + % PatternType resources + .patterntypes { pop dup /PatternType defineresource pop } forall + % Make the fixed resource categories immutable. + /.shadingtypes where { + pop .shadingtypes { pop dup /ShadingType defineresource pop } forall + } if + [ /ColorSpaceFamily /Emulator /Filter /IODevice /ColorRenderingType + /FMapType /FontType /FormType /HalftoneType /ImageType /PatternType + /.shadingtypes where { pop /ShadingType } if + ] { + /Category findresource + dup /.Instances get readonly pop + .LocalInstances readonly pop + readonly pop + } forall + % clean up + systemdict /.fixresources undef +} bind def + +%% Replace 1 (gs_resmp.ps) +(gs_resmp.ps) dup runlibfile VMDEBUG diff --git a/gs/Resource/Init/gs_resmp.ps b/gs/Resource/Init/gs_resmp.ps new file mode 100644 index 000000000..6da7a615f --- /dev/null +++ b/gs/Resource/Init/gs_resmp.ps @@ -0,0 +1,531 @@ +% Copyright (C) 2000 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% A procset to redefine a resource category with a resource map. + +% Public entries : + +% Redefine - a procedure for redefining a resource category with a map. +% Methods for interpreting the resource map to be provided by client +% in the argument dictionary. +% +% Note that the procedure Redefine is idempotential : +% consequtive calls to it will not replace the category methods, +% but will merge resource maps. If an interleaving redefinition +% needs to cancel the idempotentity, it must remove the entry +% /.IsRedefinedWithMap from the category dictionary. + +% MakeResourceEnumerator - this procedure is useful for +% redefining any category. It provides a proper order of instances +% and proper stacks during resourceforall. + +% BindWithCurrentdict - a procedure for generating temporary procedures +% from templates, binding them with a local dictionary. + +% execstack_lookup - a procedure for communicating through the execution stack. +% It allows for a callee to get an information from an indirect caller. + +% The procedures are designed for exeution witout putting +% the procset instance onto the dictionary stack. + +languagelevel 2 .setlanguagelevel +currentglobal true setglobal + +/MappedCategoryRedefiner 10 dict begin % The procset. + +currentpacking false setpacking + +/InstanceEnumeratorPattern % - InstanceEnumeratorPattern ... +{ + % This is a pattern for enumeration procedure to be built dynamically, + % applying BindWithCurrentdict with a temporary dictionary. + % The following names will be replaced with specific objects + % during BindWithCurrentdict : + % en_local_dict - a dictionary for storing the local integer variable 'status'. + % scr - the scratch string argument of resourceforall; + % proc - the procedure argument of resourceforall; + % InstancesStatus - a dictionary that maps resource instance names to their status value; + % Category - the category to be enumerated. + + % When this procedure is called from ResourceForAll, the category is the current dictionary. + % We remove it from the dictionary stack before performing the enumeration + % to provide the <proc> to write to the underlying dictionary, + % and put it back after the enumeration is completed. + end + { + 0 1 2 { + en_local_dict exch /status exch put + InstancesStatus { + en_local_dict /status get eq { + scr cvs % ... (Font) + proc exec % + } { + pop + } ifelse % ... + } forall + } for % ... + } stopped + Category begin + { stop } if +} bind def + +% An auxiliary proc for BindWithCurrentdict : +/.BindAux % <proc> BindAux <proc> +{ 0 exec +} bind def + +setpacking + +/BindWithCurrentdict % <proc> BindWithCurrentdict <proc> +{ + % Make a copy of the given procedure, binding in the values of all names + % defined in currentdict. + % Caution1 : this code cannot handle procedures that were already + % bound recursively. + % Caution2 : this code don't bind packedarrays. This was done + % intentionally for a termination of the procedure tree. + + dup length array copy + dup length 1 sub -1 0 { + 2 copy get % {precopy} i {elem} + dup dup type /arraytype eq exch xcheck and { + % {precopy} i {elem} + //.BindAux exec % {precopy} i {elem_copy} + 2 index 3 1 roll put % {precopy} + } { + dup dup type /nametype eq exch xcheck and { + % {precopy} i {elem} + currentdict exch .knownget { + 2 index 3 1 roll put % {precopy} + } { + pop + } ifelse + } { + pop pop + } ifelse + } ifelse % {precopy} + } for % {copy} + cvx +} bind def + +//.BindAux 0 //BindWithCurrentdict put % bind the recursive call in 'Bind'. + +/MakeResourceEnumerator % <proc> <scr> <InstancesStatus> MakeResourceEnumerator <Enumerator> +{ + % Build the enumeration procedure : + + % Since the resourceforall procedure may leave values on the operand stack, + % we cannot simply store the enumerator's local data on the stack. + % We also cannot use a static dictionary to store local variables, + % because of possible recursion in the resourceforall procedure. + % To work around this, we create a copy of the enumeration procedure and + % bind it dynamically with a temporary dictionary, which contains + % local variables for the currently executing instance of resourceforall. + + % Always place the enumerator in local VM, + % because its elements may be in local VM. + + currentglobal 4 1 roll + false setglobal + currentdict % Category + 6 dict begin % the temporary dictionary + /Category exch def + /InstancesStatus exch def + /scr exch def + /proc exch def + /en_local_dict currentdict def + //InstanceEnumeratorPattern //BindWithCurrentdict exec % Enumerator + /status 0 def % variable for the current status to enumerate - do not bind with it ! + end + exch setglobal +} bind def + +/execstack_lookup % <object> execstack_lookup <object1> + % <object> execstack_lookup null +{ % Checks whether execution stack contains a procedure starting with <object>, + % and retrives the 2nd element of the procedure, + % or null if the procedure was not found. + % + % Since 'execstack' actually renders subarrays of procedures, + % the pattern for recognition must be like this : + % + % { <object> <object1> + % CallSomething + % } loop + % + % The solution with 'loop' depends on how GS implements cycles, + % so it must not appear in documents, which are required to be interpreter independent. + % Any other type of cycles are also acceptable. + % If no repitition is really needed, just insert 'exit' into its body. + % If <object> <object1> are not needed for the caller, insert "pop pop" after them. + % If <object1> is really unuseful, the pattern may be simplified : + % + % { <object> pop + % CallSomething + % exit + % } loop + % + % It will retrieve 'pop' or 'null'. + % + % Note that 2 topmost execstack elements are the execstack_lookup procedure and its caller. + % We don't check them. + + currentglobal false setglobal % <object> bGlobal + countexecstack array execstack % <object> bGlobal [execstack] + dup null exch % <object> bGlobal [execstack] null [execstack] + length 3 sub -1 0 { % <object> bGlobal [execstack] null i + 2 index exch get % <object> bGlobal [execstack] null proc + dup type dup /packedarraytype eq exch /arraytype eq or { + dup rcheck { + dup length 1 gt { % <object> bGlobal [execstack] null proc + dup 0 get % <object> bGlobal [execstack] null proc elem0 + 5 index eq { % <object> bGlobal [execstack] null proc + 1 get % <object> bGlobal [execstack] null object1 + exch pop exit % <object> bGlobal [execstack] object1 + } { + pop + } ifelse + } { + pop % <object> bGlobal [execstack] false + } ifelse + } { + pop % <object> bGlobal [execstack] false + } ifelse + } { + pop % <object> bGlobal [execstack] false + } ifelse + } for % <object> bGlobal [execstack] bResult + exch pop exch setglobal exch pop % bResult +} bind def + +currentpacking false setpacking +/MethodsToRedefine 5 dict begin + + % Procedures in this dictionary really are patterns for new category methods. + % The following names will be replaced with specific objects during BindWithCurrentdict : + % .map - the map dictionary; + % DefineResource, ResourceStatus, ResourceFileName, FindResource, ResourceForAll + % - procedures from the original resource category. + + /FindResource % <Name> FindResource <dict> + { RESMPDEBUG { (resmp FindResource beg ) print dup = } if + dup ResourceStatus exec { + pop 2 lt + } { + false + } ifelse % bInVirtualMemory + { FindResource exec + } { + dup dup .map exch .knownget { % /Name /Name <<record>> + dup dup /RecordVirtualMethods get /IsActive get exec { + 1 index .getvminstance { % /Name /Name <<record>> holder + 1 get 1 eq + } { + true + } ifelse % /Name /Name <<record>> bStatusIs1 + 4 1 roll % bStatusIs1 /Name /Name <<record>> + dup /RecordVirtualMethods get /MakeInstance get exec + % bStatusIs1 /Name /Name Instance size + 5 1 roll % size bStatusIs1 /Name /Name Instance + DefineResource exec % size bStatusIs1 /Name Instance + % Make ResourceStatus to return correct values for this instance : + % Hack: we replace status values in the instance holder : + exch .getvminstance pop % size bStatusIs1 Instance holder + dup 5 -1 roll 2 exch put % bStatusIs1 Instance holder + 3 2 roll { % Instance holder + 1 1 put % Instance + } { + pop + } ifelse % Instance + } { % /Name /Name <<record>> + pop pop FindResource exec + } ifelse + } { % /Name /Name + pop FindResource exec + } ifelse + } ifelse + RESMPDEBUG { (resmp FindResource end) = } if + } bind def + + /ResourceStatus % <Name> ResourceStatus <status> <size> true + % <Name> ResourceStatus false + { RESMPDEBUG { (resmp ResourceStatus beg ) print dup == } if + dup ResourceStatus exec { % /Name status size + 1 index 2 lt { + % In VM - return with it. + 3 2 roll pop true + } { + % Not in VM. + exch pop exch % size /Name + dup .map exch .knownget { % size /Name <<record>> + dup dup /RecordVirtualMethods get /IsActive get exec { + 3 2 roll pop % /Name <<record>> + dup /RecordVirtualMethods get /GetSize get exec 2 exch true + } { % size /Name <<record>> + pop pop 2 exch true + } ifelse + } { % size /Name + pop 2 exch true + } ifelse + } ifelse + } { % /Name + dup .map exch .knownget { % /Name <<record>> + dup dup /RecordVirtualMethods get /IsActive get exec { + dup /RecordVirtualMethods get /GetSize get exec 2 exch true + } { % /Name <<record>> + pop pop false + } ifelse + } { % /Name + pop false + } ifelse + } ifelse + RESMPDEBUG { (resmp ResourceStatus end) = } if + } bind def + + /ResourceFileName % <Name> <scratch> ResourceFileName <string> + { RESMPDEBUG { (resmp ResourceFileName beg ) print 1 index = } if + exch % (scratch) /Name + .map 1 index .knownget { % (scratch) /Name <<record>> + RESMPDEBUG { (resmp ResourceFileName : have a map record.) = } if + dup dup /RecordVirtualMethods get /IsActive get exec { + RESMPDEBUG { (resmp ResourceFileName : record is active.) = } if + dup /RecordVirtualMethods get /GetFilePath get exec % (string) + RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if + } { % (scratch) /Name <<record>> + RESMPDEBUG { (resmp ResourceFileName : record is NOT active.) = } if + pop exch ResourceFileName exec + RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if + } ifelse + } { + RESMPDEBUG { (resmp ResourceFileName : have NO map record.) = } if + exch ResourceFileName exec + RESMPDEBUG { (resmp ResourceFileName : retrieving ) print dup = } if + } ifelse + RESMPDEBUG { (resmp ResourceFileName end) = } if + } bind def + + /ResourceForAll % <template> <proc> <scratch> ResourceForAll - + { RESMPDEBUG { (resmp ResourceForAll beg ) print CategoryName =string cvs print ( ) print 2 index = } if + % Create InstancesStatus dictionary : + 20 dict % IS - Instances Status + 4 1 roll % <<IS>> (templ) {proc} (sctarch) + % Check if we are under another ResourceForAll : + /.DisableResourceOrdering //execstack_lookup exec null eq 4 1 roll + % <<IS>> bOrder (templ) {proc} (sctarch) + + % Put underlying resources to the InstancesStatus dictionary : + currentdict % the category + begin % ResourceForAll removes it locally. + 2 index + { cvn % <<IS>> bOrder (templ) {proc} (sctarch) /Name + 4 index { + dup ResourceStatus exec {pop 6 index 3 1 roll put} {pop} ifelse + } { + 5 index exch 2 put % Don't need the ordering, put '2' as a scratch. + } ifelse + } + 2 index ResourceForAll exec % <<IS>> bOrder (templ) {proc} (sctarch) + 4 3 roll pop % <<IS>> (templ) {proc} (sctarch) + end + + % Put .map entries to the InstancesStatus dictionary : + 4 -1 roll begin % (templ) {proc} (sctarch) + .map { % (templ) {proc} (sctarch) /Name record + dup dup /RecordVirtualMethods get /IsActive get exec { + pop % (templ) {proc} (sctarch) /Name + dup currentdict exch known { + pop + } { + dup 2 index cvs % (templ) {proc} (sctarch) /Name (Name) + 4 index .stringmatch { % (templ) {proc} (sctarch) /Name + 2 def % It is not in VM. + } { + pop + } ifelse + } ifelse + } { % (templ) {proc} (sctarch) /Name record + pop pop + } ifelse + } forall % (templ) {proc} (sctarch) + + % prepare stacks for the enumeration : + 3 2 roll pop % {proc} (sctarch) + currentdict end % {proc} (scratch) <<IS>> + + % Make the enumerator and apply it : + //MakeResourceEnumerator exec exec + RESMPDEBUG { (resmp ResourceForAll end)= } if + } bind def + + /GetCIDSystemInfoFromMap % <Name> GetCIDSystemInfoFromMap <Name> + % <Name> GetCIDSystemInfoFromMap <dict> + { RESMPDEBUG { (resmp GetCIDSystemInfoFromMap beg ) print dup = } if + % This is a special function for communicating with GetCIDSystemInfo in gs_cidcm.ps . + dup .map exch .knownget { + RESMPDEBUG { (resmp GetCIDSystemInfoFromMap : have a map record.) = } if + dup /RecordVirtualMethods get /GetCSI get exec + dup null ne { + RESMPDEBUG { (resmp GetCIDSystemInfoFromMap : retrieving a dict.) = } if + exch + } if + pop + } if + RESMPDEBUG { (resmp GetCIDSystemInfoFromMap end) = } if + } bind def + +currentdict end def +setpacking + +/Redefine % <OptionsDict> Redefine - +{ % Before calling this proc, the OptionsDict must specify options for + % the catregory to be redefined : + % CategoryName - a name of category to redefine; + % MapFileName - a string for the resource map file name; + % VerifyMap - a procedure : + % <raw_map> VerifyMap - + % - checks the map for consistency + % PreprocessRecord - a procedure : + % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <record> true + % <map> <Name> <raw_record> PreprocessRecord <map> <Name> <raw_record> false + % - converts a map record into a dictionary; + % It must add RecordVirtualMethods dictionary to the record : + % MakeInstance - a procedure : + % <Name> <record> MakeInstance <Name> <Instance> <size> + % - converts the record to resource instance; + % GetFilePath - a procedure for ResourceFileName : + % <scratch> <Name> <record> GetFilePath <filepath> + % GetSize - a procedure for ResourceStatus : + % <Name> <record> GetSize <size> + % GetCSI - a procedure for obtaining CIDSystemInfo dictionary from the record : + % <record> GetCSI <CSI> + % <record> GetCSI null + % IsActive - a procedure for skipping records depending on the current device : + % <record> IsActive <bool> + % Also it is allowed to contain additional entries for client's needs. + % The OptionsDict is also used for storing some local variables. + + % If a category is being redefined several times with this function, + % each redefinition must either use an unique map file, + % or the map file should be scanned by the last redefinition + % (and must be defined in the last one with /MapFileName). + % This happens so because we must accumulate all variants of + % methods before scanning the map. We would like to delay + % the scanning until all redefinitions are done, but it requires + % to implement a queue of "refinish" methods and execute it + % at very end of the prelude. + + begin % OptionsDict + CategoryName /Category findresource /OldCategory exch def + OldCategory /.IsRedefinedWithMap known { + % Already redefined with map - don't redefine, but enhance the map. + OldCategory /NewCategory exch def + } { + % Redefine with a new category instance. + OldCategory dup length dict + dup /.PreprocessRecord 4 dict put + copy /NewCategory exch def + } ifelse + + % Provide the 'or' logic for PreprocessRecord, + % to allow different record types to be mixed in a single map file. + % We do this with building a dictionary of PreprocessRecord procedures, + % which come from different calls to Redefine : + NewCategory /.PreprocessRecord get dup length % <<pr>> l + currentdict /PreprocessRecord get .growput + + currentdict /MapFileName known { + MapFileName .libfile { + 1 dict begin + /; {} def + mark exch cvx exec .dicttomark % <<map>> + end + dup VerifyMap % <<map>> + } { + QUIET not { + currentdict /IsMapFileOptional .knownget not { false } if not { + (Warning: the map file ) print dup =string cvs print ( was not found.) = + } if + } if + pop 0 dict % <<map>> + } ifelse + } { + currentdict /.map .knownget not { + 0 dict % <<map>> + } if + } ifelse + + % Preprocess entries : + dup NewCategory /.PreprocessRecord get % <<map>> <<map>> <<pr>> + 3 1 roll { % <<pr>> <<map>> /Name raw_record + false 3 1 roll % <<pr>> <<map>> false /Name raw_record + 4 index { % <<pr>> <<map>> false /Name raw_record i {pr} + exch pop % <<pr>> <<map>> false /Name raw_record {pr} + exec { % <<pr>> <<map>> false /Name record + 3 -1 roll pop true 3 1 roll % <<pr>> <<map>> true /Name record + exit + } if % <<pr>> <<map>> false /Name raw_record + } forall + 3 2 roll { % <<pr>> <<map>> /Name record + 2 index 3 1 roll put % <<pr>> <<map>> + } { + exch % <<pr>> <<map>> raw_record /Name + (Incorrect record ) print =string cvs print ( of the map file ) print MapFileName =string cvs print (.) = + end % Pops OptionsDict from dstack. + pop pop pop % + /Redefine cvx /undefinedresource signalerror + } ifelse + } forall % <<pr>> <<map>> + exch pop % <<map>> + + + % Add the map : + OldCategory /.IsRedefinedWithMap known { % <<map>> + % Just add to the old map : + OldCategory /.map get copy pop % + } { % <<map>> + % Store the map to both the category and OptionsDict : + dup NewCategory exch /.map exch put + /.map exch def % + } ifelse + OldCategory /.IsRedefinedWithMap known not { + % Copy old methods to OptionsDict : + [ /DefineResource /ResourceStatus /ResourceFileName + /FindResource /ResourceForAll + ] { + dup OldCategory exch get def + } forall + + % Build new methods : + //MethodsToRedefine { + //BindWithCurrentdict exec NewCategory 3 1 roll put + } forall + CategoryName /CIDFont ne { + NewCategory /GetCIDSystemInfoFromMap undef + % This is some ugly, sorry. + } if + % Redefine the category : + NewCategory /.IsRedefinedWithMap true put + CategoryName NewCategory /Category defineresource pop + } if + end % OptionsDict +} bind executeonly def + +currentdict /PutPreprocessRecord .undef + +currentdict end +/ProcSet defineresource pop + +setglobal .setlanguagelevel diff --git a/gs/Resource/Init/gs_sepr.ps b/gs/Resource/Init/gs_sepr.ps new file mode 100644 index 000000000..e417adb3d --- /dev/null +++ b/gs/Resource/Init/gs_sepr.ps @@ -0,0 +1,268 @@ +% Copyright (C) 2001, 2002 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Separation color space method dictionary + + +% verify that Separation color spaces are supported +/.setseparationspace where + { pop } + { currentfile closefile } +ifelse + +.currentglobal true .setglobal +.cspace_util begin + + +% +% <c1> <array> apply_sepr_tint_xform <c1>' ... <cn>' <array> +% +% Apply the tint transform for a Separation color space color intensity +% value. +% +/apply_sepr_tint_xform + { + exch //bound_0_1 exec + mark exch 2 index 3 get exec + counttomark { cvr counttomark -1 roll } repeat % for CET, make all tints real. + counttomark 2 add -2 roll pop + } +bind def + + +% +% <cspace_array> build_tintxform_function <cspace_array> <proc> +% +% Convert a tint transformation into a function, if possible. If this is +% successful, <proc> will be a function procedure (a two-element, +% execute-only, executable array whose first element is the function +% data structure and whose second element is the operator %execfunction. +% If it is not successful, <proc> will be the same as the tint transform +% in <cspace_array>. +% +% Note that, for PDF files, the tint transform will likely already be a +% function-array. In this case, <proc> will be this array, and thus will +% also be identical to the original tint transform. +% +% This procedure is used for both Separation and DeviceN color spaces. +% +/build_tintxform_function + { + dup 3 get dup .isencapfunction not + { + % Try a FunctionType 4 function first; build the function dictionary + % in local VM. + .currentglobal exch //false .setglobal + % Make the dictionary a couple of elements large in case this fails + % and we need the dictionary to build a sampled function. + 6 dict begin + /FunctionType 4 def + /Function exch def + /Domain 2 index //.cs_get_range exec def + /Range 2 index 2 get //.cs_get_range exec def + currentdict end + { .buildfunction } + .internalstopped % If .buildfunction fails then not type 4 func. + { % If not then try building a sampled (type 0) func. + % We are using the dictionary which was created before .buildfunction + dup /Order 3 put + dup /BitsPerSample 16 put + { .buildsampledfunction } + .internalstopped % If .buildsamplefunction fails then invalid func. + { % Failed - Create a dummy tint transform function + % We are using the dictionary which was created before .buildfunction + dup /Function {} put % Replace invalid tint transform with dummy + .buildfunction + } + if % Check status from .buildsamplefunction/.internalstopped + } + if % check status from .buildfunction/.intermalstopped + % restore the VM mode + exch .setglobal + } + if + } +bind def + +% +% <array1> <array2> converttinttransform <array1> <array2'> +% +% Convert a Separation/DeviceN color space to use a function as a tint +% transformation, if this is possible. Possible outcomes are: +% +% 1. The tint transform already is a function, or is a procedure that +% cannot be converted to a function. In either case, <array2> is +% left unchanged (<array2> == <array2'>). +% +% 2. The tint transform is not already a function but can be converted +% to a function, and <array1> != <array2>. In this case, <array2> +% is modified directly. +% +% 3. The tint transform is not already a function but can be converted +% to a function, and <array1> == <array2>. In this case, <array2> +% is copied, and the copy is modified (i.e., after the operation +% <array1> != <array2> +% +% This slightly complex approach avoids creating an extra color space +% array unnecessarily. +% +/converttinttransform + { + % convert the tint transform to a fucntion + //build_tintxform_function exec + + % see if anything needs to be modified + 1 index 3 get 2 copy eq + { pop pop } + { + pop + + % see if the color space must be copied + 3 copy pop eq + { + % copy the array into local VM + .currentglobal //false .setglobal + 3 -1 roll dup length array copy 3 1 roll + .setglobal + } + if + 1 index exch 3 exch put + } + ifelse + } +bind def + + +colorspacedict +/Separation + mark + /cs_potential_indexed_base true + /cs_potential_pattern_base true + /cs_potential_alternate false + /cs_potential_icc_alternate false + /cs_get_ncomps //ncomps_1 + /cs_get_range //get_range_1 + /cs_get_default_color { pop 1 } bind + + /cs_get_currentgray + { //apply_sepr_tint_xform exec 2 get //.cs_get_currentgray exec } + bind + /cs_get_currentrgb + { //apply_sepr_tint_xform exec 2 get //.cs_get_currentrgb exec } + bind + /cs_get_currentcmyk + { //apply_sepr_tint_xform exec 2 get //.cs_get_currentcmyk exec } + bind + + % a lot of validation is done by the cs_validate method + /cs_validate + { + //check_array exec + dup 1 get type dup /nametype ne exch /stringtype ne and + //setcspace_typecheck + if + dup 2 get //.cs_validate exec //.cs_potential_alternate exec not + //setcspace_rangecheck + if + dup 3 get //check_array exec xcheck not + //setcspace_typecheck + if + } + bind + + % substitute the base space if appropriate + /cs_substitute + { + dup 2 get //.cs_substitute exec 2 copy eq + { pop pop dup } + { + % retain only the new alternate space + exch pop + + % build all new structures in local VM + .currentglobal 3 1 roll //false .setglobal + + % construct a new array and insert the new base color space + 1 index dup length array copy dup 2 4 -1 roll put + + % restore VM mode + 3 -1 roll .setglobal + } + ifelse + } + bind + + % + % The Ghostscript interpreter works better when tinttransform procedures + % are translated into functions. Attempt to do that here. + % + /cs_prepare //converttinttransform + + % + % Install the current color space. + % + % The current Ghostscript color space implementation requires that + % color spaces that provide a base or alternative color space set + % that base/alternative color space to be the current color space + % before attempting to set the original color space. + % + /cs_install + { + % save the current color space + currentcolorspace + + % set the base color space as the current color space + 1 index 2 get //forcesetcolorspace + + % set the indexed color space; restore the earlier space on error + mark 2 index + { .setseparationspace } + stopped + { cleartomark setcolorspace stop } + { pop pop pop } + ifelse + } + bind + + /cs_prepare_color //validate_1 + + % + % If a Separation color space is not supported in native mode by + % the current process color model, Adobe implementations will always + % execute the tint transform procedure when setcolor is invoked. + % Ghostscript may have turned this transform into a sampled function, + % and even if this is not the case, will have sampled the transform + % when the color space is first set. Some applications may depend + % on the Adobe behavior, so we implement it via the + % cs_complete_setcolor method. + % + /cs_complete_setcolor + { + .usealternate + { + currentcolor exch 3 get exec + currentcolorspace 2 get //clear_setcolor_operands exec + } + { pop } + ifelse + } + bind + + .dicttomark +put + +end % .cspace_util +.setglobal diff --git a/gs/Resource/Init/gs_setpd.ps b/gs/Resource/Init/gs_setpd.ps new file mode 100644 index 000000000..20d38f360 --- /dev/null +++ b/gs/Resource/Init/gs_setpd.ps @@ -0,0 +1,924 @@ +% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% The current implementation of setpagedevice has the following limitations: +% - It doesn't attempt to "interact with the user" for Policy = 2. + +languagelevel 1 .setlanguagelevel +level2dict begin + +% ---------------- Redefinitions ---------------- % + +% Redefine .beginpage and .endpage so that they call BeginPage and +% EndPage respectively if appropriate. + +% We have to guard against the BeginPage procedure not popping its operand. +% This is really stupid, but the Genoa CET does it. +/.beginpage { % - .beginpage - + .currentshowpagecount { + .currentpagedevice pop + dup //null ne { /BeginPage .knownget } { pop //false } ifelse { + % Stack: ... pagecount proc + count 2 .execn + % Stack: ... ..???.. oldcount + count 1 add exch sub { pop } repeat + } { + pop + } ifelse + } if +} bind odef + +% Guard similarly against EndPage not popping its operand. +/.endpage { % <reason> .endpage <print_bool> + .currentshowpagecount { + 1 index .currentpagedevice pop + dup //null ne { /EndPage .knownget } { pop //false } ifelse { + % Stack: ... reason pagecount reason proc + count 2 .execn + % Stack: ... ..???.. print oldcount + count 2 add exch sub { exch pop } repeat + } { + pop pop 2 ne + } ifelse + } { + 2 ne + } ifelse +} bind odef + +% Define interpreter callouts for handling gstate-saving operators, +% to make sure that they create a page device dictionary for use by +% the corresponding gstate-restoring operator. +% We'd really like to avoid the cost of doing this, but we don't see how. +% The names %gsavepagedevice, %savepagedevice, %gstatepagedevice, +% %copygstatepagedevice, and %currentgstatepagedevice are known to the +% interpreter. + +(%gsavepagedevice) cvn + { currentpagedevice pop gsave + } bind def + +(%savepagedevice) cvn + { currentpagedevice pop save + } bind def + +(%gstatepagedevice) cvn + { currentpagedevice pop gstate + } bind def + +(%copygstatepagedevice) cvn + { currentpagedevice pop copy + } bind def + +(%currentgstatepagedevice) cvn + { currentpagedevice pop currentgstate + } bind def + +% Define interpreter callouts for handling gstate-restoring operators +% when the current page device needs to be changed. +% The names %grestorepagedevice, %grestoreallpagedevice, +% %restorepagedevice, %restore1pagedevice, and %setgstatepagedevice +% are known to the interpreter. + +/.installpagedevice + { % Since setpagedevice doesn't create new device objects, + % we must (carefully) reinstall the old parameters in + % the same device. + .currentpagedevice pop //null currentdevice //null .trysetparams + dup type /booleantype eq + { pop pop } + { % This should never happen! + SETPDDEBUG { (Error in .trysetparams!) = pstack flush } if + cleartomark pop pop pop + /.installpagedevice cvx /rangecheck signalerror + } + ifelse pop pop + % A careful reading of the Red Book reveals that an erasepage + % should occur, but *not* an initgraphics. + erasepage .beginpage + } bind def + +/.uninstallpagedevice + { 2 .endpage { .currentnumcopies //false .outputpage } if + nulldevice + } bind def + +(%grestorepagedevice) cvn + { .uninstallpagedevice grestore .installpagedevice + } bind def + +(%grestoreallpagedevice) cvn + { .uninstallpagedevice grestore .installpagedevice grestoreall + } bind def + +(%restore1pagedevice) cvn + { .uninstallpagedevice grestore .installpagedevice restore + } bind def + +(%restorepagedevice) cvn + { .uninstallpagedevice restore .installpagedevice + } bind def + +(%setgstatepagedevice) cvn + { .uninstallpagedevice setgstate .installpagedevice + } bind def + +% Redefine .currentnumcopies so it consults the NumCopies device parameter. +/.numcopiesdict mark + /NumCopies dup +.dicttomark readonly def + +/.currentnumcopies + { currentdevice //.numcopiesdict .getdeviceparams + dup type /integertype eq + { exch pop exch pop } + { cleartomark #copies } + ifelse + } bind odef + +% Redefine .currentpagedevice and .setpagedevice so they convert between +% null and a fixed empty directionary. +/.nullpagedevice 0 dict readonly def +/.currentpagedevice { + //.currentpagedevice exch dup //null eq { pop //.nullpagedevice } if exch +} bind odef +/.setpagedevice { + dup //.nullpagedevice eq { pop //null } if //.setpagedevice +} bind odef + +% ---------------- Auxiliary definitions ---------------- % + +% Define the required attributes of all page devices, and their default values. +% We don't include attributes such as .MediaSize, which all devices +% are guaranteed to supply on their own. +/.defaultpolicies mark + % M. Sweet, Easy Software Products + % + % Due to the fact that it is not possible to properly implement + % the selection policies from a Ghostscript driver, we have changed + % the default policy to "7" (impose) to avoid numerous problems with + % printing within CUPS... + % + NOMEDIAATTRS { + /PolicyNotFound 7 + /PageSize 7 + } { + /PolicyNotFound 1 + /PageSize 0 + } ifelse + /PolicyReport { + dup /.LockSafetyParams known { + % Only possible error is invalidaccess + /setpagedevice .systemvar /invalidaccess signalerror + } + if + pop + } bind +.dicttomark readonly def +% Note that the values of .requiredattrs are executed, not just fetched. +/.requiredattrs mark + /PageDeviceName //null + /PageOffset [0 0] readonly +% We populate InputAttributes with all of the known page sizes +% followed by a dummy media type that handles pages of any size. +% This will create some duplicates, but that only slightly slows +% down the media selection (loop is in zmedia2.c). +% +% Some PostScript creators assume that slot 0 is the default media +% size and some can't handle a non-standard 4-element array which +% is a 'range' type page size (always put last). +% +% Real Devices that can only handle specific page sizes will override this. + /InputAttributes { + mark + % First put the device's default page size in slot 0 + % This satifies those that have devices built with a4 as the default + 0 mark /PageSize currentdevice /PageSize gsgetdeviceprop .dicttomark + statusdict /.pagetypenames get { + counttomark 1 sub 2 idiv exch mark exch /PageSize exch + % stack: mark --dict-- --dict-- ... key mark /PageSize pagetypename + % see note above about pagetype executable array contents. + load dup 0 get exch 1 get 2 array astore .dicttomark + } forall + % If NORANGEPAGESIZE is defined, (-dNORANGEPAGESIZE), then don't add + % the 'match any' PageSize entry + systemdict /NORANGEPAGESIZE known not { + % Add one last entry which is the 4 element range array (non-standard) + counttomark 2 idiv + % PageSize with either dimension 0 will be detected in + % match_page_size, so we can allow it here + mark /PageSize [0 dup 16#7ffff dup] .dicttomark + } if + .dicttomark + } + (%MediaSource) 0 + /OutputAttributes { + mark 0 mark .dicttomark readonly .dicttomark + } + (%MediaDestination) 0 + /Install {{.callinstall}} bind + /BeginPage {{.callbeginpage}} bind + /EndPage {{.callendpage}} bind + /Policies .defaultpolicies + /ImagingBBox //null % default value + /UseCIEColor /.getuseciecolor load +.dicttomark readonly def + +% Define currentpagedevice so it creates the dictionary on demand if needed, +% adding all the required entries defined just above. +% We have to deal specially with entries that the driver may change +% on its own. +/.dynamicppkeys mark + /.MediaSize dup % because it changes when PageSize is set +% /LeadingEdge dup + /PageCount dup + /Colors dup + /BitsPerPixel dup + /ColorValues dup +.dicttomark readonly def +/.makecurrentpagedevice { % - .makecurrentpagedevice <dict> + currentdevice //null .getdeviceparams + % Make the dictionary large enough to add defaulted entries. + counttomark 2 idiv .requiredattrs length add dict + counttomark 2 idiv { dup 4 2 roll put } repeat exch pop + % Add any missing required attributes. + % Make a writable and (if possible) local copy of any default + % dictionaries, to work around a bug in the output of WordPerfect, + % which assumes that these dictionaries are writable and local. + .currentglobal exch dup gcheck .setglobal + .requiredattrs { + 2 index 2 index known { + 1 index /Policies eq { + % Merge policies from the device driver with defaults + 2 index % <<>> /key value <<>> + 3 2 roll get % <<>> value <<policies>> + exch { + 2 index 2 index known { + pop pop + } { + 2 index 3 1 roll put + } ifelse + } forall + pop + } { + pop pop + } ifelse + } { + exec 2 index 3 1 roll put + } ifelse + } forall exch .setglobal + dup .setpagedevice +} bind def +/currentpagedevice { + .currentpagedevice { + dup length 0 eq { + pop .makecurrentpagedevice + } { + % If any of the dynamic keys have changed, + % we must update the page device dictionary. + currentdevice //.dynamicppkeys .getdeviceparams .dicttomark { + % Stack: current key value + 2 index 2 index .knownget { 1 index ne } { //true } ifelse + { 2 index wcheck not + { % This is the first entry being updated. + % Copy the dictionary to make it writable. + 3 -1 roll + currentglobal 1 index dup gcheck currentglobal and setglobal + length dict + exch setglobal + .copydict + 3 1 roll + } + if + 2 index 3 1 roll put + } + { pop pop + } + ifelse + } forall + % If the device is the distiller device, update distillerparams that + % may have been changed by setdistillerparams + currentdevice .devicename /pdfwrite eq { + currentdistillerparams { + % Stack: current key value + 2 index 2 index .knownget { 1 index ne } { //true } ifelse + { 2 index 3 1 roll put } { pop pop } ifelse + } forall + } if + % If the dictionary was global and is now local, copy + % any global subsidiary dictionaries to local VM. This + % too is to work around the Word Perfect bug (see above). + dup gcheck not { + dup { + dup type /dicttype eq { dup gcheck } { //false } ifelse { + % Copy-on-write, see above. + 2 index wcheck not { + 3 -1 roll dup length dict .copydict + 3 1 roll + } if + .copytree 2 index 3 1 roll put + } { + pop pop + } ifelse + } forall + } if + % We would like to do a .setpagedevice so we don't keep + % re-creating the dictionary. Unfortunately, the effect + % of this is that if any dynamic key changes (PageCount + % in particular), we will do the equivalent of a + % setpagedevice at the next restore or grestore. + % Therefore, we make the dictionary read-only, but + % we don't store it away. I.e., NOT: + % dup wcheck { .setpagedevice .currentpagedevice pop } if + readonly + } ifelse + } if +} bind odef + +% Copy a dictionary recursively. +/.copytree { % <dict> .copytree <dict'> + dup length dict exch { + dup type /dicttype eq { .copytree } if 2 index 3 1 roll put + } forall +} bind def + +% The implementation of setpagedevice is quite complex. Currently, +% everything but the media matching algorithm is implemented here. + +% By default, we only present the requested changes to the device, +% but there are some parameters that require special merging action. +% Define those parameters here, with the procedures that do the merging. +% The procedures are called as follows: +% <merged> <key> <new_value> -proc- <merged> <key> <new_value'> +/.mergespecial mark + /InputAttributes + { dup //null eq + { pop //null + } + { 3 copy pop .knownget + { dup //null eq + { pop dup length dict } + { dup length 2 index length add dict .copydict } + ifelse + } + { dup length dict + } + ifelse .copydict readonly + } + ifelse + } bind + /OutputAttributes 1 index + /Policies + { 3 copy pop .knownget + { dup length 2 index length add dict .copydict } + { dup length dict } + ifelse copy readonly + } bind +.dicttomark readonly def + +% M. Sweet, Easy Software Products: +% +% Define NOMEDIAATTRS to turn off the default (but unimplementable) media +% selection policies for setpagedevice. This is used by CUPS to support +% the standard Adobe media attributes. +NOMEDIAATTRS { + % Define only PageSize for input attribute matching. + /.inputattrkeys [ + /PageSize + ] readonly def + % Define no other keys used in media selection. + /.inputselectionkeys [ + /noInputSelectionsKeys + ] readonly def + + % Define no keys used in output attribute matching. + /.outputattrkeys [ + /noOutputAttrKeys + ] readonly def +} { + % Define the keys used in input attribute matching. + /.inputattrkeys [ + /PageSize /MediaColor /MediaWeight /MediaType /InsertSheet /ManualFeed + % The following are documented in Adobe's supplement for v2017. + /LeadingEdge /MediaClass + ] readonly def + % Define other keys used in media selection. + /.inputselectionkeys [ + /MediaPosition /Orientation + ] readonly def + + % Define the keys used in output attribute matching. + /.outputattrkeys [ + /OutputType /Duplex /Tumble /ManualFeed + ] readonly def +} ifelse + +% Define all the parameters that should always be copied to the merged +% dictionary. +/.copiedkeys [ + /OutputDevice + .mergespecial { pop } forall + .inputattrkeys aload pop + .inputselectionkeys aload pop + .outputattrkeys aload pop +] readonly def + +% Define the parameters that should not be presented to the device. +% The procedures are called as follows: +% <merged> <key> <value> -proc- +% The procedure leaves all its operands on the stack and returns +% true iff the key/value pair should be presented to .putdeviceparams. +/.presentspecial mark + .dynamicppkeys + { pop dup /LeadingEdge ne { //false } { pop } ifelse } + forall + % We must ignore an explicit request for .MediaSize, + % because media matching always handles this. + /.MediaSize //false + /Name //false + /OutputDevice //false + /PageDeviceName //false + /PageOffset //false + /PageSize //false % obsolete alias for .MediaSize + /InputAttributes //false + .inputattrkeys + { dup dup /PageSize eq exch /LeadingEdge eq or + { pop } + { { 2 index /InputAttributes .knownget { //null eq } { //true } ifelse } } + ifelse + } + forall + .inputselectionkeys { //false } forall + /OutputAttributes //false + .outputattrkeys + { { 2 index /OutputAttributes .knownget { //null eq } { //true } ifelse } } + forall + /Install //false + /BeginPage //false + /EndPage //false + /Policies //false + % Our extensions: + /HWColorMap + { % HACK: don't transmit the color map, because + % window systems can change the color map on their own + % incrementally. Someday we'll have a better + % solution for this.... + //false + } + /ViewerPreProcess //false + /ImagingBBox //false % This prevents the ImagingBBox value in the setpagedevice + % from affecting the device's ImagingBBox parameter, but + % does retain a 'shadow' copy at the PostScript level. + % This is done for Adobe compatibility since Adobe does + % render marks outside the ImagingBBox (and QuarkXpress + % relies on it). +.dicttomark readonly def + +% Define access to device defaults. +/.defaultdeviceparams + { finddevice //null .getdeviceparams + } bind def + +% Select media (input or output). The hard work is done in an operator: +% <pagedict> <attrdict> <policydict> <keys> .matchmedia <key> true +% <pagedict> <attrdict> <policydict> <keys> .matchmedia false +% <pagedict> null <policydict> <keys> .matchmedia null true +/.selectmedia % <orig> <request> <merged> <failed> <-- retained + % <attrdict> <policydict> <attrkeys> <mediakey> + % .selectmedia + { 5 index 5 -2 roll 4 index .matchmedia + % Stack: orig request merged failed attrkeys mediakey + % (key true | false) + { 4 index 3 1 roll put pop + } + { % Adobe's implementations have a "big hairy heuristic" + % to choose the set of keys to report as having failed the match. + % For the moment, we report any keys that are in the request + % and don't have the same value as in the original dictionary. + 5 index 1 index .knownget + { 4 index 3 1 roll put } + { 3 index exch .undef } + ifelse + { % Stack: <orig> <request> <merged> <failed> <attrkey> + 3 index 1 index .knownget + { 5 index 2 index .knownget { ne } { pop //true } ifelse } + { //true } + ifelse % Stack: ... <failed> <attrkey> <report> + { 2 copy /rangecheck put } + if pop + } + forall + } + ifelse + } bind def + +% Apply Policies to any unprocessed failed requests. +% As we process each request entry, we replace the error name +% in the <failed> dictionary with the policy value, +% and we replace the key in the <merged> dictionary with its prior value +% (or remove it if it had no prior value). +/.policyprocs mark +% These procedures are called with the following on the stack: +% <orig> <merged> <failed> <Policies> <key> <policy> +% They are expected to consume the top 2 operands. +% NOTE: we currently treat all values other than 0, 1, or 7 (for PageSize) +% the same as 0, i.e., we signal an error. +% +% M. Sweet, Easy Software Products: +% +% Define NOMEDIAATTRS to turn off the default (but unimplementable) media +% selection policies for setpagedevice. This is used by CUPS to support +% the standard Adobe media attributes. + 0 { % Set errorinfo and signal a configurationerror. + NOMEDIAATTRS { + % NOMEDIAATTRS means that the default policy is 7... + pop 2 index exch 7 put + } { + pop dup 4 index exch get 2 array astore + $error /errorinfo 3 -1 roll put + cleartomark + /setpagedevice .systemvar /configurationerror signalerror + } ifelse + } bind + 1 { % Roll back the failed request to its previous status. +SETPDDEBUG { (Rolling back.) = pstack flush } if + 3 index 2 index 3 -1 roll .forceput + 4 index 1 index .knownget + { 4 index 3 1 roll .forceput } + { 3 index exch .undef } + ifelse + } .bind + 7 { % For PageSize only, just impose the request. + 1 index /PageSize eq + { pop pop 1 index /PageSize 7 put } + { .policyprocs 0 get exec } + ifelse + } bind +.dicttomark readonly def +/.applypolicies % <orig> <merged> <failed> .applypolicies + % <orig> <merged'> <failed'> + { 1 index /Policies get 1 index + { type /integertype eq + { pop % already processed + } + { 2 copy .knownget not { 1 index /PolicyNotFound get } if + % Stack: <orig> <merged> <failed> <Policies> <key> + % <policy> + .policyprocs 1 index .knownget not { .policyprocs 0 get } if exec + } + ifelse + } + forall pop + } bind def + +% Prepare to present parameters to the device, by spreading them onto the +% operand stack and removing any that shouldn't be presented. +/.prepareparams % <params> .prepareparams -mark- <key1> <value1> ... + { mark exch dup + { % Stack: -mark- key1 value1 ... merged key value + .presentspecial 2 index .knownget + { exec { 3 -1 roll } { pop pop } ifelse } + { 3 -1 roll } + ifelse + } + forall pop + } bind def + +% Put device parameters without resetting currentpagedevice. +% (.putdeviceparams clears the current page device.) +/.putdeviceparamsonly % <device> <Policies|null> <require_all> -mark- + % <key1> <value1> ... .putdeviceparamsonly + % On success: <device> <eraseflag> + % On failure: <device> <Policies|null> <req_all> -mark- + % <key1> <error1> ... + { .currentpagedevice + { counttomark 4 add 1 roll .putdeviceparams + dup type /booleantype eq { 3 } { counttomark 5 add } ifelse -1 roll + .setpagedevice + } + { pop .putdeviceparams + } + ifelse + } bind def + +% Try setting the device parameters from the merged request. +/.trysetparams % <merged> <(ignored)> <device> <Policies> + % .trysetparams + { //true 4 index .prepareparams + % Add the computed .MediaSize. + % Stack: merged (ignored) device Policies -true- + % -mark- key1 value1 ... + counttomark 5 add index .computemediasize + exch pop exch pop /.MediaSize exch +SETPDDEBUG { (Putting.) = pstack flush } if + .putdeviceparamsonly +SETPDDEBUG { (Result of putting.) = pstack flush } if + } bind def + +% Compute the media size and initial matrix from a merged request (after +% media selection). +/.computemediasize % <request> .computemediasize + % <request> <matrix> <[width height]> + { dup /PageSize get % requested page size + 1 index /InputAttributes get + 2 index (%MediaSource) get get /PageSize get % media size + % (may be a range) + 2 index /Policies get + dup /PageSize .knownget + { exch pop } { /PolicyNotFound get } ifelse % PageSize policy, + % affects scaling + 3 index /Orientation .knownget not { //null } if + 4 index /RollFedMedia .knownget not { //false } if + matrix .matchpagesize not { + % This is a "can't happen" condition! + /setpagedevice .systemvar /rangecheck signalerror + } if + 2 array astore + } bind def + +% ---------------- setpagedevice itself ---------------- % + +/setpagedevice + { % We mustn't pop the argument until the very end, + % so that the pseudo-operator machinery can restore the stack + % if an error occurs. + mark 1 index currentpagedevice + + % Check whether we are changing OutputDevice; + % also handle the case where the current device + % is not a page device. + % Stack: mark <request> <current> +SETPDDEBUG { (Checking.) = pstack flush } if + + dup /OutputDevice .knownget + { % Current device is a page device. + 2 index /OutputDevice .knownget + { % A specific OutputDevice was requested. + 2 copy eq + { pop pop //null } + { exch pop } + ifelse + } + { pop //null + } + ifelse + } + { % Current device is not a page device. + % Use the default device. + 1 index /OutputDevice .knownget not { .defaultdevicename } if + } + ifelse + dup //null eq + { pop + } + { exch pop .defaultdeviceparams + % In case of duplicate keys, .dicttomark takes the entry + % lower on the stack, so we can just append the defaults here. + .requiredattrs { exec } forall .dicttomark + } + ifelse + + % Check whether a viewer wants to intervene. + % We must check both the request (which takes precedence) + % and the current dictionary. + % Stack: mark <request> <orig> + exch dup /ViewerPreProcess .knownget + { exec } + { 1 index /ViewerPreProcess .knownget { exec } if } + ifelse exch + + % Construct a merged request from the actual request plus + % any keys that should always be propagated. + % Stack: mark <request> <orig> +SETPDDEBUG { (Merging.) = pstack flush } if + + exch 1 index length 1 index length add dict + .copiedkeys + { % Stack: <orig> <request> <merged> <key> + 3 index 1 index .knownget { 3 copy put pop } if pop + } + forall + % Stack: <orig> <request> <merged> + dup 2 index + { % stack: <orig> <request> <merged> <merged> <rkey> <rvalue> + .mergespecial 2 index .knownget { exec } if + put dup + } + forall pop + % Hack: if FIXEDRESOLUTION is true, discard any attempt to + % change HWResolution. + FIXEDRESOLUTION { dup /HWResolution .undef } if + % Hack: if FIXEDMEDIA is true, discard any attempt to change + % PageSize or HWSize. + FIXEDMEDIA + { dup /PageSize 4 index /PageSize get put + dup /HWSize 4 index /HWSize get put + } if + % Hack: to work around some files that take a PageSize + % from InputAttributes and impose it, discard any attempt + % to set PageSize to a 4-element value. + % Stack: mark <orig> <request> <merged> + dup /PageSize .knownget { + length 2 ne { + dup /PageSize 4 index /PageSize get put + } if + } if + + % Select input and output media. + % Stack: mark <orig> <request> <merged> +SETPDDEBUG { (Selecting.) = pstack flush } if + + 0 dict % <failed> + 1 index /InputAttributes .knownget + { 2 index /Policies get + .inputattrkeys (%MediaSource) cvn .selectmedia + } if + 1 index /OutputAttributes .knownget + { 2 index /Policies get + .outputattrkeys (%MediaDestination) cvn .selectmedia + } if + 3 -1 roll 4 1 roll % temporarily swap orig & request + .applypolicies + 3 -1 roll 4 1 roll % swap back + + % Construct the new device, and attempt to set its attributes. + % Stack: mark <orig> <request> <merged> <failed> +SETPDDEBUG { (Constructing.) = pstack flush } if + + currentdevice .devicename 2 index /OutputDevice get eq + { currentdevice } + { 1 index /OutputDevice get finddevice } + ifelse + %**************** We should copy the device here, + %**************** but since we can't close the old device, + %**************** we don't. This is WRONG. + %****************copydevice + 2 index /Policies get + .trysetparams + dup type /booleantype ne + { % The request failed. + % Stack: ... <orig> <request> <merged> <failed> <device> + % <Policies> true mark <name> <errorname> ... +SETPDDEBUG { (Recovering.) = pstack flush } if + counttomark 4 add index + counttomark 2 idiv { dup 4 -2 roll put } repeat + pop pop pop + % Stack: mark ... <orig> <request> <merged> <failed> <device> + % <Policies> + 6 2 roll 3 -1 roll 4 1 roll + .applypolicies + 3 -1 roll 4 1 roll 6 -2 roll + .trysetparams % shouldn't fail! + dup type /booleantype ne + { 2 { counttomark 1 add 1 roll cleartomark } repeat + /setpagedevice .systemvar exch signalerror + } + if + } + if + + % The attempt succeeded. Install the new device. + % Stack: mark ... <merged> <failed> <device> <eraseflag> +SETPDDEBUG { (Installing.) = pstack flush } if + + pop 2 .endpage + { 1 //true .outputpage + (>>setpagedevice, press <return> to continue<<\n) .confirm + } + if + % .setdevice clears the current page device! + .currentpagedevice pop exch + .setdevice pop + .setpagedevice + + % Implement UseCIEColor directly if this is a LL3 system. + % The color substitution feature is now implemented in + % the interpreter, and this is used as an optimization. + % + % NB: This shoud be the only use of the .setuseciecolor + % operator anywhere. + % + % If UseCIEColor is transitioned to false, set some + % color space other than /DeviceGray, to insure that + % initgraphics will actually perform a setcolorspace + % operation (there is an optimization in setcolorspace + % that does nothing if the operand and current color + % spaces are the same, and UseCIEColor is false). + + /.setuseciecolor where + { + pop 1 index /UseCIEColor .knownget + { + dup .setuseciecolor not + { /DeviceRGB setcolorspace } + if + } + if + } + if + + % Merge the request into the current page device, + % unless we're changing the OutputDevice. + % Stack: mark ... <merged> <failed> + exch currentpagedevice dup length 2 index length add dict + % Stack: mark ... <failed> <merged> <current> <newdict> + 2 index /OutputDevice .knownget { + 2 index /OutputDevice .knownget not { //null } if eq + } { + //true + } ifelse { + % Same OutputDevice, merge the dictionaries. + .copydict + } { + % Different OutputDevice, discard the old dictionary. + exch pop + } ifelse .copydict + % Initialize the default matrix, taking media matching + % into account. + .computemediasize pop initmatrix concat + dup /PageOffset .knownget + { % Translate by the given number of 1/72" units in device X/Y. + dup 0 get exch 1 get + 2 index /HWResolution get dup 1 get exch 0 get + 4 -1 roll mul 72 div 3 1 roll mul 72 div + idtransform translate + } + if + % We must install the new page device dictionary + % before calling the Install procedure. + dup .setpagedevice + .setdefaulthalftone % Set the default screen before calling Install. + dup /Install .knownget { + { .execinstall } stopped { + pop % Install procedure failed. One element will have been left on the stack. + % stack: mark <orig> <request> <failed> <merged> + 1 index /Install $error /errorname get put % Put it in the "failed" dict + % .applypolicies needs stack: <orig> <merged> <failed> + exch 4 2 roll exch 4 2 roll .applypolicies exch 4 2 roll exch 4 2 roll + % Now execute the old Install -- failures after this are not handled + dup /Install .knownget { { .execinstall } stopped { pop } if } if + .postinstall stop + } { + .postinstall + } ifelse + } { + .postinstall + } ifelse +} odef + +% We break out the code after calling the Install procedure into a +% separate procedure, since it is executed even if Install causes an error. +% By making .execinstall a separate operator procedure, we get the stacks +% mostly restored if it fails, except for one element (the operand). +% Thus if it fails, there will be one element left on the op stack. + +/.execinstall { % <proc> .execinstall - + dup % element left on the stack if the exec fails. + + % Because the interpreter optimizes tail calls, we can't just let + % the body of this procedure be 'exec', because that would lose + % the stack protection that is the whole reason for having the + % procedure in the first place. The 'pop' for the dummy element + % on the op stack suffices. + exec + pop % See above. +} odef + +/.postinstall { % mark ... <failed> <merged> .postinstall - + matrix currentmatrix .setdefaultmatrix + % Erase and initialize the page. + initgraphics + currentoverprint //false setoverprint 1 setcolor + .fillpage + 0 setcolor setoverprint + .beginpage + + % Clean up, calling PolicyReport if needed. + % Stack: mark ... <failed> <merged> +SETPDDEBUG { (Finishing.) = pstack flush } if + + exch dup length 0 ne + { 1 index /Policies get /PolicyReport get + counttomark 1 add 2 roll cleartomark + exec + } + { cleartomark + } + ifelse pop + +} odef + +end % level2dict +.setlanguagelevel diff --git a/gs/Resource/Init/gs_statd.ps b/gs/Resource/Init/gs_statd.ps new file mode 100644 index 000000000..8252bc3d0 --- /dev/null +++ b/gs/Resource/Init/gs_statd.ps @@ -0,0 +1,374 @@ +% Copyright (C) 1989, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% This file provides statusdict, serverdict, and assorted LaserWriter +% operators, mostly for the benefit of poorly designed PostScript programs +% that 'know' they are running on a LaserWriter. + +systemdict begin + % We make statusdict a little larger for Level 2 stuff. + % Note that it must be allocated in local VM. + .currentglobal false .setglobal + /statusdict 89 dict .forcedef % statusdict is local, sys'dict global + % To support the Level 2 job control features, + % serverdict must also be in local VM. + /serverdict 10 dict .forcedef % serverdict is local, sys'dict global + .setglobal +end + +% Define various paper formats. The Adobe documentation defines only these: +% 11x17, a3, a4, a4small, b5, ledger, legal, letter, lettersmall, note. +% These procedures are also accessed as data structures during initialization, +% so the page dimensions must be the first two elements of the procedure. + +/.setpagesize { /statusdict .systemvar begin .setpagesize end } bind def +userdict begin + % Page sizes defined by Adobe documentation + % Note: these executable arrays should all begin with two + % integers which are the width and height (see gs_setpd.ps). + /11x17 {792 1224 //.setpagesize exec} bind def % 11x17 portrait + /a3 {842 1191 //.setpagesize exec} bind def + /a4 {595 842 //.setpagesize exec} bind def +% a4small should be a4 with an ImagingBBox of [25 25 570 817]. + /a4small /a4 load def +% b5 see below. + /ledger {1224 792 //.setpagesize exec} bind def % 11x17 landscape + /legal {612 1008 //.setpagesize exec} bind def + /letter {612 792 //.setpagesize exec} bind def +% lettersmall should be letter with an ImagingBBox of [25 25 587 767]. + /lettersmall /letter load def +% note should be letter (or some other size) with the ImagingBBox +% shrunk by 25 units on all 4 sides. + /note /letter load def + % End of Adobe-defined page sizes +STRICT { (%END SIZES) .skipeof } if + % Other page sizes + % ISO standard paper sizes + /a0 {2384 3370 //.setpagesize exec} bind def + /a1 {1684 2384 //.setpagesize exec} bind def + /a2 {1191 1684 //.setpagesize exec} bind def +% /a3 {842 1191 //.setpagesize exec} bind def % defined by Adobe +% /a4 {595 842 //.setpagesize exec} bind def % defined by Adobe + /a5 {420 595 //.setpagesize exec} bind def + /a6 {297 420 //.setpagesize exec} bind def + /a7 {210 297 //.setpagesize exec} bind def + /a8 {148 210 //.setpagesize exec} bind def + /a9 {105 148 //.setpagesize exec} bind def + /a10 {73 105 //.setpagesize exec} bind def +% ISO and JIS B sizes are different.... + /isob0 {2835 4008 //.setpagesize exec} bind def + /b0 /isob0 load def + /isob1 {2004 2835 //.setpagesize exec} bind def + /b1 /isob1 load def + /isob2 {1417 2004 //.setpagesize exec} bind def + /b2 /isob2 load def + /isob3 {1001 1417 //.setpagesize exec} bind def + /b3 /isob3 load def + /isob4 {709 1001 //.setpagesize exec} bind def + /b4 /isob4 load def + /isob5 {499 709 //.setpagesize exec} bind def + /b5 /isob5 load def + /isob6 {354 499 //.setpagesize exec} bind def + /b6 /isob6 load def + /jisb0 {2920 4127 //.setpagesize exec} bind def + /jisb1 {2064 2920 //.setpagesize exec} bind def + /jisb2 {1460 2064 //.setpagesize exec} bind def + /jisb3 {1032 1460 //.setpagesize exec} bind def + /jisb4 {729 1032 //.setpagesize exec} bind def + /jisb5 {516 729 //.setpagesize exec} bind def + /jisb6 {363 516 //.setpagesize exec} bind def + /c0 {2599 3677 //.setpagesize exec} bind def + /c1 {1837 2599 //.setpagesize exec} bind def + /c2 {1298 1837 //.setpagesize exec} bind def + /c3 {918 1298 //.setpagesize exec} bind def + /c4 {649 918 //.setpagesize exec} bind def + /c5 {459 649 //.setpagesize exec} bind def + /c6 {323 459 //.setpagesize exec} bind def + % U.S. CAD standard paper sizes + /archE {2592 3456 //.setpagesize exec} bind def + /archD {1728 2592 //.setpagesize exec} bind def + /archC {1296 1728 //.setpagesize exec} bind def + /archB {864 1296 //.setpagesize exec} bind def + /archA {648 864 //.setpagesize exec} bind def + % Other paper sizes + /flsa {612 936 //.setpagesize exec} bind def % U.S. foolscap + /flse {612 936 //.setpagesize exec} bind def % European foolscap + /halfletter {396 612 //.setpagesize exec} bind def + % minimum of a4 and letter (a4 width, letter length) + /pa4 {595 792 //.setpagesize exec} bind def +% /tabloid {792 1224 //.setpagesize exec} bind def % 11x17 portrait +% /csheet {1224 1584 //.setpagesize exec} bind def % ANSI C 17x22 +% /dsheet {1584 2448 //.setpagesize exec} bind def % ANSI D 22x34 +% /esheet {2448 3168 //.setpagesize exec} bind def % ANSI E 34x44 +%END SIZES +end +currentdict /.setpagesize .undef + +statusdict begin + +% Define the pagetype values for the known page formats. +% The values for all but letter and note are arbitrary. +/.pagetypenames + [ /letter /note %do not change this line, needed by 'setpagetype' + /legal /lettersmall + /11x17 /ledger + /a4small /a3 /a4 +STRICT { (%END SIZES) .skipeof } if + /a0 /a1 /a2 /a5 /a6 /a7 /a8 /a9 /a10 + /archA /archB /archC /archD /archE + /b0 /b1 /b2 /b3 /b4 /b5 /b6 + /c0 /c1 /c2 /c3 /c4 /c5 /c6 + /flsa /flse /halfletter + /isob0 /isob1 /isob2 /isob3 /isob4 /isob5 /isob6 + /jisb0 /jisb1 /jisb2 /jisb3 /jisb4 /jisb5 /jisb6 + /pa4 +%END SIZES + ] cvlit readonly def + +%%%%%% The following items were suggested by a user as useful. + +% Permanent definitions + +/ramsize 4194304 def +/hardwareiomode 0 def + /sethardwareiomode {pop} bind def +/softwareiomode 0 def + /setsoftwareiomode {pop} bind def +/dosysstart false def + /setdosysstart {pop} bind def +/allowjobreset true def + /setallowjobreset {pop} bind def +/defaultpaperfamily 0 def + /setdefaultpaperfamily {pop} bind def +/defaultpapertray 0 def + /setdefaultpapertray {pop} bind def +/defaulttrayswitch false def + /setdefaulttrayswitch {pop} bind def + +% Tray and format selection + + /11x17tray {/11x17 .uservar exec} bind def + /a3tray {/a3 .uservar exec} bind def + /a4tray {/a4 .uservar exec} bind def + /a5tray {/a5 .uservar exec} bind def + /a6tray {/a6 .uservar exec} bind def + /b4tray {/b4 .uservar exec} bind def + /b5tray {/b5 .uservar exec} bind def + /flsatray {/flsa .uservar exec} bind def + /flsetray {/flse .uservar exec} bind def + /halflettertray {/halfletter .uservar exec} bind def + /ledgertray {/ledger .uservar exec} bind def + /legaltray {/legal .uservar exec} bind def + /lettertray {/letter .uservar exec} bind def + +% Per-job parameters + +/paperfamily 0 def % 0 is US, 1 is European +/papertray 1 def + /setpapertray {statusdict exch /papertray exch put} bind def +/trayswitch false def % paperout feeds from another tray +% We don't implement the (undocumented by Adobe) papersize 'operator', +% because it's very awkward to make it interact properly with all the +% different ways of setting the paper size. +%/papersize {/letter true} bind def % <name of paper size>, <short-edge-first-p> +/appletalktype (LaserWriter) def + +%%%%%% The following items are defined in the PostScript Language +%%%%%% Reference Manual, First Edition, and subsequent 'compatibility' +%%%%%% documentation from Adobe. + + /checkpassword {statusdict begin .password eq end} bind def + /defaulttimeouts {statusdict begin .timeouts aload pop end} bind def + /diskonline { + false (%disk*%) { pop not exit } 8192 string /IODevice resourceforall + } bind def + /diskstatus {10240 2097152 } bind odef % - diskstatus <free> <total> (in 1024 byte pages) + +%/dostartpage + /eescratch {pop 0} bind def + /idlefonts {statusdict begin mark .idlefonts aload pop end} bind def + /jobname () def +%/jobtimeout + /manualfeed false def + /manualfeedtimeout 60 def + /margins {statusdict begin .topmargin .leftmargin end} bind def + /pagecount {4711} bind def + /pagestackorder {false} bind def + /pagetype 0 def + /prefeed false def + /printererror {pop pop} bind def + /printername {statusdict /.printername get exch copy} bind def + /processcolors /processcolors load def % defined in systemdict + /product product def % product is defined in systemdict + /revision revision def % revision is defined in systemdict + /sccbatch {pop 9600 0} bind def + /sccinteractive {pop 9600 0} bind def + /setdefaulttimeouts {statusdict begin .timeouts astore pop end} bind def + /setdostartpage {statusdict exch /dostartpage exch put} bind def + /setduplexmode {mark /Duplex 3 -1 roll currentdevice putdeviceprops} bind def + /seteescratch {pop pop} bind def + /setidlefonts {] statusdict exch /.idlefonts exch put} bind def + /setjobtimeout {statusdict exch /jobtimeout exch put} bind def + /setmargins + { statusdict begin + /.leftmargin exch def /.topmargin exch def + end + } bind def + +% The following compatibility operators are only documented by Adobe in a +% supplement to the Red Book. +% +% - pagemargin <offset> +% - pageparams <width> <height> <offset> <orientation> +% <width> <height> <orientation> setpage - +% <offset> setpagemargin - +% <width> <height> <offset> <orientation> setpageparams - +% +% width and height are in default units (and if orientation is odd, are +% exchanged!). offset is the x margin, also in default units. +% Unfortunately, because orientation is relative to the device paper feed, +% it does not have a consistent meaning in terms of image orientation. +% We follow the convention that ORIENT1 determines the orientation value +% that means portait: false means 0, true means 1. + + /pagemargin { 0 } bind def + /pageparams + { currentdevice 1 dict dup /.MediaSize dup put .getdeviceparams + exch pop exch pop aload pop 0 ORIENT1 { 1 } { 0 } ifelse + } bind def + /setpage + { ORIENT1 { 1 } { 0 } ifelse ne {exch} if + statusdict /.setpagesize get exec + } bind def + /setpagemargin {pop} bind def % can't do better without setpagedevice + /setpageparams + { exch pop ORIENT1 { 1 } { 0 } ifelse ne {exch} if + statusdict /.setpagesize get exec + } bind def + /setpagetype + { statusdict begin + % The Adobe documentation only defines setpagetype + % (a Level 1 operator) as accepting the values 0 and 1, + % so we do too. + dup .pagetypenames 0 2 getinterval exch get + //systemdict /userdict get exch get cvx exec + /pagetype exch def + end + } bind def + /setpassword + {exch checkpassword + {statusdict exch /.password exch put true} + {pop false} + ifelse} bind def + /setprintername + {dup length string copy statusdict exch /.printername exch put} bind def + +% setresolution is not documented by Adobe, but some applications +% use it anyway, without testing whether or not it is present. +% +% <pixels_per_inch> setresolution - +% +% sets the resolution of the device. + + /setresolution + { mark /HWResolution [ 4 -1 roll dup ] currentdevice putdeviceprops pop + initmatrix erasepage + } bind def + /setsccbatch {pop pop pop} bind def + /setsccinteractive {pop pop pop} bind def + /settumble {pop} bind def + /waittimeout 300 def + +%%%%%% End of documented items. + +/.setpagesize + { mark /HWSize [ + 4 index 4 index matrix defaultmatrix dtransform + abs ceiling cvi exch abs ceiling cvi exch + ] currentdevice putdeviceprops pop pop pop + initmatrix initclip erasepage + } bind def +/.password 0 def +/.timeouts [0 60 30] def +true setdostartpage +mark setidlefonts +0 setjobtimeout +0 0 setmargins +product setprintername + +end % statusdict + +%%%%%% The following documented compatibility "operators" are in systemdict, +%%%%%% not in statusdict. + +systemdict begin +.currentglobal true .setglobal + +/devformat true def +/devforall { % <pattern> <proc> <scratch> devforall - + exch { + 1 index currentdevparams + /Type .knownget { /FileSystem eq } { false } ifelse + { exec } { pop pop } ifelse + } /exec load 3 packedarray cvx exch + (*) 3 1 roll /IODevice resourceforall +} odef + +/devstatus { % <(%disk*%)> devstatus <searchable> <writable> + % <hasNames> <mounted> <removable> <searchOrder> + % <freePages> <size> true + % <string> devstatus false + dup length 5 ge { + dup 0 5 getinterval (%disk) eq { + dup /IODevice resourcestatus { + pop pop dup currentdevparams + dup /Searchable get + exch dup /Writeable get + exch dup /HasNames get + exch dup /Mounted get + exch dup /Removable get + exch dup /SearchOrder get + exch dup /Free get + exch /LogicalSize get + 9 -1 roll pop true + } { + pop false + } ifelse + } { + pop false + } ifelse + } { + pop false + } ifelse +} odef + +.setglobal end % systemdict + +% The following contents of serverdict are a complete guess, +% based on some observed LaserWriter boilerplate. + +serverdict begin + + /execjob { } bind def +% The Red Book implies that something like the following is +% an appropriate definition of exitserver. + /exitserver { clear stop } bind def +% However, this interacts badly with our standard error handler, +% so we override it with the following less appropriate definition. + /exitserver { 0 ne { clear cleardictstack } if } bind def + /setrealdevice { } bind def + +end % serverdict diff --git a/gs/Resource/Init/gs_std_e.ps b/gs/Resource/Init/gs_std_e.ps new file mode 100644 index 000000000..4e1aa10e6 --- /dev/null +++ b/gs/Resource/Init/gs_std_e.ps @@ -0,0 +1,73 @@ +% Copyright (C) 1993, 1994 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the standard encoding vector. +/StandardEncoding +% \00x + /.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 +% \04x + /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 +% \10x + /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 +% \14x + /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 +% \20x + /.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 +% \24x + /.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 +% \30x + /.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 +% \34x + /.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 +% Make an array on large systems, a packed array on small ones. +256 +vmstatus exch pop exch pop +100000 ge { array astore readonly } { packedarray } ifelse +def +0 StandardEncoding .registerencoding +/StandardEncoding StandardEncoding .defineencoding diff --git a/gs/Resource/Init/gs_sym_e.ps b/gs/Resource/Init/gs_sym_e.ps new file mode 100644 index 000000000..453949c84 --- /dev/null +++ b/gs/Resource/Init/gs_sym_e.ps @@ -0,0 +1,83 @@ +% Copyright (C) 1991, 1994, 1998, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the Symbol encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/SymbolEncoding +% \000 + StandardEncoding 0 32 getinterval aload pop % /.notdef +% \040 + /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 +% \100 + /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 +% \140 + /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 /.notdef +% \200 + StandardEncoding 0 32 getinterval aload pop % /.notdef +% \240 + /Euro /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 +% \300 + /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 +% \340 + /lozenge /angleleft /registersans /copyrightsans + /trademarksans /summation /parenlefttp /parenleftex + /parenleftbt /bracketlefttp /bracketleftex /bracketleftbt + /bracelefttp /braceleftmid /braceleftbt /braceex + /.notdef /angleright /integral /integraltp + /integralex /integralbt /parenrighttp /parenrightex + /parenrightbt /bracketrighttp /bracketrightex /bracketrightbt + /bracerighttp /bracerightmid /bracerightbt /.notdef +256 packedarray .defineencoding +2 SymbolEncoding .registerencoding +exec diff --git a/gs/Resource/Init/gs_trap.ps b/gs/Resource/Init/gs_trap.ps new file mode 100644 index 000000000..f91090c31 --- /dev/null +++ b/gs/Resource/Init/gs_trap.ps @@ -0,0 +1,103 @@ +% Copyright (C) 1999, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% PostScript LanguageLevel 3 in-RIP trapping support. + +ll3dict begin + +% We need LanguageLevel 2 or higher in order to have setuserparams and +% defineresource. +languagelevel dup 2 .max .setlanguagelevel + +% ------ Trapping ------ % + +% The PostScript-level trapping parameters are maintained in userdict, +% and explicitly reinstalled upon restore. + +/Trapping mark + +/settrapparams dup { % <paramdict> settrapparams - + /.trapparams .uservar dup length dict .copydict + dup 2 index { + % Stack: paramdict olddict olddict key value + 2 index 2 index known { put dup } { pop pop } ifelse + } forall pop + dup .settrapparams % Let the operator check parameter validity. + .userdict /.trapparams 3 -1 roll put pop +} bind .makeoperator + +/.copyparams { % <obj> .copyparams <obj'> + dup type /dicttype eq { + dup length dict .copydict + dup { + .copyparams 3 copy put pop pop + } forall + } { + dup type /arraytype eq { + [ exch { .copyparams } forall ] + } if + } ifelse +} odef + +/currenttrapparams dup { % - currenttrapparams <paramdict> + /.trapparams .uservar .copyparams +} bind .makeoperator + +/settrapzone dup { % - settrapzone - + % ****** DUMMY ****** + newpath +} bind .makeoperator + +% Define initial (dummy) trapping parameters. +% These values are mostly complete guesses. +userdict /.trapparams mark + /BlackColorLimit 1.0 + /BlackDensityLimit 1.0 + /BlackWidth 1.0 + /ColorantZoneDetails 0 dict + /Enabled true + /HalftoneName null + /ImageInternalTrapping false + /ImagemaskTrapping true + /ImageResolution 1 + /ImageToObjectTrapping true + /ImageTrapPlacement /Center + /SlidingTrapLimit 1.0 + /StepLimit 1.0 + /TrapColorScaling 0.0 + /TrapSetName null + /TrapWidth 1.0 +.dicttomark readonly put + +.dicttomark /ProcSet defineresource pop + +% Define the InkParams and TrapParams resource categories. +{ /InkParams /TrapParams } { + /Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /dicttype def + currentdict end /Category defineresource pop +} forall + +% Define the TrappingType resource category. +/Generic /Category findresource dup maxlength 3 add dict .copydict begin + /InstanceType /integertype def +/TrappingType currentdict end /Category defineresource pop + +{1001} { dup /TrappingType defineresource pop } forall + +.setlanguagelevel + +end % ll3dict diff --git a/gs/Resource/Init/gs_ttf.ps b/gs/Resource/Init/gs_ttf.ps new file mode 100644 index 000000000..c56371c16 --- /dev/null +++ b/gs/Resource/Init/gs_ttf.ps @@ -0,0 +1,1947 @@ +% Copyright (C) 1996-2003 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Support code for direct use of TrueType fonts. +% (Not needed for Type 42 fonts.) + +% Note that if you want to use this file without including the ttfont.dev +% option when you built Ghostscript, you will need to load the following +% files before this one: +% lib/gs_mgl_e.ps +% lib/gs_mro_e.ps +% lib/gs_wan_e.ps + +% Thanks to B. Jackowski and GUST (the Polish TeX Users' Group) for +% the glyf-splitting code. + +% ---------------- Font loading machinery ---------------- % + +% Augment the FONTPATH machinery so it recognizes TrueType fonts. + +/.scanfontheaders where { + pop /.scanfontheaders [ + .scanfontheaders aload pop (\000\001\000\000*) (true*) + ] def +} if + +% <file> <key> .findfontvalue <value> true +% <file> <key> .findfontvalue false +% Closes the file in either case. +/.findnonttfontvalue /.findfontvalue load def +/.findfontvalue { + 1 index read { + 2 index 1 index unread + % beginning with binary 0 or 't' (TrueType), or 'O' (OpenType) + dup 0 eq 1 index (O) 0 get eq or exch (t) 0 get eq or { + % If this is a font at all, it's a TrueType font. + dup /FontType eq { + pop closefile 42 true + } { + dup /FontName eq { pop .findttfontname } { pop closefile false } ifelse + } ifelse + } { + % Not a TrueType font. + .findnonttfontvalue + } ifelse + } { pop closefile false } ifelse +} bind def + +% <file> .findttfontname <fname> true +% <file> .findttfontname false +% Closes the file in either case. +/.findttfontname { + //true 0 .loadttfonttables + tabdict /name .knownget { + dup 8 getu32 f exch setfileposition + 12 getu32 string f exch readstring pop + dup + 6 findname not { + 4 findname % Try FullName + } { + exch pop true + } + ifelse + } { + false + } ifelse + f closefile end end +} bind def + +% Load a font file that might be a TrueType font. + +/tt_tag_dict << <00010000> 0 (true) 0 (typ1) 0 (ttcf) 0 >> readonly def + +% <file> .loadfontfile - +/.loadnonttfontfile /.loadfontfile load def +/.loadfontfile { + dup (1234) .peekstring { //tt_tag_dict exch known } { //false } ifelse { + % If this is a font at all, it's a TrueType font. + .loadttfont pop + } { + % Not a TrueType font. + .loadnonttfontfile + } ifelse +} bind def + +currentdict /tt_tag_dict .undef + +% ---------------- Automatic Type 42 generation ---------------- % + +% Load a TrueType font from a file as a Type 42 PostScript font. +% The thing that makes this really messy is the handling of encodings. +% There are 2 interacting tables that affect the encoding: +% 'cmap' provides multiple maps from character codes to glyph indices +% 'post' maps glyph indices to glyph names (if present) +% What we need to get out of this is: +% Encoding mapping character codes to glyph names +% (the composition of cmap and post) +% CharStrings mapping glyph names to glyph indices +% (the inverse of post) +% If the post table is missing, we have to take a guess based on the cmap +% table. + +/.loadttfontdict 50 dict dup begin + +/orgXUID AladdinEnterprisesXUID def +/maxstring 32764 def % half the maximum length of a PostScript string, + % must be a multiple of 4 (for hmtx / loca / vmtx) + +/.invert_encoding % <array> invert_encoding <dict> +{ dup 256 dict exch + 0 exch 1 exch length 1 sub { % [] <> i + dup 3 index exch get % [] <> i v + dup /.notdef ne { + exch 2 index 2 index .knownget { + dup type /arraytype eq { + [ exch aload pop counttomark 2 add -1 roll ] + } { + exch 2 array astore + } ifelse + } if 2 index 3 1 roll put + } { + pop pop + } ifelse + } for + exch pop +} bind def + +% Make /MacRomanEncodingForTrueType including additional +% characters in Mac OS Roman encoding, which is missing +% in /MacRomanEncoding. See PDF spec 1.7, p. 431 or +% "Inside Macintosh: Text" 1-55, Figure 1-36. +% This is useful to exploit the glyphs via Apple Roman +% TrueType cmap subtable, but not appropriate for information +% interchange. + +/MacRomanEncodingForTrueType + /MacRomanEncoding .findencoding + dup length array copy + << + /notequal 173 + /infinity 176 + /lessequal 178 + /greaterequal 179 + /partialdiff 182 + /summation 183 + /product 184 + /pi 185 + /integral 186 + /Omega 189 + /radical 195 + /approxequal 197 + /Delta 198 + /lozenge 215 + /Euro 219 + /apple 240 + >> { + TTFDEBUG { (Extend MacRomanEncodingForTrueType for TrueType: ) =only } if + + % check /.notdef to avoid overwriting + 2 index 1 index get dup /.notdef eq { + TTFDEBUG { (insert /) =only 2 index =only ( @ ) =only 1 index == } if + pop + exch 2 index 3 1 roll put + } { + TTFDEBUG { (cannot insert /) =only 2 index =only ( @ ) =only 1 index =only ( used for ) =only dup == } if + pop + pop pop + } ifelse + } forall + aload pop + 256 packedarray + 5 1 index .registerencoding +.defineencoding + +% Define the Macintosh standard mapping from characters to glyph indices. +/MacRomanEncoding dup .findencoding def +/MacGlyphEncoding dup .findencoding def +/MacRomanEncodingForTrueType dup .findencoding def + +% Invert the MacRomanEncoding. +/.romanmacdict MacRomanEncodingForTrueType .invert_encoding def +/.latin1isodict ISOLatin1Encoding .invert_encoding def + +% Define remapping for misnamed glyphs in TrueType 'post' tables. +% There are probably a lot more than this! +% Also see /postalias table below. +/postremap mark + /Eoverdot /Edotaccent + /eoverdot /edotaccent +.dicttomark readonly def + +% Array used for fast pre-filling of cmap array +/.array1024z [ 1024 { 0 } repeat ] def + +% ---- Utilities ---- % + +% Define a serial number for creating unique XUIDs for TrueType fonts. +% We used to use the checkSumAdjustment value from the font, but this is +% not reliable, since some fonts don't set it correctly. +% Note that we must do this in a string to make it immune to save/restore. +/xuidstring <80000000> def +/curxuid { % - curxuid <int> + 0 xuidstring { exch 8 bitshift exch add } forall +} bind def +/nextxuid { % - nextxuid - + 3 -1 0 { + xuidstring 1 index 2 copy get dup 255 ne { + 1 add put pop exit + } if pop 0 put pop + } for +} bind def + +% <string> <index> getu16 <integer> +/getu16 { + 2 copy get 8 bitshift 3 1 roll 1 add get add +} bind def + +% <string> <index> gets16 <integer> +/gets16 { + getu16 16#8000 xor 16#8000 sub +} bind def + +% <string> <index> getu32 <integer> +/getu32 { + 2 copy getu16 16 bitshift 3 1 roll 2 add getu16 add +} bind def + +% <string> <index> gets32 <integer> +/gets32 { + 2 copy gets16 16 bitshift 3 1 roll 2 add getu16 add +} bind def + +% <string|array> <index> getu16 <integer> +/getu16a { + 2 getinterval_from_stringarray 0 getu16 +} bind def + +% <string|array> <index> gets16 <integer> +/gets16a { + 2 getinterval_from_stringarray 0 gets16 +} bind def + +% <string|array> <index> getu32a <integer> +/getu32a { + 4 getinterval_from_stringarray 0 getu32 +} bind def + +% <string|array> <index> gets32a <integer> +/gets32a { + 4 getinterval_from_stringarray 0 gets32 +} bind def + +16#ffffffff 0 gt { % 64-bit sign extension + { /curxuid /gets32 /gets32a} { + mark 1 index load aload pop { 16#80000000 xor 16#80000000 sub } aload pop + .packtomark cvx def + } bind forall +} if + +% <string> <index> <integer> putu16 - +/putu16 { + 3 copy -8 bitshift put + exch 1 add exch 16#ff and put +} bind def + +% <string> <index> <integer> putu32 - +/putu32 { + 3 copy -16 bitshift putu16 + exch 2 add exch 16#ffff and putu16 +} bind def + +% <nametable> <nameid> findname <string> true +% <nametable> <nameid> findname false +/findname { + TTFDEBUG { (findname: ) print dup =only } if + false 3 1 roll + 1 index length 0 gt { % check for zero length name table + 0 1 3 index 2 getu16 1 sub { + % Stack: false table id index + 12 mul 6 add 2 index exch 12 getinterval + dup 6 getu16 2 index eq { + % We found the name we want. + exch pop + % Stack: false table record + dup 10 getu16 2 index 4 getu16 add + 1 index 8 getu16 4 -1 roll 3 1 roll + 3 copy add 1 index length + le { + pop + getinterval exch + % Stack: false string record + % Check for 8- vs. 16-bit characters. + is2byte { true } { dup is2byte2 } ifelse { string2to1 } if true null 4 -1 roll exit + } { + pop pop pop pop + false + exit + } ifelse + } if pop + } for + } if + pop pop + TTFDEBUG { + dup { ( = ) print 1 index == } { ( not found) = } ifelse + } if +} bind def + +% <namerecord> is2byte <bool> +/is2byte { + dup 0 getu16 { + { pop true } % Apple Unicode + { pop false } % Macintosh Script manager + { 1 getu16 1 eq } % ISO + { 1 getu16 1 eq } % Microsoft + } exch get exec +} bind def + +% <string> is2byte2 <bool> +/is2byte2 { + dup length + dup 2 mod 0 ne { + pop pop false + } { % s l + true exch % s b l + 1 sub 0 exch 2 exch { + 2 index exch get 0 ne { + pop false exit + } if + } for + exch pop + } ifelse +} bind def + +% <string2> string2to1 <string> +/string2to1 { + dup length 2 idiv string dup + 0 1 3 index length 1 sub { + 3 index 1 index 2 mul 1 add get put dup + } for pop exch pop +} bind def + +% Each procedure in this dictionary is called as follows: +% <encodingtable> proc <glypharray> +/cmapformats mark + 0 { % Apple standard 1-to-1 mapping. + 6 256 getinterval_from_stringarray + mark 0 3 -1 roll + { 1 index 1 add } forall pop + .dicttomark + } bind + 2 { % Apple 16bit CJK (ShiftJIS etc) + + % /sHK_sz subHeaderKey_size % 1 * uint16 + % /sH_sz subHeader_size % 4 * uint16 + % /sH_len subHeader_length + % /cmapf2_tblen total table length + % /cmapf2_lang language code (not used) + % /sHKs subHeaderKeys + + /sHK_sz 2 def + /sH_sz 8 def + dup 2 getu16a /cmapf2_tblen exch def + + dup 4 getu16a /cmapf2_lang exch def + + dup 6 256 sHK_sz mul getinterval_from_stringarray /sHKs exch def + + 0 % initialization value for /sH_len + 0 1 255 { + sHKs exch + 2 mul getu16 + 1 index % get current max + 1 index % get current subHeaderKey + lt {exch} if pop + } for + /sH_len exch def + + dup 6 256 sHK_sz mul add + cmapf2_tblen 1 index sub getinterval_from_stringarray + /sH_gIA exch def + + /cmapf2_glyph_array 0 dict def + + /.cmapf2_putGID { + /cmapf2_ch cmapf2_ch_hi 8 bitshift cmapf2_ch_lo add def + firstCode cmapf2_ch_lo le + cmapf2_ch_lo firstCode entryCount add lt + and { % true: j is inside + sH_offset idRangeOffset add % offset to gI + cmapf2_ch_lo firstCode sub 2 mul % rel. pos. in range + add 6 add % offset in sH_gIA + sH_gIA exch getu16 + dup 0 gt { % + idDelta add + cmapf2_glyph_array exch cmapf2_ch exch put + } { + pop + % cmapf2_glyph_array cmapf2_ch 0 put + } ifelse + } { % false: j is outside + % cmapf2_glyph_array cmapf2_ch 0 put + } ifelse + } def + + 16#00 1 16#ff { % hi_byte scan + /cmapf2_ch_hi exch def + sHKs cmapf2_ch_hi sHK_sz mul getu16 + /sH_offset exch def + sH_gIA sH_offset sH_sz getinterval + dup 0 getu16 /firstCode exch def + dup 2 getu16 /entryCount exch def + dup 4 gets16 /idDelta exch def + dup 6 getu16 /idRangeOffset exch def + pop + sH_offset 0 eq { + /cmapf2_ch_lo cmapf2_ch_hi def + /cmapf2_ch_hi 0 def + .cmapf2_putGID + } { + 16#00 1 16#ff { % lo_byte scan + /cmapf2_ch_lo exch def + .cmapf2_putGID + } for + } ifelse + } for + pop + cmapf2_glyph_array + } bind + 4 { % Microsoft/Adobe segmented mapping. + /etab exch def + /nseg2 etab 6 getu16 def + 14 /endc etab 2 index nseg2 getinterval_from_stringarray def + % The Apple TrueType documentation omits the 2-byte + % 'reserved pad' that follows the endCount vector! + 2 add + nseg2 add /startc etab 2 index nseg2 getinterval_from_stringarray def + nseg2 add /iddelta etab 2 index nseg2 getinterval_from_stringarray def + nseg2 add /idroff etab 2 index nseg2 getinterval_from_stringarray def + % The following hack allows us to properly handle + % idiosyncratic fonts that start at 0xf000: + pop + /firstcode startc 0 getu16 16#ff00 and dup 16#f000 ne { pop 0 } if def + /putglyph { + glyphs code 3 -1 roll put /code code 1 add def + } bind def + % Do a first pass to compute the size of the glyphs array. + /numcodes 0 def + /glyphs 0 dict def + 0 0 2 nseg2 3 sub { + % Stack: /glyphs numglyphs i2 + /i2 exch def + /scode startc i2 getu16 def + /ecode endc i2 getu16 def + numcodes scode firstcode sub + % Hack for fonts that have only 0x0000 and 0xf000 ranges + %dup 16#e000 ge { 255 and } if + % the previous line is obstructive to CJK fonts, so it was removed + exch sub 0 .max ecode scode sub 1 add add + exch 1 index add exch + numcodes add /numcodes exch def + } for pop + + % Now fill in the array. + /numcodes 0 def /code 0 def + 0 2 nseg2 3 sub { + /i2 exch def + /scode startc i2 getu16 def + /ecode endc i2 getu16 def + numcodes scode firstcode sub + % Hack for fonts that have only 0x0000 and 0xf000 ranges + %dup 16#e000 ge { 255 and } if + % the previous line is obstructive to CJK fonts, so it was removed + exch sub 0 .max dup /code exch code exch add def + ecode scode sub 1 add add numcodes add /numcodes exch def + /delta iddelta i2 gets16 def + TTFDEBUG { + (scode=) print scode =only + ( ecode=) print ecode =only + ( delta=) print delta =only + ( droff=) print idroff i2 getu16 = + } if + idroff i2 getu16 dup 0 eq { + pop scode delta add 65535 and 1 ecode delta add 65535 and + { putglyph } for + } { % The +2 is for the 'reserved pad'. + /gloff exch 14 nseg2 3 mul add 2 add i2 add add def + 0 1 ecode scode sub { + 2 mul gloff add etab exch getu16a + dup 0 ne { delta add 65535 and } if putglyph + } for + } ifelse + } for glyphs /glyphs null def % for GC + } bind + 6 { % Single interval lookup. + dup 6 getu16a /firstcode exch def + dup 8 getu16a /ng exch def + firstcode ng add dict + % Stack: tab array + % Fill elements 0 .. firstcode-1 with 0 + 0 1 firstcode 1 sub { 2 copy 0 put pop } for + dup + % Stack: tab dict dict + % Fill elements firstcode .. firstcode+nvalue-1 with glyph values + 0 1 ng 1 sub { + dup firstcode add exch + 2 mul 10 add 4 index exch getu16a 3 copy put pop pop + } for pop exch pop + } bind +.dicttomark readonly def % cmapformats + +% <cmaptab> cmaparray <glypharray> +/cmaparray { + dup 0 getu16a cmapformats exch .knownget { + TTFDEBUG { + (cmap: format ) print 1 index 0 getu16a = flush + } if exec + } { + (Can't handle format ) print 0 getu16a = flush + mark 0 1 255 { dup } for .dicttomark + } ifelse + TTFDEBUG { + (cmap: length=) print dup length = dup === + } if +} bind def + +/get_from_stringarray % <array|string> <offset> get_from_stringarray <int> +{ 1 index type /stringtype eq { + get + } { + exch { % o () + 2 copy length ge { + length sub + } { + exch get exit + } ifelse + } forall + } ifelse +} bind def + +/getinterval_from_stringarray % <array|string> <offset> <length> getinterval_from_stringarray <string> +{ % May allocate a string in VM. + 2 index type /stringtype eq { + getinterval + } { + string exch 0 % [] s o p + 4 3 roll { % s o p Si + dup length % s o p Si lSi + dup 4 index lt { + 3 index exch sub % s o p Si o' + exch pop 3 1 roll exch pop % s o' p + } { % s o p Si lSi + dup 3 1 roll % s o p lSi Si lSi + 4 index sub % s o p lSi Si lSi-o + 5 index length 4 index sub % s o p lSi Si lSi-o ls-p + 2 copy gt { exch } if pop % s o p lSi Si minl + dup 3 1 roll % s o p lSi minl Si minl + 5 index exch getinterval % s o p lSi minl from + 5 index 4 index 3 index % s o p lSi minl from s p minl + getinterval % s o p lSi minl from to + copy pop % s o p lSi minl + exch pop add exch pop 0 exch % s 0 p' + dup 3 index length ge { exit } if + } ifelse + } forall + pop pop % s + } ifelse +} bind def + +/string_array_size % <array|string> string_array_size <int> +{ dup type /stringtype eq { + length + } { + 0 exch { length add } forall + } ifelse +} bind def + +% Each procedure in this dictionary is called as follows: +% posttable <<proc>> glyphencoding +/postformats mark + 16#00010000 { % 258 standard Macintosh glyphs. + pop MacGlyphEncoding + } + 16#00020000 { % Detailed map, required by Microsoft fonts. + dup dup type /arraytype eq { 0 get } if length 36 lt { + TTFDEBUG { (post format 2.0 invalid.) = flush } if + pop [ ] + } { + /postglyphs exch def + /post_first postglyphs dup type /arraytype eq { 0 get } if def + post_first 32 getu16 /numglyphs exch def + /glyphnames numglyphs 2 mul 34 add def + % Build names array in the order they occur in the 'post' table + /postpos glyphnames def + /total_length postglyphs //string_array_size exec def + numglyphs array 0 1 numglyphs 1 sub { + postpos total_length ge { + % Fill the rest with .notdef + 1 numglyphs 1 sub { 1 index exch /.notdef put } for + exit + } if + % No name available, /postnames will be defined as an empty + % array and the glyph won't get a name attached. + postglyphs postpos //get_from_stringarray exec + postglyphs postpos 1 add 2 index //getinterval_from_stringarray exec cvn + exch postpos add 1 add /postpos exch def + 2 index 3 1 roll + put + } for + /postnames exch def + + % Some TrueType fonts converted by "Windows Type 1 Installer" have + % problematic post table including MacGlyphEncoding entries which + % should be omitted. Such extra entries in the beginning of glyphName + % array make /Encoding broken. If we find populary predefined + % ISOLatin1Encoding glyph name in the post table, empty encoding is + % returned. Some TrueType fonts for Microsoft Windows redefines + % MacGlyphEncoding glyph name out of predefined range). To permit + % such fonts, ISOLatin1Encoding is used to find broken post. Bug 689495. + /.broken_post //false def + tabdict /name .knownget { + (Windows Type 1 Installer V1.0) search { + pop pop pop + .latin1isodict postnames { + dup /.notdef ne { + 2 copy known { + TTFDEBUG { (ignore post table that redefines ISOLatin1Encoding glyph name ) print dup == flush } if + /.broken_post //true def + pop exit + } if + } if + pop + } forall + pop + } { + pop + } ifelse + } if + + numglyphs array 0 1 numglyphs 1 sub { + dup 2 mul 34 add postglyphs exch 2 //getinterval_from_stringarray exec + dup 0 get 8 bitshift exch 1 get add dup 258 lt { + MacGlyphEncoding exch get + } { + dup 32768 ge { + % According to the published TrueType spec, such values are + % "reserved for future use", but at least some PDF files + % produced by the Adobe PDF library contain entries with a + % value of 16#ffff. + pop /.notdef + } { + % Get the name for this glyph + 258 sub dup postnames length ge { + TTFDEBUG { ( *** warning: glyph index past end of 'post' table) = flush } if + pop + exit + } if + postnames exch get + % At least some of Microsoft's TrueType fonts use incorrect + % (Adobe-incompatible) names for some glyphs. + % Correct for this here. + postremap 1 index .knownget { exch pop } if + } ifelse + } ifelse + 2 index 3 1 roll put + } for + + .broken_post { + pop + [ postnames aload length 1 roll ] + } if + } + ifelse + } bind + 16#00030000 { % No map. + pop [ ] + } bind +.dicttomark readonly def % postformats + +/call.readtable +{ .readtable +} bind def +/call.readbigtable +{ .readbigtable +} bind def + +% Each procedure in this dictionary is called as follows: +% <file> <length> -proc- <string|array_of_strings> +% Note that each table must have an even length, because of a strange +% Adobe requirement that each sfnts entry have even length. +/readtables mark + % Ordinary tables + (head) //call.readtable + (hhea) 1 index + (maxp) 1 index + (name) 1 index + (OS/2) 1 index + (post) //call.readbigtable + (vhea) //call.readtable + % Big tables + (cmap) //call.readbigtable + (glyf) 1 index + (loca) 1 index + (hmtx) 1 index + (vmtx) 1 index + % Tables only needed for embedding in PDF files + (cvt ) //call.readtable + (fpgm) 1 index + (prep) 1 index +.dicttomark +% Normally there would be a 'readonly' here, but the ttf2pf utility wants +% to include the 'kern' table as well, so we leave the readtables dictionary +% writable. +def % readtables + +/readtables_stripped readtables dup length dict copy +dup (loca) { .skiptable } put +dup (glyf) { .skiptable } put +def + +% Read a table as a single string. +% <file> <length> .skiptable <string> +/.skiptable { + pop pop () +} bind def + +% Read a table as a single string. +% <file> <length> .readtable <string> +/.readtable { + dup dup 1 and add string + % Stack: f len str + dup 0 4 -1 roll getinterval + % Stack: f str str1 + % Because of the absurd PostScript specification that gives an + % error for reading into an empty string, we have to check for + % this explicitly here. + 3 -1 roll exch + dup () ne { readstring } if pop pop +} bind def + +% Read a big table (one that may exceed 64K). +% <file> <length> .readbigtable <string[s]> +/.readbigtable { + dup 65400 lt { + .readtable + } { + currentuserparams /VMReclaim get -2 vmreclaim + [ 4 2 roll { + % Stack: mark ... f left + dup maxstring le { exit } if + 1 index maxstring string readstring pop 3 1 roll maxstring sub + } loop .readtable ] + exch vmreclaim + } ifelse +} bind def + +end readonly def % .loadttfontdict + +% <tab> .printtab - +/.printtab { + dup 0 4 getinterval print ( ) print + dup 8 getu32 =only ( ) print + 12 getu32 = +} bind def + +% <file> <bool> <SubfontID> .loadttfonttables - +% Pushes .loadttfontdict & scratch dict on d-stack. +% Defines f, offsets, tables, tabdict, tabs. +% Skips loca and glyf if <bool> is true. +/.loadttfonttables { + .loadttfontdict begin + 40 dict begin + /SubfontID exch def + /load_stripped exch def + /f exch def + /offsets f 12 string readstring pop def + load_stripped { readtables_stripped } { readtables } ifelse /readtables_ exch def + offsets 0 4 getinterval (ttcf) eq { + % We need to handle TT collections with disk fonts only. + % Therefore the file is a disk file and it can be positioned. + offsets 8 getu32 /num_fonts exch def + SubfontID num_fonts ge { + QUIET not { (True Type collection contains insufficient fonts.) = } if + /.loadttfonttables cvx /invalidfont signalerror + } if + SubfontID 4 mul 12 add f exch setfileposition + f 4 string readstring pop 0 + getu32 /ttc_offset exch def + f ttc_offset setfileposition + /offsets f 12 string readstring pop def + } { + SubfontID 0 gt { + QUIET not { (SubfontID > 0 with a True Type file which is not a collection.) = } if + /.loadttfonttables cvx /invalidfont signalerror + } if + /ttc_offset 0 def + } ifelse + /tables f offsets 4 getu16 16 mul string readstring pop def + /tabdict tables length 16 idiv dict def + % tabs = tables we want to keep, sorted by file position. + /tabs [ 0 16 tables length 1 sub { + tables exch 16 getinterval + TTFDEBUG { dup .printtab } if + dup 0 4 getinterval readtables_ 1 index known { + % put all 0 length tables at 0 to avoid overlap + 1 index 12 getu32 0 eq { 1 index 8 0 putu32 } if + tabdict exch 2 index put + } { + pop pop + } ifelse + } for ] { + exch 8 getu32 exch 8 getu32 lt + } .sort def + % In certain malformed TrueType fonts, tables overlap. + % Truncate tables if necessary. + 0 1 tabs length 2 sub { + dup tabs exch get exch 1 add tabs exch get + 1 index 8 getu32 2 index 12 getu32 add + 1 index 8 getu32 gt { + (**** Warning: ) print 1 index 0 4 getinterval print + ( overlaps ) print dup 0 4 getinterval print + (, truncating.) = flush + dup 8 getu32 2 index 8 getu32 sub + 2 index 12 3 -1 roll putu32 + } if pop pop + } for +} bind def + +/.file_table_pos_names +mark +/glyf 0 +/loca 0 +.dicttomark readonly def + +% - .readttdata - +% Read data. Updates offsets, tabs; stores data in tabdict. +/.readttdata { + /file_table_pos 10 dict def + /fpos offsets length tables length add ttc_offset add def + /sfpos offsets length tabs length 16 mul add def + offsets 4 tabs length putu16 + tabs { + dup 0 4 getinterval /tname exch def + dup 8 getu32 /tpos exch def + dup 12 getu32 /tlen exch def + load_stripped //.file_table_pos_names tname known and { + pop + file_table_pos tname [tpos tlen] put + tabdict tname () put + } { + 8 sfpos putu32 + % Skip data between the end of the previous table and + % the beginning of this one, if any. + tpos fpos gt { + load_stripped { + % 'setfileposition' is faster for skipping a big data. + f tpos setfileposition + } { + f tpos fpos sub () /SubFileDecode filter dup flushfile closefile + /fpos tpos def + } ifelse + } if + f tlen readtables_ tname get exec + tabdict tname 3 -1 roll put + % Round up the table length to an even value. + /sfpos sfpos tlen dup 1 and add add def + } ifelse + /fpos fpos tlen add def + } forall +} bind def + +% Find the string in a list of strings that includes a given index. +% <strings> <index> .findseg <string> <index'> +/.findseg { + exch { + dup length 2 index gt { exch exit } if + length sub + } forall +} bind def + +% - .makesfnts - +% Defines checksum, getloca, head, locatable, numloca, post, sfnts, upem +% Note that the 'loca' table may be out of order. This is handled when +% needed in .dividesfnts +/.makesfnts { + .readttdata + /head tabdict /head get def + /post tabdict /post .knownget { + dup 0 get /post_first_part exch def + } { + null + } ifelse def + load_stripped not { + /locatable tabdict /loca get def + /numloca + locatable dup type /stringtype eq + { length } + { 0 exch { length add } forall } + ifelse % no def yet + locatable type /stringtype eq { + /.indexloca {} def + } { + /.indexloca /.findseg load def + } ifelse + head 50 getu16 0 ne { + /getloca { + 2 bitshift locatable exch .indexloca getu32 + } def + 4 idiv 1 sub + } { + /getloca { + dup add locatable exch .indexloca getu16 dup add + } def + 2 idiv 1 sub + } ifelse def % numloca + % If necessary, re-partition the glyfs. + tabdict /glyf get dup type /stringtype ne { + .dividesfnts tabdict /glyf 3 -1 roll put + } { + pop + } ifelse + } { + % We did not load loca, take the number of glyphs from maxp. + /numloca tabdict /maxp get 4 getu16 def + } ifelse + /sfnts [ + offsets tabs { concatstrings } forall + tabs { + 0 4 getinterval tabdict exch get + dup type /stringtype ne { aload pop } if + } forall + ] def +} bind def + +% <glyfs> .dividesfnts <glyfs'> +/.dividesfnts { + /glyfs exch def + /len1 0 glyfs { length add } forall def + % Determine where to split the glyfs by scanning the sorted locatable + % The very last entry in loca may be bogus. + % Note that some loca entries may be odd, but we can only + % split at even positions. + % + % Construct splitarray, the array of final lengths of + % the sfnts entries covering the glyfs (i.e., all but + % the first and last sfnts entries). + /prevsplit 0 def + /prevboundary 0 def + % sort the locatable in case it is out of order + % Note the 'loca' table remains unchanged + /needsort false def + numloca array % the array of 'loca' entries (may be out of order) + -1 % initial values for in order check + 0 1 numloca 1 sub { + dup getloca dup + 4 -1 roll lt { /needsort true def } if + 3 copy put exch pop + } for pop % discard inorder check value + needsort { + { lt } bind .sort % stack: locatable_array + } if + /splitarray [ + 3 -1 roll 0 1 numloca 1 sub { + % stack: /splitarray -mark- { splitlen splitlen ... } locatable_array index + 1 index exch get dup prevsplit maxstring add gt { + prevboundary prevsplit sub exch + /prevsplit prevboundary def + } if + dup 1 and 0 eq { /prevboundary exch def } { pop } ifelse + dup type /arraytype ne { exch } if % keep locatable_array on top + } for + len1 prevsplit sub + exch pop % discard locatable_array + ] def + currentuserparams /VMReclaim get -2 vmreclaim + [ + % Re-split the sfnts glyfs strings according to splitarray. + % We do this by iterating over the final segments defined + % by splitarray, and constructing them from pieces of the + % current glyfs strings. We recycle the current strings + % when possible, to avoid stressing the allocator. + /sfnt_idx 0 def + /strpos 0 def + /avail () def + splitarray { + /seglen exch def + /segpos 0 def + avail length seglen ge + { avail 0 seglen getinterval /avail () def } { seglen string } + ifelse + { + /str glyfs sfnt_idx get def + /strlen str length def + /strleft strlen strpos sub def + seglen segpos sub strleft lt { exit } if + % Copy the (rest of the) string into the new segment. + % We know strleft <= segleft. + dup segpos str strpos strleft getinterval putinterval + /segpos segpos strleft add def + /avail str def + /sfnt_idx sfnt_idx 1 add def + /strpos 0 def + segpos seglen eq { exit } if + } loop + % Fill up the segment with an initial piece of the next + % existing glyfs string. We know strleft > segleft. + /segleft seglen segpos sub def + dup segpos str strpos segleft getinterval putinterval + /strpos strpos segleft add def + } forall + ] + exch vmreclaim +} bind def + +/first_post_string % - first_post_string <string> +{ + post dup type /arraytype eq { 0 get } if +} bind def + +% - .getpost - +% Uses post, defines glyphencoding +/.getpost { + /glyphencoding post null eq { + TTFDEBUG { (post missing) = flush } if [ ] + } { + postformats first_post_string 0 getu32 .knownget { + TTFDEBUG { + (post: format ) print + first_post_string + dup 0 getu16 =only (,) print 2 getu16 = flush + } if + post exch exec + } { + TTFDEBUG { (post: unknown format ) print post 0 getu32 = flush } if [ ] + } ifelse + } ifelse + TTFDEBUG { (post=) print dup == } if + def +} bind def + +% - .ttkeys <key> <value> ... +/.ttkeys { + count /ttkeycount exch def + /upem head 18 getu16 def + /FontMatrix matrix + /FontBBox [ 36 2 42 { head exch gets16 upem div } for ] + nextxuid + tabdict /name .knownget { + % Find the names from the 'name' table. + /names exch def + /FontName names 6 findname not { names 4 findname not { curxuid 16#ffffffff and 16 32 string cvrs } if } if + /fontname 1 index def + /FontInfo mark + names 0 findname { /Notice exch } if + names 1 findname { /FamilyName exch } if + names 4 findname { /FullName exch } if + names 5 findname { /Version exch } if + } { + % No name table, fabricate a FontName. + /FontName curxuid 16#ffffffff and 16 32 string cvrs + /fontname 1 index def + /FontInfo mark + } ifelse + % Stack: ... /FontInfo mark key1 value1 ... + post null ne { + /ItalicAngle first_post_string 4 gets32 65536.0 div + /isFixedPitch first_post_string 12 getu32 0 ne + /UnderlinePosition first_post_string 8 gets16 upem div + /UnderlineThickness first_post_string 10 gets16 upem div + } if + counttomark 0 ne { .dicttomark } { pop pop } ifelse + /XUID [orgXUID 42 curxuid] + TTFDEBUG { + tabs { .printtab } forall + [ sfnts { length } forall ] == + count ttkeycount sub array astore dup { == } forall aload pop + } if + /sfnts sfnts +} bind def + +% ---------------- Standard TrueType font loading ---------------- % + +% - .pickcmap_with_no_xlatmap - +% Defines cmapsub, cmaptab +/.pickcmap_with_no_xlatmap { + tabdict /cmap get + % The Apple cmap format is no help in determining the encoding. + % Look for a Microsoft table. If we can't find one, + % just use the first table, whatever it is. + dup 4 8 getinterval_from_stringarray exch % () [] % the default + 0 1 2 index 2 getu16a 1 sub { % () [] i + 8 mul 4 add 1 index exch 8 getinterval_from_stringarray % () [] () + TTFDEBUG { + (cmap: platform ) print dup 0 getu16 =only + ( encoding ) print dup 2 getu16 = flush + } if + dup 0 getu16 3 eq { exch 3 -1 roll pop exit } if pop + } for + % Stack: subentry table + /cmapsub 2 index def % () [] + exch 4 getu32 1 index string_array_size 1 index sub getinterval_from_stringarray + /cmaptab exch def +} bind def + +% - .pickcmap_with_xlatmap - +% Defines cmapsub, cmaptab +/.pickcmap_with_xlatmap { + .xlatmap_dict /TrueType known not { + (Emulating a CID font with a True Type file, ) print + (the file gs/lib/xlatmap must contain /TrueType key.) = + /.pickcmap_with_xlatmap cvx /configurationerror signalerror + } if + false + .xlatmap_dict /TrueType get + dup length 2 sub 0 exch 2 exch { % bool [] i + 2 copy get % bool [] i () + (.) search { % bool [] i post match pre + cvi exch pop exch cvi % bool [] i PlatID SpecID + } { + (gs/lib/xlatmap containg a record with an invalid (PlatformID.SpecificID)) = + /.pickcmap_with_xlatmap cvx /configurationerror signalerror + } ifelse + TTFDEBUG { + (Seeking a cmap for platform=) print 1 index =only ( encoding=) print dup = + } if + tabdict /cmap get % bool [] i PlatID SpecID (cmap) + dup /cmaptab exch def % temporary + 0 1 2 index 2 getu16a 1 sub { % bool [] i PlatID SpecID (cmap) j + 8 mul 4 add 1 index exch 8 + getinterval_from_stringarray % bool [] i PlatID SpecID (cmap) (cmapsub) + TTFDEBUG { + (cmap: platform ) print dup 0 getu16 =only + ( encoding ) print dup 2 getu16 = flush + } if + dup 0 getu16 4 index eq { + dup 2 getu16 3 index eq { % bool [] i PlatID SpecID (cmap) (cmapsub) + TTFDEBUG { + (Choosen a cmap for platform=) print 3 index =only + ( encoding=) print 2 index = + } if + /cmapsub 1 index def + dup 4 getu32 % bool [] i PlatID SpecID (cmap) (cmapsub) p + cmaptab 1 index getu16a % get cmap format + 8 lt { % length for traditional 16bit format 0, 2, 4, 6 + cmaptab 1 index 2 add getu16a + } { % length for advanced 32bit format 8, 10, 12 + cmaptab 1 index 4 add getu32a + } ifelse % bool [] i PlatID SpecID (cmap) (cmapsub) p l + cmaptab 3 1 roll getinterval_from_stringarray + /cmaptab exch def % bool [] i PlatID SpecID (cmap) (cmapsub) + 5 index 5 index 1 add get % bool [] i PlatID SpecID (cmap) (cmapsub) /Decoding + /Decoding exch def % bool [] i PlatID SpecID (cmap) (cmapsub) + 7 -1 roll pop true 7 1 roll % true [] i PlatID SpecID (cmap) (cmapsub) + } if + } if + pop % true [] i PlatID SpecID (cmap) + 5 index { exit } if + } for % bool [] i PlatID SpecID (cmap) + pop pop pop pop % bool [] + 1 index { exit } if + } for % bool [] + pop % bool + not { + QUIET not { (True Type font doesn't contain a charset listed in gs/lib/xlatmap.) = } if + /.pickcmap_with_xlatmap cvx /invalidfont signalerror + } if % +} bind def + +% - .pickcmap - +% Defines cmapsub, cmaptab +/.pickcmap { + % Currently we use xlatmap only for emulation CIDFontType 2 with + % a disk True Type font files, and use load_stripped + % to check this regime. We would like to do so + % while emulating a Type 42, but first the old code + % about handling them to be changed + % with adding a handling of a Decoding. + % fixme : A correct way to fix this is to implenent + % the Type 42 emulation with gs_fntem.ps . + % Also note that PDF embedded fonts probably don't need a xlatmap - + % see PDF spec, "Encodings for True Type fonts". + load_stripped { + //.pickcmap_with_xlatmap exec + } { + //.pickcmap_with_no_xlatmap exec + } ifelse +} bind def + +% <glyph> .nname <_name> +/.nname { + =string cvs (_) exch concatstrings cvn +} bind def + +% Provide alternative backward-compatible names for new TTF glyphs. +% This list was extracted from Adobe's Glyph List 2.0 and consists of +% glyph names that map to the same Unicode value. +% See: http://partners.adobe.com/asn/developer/typeforum/unicodegn.html +/postalias mark + /pi1 /pi /plusinus /plusminus + /Acyrillic /afii10017 /Becyrillic /afii10018 + /Cdot /Cdotaccent /Checyrillic /afii10041 + /Dcroat /Dslash /Decyrillic /afii10021 + /Delta /increment /Djecyrillic /afii10051 + /Dzecyrillic /afii10054 /Dzhecyrillic /afii10145 + /Ecyrillic /afii10053 /Edot /Edotaccent + /Efcyrillic /afii10038 /Elcyrillic /afii10029 + /Emcyrillic /afii10030 /Encyrillic /afii10031 + /Ercyrillic /afii10034 /Ereversedcyrillic /afii10047 + /Escyrillic /afii10035 /Euro /euro + /Fitacyrillic /afii10147 /Gcedilla /Gcommaaccent + /Gdot /Gdotaccent /Gecyrillic /afii10020 + /Gheupturncyrillic /afii10050 /Gjecyrillic /afii10052 + /H18533 /blackcircle /H18543 /blacksmallsquare + /H18551 /whitesmallsquare /H22073 /whitesquare + /Hardsigncyrillic /afii10044 /IAcyrillic /afii10049 + /IUcyrillic /afii10048 /Icyrillic /afii10055 + /Idot /Idotaccent /Iecyrillic /afii10022 + /Iicyrillic /afii10026 /Iishortcyrillic /afii10027 + /Iocyrillic /afii10023 /Izhitsacyrillic /afii10148 + /Jecyrillic /afii10057 /Kacyrillic /afii10028 + /Kcedilla /Kcommaaccent /Khacyrillic /afii10039 + /Kjecyrillic /afii10061 /Lcedilla /Lcommaaccent + /Ldot /Ldotaccent /Ljecyrillic /afii10058 + /Ncedilla /Ncommaaccent /Njecyrillic /afii10059 + /Ocyrillic /afii10032 /Odblacute /Ohungarumlaut + /Ohm /Omega /Oslashacute /Ostrokeacute + /Pecyrillic /afii10033 /Rcedilla /Rcommaaccent + /Shacyrillic /afii10042 /Shchacyrillic /afii10043 + /Softsigncyrillic /afii10046 /Tcedilla /Tcommaaccent + /Tecyrillic /afii10036 /Tsecyrillic /afii10040 + /Tshecyrillic /afii10060 /Ucyrillic /afii10037 + /Udblacute /Uhungarumlaut /Upsilon1 /Upsilonhooksymbol + /Ushortcyrillic /afii10062 /Vecyrillic /afii10019 + /Yatcyrillic /afii10146 /Yericyrillic /afii10045 + /Yicyrillic /afii10056 /Zdot /Zdotaccent + /Zecyrillic /afii10025 /Zhecyrillic /afii10024 + /acutecmb /acutecomb /acyrillic /afii10065 + /afii00208 /horizontalbar /afii08941 /lira + /afii10066 /becyrillic /afii10067 /vecyrillic + /afii10068 /gecyrillic /afii10069 /decyrillic + /afii10070 /iecyrillic /afii10071 /iocyrillic + /afii10072 /zhecyrillic /afii10073 /zecyrillic + /afii10074 /iicyrillic /afii10075 /iishortcyrillic + /afii10076 /kacyrillic /afii10077 /elcyrillic + /afii10078 /emcyrillic /afii10079 /encyrillic + /afii10080 /ocyrillic /afii10081 /pecyrillic + /afii10082 /ercyrillic /afii10083 /escyrillic + /afii10084 /tecyrillic /afii10085 /ucyrillic + /afii10086 /efcyrillic /afii10087 /khacyrillic + /afii10088 /tsecyrillic /afii10089 /checyrillic + /afii10090 /shacyrillic /afii10091 /shchacyrillic + /afii10092 /hardsigncyrillic /afii10093 /yericyrillic + /afii10094 /softsigncyrillic /afii10095 /ereversedcyrillic + /afii10096 /iucyrillic /afii10097 /iacyrillic + /afii10098 /gheupturncyrillic /afii10099 /djecyrillic + /afii10100 /gjecyrillic /afii10101 /ecyrillic + /afii10102 /dzecyrillic /afii10103 /icyrillic + /afii10104 /yicyrillic /afii10105 /jecyrillic + /afii10106 /ljecyrillic /afii10107 /njecyrillic + /afii10108 /tshecyrillic /afii10109 /kjecyrillic + /afii10110 /ushortcyrillic /afii10193 /dzhecyrillic + /afii10194 /yatcyrillic /afii10195 /fitacyrillic + /afii10196 /izhitsacyrillic /afii10846 /schwacyrillic + /afii57381 /percentarabic /afii57388 /commaarabic + /afii57392 /zeroarabic /afii57393 /onearabic + /afii57394 /twoarabic /afii57395 /threearabic + /afii57396 /fourarabic /afii57397 /fivearabic + /afii57398 /sixarabic /afii57399 /sevenarabic + /afii57400 /eightarabic /afii57401 /ninearabic + /afii57403 /semicolonarabic /afii57407 /questionarabic + /afii57409 /hamzaarabic /afii57410 /alefmaddaabovearabic + /afii57411 /alefhamzaabovearabic /afii57412 /wawhamzaabovearabic + /afii57413 /alefhamzabelowarabic /afii57414 /yehhamzaabovearabic + /afii57415 /alefarabic /afii57416 /beharabic + /afii57417 /tehmarbutaarabic /afii57418 /teharabic + /afii57419 /theharabic /afii57420 /jeemarabic + /afii57421 /haharabic /afii57422 /khaharabic + /afii57423 /dalarabic /afii57424 /thalarabic + /afii57425 /reharabic /afii57426 /zainarabic + /afii57427 /seenarabic /afii57428 /sheenarabic + /afii57429 /sadarabic /afii57430 /dadarabic + /afii57431 /taharabic /afii57432 /zaharabic + /afii57433 /ainarabic /afii57434 /ghainarabic + /afii57440 /tatweelarabic /afii57441 /feharabic + /afii57442 /qafarabic /afii57443 /kafarabic + /afii57444 /lamarabic /afii57445 /meemarabic + /afii57446 /noonarabic /afii57448 /wawarabic + /afii57449 /alefmaksuraarabic /afii57450 /yeharabic + /afii57451 /fathatanarabic /afii57452 /dammatanarabic + /afii57453 /kasratanarabic /afii57454 /fathaarabic + /afii57455 /dammaarabic /afii57456 /kasraarabic + /afii57457 /shaddaarabic /afii57458 /sukunarabic + /afii57470 /heharabic /afii57505 /veharabic + /afii57506 /peharabic /afii57507 /tcheharabic + /afii57508 /jeharabic /afii57509 /gafarabic + /afii57511 /tteharabic /afii57512 /ddalarabic + /afii57513 /rreharabic /afii57514 /noonghunnaarabic + /afii57519 /yehbarreearabic /afii57636 /newsheqelsign + /afii57645 /maqafhebrew /afii57658 /sofpasuqhebrew + /afii57664 /alef /afii57665 /bet + /afii57666 /gimel /afii57667 /dalet + /afii57668 /he /afii57669 /vav + /afii57670 /zayin /afii57671 /het + /afii57672 /tet /afii57673 /yod + /afii57674 /finalkaf /afii57675 /kaf + /afii57676 /lamed /afii57677 /finalmem + /afii57678 /mem /afii57679 /finalnun + /afii57680 /nun /afii57681 /samekh + /afii57682 /ayin /afii57683 /finalpe + /afii57684 /pe /afii57685 /finaltsadi + /afii57686 /tsadi /afii57687 /qof + /afii57688 /resh /afii57689 /shin + /afii57690 /tav /afii57694 /shinshindot + /afii57695 /shinsindot /afii57700 /vavholam + /afii57705 /doubleyodpatah /afii57716 /vavvavhebrew + /afii57717 /vavyodhebrew /afii57718 /yodyodhebrew + /afii57723 /vavdagesh /afii57793 /hiriq + /afii57794 /tsere /afii57795 /segol + /afii57796 /qubuts /afii57797 /qamats + /afii57798 /patah /afii57799 /sheva + /afii57800 /hatafpatah /afii57801 /hatafsegol + /afii57802 /hatafqamats /afii57803 /sindothebrew + /afii57804 /shindothebrew /afii57806 /holam + /afii57807 /dagesh /afii57839 /siluqhebrew + /afii57841 /rafe /afii57842 /paseqhebrew + /afii57929 /apostrophemod /afii61248 /careof + /afii61289 /lsquare /afii61352 /numero + /afii61664 /zerowidthnonjoiner /afii63167 /asteriskarabic + /afii64937 /commareversedmod /alefmaksurainitialarabic /yehinitialarabic + /alefmaksuramedialarabic /yehmedialarabic /approximatelyequal /congruent + /arrowdblboth /dblarrowleft /arrowdblleft /arrowleftdbl + /arrowdblright /dblarrowright /arrowupdnbse /arrowupdownbase + /bar /verticalbar /betdagesh /betdageshhebrew + /blackdownpointingtriangle /triagdn /blackleftpointingpointer /triaglf + /blackrectangle /filledrect /blackrightpointingpointer /triagrt + /blacksmilingface /invsmileface /blacksquare /filledbox + /blackuppointingtriangle /triagup /bulletinverse /invbullet + /cdot /cdotaccent /circle /whitecircle + /circlemultiply /timescircle /circleplus /pluscircle + /club /clubsuitblack /colonmonetary /colonsign + /compass /sun /daletdagesh /daletdageshhebrew + /dargahebrew /dargalefthebrew /dbllowline /underscoredbl + /dcroat /dmacron /decimalseparatorarabic /decimalseparatorpersian + /dialytikatonos /dieresistonos /dkshade /shadedark + /dotbelowcmb /dotbelowcomb /edot /edotaccent + /eighthnotebeamed /musicalnotedbl /etnahtafoukhhebrew /etnahtahebrew + /existential /thereexists /female /venus + /finalkafdagesh /finalkafdageshhebrew /forall /universal + /gcedilla /gcommaaccent /gdot /gdotaccent + /gimeldagesh /gimeldageshhebrew /gradient /nabla + /gravecmb /gravecomb /haaltonearabic /hehaltonearabic + /heart /heartsuitblack /hedagesh /hedageshhebrew + /hehfinalalttwoarabic /hehfinalarabic /hookabovecomb /hookcmb + /ilde /tilde /integralbottom /integralbt + /integraltop /integraltp /invcircle /whitecircleinverse + /kafdagesh /kafdageshhebrew /kcedilla /kcommaaccent + /lameddagesh /lameddageshhebrew /lcedilla /lcommaaccent + /ldot /ldotaccent /logicalnotreversed /revlogicalnot + /longs /slong /ltshade /shadelight + /macron /overscore /mahapakhhebrew /mahapakhlefthebrew + /male /mars /memdagesh /memdageshhebrew + /merkhahebrew /merkhalefthebrew /merkhakefulahebrew /merkhakefulalefthebrew + /middot /periodcentered /mu /mu1 + /munahhebrew /munahlefthebrew /napostrophe /quoterightn + /nbspace /nonbreakingspace /ncedilla /ncommaaccent + /notelement /notelementof /nundagesh /nundageshhebrew + /odblacute /ohungarumlaut /omega1 /pisymbolgreek + /openbullet /whitebullet /orthogonal /rightangle + /oslashacute /ostrokeacute /pedagesh /pedageshhebrew + /phi1 /phisymbolgreek /propersubset /subset + /propersuperset /superset /qofdagesh /qofdageshhebrew + /quoteleftreversed /quotereversed /rcedilla /rcommaaccent + /reflexsubset /subsetorequal /reflexsuperset /supersetorequal + /reviahebrew /reviamugrashhebrew /samekhdagesh /samekhdageshhebrew + /sfthyphen /softhyphen /shade /shademedium + /sheqel /sheqelhebrew /shindagesh /shindageshhebrew + /shindageshshindot /shindageshshindothebrew /shindageshsindot /shindageshsindothebrew + /sigma1 /sigmafinal /similar /tildeoperator + /smileface /whitesmilingface /space /spacehackarabic + /spade /spadesuitblack /tavdages /tavdagesh + /tcedilla /tcommaaccent /tetdagesh /tetdageshhebrew + /tevirhebrew /tevirlefthebrew /theta1 /thetasymbolgreek + /thousandsseparatorarabic /thousandsseparatorpersian /tildecmb /tildecomb + /tipehahebrew /tipehalefthebrew /tsadidagesh /tsadidageshhebrew + /twodotenleader /twodotleader /udblacute /uhungarumlaut + /yerahbenyomohebrew /yerahbenyomolefthebrew /yoddagesh /yoddageshhebrew + /zayindagesh /zayindageshhebrew /zdot /zdotaccent +.dicttomark readonly def + +% - .charkeys /CharStrings <charstrings> /Encoding <encoding> +% Resets glyphencoding +/.charkeys { + TTFDEBUG { + (glyphencoding: length=) print glyphencoding dup length = === flush + } if + % Hack: if there is no usable post table but the cmap uses + % the Microsoft Unicode encoding, use ISOLatin1Encoding. + % if 'post' presents, .charkeys computes (with dropping minor details) : + % CharStrings = glyphencoding^-1 + % Encoding = cmap*glyphencoding + % because 'post' maps glyph indices to glyph names. + % Otherwise .charkeys must compute (with dropping same details) : + % CharStrings = glyphencoding^-1 * cmap + % Encoding = glyphencoding + % because glyphencoding is stubbed with an encoding, + % which maps char codes to glyph names. + glyphencoding length 0 eq { + /have_post false def + cmapsub 0 4 getinterval <00030001> eq { + PDFDEBUG { (No post but have cmap 3.1, so use ISOLatin1Encoding) = } if + /glyphencoding ISOLatin1Encoding dup length array copy def + } { + PDFDEBUG { (No encoding info, use .GS_extended_SymbolEncoding) = } if + /glyphencoding /.GS_extended_SymbolEncoding findencoding dup length array copy def + } ifelse + } { + /have_post true def + } ifelse + % If necessary, fabricate additional glyphencoding entries + % to cover all of loca + glyphencoding length numloca lt { + /glyphencoding numloca array + glyphencoding length dup 1 sub 0 1 3 2 roll { + dup glyphencoding exch get + 3 index 3 1 roll put + } for + % /glyphencoding <newarray> <glyphencoding length> + 1 numloca 1 sub { + 1 index exch dup .nname put + } for + def + } if + /cmapa cmaptab cmaparray def + % Some badly designed Chinese fonts have a post table + % in which all glyphs other than 0 are named .null. + % Use CharStrings to keep track of the reverse map from + % names to glyphs, and don't let any name be used for + % more than one glyph. + /CharStrings glyphencoding dup length 1 add dict % +1 for .notdef + 0 1 3 index length 1 sub { + % Stack: glyphencoding dict index + 2 index 1 index get + have_post not { + exch + cmapa exch .knownget not { + 0 % a stub for a while. Must skip the entry. + } if + exch + } if + 2 index 1 index known + { % The same name maps to more than one glyph. Change the name. + % No special treatment for /.notdef glyph. Bug 689408. + pop dup .nname 3 index 2 index 2 index put + 2 index exch 3 -1 roll put + } { + 2 index exch 3 -1 roll put % unique name + } ifelse + } for exch pop + % If there is no .notdef entry, map it to glyph 0. + dup /.notdef known not { dup /.notdef 0 put } if + TTFDEBUG { + (CharStrings:)= dup { exch =string cvs print ( ) print == } forall + } if + //postalias { + % process pairs of names. If both names are known, do nothing. Otherwise + % make the name that is not defined an alias for the one that does exist. + % Stack: CharStrings(dict) /name1 /name2 + 2 index 2 index known 3 index 2 index known 1 index xor not { + pop pop pop % both names known or neither known + } { + % Stack: CharStrings(dict) /name1 /name2 name1_known(bool) + { exch } if % /name1 known -- we need it on top + % Stack: CharStrings(dict) /alias_name /known_name + TTFDEBUG { (setting alias: ) print 1 index ==only ( to be the same as glyph: ) print dup == } if + 2 index exch get 2 index 3 1 roll put + } ifelse + } forall + readonly + /Encoding [ + have_post { + 0 1 255 { + cmapa exch .knownget not { 0 } if + glyphencoding dup length + 2 index le { + pop pop /.notdef + } { + exch get + } ifelse + } for + } { + glyphencoding dup length 256 gt { 0 256 getinterval } if + aload pop + counttomark 256 exch sub { /.notdef } repeat + } ifelse + ] + TTFDEBUG { (Encoding: ) print dup === flush } if +} bind def + +currentdict /postalias undef + +% <file> .loadttfont <type42font> +/.loadttfont { + TTFDEBUG { (.loadttfont) = } if + //false 0 .loadttfonttables + .makesfnts + .getpost + .pickcmap + mark + .charkeys + .ttkeys + /FontType 42 + /PaintType 0 + TTFDEBUG { + (numloca=) print numloca = + } if + .dicttomark + end end dup /FontName get exch definefont +} bind def + +% ---------------- CIDFontType 2 font loading ---------------- % + +% Fill a string with sequential CIDs starting from the initial value. +% <string> <value> .fill_identity_cmap <string> +/.fill_identity_cmap { % () v + 1 index length 2 sub % () v n-2 + 0 2 3 2 roll { % () v 0 2 n-1 + 3 copy exch % () v i () i v + -8 bitshift % () v i () i v>>8 + put % () v i + 3 copy 1 add % () v i () v i+1 + exch 255 and % () v i () i+1 v&255 + put % () v i + pop 1 add % () v+1 + } for + pop +} bind def + +% -mark- <key> <value> ... .definettcidfont <font> +/.definettcidfont { + /CIDFontName fontname + /CIDFontType 2 + /CIDSystemInfo mark + /Registry (Adobe) + /Ordering (Japan1) % adhoc + /Supplement 0 + .dicttomark + /CharStrings mark /.notdef 0 .dicttomark + % The cmap isn't of any use even if it is present. + % Just construct an identity CIDMap covering all the glyphs. + + /CIDCount numloca % Wrong if a CIDFontType2 embedded into PDF with a non-Identity CIDToGIDMap. + % processCIDToGIDMap may replace. + /CIDMap numloca maxstring le { + % Use a single string. + numloca 2 mul string 0 .fill_identity_cmap + } { + % We must use 2 strings. + maxstring 2 mul string 0 .fill_identity_cmap + numloca maxstring sub 2 mul string maxstring .fill_identity_cmap + 2 array astore + } ifelse + + /GDBytes 2 + .dicttomark + end end dup /CIDFontName get exch /CIDFont defineresource +} bind def + +% <file> .loadttcidfont <cidtype2font> +/.loadttcidfont { + //false 0 .loadttfonttables + .makesfnts + % CIDFontType2 fonts don't have a cmap: they are indexed by CID. + mark + .ttkeys + .definettcidfont +} bind def + +% <file> <SubfontID> .load_tt_font_stripped <font_data> +% The font_data includes sfnts, NumGlyphs, TT_cmap, file_table_pos, Decoding. +% CIDMap to be created later from TT_cmap. +/.load_tt_font_stripped { + //true exch .loadttfonttables + .makesfnts + .pickcmap + mark + .ttkeys + /NumGlyphs numloca + /TT_cmap cmaptab cmaparray + /file_table_pos file_table_pos + /Decoding Decoding + .dicttomark + end end +} bind def + +% ---------------- PDF TrueType font loading ---------------- % + +% Strictly speaking, this code should be loaded only if we have a PDF +% interpreter, but it's so closely tied to the rest of the code in this +% file that we always include it. + +% <plat+enc> .findcmap <subtable> true +% <plat+enc> .findcmap false +/.findcmap { + false exch tabdict /cmap get + % Some fonts have multiple cmaps with the same platform and + % encoding. Use the first one we find. + 0 1 2 index 2 getu16a 1 sub { + % Stack: false plat+enc cmap index + 8 mul 4 add 1 index exch 8 getinterval_from_stringarray + dup 0 4 getinterval 3 index eq { + 4 getu32 1 index exch 1 index string_array_size 1 index sub getinterval_from_stringarray + 4 -1 roll not 4 2 roll exit + } if pop + } for + % Stack: false plat+enc cmap || subtable true plat+enc cmap + pop pop +} bind def + +% Build .symbol_list for .pdfcharkeys . +% It is a dictionary containing all SymbolEncoding glyph names +% and random names for filling gaps in the character code range. +/.symbol_list 256 dict def +{ + =string 0 (x) 0 get put + /SymbolEncoding .findencoding + 0 1 255 { + dup 2 index exch get + dup /.notdef eq { + pop dup + =string 1 3 getinterval cvs length 1 add + =string exch 0 exch getinterval cvn + } if + exch //.symbol_list 3 1 roll put + } for + pop +} bind exec + +% Create .GS_extended_SymbolEncoding as inverse of .symbol_list . +{ + /.GS_extended_SymbolEncoding 256 array + //.symbol_list { + exch 2 index 3 1 roll put + } forall + .defineencoding +} bind exec + +/.hexdigits (0123456789ABCDEF) def + +/.is_hex_digit { % <int> .is_hex_digit <bool> + dup 48 ge exch + dup 57 le exch + dup 65 ge exch + 70 le and + 3 1 roll + and or +} bind def + +/.popfex { pop //false exit } bind def +/.pop3ex { pop pop pop exit } bind def + +/.addglyph { % <dict> <name> <glyph#> .addglyph - + 1 index .namestring % d n g s + dup length 7 eq { + % Bug688467.ps doesn't work if the uniXXXX mapping is allowed with any cmap. + % Allow it with cmap 3.1 only. + currentdict /.allow_uniXXXX_glyph_names .knownget not { //false } if + } { //false + } ifelse % d n g s b + { + % An undocumented Adobe feature (not sure) : + % if the name is uniXXXX, obtain Unicode code from it. + % See bug 688946. + TTFDEBUG { (Try uniXXXX:) print dup print } if + { dup 0 get 117 ne //.popfex if % u + dup 1 get 110 ne //.popfex if % n + dup 2 get 105 ne //.popfex if % i + dup 3 get //.is_hex_digit exec not //.popfex if + dup 4 get //.is_hex_digit exec not //.popfex if + dup 5 get //.is_hex_digit exec not //.popfex if + dup 6 get //.is_hex_digit exec not //.popfex if + dup 3 1 getinterval .hexdigits exch search pop length exch pop exch pop 12 bitshift exch + dup 4 1 getinterval .hexdigits exch search pop length exch pop exch pop 8 bitshift exch + dup 5 1 getinterval .hexdigits exch search pop length exch pop exch pop 4 bitshift exch + dup 6 1 getinterval .hexdigits exch search pop length exch pop exch pop exch pop + add add add + + cmapencoding exch .knownget not { 0 } if + dup 0 eq //.popfex if + + TTFDEBUG { ( index=) print dup =string cvs print } if + exch pop + put //true exit + } loop + TTFDEBUG { ()= } if + } { + pop //false + } ifelse + not { % d n g + { + cmapencoding exch .knownget not { 0 } if + dup 0 eq //.pop3ex if + 3 copy pop known //.pop3ex if + put exit + } loop + } if +} bind def + +% <subcmap> <chartoglyphmap> .pdfmapchars /CharStrings <charstrings> +/.pdfmapchars { + exch cmaparray /cmapencoding exch def % c2g + /CharStrings 0 dict % c2g /CS <<>> + + % Add glyphs of <chartoglyphmap>*<subcmap> : + 3 2 roll { % /CS <<>> v + dup type /arraytype eq { % /CS <<>> /name [] + { 3 copy //.addglyph exec + pop + } forall + } { + 3 copy //.addglyph exec pop + } ifelse + pop + } forall + + % Add glyphs of 'post' with lower priority : + 0 1 glyphencoding length 1 sub { + dup glyphencoding exch get exch + dup 0 ne { + 3 copy pop known not { + 3 copy put + } if + } if + pop pop + } for + + dup /.notdef 0 put + +} bind def + +% - .pdfcharkeys /CharStrings <charstrings> /Encoding <encoding> +/.pdfcharkeys { + % The following algorithms are per the PDF Reference, Second Edition + % (PDF 1.3 reference manual). + TTFDEBUG { (.pdfcharkeys beg) = } if + is_symbolic { + <00030001> .findcmap { + % + % Adobe PDF spec says that symbolic fonts should contain exactly one + % cmap subtable for Platform=1, Encoding=0. + % Perhaps "Adobe Acrobat PDFWriter 4.0 for Windows" sometimes embeds + % fonts with both subtables 3.1 and 1.0 (see comparefiles/159.pdf, + % the font "Arial,Bold" with the character "registered"), + % and both Acrobat Reader 4.0 and 5.0 choose 3.1. + % Therefore we try 3.1 first. + % + ( **** Warning: Embedded symbolic TT fonts should not contain a cmap for Platform=3 Encoding=1.\n) + pdfformaterror + prebuilt_encoding null ne { + % Bug 689083. + TTFDEBUG { (Using cmap 3.0 with prebuilt_encoding.) = } if + prebuilt_encoding .invert_encoding .pdfmapchars + /Encoding prebuilt_encoding + } { + TTFDEBUG { (Using cmap 3.1 with WinAnsiEncoding) = } if + AdobeGlyphList .pdfmapchars + /Encoding /WinAnsiEncoding .findencoding + } ifelse + } { + % + % Adobe PDF spec says that in this case PDF interpreter should + % map character codes directly to glyphs using + % the cmap <00010000>. But we use PS interpreter to emulate + % a PDF interpreter. Therefore we need to construct + % a type 42 font, which requires an Encoding and a Charstrings. + % We construct them with symbol_list, which + % includes all glyphs from SymbolEncoding and additional + % random names for 1-to-1 mapping. + % + % A real TT font may use a different characters than + % the Symbol charaster set. Perhaps our code + % will give a correct printing, because glyph names are not + % important for symbolic fonts in PDF. + % + <00010000> .findcmap { + prebuilt_encoding null ne { + TTFDEBUG { (Using cmap 1.0 with prebuilt_encoding.) = } if + prebuilt_encoding .invert_encoding .pdfmapchars + /Encoding prebuilt_encoding + } { + % This is a case, in which an obsolete software could stupidly specify Macintosh Roman + % for a random encoding. Particulatrly GPL Ghostscript 7.06 does so. + % Trying to recover with 'post'. + pop % The table itself doesn't contain useful data. + TTFDEBUG { (Using cmap 1.0 with post or .GS_extended_SymbolEncoding) = } if + .charkeys + } ifelse + } { + % This is illegal with PDF spec. + ( **** Warning: Embedded symbolic TT fonts must contain a cmap for Platform=1 Encoding=0.\n) + pdfformaterror + % Apply the default algorithm. Hopely it has 'post'. + .charkeys + % check if the CharStrings dict contains glyphs needed by the + % prebuilt_encoding otherwise try the 3,0 cmap. + prebuilt_encoding null ne { + false prebuilt_encoding { % false means no missing glyphs + 4 index exch known not { pop true exit } if + } forall + { + ( **** Warning: Encoding derived from 'post' is incomplete.\n) + pdfformaterror + % Try another cmap format 3,0 -- Adobe doesn't mention it, but does + % use it apparently (empirically determined). + <00030000> .findcmap { + TTFDEBUG { (Adding cmap 3.0) = } if + 5 1 roll pop pop pop pop + prebuilt_encoding null ne { + prebuilt_encoding .invert_encoding .pdfmapchars + /Encoding prebuilt_encoding + } { + AdobeGlyphList .pdfmapchars + /Encoding /SymbolEncoding .findencoding + } ifelse + } if + } if + } if + } ifelse + } ifelse + } { + <00030001> .findcmap { + prebuilt_encoding null ne { + TTFDEBUG { (Using cmap 3.1 with prebuilt_encoding for non-symbolic.) = } if + + % The character code in /prebuilt_encoding[] is not guaranteed to be + % compatible with the Microsoft UCS2 TrueType cmap subtable. + % If the glyphname is known by AdobeGlyphList, the charcode for the glyph + % is replaced by UCS2 charcode from AdobeGlyphList. Otherwise it is left + % as in /prebuilt_encoding[]. /.pdfmapchars should dredge them. + + /.allow_uniXXXX_glyph_names //true def + AdobeGlyphList prebuilt_encoding .invert_encoding dup { % <<AGL>> <<pbe>> <glyphname> <pbecode> + pop % <<AGL>> <<pbe>> <glyphname> + TTFDEBUG { (check glypname /) print dup =only flush } if + 2 index 1 index .knownget { % <<AGL>> <<pbe>> <glyphname> <AGLcode> + 2 index 3 1 roll % <<AGL>> <<pbe>> <<pbe>> <glyphname> <AGLcode> + TTFDEBUG { ( redefine codepoint by AdobeGlyphList, ) print dup == flush } if + put % <<AGL>> <<pbe>> + } { % <<AGL>> <<pbe>> <glyphname> + TTFDEBUG { ( unknown glyphname, leave as it is ) print flush } if + pop % <<AGL>> <<pbe>> + } ifelse + } forall + exch pop % <<pbe>> + TTFDEBUG { dup (<<\n) print { exch ( ) print =only (\t) print == } forall (>>\n) print flush } if + .pdfmapchars + /Encoding prebuilt_encoding + } { + % Likely this branch is now obsolete. + TTFDEBUG { (Using cmap 3.1 for non-symbolic.) = } if + AdobeGlyphList .pdfmapchars + /Encoding /WinAnsiEncoding .findencoding + % WinAnsiEncoding is just a stub here. + % It will be replaced with one from font resource, + % because PDF spec requires it. + } ifelse + } { + <00010000> .findcmap { + TTFDEBUG { (Using cmap 1.0 for non-symbolic.) = } if + .romanmacdict .pdfmapchars + /Encoding + prebuilt_encoding null ne { + prebuilt_encoding + } { + /MacRomanEncodingForTrueType .findencoding + } ifelse + } { + % Apply the default algorithm for using the 'post'. + .charkeys + } ifelse + } ifelse + } ifelse + TTFDEBUG { (.pdfcharkeys end) = } if +} bind def + +% <file> <is_symbolic> <Encoding|null> .loadpdfttfont <type42font> +/.loadpdfttfont { + TTFDEBUG { (.loadpdfttfont Encoding=) print dup == } if + /prebuilt_encoding gput % for .pdfcharkeys + /is_symbolic gput + //false 0 .loadttfonttables + .makesfnts + tabdict /cmap known not { + ( **** Warning: Embedded TT font lacks required cmap table. Using identity cmap.\n) + pdfformaterror + % Unknown (i.e. not 0 ) language ID brings in post table. + % Fields: cmap_version, number_of_subtables, + % plarform_id, encoding_id, offset, + % format, subtable_length, language, + % 256 bytes of identity mapping. + tabdict /cmap + < 0000 0001 + 0001 D00D 0000000c + 0000 0106 0000 + 00 01 02 03 04 05 06 07 08 09 0a 0d 0c 0d 0e 0f + 10 11 12 13 14 15 16 17 18 19 1a 1d 1c 1d 1e 1f + 20 21 22 23 24 25 26 27 28 29 2a 2d 2c 2d 2e 2f + 30 31 32 33 34 35 36 37 38 39 3a 3d 3c 3d 3e 3f + 40 41 42 43 44 45 46 47 48 49 4a 4d 4c 4d 4e 4f + 50 51 52 53 54 55 56 57 58 59 5a 5d 5c 5d 5e 5f + 60 61 62 63 64 65 66 67 68 69 6a 6d 6c 6d 6e 6f + 70 71 72 73 74 75 76 77 78 79 7a 7d 7c 7d 7e 7f + 80 81 82 83 84 85 86 87 88 89 8a 8d 8c 8d 8e 8f + 90 91 92 93 94 95 96 97 98 99 9a 9d 9c 9d 9e 9f + a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ad ac ad ae af + b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bd bc bd be bf + c0 c1 c2 c3 c4 c5 c6 c7 c8 c9 ca cd cc cd ce cf + d0 d1 d2 d3 d4 d5 d6 d7 d8 d9 da dd dc dd de df + e0 e1 e2 e3 e4 e5 e6 e7 e8 e9 ea ed ec ed ee ef + f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 fa fd fc fd fe ff + > readonly put + } if + .getpost + .pickcmap + mark + .pdfcharkeys + .ttkeys + /FontType 42 + /PaintType 0 + TTFDEBUG { + (numloca=) print numloca = + } if + .dicttomark + end end + .completefont +} bind def diff --git a/gs/Resource/Init/gs_typ32.ps b/gs/Resource/Init/gs_typ32.ps new file mode 100644 index 000000000..c1d803bc3 --- /dev/null +++ b/gs/Resource/Init/gs_typ32.ps @@ -0,0 +1,133 @@ +% Copyright (C) 1997 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Initialization file for Type 32 fonts. + +% ------ Type 32 fonts ------ % + +% We need LanguageLevel 2 or higher in order to have defineresource. +languagelevel dup 2 .max .setlanguagelevel + +/BitmapFontInit mark + +/.makeglyph32 systemdict /.makeglyph32 get +systemdict /.makeglyph32 .undef + +/addglyph { % ([wx wy llx lly urx ury] | + % [w0x w0y llx lly urx ury w1x w1y vx vy]) + % <bitmap> <cid> <type32font> addglyph - + 1 index dup 2 index .removeglyphs + 22 string .makeglyph32 + % Stack: metrics bitmap cid font metstr + 3 index () ne { + % Use G4 encoding to compress the bitmap. + % Define a string large enough to hold the metrics, + % an uncompressed bitmap (worst case = 5x expansion), + % and the 2 RTC codes (3 bytes). + dup length 4 index length 5 mul add 10 add string + % Stack: metrics bitmap cid font metstr buffer + dup 0 3 index putinterval + dup 2 index length 1 index length 1 index sub getinterval + % Stack: metrics bitmap cid font metstr buffer bitbuf + mark /Columns 8 index dup 4 get exch 2 get sub + /Rows 10 index dup 5 get exch 3 get sub + /K -1 /EndOfBlock true /BlackIs1 true + .dicttomark /CCITTFaxEncode filter + % Stack: metrics bitmap cid font metstr buffer filter + dup 6 index writestring closefile + % Find the end of the data by scanning backwards for the RTC. + % There are 2 RTCs x 12 bits = 3 bytes to remove. + { + dup dup length 1 sub get 0 ne { exit } if + 0 1 index length 1 sub getinterval + } loop + 0 1 index length 3 sub getinterval + exch pop % metstr + } if + 1 index /CharStrings get 3 index 3 -1 roll put + pop pop pop pop +} obind + +/removeall { % <type32font> removeall - + 0 65535 2 index removeglyphs pop +} obind + +/.removeglyphs systemdict /.removeglyphs get +systemdict /.removeglyphs .undef + +/removeglyphs { % <cid_min> <cid_max> <type32font> .removeglyphs - + 3 copy .removeglyphs + dup /CharStrings get dup { + % Stack: cidmin cidmax font CharStrings cid bitmap + pop dup 5 index ge { dup 4 index le { 2 copy undef } if } if pop + } forall pop pop pop pop +} obind + +.dicttomark /ProcSet defineresource pop + +/.cidfonttypes where { pop } { /.cidfonttypes 6 dict def } ifelse +.cidfonttypes begin + +4 % CIDFontType 4 = FontType 32 +{ dup /FontType 32 .forceput + dup /CharStrings 20 dict .forceput + 1 index exch .buildfont32 exch pop +} bind def + +end % .cidfonttypes + +% Define the BuildGlyph procedure. +% Since Type 32 fonts are indexed by CID, there is no BuildChar procedure. +% The name %Type32BuildGlyph is known to the interpreter. +(%Type32BuildGlyph) cvn { % <font> <cid> %Type32BuildGlyph - + 1 index /CharStrings get + % Stack: font cid CharStrings + dup 2 index .knownget { + exch pop + } { + 0 .knownget not { + exch pop % Stack: cid + .getshowoperator /invalidfont signalerror + } if + } ifelse + % Stack: font cid cstr + dup //.getmetrics32 % use // because of .undef below + dup 14 gt { + 8 index 8 index 13 3 roll setcachedevice2 + } { + 4 index 4 index 9 3 roll setcachedevice + } ifelse + % Stack: font cid cstr w h nmetrics llx lly + 6 -1 roll 4 -1 roll 1 index length 1 index sub getinterval + % Stack: font cid w h llx lly bitstr + dup () eq { + pop pop pop + } { + mark /Columns 6 index /Rows 7 index /K -1 /EndOfBlock false /BlackIs1 true + .dicttomark /CCITTFaxDecode filter 4 index 4 index true + % Stack: font cid w h llx lly filter w h true + [ 1 0 0 1 11 -2 roll exch neg exch neg ] 5 -1 roll imagemask + } ifelse + pop pop pop pop +} .bind def + +systemdict /.getmetrics32 .undef + +buildfontdict 32 /.buildfont32 cvx put + +32 dup /FontType defineresource pop + +.setlanguagelevel diff --git a/gs/Resource/Init/gs_typ42.ps b/gs/Resource/Init/gs_typ42.ps new file mode 100644 index 000000000..13eb3794f --- /dev/null +++ b/gs/Resource/Init/gs_typ42.ps @@ -0,0 +1,62 @@ +% Copyright (C) 1996 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Type 42 font support code. + +% Here are the BuildChar and BuildGlyph implementation for Type 42 fonts. +% The names %Type42BuildChar and %Type42BuildGlyph are known to the +% interpreter. The real work is done in an operator: +% <font> <code|name> <name> <glyphindex> .type42execchar - + +(%Type42BuildChar) cvn % <font> <code> %Type42BuildChar - + { 1 index /Encoding get 1 index get .type42build + } bind def +(%Type42BuildGlyph) cvn % <font> <name> %Type42BuildGlyph - + { dup .type42build + } bind def +/.type42build % <font> <code|name> <name> .type42build - + { 2 index begin + dup CharStrings exch .knownget not + { 2 copy eq { exch pop /.notdef exch } if + QUIET not + { (Substituting .notdef for ) print + =string cvs print ( in the font ) print + 1 index /FontName get = flush + } + { pop } + ifelse + /.notdef CharStrings /.notdef get + } if + end .type42execchar + } bind def + +% Register the font type for definefont. +buildfontdict 42 + { % check for bogus sfnts -- this happens in Genoa FTS 421-01.ps + dup /sfnts get 0 get length 14 lt { % smallest valid sfnts is 14 bytes + % HACK: Add a BuildGlyph and make this a Type 3 font instead + dup /FontType 3 put + dup /BuildGlyph { + 1 index /CharStrings get exch 2 copy known not { pop /.notdef } if get exec + } bind put + //.buildfont3 exec + } { + systemdict /.buildfont42 get exec + } ifelse + } bind +put + + diff --git a/gs/Resource/Init/gs_type1.ps b/gs/Resource/Init/gs_type1.ps new file mode 100644 index 000000000..e7917fa2d --- /dev/null +++ b/gs/Resource/Init/gs_type1.ps @@ -0,0 +1,238 @@ +% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Type 1 font support code. + +% The standard representation for PostScript compatible fonts is described +% in the book "Adobe Type 1 Font Format", published by Adobe Systems Inc. + +/t1_glyph_equivalence mark + /Odblacute /Ohungarumlaut + /Udblacute /Uhungarumlaut + /odblacute /ohungarumlaut + /udblacute /uhungarumlaut +.dicttomark readonly def + +% Define an augmented version of .buildfont1 that inserts UnderlinePosition +% and UnderlineThickness entries in FontInfo if they aren't there already, +% and FontBBox isn't degenerate. +% (This works around the incorrect assumption, made by many word processors, +% that these entries are present in the built-in fonts.) +% Also add alternative names to some glyphs. +/.buildfont1 + { + .currentglobal 3 1 roll + dup .gcheck .setglobal + dup .fontbbox { + pop pop pop pop + dup /FontInfo known not + { .growfontdict dup /FontInfo 2 dict put } + if + dup dup /FontInfo get dup dup + /UnderlinePosition known exch /UnderlineThickness known and + { pop pop % entries already present + } + { dup length 2 add dict .copydict + dup /UnderlinePosition known not + { dup /UnderlinePosition 3 index /FontBBox get + 1 get 2 div put % 1/2 the font descent + } + if + dup /UnderlineThickness known not + { dup /UnderlineThickness 3 index /FontBBox get + dup 3 get exch 1 get sub 20 div put % 1/20 the font height + } + if + 1 index /FontInfo get wcheck not { readonly } if + /FontInfo exch put + } + ifelse + } if + dup /CharStrings get dup dup + //t1_glyph_equivalence { % <<>> <<>> <<>> /gl1 /gl2 + 2 index 2 index known { + 2 index 1 index known { + pop pop + } { + 3 1 roll get //.growput superexec dup dup + } ifelse + } { + 2 index 1 index known { + exch 3 1 roll get //.growput superexec dup dup + } { + pop pop + } ifelse + } ifelse + } forall + pop pop pop + + //.buildfont1 + 3 2 roll .setglobal + } bind def + +currentdict /t1_glyph_equivalence .undef + +% If the diskfont feature isn't included, define a dummy .loadfontdict. +/.loadfontdict where + { pop } + { /.loadfontdict 0 dict readonly def } +ifelse +/.loadfontfile % <file> .loadfontfile - + { mark exch + DISKFONTS { .loadfontdict begin } if + % In order to load fonts reliably, we should push systemdict + % here. However, Ed Taft says that Adobe implementations + % push userdict and nothing else! + % We really would just like systemdict on the stack, + % but fonts produced by Fontographer require a writable dictionary. + % However, we can't use any of the other well-known dictionaries + % (such as userdict), since the whole point of pushing systemdict + % is to make sure that nothing important has been redefined. + /userdict .systemvar begin + % We can't just use `run', because we want to check for .PFB files. + currentpacking + { //false setpacking .loadfont1 //true setpacking } + { .loadfont1 } + ifelse end + { stop } if + DISKFONTS { end } if + cleartomark + } bind def + % container for CloseSource flag (default //true to prevent buildup of file handles) + /closesourcedict mark + /CloseSource //true + .dicttomark readonly def +/.loadfont1 { % <file> .loadfont1 <errorflag> + { % We would like to use `false /PFBDecode filter', + % but this occasionally produces a whitespace character as + % the first of an eexec section, so we can't do it. + % Also, since the real input file never reaches EOF if we are using + % a PFBDecode filter (the filter stops just after reading the last + % character), we must explicitly close the real file in this case. + % Since the file might leave garbage on the operand stack, + % we have to create a procedure to close the file reliably. + dup read not { -1 } if + 2 copy unread 16#80 eq { + dup //closesourcedict //true /PFBDecode filter cvx + exch .currentresourcefile eq { + dup /.execasresource .systemvar + } { + {exec} + } ifelse + 2 index cvlit + /closefile .systemvar 3 .execn + } { + cvx exec + } ifelse + } stopped +} bind def +% undefine a dict that is only used internally, and is immediately bound +currentdict /closesourcedict .undef + +% Here are the BuildChar and BuildGlyph implementation for Type 1 fonts. +% The names %Type1BuildChar and %Type1BuildGlyph are known to the interpreter. +% The real work is done in an operator: +% <font> <code|name> <name> <charstring> .type1execchar - + +(%Type1BuildChar) cvn { % <font> <code> %Type1BuildChar - + 1 index /Encoding get 1 index get .type1build .type1execchar +} bind def +(%Type1BuildGlyph) cvn { % <font> <name> %Type1BuildGlyph - + dup .type1build .type1execchar +} bind def +% Note: this procedure is used for both Type 1 and Type 2 fonts. +/.type1build { % <font> <code|name> <name> .type1build + % <font> <code|name> <name> <charstring> + 2 index begin + dup CharStrings exch .knownget not { + 2 copy eq { exch pop /.notdef exch } if + QUIET not + { (Substituting .notdef for ) print + =string cvs print ( in the font ) print + 1 index /FontName get = flush + } + { pop } + ifelse + /.notdef CharStrings /.notdef get + } if + end +} bind def + +1183615869 internaldict begin +% CCRun is an undocumented procedure provided for Type 4 and Type 0 fonts. +% Apparently there are two different argument lists for CCRun. +% Handling the one with the extra Private dictionary requires fabricating +% a Type 1 font on the fly, since we aren't currently prepared to parse the +% dictionary any other way. +/CCRun { % <font> <code|name> <charstring> CCRun - + % <font> <code|name> <charstring> <Private> CCRun - + dup type /dicttype eq { + dup 4 index /Private .knownget { ne } { pop //true } ifelse { + % The Private dictionary was supplied, and is different + % from the Private dictionary of the font. Fabricate a + % Type 1 font with this Private dictionary. Most of the + % font entries are arbitrary or not needed. + .currentglobal //false .setglobal 10 dict exch .setglobal begin + /Private exch def + /FontType 1 def + /FontMatrix 3 index /FontMatrix get def + /Encoding 3 index /Encoding .knownget not { StandardEncoding } if def + /FontBBox 3 index /FontBBox .knownget not { {0 0 0 0} } if def + /PaintType 0 def + /CharStrings 1 dict dup /.notdef () put def + 3 -1 roll pop () currentdict end .buildfont1 exch pop 3 1 roll + } { + pop + } ifelse + } if + 1 index dup type /integertype eq { + 3 index /Encoding get exch get + } if exch .type1execchar +} bind def + +% setweightvector is an undocumented procedure that force writes +% weight vector to the font. Do extra checks for safety. +/setweightvector { % <font> <vector> setweightvector - + dup type dup /arraytype ne exch /packedarraytype ne and + 2 index type /dicttype ne or { + /setweightvector cvx /typecheck signalerror + } if + 1 index /FontType known not { + /setweightvector cvx /invalidfont signalerror + } if + dup gcheck 2 index gcheck not and { + /setweightvector cvx /invalidaccess signalerror + } if + 2 copy /WeightVector exch .forceput + .setweightvector +} .bind executeonly def +end + +% Register the font types for definefont. +buildfontdict 1 /.buildfont1 cvx put +buildfontdict 4 /.buildfont4 cvx put + +% Add Type 2 support if applicable. +/.buildfont2 where not { (%END2) .skipeof } if +pop +(%Type2BuildChar) cvn { % <font> <code> %Type2BuildChar - + 1 index /Encoding get 1 index get .type1build .type2execchar +} bind def +(%Type2BuildGlyph) cvn { % <font> <name> %Type2BuildGlyph - + dup .type1build .type2execchar +} bind def +buildfontdict 2 /.buildfont2 cvx put +%END2 diff --git a/gs/Resource/Init/gs_wan_e.ps b/gs/Resource/Init/gs_wan_e.ps new file mode 100644 index 000000000..15916c119 --- /dev/null +++ b/gs/Resource/Init/gs_wan_e.ps @@ -0,0 +1,46 @@ +% Copyright (C) 1994, 1996, 1997, 1999 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Define the WinAnsi encoding vector. +/currentglobal where + { pop currentglobal { setglobal } true setglobal } + { { } } +ifelse +/WinAnsiEncoding +ISOLatin1Encoding 0 39 getinterval aload pop + /quotesingle +ISOLatin1Encoding 40 5 getinterval aload pop + /hyphen +ISOLatin1Encoding 46 50 getinterval aload pop + /grave +ISOLatin1Encoding 97 30 getinterval aload pop + /bullet +% \20x + % NOTE: /Euro, /Zcaron, and /zcaron are new for PDF 1.3. + % We may have to take them out for backward compatibility. + /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 +ISOLatin1Encoding 160 96 getinterval aload pop +256 packedarray +4 1 index .registerencoding +.defineencoding +exec diff --git a/gs/Resource/Init/pdf_base.ps b/gs/Resource/Init/pdf_base.ps new file mode 100644 index 000000000..018d24003 --- /dev/null +++ b/gs/Resource/Init/pdf_base.ps @@ -0,0 +1,1066 @@ +% Copyright (C) 1994-2006 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% pdf_base.ps +% Basic parser for PDF reader. + +% This handles basic parsing of the file (including the trailer +% and cross-reference table), as well as objects, object references, +% streams, and name/number trees; it doesn't include any facilities for +% making marks on the page. + +/.setlanguagelevel where { pop 2 .setlanguagelevel } if +.currentglobal true .setglobal +/pdfdict where { pop } { /pdfdict 100 dict def } ifelse +pdfdict begin + +% Define the name interpretation dictionary for reading values. +/valueopdict mark + (<<) cvn { mark } bind % don't push an actual mark! + (>>) cvn { { .dicttomark } stopped { + ( **** File has an unbalanced >> \(close dictionary\).\n) + pdfformaterror + } if + } bind + ([) cvn { mark } bind % ditto + (]) cvn dup load +% /true true % see .pdfexectoken below +% /false false % ibid. +% /null null % ibid. + /F dup cvx % see Objects section below + /R dup cvx % see Objects section below + /stream dup cvx % see Streams section below +.dicttomark readonly def + +% ------ Utilities ------ % + +% Define a scratch string. The PDF language definition says that +% no line in a PDF file can exceed 255 characters, but this string +% is also used to search for %PDF-, which needs 1024 characters. +/pdfstring 1024 string def + +% Read the previous line of a file. If we aren't at a line boundary, +% read the line containing the current position. +% Skip any blank lines. +/prevline % - prevline <startpos> <substring> + { PDFfile fileposition dup () pdfstring + 2 index 257 sub 0 .max PDFfile exch setfileposition + { % Stack: initpos linepos line string + PDFfile fileposition + PDFfile 2 index readline pop + dup length 0 gt + { 3 2 roll 5 -2 roll pop pop 2 index } + { pop } + ifelse + % Stack: initpos linepos line string startpos + PDFfile fileposition 5 index ge { exit } if + pop + } + loop pop pop 3 -1 roll pop + } bind def + +% Handle the PDF 1.2 #nn escape convention when reading from a file. +% This should eventually be done in C. +/.pdffixname { % <execname> .pdffixname <execname'> + PDFversion 1.2 ge { + dup .namestring (#) search { + name#escape cvn exch pop + } { + pop + } ifelse + } if +} bind def +/name#escape % <post> <(#)> <pre> name#escape <string> +{ exch pop + 1 index 2 () /SubFileDecode filter dup (x) readhexstring + % Stack: post pre stream char t/f + not { % tolerate, but complain about bad syntax + pop closefile (#) concatstrings exch + ( **** Warning: Invalid hex following '#' name escape, using literal '#' in name.\n) + pdfformaterror + } { + exch closefile concatstrings + exch 2 1 index length 2 sub getinterval + } ifelse + (#) search { name#escape } if concatstrings +} bind def + +% Execute a file, interpreting its executable names in a given +% dictionary. The name procedures may do whatever they want +% to the operand stack. +/.pdftokenerror { % <count> <opdict> <errtoken> .pdftokenerror - + BXlevel 0 le { + ( **** Unknown operator: ') pdfformaterror + dup =string cvs pdfformaterror + % Attempt a retry scan of the element after changing to PDFScanInvNum + << /PDFScanInvNum true >> setuserparams + =string cvs + token pop exch pop dup type + dup /integertype eq exch /realtype eq or { + exch pop exch pop + (', processed as number, value: ) pdfformaterror + dup =string cvs pdfformaterror (\n) pdfformaterror + << /PDFScanInvNum null >> setuserparams % reset to default scanning rules + false % suppress any stack cleanup + } { + % error was non-recoverable with modified scanning rules + ('\n) pdfformaterror + true + } ifelse + } { + true + } ifelse + { % clean up the operand stack if this was non-recoverable + pop pop count exch sub { pop } repeat % pop all the operands + } if +} bind def +/.pdfexectoken { % <count> <opdict> <exectoken> .pdfexectoken ? + PDFDEBUG { + pdfdict /PDFSTEPcount known not { pdfdict /PDFSTEPcount 1 .forceput } if + PDFSTEP { + pdfdict /PDFtokencount 2 copy .knownget { 1 add } { 1 } ifelse .forceput + PDFSTEPcount 1 gt { + pdfdict /PDFSTEPcount PDFSTEPcount 1 sub .forceput + } { + dup ==only + ( step # ) print PDFtokencount =only + ( ? ) print flush 1 false .outputpage + (%stdin) (r) file 255 string readline { + token { + exch pop pdfdict /PDFSTEPcount 3 -1 roll .forceput + } { + pdfdict /PDFSTEPcount 1 .forceput + } ifelse % token + } { + pop /PDFSTEP false def % EOF on stdin + } ifelse % readline + } ifelse % PDFSTEPcount > 1 + } { + dup ==only () = flush + } ifelse % PDFSTEP + } if % PDFDEBUG + 2 copy .knownget { + exch pop exch pop exch pop exec + } { + % Normally, true, false, and null would appear in opdict + % and be treated as "operators". However, there is a + % special fast case in the PostScript interpreter for names + % that are defined in, and only in, systemdict and/or + % userdict: putting these three names in the PDF dictionaries + % destroys this property for them, slowing down their + % interpretation in all PostScript code. Therefore, we + % check for them explicitly here instead. + dup dup dup /true eq exch /false eq or exch /null eq or { + exch pop exch pop //systemdict exch get + } { + % Hackish fix to detect missing whitespace after "endobj". Yet another + % problem that (you guessed it!) Adobe Acrobat ignores silently + 256 string cvs (endobj) anchorsearch { + ( **** Missing whitespace after 'endobj'.\n) pdfformaterror + exch pop cvn get exch pop exec + } { + .pdftokenerror + } ifelse + } ifelse + } ifelse +} bind def +/PDFScanRules_true << /PDFScanRules true >> def +/PDFScanRules_null << /PDFScanRules null >> def +/.pdfrun { % <file> <opdict> .pdfrun - + % Construct a procedure with the stack depth, file and opdict + % bound into it. + 1 index cvlit count 2 sub 3 1 roll mark + /PDFScanRules .getuserparam //null eq { + //PDFScanRules_true { setuserparams } 0 get % force PDF scanning mode + mark 7 4 roll + } { + mark 5 2 roll + } ifelse + { % Stack: ..operands.. count opdict file + { token } stopped { + dup type /filetype eq { pop } if % pop the operand if it is restored + ( **** Error reading a content stream. The page may be incomplete.\n) + pdfformaterror + //false + } if { + dup type /nametype eq { + dup xcheck { + .pdfexectoken + } { + .pdffixname + exch pop exch pop PDFDEBUG { + PDFSTEPcount 1 le { + dup ==only ( ) print flush + } if + } if + } ifelse + } { + exch pop exch pop PDFDEBUG { + PDFSTEPcount 1 le { + dup ==only ( ) print flush + } if + } if + } ifelse + } { + (%%EOF) cvn cvx .pdfexectoken + } ifelse + } + aload pop .packtomark cvx + { loop } 0 get 2 packedarray cvx + { stopped } 0 get + /PDFScanRules .getuserparam //null eq { + //PDFScanRules_null { setuserparams } 0 get % reset PDF scannig mode if it was off + } if + /PDFsource PDFsource + { store { stop } if } aload pop .packtomark cvx + /PDFsource 3 -1 roll store exec +} bind def + +% Execute a file, like .pdfrun, for a marking context. +% This temporarily rebinds LocalResources and DefaultQstate. +/.pdfruncontext { % <resdict> <file> <opdict> .pdfruncontext - + /.pdfrun load LocalResources DefaultQstate + /LocalResources 7 -1 roll store + /DefaultQstate qstate store + 3 .execn + /DefaultQstate exch store + /LocalResources exch store +} bind def + +% Get the depth of the PDF operand stack. The caller sets pdfemptycount +% before calling .pdfrun or .pdfruncontext. It is initially set by +% pdf_main, and is also set by any routine which changes the operand +% stack depth (currently .pdfpaintproc, although there are other callers +% of .pdfrun{context} which have not been checked for opstack depth. +/.pdfcount { % - .pdfcount <count> + count pdfemptycount sub +} bind def + +% Read a token, but simply return false (no token read) in the case of an +% error. This is messy because 'token' either may or may not pop its operand +% if an error occurs, and because the return values are different depending +% on whether the source is a file or a string. To avoid closing the file +% check for '{' before trying 'token'. +/token_nofail_dict mark + ( ) { dup ( ) readstring pop pop } bind + (\t) 1 index + (\r) 1 index + (\n) 1 index + (\000) 1 index + ({) { //null //true exit } bind +.dicttomark def + +/token_nofail { % <file|string> token_nofail false + % <file> token_nofail <token> true + % <string> token_nofail <post> <token> true + dup type /filetype eq { + { dup ( ) .peekstring not { ({) } if + //token_nofail_dict exch .knownget not { + //null 1 index { token } .internalstopped exit + } if + exec + } loop + { % stack: source null [source] + //null ne { pop } if pop //false + } { % stack: source null ([post] token true | false) + { 3 1 roll pop pop //true } + { pop pop //false } + ifelse + } ifelse + } { + //null 1 index % stack: source null source + { token } .internalstopped { % stack: source null [source] + //null ne { pop } if pop //false + } { % stack: source null ([post] token true | false) + { 4 2 roll pop pop //true } + { pop pop //false } + ifelse + } ifelse + } ifelse +} bind def + +currentdict /token_nofail_dict .undef + +% ================================ Objects ================================ % + +% Since we may have more than 64K objects, we have to use a 2-D array to +% hold them (and the parallel Generations structure). +/lshift 9 def +/lnshift lshift neg def +/lsubmask 1 lshift bitshift 1 sub def +/lsublen lsubmask 1 add def +/larray { % - larray <larray> + [ [] ] +} bind def +/lstring { % - lstring <lstring> + [ () ] +} bind def +/ltype { % <lseq> type <type> + 0 get type +} bind def +/lget { % <lseq> <index> lget <value> + dup //lsubmask and 3 1 roll //lnshift bitshift get exch get +} bind def +/lput { % <lseq> <index> <value> lput - + 3 1 roll + dup //lsubmask and 4 1 roll //lnshift bitshift get + 3 1 roll put +} bind def +/llength { % <lseq> llength <length> + dup length 1 sub dup //lshift bitshift + 3 1 roll get length add +} bind def +% lgrowto assumes newlength > llength(lseq) +/growto { % <string/array> <length> growto <string'/array'> + 1 index type /stringtype eq { string } { array } ifelse + 2 copy copy pop exch pop +} bind def +/lgrowto { % <lseq> <newlength> lgrowto <lseq'> + dup //lsubmask add //lnshift bitshift dup 3 index length gt { + % Add more sub-arrays. Start by completing the last existing one. + % Stack: lseq newlen newtoplen + 3 -1 roll dup llength 1 sub //lsubmask or 1 add lgrowto + % Stack: newlen newtoplen lseq + [ exch aload pop + counttomark 2 add -1 roll % newtoplen + counttomark sub { dup 0 0 getinterval lsublen growto } repeat + dup 0 0 getinterval ] exch + } { + pop + } ifelse + % Expand the last sub-array. + 1 sub //lsubmask and 1 add + exch dup dup length 1 sub 2 copy + % Stack: newsublen lseq lseq len-1 lseq len-1 + get 5 -1 roll growto put +} bind def +/lforall { % <lseq> <proc> lforall - + /forall cvx 2 packedarray cvx forall +} bind def + +% We keep track of PDF objects using the following PostScript variables: +% +% Generations (lstring): Generations[N] holds 1+ the current +% generation number for object number N. (As far as we can tell, +% this is needed only for error checking.) For free objects, +% Generations[N] is 0. +% +% Objects (larray): If object N is loaded, Objects[N] is the actual +% object; otherwise, Objects[N] is an executable integer giving +% the file offset of the object's location in the file. If +% ObjectStream[N] is non-zero then Objects[N] contains the index +% into the object stream instead of the file offset of the object. +% +% ObjectStream (larray): If object N is in an object stream then +% ObjectStream[N] holds the object number of the object stream. +% Otherwise ObjectStream[N] contains 0. If ObjectStream[N] +% is non-zero then Objects[N] contains the index into the object +% stream. +% +% GlobalObjects (dictionary): If object N has been resolved in +% global VM, GlobalObjects[N] is the same as Objects[N] +% (except that GlobalObjects itself is stored in global VM, +% so the entry will not be deleted at the end of the page). +% +% IsGlobal (lstring): IsGlobal[N] = 1 iff object N was resolved in +% global VM. This is an accelerator to avoid having to do a +% dictionary lookup in GlobalObjects when resolving every object. + +% Initialize the PDF object tables. +/initPDFobjects { % - initPDFobjects - + /ObjectStream larray def + /Objects larray def + /Generations lstring def + .currentglobal true .setglobal + /GlobalObjects 20 dict def + .setglobal + /IsGlobal lstring def +} bind def + +% Grow the tables to a specified size. +/growPDFobjects { % <minsize> growPDFobjects - + dup ObjectStream llength gt { + dup ObjectStream exch lgrowto /ObjectStream exch def + } if + dup Objects llength gt { + dup Objects exch lgrowto /Objects exch def + } if + dup Generations llength gt { + dup Generations exch lgrowto /Generations exch def + } if + dup IsGlobal llength gt { + dup IsGlobal exch lgrowto /IsGlobal exch def + } if + pop +} bind def + +% We represent an unresolved object reference by a procedure of the form +% {obj# gen# resolveR}. This is not a possible PDF object, because PDF has +% no way to represent procedures. Since PDF in fact has no way to represent +% any PostScript object that doesn't evaluate to itself, we can 'force' +% a possibly indirect object painlessly with 'exec'. +% Note that since we represent streams by executable dictionaries +% (see below), we need both an xcheck and a type check to determine +% whether an object has been resolved. +/resolved? { % <object#> resolved? <value> true + % <object#> resolved? false + Objects 1 index lget dup xcheck { % Check if executable + dup type /integertype eq { % Check if an integer + % Check whether the object is in GlobalObjects. + pop IsGlobal 1 index lget 0 eq { % 0 --> Not in GlabalObjects + pop false % The object is not resolved + } { % The object is in GlobalObjects + % Update Objects from GlobalObjects + PDFDEBUG { (%Global=>local: ) print dup == } if + GlobalObjects 1 index get dup Objects 4 1 roll lput true + } ifelse + } { % Else object is executable but not integer + exch pop true % Therefore must be executable dict. (stream) + } ifelse + } { % Else object is not executable. + exch pop true % Therefore it must have been resolved. + } ifelse +} bind def +/oforce /exec load def +/oget { % <array> <index> oget <object> + % <dict> <key> oget <object> + % Before release 6.20, this procedure stored the resolved + % object back into the referring slot. In order to support + % PDF linearization, we no longer do this. + get oforce +} bind def +/oforce_array { % <array> oforce_array <array> + [ exch { oforce } forall ] +} bind def +/oforce_elems { % <array> oforce_elems <first> ... <last> + { oforce } forall +} bind def +/oforce_recursive { % <any> oforce_recursive <any> + oforce dup type dup /arraytype eq { + pop [ exch { oforce_recursive } forall ] + } { + /dicttype eq { + << exch { oforce_recursive exch oforce exch } forall >> + } if + } ifelse +} bind def + +% A null value in a dictionary is equivalent to an omitted key; +% we must check for this specially. +/knownoget { % <dict> <key> knownoget <value> true + % <dict> <key> knownoget false + % See oget above regarding this procedure. + .knownget { + oforce dup //null eq { pop //false } { //true } ifelse + } { + //false + } ifelse +} bind def + +/knownogetdict { % <dict> <key> knownogetdict <dict> true + % <dict> <key> knownogetdict false + //knownoget exec dup { + 1 index type /dicttype ne { pop pop //false } if + } if +} bind def + + +% PDF 1.1 defines a 'foreign file reference', but not its meaning. +% Per the specification, we convert these to nulls. +/F { % <file#> <object#> <generation#> F <object> + % Some PDF 1.1 files use F as a synonym for f! + .pdfcount 3 lt { f } { pop pop pop null } ifelse +} bind def + +% Verify the generation number for a specified object +% Note: The values in Generations is the generation number plus 1. +% If the value in Generations is zero then the object is free. +/checkgeneration { % <object#> <generation#> checkgeneration <object#> <OK> + Generations 2 index lget 1 sub 1 index eq { % If generation # match ... + pop true % Then return true + } { % Else not a match ... + QUIET not { % Create warning message if not QUIET + Generations 2 index lget 0 eq { % Check if object is free ... + ( **** Warning: reference to free object: ) + 2 index =string cvs concatstrings ( ) concatstrings % put obj # + exch =string cvs concatstrings ( R\n) concatstrings % put gen # + } { + ( **** Warning: wrong generation: ) + 2 index =string cvs concatstrings ( ) concatstrings % put obj # + exch =string cvs concatstrings % put gen # + (, xref gen#: ) concatstrings 1 index Generations % put xref gen # + exch lget 1 sub =string cvs concatstrings (\n) concatstrings + } ifelse + pdfformaterror % Output warning message + } { % Else QUIET ... + pop % Pop generation number + } ifelse + % We should return false for an incorrect generation number, however + % we are simply printing a warning and then returning true. This makes + % Ghostscript tolerant of of bad generation numbers. + true + } ifelse +} bind def +/R { % <object#> <generation#> R <object> + /resolveR cvx 3 packedarray cvx +} bind def + +% If we encounter an object definition while reading sequentially, +% we just store it away and keep going. +/objopdict mark + valueopdict { } forall + /endobj dup cvx +.dicttomark readonly def + +/obj { % <object#> <generation#> obj <object> + PDFfile objopdict .pdfrun +} bind def + +/endobj { % <object#> <generation#> <object> endobj <object> + 3 1 roll + % Read the xref entry if we haven't yet done so. + % This is only needed for generation # checking. + 1 index resolved? { + pop + } if + checkgeneration { + % The only global objects we bother to save are + % (resource) dictionaries. + 1 index dup gcheck exch type /dicttype eq and { + PDFDEBUG { (%Local=>global: ) print dup == } if + GlobalObjects 1 index 3 index put + IsGlobal 1 index 1 put + } if + Objects exch 2 index lput + } { + pop pop null + } ifelse +} bind def + +% When resolving an object reference in an object stream, we stop at +% the end of file. Note: Objects in an object stream do not have either +% a starting 'obj' or and ending 'endobj'. +/resolveobjstreamopdict mark + valueopdict { } forall + (%%EOF) cvn { exit } bind + /endobj { % bug 689795 + ( **** Warning: Objects in an object stream should not have 'endobj'.\n) + pdfformaterror + } bind +.dicttomark readonly def + +% Note: This version of this function is not currently being used. +% Resolve all objects in an object stream +/resolveobjectstream { % <object stream #> resolveobjectstream - + PDFDEBUG { (%Resolving object stream: ) print } if + 0 resolveR % Get the objectstream dict, all objstrms use 0 as the gen # + dup /First get % Save location of first object onto the stack + 1 index /N get % Save number of objects onto the stack + 2 index false resolvestream % Convert stream dict into a stream + /ReusableStreamDecode filter % We need to be able to position stream + % Objectstreams begin with list of object numbers and locations + % Create two arrays to hold object numbers and stream location + 1 index array % Array for holding object number + 2 index array % Array for holding stream object location + % Get the object numbers and locations. + 0 1 5 index 1 sub { % Loop and collect obj # and locations + % Stack: objstreamdict First N objectstream [obj#] [loc] index + 2 index 1 index % Setup to put obj# into object number array + 5 index token pop put % Get stream, then get obj# and put into array + 1 index 1 index % Setup to put object loc into location array + 5 index token pop put % Get stream, get obj loc and put into array + pop % Remove loop index + } for + % Create a bytestring big enough for reading any object data + % Scan for the size of the largest object + 0 0 % Init max object size and previous location + 2 index { % Loop through all object locations + % Stack: ... maxsize prevloc currentloc + dup 4 1 roll % Save copy of object location into stack + exch sub % Object size = currentloc - prevloc + .max % Determine maximum object size + exch % Put max size under previous location + } forall + pop % Remove previous location + .bigstring % Create bytestring based upon max obj size + % Move to the start of the object data + 3 index 6 index % Get objectstream and start of first object + setfileposition % Move to the start of the data + % Read the data for all objects except the last. We do + % not know the size of the last object so we need to treat + % it as a special case. + 0 1 6 index 2 sub { + dup 4 index exch get % Get our current object number + % Stack: objstreamdict First N objectstream [obj#] [loc] + % bytestring loopindex object# + dup resolved? { % If we already have this object + (yyy) = pstack (yyy) = flush xxx + pop pop % Remove object and object number + 1 add 2 index exch get % Get location of next object + 6 index add 6 index exch % Form location of next object and get stream + setfileposition % Move to the start of the next object data + } { % Else this is a new object ... + % We are going to create a string for reading the object + 2 index 0 % use our working string + % Determine the size of the object + 5 index 4 index 1 add get % Get location of the next object + 6 index 5 index get % Get location of this object + sub % Size of object = next loc - this loc + getinterval % Create string for reading object + 6 index exch readstring pop % Read object + /ReusableStreamDecode filter % Convert string into a stream + resolveobjstreamopdict .pdfrun % Get PDF object + Objects exch 2 index exch lput % Put object into Objects array + pop pop % Remove object # and loop index + } ifelse + } for + pop pop % Remove our working string and loc array + % Now read the last object in the object stream. Since it + % is the last object, we can use the original stream and + % terminate when we hit the end of the stream + % Stack: objstreamdict First N objectstream [obj#] + 2 index 1 sub get % Get our current object number + dup resolved? not { % If we do not already have this object + exch % Get our object stream + resolveobjstreamopdict .pdfrun % Get PDF object + Objects exch 2 index exch lput % Put object into Objects array + } if + pop pop pop pop % Clear stack +} bind def + +% Resolve all objects in an object stream +/resolveobjectstream { % <object stream #> resolveobjectstream - + PDFDEBUG { (%Resolving object stream: ) print } if + 0 resolveR % Get the objectstream dict, all objstrms use 0 as the gen # + dup /Type get /ObjStm ne { % Verify type is object stream + ( **** Incorrect Type in object stream dictionary.\n) pdfformaterror + /resolveobjectstream cvx /typecheck signalerror + } if + dup /N get % Save number of objects onto the stack + 1 index false resolvestream % Convert stream dict into a stream + /ReusableStreamDecode filter % We need to be able to position stream + % Objectstreams begin with list of object numbers and locations + 1 index array % Create array for holding object number + % Get the object numbers + 0 1 4 index 1 sub { % Loop and collect obj numbers + % Stack: objstreamdict N PDFDEBUG objectstream [obj#] loopindex + 1 index 1 index % Setup to put obj# into object number array + 4 index token pop put % Get stream, then get obj# and put into array + 2 index token pop pop pop % Get stream, get obj loc and clear stack + } for + % Move to the start of the object data + 1 index 4 index /First get % Get objectstream and start of first object + setfileposition % Move to the start of the data + % We disable PDFDEBUG while reading the data stream. We will + % print the data later + PDFDEBUG /PDFDEBUG false def % Save PDFDEBUG and disable it while reading + % Read the data for all objects. We check to see if we get + % the number of objects that we expect. + % Stack: objstreamdict N objectstream [obj#] PDFDEBUG + mark 4 -1 roll % Get objectstream + count 5 index add % Determine stack depth with objects + /PDFObjectStkCount exch def + resolveobjstreamopdict .pdfrun % Get PDF objects + PDFObjectStkCount count ne { % Check stack depth + ( **** Incorrect object count in object stream.\n) pdfformaterror + /resolveobjectstream cvx /rangecheck signalerror + } if + % We have the object data + counttomark array astore % Put objects into an array + exch pop % Remove mark + exch /PDFDEBUG exch def % Restore PDFDEBUG flag + % Save the objects into Objects + 0 1 2 index length 1 sub { % Loop through all objects + % Stack: objstreamdict N [obj#] [objects] loopindex + dup 3 index exch get % Get our current object number + dup resolved? { % If we already have this object + pop pop % Remove object and object number + } { % Else if we do not have this object + PDFDEBUG { (%Resolving compressed object: [) print dup =only ( 0]) = } if + Objects exch 3 index % Put the object into Objects + 3 index get + PDFDEBUG { dup === flush } if + lput + } ifelse + pop % Remove loop index + } for + pop pop pop pop % Remove objstream, N, (obj#], and [objects] +} bind def + +% When resolving an object reference, we stop at the endobj or endstream. +/resolveopdict mark + valueopdict { } forall + /endstream { endobj exit } bind + /endobj { endobj exit } bind + /endjobj { % Bug 689876. + ( **** Operator 'endobj' is misspelled as 'endjobj'.\n) pdfformaterror + endobj exit + } bind + % OmniForm generates PDF file with endobj missing in some + % objects. AR ignores this. So we have to do it too. + /obj { pop pop endobj exit } bind +.dicttomark readonly def + +/resolveR { % <object#> <generation#> resolveR <object> + PDFDEBUG { + PDFSTEPcount 1 le { + (%Resolving: ) print 2 copy 2 array astore == + } if + } if + 1 index resolved? { % If object has already been resolved ... + exch pop exch pop % then clear stack and return object + } { % Else if not resolved ... + PDFfile fileposition 3 1 roll % Save current file position + 1 index Objects exch lget % Get location of object from xref + 3 1 roll checkgeneration { % Verify the generation number + % Stack: savepos objpos obj# + ObjectStream 1 index lget dup 0 eq { % Check if obj in not an objstream + pop exch PDFoffset add PDFfile exch setfileposition + PDFfile token pop 2 copy ne + { ( **** Unrecoverable error in xref!\n) pdfformaterror + /resolveR cvx /rangecheck signalerror + } + if pop PDFfile token pop + PDFfile token pop /obj ne + { ( **** Unrecoverable error in xref!\n) pdfformaterror + /resolveR cvx /rangecheck signalerror + } + if + pdf_run_resolve % PDFfile resolveopdict .pdfrun + } { % Else the object is in an ObjectStream + % Process an objectstream object. We are going to resolve all + % of the objects in sthe stream and place them into the Objects + % array. + % Stack: savepos objpos obj# objectstream# + resolveobjectstream + resolved? { % If object has already been resolved ... + exch pop % Remove object pos from stack. + } { + pop pop null % Pop objpos and obj#, put null for object + } ifelse + } ifelse + } { % Else the generation number is wrong + % Don't cache if the generation # is wrong. + pop pop null % Pop objpos and obj#, put null for object + } ifelse % ifelse generation number is correct + exch PDFfile exch setfileposition % Return to original file position + } ifelse +} bind def + +% ================================ Streams ================================ % + +% We represent a stream by an executable dictionary that contains, +% in addition to the contents of the original stream dictionary: +% /File - the file or string where the stream contents are stored, +% if the stream is not an external one. +% /FilePosition - iff File is a file, the position in the file +% where the contents start. +% /StreamKey - the key used to decrypt this stream, if any. +% We do the real work of constructing the data stream only when the +% contents are needed. + +% Construct a stream. The length is not reliable in the face of +% different end-of-line conventions, but it's all we've got. +% +% PDF files are inconsistent about what may fall between the 'stream' keyword +% and the actual stream data, and it appears that no one algorithm can +% detect this reliably. We used to try to guess whether the file included +% extraneous \r and/or \n characters, but we no longer attempt to do so, +% especially since the PDF 1.2 specification states flatly that the only +% legal terminators following the 'stream' keyword are \n or \r\n, both of +% which are properly skipped and discarded by the token operator. +% Unfortunately, this doesn't account for other whitespace characters that +% may have preceded the EOL, such as spaces or tabs. Thus we back up one +% character and scan until we find the \n terminator. +/stream { % <dict> stream <modified_dict> + dup /Length oget 0 eq { + dup /Filter undef % don't confuse any filters that require data + } if + dup /F known dup PDFsource PDFfile eq or { + not { + dup /File PDFfile put + % make sure that we are just past the EOL \n character + PDFfile dup fileposition 1 sub setfileposition % back up one + + PDFfile read pop + dup 13 eq { + % If there had been a \n, token would have advanced over it + % thus, if the terminator was \r, we have a format error! + ( **** Warning: stream operator not terminated by valid EOL.\n) pdfformaterror + pop % fileposition is OK (just past the \r). + } { + % Otherwise, scan past \n + { 10 eq { exit } if + PDFfile read pop + } loop + } ifelse + dup /FilePosition PDFfile fileposition put + PDFDEBUG { + PDFSTEPcount 1 le { + (%FilePosition: ) print dup /FilePosition get == + } if + } if + } if + % Some (bad) PDf files have invalid stream lengths. This causes problems + % if we reposition beyond the end of the file. So we compare the given + % length to number of bytes left in the file. + dup /Length oget + dup PDFfile bytesavailable lt { % compare to to bytes left in file + PDFfile fileposition % reposition to the end of stream + add PDFfile exch setfileposition + } { + pop % bad stream length - do not reposition. + % This will force a length warning below + } ifelse + } { + pop + % We're already reading from a stream, which we can't reposition. + % Capture the sub-stream contents in a string. + dup /Length oget string PDFsource exch readstring + not { + ( **** Warning: Unexpected EOF in stream!\n) pdfformaterror + /stream cvx /rangecheck signalerror + } if + 1 index exch /File exch put + } ifelse + PDFsource token_nofail not { null } if + dup /endobj eq { + % Another case that Acrobat Reader handles -- 'endobj' without 'endstream'. + ( **** Warning: stream missing 'endstream'.\n) pdfformaterror + pop /endstream % fake a valid endstream + } if + /endstream ne { + ( **** Warning: stream Length incorrect.\n) pdfformaterror + dup /Length undef % prevent the use of the incorrect length. + cvx endobj exit % exit from .pdfrun now. + } if + cvx +} bind def +/endstream { + exit +} bind def + +% Contrary to the published PDF (1.3) specification, Acrobat Reader +% accepts abbreviated filter names everywhere, not just for in-line images, +% and some applications (notably htmldoc) rely on this. +/unabbrevfilterdict mark + /AHx /ASCIIHexDecode /A85 /ASCII85Decode /CCF /CCITTFaxDecode + /DCT /DCTDecode /Fl /FlateDecode /LZW /LZWDecode /RL /RunLengthDecode +.dicttomark readonly def + +% Extract and apply filters. +/filterparms { % <dict> <DPkey> <Fkey> filterparms + % <dict> <parms> <filternames> + 2 index exch knownoget { + oforce_recursive + exch 2 index exch knownoget { + % Both filters and parameters. + oforce_recursive + exch dup type /nametype eq { + 1 array astore exch + dup type /arraytype ne { 1 array astore } if exch + } if + } { + % Filters, but no parameters. + //null exch + dup type /nametype eq { 1 array astore } if + } ifelse + } { + % No filters: ignore parameters, if any. + pop //null { } + } ifelse +} bind def +/filtername { % <filtername> filtername <filtername'> + //unabbrevfilterdict 1 index .knownget { exch pop } if + dup /Filter resourcestatus { pop pop } { + Repaired exch % this error is not the creator's fault + ( **** ERROR: Unable to process ) pdfformaterror + 64 string cvs pdfformaterror + ( data. Page will be missing data.\n) pdfformaterror + /Repaired exch store % restore the previous "Repaired" state + % provide a filter that returns EOF (no data) + /.EOFDecode + } ifelse +} bind def +/applyfilters { % <parms> <source> <filternames> applyfilters <stream> + 2 index null eq { + { filtername filter } + } { + { % Stack: parms source filtername + 2 index 0 oget dup null eq { pop } { + exch filtername dup /JBIG2Decode eq { exch jbig2cachectx exch } if + } ifelse filter + exch dup length 1 sub 1 exch getinterval exch + } + } ifelse forall exch pop +} bind def + +% JBIG2 streams have an optional 'globals' stream obj for +% sharing redundant data between page images. Here we resolve +% that stream reference (if any) and run it through the decoder, +% creating a special -jbig2globalctx- postscript object our +% JBIG2Decode filter implementation looks for in the parm dict. +/jbig2cachectx { % <parmdict> jbig2cachectx <parmdict> + dup /JBIG2Globals knownoget { + % make global ctx + PDFfile fileposition exch % resolvestream is not reentrant + true resolvestream % stack after: PDFfileposition -file- + % Read the data in a loop until EOF to so we can move the strings into a bytestring + [ { counttomark 1 add index 60000 string readstring not { exit } if } loop ] + exch pop 0 1 index { length add } forall % compute the total length + % now copy the data from the array of strings into a bytestring + .bytestring exch 0 exch { 3 copy putinterval length add } forall pop + .jbig2makeglobalctx + PDFfile 3 -1 roll setfileposition + 1 index exch + /.jbig2globalctx exch put + } if +} bind def + +% When used with a PDF image dict, the JPXDecode filter needs to know +% about any ColorSpace entries, since this overrides whatever is in +% the image stream itself. We therefore propagate any such key into +% a filter's DecodeParms. +/jpxparmfix { % <streamdict> <readdata?> jpxparmfix <streamdict <readdata?> + 1 index /Filter .knownget + { /JPXDecode eq % we only need to do this for JPXDecode filters + % TODO: handle filter arrays + { + 1 index /ColorSpace knownoget { + 2 index /DecodeParms knownoget { + % insert in the existing DecodeParms dict + /ColorSpace 3 -1 roll put + }{ + 1 dict % need to create a custom DecodeParms dict + dup /ColorSpace 4 -1 roll put + 2 index exch /DecodeParms exch put + } ifelse + } if + } if + } if +} bind def + +% Resolve a stream dictionary to a PostScript stream. +% Streams with no filters require special handling: +% - Whether we are going to interpret the stream, or If we are just +% going to read data from them, we impose a SubFileDecode filter +% that reads just the requisite amount of data. +% Note that, in general, resolving a stream repositions PDFfile. +% Clients must save and restore the position of PDFfile themselves. +/resolvestream { % <streamdict> <readdata?> resolvestream <stream> + jpxparmfix + 1 index /F knownoget { + % This stream is stored on an external file. + (r) file 3 -1 roll + /FDecodeParms /FFilter filterparms + % Stack: readdata? file dict parms filternames + 4 -1 roll exch + pdf_decrypt_stream + applyfilters + } { + exch + dup /Length knownoget { 0 eq } { //false } ifelse { + () 0 () /SubFileDecode filter + } { + dup /FilePosition .knownget { + 1 index /File get exch setfileposition + } if + % Stack: readdata? dict + /DecodeParms /Filter filterparms + % Stack: readdata? dict parms filternames + 2 index /File get exch + % Stack: readdata? dict parms file/string filternames + dup length 0 eq { + % All the PDF filters have EOD markers, but in this case + % there is no specified filter. + exch dup type /filetype eq 5 index or { + % Use length for any files or reading data from any source. + 3 index /Length knownoget not { 0 } if + } { + 0 % Otherwise length of 0 for whole string + } ifelse + 4 index /IDFlag known { pop } { () /SubFileDecode filter } ifelse + exch + pdf_decrypt_stream % add decryption if needed + pop exch pop + } { + % Stack: readdata? dict parms source filternames + exch 3 index /Length knownoget { + () /SubFileDecode filter + } if exch + pdf_decrypt_stream % add decryption if needed + applyfilters + } ifelse + } ifelse + } ifelse + % Stack: readdata? dict file + exch pop exch pop +} bind def + +% ============================ Name/number trees ============================ % + +/nameoget { % <nametree> <key> nameoget <obj|null> + exch /Names exch .treeget +} bind def + +/numoget { % <numtree> <key> numoget <obj|null> + exch /Nums exch .treeget +} bind def + +/.treeget { % <key> <leafkey> <tree> .treeget <obj|null> + dup /Kids knownoget { + exch pop .branchget + } { + exch get .leafget + } ifelse +} bind def + +/.branchget { % <key> <leafkey> <kids> .branchget <obj|null> + dup length 0 eq { + pop pop pop null + } { + dup length -1 bitshift 2 copy oget + % Stack: key leafkey kids mid kids[mid] + dup /Limits oget aload pop + % Stack: key leafkey kids mid kids[mid] min max + 6 index lt { + pop pop + 1 add 1 index length 1 index sub getinterval .branchget + } { + 5 index gt { + pop + 0 exch getinterval .branchget + } { + exch pop exch pop .treeget + } ifelse + } ifelse + } ifelse +} bind def + +/.leafget { % <key> <pairs> .leafget <obj|null> + dup length 2 eq { + dup 0 get 2 index eq { 1 oget } { pop null } ifelse + exch pop + } { + dup length -1 bitshift -2 and 2 copy oget + % Stack: key pairs mid pairs[mid] + 3 index gt { 0 exch } { 1 index length 1 index sub } ifelse + getinterval .leafget + } ifelse +} bind def + +end % pdfdict +.setglobal diff --git a/gs/Resource/Init/pdf_cslayer.ps b/gs/Resource/Init/pdf_cslayer.ps new file mode 100644 index 000000000..b9ffb2d05 --- /dev/null +++ b/gs/Resource/Init/pdf_cslayer.ps @@ -0,0 +1,121 @@ +% Copyright (C) 2007 Artifex Software, Inc. +% All Rights Reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, modified +% or distributed except as expressly authorized under the terms of that +% license. Refer to licensing information at http://www.artifex.com/ +% or contact Artifex Software, Inc., 7 Mt. Lassen Drive - Suite A-134, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861, for further information. +% +% $Id$ +% +% Layer data extraction from Illustator CS2/CS3 files +% + +.languagelevel dup 2 .max .setlanguagelevel +.currentglobal //true .setglobal +/pdfdict load dup /pdfopdict get dup length dict copy dup begin /pdfopdict exch put + +/BMC { + currentdevice //null //false mark + /MarkType (BMC) + /BMC_Tag 8 1 roll 256 string cvs + //systemdict /CSLAYERDEBUG .knownget { + { (### BMC to deviceparams, tag: ) print dup = flush } if + } if + .putdeviceparamsonly dup type /booleantype ne { + cleartomark pop + } if + pop pop % discard the device and flag + pop pop % discard /BMC_Tag and the tag name +} bind def + +/BDC { % send selected BDC info to the device as properties + 10 dict begin % private working dictionary + /MarkType (BDC) def % BDC code + % process the tag and Title for now + exch 256 string cvs /BDC_Tag exch def % convert tag to a string + dup type /nametype eq { + dup Page /Properties rget not { + pop 0 dict % empty dict in case missing Properties Resource + } if + exch pop % discard the resource name + } if + + dup /Type knownoget { /OCG eq } { //false } ifelse { + % Illustrator CS3 and higher + dup /Name knownoget not { () } if % no Name, use an empty string + /BDC_Title exch def + + dup /Usage knownoget not { 0 dict } if + dup /View knownoget { /ViewState knownoget { /OFF ne } { //true } ifelse } { //true } ifelse + /BDC_Visible exch def + dup /Print knownoget { /PrintState knownoget { /OFF ne } { //true } ifelse } { //true } ifelse + /BDC_Printed exch def + pop % Usage dict + + dup /Intent knownoget { + dup type /nametype eq { + /Design eq + } { + //false exch { oforce /Design eq or } forall + } ifelse + } { + //false + } ifelse + /BDC_Editable exch def + + /BDC_Preview //true def + /BDC_Dimmed //false def + /BDC_Transparency //true def + /BDC_FlatLayer //true def + } { + % Illustrator CS2 + dup /Title knownoget not { () } if % no Title, use an empty string + /BDC_Title exch def + dup /Visible knownoget not { //true } if % no Visible flag, set true + /BDC_Visible exch def + dup /Preview knownoget not { //true } if % no preview flag, set true + /BDC_Preview exch def + dup /Editable knownoget not { //true } if % no Editable flag, set true + /BDC_Editable exch def + dup /Printed knownoget not { //true } if % no printed flag, set true + /BDC_Printed exch def + dup /Dimmed knownoget not { //true } if % no dimmed flag, set true + /BDC_Dimmed exch def + dup /Transparency knownoget not { //true } if % no Transparency flag, set true + /BDC_Transparency exch def + dup /FlatLayer knownoget not { //true } if % no flat layer flag, set true + /BDC_FlatLayer exch def + } ifelse + + % now send the collected info to the device + //systemdict /CSLAYERDEBUG .knownget { + { (### BDC info to deviceparams: ) print currentdict === flush } if + } if + currentdevice //null //false mark currentdict { } forall + .putdeviceparamsonly dup type /booleantype ne { + cleartomark pop + } if + pop pop % discard the device and flag + end % discard private dict + pop % done with properties dict +} bind def + +/EMC { + currentdevice //null //false mark /MarkType (EMC) + //systemdict /CSLAYERDEBUG .knownget { + { (### EMC to deviceparams) = flush } if + } if + .putdeviceparamsonly dup type /booleantype ne { + cleartomark pop + } if + pop pop % discard the device and flag +} bind def + +currentdict readonly pop end +.setglobal +.setlanguagelevel diff --git a/gs/Resource/Init/pdf_font.ps b/gs/Resource/Init/pdf_font.ps new file mode 100644 index 000000000..81b556e44 --- /dev/null +++ b/gs/Resource/Init/pdf_font.ps @@ -0,0 +1,1663 @@ +% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% PDF font operations. + +% Since PDF font are not unique and can collide with external font resources +% or each other, use font dictionaries obtained from PDF directly, never +% register them as resources or look them up by name. Use findfont oparator +% for non-embedded fonts only. CIDFont resources still use the old logic +% described below. + +% Finding a font by name can't give a proper result when PDF font names aren't unique. +% But it is only the way to obtain a font in Postscript after a font file is executed. +% Therefore using a FontName (and findfont) is allowed only +% immediately after a font file is executed. +% In all other cases the font to be found by a pointer through PDF structures. +% +% This ideal logics can't work for documents, +% which define a font resource with an embedded font, +% and another font resource with same BaseFont but with no embedded font +% (and possibly with no font descriptor). +% Our testbase does contain such examples. +% In this case we do find font by FontName (with findfont), +% since there is no other way to get a reasonable result. + +/.setlanguagelevel where { pop 2 .setlanguagelevel } if +.currentglobal true .setglobal +/pdfdict where { pop } { /pdfdict 100 dict def } ifelse +GS_PDF_ProcSet begin +pdfdict begin + +% We cache the PostScript font in an additional element of the +% font resource dictionary, called PSFont. + +% ---------------- Encodings ---------------- % + +/.notdefEncoding 256 { /.notdef } repeat 256 packedarray def + +% Apply a list of differences to an Encoding. +% Note that the differences may cause the array to grow. +/updateencoding { % <encoding|null> <differences> updateencoding <enc'> + % Calculate the length of the result. + % in case the incoming Encoding is null, use .notdefEncoding + exch dup null eq { pop .notdefEncoding } if + 0 0 3 index { + dup type /nametype ne { exch pop oforce } { pop 1 add } ifelse + % Differences list may not be in order, update the largest_index + % stack: <Differences> <encoding> <largest_index> <at_index> + 2 copy lt { exch pop dup } if % at_index is new largest + } forall + pop 1 index length .max array dup 0 4 -1 roll putinterval + exch 0 exch { + % Stack: enc' code element + dup type /nametype ne + { exch pop oforce } + { 3 copy put pop 1 add } + ifelse + } forall pop +} bdef + +% Get the Encoding for a font. +/getencoding % <base-encoding> <font-resource> getencoding <enc> + { /Encoding knownoget + { dup type /nametype eq + { + % The published PDF specification says the Encoding name + % "must be" one of the 3 predefined Encodings, implying + % that an error should occur if it isn't. However, Acrobat + % Reader simply ignores unknown names, and since there are + % some buggy applications that rely on this, we do the same. + + dup dup dup /MacRomanEncoding eq + exch /MacExpertEncoding eq or + exch /WinAnsiEncoding eq or + { exch pop findencoding } + { pop } + ifelse + } + { dup type /arraytype eq + { exch pop + ( **** Warning: Encoding is an array, not name or dictionary.\n) pdfformaterror + } + { dup /BaseEncoding knownoget + { dup / eq + { pop + ( **** Warning: Ignoring bad BaseEncoding name.\n) pdfformaterror + % as found in a PDF file from J.D.Edwards OneWorld (B7333), bug 687786 + } + { findencoding 3 -1 roll pop exch } + ifelse + } + if + /Differences knownoget { updateencoding } if + } + ifelse + } + ifelse + } { + ( **** Warning: Encoding not present.\n) pdfformaterror + } + ifelse + } bdef + +/checkGlyphNames2Unicode % <dict> checkGlyphNames2Unicode - +{ + PDFDEBUG { + dup /FontInfo .knownget { + /GlyphNames2Unicode .knownget { + (Has GlyphNames2Unicode) = + pop % { exch == ==} forall + } if + } if + } if + pop +} bind def + +% Define a font using it's FontName as the key. +% Adjust a font according to the Encoding and Widths in the font resource. +/adjustfont { % <font-resource> <font> adjustfont <font'> + getfontencoding + 3 copy .processToUnicode + getfontmetrics 5 -1 roll pop .updatefont { .completefont } if +} bind def + +% Get the (possibly modified) encoding of a font. +/getfontencoding { % <font-resource> <font> getfontencoding + % <font-resource> <font> <Encoding|null> + //systemdict /IgnoreTTEncoding .knownget not { //false } if { + 1 index /Subtype get /TrueType eq } { //false } ifelse { + //null + } { + 1 index /Encoding known { + dup /Encoding knownoget { 2 index getencoding } { //null } ifelse + } { + //null + } ifelse + } ifelse +} bdef + +% Returns true if the current glyph is in the Differences array at +% the specified index value. This is needed because the Widths +% array may map to the same glyph at different positions from the +% Encoding. We want to use the Width that was associated with the +% one specified in the Encoding::Differences list. +/match_in_diff % <Differences> <index> <glyphname> match_in_diff <bool> +{ false 4 1 roll 0 4 -1 roll % stack: false index glyphname at_index==0 Differences + { exch 1 index type /nametype ne { + % stack: false index glyphname Diff_element at_index + pop % Diff_element is new at_index + } { + % stack: false index glyphname Diff_element at_index + exch 2 index eq { + % stack: false index glyphname at_index + dup 3 index eq { + true 5 1 roll % stack: true false index glyphname at_index + pop exit + } if + } if + 1 add % at_index++ stack: false index glyphname at_index' + } ifelse + } forall + % stack: true false index glyphname + % or : false index glyphname at_index + pop pop pop +} bdef + +/unique_name { % <dict> </root> unique_name </unique> + % + % Note : this function interacts with pdf_write_encoding in src/gdevpdtw.c + % and with copied_drop_extension_glyphs in src\gxfcopy.c + % by adding a reserved substring (~GS~). + % + .namestring % <<>> (root) + 0 1 65535 { + 5 string cvs % <<>> (root) (0) + (~GS~) exch concatstrings + 1 index exch % <<>> (root) (root) (~GS~0) + concatstrings % <<>> (root) (root~GS~0) + dup % <<>> (root) (root~GS~0) (root~GS~0) + 3 index exch % <<>> (root) (root~GS~0) <<>> (root~GS~0) + known not { + exch pop exit % <<>> (root~GS~0) + } if + pop + } for + exch pop cvn % /root0 +} bdef + +% Get the metrics of a font, if specified. +/getfontmetrics { % <font-resource> <font> <Encoding|null> getfontmetrics + % <font-resource> <font> <Encoding|null> + % <Metrics|null> <GlyphMap|null> + + 2 index /Widths known { + dup //null eq { pop dup /Encoding get } if + 7 dict begin + dup length dict + /Metrics exch def + /Encoding exch def + /GlyphMap //null def + exch + dup /Widths oget /Widths exch def + % Stack: font font-res + % Note that widths are always based on a 1000-unit + % character space, but the FontMatrix may specify + % some other scale factor. Compensate for this here, + % by scaling the Widths if necessary. + 0.001 2 index /FontMatrix get 0 get + dup 0 eq { + % FontMatrix.xx == 0, so we cannot scale down by xx. + % - FontMatrix[0] == 0 implies either FontMatrix[1] <> 0 or + % FontMatrix cannot be inverted. In the 1st case we have + % FontMatrixNonHV == true and will render text with cshow + xshow. + % In the 2nd case, metrics in the PDF Font object cannot be enforced + % [by altering metrics in PS glyph space]. + % HACK: + % - we scale down by FontMatrix[1]; + % - given the format of Metrics entries we use, wy = 0 in glyph space; + % - as a result, the cshow procedure receives as wy the value we + % need for wx (all of this in PS user space). + pop + 2 index /FontMatrix get 1 get + dup 0 eq { pop 1 } if % sorry, no way to enforce PDF metrics by altering the font + } if + div + % Stack: font font-res mscale + /FirstChar 2 index /FirstChar oget def + /LastChar 2 index /LastChar oget def + + Encoding length LastChar le { + ( **** Warning: Font Encoding array size is smaller than character range.\n) + pdfformaterror + } if + + 1 index /FontDescriptor knownoget { + /MissingWidth knownoget not { 0 } if + } + { 1000 + } + ifelse /MissingWidth exch def + + Widths length LastChar FirstChar sub le { + ( **** Warning: Font Widths array size is smaller than character range.\n) + pdfformaterror + /Widths [Widths aload length LastChar FirstChar sub exch sub MissingWidth exch {dup} repeat] def + } if + FirstChar + + 0 Encoding + { % Stack: font font-res mscale first-char index charname + + 1 index FirstChar lt { MissingWidth } { + 1 index LastChar gt { MissingWidth } { Widths 2 index FirstChar sub get } ifelse + } ifelse + + % Stack: font font-res mscale first-char index charname width + 4 index mul + % The following 'loop' is only context for 'exit'. + { + % Work around a bug in pdfTeX, which can generate Encoding + % vectors containing nulls : + 1 index //null eq { exit } if + Metrics 2 index .knownget { + 1 index ne + } { + //false + } ifelse { + % Two or more Encoding elements refer same glyph name, + % and Widths specify different wihts for it. + % Since a Postscript font can't have different + % Metrics for same glyph name, + % we generate an unique name, and create a new + % Charstrings entry with same glyph value. + GlyphMap //null eq { + /Encoding Encoding dup length array copy def + /GlyphMap 4 dict def + } if + % To prevent too many new names, check whether + % we can use one already created for same glyph. + //true + GlyphMap { % f r s c i n w b n1 n2 + 4 index eq { % f r s c i n w b n1 + dup Metrics exch get % f r s c i n w b n1 w1 + 3 index eq { % f r s c i n w b n1 + 4 3 roll pop % f r s c i w b n1 + 3 1 roll pop % f r s c i n1 w + Encoding 3 index 3 index put + //false % f r s c i n1 w b + exit + } { + pop + } ifelse + } { % f r s c i n w b n1 + pop + } ifelse + } forall % f r s c i n w b + { % Do create a new name. + Metrics 2 index //unique_name exec % f r s c i n w nn + Encoding 4 index 2 index put + GlyphMap 1 index 5 -1 roll put % f r s c i w nn + exch + % Stack: font font-res mscale first-char index new_name width + } if + } if + 2 copy Metrics 3 1 roll put + exit + } loop + pop pop + 1 add + } + forall pop pop pop + exch Encoding Metrics GlyphMap end + } { + //null //null + } ifelse +} bdef + +currentdict /unique_name undef +currentdict /match_in_diff undef + +/ToUnicodeCMapReader 3 dict begin + /defineresource % <name> <dict> <cat-name> defineresource <dict> + { + pop + dup userdict exch /.lastToUnicode exch put + exch pop + } bind def + /CIDSystemInfo + { + ( **** Warning: ToUnicode CMap has invalid syntax near CIDSystemInfo.\n) pdfformaterror + /CIDSystemInfo + } bind def % A work around a bug in Altona.Page_3.2002-09-27.pdf - a slash is missed. + /CMapName + { + ( **** Warning: ToUnicode CMap has no CMapName.\n\ + See the comment to revision 6201 in gs/doc/ps2pdf.htm#Problems .\n) pdfformaterror + /CMap1 % arbitrary, PDF defineresource tolerates non-unique names + } bind def % A work around incorrect ToUnicode CMap generated by GS before rev. 6201. +currentdict end readonly def + +/string2number % <string> string2number <number> +{ 0 exch dup 0 exch 1 exch length 1 sub { % n () i + 1 index exch get % n () v + 3 2 roll 256 mul add exch % v+n*256 () + } for + pop % N +} bind def + +/copy&def % <key> <value> <bool> copy&def - +{ + { true + } { + currentdict gcheck { + dup gcheck not + } { + false + } ifelse + } ifelse + { currentglobal currentdict gcheck setglobal + exch dup length string copy exch + setglobal + } if + def +} bind def + +/.convert_ToUnicode-into-g2u % <GlyphNames2Unicode> <Encoding|null> <CMap> .convert_ToUnicode-into-g2u - +{ + PDFDEBUG { + (.convert_ToUnicode-into-g2u beg) = + } if + 3 2 roll begin + /.CodeMapData get % About the data format see gs_cmap.ps, the comment after "CMap operators". + 1 get % code maps + { + PDFDEBUG { + dup == + } if + dup length 1 sub 0 exch 5 exch { % e [] i + 2 copy get % e [] i (prefix) + string2number % e [] i prefix + 2 index 2 index 1 add get % e [] i prefix (key_size,?is_range,value_type,value_size) + dup 0 get 8 mul % e [] i prefix (key_size,?is_range,value_type,value_size) key_size*8 + 3 2 roll exch bitshift exch % e [] i prefix<<key_size*8 (key_size,?is_range,value_type,value_size) + dup 0 get exch 3 get % e [] i offset key_size value_size + 4 index 4 index 2 add get % e [] i offset key_size value_size (keys) + 5 index 5 index 3 add get % e [] i offset key_size value_size (keys) (values) + PDFDEBUG { + ( offset=) print 4 index =string cvs print + ( key_size=) print 3 index =string cvs print + ( value_size=) print 2 index = + ( keys=) print 1 index == + ( values=) print dup == + } if + 1 index length 0 eq { + % A single pair. + exch pop exch pop exch pop exch % e [] i (values) offset + 4 index null ne { + 4 index length 1 index gt { + 4 index exch get + } if + } if % e [] i (values) cid|name + exch + PDFDEBUG { + ( defined single: ) print 1 index =string cvs print ( ) print dup == + } if + false copy&def % e [] i + pop % e [] + } { + % A range. % e [] i offset key_size value_size (keys) (values) + dup length string copy % protect the original string from modifications below. + 0 4 index 2 mul 3 index length 1 sub { % e [] i offset key_size value_size (keys) (values) j + 2 index 1 index 6 index getinterval + string2number % e [] i offset key_size value_size (keys) (values) j keyL + PDFDEBUG { + ( keyL=) print dup =string cvs print + } if + 3 index 2 index 7 index add 7 index getinterval + string2number % e [] i offset key_size value_size (keys) (values) j keyL keyH + PDFDEBUG { + ( keyH=) print dup = + } if + 3 2 roll 6 index idiv 5 index mul % e [] i offset key_size value_size (keys) (values) keyL keyH J + 3 index exch 6 index getinterval % e [] i offset key_size value_size (keys) (values) keyL keyH (valueL) + 3 1 roll 1 exch { % e [] i offset key_size value_size (keys) (values) (value) k + 9 index null ne { + 9 index exch get % e [] i offset key_size value_size (keys) (values) (value) name + } if % e [] i offset key_size value_size (keys) (values) (value) cid|name + 1 index % e [] i offset key_size value_size (keys) (values) (value) cid|name (value) + PDFDEBUG { + ( defined from range: ) print 1 index =string cvs print ( ) print dup == + } if + true copy&def % e [] i offset key_size value_size (keys) (values) (value) + % Assuming the lowest byte of 'value' changes, others don't. + dup dup length 1 sub % e [] i offset key_size value_size (keys) (values) (value) (value) l + 2 copy get % e [] i offset key_size value_size (keys) (values) (value) (value) l v + % Modulo 256 increment prevents a rangecheck error when the result is stored in a string. + % The adjustment can happen only at the end of the loop where the string is discarded. Bug 688535. + 1 add 255 and put % e [] i offset key_size value_size (keys) (values) (value') + } for % e [] i offset key_size value_size (keys) (values) (value) + } for + pop pop pop pop pop pop pop % e [] + } ifelse + } for + pop % e + } forall + end + pop % + PDFDEBUG { + (.convert_ToUnicode-into-g2u end) = + } if +} bind def + +/.processToUnicode % <font-resource> <font-dict> <encoding|null> .processToUnicode - +{ + % Currently pdfwrite is only device which can handle GlyphNames2Unicoide to + % generate a ToUnicode CMaps. So don't bother with other devices. + currentdevice .devicename /pdfwrite eq { + PDFDEBUG { + (.processToUnicode beg) = + } if + 2 index /ToUnicode knownoget { + dup type /nametype eq { + % Bug687351.pdf defines /ToUnicode /Identity-H, what is incorrect. + ( **** Warning: Ignoring bad ToUnicode CMap.\n) pdfformaterror + pop + } { + + /PDFScanRules .getuserparam dup //null eq { + pop //PDFScanRules_null + } { + 1 dict dup /PDFScanRules 4 -1 roll put + } ifelse + //PDFScanRules_true setuserparams + PDFfile fileposition 3 -1 roll + + //false resolvestream + //ToUnicodeCMapReader begin + % Following Acrobat we ignore everything outside begincmap..endcmap. + dup 0 (begincmap) /SubFileDecode filter flushfile + /CIDInit /ProcSet findresource begin 12 dict begin + 0 (endcmap) /SubFileDecode filter cvx /begincmap cvx exch 2 .execn + endcmap + userdict /.lastToUnicode currentdict put + end end end + + PDFfile exch setfileposition + setuserparams + + 1 index /FontInfo .knownget not { + 1 index /FontInfo 5 dict dup 4 1 roll put + } if + dup /GlyphNames2Unicode .knownget not { + currentglobal exch dup gcheck setglobal + dup /GlyphNames2Unicode 100 dict dup 4 1 roll .forceput + 3 2 roll setglobal + } if % font-res font-dict encoding|null font-info g2u + exch pop exch % font-res font-dict g2u encoding|null + userdict /.lastToUnicode get % font-res font-dict g2u Encoding|null CMap + .convert_ToUnicode-into-g2u % font-res font-dict + //null % font-res font-dict null + } ifelse + } if + PDFDEBUG { + (.processToUnicode end) = + } if + } if + pop pop pop +} bind def + +% ---------------- Descriptors ---------------- % + +% Partial descriptors for the 14 built-in fonts. Note that +% from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor +% object has undergone a subtle change in its meaning which has serious +% consequences for searching with Acrobat: +% In PDF 1.1, the flag meant: Font has StandardEncoding +% In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet +/standardfontdescriptors mark + /Courier mark /Flags 16#23 .dicttomark + /Courier-Oblique 1 index + /Courier-Bold 1 index + /Courier-BoldOblique 1 index + /Helvetica mark /Flags 16#20 .dicttomark + /Helvetica-Oblique 1 index + /Helvetica-Bold 1 index + /Helvetica-BoldOblique 1 index + /Times-Roman mark /Flags 16#22 .dicttomark + /Times-Bold 1 index + /Times-Italic mark /Flags 16#62 .dicttomark + /Times-BoldItalic 1 index + /Symbol mark /Flags 16#4 .dicttomark + /ZapfDingbats 1 index +.dicttomark readonly def + +% ---------------- Utilities ---------------- % + + +/.pdforigfontcache_g 20 dict def +currentglobal false setglobal +systemdict /.pdforigfontcache_l 20 dict .forceput +setglobal + +% Find an original font, using cache to prevent adjustfont to accumulate changes. +/pdffindcachedfont { % <font_name> pdffindcachedfont <font> + dup //.pdforigfontcache_g exch .knownget { + exch pop + } { + dup .pdforigfontcache_l exch .knownget { + exch pop + } { + dup findfont dup + dup gcheck { //.pdforigfontcache_g } { .pdforigfontcache_l } ifelse + % Stack : font_name font font cache + 4 2 roll .growput + } ifelse + } ifelse +} bind def + +% Add original font to cache to prevent adjustfont to accumulate changes. +/pdfaddcachedfont { % <font_name> pdfaddcachedfont <font> + dup findfont dup % name font font + dup gcheck { //.pdforigfontcache_g } {.pdforigfontcache_l} ifelse + 4 2 roll % font d name font + put % font +} bind def + +/.remove_font_name_prefix { % <name> .remove_font_name_prefix <name> + dup .namestring (+) search { + true exch + { dup 65 lt exch 90 gt or { + pop false exit + } if + } forall + { pop exch pop cvn + } { + pop pop + } ifelse + } { + pop + } ifelse +} bind def + +% Find a font (except for embedded ones), and adjust its encoding if necessary. +/.pdfdfndict mark + /defaultfontname /Helvetica +.dicttomark readonly def +/pdffindfont { % <font-resource> <fontname> pdffindfont <font> + % If the font isn't available, synthesize one based on + % its descriptor. + dup /Font resourcestatus { + pop pop pdffindcachedfont + } { + 1 index /FontDescriptor knownoget { + % Stack: font-res fontname fontdesc + dup /Flags oget + dup 16#40 and -6 bitshift % 1, oblique/italic + 1 index 16#40000 and -17 bitshift add % 2, bold + exch 16#2 and 2 bitshift add % 8, serif + % We should look at the fixed flag, too. + % Stack: font-res fontname fontdesc properties + + % Even though /FontName is a required key in FontDescriptor dict + % (As of the PDF 1.4 Reference Manual), In the case of missing + % /FontName key, we substitue /BaseFont for the value of /FontName. + % Yet another case of broken PDF's that Adobe Reader accepts. + 1 index dup /FontName known { + /FontName oget + } { + ( **** FontDescriptor missing required /FontName key. BaseFont name used.\n) + pdfformaterror + pop 2 index % grab the BaseFont from the stack. + } ifelse + .remove_font_name_prefix + exch + % Analyzes font name and extract "Bold" and "Narrow" properties + % which are not described by the FontDescriptor Flags. + 0 2 index .fontnameproperties 6 and or + % Rebind the default font name to Helvetica so that + % fonts with no properties are handled correctly. + //.pdfdfndict begin .substitutefontname end + % Stack: font-res fontname fontdesc substname|null + Fontmap 1 index known not { + % No available good substitution, use the standard one. + pop 1 index .substitutefont + } if + dup 3 index ne QUIET not and { + (Substituting font ) print dup =only + ( for ) print 2 index =only (.) = flush + } if + pdffindcachedfont + % Stack: font-res fontname fontdesc font + % If this is a small-caps font, replace the CharString + % entries for a..z. + exch /Flags oget 16#20000 and 0 ne { + true .copyfontdict + dup /CharStrings 2 copy get dup length dict .copydict + % stack: font-res fontname font font /CharStrings CharStringsdict + 5 index /FirstChar get 97 .max + 6 index /LastChar get 122 .min 1 exch { + % Stack: font-res fontname font' font' /CharStrings charstrings code + % Note that this only remaps a-z, not accented characters. + 6 index /Widths oget 1 index 8 index /FirstChar get sub oget + 1 string dup 0 5 -1 roll put + % Stack: font-res font' font' /CharStrings charstrings code + % width (x) + 2 index exch dup cvn exch + dup 0 2 copy get 32 sub put 4 -1 roll { + % Stack: operand (X) width + 0 setcharwidth exch pop + currentfont /FontMatrix get matrix invertmatrix concat + 0.7 dup scale 0 0 moveto show + } /exec cvx 4 packedarray cvx put + } for put + } if + dup /FontName get 2 index ne { + true .copyfontdict + 2 copy exch /FontName exch put + } if + exch pop .completefont + } { + % No descriptor available, use the default algorithm. + pdffindcachedfont + } ifelse + } ifelse + exch pop +} bdef + +% ---------------- Type 1 fonts ---------------- % + +/buildType1 % <Type1-font-resource> buildType1 <font> + { dup /BaseFont get pdffindfont + } bdef + +% Read an embedded Type 1 font. +/readfontfilter { % <proc> readfontfilter <filter> + 0 () /SubFileDecode filter +} bdef + +% Adobe Acrobat doesn't skip space characters after eexec +/eexec_pdf_param_dict mark + .eexec_param_dict {} forall + /keep_spaces true +.dicttomark readonly def + +% When Type 1 font reading procedure is executing, a copy of this dictionary is current. +% We have to do something special about embedded fonts that execute definefont +% more than once -- that is the function of topFontDict. +% The whole type1 stream can be executed directly. There's no need to process +% Length1, 2, 3 keys. + +/readtype1dict 5 dict dup begin + /definefont { + exch pop + dup /UniqueID .knownget { + dup dup 0 lt exch 16#ffffff gt or { + ( **** Warning: Ignoring invalid /UniqueID = ) exch =string cvs + concatstrings (\n) concatstrings pdfformaterror + dup /UniqueID undef + } { + pop + } ifelse + } if + .completefont + } bdef + + /undef_proc_warning { + /Repaired true store % flag that we have warnings + UndefProcList exch 2 copy .knownget { 1 add } { 1 } ifelse put + } bdef + + /missing-type1-procs 6 dict begin + /-| { string currentfile exch readstring pop /-| //undef_proc_warning exec } executeonly bdef + /RD { string currentfile exch readstring pop /RD //undef_proc_warning exec } executeonly bdef + /|- { noaccess def /|- //undef_proc_warning exec } executeonly bdef + /ND { noaccess def /ND //undef_proc_warning exec } executeonly bdef + /| { noaccess put /| //undef_proc_warning exec } executeonly bdef + /NP { noaccess put /NP //undef_proc_warning exec } executeonly bdef + currentdict end readonly def + + /eexec { + % Assume the font dictionary is directly below the file on the stack + count 0 gt { /topFontDict 2 index cvlit store } if + //eexec_pdf_param_dict /eexecDecode filter + + //missing-type1-procs begin + /userdict .systemvar begin + //systemdict begin + readtype1dictcopy begin cvx stopped + + { currentdict end //missing-type1-procs eq { exit } if } loop + { stop } if + } bdef + + /readonly-op-dict << + /stringtype 0 + /arraytype 0 + /packedarraytype 0 + /dicttype 0 + >> readonly def + + /readonly { % bug 689617 + dup type //readonly-op-dict exch known { + readonly + } { + ( **** Warning: Type 1 font applies operator readonly to a wrong type.\n) + pdfformaterror + } ifelse } .bind def + + currentdict dup dup + /undef_proc_warning undef + /missing-type1-procs undef + /readonly-op-dict undef + +end readonly def + +currentdict /eexec_pdf_param_dict .undef + +/readtype1 { % <font-resource> <stream-dict> readtype1 <font> + 1 index exch % res res stream + PDFfile fileposition 3 1 roll % res pos res stream + dup /PFB known exch % res pos res pfb? stream + true resolvestream % res pos res pfb? file + exch { + //false /PFBDecode filter + } if + % Some buggy embedded fonts leave extra junk on the stack, + % so we have to make a closure that records the stack depth + % in a fail-safe way. This code also removes the mark when + % the implied cleartomark is not executed, i.e. Length3 == 0. + % Also restore dictstack depth. + % + //systemdict begin + //readtype1dict dup length 3 add dict copy begin + 1 index /BaseFont oget /savedFontName exch def + /topFontDict null def + /readtype1dictcopy currentdict def + { cvx exec } aload pop count 2 sub 3 packedarray cvx exec + % clean up the dictstack + { currentdict /topFontDict known not { end } { exit } ifelse } loop + count exch sub { pop } repeat + PDFfile 3 -1 roll setfileposition + pop pop + currentdict end end /topFontDict get + } bdef + +% ---------------- Type 3 fonts ---------------- % + +/buildType3 { % <Type3-font-resource> buildType3 <font> + 8 dict begin + /FontType 3 def + % If the font does not contain a Resources entry, then we use + % the resources from our current context. Page 391 of the PDF + % 1.6 spec says that the Resources dict is optional and if not + % present then we should use the Resources for the page. + % However we have a test file (687989) which uses a Type3 font + % inside a form XObject and the desired Resources are in the + % XObject dict and not in the Page dict. So we are going to + % the parent object to find resources instead of only going to + % the page dict when a font does not specify its required + % resources. + /Resources 1 index /Resources knownoget { + oforce + } { + LocalResources + } ifelse def + /FontBBox 1 index /FontBBox get cvx def + /FontMatrix 1 index /FontMatrix oget def + /CharProcs 1 index /CharProcs oget def + 1 index /Widths knownoget { + /Widths exch def + /FirstChar 1 index /FirstChar oget def + /LastChar 1 index /LastChar oget def + } if + /FontName 1 index /Name .knownget not { + PDFfile fileposition 16 32 string cvrs cvn + } if def + + /Encoding .notdefEncoding 2 index getencoding def + % We have to define BuildChar rather than BuildGlyph: + % there is no PDF equivalent of glyphshow, and we need + % the character code to access the Widths. + /BuildChar { + % Stack: font charcode + 1 index begin 3 dict begin + /Font 3 -1 roll def /CharCode 1 index def + Encoding exch get CharProcs exch knownoget { + { //false resolvestream + % Stack: filepos stream + % Don't let setgcolor set the color inside the BuildGlyph + % procedure, because this causes an /undefined error. + q //null /FillColor gput //null /StrokeColor gput + Font /Resources get exch pdfopdict .pdfruncontext + Q + } PDFfile fileposition 2 .execn % Keep pdfcount valid. + PDFfile exch setfileposition + } { + % PDF Type 3 fonts don't use .notdef + % d1 implementation adjusts the width as needed + 0 0 0 0 0 0 + pdfopdict /d1 get exec + } ifelse + end end + } bdef + dup currentdict Encoding .processToUnicode + currentdict end .completefont exch pop +} bdef +/.adjustcharwidth { % <wx> <wy> .adjustcharwidth <wx'> <wy'> + % Enforce the metrics, in glyph space, to the values found in the PDF Font object + % - force wy == 0 (assumed, and not stored in the PDF font) + % Even though PDF1.3-1.7 specifications state that this must be 0, + % Distiller sometimes creates Type3 fonts with non-zero wy. We set + % it to 0 since this is apparently what Acrobat Reader 4 and 5 do. + % PDF1.2 does not mention this restriction, it only says + % "see setcharwidth/ setcachedevice in the PostScript Reference". + % - get wx from the Widths array (do nothing if not present) + pop 0 + /Widths where { + begin + CharCode FirstChar ge CharCode LastChar le and { + exch pop Widths CharCode FirstChar sub get exch + } if end + } if +} bdef + +% ---------------- TrueType fonts ---------------- % + +/TTfonts mark + /Arial /Helvetica + /Arial,Italic /Helvetica-Oblique + /Arial,Bold /Helvetica-Bold + /Arial,BoldItalic /Helvetica-BoldOblique + /CourierNew /Courier + /CourierNew,Bold /Courier-Bold + /TimesNewRoman /Times-Roman + /TimesNewRoman,Italic /Times-Italic + /TimesNewRoman,Bold /Times-Bold + /TimesNewRoman,BoldItalic /Times-BoldItalic +.dicttomark readonly def + +/buildTrueType { % <TrueType-font-resource> buildTrueType <font> + dup /BaseFont oget + dup /Font resourcestatus dup { exch pop exch pop } if not + TTfonts 2 index known and { + dup TTfonts exch get + QUIET not { + (Substituting font ) print dup =only + ( for ) print 1 index =only (.) = flush + } if + exch 3 1 roll pdffindfont + true .copyfontdict + 2 copy exch /FontName exch put + exch pop .completefont + } { + pdffindfont + } ifelse +} bdef + +% Read an embedded TrueType font. +/readtruetype { % <font-resource> <stream-dict> readtruetype <font> + 1 index exch + PDFfile fileposition 3 1 roll + true resolvestream readfontfilter + % Stack: filepos fontres stream + 1 index /Subtype get /CIDFontType2 eq { + .loadttcidfont + % Stack: filepos fontres cidfont + } { + % filepos fontres stream + 1 index /FontDescriptor oget % filepos fontres stream fd + /Flags get 4 and 0 ne % filepos fontres stream is_symbolic + dup { //null } { StandardEncoding } ifelse + 3 index /Encoding known { + 3 index getencoding + } if % filepos fontres stream is_symbolic Encoding + dup 4 index exch % filepos fontres stream is_symbolic Encoding fontres Encoding + /prebuilt_encoding exch put % filepos fontres stream is_symbolic Encoding + .loadpdfttfont + } ifelse + exch pop + PDFfile 3 -1 roll setfileposition + % Ignore both the Encoding and the Widths. + exch pop +} bdef + +% ---------------- Type 0 fonts ---------------- % + +% Predefine the known CMaps, but only create them on demand. +/knownCMaps mark + /Identity-H { /Identity-H 0 makeIdentityCMap } + /Identity-V { /Identity-V 1 makeIdentityCMap } +.dicttomark def + +/makeIdentityCMap { % <cmapname> <wmode> .makeIdentityCMap - + .currentglobal true .setglobal 3 1 roll + /CIDInit /ProcSet findresource begin + 12 dict begin + begincmap + /WMode exch def + /CMapName exch def + /CIDSystemInfo 3 dict dup begin + /Registry (Adobe) def + /Ordering (Identity) def + /Supplement 0 def + end def + %/CMapName (see above) + /CMapVersion 1 def + /CMapType 1 def + %WMode (see above) + % The PDF documentation says that these CMaps map CIDs + % "1 to 65,536". This is a misprint for 0 to 65,535. + 1 begincodespacerange + % <0001> <00ff> <0100> <ffff> + <0000> <ffff> + endcodespacerange + 1 begincidrange + % <0001> <00ff> 1 <0100> <ffff> 256 + <0000> <ffff> 0 + endcidrange + endcmap + CMapName currentdict /CMap defineresource + knownCMaps CMapName 2 index put + end % CMap + end % CIDInit ProcSet + exch .setglobal +} bdef + +/buildType0 { % <Type0-font-resource> buildType0 <font> + dup /BaseFont get % FontName + 1 index /Encoding oget + dup type /nametype eq { + dup /CMap resourcestatus { + pop pop /CMap findresource + } { + knownCMaps 1 index .knownget + { exch pop exec } { /undefined signalerror } ifelse + } ifelse + } { + PDFfile fileposition exch + dup /CMapName get exch true resolvestream cvx exec + /CMap findresource + exch PDFfile exch setfileposition + } ifelse % CMap + [ + 3 index /DescendantFonts oget { exec resourcefont } forall + ] % subfonts + .composefontdict % composefont must insert FontInfo dictionary - see gs_cmap.ps . + % Stack: fontres name font + 3 copy exch pop null .processToUnicode + exch pop .completefont % Stack: fontres font + 1 index /FontMatrix knownoget { + dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall { + 1 index exch makefont exch /FontName get exch + exch pop .completefont + } { + pop + } ifelse + } if exch pop +} bdef + +% ---------------- CIDFontType0/2 fonts ---------------- % + +% Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2 +% arrays and using a (currently very inefficient) CDevProc. +% For detail, refer "PDF Reference" 2nd ed., p314 "5.6.3 CIDFonts". +% It notes default DW is 0, but Acrobat Reader uses 1000 as default. +% If DW is 0, currentpoint does not move by default in rendering text +% horizontally, the result is unreadable. You can check it by Acrobat. + +/.pdfDefaultDW 1000 def +/.pdfDefaultDW2 [ 880 -1000 ] def + +/addCIDmetrics { % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict> + dup length 5 add dict .copydict + dup /FID undef + dup /UniqueID undef + dup /XUID undef + % Insert the widths into the font. + + % Stack: pdfresource newfont + + 1 index /DW knownoget { + 1 index /DW 3 -1 roll put + } { + dup /DW .pdfDefaultDW put + } ifelse + + 1 index /W knownoget { + dup 2 index /W 3 -1 roll put + .pdfMakeInternalW 1 index /.internalW 3 -1 roll put + } if + + 1 index /DW2 knownoget { + 1 index /DW2 3 -1 roll put + } { + dup /DW2 .pdfDefaultDW2 put + } ifelse + + 1 index /W2 knownoget { + dup 2 index /W2 3 -1 roll put + .pdfMakeInternalW2 1 index /.internalW2 3 -1 roll put + } if + + dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put + exch pop +} bdef + +/.pdfMakeInternalMTXArray { % <mtx_array> <item_size> .pdfConvertInternalW <mtx_array'> + + % convert /W or /W2 to internal expression + % + % mtx_array: original /W or /W2 array + % item_size: number of metrics values per CID + % + % for detail of the metrics list format in PDF, + % refer PDF Ref. p.317 "Glyph Metrics in CIDFonts". + % + % format of single entry in internal expression + % + % [ + % [cid_begin cid_end] + % value_is_varied (bool) + % [ [values for cid_begin...] + % [values for cid_begin + 1] + % ... ] + % ] + % + + 7 dict + begin + /itemSize exch def + /M exch def % original /W or /W2 + /Msize M length def + /Mi { M i get } def % W[i] + /Mi1 { M i 1 add get } def % W[i + 1] + /putMTXEntry << + /arraytype { + [ + [Mi Mi Mi1 length itemSize idiv add 1 sub] + true + [ + 0 itemSize Mi1 length 1 sub { + [ exch 1 1 index itemSize add 1 sub { Mi1 exch get } for ] + } for + ] + ] + /i i 2 add def + } + /integertype { + [ + [Mi Mi1] + false + [[ i 2 add 1 i 1 add itemSize add { M exch get } for ]] + ] + /i i 3 add def + } + >> def + + /i 0 def + + [ { putMTXEntry Mi1 type get exec i Msize ge { exit } if } loop ] + end +} def + +/.pdfMakeInternalW { dup length 0 gt { 1 .pdfMakeInternalMTXArray } if } def +/.pdfMakeInternalW2 { dup length 0 gt { 3 .pdfMakeInternalMTXArray } if } def + +/.pdfGetMTXByCID { % <internalMTXArray> <cid> + % .pdfGetMTXByCID + % { <MTXEntry> true | false } + + % get values for given CID from internal format of /W or /W2 + + exch + { + { + dup 0 get {} forall % Stack: <cid> <entry> <cid_0> <cid_1> + 3 index lt { pop pop false exit } if + 2 index exch sub dup 0 lt { pop pop false exit } if + 1 index 1 get not { pop 0 } if + exch 2 get exch get true exit + } loop + { exit } if + } forall + dup type /arraytype eq { exch pop true } { pop false } ifelse +} def + + +% Apply the [D]W[2] metrics to a character before displaying. +/CIDWProc { % <w0x> <w0y> <llx> <lly> <urx> <ury> + % <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc + % <w0x'> ... <vy'> + begin % push <font> to currentdict + % <w1x> <w1y> <vx> <vy> won't be used and replaced, discard now + 5 1 roll pop pop pop pop + + { + currentdict /DW .knownget not { % no DW + .pdfDefaultDW exit % replace <w0x> by defaultDW + } if + + currentdict /.internalW .knownget not { % no W + exit % use already-stacked DW + } if + + dup length 0 eq { % W is null array + pop % discard unusable W + exit % use already-stacked DW + } if + + % W is finite array, try to get W_cid + 2 index .pdfGetMTXByCID { % got W, discard DW + exch pop {} forall + exit + } if + + exit + } loop + + FontType 11 eq { + 1000 div % <w0x'> (normalized W) + } if + 0 % <w0y'> + + % Stack: <w0x> <w0y> <llx> <lly> <urx> <ury> <cid> <w0x'> <w0y'> + 9 -2 roll pop pop % discard <w0x> <w0y> + 7 2 roll % put <w0x'> <w0y'> + + % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <cid> + 0 % <w1x'> + exch % put <w1x'> + + % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> <cid> + { + currentdict /DW2 .knownget not { % no DW2, use defaultDW2 + .pdfDefaultDW2 exit + } if + + currentdict /.internalW2 .knownget not { % has DW2, no W2 + exit % use already-stacked DW2 + } if + + dup length 0 eq { % W2 is null array + pop % discard unusable W2 + exit % use already-stacked DW2 + } if + + 2 index .pdfGetMTXByCID { % got W2_cid, discard DW2 + exch pop + exit + } if + + % could not get W2_cid + exit + + } loop + + exch pop % discard <cid> + + % Stack: <w0x'> <w0y'> <llx> <lly> <urx> <ury> <w1x'> { [<vy'> <w1y'>] | [<w1y'> <vx'> <vy'>] } + dup length 2 eq { % this is DW2 + FontType 11 eq {{1000 div}} {{}} ifelse forall exch + 8 index 2 div % <vx'> = <w0x'> / 2 + exch + }{ % assume W2 + FontType 11 eq {{1000 div}} {{}} ifelse forall + } ifelse + end % recover currentdict + +} def + +% <string> <match> tailmatch ==> <pre> true +% ==> <string> false +/tailmatch { + 2 copy length 1 index length .min + dup 2 index length exch sub exch getinterval + 1 index eq { + length 1 index length exch sub + 0 exch getinterval true + } { + pop false + } ifelse +} bind def + +/makeboldfont { + 16 dict begin + /strokewidth exch def + /basecidfont exch def + /FontMatrix [ 1 0 0 1 0 0 ] def + + /CIDFontName /.boldfont def + /CIDFontType 1 def + + /basefont-H /.basefont-H /Identity-H [ basecidfont ] composefont def + /basefont-V /.basefont-V /Identity-V [ basecidfont ] composefont def + + /CIDSystemInfo dup basecidfont exch get def + /FontBBox [ basecidfont /FontBBox get cvx exec + 4 2 roll basecidfont /FontMatrix get transform + 4 2 roll basecidfont /FontMatrix get transform + ] def + + /tmpstr 2 string def + /BuildGlyph { + gsave + exch begin + dup 256 idiv tmpstr exch 0 exch put + 256 mod tmpstr exch 1 exch put + rootfont /WMode known { rootfont /WMode get 1 eq } { false } ifelse + { basefont-V } { basefont-H } ifelse setfont + strokewidth setlinewidth + 1 setlinejoin + newpath + 0 0 moveto tmpstr false charpath stroke + 0 0 moveto tmpstr show + currentpoint setcharwidth + end + grestore + } bind def + + currentdict + end + dup /CIDFontName get exch /CIDFont defineresource +} bind def + +% <CIDFont-resource> <CIDFontName> findCIDFont <CIDFont-resource> <font> +% CIDFont-resource is not modified. +/findCIDFont { + { + dup /CIDFont resourcestatus { + pop pop /CIDFont findresource + exit + } if + .remove_font_name_prefix + dup dup length string cvs + (,Bold) tailmatch { + exch pop + cvn findCIDFont 0.03 makeboldfont + exit + } if + (,Italic) tailmatch { + exch pop + cvn findCIDFont + [ 1 0 0.3 1 0 0 ] makefont + exit + } if + (,BoldItalic) tailmatch { + exch pop + cvn findCIDFont 0.03 makeboldfont + [ 1 0 0.3 1 0 0 ] makefont + exit + } if + pop + + 1 index /CIDSystemInfo oget begin Registry (-) Ordering end + concatstrings concatstrings + cvn + QUIET not { + (Substituting CID font resource) print dup ==only + ( for ) print 1 index ==only (.\n) print + } if + exch pop + /CIDFont findresource + exit + } loop +} bdef + +/buildCIDType0 { % <CIDFontType0-font-resource> buildCIDType0 <font> + dup /BaseFont get findCIDFont exch pop +} bdef + +/buildCIDType2 { % <CIDFontType2-font-resource> buildCIDType2 <font> + dup /BaseFont get findCIDFont exch pop +} bdef + +/processCIDToGIDMap { % <fontres> <cidfont> processCIDToGIDMap <fontres> <cidfont> + 1 index /CIDToGIDMap knownoget { + PDFfile fileposition 4 1 roll + dup /Identity eq { + pop + } { + true resolvestream + % Stack: filepos fontres font mapstream + % Can't know the length of the decompressed stream, so allocate a big buffer... + dup 65534 string readstring { + % Length exceeded max string size, use an array of two strings + 1 index 65534 string readstring pop % maybe a null string - not important. + 2 array astore + % Stack: filepos fontres font mapstream array + dup 1 get length 65534 add + } { + dup length + } ifelse + 2 idiv + % Stack: filepos fontres font mapstream array/string CIDCount + 3 index exch /CIDCount exch put + exch closefile exch + dup /CIDMap 4 -1 roll put + } ifelse + 3 2 roll PDFfile exch setfileposition + } if +} bdef + +% Adjust a CIDFontType0 DW[2] in the font resource. +/adjustCIDType0 { % <font-resource> <font> adjustfont <font'> + addCIDmetrics + dup /CIDFontName get exch /CIDFont defineresource +} bind def + +% Adjust a CIDFontType2 DW[2] and CIDToGIDMap in the font resource. +/adjustCIDType2 { % <font-resource> <font> adjustfont <font'> + addCIDmetrics + dup /CIDFontType get 2 eq { % OpenType CFF font converts to CIDFontType 0 + processCIDToGIDMap % that ignores CIDMap. + } if + dup /CIDFontName get exch /CIDFont defineresource +} bind def + +% ---------------- Other embedded fonts ---------------- % + +/fontloadprocs mark + /Type1C /readType1C cvx + /CIDFontType0C /readCIDFontType0C cvx +.dicttomark readonly def + +% Read an embedded compressed font. +/readType1C { % <font-resource> <stream-dict> readType1C <font> + 1 index exch + PDFfile fileposition 3 1 roll + dup true resolvestream dup readfontfilter + % Stack: pos resource streamdict stream filter + 3 index /FontDescriptor oget /FontName oget + 1 index + /FontSetInit /ProcSet findresource begin //true //false ReadData + { exch pop exit } forall + 7 1 roll + closefile closefile pop + PDFfile 3 -1 roll setfileposition + pop pop +} bdef + +% Read an embedded CFF CIDFont. +/readCIDFontType0C { % <font-resource> <stream-dict> readCIDFontType0C <font> + PDFfile fileposition 3 1 roll + dup true resolvestream dup readfontfilter + % Stack: pos resource streamdict stream filter + 3 index /FontDescriptor oget /FontName oget + 1 index + /FontSetInit /ProcSet findresource begin //true //false ReadData pop + closefile closefile pop + PDFfile 3 -1 roll setfileposition + % Some broken Adobe software produces PDF files in which + % the FontName of the CFF font and the FontName in the + % FontDescriptor don't match the BaseFont in the font. + % Use the FontName, rather than the BaseFont, here. + dup /FontDescriptor oget /FontName oget /CIDFont findresource + addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource +} bdef + +% Read an embedded OpenType font. +/readOTTOfont { % <font-resource> <stream-dict> readOTTOfont <font> + 1 index exch % res res strdict + PDFfile fileposition 3 1 roll % res pos res strdict + dup //true resolvestream % res pos res strdict stream + dup readfontfilter % res pos res strdict stream filter + 3 index /FontDescriptor oget + /FontName oget % res pos res strdict stream filter /name + 1 index .init_otto_font_file % res pos res strdict stream filter /name filter' + //true + 6 index /CIDSystemInfo known % res pos res strdict stream filter /name filter' bool bool + ReadData % res pos res strdict stream filter fontset + { exch pop exit } forall % res pos res strdict stream filter font + dup /FontType get 9 eq { + % OpenType may contain simple CFF font, which is accesed as a CIDFont by PDF. + % The font is converted to Type 9 CIDFont resource, which ignores CIDMap attribute. + % The following code just shuffles GlyphDirectory to the same effect. + 4 index /CIDToGIDMap knownoget { + dup type /dicttype eq { + 1 index /GlyphDirectory get exch % res pos res strdict stream filter font dir c2g + //true resolvestream % res pos res strdict stream filter font dir c2g_file + 256 dict begin + 0 2 index 0 get def % copy .notdef + 0 1 16#7fffffff { + 1 index read not { pop exit } if % res pos res strdict stream filter font dir c2g_file cid hi + 256 mul % res pos res strdict stream filter font dir c2g_file cid hi + 2 index read not { pop pop exit } if % res pos res strdict stream filter font dir c2g_file cid hi lo + add % res pos res strdict stream filter font dir c2g_file cid gid + dup 0 ne { + dup 4 index length lt { + 3 index exch get % res pos res strdict stream filter font dir c2g_file cid charstr + def % res pos res strdict stream filter font dir c2g_file + } { + pop pop + } ifelse + } { + pop pop + } ifelse + } for + closefile pop % res pos res strdict stream filter font + dup length dict copy % res pos res strdict stream filter font' + dup /GlyphDirectory currentdict put % res pos res strdict stream filter font' + end + dup /GlyphDirectory get 0 exch { + pop .max + } forall + 1 index exch /CIDCount exch 1 add put + } { + pop + } ifelse + } if + } if + 7 1 roll % font res pos res strdict stream filter + closefile closefile pop pop % font res pos + PDFfile exch setfileposition % font res + pop % font +} bdef + +% ---------------- Font lookup ---------------- % + +% Some PDF files mis-identify font type of the embedded font streams or +% include raw PFB font streams. Length1, Length2, Length3 may be wrong or +% missing. Adobe Acrobat corrects these errors transparently to the user. +% +% We ignore the font type keys and recognize the font type by the 1st 4 bytes +% of the font stream. The PFB stream is recognized by the 1st 2 bytes. + +/fonttypeprocs mark % <font-resource> -proc- <font> + /Type0 //buildType0 + /Type1 //buildType1 + /MMType1 //buildType1 + /Type3 //buildType3 + /TrueType //buildTrueType + /CIDFontType0 //buildCIDType0 + /CIDFontType2 //buildCIDType2 +.dicttomark readonly def + +/adjustfonttypes mark + /Type1 //adjustfont + /MMType1 //adjustfont + /TrueType //adjustfont + /CIDFontType0 //adjustCIDType0 + /CIDFontType2 //adjustCIDType2 +.dicttomark readonly def + +% Bind a proc and define n names +% /name ... /name {proc} n bndef - +/bndef + { exch bind exch + { dup 3 1 roll def } repeat + pop + } bdef + +% Prototype for all procedures: <res> <desc> <stream> foo <font> +/font_tag_dict 13 dict begin + + % When the font stream is absent or cannot be read we load the font by the name. + /no_stream + { pop pop + dup /Subtype get % res res /subtype + dup / eq { + ( **** Warning: Font missing required Subtype, /Type1 assumed.\n) + pdfformaterror + pop /Type1 + } if + //fonttypeprocs exch get exec + } bdef + + /bad_stream + { ( **** Warning: Error reading font stream, loading font by the name\n) + pdfformaterror + //no_stream exec + } bdef + + <8001> % PFB + { dup /PFB //true put + exch pop readtype1 + } bdef + + (%!PS) (%!Fo) % Type1 + { exch pop readtype1 + } 2 bndef + + <01000401> <01000402> <01000403> <01000404> % Type 1C + <01000C02> + { exch pop + dup /Subtype get + fontloadprocs exch get exec + } 5 bndef + + <00010000> (true) (typ1) (ttcf) % TrueType OpenType + { exch pop readtruetype + } 4 bndef + + (OTTO) + { exch pop + readOTTOfont + } bdef + + +currentdict end readonly def +currentdict /bndef undef + +/resourcefont % <font-resource> resourcefont <font> +{ dup /PSFont .knownget dup { + pop /FID knownoget dup { pop type /fonttype eq } if + } if { + /PSFont get + } { + dup dup /FontDescriptor knownoget { + % font-res font-res font-desc + % The same font descriptor can be reused in a CID and non-CID contexts. + % Store CID and non-CID fonts under different keys. Bug 689301 + 1 index /Subtype knownoget dup { + pop dup /CIDFontType0 eq exch /CIDFontType2 eq or + } if { /CIDFontObject } { /FontObject } ifelse + % font-res font-res font-desc /key + 2 copy .knownget { + 4 1 roll pop pop pop % font-res obj + } { + 4 1 roll % /key font-res font-res font-desc + + dup /FontFile knownoget not { + dup /FontFile2 knownoget not { + dup /FontFile3 knownoget not { + //null + } if + } if + } if + % /key res res desc stream + dup //null ne { + PDFfile fileposition + 1 index //true resolvestream dup + 4 string readstring pop + exch closefile + PDFfile 3 -1 roll setfileposition + dup length 4 lt { pop /bad_stream } if + } { + /no_stream + } ifelse + % /key res res desc stream tag + + //font_tag_dict 1 index known not { + dup 0 2 getinterval <8001> eq { + 0 2 getinterval % /key res res desc stream pfb_tag + } { + (12345678>\n) dup /ASCIIHexEncode filter dup 4 -1 roll writestring closefile + ( **** Warning: unrecognized font file starts with <) exch concatstrings + pdfformaterror + /no_stream % /key res res desc stream unknown_tag + } ifelse + } if + + //font_tag_dict exch get exec + + 1 index /FontDescriptor oget % /key res font desc + 4 -1 roll 2 index % res font desc /key font + put % Save pointer to the font. + } ifelse + } { + dup /Subtype get + dup / eq { + ( **** Warning: Font missing required Subtype, /Type1 assumed.\n) + pdfformaterror + pop /Type1 + } if + //fonttypeprocs exch get exec + } ifelse + % Stack: font-res font + 1 index exch + 1 index /Subtype get + //adjustfonttypes exch .knownget { exec } { exch pop } ifelse + dup 3 1 roll /PSFont exch put + } ifelse + dup checkGlyphNames2Unicode +} bdef + +currentdict /font_tag_dict .undef +currentdict /fonttypeprocs .undef +currentdict /adjustfonttypes .undef + +drawopdict begin + /d0 { + .adjustcharwidth setcharwidth + } bdef + /d1 { + 2 copy % ... llx lly urx ury | urx ury + 0 ne exch 0 ne % ... llx lly urx ury | ury!=0 urx!=0 + 3 index 6 index eq and % ... llx lly urx ury | ury!=0 (urx!=0 && llx==urx) + exch 2 index 5 index eq and or { % ... llx lly urx ury | (urx!=0 && llx==urx) || (ury!=0 && lly==ury) + % The bounding box is empty and likely incorrect. Don't cache. + pop pop pop pop .adjustcharwidth setcharwidth + } { + 6 -2 roll .adjustcharwidth 6 2 roll setcachedevice + } ifelse + } bdef + /Tf { + 1 index Page /Font rget { + resourcefont exch Tf pop + } + { % Bug 689037 + ( **** Warning: Tf refers to an unknown resource name: ) pdfformaterror + 1 index .namestring pdfformaterror + ( Assuming it's a font name.\n) pdfformaterror + Tf + } ifelse + } bdef +end + +end % pdfdict +end % GS_PDF_ProcSet +.setglobal diff --git a/gs/Resource/Init/pdf_main.ps b/gs/Resource/Init/pdf_main.ps new file mode 100644 index 000000000..573f1ddc8 --- /dev/null +++ b/gs/Resource/Init/pdf_main.ps @@ -0,0 +1,1884 @@ +% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id: pdf_main.ps 8933 2008-08-03 17:54:46Z alexcher $ +% pdf_main.ps +% PDF file- and page-level operations. + +/.setlanguagelevel where { pop 2 .setlanguagelevel } if +.currentglobal true .setglobal +/pdfdict where { pop } { /pdfdict 100 dict def } ifelse +pdfdict begin + +% Patch in an obsolete variable used by some third-party software. +/#? false def + +% Test whether the current output device handles pdfmark. +/.writepdfmarkdict 1 dict dup /pdfmark null put readonly def +/.writepdfmarks { % - .writepdfmarks <bool> + currentdevice //.writepdfmarkdict .getdeviceparams + mark eq { false } { pop pop true } ifelse + systemdict /DOPDFMARKS known or +} bind def + +% For simplicity, we use a single interpretation dictionary for all +% PDF graphics execution, even though this is too liberal. +/pdfopdict mark + objopdict { } forall + drawopdict { } forall + /endstream { exit } bind + (%%EOF) cvn { exit } bind % for filters + /obj { ( **** Warning: Content stream is not terminated by 'endstream'.\n) + pdfformaterror pop pop exit + } bind + % PDF 1.1 operators + /BX { /BXlevel BXlevel 1 add store } bind + /EX { /BXlevel BXlevel 1 sub store } bind + /PS { cvx exec } bind + % PDF 1.2 operators + /BMC { pop } bind + /BDC { pop pop } bind + /EMC { } + /MP { pop } bind + /DP { pop pop } bind +.dicttomark readonly def + +% ======================== Main program ======================== % + +end % pdfdict +userdict begin + +/defaultfontname /Times-Roman def + +% Make sure the registered encodings are loaded, so we don't run the risk +% that some of the indices for their names will overflow the packed +% representation. (Yes, this is a hack.) +SymbolEncoding pop +DingbatsEncoding pop + +% Redefine 'run' so it recognizes PDF files. +systemdict begin +/.runps /run load def +/run { + dup type /filetype ne { (r) file } if + % skip leading whitespace characters (actually anything less than or equal to <sp>) + { dup ( ) .peekstring not { false exit } if + dup 0 get 32 le { pop dup read pop pop } { true exit } ifelse + } loop + exch pop + { + % Appletalk PAP sends short strings with %! header expecting a response. + % 'gv' swallows the %!PS line, then sends DSC comments beginning with %% + % and also waits for a response. The following avoids those hangs. + dup 2 string .peekstring pop dup (%!) eq exch (%%) eq or { + cvx .runps + } { + dup 1023 string .peekstring pop dup length 400 ge { + % "1024 string" exceeds current %stdin buffer + % Valid PDF file cannot be smaller than 400 bytes. + (%PDF-) search { + 3 1 roll pop pop + dup (%!PS) search not { + length 0 ne { + 1 index exch readstring pop pop + (%stderr) (w) file dup + ( **** Warning: File has some garbage before %PDF- .\n) + writestring flushfile + } { + pop + } ifelse + dup (%stdin) (r) file eq { + % Copy PDF from stdin to temporary file then run it. + null (w+) /.tempfile .systemvar exec exch 3 1 roll + % stack: tempname stdin tempfile + 64000 string + { + % stack: tempname stdin tempfile string + 2 index 1 index readstring + exch 3 index exch writestring + not { exit } if + } + loop + pop exch closefile + % stack: tempname tempfile + dup 0 setfileposition + dup runpdf + closefile deletefile + } { + runpdf + } ifelse + } { + pop pop pop pop cvx .runps % (%!PS) found first + } ifelse + } { + pop cvx .runps % (%PDF-) not found + } ifelse + } { + pop cvx .runps % too short for PDF + } ifelse + } ifelse + } { + closefile % file was empty + } ifelse +} bind odef +currentdict /runpdfstring .undef + + +/runpdfbegin { % <file> runpdfbegin - + userdict begin + % It turns out that the PDF interpreter uses memory more + % effectively if it is run under at least one level of save. + % This is counter-intuitive, and we don't understand why it happens, + % but the improvement is significant. + /PDFTopSave save def + 0 setobjectformat + /Page# null def + /Page null def + /DSCPageCount 0 def + /PDFSave null def + GS_PDF_ProcSet begin + pdfdict begin + pdfopen begin +} bind def + +/runpdfpagerange { % - runpdfpagerange <firstpage#> <lastpage#> + /FirstPage where + { pop FirstPage dup pdfpagecount gt + { (\nRequested FirstPage is greater than the number of pages in the file: ) print + pdfpagecount = flush + } if + } { + 1 + } ifelse + /LastPage where { pop LastPage pdfpagecount .min } { pdfpagecount } ifelse + 1 index 1 index gt + { ( No pages will be processed \(FirstPage > LastPage\).) = flush } + { QUIET not + { (Processing pages ) print 1 index =only ( through ) print dup =only + (.) = flush + } + if + } + ifelse +} bind def + +/dopdfpages { % firstpage# lastpage# dopdfpages - + << /PDFScanRules //true >> setuserparams % set scanning rules for PDF vs. PS + << /RenderTTNotdef systemdict + /RENDERTTNOTDEF get >> setuserparams % Should we render TT /.notdef + 1 exch + { dup /Page# exch store + QUIET not { (Page ) print dup == flush } if + pdfgetpage pdfshowpage + } for + << /PDFScanRules //null >> setuserparams % restore scanning rules for PS +} bind def + +/runpdfend { + Repaired { printrepaired } if + currentdict pdfclose + end % temporary dict + end % pdfdict + end % GS_PDF_ProcSet + PDFTopSave restore + end % userdict + 2 vmreclaim % couldn't hurt +} bind def + + +% Copy default subfile to a temporary file and return the file name +% as a PostScript name to protect it from restore. Return null if +% there's no default subfile. +% +% - pdf_collection_files /temp_file_name | null +/pdf_collection_files { + //null + Trailer /Root oget /Collection knownoget { + /D knownoget { % We have default document in the collection + Trailer /Root oget /Names knownoget { + /EmbeddedFiles knownoget { + exch nameoget dup //null ne { + /EF knownoget { + /F knownoget { + //true resolvestream % null strm + //null (w) /.tempfile % null strm (name) null (w) /.tempfile + .systemvar exec % null strm (name) file + 3 -1 roll % null (name) file strm + 32768 string % null (name) file strm (buf) + { 3 copy readstring % null (name) file strm (buf) file (data) bool + 3 1 roll % null (name) file strm (buf) bool file (data) + writestring % null (name) file strm (buf) bool + not { exit } if + } loop + pop closefile % null (name) file + closefile % null (name) + exch pop cvn % /name + } if + } if + } { + pop + } ifelse + } { + pop + } ifelse + } { + pop + } ifelse + } if + } if +} bind def + +/runpdf { % <file> runpdf - + //runpdfbegin exec + //pdf_collection_files exec + dup type /nametype ne { + copy_trailer_attrs + //runpdfpagerange exec + //dopdfpages exec + } if + //runpdfend exec + dup type /nametype eq { + .namestring dup (r) file + //runpdfbegin exec + copy_trailer_attrs + //runpdfpagerange exec + //dopdfpages exec + //runpdfend exec + deletefile + } { + pop + } ifelse +} bind def + +currentdict /runpdfpagerange .undef +currentdict /pdf_collection_files .undef + +end % systemdict +% Redefine the procedure that the C code uses for running piped input. +% It is OK to use { (%stdin) run } here, because a startjob cannot occur. +/.runstdin { + { (%stdin) run } execute0 +} bind def + +end % userdict +pdfdict begin + +% ======================== File parsing ======================== % + +% Read the cross-reference and trailer sections. + +/traileropdict mark + (<<) cvn { /dictlevelcount dictlevelcount 1 add store mark } bind + (>>) cvn { { .dicttomark } stopped { + ( **** File has unbalanced >> in trailer.\n) pdfformaterror + } if + /dictlevelcount dictlevelcount 1 sub def + dictlevelcount 0 eq { exit } if + } bind + ([) cvn { mark } bind % ditto + (]) cvn dup load +% /true true % see .pdfexectoken in pdf_base.ps +% /false false % ibid. +% /null null % ibid. + /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below +.dicttomark readonly def + +% Because of EOL conversion, lines with fixed contents might be followed +% by one or more blanks. +/lineeq % <filestr> <conststr> lineeq <bool> + { anchorsearch + { pop { ( ) anchorsearch not { () eq exit } if pop } loop } + { pop false } + ifelse + } bind def +/linene { lineeq not } bind def + + % Read original version (pre PDF 1.5) of the xref table. + % Note: The position is the location of 'xref'. The current PDFfile + % position is just after the 'XREF'. +/readorigxref % <pos> readorigxref <trailerdict> + { + pop % We do not need the position. + 0 % Initialize xref table error counter + { PDFfile token pop % first object # or trailer + dup /trailer eq { pop exit } if + PDFfile pdfstring readline pop + token pop % entry count + % remaining must be whitespace only (otherwise this xref Size was invalid. + exch dup length 0 ne { + false 1 index { 32 gt { pop true exit } if } forall { + ( **** Warning: xref subsection header has extra characters.\n) + pdfformaterror + /setxrefentry cvx /syntaxerror signalerror + } if + } if + pop % remove last + % This section might be adding new objects: + % ensure that Objects and Generations are big enough. + % stack: <err count> <first obj> <entry count> + 2 copy add growPDFobjects + { % stack: <err count> <obj num> + % Read xref line + PDFfile 20 string readstring pop % always read 20 chars. + token pop % object position + exch token pop % generation # + exch token pop % n or f + exch % stack: <err count> <obj#> <loc> <gen#> <tag> <remainder of line> + dup length 0 ne { + % check to make sure trailing garbage is just white space + dup { 32 gt { 5 -1 roll 1 add 5 1 roll } if } forall % bump error count on garbage + } if + pop % Stack: <err count> <obj#> <loc> <gen#> <tag> + dup /n eq { % xref line tag is /n + pop % pop dup of line tag + 0 3 1 roll % Set ObjectStream object number = 0 + //false setxrefentry % Save xref entry, don't change existing entries + 3 -1 roll pop % Remove ObjectStream object onumber + } + { % xref line tag was not /n + /f ne % verify that the tag was /f + { /setxrefentry cvx /syntaxerror signalerror + } if + } ifelse + pop pop % pop <obj location> and <gen num> + % stack: <err count> <obj num> + 1 add % increment object number + } repeat + pop % pop <obj #> + } loop + 0 ne { + ( **** Warning: length of some xref entries is not equal to 20 bytes.\n) + pdfformaterror + } if + /dictlevelcount 0 def + PDFfile traileropdict .pdfrun + } bind def + + % This dicitonary is used to read the xref dictionary. It should work for + % reading any dictionary. dictlevelcount must contain 0. +/xrefopdict mark + (<<) cvn { /dictlevelcount dictlevelcount 1 add def mark } bind + (>>) cvn { .dicttomark /dictlevelcount dictlevelcount 1 sub def + dictlevelcount 0 eq { exit} if } bind + ([) cvn { mark } bind % ditto + (]) cvn dup load +% /true true % see .pdfexectoken in pdf_base.ps +% /false false % ibid. +% /null null % ibid. + /R { /resolveR cvx 3 packedarray cvx } bind % see Objects below +.dicttomark readonly def + +% Get a variable length positive integer value from a stream. A value +% of zero is returned if the count is zero. +/getintn { % <stream> <count> getintn int + 0 exch { 256 mul 1 index read pop add } repeat + exch pop % Discard stream +} bind def + +% This array contains handlers for processing the different types of +% entries in the XRef stream. +% Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num> +% <field 2> <field 3> +% The handlers leave the stack unchanged. +/xref15entryhandlers [ + { % XRef entry type 0 - free or f type xref entry +% (free ) print +% (obj num: ) print 2 index pdfstring cvs print ( ) print +% (loc: ) print 1 index pdfstring cvs print ( ) print +% (gen: ) print dup === flush + } bind % Do nothing for free xref entries + % XRef entry type 1 - normal or n type xref entry + { % field 2 = obj loc, field 3 = gen num +% (normal ) print +% (obj num: ) print 2 index pdfstring cvs print ( ) print +% (loc: ) print 1 index pdfstring cvs print ( ) print +% (gen: ) print dup === flush + 0 3 1 roll % set stream number = 0 + //false setxrefentry + 3 -1 roll pop % remove stream number + } bind + % XRef entry type 2 - compressed object type xref entry + { % field 2 = object stream num, field 3 = index into object stream +% (Compressed objects: ) print +% (obj num: ) print 2 index pdfstring cvs print ( ) print +% (field 2: ) print 1 index pdfstring cvs print ( ) print +% (field 3: ) print dup === flush + 0 //false setxrefentry pop % set generation number = 0 + } bind +] def + + % Read the PDF 1.5 version of the xref table. + % Note: The position is the location of the start of the dictionary object + % In PDF 1.5, the XRef dictionary also serves as the trailer dictionary +/readpdf15xref % <pos> readpdf15xref <trailerdict> + { + PDFfile exch setfileposition % move to start of object + % Get object number, revision, and 'obj' and discard + PDFfile token pop pop + PDFfile token pop pop + PDFfile token pop pop + % Get the XRef dicitionary + /dictlevelcount 0 def PDFfile xrefopdict .pdfrun + % Verify that we have an XRef dictionary + dup /Type get /XRef ne { + /readpdf15xref cvx /syntaxerror signalerror + } if + % Ensure that we we have room in the objects array, etc. + dup /Size get growPDFobjects + % Create a stream for the XRef data + PDFfile token pop pop % Skip over 'stream' + dup stream false resolvestream + % Stack: <XRefdict> <xref stream> + % The Index array defines the ranges of object numbers in the + % XRef stream. Each value pair is consists of starting object + % number and the count of consecutive objects. + % Get the Index array, if present + 1 index /Index .knownget not { % If no Index array ... + [ 0 3 index /Size get ] % Default = [ 0 Size ] + } if + % Loop through the Index array + 0 2 2 index length 1 sub { + % Get start and end of object range + 2 copy get % Start of the range + dup 3 index 3 index 1 add get % Number of entries in range + % Loop through the range of object numbers + add 1 sub 1 exch { % Form end of range, set increment = 1 + % Stack: <Xrefdict> <xref stream> <Index array> <pair loc> <obj num> + % Get xref parameters. Note: The number of bytes for each parameter + % is defined by the entries in the W array. + 4 index /W get aload pop % Get W array values + % The first field indicates type of entry. Get first field value. + % If the num. of bytes for field 1 is 0 then default field value is 1 + 3 -1 roll dup 0 eq { pop 1 } { 6 index exch getintn } ifelse + % Get the handler for the xref entry type. We will execute the + % handler after we get the other two field values. + xref15entryhandlers exch get + 3 -1 roll 6 index exch getintn % Get second field + 3 -1 roll 6 index exch getintn % Get third field + 3 -1 roll exec % Execute Xref entry handler + pop pop pop % Remove field values and obj num + } for % Loop through Xref entries + pop % Remove Index array pair loc + } for % Loop through Index array entries + pop pop % Remove Index array and xref stream + } bind def + +% Read the cross-reference table. +% <pos> is the position either from the startxref statement or the /Prev +% entry in the prior trailer dictionary. +/readxref % <pos> readxref <trailerdict> + { + PDFoffset add PDFfile exch + % Check that the given location is within the file. + dup PDFfilelen gt { + ( **** Warning: Specified xref location is beyond end of file.\n) + pdfformaterror + /readxref cvx /invalidaccess signalerror + } if + setfileposition + % In some PDF files, this position actually points to + % white space before the xref line. Skip over this here. + { + PDFfile fileposition PDFfile read pop 32 gt { exit } if pop + } loop + dup % Make copy of the file position (before last char was read). + PDFfile exch setfileposition + % The PDF specification says that the 'xref' must be on a line + % by itself. The code here formerly used readline and linene to + % check this. However, Acrobat Reader only requires the line to + % begin with 'xref', and there are enough applications producing + % non-compliant PDF files that we have to do this too. + PDFfile pdfstring 0 4 getinterval readstring pop + (xref) eq + { + readorigxref % 'xref' -> original xref table + % if hybrid-reference PDF, also fetch the entries + % found in the XRef stream pointed by /XRefStm + dup /XRefStm knownoget { + readpdf15xref pop + } if + } + { readpdf15xref } % otherwise assume PDF 1.5 xref stream + ifelse + } bind def + +% Open a PDF file and read the header, trailer, and cross-reference. +/pdfopen { % <file> pdfopen <dict> + % Color space substitution in PDF is handled somewhat differently + % than in PostScript. A given device color space will be substituted + % if the corresponding "Default..." entry exists in the Page's + % Resource dictionary (which might be inhereted); there is no + % UseCIEColor to enable/disable color mapping. + % + % This behavior is achieved by always setting UseCIEColor to true + % in the page device dictionary. If the value of this parameter was + % originally false (i.e.: the output device does not perform color + % space substitution by default), the instances DefaultGray, + % DefaultRGB, and DefaultCMYK of the (local) ColorSpace category + % are redefined to be DeviceGray, DeviceRGB, and DeviceCMYK, + % respectively. This is not done if UseCIEColor is true by default, + % as in that case color substitution is presumably desired even + % if the file does not request it. + currentpagedevice /UseCIEColor .knownget dup { pop } if not + { .currentglobal false .setglobal + /DefaultGray { /DeviceGray } cvlit /ColorSpace defineresource pop + /DefaultRGB { /DeviceRGB } cvlit /ColorSpace defineresource pop + /DefaultCMYK { /DeviceCMYK } cvlit /ColorSpace defineresource pop + .setglobal + } + if + pdfopenfile begin + pdfopencache + currentdict end +} bind def + +/copy_trailer_attrs { % - copy_trailer_attrs - + writeoutputintents + .writepdfmarks { + % Copy bookmarks (outline) to the output. + Trailer /Root oget /Outlines knownoget { + /First knownoget { + { dup writeoutline /Next knownoget not { exit } if } loop + } if + } if + } if % end .writepdfmarks +} bind def + +% Verify that each entry in the xref table is pointing at an object with +% the correct object number and generation number. +/verify_xref % - verify_xref - +{ PDFfilelen + 1 1 Objects llength 1 sub % stack: filesize 1 1 <number of objects - 1> + { % Check if the object is free (i.e. not used). The values in + % Generations is the generation number plus 1. If the value in + % Generations is zero then the object is free. + % Stack: <filesize> <obj num> + Generations 1 index lget % Get the genration number + 0 ne { % Skip if object number is free + ObjectStream 1 index lget % Check if object is in objectstream + 0 eq { % We only check objects not in an objectstream + { % Use stop context since we may get an error if object is invalid + dup Objects exch lget % Get the object location + PDFoffset add dup 3 index ge % Compare object location to file size + { pop true } % Rebuild if location not in file + { PDFfile exch setfileposition % Go to the object location + true % Stack: <filesize> <obj num> <true> + PDFfile token pop % Read object number from file + 2 index eq { % Verify object number + PDFfile token pop % Read generation number from file + Generations 3 index % Get specified generaton number + lget 1 sub % Gen numbs are stored with 1 added. + eq { % Verify generation number + PDFfile token pop + /obj eq { % Verify 'obj' text + pop false % We have valid object, do not rebuild + } if + } if + } if + } ifelse + } .internalstopped + { true } if % If we stop then we need to rebuild + % Stack: <filesize> <obj num> <need rebuild flag> + { + ( **** Warning: File has an invalid xref entry: ) + pdfformaterror + pdfstring cvs pdfformaterror + (. Rebuilding xref table.\n) pdfformaterror + search_objects + exit + } if % If the entry is invalid + } { + % The object is in an object stream. We currently do not rebuild + % objects in an object stream. So If we find one, then abort the + % verification of the xref table entries. + pop exit % Pop object number and then exit loop + } ifelse % If not in an object stream + } if % If object entry is not free + pop % Remove object number + } for + pop % Remove the size of the file +} bind odef + +/pdfopencache { % - pdfopencache - + % Create and initialize some caches. + /PageCount pdfpagecount def + /PageNumbers PageCount 65534 .min dict def + /PageIndex PageCount 65534 .min array def +} bind def + +/pdfopenfile { % <file> pdfopenfile <dict> + pdfdict readonly pop % can't do it any earlier than this + 15 dict begin + /LocalResources 0 dict def + /DefaultQstate //null def % establish binding + /Printed where { pop } { + % Guess whether the output device is a printer. + /Printed currentpagedevice /OutputFile known def + } ifelse + /PSLevel1 where { pop } { /PSLevel1 false def } ifelse + % NB: PDFfile is used outside of the PDF code to determine that a + % PDF job is being processed; to not change or hide this key. + cvlit /PDFfile exch def + /PDFsource PDFfile def + /Repaired false def + currentglobal true .setglobal globaldict begin + /UndefProcList 0 dict def + end .setglobal + PDFfile dup 0 setfileposition + 0 () /SubFileDecode filter % to avoid file closure + pdfstring readstring pop + (%PDF-) search not {/pdfopen cvx /syntaxerror signalerror} if + length /PDFoffset exch def pop + % some badly formed PDF's (Visioneer) have something other than EOL + % after the version number. If we get an error, shorten the string + % and try again. + false exch % error encountered + { { cvr } stopped + { exch pop true exch 0 1 index length 1 sub dup 0 eq + { pop 0 exit } if % exit if string now empty + getinterval % trim character from right end and retry + } + { exch { + ( **** Warning: PDF version number not followed by EOL.\n) + pdfformaterror + } + if exit + } + ifelse + } loop + + /PDFversion exch def + % Read the last cross-reference table. + count /pdfemptycount exch def + /Trailer << >> def % Initialize to an emptry dict. + { initPDFobjects findxref readxref } .internalstopped { + recover_xref_data % Read failed. Attempt to recover xref data. + search_trailer % Search for the primary trailer + } { + /Trailer exch def % Save trailer dict after first xref table + % Read any previous cross-reference tables. When we are done, + % verify that the entries in the xref tables are valid if NoVerifyXref + % is not defined. + Trailer + { /Prev knownoget not { % If no previous xref table then ... + /NoVerifyXref where { pop } { verify_xref } ifelse exit + } if + { readxref } .internalstopped { + recover_xref_data % Read failed. Attempt to recover xref data. + exit % Exit loop since recover gets all obj data. + } if % If readxref stopped + % The PDF spec. says that each trailer dict should contain the required + % entries. However we have seen a PDF file that only has a Prev entry in + % the initial trailer dict. Acrobat complains but it accepts these files. + % To work with these files, we are copying any entries which we find in + % a previous trailer dict which are not present in the initial dict. + dup { + Trailer 2 index known { + pop pop % discard if key already present + } { + Trailer 3 1 roll put % add key if not present + } ifelse + } forall + } loop % Loop to previous trailer + } ifelse % Ifelse readxref stopped + + % Check for recursion in the page tree. Bug 689954, MOAB-06-01-2007 + verify_page_tree + + % Scan numbers in the range 2147483648..4294967295 in Encrypt dictionary + % as unsigned integers for compatibility with Acrobat Reader. Bug 689010. + << /PDFScanUnsigned //true >> setuserparams + { Trailer /Encrypt knownoget { + pop + pdf_process_Encrypt % signal error + } if + } stopped + << /PDFScanUnsigned //false >> setuserparams + { stop } if + + currentdict end + } bind def + +% Look for [\r\n]%%EO from the current position of the file. +% Return the position of %%EO if found or -1 . +/findeof { % <file> find_eof <file> <position> + -1 exch + { + dup bytesavailable 4 lt { exit } if + dup 0 (%%EO) /SubFileDecode filter flushfile + dup dup fileposition 5 sub setfileposition + dup 5 string readstring not { pop exit } if + dup (\r%%EO) eq exch (\n%%EO) eq or { + dup fileposition 4 sub + 3 1 roll exch pop + } if + } loop + exch +} bind def + +% Skip backward over the %%EOF at the end of the PDF file, and read +% the preceding startxref line. The PDF specification unambiguously +% requires that the %%EOF appear on a line by itself, and that the +% startxref and the following position value appear on separate lines; +% however, some applications truncate the %%EOF to %%EO, and/or put the +% startxref and the following value on the same line. +% There seems to be no limit on the amount of garbage that can be +% appended to the PDF file. Current record (60K) belongs to +% PDF-Out (v 2.0 - 35). We start the search for %%EO from the last 1024 +% bytes and continue from the beginning of the file. +/findxref { % - findxref <xrefpos> + PDFfile dup dup dup 0 setfileposition bytesavailable + dup /PDFfilelen exch def + % Find the last %%EOF string (within 1024 bytes) + 1024 sub PDFoffset .max + setfileposition findeof % search the last 1024 bytes + dup 0 le { + pop + dup PDFoffset setfileposition findeof % search from the beginnibg + dup 0 le { + ( **** Error: Cannot find a %%EOF marker anywhere in the file.\n) + pdfformaterror + /findxref cvx /syntaxerror signalerror + } if + } if + dup 3 1 roll setfileposition + % Stack: eofpos + % Check for whether this is, in fact, a valid PDF file. + dup PDFfilelen exch sub dup dup 7 gt exch 5 lt or { + pop true + } { + string PDFfile exch readstring pop + dup (%%EOF\n) eq exch dup (%%EOF\r) eq + exch dup (%%EOF\r\n) eq exch (%%EOF) eq or or or not + } ifelse { + ( **** Warning: File has a corrupted %%EOF marker, or garbage after %%EOF.\n) + pdfformaterror + } if + PDFfile exch setfileposition + % Now read the startxref and xref start position. + prevline token not { null } if dup type /integertype eq { + exch pop cvi % xref start position + exch PDFfile exch setfileposition + prevline dup (startxref) linene { + % startxref not on a line by itself. We have found PDF from + % www.verypdf.com in which the startxref was on the same line as + % the end of trailer dictionary. Check for this. Note: This + % violates the spec. + dup (startxref) search { + % found startxref - print warning + pop pop pop % clear strings from search + ( **** Warning: format of the startxref line in this file is invalid.\n) + pdfformaterror + } { % no startxref - we have a problem. + /findxref cvx /syntaxerror signalerror + } ifelse + } if + pop pop + } { % else, this file has 'startxref #####' format + (startxref) ne { /findxref cvx /syntaxerror signalerror } if + cvi % xref start position + ( **** Warning: format of the startxref line in this file is invalid.\n) + pdfformaterror + exch PDFfile exch setfileposition + } ifelse +} bind def +/stderrfile (%stderr) (w) file def +/stderrprint { % <string> stderrprint - + //stderrfile dup 3 -1 roll writestring flushfile +} bind def +/pdfformaterror { % <string> pdfformaterror - + stderrprint + /Repaired true store +} bind def + +/knownoget_safe +{ 2 copy knownoget { 3 1 roll pop pop //true } { pop pop //false } ifelse +} odef + +/printProducer { + Trailer /Info { knownoget_safe } stopped { pop pop false } if { + /Producer knownoget not { null } if + } { + null + } ifelse + dup null eq { + pop + } { + ( **** The file was produced by: \n **** >>>> ) stderrprint + % Handle a Unicode Producer. + (\376\377) anchorsearch { + pop dup length 2 idiv string 0 1 2 index length 1 sub { + % Stack: origstr newstr i + 1 index exch 3 index 1 index 2 mul 1 add get put + } for exch pop + } if + stderrprint + ( <<<<\n) stderrprint + } ifelse +} bind def +% The UndefProcList collects noisy warnings. +% This gets rid of many multiple warnings from pdf_font.ps +/printCollectedWarnings { + UndefProcList length 0 gt { + (\n **** Embedded font uses undefined procedure\(s\): ) stderrprint + UndefProcList { + exch .namestring stderrprint ( ) stderrprint + =string cvs stderrprint ( times, ) stderrprint + } forall + (\n) stderrprint + } if +} bind def +/printrepaired { + printCollectedWarnings + (\n **** This file had errors that were repaired or ignored.\n) + stderrprint + printProducer + ( **** Please notify the author of the software that produced this\n) + stderrprint + ( **** file that it does not conform to Adobe's published PDF\n) + stderrprint + ( **** specification.\n\n) + stderrprint +} bind def + +% Write the outline structure for a file. Uses linkdest (below). +% omit links to pages that don't exist. +/writeoutline % <outlinedict> writeoutline - + { mark + 0 2 index /First knownoget + { { exch 1 add exch /Next knownoget not { exit } if } loop } + if + % stack: dict mark count + dup 0 eq + { pop 1 index } + { 2 index /Count knownoget { 0 lt { neg } if } if + /Count exch 3 index + } + ifelse + { + dup /A knownoget { + dup /URI known { + /A mark 3 2 roll % <<>> /A [ <<action>> + { oforce } forall + .dicttomark + 3 2 roll + } { + dup /D knownoget { + exch pop exch dup length dict copy dup /Dest 4 -1 roll put + } { + /N knownoget { % Assume /S /Named + namedactions exch .knownget { exec } if + } if + } ifelse + } ifelse + } if + linkdest + } stopped + { + cleartomark % ignore this link + ( **** Warning: Outline has invalid link that was discarded.\n) + pdfformaterror + } { + /Title oget /Title exch /OUT pdfmark + } + ifelse + /First knownoget + { { dup writeoutline /Next knownoget not { exit } if } loop } + if + } bind def + +% Close a PDF file. +/pdfclose % <dict> pdfclose - + { begin + PDFfile closefile + end + } bind def + +% ======================== Page accessing ======================== % + +% Get a (possibly inherited) attribute of a page. +/pget % <pagedict> <key> pget <value> -true- + % <pagedict> <key> pget -false- + { + 2 copy knownoget + { exch pop exch pop true } + { exch /Parent knownoget + { exch pget } + % finally see if the key is (misplaced) in the Root Catalog dict + { dup Trailer /Root oget exch knownoget dup { + 3 -1 roll ( **** Warning: The /) pdfformaterror 50 string cvs pdfformaterror + ( key is missing from the Page tree.\n) pdfformaterror + } + { exch pop } + ifelse + } + ifelse + } + ifelse + } bind def + +% Get the value of a resource on a given page. +/rget { % <resname> <pagedict> <restype> rget <value> -true- + % <resname> <pagedict> <restype> rget -false- + LocalResources 1 index knownoget { + 3 index knownoget + } { + false + } ifelse { + exch pop exch pop exch pop true + } { + exch /Resources pget { + exch knownoget { exch knownoget } { pop false } ifelse + } { + pop pop false + } ifelse + } ifelse +} bind def + +% Get the total number of pages in the document. +/pdfpagecount % - pdfpagecount <int> + { Trailer /Root oget /Pages oget + dup /Count knownoget { + dup 0 le { + pop ( **** Warning: Invalid Page count.\n) pdfformaterror + % find the last page and use that as the Count + 1 1 999999999 { + dup pdffindpage? + exch pop + //null eq { exit } { pop } ifelse + } for + 1 sub % decrement to last page that we were able to find + 2 copy /Count exch put + } if + exch pop + } { + dup /Type oget /Page eq { + << exch 1 array astore /Kids exch /Count 1 /Type /Pages >> + Trailer /Root oget /Pages 3 -1 roll put + 1 + ( **** Warning: No /Pages node. The document root directly point a page.\n) + pdfformaterror + } { + ( **** Warning: Page count not found; assuming 1.\n) + pdfformaterror + pop 1 + } ifelse + } ifelse + } bind def + +% Check for loops in the 'page tree' but accept an acyclic graph. +% - verify_page_tree - +/verify_page_tree { + Trailer /Root oget /Pages oget + 10 dict begin + /verify_page_tree_recursive { + dup 1 def + dup /Kids knownoget { + { oforce + currentdict 1 index known { + ( **** Error: there's a loop in the page tree. Giving up.\n) pdfformaterror + /verify_page_tree cvx /syntaxerror signalerror + } if + verify_page_tree_recursive + } forall + } if + currentdict exch undef + } def + verify_page_tree_recursive + end +} bind def + +/pdffindpage? { % <int> pdffindpage? 1 null (page not found) + % <int> pdffindpage? 1 noderef (page found) + % <int> pdffindpage? 0 null (Error: page not found) + Trailer /Root oget /Pages get + { % We should be able to tell when we reach a leaf + % by finding a Type unequal to /Pages. Unfortunately, + % some files distributed by Adobe lack the Type key + % in some of the Pages nodes! Instead, we check for Kids. + dup oforce /Kids knownoget not { exit } if + exch pop null + 0 1 3 index length 1 sub { + 2 index exch get + dup oforce dup /Kids known { /Count oget } { pop 1 } ifelse + % Stack: index kids null noderef count + dup 5 index ge { pop exch pop exit } if + 5 -1 roll exch sub 4 1 roll pop + } for exch pop + % Stack: index null|noderef + dup null eq { pop pop 1 null exit } if + } loop +} bind def + +% Find the N'th page of the document by iterating through the Pages tree. +% The first page is numbered 1. +/pdffindpageref { % <int> pdffindpage <objref> + dup pdffindpage? + % Stack: index countleft noderef + 1 index 1 ne { pop pop /pdffindpage cvx /rangecheck signalerror } if + exch pop + PageIndex 2 index 1 sub 65533 .min 2 index oforce put + PageNumbers 1 index oforce 3 index dup 65534 le + { put } + { pop pop pop } % don't store more than 65534 pagenumbers + ifelse + exch pop +} bind def +/pdffindpage { % <int> pdffindpage <pagedict> + pdffindpageref oforce +} bind def + +% Find the N'th page of the document. +% The first page is numbered 1. +/pdfgetpage % <int> pdfgetpage <pagedict> + { PageIndex 1 index 1 sub dup 65533 lt + { get } + { pop pop null } + ifelse + dup null ne + { exch pop oforce } + { pop pdffindpage } + ifelse + } bind def + +% Find the page number of a page object (inverse of pdfgetpage). +/pdfpagenumber % <pagedict> pdfpagenumber <int> + { % We use the simplest and stupidest of all possible algorithms.... + PageNumbers 1 index .knownget + { exch pop + } + { 1 1 PageCount 1 add % will give a rangecheck if not found + { dup pdfgetpage oforce 2 index eq { exit } if pop + } + for exch pop + } + ifelse + } bind def + +% Arrange the four elements that define a rectangle into a 'normal' order. +/normrect_elems % <x1> <y1> <x2> <y2> normrect_elems <llx> <lly> <urx> <ury> +{ + exch 4 1 roll % <x2> <x1> <y1> <y2> + 2 copy gt { exch } if % <x2> <x1> <lly> <ury> + 4 2 roll 2 copy lt { exch } if % <lly> <ury> <urx> <llx> + 4 1 roll exch % <llx> <lly> <urx> <ury> +} bind def + +% Arrange a rectangle into a 'normal' order. I.e the lower left corner +% followed by the upper right corner. +/normrect % <rect> normrect <rect> +{ + aload pop normrect_elems 4 array astore +} bind def + +/fix_empty_rect_elems % </Name> <x1> <y1> <x2> <y2> fix_empty_rect_elems <x1> <y1> <x2'> <y2'> +{ dup 3 index eq { //true } { 1 index 4 index eq } ifelse { + pop pop pop pop + ( **** Warning: File has an empty ) pdfformaterror pdfstring cvs pdfformaterror + (. Using the current page size instead.\n) pdfformaterror + 0 0 currentpagedevice /PageSize get aload pop + } { + 5 -1 roll pop + } ifelse +} bind def + +/boxrect % <llx> <lly> <urx> <ury> boxrect <x> <y> <w> <h> + { exch 3 index sub exch 2 index sub + } bind def +/resolvedest { % <name|string|other> resolvedest <other|null> + dup type /nametype eq { + Trailer /Root oget /Dests knownoget { + exch knownoget not { null } if + } { + pop null + } ifelse + } { + dup type /stringtype eq { + Trailer /Root oget /Names knownoget { + /Dests knownoget { + exch nameoget + } { + pop null + } ifelse + } { + pop null + } ifelse + } if + } ifelse +} bind def + +% Procedures to do the necessary transformations of view destinations +% <PDF2PS_matrix> <rot> <view> -- <view'> +/viewdestprocs 8 dict dup begin + /Fit { exch pop exch pop } bind def + /FitH { + aload pop + 0 4 -1 roll 1 and 0 eq { exch } if + 4 -1 roll transform exch pop + 2 array astore + } bind def + /FitV { + aload pop + 0 4 -1 roll 1 and 0 ne { exch } if + 4 -1 roll transform pop + 2 array astore + } bind def + /FitB /Fit load def + /FitBH /FitH load def + /FitBV /FitV load def + /XYZ { + aload pop + 3 1 roll + 2 copy 7 -1 roll 1 and 0 ne { exch } if 4 2 roll % odd rotation switches x<->y + 2 { dup null eq { pop 0 } if exch } repeat % replace nulls with 0 + 7 -1 roll transform % transform coordinates + 2 { 3 -1 roll null eq { pop null } if exch } repeat % put the nulls back + 3 -1 roll + 4 array astore + } bind def + /FitR { + exch pop + aload pop + 2 { 5 index transform 4 2 roll } repeat normrect_elems + 5 array astore + exch pop + } bind def +end readonly def + +/linkdest { % <link|outline> linkdest + % ([/Page <n>] /View <view> | ) <link|outline> + dup /Dest knownoget + { resolvedest + dup type /dicttype eq { /D knownoget not { null } if } if + dup null eq + { pop } + { dup 0 oget + false % don't have a page# and transformation matrix (yet) + 1 index type /dicttype eq { + 1 index /Type knownoget { + /Page eq { + pop % the "false" flag + dup pdf_cached_PDF2PS_matrix exch + dup /Rotate pget not { 0 } if 90 idiv exch + pdfpagenumber + true % now we have a page# and a transformation matrix + } if + } if + } if + % stack: <link|outline> <dest> ( <PDF2PS_matrix> <rot> <page#> true | <page> false ) + { + /Page exch 6 2 roll + % stack: [/Page <page#>] <link|outline> <dest> <PDF2PS_matrix> <rot> + 3 -1 roll dup length 1 sub 1 exch getinterval /View 4 1 roll + % stack: [/Page <page#>] <link|outline> /View <PDF2PS_matrix> <rot> <view> + //viewdestprocs 1 index 0 get get exec + 3 -1 roll + } { + pop + dup length 1 sub 1 exch getinterval /View exch 3 -1 roll + } ifelse + } + ifelse + } + if +} bind def +% <pagedict> mark ... -proc- <page#> <error> +/namedactions 8 dict dup begin + /FirstPage { 1 //false } def + /LastPage { pdfpagecount //false } def + /NextPage { counttomark 2 add index pdfpagenumber 1 add dup pdfpagecount gt } bind def + /PrevPage { counttomark 2 add index pdfpagenumber 1 sub dup 1 lt } bind def +end readonly def +% <pagedict> <annotdict> -proc- - +/annottypes 5 dict dup begin + /Text { + mark exch + { /Rect /Open /Contents } + { 2 copy knownoget { 3 -1 roll } { pop } ifelse } + forall pop /ANN pdfmark + } bind def + /Link { + mark exch + dup /C knownoget { /Color exch 3 -1 roll } if + { /Rect /Border } + { 2 copy knownoget { 3 -1 roll } { pop } ifelse } + forall dup /A knownoget { + dup /URI known { + /A mark 3 2 roll % <<>> /A [ <<action>> + { oforce } forall + .dicttomark + 3 2 roll + } { + dup /D knownoget { + exch pop exch dup length dict copy dup /Dest 4 -1 roll put + } { + /N knownoget { % Assume /S /Named + namedactions exch .knownget { + exec { + pop + ( **** Warning: Ignoring a named action pointing out of the document page range.\n) + pdfformaterror + } { + /Page exch 3 -1 roll + } ifelse + } if + } if + } ifelse + } ifelse + } if + linkdest pop /LNK pdfmark + } bind def +end readonly def + +% **** The following procedure should not be changed to allow clients +% **** to directly interface with the constituent procedures. GSview +% **** and some Artifex customers rely on the pdfshowpage_init, +% **** pdfshowpage_setpage, pdfshowpage_finish so all logic should be +% **** implemented in one of those three procedures. +/pdfshowpage % <pagedict> pdfshowpage - + { dup /Page exch store + pdfshowpage_init + pdfshowpage_setpage + pdfshowpage_finish + } bind def + +/pdfpagecontents % <pagedict> pdfpagecontents <contents> + { } bind def + +/pdfshowpage_init % <pagedict> pdfshowpage_init <pagedict> + { /DSCPageCount DSCPageCount 1 add store + } bind def + +/get_media_box { % <pagedict> get_media_box <box> + /MediaBox pget not { + ( **** Page has no /MediaBox attribute. Using the current page size.\n) + pdfformaterror + [ 0 0 currentpagedevice /PageSize get aload pop ] + } if +} bind def + +% Compute the matrix that transforms the PDF->PS "default" user space +/pdf_PDF2PS_matrix { % <pdfpagedict> -- matrix + matrix currentmatrix matrix setmatrix exch + % stack: savedCTM <pdfpagedict> + dup /CropBox pget dup {exch pop} if //systemdict /UseCropBox known and { + /CropBox 2 copy pget pop + } { + /MediaBox 1 index get_media_box + } ifelse + % stack: savedCTM <pdfpagedict> /Crop|MediaBox <Crop|Media Box> + oforce_elems normrect_elems fix_empty_rect_elems 4 array astore + //systemdict /PDFFitPage known { + PDFDEBUG { (Fiting PDF to imageable area of the page.) = flush } if + currentpagedevice /.HWMargins get aload pop + currentpagedevice /PageSize get aload pop + % Adjust PageSize and .HWMargins for the page portrait/landscape orientation + 2 copy gt + 7 index aload pop 3 -1 roll sub 3 1 roll exch sub exch + 10 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if + gt + ne { + 2 copy ne { + % rotate the .HWMargins + 2 copy lt { + 6 2 roll 4 -1 roll 6 -2 roll + } { + 6 2 roll 4 1 roll 6 -2 roll + } ifelse + % rotate the page dimensions + exch + } if + } if + 3 -1 roll sub 3 1 roll exch sub exch + % stack: savedCTM <pdfpagedict> <Crop|Media Box> Xmin Ymin Xmax Ymax + PDFDEBUG { ( Translate up by [ ) print 3 index =print (, ) print 2 index =print ( ]) = flush } if + 3 index 3 index translate % move origin up to imageable area + 2 index sub exch 3 index sub exch 4 2 roll pop pop + % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable + 2 index aload pop 2 index sub exch 3 index sub exch 4 2 roll pop pop + 5 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if + % stack: savedCTM <pdfpagedict> [Box] XImageable YImageable XBox YBox + 3 -1 roll exch div 3 1 roll div .min + PDFDEBUG { ( Scale by ) print dup = flush } if + } { + //systemdict /NoUserUnit .knownget not { false } if { + 1 + } { + 1 index /UserUnit knownoget { + PDFDEBUG { (Scaling due to UserUnit by ) print dup = flush } if + } { + 1 + } ifelse + } ifelse + } ifelse + % stack: savedCTM <pdfpagedict> [Box] scale + dup scale + % Rotate according to /Rotate + aload pop boxrect + { + { pop pop } + { -90 rotate pop neg 0 translate } + { 180 rotate neg exch neg exch translate } + { 90 rotate neg 0 exch translate pop } + } + 5 index /Rotate pget not { 0 } if + PDFDEBUG { dup 0 ne { (Rotating by ) print dup =print ( degrees.) = flush } if } if + 90 idiv 3 and get exec + % Now translate to the origin given in the Crop|Media Box + exch neg exch neg translate + % stack: savedCTM <pdfpagedict> + pop + matrix currentmatrix exch setmatrix +} bind def + +% Cache the matrix that transforms the PDF->PS "default" user space +% into <pdfpagedict> under the key //PDF2PS_matrix_key, then return it +/PDF2PS_matrix_key (PDF->PS matrix) cvn def +/pdf_cached_PDF2PS_matrix { % <pdfpagedict> -- <PDF2PS_matrix> + dup //PDF2PS_matrix_key .knownget { + exch pop + } { + dup dup pdf_PDF2PS_matrix //PDF2PS_matrix_key exch put + //PDF2PS_matrix_key get + } ifelse +} bind def +currentdict /PDF2PS_matrix_key undef + +/.pdfshowpage_Install { % <pagedict> [<prevproc>] .pdfshowpage_Install - + exch pdf_cached_PDF2PS_matrix concat + 0 get exec +} bind def + +/pdfshowpage_setpage { % <pagedict> pdfshowpage_setpage <pagedict> + 5 dict begin % for setpagedevice + % Stack: pdfpagedict + % UseCIEColor is always true for PDF; see the comment in runpdf above + /UseCIEColor true def + /Orientation 0 def + currentpagedevice + % Stack: pdfpagedict currentpagedevicedict + 1 index /CropBox pget dup {exch pop} if //systemdict /UseCropBox known and { + /CropBox 2 index /CropBox pget % will use the CropBox + } { + /MediaBox 2 index get_media_box true % will use the MediaBox + } ifelse + { + oforce_elems normrect_elems fix_empty_rect_elems boxrect 4 2 roll pop pop + 3 index /Rotate pget not { 0 } if 90 idiv 1 and 0 ne { exch } if + % stack: pdfpagedict currentpagedevicedict boxwidth boxheight + //systemdict /PDFFitPage known { + % Preserve page size, + % but choose portrait/landscape depending on box width:height ratio + % (if box width == height, select portrait orientation) + gt + 1 index /PageSize get aload pop + 2 copy gt + 4 -1 roll ne { exch } if + } { + % Set the page size. + //systemdict /NoUserUnit .knownget not { false } if not { + 3 index /UserUnit knownoget { + dup 4 -1 roll mul 3 1 roll mul + } if + } if + } ifelse + 2 array astore /PageSize exch def + } { + pop % pops /Crop|MediaBox + } ifelse + % Determine the number of spot colors used on the page. Note: This searches + % the pages resources. It may be high if a spot color is in a resource but + % is not actually used on the page. + << /PageSpotColors 3 index countspotcolors >> setpagedevice + + % Let the device know if we will be using PDF 1.4 transparency. + % The clist logic may need to adjust the size of bands. + 1 index pageusestransparency /PageUsesTransparency exch def + dup /Install .knownget { + % Don't let the Install procedure get more deeply + % nested after every page. + dup type dup /arraytype eq exch /packedarraytype eq or { + dup length 4 eq { + dup 2 get /.pdfshowpage_Install load eq { + 1 get 0 get % previous procedure + } if + } if + } if + } { + { } + } ifelse 1 array astore + 2 index exch /.pdfshowpage_Install load /exec load + 4 packedarray cvx + % Stack: pagedict currentpagedict installproc + /Install exch def + % Stack: pagedict currentpagedict + pop currentdict end setpagedevice +} bind def + +/.free_page_resources { % - .free_page_resources - + Page /Resources pget { + /Shading knownoget { + { dup type /dicttype eq { + dup /.shading_dict known { + dup /.shading_dict undef + } if + } if + pop pop + } forall + } if + } if +} bind def + +/pdfshowpage_finish { % <pagedict> pdfshowpage_finish - + save /PDFSave exch store + /PDFdictstackcount countdictstack store + (before exec) VMDEBUG + + % set up color space substitution (this must be inside the page save) + pdfshowpage_setcspacesub + + .writepdfmarks { + + % Copy the crop box. + dup /CropBox pget { + % .pdfshowpage_Install transforms the user space - + % do same here with the CropBox. + oforce_elems + 2 { Page pdf_cached_PDF2PS_matrix transform 4 2 roll } repeat + normrect_elems /CropBox 5 1 roll fix_empty_rect_elems 4 array astore + mark /CropBox 3 -1 roll + /PAGE pdfmark + } if + + % Copy annotations and links. + dup /Annots knownoget { + 0 1 2 index length 1 sub + { 1 index exch oget + dup /Subtype oget annottypes exch .knownget { exec } { pop } ifelse + } + for pop + } if + + } if % end .writepdfmarks + + % Display the actual page contents. + 6 dict begin + /BXlevel 0 def + /BGDefault currentblackgeneration def + /UCRDefault currentundercolorremoval def + %****** DOESN'T HANDLE COLOR TRANSFER YET ****** + /TRDefault currenttransfer def + matrix currentmatrix 2 dict + 2 index /CropBox pget { + oforce_elems normrect_elems boxrect + 4 array astore 1 index /ClipRect 3 -1 roll put + } if + dictbeginpage setmatrix + /DefaultQstate qstate store + + count 1 sub /pdfemptycount exch store + % If the page uses any transparency features, show it within + % a transparency group. + dup pageusestransparency dup /PDFusingtransparency exch def { + % Show the page within a PDF 1.4 device filter. + 0 .pushpdf14devicefilter { + /DefaultQstate qstate store % device has changed -- reset DefaultQstate + % If the page has a Group, enclose contents in transparency group. + % (Adobe Tech Note 5407, sec 9.2) + dup /Group knownoget { + 1 index /CropBox pget { + /CropBox exch + } { + 1 index get_media_box /MediaBox exch + } ifelse + oforce_elems normrect_elems fix_empty_rect_elems 4 array astore .beginformgroup { + showpagecontents + } stopped { + .discardtransparencygroup stop + } if .endtransparencygroup + } { + showpagecontents + } ifelse + } stopped { + % todo: discard + .poppdf14devicefilter + /DefaultQstate qstate store % device has changed -- reset DefaultQstate + stop + } if .poppdf14devicefilter + /DefaultQstate qstate store % device has changed -- reset DefaultQstate + } { + showpagecontents + } ifelse + .free_page_resources + % todo: mixing drawing ops outside the device filter could cause + % problems, for example with the pnga device. + endpage + end % scratch dict + % Indicate that the number of spot colors is unknown in case the next page + % imaged is a PS file. + << /PageSpotColors -1 >> setpagedevice + % Some PDF files don't have matching q/Q (gsave/grestore) so we need + % to clean up any left over dicts from the dictstack + countdictstack PDFdictstackcount sub dup 0 ne { + ( **** Warning: File has imbalanced q/Q operators \(too many q's\)\n) + pdfformaterror + { end } repeat + } { + pop + } ifelse + (after exec) VMDEBUG + Repaired % pass Repaired state around the restore + PDFSave restore + /Repaired exch def +} bind def + +% Display the contents of a page (including annotations). +/showpagecontents { % <pagedict> showpagecontents - + dup % Save the pagedict for the Annotations + count 1 sub /pdfemptycount exch store + gsave % preserve gstate for Annotations later + /Contents knownoget not { 0 array } if + dup type /arraytype ne { 1 array astore } if { + oforce false resolvestream pdfopdict .pdfrun + } forall + % check for extra garbage on the ostack and clean it up + count pdfemptycount sub dup 0 ne { + ( **** File did not complete the page properly and may be damaged.\n) + pdfformaterror + { pop } repeat + } { + pop + } ifelse + grestore + % Draw the annotations + //systemdict /ShowAnnots .knownget not { //true } if { + /Annots knownoget { { oforce drawannot } forall } if + } if + //systemdict /ShowAcroForm .knownget { //true eq } { //false } ifelse { + Trailer /Root oget /AcroForm knownoget { draw_acro_form } if + } if +} bind def + +/processcolorspace { % - processcolorspace <colorspace> + % The following is per the PLRM3. + currentdevice 1 dict dup /ProcessColorModel dup put .getdeviceparams + exch pop exch pop + dup type /nametype ne { cvn } if + dup { setcolorspace } .internalstopped { pop /DeviceRGB } if +} bind def + +% ------ Transparency support ------ % + +% Define minimum PDF version for checking for transparency features. +% Transparency is a 1.4 feature however we have seen files that claimed +% to be PDF 1.2 with transparency features. Bug 689288. +/PDFtransparencyversion 1.2 def + +% Determine whether a page might invoke any transparency features: +% - Non-default BM, ca, CA, or SMask in an ExtGState +% - Image XObject with SMask +% Note: we deliberately don't check to see whether a Group is defined, +% because Adobe Illustrator 10 (and possibly other applications) define +% a page-level group whether transparency is actually used or not. +% Ignoring the presence of Group is justified because, in the absence +% of any other transparency features, they have no effect. +/pageusestransparency { % <pagedict> pageusestransparency <bool> + PDFversion PDFtransparencyversion lt NOTRANSPARENCY or { + pop //false + } { + dup //false exch { + 4 dict 1 index resourceusestransparency { pop not exit } if + /Parent knownoget not { exit } if + } loop + % Also check for transparency in the annotation (if not in resources). + { pop //true } { annotsusetransparency } ifelse + } ifelse +} bind def + +% Check if transparency is specified in an ExtGState dict +/extgstateusestransparency { % <gstate dict> extgstateusestransparency <bool> + //false exch % Assume no transparency + { % establish loop context + exch pop oforce + dup /BM knownoget { dup /Normal ne exch /Compatible ne and + { pop not exit } if + } if + dup /ca knownoget { 1 ne { pop not exit } if } if + dup /CA knownoget { 1 ne { pop not exit } if } if + dup /SMask knownoget { /None ne { pop not exit } if } if + pop + } forall +} bind def + +% Check the Resources of a page or Form. Check for loops in the resource chain. +/resourceusestransparency { % <dict> <dict> resourceusestransparency <bool> + { % Use loop to provide an exitable context. + /Resources knownoget not { 0 dict } if + 2 copy .knownget { + { % Some circular references may be missed because scanning stops + % when the 1st transparency is found. + ( **** File has circular references in resource dictionaries.\n) + pdfformaterror + } if + pop //false exit + } if + 2 copy //true put % In the current chain. + dup /ExtGState knownoget { + extgstateusestransparency + { pop //true exit } if + } if + dup /XObject knownoget { + //false exch { + exch pop oforce dup /Subtype get + dup /Image eq { 1 index /SMask known { pop pop not exit } if } if + /Form eq { + 3 index exch resourceusestransparency { not exit } if + } { + pop + } ifelse + } forall { pop //true exit } if + } if + 2 copy //false put % Visited but not in the current chain. + pop //false exit + } loop + exch pop +} bind def + +% Check if the annotations on a page use transparency +/annotsusetransparency { % <page dict> annotsusetransparency <bool> + //false exch % Assume no transparency + /Annots knownoget { % Get Annots array + { oforce /AP knownoget { % Get appearance dict for the annoation + /N knownogetdict { % Get the /N (i.e. normal) appearance stream + 4 dict exch resourceusestransparency { pop //true exit } if + } if + } if % If AP dict known + } forall % For all annots on the page + } if +} bind def + +% Add a color name to our spot color list. Ignore /All and /None +/putspotcolor { % <name> <spotcolordict> putspotcolor - + % The 'name' could be a string. If so then convert to a name. + exch dup type /stringtype eq { cvn } if + dup dup /None eq exch /All eq or { pop pop } { 0 put } ifelse +} bind def + +% Determine which spot colors are used within a color space Note: This +% dict will include all colors used in Separation or DeviceN color spaces. +% Thus it may include Cyan, Magenta, Yellow, and Black. +% <colorspace> <spotcolordict> colorspacespotcolors - +/colorspacespotcolors { + exch dup type /arraytype eq { + % If we have an Indexed color space then get the base space. + dup 0 oget dup /Indexed eq { + pop 1 oget 2 copy colorspacespotcolors + } { + % Stack: <spotcolordict> <colorspace> <colorspacetype> + dup /Separation eq exch /DeviceN eq or { + dup 1 oget dup type /arraytype eq { + { oforce 2 index putspotcolor } forall + } { + 2 index putspotcolor + } ifelse + } if + } ifelse + } if + pop pop +} bind def + +% Check the Resources of a page, form, or annotation. Determine which spot +% colors are used within the resource Note: The spot color dict will include +% all colors used in Separation or DeviceN color spaces. Thus it may include +% Cyan, Magenta, Yellow, and Black. We also pass a dict that is used to check +% for loops in the resource list. +% <spotcolordict> <loopdict> <page/form/annot dict> +% resourcespotcolors <spotcolordict> <loopdict> +/resourcespotcolors { + { % Use loop to provide an exitable context. + % Exit if no Resources entry + /Resources knownoget not { exit } if + % Exit if we have already seen this dict + 2 copy known { pop exit } if + + % Save the Resources dict into our loop checking dict. + 2 copy 0 put + + % Scan resources that might contain a color space. + dup /ColorSpace knownoget { + { exch pop oforce 3 index colorspacespotcolors } forall + } if + dup /Pattern knownoget { + { exch pop oforce 4 copy exch pop resourcespotcolors pop pop pop } forall + } if + dup /Shading knownoget { + { exch pop oforce /ColorSpace oget 3 index colorspacespotcolors } forall + } if + /XObject knownoget { + { exch pop oforce dup + /Subtype get /Form eq { resourcespotcolors } { pop } ifelse + } forall + } if + exit + } loop +} bind def + +% Determine which spot colors are used within the annotations. Note: This +% dict will include all colors used in Separation or DeviceN color spaces. +% Thus it may include Cyan, Magenta, Yellow, and Black. +% <spotcolordict> <loopdict> <annotsarray> +% annotsspotcolors <spotcolordict> <loopdict> +/annotsspotcolors { + { oforce /AP knownoget { % Get appearance dict for the annoation + /N knownogetdict { % Get the /N (i.e. normal) appearance stream + resourcespotcolors + } if % If normal appearance streamknown + } if % If AP dict known + } forall +} bind def + +% Determine spot colors are used within a page. We are creating a dict to +% hold the spot color names as keys. Using a dict avoids having to worry +% about duplicate entries. The keys in the dict contain the spot color +% names. However the values have no meaning. Note: This dict will include +% all colors used in Separation or DeviceN color spaces specified in the +% page's resources. Thus it may include Cyan, Magenta, Yellow, and Black. +% There is no attempt to verify that these color spaces are actually used +% within the object streams for the page. +/pagespotcolors { % <pagedict> pagespotcolors <spotcolordict> + dup + % Create a dict to hold spot color names. + 0 dict exch + % Create a dict to be used to check for reference loops. + 4 dict exch + % Check for color spaces in the Resources + resourcespotcolors + % Also check for color spaces in the annotations. + 3 -1 roll + /Annots knownoget { annotsspotcolors } if + pop % Discard reference loop dict +} bind def + +% Determine how many (if any) spot colors are used by a page. +% Note: This count does not include Cyan, Magenta, Yellow, or Black +/countspotcolors { % <pagedict> countspotcolors <count> + pagespotcolors % Get dict with all spot colors + dup length % spot color dict length + % Remove CMYK from the spot color count. + [ /Cyan /Magenta /Yellow /Black ] + { 2 index exch known { 1 sub } if } forall + exch pop % Remove spot color dict +} bind def + +% ------ ColorSpace substitution support ------ % + +% +% <pagedict> pdfshowpage_setcspacesub <pagedict> +% +% Set up color space substitution for a page. Invocations of this procedure +% must be bracketed by the save/restore operation for the page, to avoid +% unintended effects on other pages. +% +% If any color space substitution is used, and the current color space is a +% device dependent color space, make sure the current color space is updated. +% There is an optimization in the setcolorspace pseudo-operator that does +% nothing if both the current and operand color spaces are the same. For +% PostScript this optimization is disabled if the UseCIEColor page device +% parameter is true. This is not the case for PDF, as performance suffers +% significantly on some PDF files if color spaces are set repeatedly. Hence, +% if color space substitution is to be used, and the current color space +% is a device dependent color space, we must make sure to "transition" the +% current color space. +% +/pdfshowpage_setcspacesub + { + false + { /DefaultGray /DefaultRGB /DefaultCMYK } + { + dup 3 index /ColorSpace //rget exec + { resolvecolorspace /ColorSpace defineresource pop } + { pop } + ifelse + } + forall + + % if using color space substitution, "transition" the current color space + { + currentcolorspace dup length 1 eq % always an array + { + 0 get + dup /DeviceGray eq 1 index /DeviceRGB eq or 1 index /DeviceCMYK or + { /Pattern setcolorspace setcolorspace } + { pop } + ifelse + } + { pop } + if + } + if + } +bind def + +% Write OutputIntents to device if the device handles it +/writeoutputintents { + currentdevice 1 dict dup /OutputIntent //null put readonly + .getdeviceparams + mark ne { pop pop + % device supports OutputIntent parameter + Trailer /Root oget /OutputIntents knownoget { + dup type /arraytype eq { + { % process all output profiles present + oforce + dup length dict .copydict + dup /DestOutputProfile knownoget { + PDFfile fileposition exch + mark exch { oforce } forall .dicttomark + //true resolvestream + [ { counttomark 1 add index + 64000 string readstring + not { exit } if + } loop + ] exch closefile + 0 1 index { length add } forall .bytestring + 0 3 2 roll { + 3 copy putinterval + length add + } forall pop + exch PDFfile exch setfileposition + 1 index /DestOutputProfile 3 2 roll put + } if + % Convert to string array because it's easier for the device + [ 1 index /OutputCondition knownoget not { () } if + 2 index /OutputConditionIdentifier knownoget not { () } if + 3 index /RegistryName knownoget not { () } if + 4 index /Info knownoget not { () } if + 5 index /DestOutputProfile knownoget not { () } if + ] + [ /OutputIntent 3 2 roll .pdfputparams pop pop + pop % done with this OutputIntent dictionary + } forall + } { + pop + ( **** Warning: OutputIntent attribute of a wrong type is ignored.\n) + pdfformaterror + } ifelse + } if % OutputIntents known + % tell device there are no more OutputIntents + [ /OutputIntent [ ] .pdfputparams pop pop + } if +} bind def + +end % pdfdict +.setglobal diff --git a/gs/Resource/Init/pdf_ops.ps b/gs/Resource/Init/pdf_ops.ps new file mode 100644 index 000000000..4139a92e6 --- /dev/null +++ b/gs/Resource/Init/pdf_ops.ps @@ -0,0 +1,852 @@ +% Copyright (C) 1994, 2000 Aladdin Enterprises. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% Definitions for most of the PDF operators. + +.currentglobal true .setglobal + +% Define pdfmark. Don't allow it to be bound in. +% Also don't define it in systemdict, because this leads some Adobe code +% to think this interpreter is a distiller. +% (If this interpreter really is a distiller, don't do this.) +systemdict /pdfmark known not + { userdict /pdfmark { cleartomark } bind put } if + +userdict /GS_PDF_ProcSet 127 dict dup begin + +% ---------------- Abbreviations ---------------- % + +/bdef { bind def } bind def + +% ---------------- Graphics state stack ---------------- % + +% PDF adds a number of parameters to the graphics state. +% We implement this by pushing and popping a dictionary +% each time we do a PDF gsave or grestore. +% The keys in this dictionary are as follows: +% self % identifies the dictionary as one of ours +% ClipRect % (optional) +% Show +% TextSaveMatrix % matrix at time of BT (iff within BT/ET) +% (The following correspond directly to PDF state parameters.) +% AlphaIsShape +% FillConstantAlpha +% FillColor +% FillColorSpace +% FillOverprint +% SoftMask +% StrokeConstantAlpha +% StrokeColor +% StrokeColorSpace +% StrokeOverprint +% TextSpacing +% TextHScaling +% Leading +% TextFont +% TextLineMatrix +% TextMatrix +% TextRise +% TextRenderingMode +% WordSpacing +% (The following is cached information derived from other graphics state params) +% FontMatrixNonHV % TextFont.FontMatrix alters horz/vert glyph advance vector direction + +/nodict 1 dict def +nodict /self { //nodict } executeonly put +nodict readonly pop + +/dictbeginpage { % <initialdict> dictbeginpage - + //nodict 20 dict .copydict begin { def } forall + graphicsbeginpage textbeginpage +} bdef +/endpage { % - endpage - + showpage end +} bdef + +/graphicsbeginpage { + initgraphics + //true .setaccuratecurves + currentdict /ClipRect knownoget { aload pop rectclip } if + 0 g 0 G false op false OP 0 OPM + 1 ca 1 CA null SMask false AIS /Compatible BM true TK +} bdef + +/gput % <value> <key> gput - + { exch currentdict //nodict eq { /self dup load end 5 dict begin def } if + % If we're in a Level 1 system, we need to grow the + % dictionary explicitly. + currentdict length currentdict maxlength ge %eq + { currentdict dup length 3 mul 2 idiv 1 add dict .copydict end begin + } + if def + } bdef + +/q { + gsave //nodict begin +} bdef + +% Some PDF files have excess Q operators! +/Q { + currentdict /self .knownget { + exec //nodict eq { + end + % Restore graphics state, but do not modify path. Paths are not part + % of the PDF graphics state; see 4.4.1 of PDF reference 3rd ed. + % Collecting the path with one ctm and re-playing it with another ctm + % transforms the path exactly as PDF needs. + .getpath grestore newpath { exec } forall + //false + } { + //true + } ifelse + } { + //true % formaterror -- not a gsave dict + } ifelse + { (\n **** File has imbalanced q/Q operators \(too many Q's\) ****\n) + pdfformaterror + } if +} bdef + +% Save PDF gstate +/qstate { % - qstate <qstate> + gstate +} bdef + +% Set PDF gstate +/setqstate { % <qstate> setqstate - + { matrix setmatrix //false upath } stopped { + pop setgstate newpath + } { + % Save the CTM, set identity during the uappend, then set the CTM + exch setgstate matrix currentmatrix matrix setmatrix + exch newpath uappend setmatrix + } ifelse +} bdef + +% ---------------- Color setting ---------------- % + +/fcput % <color> <colorspace> fcput - + { /FillColorSpace gput /FillColor gput + } bdef +/scput % <color> <colorspace> scput - + { /StrokeColorSpace gput /StrokeColor gput + } bdef +/csput % <colorspace> csput - + { csset 2 copy fcput scput + } bdef + +/csdevgray [/DeviceGray] readonly def +/csdevrgb [/DeviceRGB] readonly def +/csdevcmyk [/DeviceCMYK] readonly def +/cspattern [/Pattern] readonly def +/nullpattern1 mark + /PatternType 1 /PaintType 1 /TilingType 3 /BBox [0 0 1 1] + /XStep 1 /YStep 1 /PaintProc { pop } bind +.dicttomark readonly def +/nullpattern2 nullpattern1 dup length dict copy readonly def + +% Each entry in the color space dictionary is a procedure of the form +% <cspace> -proc- <cspace> <initial-color> +/CSdict mark + /DeviceGray { pop //csdevgray 0 } bind + /DeviceRGB { pop //csdevrgb [0 0 0] cvx } bind + /DeviceCMYK { pop //csdevcmyk [0 0 0 1] cvx } bind + /CIEBasedA { 0 } bind + /CIEBasedABC { [0 0 0] cvx } bind + /ICCBased { [ 1 index 1 oget /N get { 0 } repeat ] cvx } bind + /Separation { 1 } bind + /DeviceN { % What is the correct value?? + [ 1 index 1 get length { 1 } repeat ] cvx + } bind + /Indexed { 0 } bind + /Pattern { + dup type /nametype eq 1 index length 1 eq or { + pop //cspattern //nullpattern1 matrix makepattern + } { + //nullpattern2 matrix makepattern 1 index 1 get csset + % Stack: patternspace nullpattern basecolor basespace + pop [ 3 1 roll dup type /arraytype eq { aload pop } if + counttomark -1 roll ] cvx + } ifelse + } bind +.dicttomark readonly def +/csset % <cspace> csset <color> <cspace> + { dup dup type /nametype ne { 0 get } if //CSdict exch get exec exch + } bdef + +/g { //csdevgray fcput } bdef +/G { //csdevgray scput } bdef +/rg { 3 array astore cvx //csdevrgb fcput } bdef +/RG { 3 array astore cvx //csdevrgb scput } bdef +/k { 4 array astore cvx //csdevcmyk fcput } bdef +/K { 4 array astore cvx //csdevcmyk scput } bdef +/cs { csset fcput } bdef +/CS { csset scput } bdef +/ri { //.renderingintentdict exch .knownget { .setrenderingintent } if } bdef +% We have to break up sc according to the number of operands. +/sc1 { /FillColor gput } bdef +/SC1 { /StrokeColor gput } bdef +% We have to avoid storing into a color array associated with an outer +% gsave level, so we do a kind of "copy on write". +/sc* { + currentdict /FillColor .knownget { + astore pop + } { + /FillColor load + % FillColor may contain either a single value or an array. + dup type /arraytype eq { length }{ pop 1 } ifelse + array astore cvx /FillColor gput + } ifelse +} bdef +/SC* { + currentdict /StrokeColor .knownget { + astore pop + } { + /StrokeColor load + % StrokeColor may contain either a single value or an array. + dup type /arraytype eq { length }{ pop 1 } ifelse + array astore cvx /StrokeColor gput + } ifelse +} bdef + +% ---------------- Overprint/transparency setting ---------------- % + +/op { /FillOverprint gput } bdef +/OP { /StrokeOverprint gput } bdef +/OPM { + /.setoverprintmode where { pop .setoverprintmode } { pop } ifelse +} bdef +/ca { /FillConstantAlpha gput } bdef +/CA { /StrokeConstantAlpha gput } bdef +/SMask { /SoftMask gput } bdef +/AIS { /AlphaIsShape gput } bdef +/BM { + /.setblendmode where { + pop [ exch dup type /nametype ne { aload pop } if /Normal ] { + { .setblendmode } .internalstopped not { exit } if pop + } forall + } { + pop + } ifelse +} bdef +/TK { + /.settextknockout where { pop .settextknockout } { pop } ifelse +} bdef + +% ---------------- Color installation ---------------- % + +% Establish a given color (and color space) as current. +/.settransparencyparams { % <alpha> <smask> .settransparencyparams - + PDFusingtransparency { + /.begintransparencygroup where { + pop AlphaIsShape { + 1 .setopacityalpha exch .setshapealpha 1 + } { + 1 .setshapealpha exch .setopacityalpha 0 + } ifelse + % Set the soft mask by rendering the XObject. Doing this every time + % is obviously very inefficient; we'll improve it later. + .settransparencymask + } { + pop pop + } ifelse + } { + pop pop + } ifelse +} bdef +/.settransparencymask { % <paramdict> <masknum> .settransparencymask - + exch dup null eq { + PDFusingtransparency { + pop pop + } { + dup /Draw get exec + } ifelse + } { + dup /Draw get exec + } ifelse +} bdef +% (Non-mask) images must execute setfillblend. +/setfillblend { + FillOverprint setoverprint + FillConstantAlpha SoftMask .settransparencyparams +} def +/setfillstate { + FillColor FillColorSpace setgcolor setfillblend +} def +/setstrokestate { + StrokeColor StrokeColorSpace setgcolor StrokeOverprint setoverprint + StrokeConstantAlpha SoftMask .settransparencyparams +} def +/Cdict 15 dict dup begin % <color...> <colorspace> -proc- - + /DeviceGray { pop setgray } bdef + /DeviceRGB { pop setrgbcolor } bdef + /DeviceCMYK { pop setcmykcolor } bdef + /CIEBasedA { setgcolorspace setcolor } bdef + /CIEBasedABC /CIEBasedA load def + /CIEBasedDEF /CIEBasedA load def + /CIEBasedDEFG /CIEBasedA load def + /ICCBased /CIEBasedA load def + /Separation /CIEBasedA load def + /DeviceN /CIEBasedA load def + /Indexed /CIEBasedA load def + /Pattern + { setgcolorspace + + % Since multiple patterns may share + % same data stream, we need to ensure + % that the stream is at 0 position. + % Making this consistently with resolveshading, + % which applies ReusableStreamDecode filter + % to the PS stream, which represents the + % PDF stream in dynamics. + + dup /Shading knownoget { + dup /ShadingType oget 4 ge { + /DataSource knownoget { + dup type /filetype eq { + 0 setfileposition + } { + pop + } ifelse + } if + } { + pop + } ifelse + } if + + % Associate pattern instance with the default qstate for the context. + % A single pattren object can be reused in several contexts. + dup DefaultQstate .knownget { + exch pop + } { + dup dup /Matrix knownoget not { { 1 0 0 1 0 0 } } if + gsave DefaultQstate setqstate makepattern grestore + dup 3 1 roll + DefaultQstate exch put + } ifelse + setcolor + } bdef +end def +/setgcolor % (null | <color...>) <colorspace> setgcolor - + { 1 index null eq + { pop pop } + { dup 0 get //Cdict exch get exec } + ifelse + } bdef +% Compare the old and new color spaces in an attempt to avoid expensive +% reloads of CIEBased color spaces. +/PCSdict 15 dict dup begin % <colorspace> -proc- <colorspace|pdfcspace> + /CIEBasedA { dup 1 get /PDFColorSpace .knownget { exch pop } if } bdef + /CIEBasedABC /CIEBasedA load def + /CIEBasedDEF /CIEBasedA load def + /CIEBasedDEFG /CIEBasedA load def + /Indexed { + dup 1 get dup pdfcolorspace 2 copy ne { 3 1 roll } if pop pop + } bdef +end def +/pdfcolorspace { % <colorspace> pdfcolorspace <colorspace|pdfcspace> + dup type /arraytype eq { + //PCSdict 1 index 0 get .knownget { exec } if + } if +} bdef +/setgcolorspace { % <colorspace> setgcolorspace - + dup pdfcolorspace currentcolorspace pdfcolorspace eq { + pop + } { + setcolorspace + } ifelse +} bdef +/fsexec % <fillop|strokeop> fsexec - + { % Preserve the current point, if any. + { currentpoint } stopped + { $error /newerror false put cvx exec } + { 3 -1 roll cvx exec moveto } + ifelse + } bdef + +% ---------------- Path painting and clipping ---------------- % + +/S { setstrokestate /stroke fsexec } bdef +/f { setfillstate /fill fsexec } bdef +/f* { setfillstate /eofill fsexec } bdef +/n { newpath } bdef % don't allow n to get bound in +/s { closepath S } bdef +/B { gsave setfillstate fill grestore S } bdef +/b { closepath B } bdef +/B* { gsave setfillstate eofill grestore S } bdef +/b* { closepath B* } bdef + +% Clipping: + +/Wdict 4 dict dup begin +/S { gsave setstrokestate stroke grestore n } bdef +/f { gsave setfillstate fill grestore n } bdef +/f* { gsave setfillstate eofill grestore n } bdef +/n { end clip newpath } bdef +end readonly def +/W { //Wdict begin } bdef +/W*dict 4 dict dup begin +Wdict { def } forall +/n { end eoclip newpath } bdef +end readonly def +/W* { //W*dict begin } bdef + +% ---------------- Text control ---------------- % + +/textbeginpage + { /TextSpacing 0 def % 0 Tc + /TextLeading 0 def % 0 TL + /TextRenderingMode 0 def % 0 Tr + /TextRise 0 def % 0 Ts + /WordSpacing 0 def % 0 Tw + /TextHScaling 1.0 def % 100 Tz + /TextFont null def + /FontMatrixNonHV //false def + /Show { showfirst } def + } bdef + +% Contrary to the statement in the PDF manual, BT and ET *can* be nested, +% if the CharProc for a Type 3 font does a BT/ET itself. +% Since we always call the CharProc inside a q/Q, we simply ensure that +% the text state is saved and restored like the rest of the extended +% graphics state. + +/settextmatrix { + TextMatrix concat + TextHScaling 1 ne { TextHScaling 1 scale } if + TextRise 0 ne { 0 TextRise translate } if + TextFont dup null eq { pop } { setfont } ifelse +} bdef +/settextstate { + % The text state can be set even outside BT/ET. + currentdict /TextSaveMatrix known { + TextSaveMatrix setmatrix settextmatrix + } if +} bdef +/settextposition { + % Update the TextMatrix translation. + gsave TextSaveMatrix setmatrix + currentpoint TextRise sub TextMatrix 4 2 getinterval astore pop + % We would like to do "grestore currentpoint translate" + % here, but some PDF files set a singular text matrix + % (0 0 0 0 <x> <y> Tm), so we can't do this. + TextTempMatrix identmatrix setmatrix currentpoint + grestore + TextTempMatrix currentmatrix 4 2 getinterval astore pop + TextTempMatrix setmatrix +} bdef + +/BT { + currentdict /TextLineMatrix .knownget + { identmatrix pop TextMatrix identmatrix pop } + { matrix /TextLineMatrix gput matrix /TextMatrix gput } + ifelse + { showfirst } /Show gput + currentdict /TextSaveMatrix .knownget not { + matrix dup /TextSaveMatrix gput + } if currentmatrix pop settextmatrix + matrix /TextTempMatrix gput % see settextposition +} bdef +/ET { + TextRenderingMode 4 ge { clip newpath } if + TextSaveMatrix setmatrix + currentdict /TextSaveMatrix undef +} bdef +/Tc { /TextSpacing gput { showfirst } /Show gput } bdef +/TL { /TextLeading gput } bdef +/Tr { dup .settextrenderingmode /TextRenderingMode gput { showfirst } /Show gput } bdef +/Ts { /TextRise gput settextstate } bdef +/Tw { /WordSpacing gput { showfirst } /Show gput } bdef +/Tz { 100 div /TextHScaling gput settextstate} bdef + +% ---------------- Font control ---------------- % + +% Test if the FontMatrix could transform a horizontal/vertical (depending +% on writing mode) advance vector in glyph space into one with a different +% direction in text space. +% - if FontMatrix = [a b c d tx ty], this condition translates to: +% b != 0 for horizontal writing mode +% c != 0 for vertical writing mode +% - when false, we automatically have wy/x == 0 in text space whenever wy/x == 0 +% in glyph space, and can avoid the slow method that is otherwise necessary +% to implement zeroing wy/x cf PDF Ref 5.3.3 "Text space details" + % Worker procedure for testing a single font matrix +/?FontMatrixNonHV { % ?horz <<fontdict>> -- ?horz ?nonhv + /FontMatrix .knownget { + 1 index { 1 } { 2 } ifelse get 0 ne + } { + //false + } ifelse +} bdef + % Worker procedure for recursive checking of font matrices +/?FontMatrixNonHV { % {self} ?horz <<font>> -- {self} ?horz ?nonhv + 2 copy //?FontMatrixNonHV exec { % check the font's own FontMatrix + pop pop //true + } { + % look for descendents/ components + pop % {self} ?horz <<font>> + dup /FontType get + dup 0 eq { % Type 0: look into FDepVector + pop /FDepVector get 2 index % {self} ?horz [fonts..] {testproc} + } { + 9 eq { % Type 9 (CIDFontType 0): check FDArray + /FDArray get //?FontMatrixNonHV + } { % all others: nothing more to check + pop {} {} + } ifelse + } ifelse + %stack: {self} ?horz [fonts..] {testproc} + //false 5 2 roll { % {testproc} false {self} ?horz <<subfont>> + 4 index exec { + 4 -1 roll pop //true 4 1 roll + exit + } if + } forall + %stack: {testproc} ?nonhv {self} ?horz + 4 2 roll exch pop + } ifelse +} bdef + % Main procedure +/?FontMatrixNonHV { % <<rootfont>> -- ?nonhv + //?FontMatrixNonHV exch + % determine WMode + dup /WMode .knownget { 0 eq } { //true } ifelse % {proc} <<rootfont>> ?horz + exch + % call the worker procedure + //?FontMatrixNonHV exec + exch pop exch pop +} bdef + +/Tf { % <font> <scale> Tf - + dup 0 eq { + (\n **** Warning: Invalid 0.0 font scale given for Tf ****\n) + pdfformaterror + pop 0.00000001 % handle invalid scale by using a really small value + } if + 1 index type /dicttype ne { + selectfont currentfont + } { + dup 1 eq { pop } { scalefont } ifelse + } + ifelse + dup ?FontMatrixNonHV dup FontMatrixNonHV ne { + /FontMatrixNonHV gput + { showfirst } /Show gput + } { + pop + } ifelse + /TextFont gput settextstate +} bdef + +% Copy a font, removing its FID. If changed is true, also remove +% the UniqueID and XUID, if any. If the original dictionary doesn't have +% the keys being removed, don't copy it. +/.copyfontdict % <font> <changed> .copyfontdict <dict> + { 1 index /FID known + 1 index { 2 index /UniqueID known or 2 index /XUID known or } if + { % We add 1 to the length just in case the original + % didn't have a FID. + exch dup length 1 add dict exch + { % Stack: changed newfont key value + 1 index /FID eq 4 index + { 2 index /UniqueID eq or 2 index /XUID eq or } + if not { 3 copy put } if pop pop + } + forall exch + } + if pop + } bdef + +% Insert a new Encoding or Metrics into a font if necessary. +% Return a possibly updated font, and a flag to indicate whether +% the font was actually copied. +/.updatefontmetrics { % <font> <Metrics|null> .updatefontmetrics + % <font'> <copied> + dup //null ne { + exch //true .copyfontdict dup /Metrics 4 -1 roll put //true + } { + pop //false + } ifelse +} bdef + +/.updatefontencoding { % <font> <Encoding|null> .updatefontencoding + % <font'> <copied> + dup //null ne { dup 2 index /Encoding get ne } { //false } ifelse { + exch //false .copyfontdict dup /Encoding 4 -1 roll put //true + } { + pop //false + } ifelse +} bdef + +% Duplicate keys in CharString dictionary according to GlyphMap: <</new_glyph /old_glyph>> +% We have to do this because PDF fonts can associate multiple widths with the same glyph +% but Metrics dictionary works by the glyph name. +/.update_charstring { % <font> <GlyphMap> .update_charstring <font'> <copied> + dup //null ne { + exch //true .copyfontdict % map font + dup dup /CharStrings get % map font font cstr + dup length % map font font cstr len + 4 index length add % map font font cstr len+map_len + dict copy dup begin % map font font cstr' + /CharStrings exch put % map font + exch { % font /new /old + currentdict exch .knownget { + def + } { + currentdict /.notdef .knownget { + def + } { + pop + % The font has no .notdef. + % Could not resolve the conflict, + % but either the font is invalid or the glyph name is never used. + } ifelse + } ifelse + } forall + end //true + } { + pop //false + } ifelse +} bdef + +/.updatefont { % <font> <Encoding|null> <Metrics|null> <GlyphMap|null> + % .updatefont <font'> <copied> + 4 2 roll % <Metrics|null> <GlyphMap> <font> <Encoding|null> + .updatefontencoding % <Metrics|null> <GlyphMap> <font> bool + 4 1 roll exch % bool <Metrics|null> <font> <GlyphMap> + .update_charstring % bool <Metrics|null> <font> bool + 3 1 roll exch % bool bool <font> <Metrics|null> + .updatefontmetrics % bool bool <font> bool + 4 2 roll or or % <font> is_copied +} bdef + +% ---------------- Text positioning ---------------- % + +/Td { + TextLineMatrix transform TextLineMatrix 4 2 getinterval astore pop + TextLineMatrix TextMatrix copy pop settextstate +} bdef +/TD { dup neg /TextLeading gput Td } bdef +/T* { 0 TextLeading neg Td } bdef +/Tm { + TextLineMatrix astore TextMatrix copy pop settextstate +} bdef + +% ---------------- Text painting ---------------- % + +/Vexch { + rootfont /WMode knownoget { 1 eq { exch } if } if +} bind def + +/textrenderingprocs [ % (0 is handled specially) + % Painting-only modes + { tf } { tS } { tB } { tn } + % Clipping modes + { gsave tf grestore tW } + { gsave tS grestore tW } + { gsave tB grestore tW } + { tW } +] readonly def + +/pdfwrite_textrenderingprocs [ + { setfillstate show } bind + { setstrokestate show } bind + { gsave 0 .settextrenderingmode + setfillstate dup show currentpoint 3 -1 roll + grestore gsave setstrokestate false charpath stroke + grestore moveto + } bind + { setfillstate show } bind + { gsave 0 .settextrenderingmode + setfillstate dup show grestore true charpath } bind + { gsave 1 .settextrenderingmode + setstrokestate dup show grestore + true charpath } bind + { gsave 0 .settextrenderingmode + setfillstate dup show grestore gsave dup + setstrokestate false charpath stroke grestore + true charpath } bind + { true charpath } bind +] readonly def + +/setshowstate + { WordSpacing 0 eq TextSpacing 0 eq and FontMatrixNonHV not and + { + currentdevice .devicename /pdfwrite eq + { + pdfwrite_textrenderingprocs TextRenderingMode get + } + { + TextRenderingMode 0 eq { + { setfillstate show } + } { + TextRenderingMode 3 eq { + % Some PDF files execute 'tm' with a singular matrix, + % and then use the text rendering mode 3. + % The graphics library currently cannot handle text + % operations when the CTM is singular. + % Work around this here. + { + matrix currentmatrix dup dup + dup 0 get 0 eq 1 index 1 get 0 eq and { + dup dup 2 get 0 eq { 0 }{ 1 } ifelse 1 put + } if + dup 2 get 0 eq 1 index 3 get 0 eq and { + dup dup 1 get 0 eq { 3 }{ 2 } ifelse 1 put + } if + setmatrix + 2 index setfillstate show % Tr was set to graphic state. + setmatrix + % now set the currentpoint using the original matrix + gsave + setmatrix + false charpath currentpoint newpath + grestore + moveto + } + } { + { false charpath textrenderingprocs TextRenderingMode get exec } + } ifelse + } ifelse + } ifelse + } + { TextRenderingMode 0 eq TextRenderingMode 3 eq or + % Tr was set to graphic state. + { FontMatrixNonHV { + { + setfillstate + [ TextSpacing WordSpacing 3 index + { % str [... weach wword c undef|ythis xthis|undef + exch % will be removed, unless FontMatrix.xx/yy == 0 (FontMatrixNonHV already true) + Vexch pop % str [... weach wword c wthis + 3 index add exch 32 eq {1 index add} if % str [... weach wword w + 3 1 roll % str [... w weach wword + } + % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics + currentfont /FontMatrix get 0 3 Vexch pop get 0 ne { + 1 1 index length 1 sub getinterval cvx + } if + cshow pop pop ] + { xshow } { yshow } Vexch pop exec + } + } { + WordSpacing 0 eq + { { setfillstate TextSpacing 0 Vexch 3 -1 roll ashow } } + { TextSpacing 0 eq + { { setfillstate WordSpacing 0 Vexch 32 4 -1 roll widthshow } } + { { setfillstate WordSpacing 0 Vexch 32 + TextSpacing 0 Vexch 6 -1 roll awidthshow } } + ifelse + } + ifelse + } ifelse + } + { { WordSpacing TextSpacing + % Implement the combination of t3 and false charpath. + % Note that we must use cshow for this, because we + % can't parse multi-byte strings any other way. + % Stack: string wword wchar + { + exch % will be removed, unless FontMatrixNonHV && FontMatrix.xx/yy == 0 + % Stack: str wword wchar ccode xthis ythis + Vexch pop currentpoint 6 3 roll + % Stack: str wthis xorig yorig wword wchar ccode + (x) dup 0 3 index put //false charpath + 3 copy 32 eq { add } { exch pop } ifelse + % Stack: str wthis xorig yorig wword wchar ccode wextra + 7 -3 roll moveto add + 0 Vexch rmoveto pop + } + % for the "exch" removed or not below, see comment in pdf_font.ps::getfontmetrics + FontMatrixNonHV dup not exch { + currentfont /FontMatrix get 0 3 Vexch pop get 0 ne + } if { + 1 1 index length 1 sub getinterval cvx + } if + 4 -1 roll cshow pop pop + textrenderingprocs TextRenderingMode get exec + } + } + ifelse + } + ifelse /Show gput + } bdef +/showfirst { setshowstate Show } def + +/Tj { + 0 0 moveto Show settextposition +} bdef +/' { T* Tj } bdef +/" { exch Tc exch Tw T* Tj } bdef +/TJ { + 0 0 moveto { + dup type /stringtype eq { + Show + } { -1000 div + currentfont /ScaleMatrix .knownget { 0 get mul } if + 0 Vexch rmoveto + } ifelse + } forall settextposition +} bdef + +/tf { setfillstate currentpoint fill moveto } bdef +/tn { currentpoint newpath moveto } bdef % Obsolete, never used. +% For stroking characters, temporarily restore the graphics CTM so that +% the line width will be transformed properly. +/Tmatrix matrix def +/tS + { setstrokestate + currentpoint //Tmatrix currentmatrix TextSaveMatrix setmatrix stroke + setmatrix moveto + } bdef +/tB { gsave tf grestore tS } bdef +% This does the wrong thing if there have been multiple text operations +% within a single BT/ET pair, but it's a start. +/tW { } bdef + +% Text formatting and painting for the AcroForm field without appearance streams. +/Tform { % <MaxLen> (V) <Ff> <Q> Tform - + clippath pathbbox 4 2 roll pop pop % MaxLen (V) Ff Q dx dy + currentfont /ScaleMatrix .knownget { 3 get } { 1 } ifelse % MaxLen (V) Ff Q dx dy yy + currentfont /FontBBox get dup 1 get neg exch 3 get % MaxLen (V) Ff Q dx dy yy desc asc + dup 0 ne { div } { pop pop 0 } ifelse % MaxLen (V) Ff Q dx dy yy desc/asc + 1 index mul % MaxLen (V) Ff Q dx dy yy desc/asc*yy + + 4 index 16#1000 and 0 ne { % multiline + 8 { pop } repeat (Multiline form fields are not yet implemented.) = + } { + 4 index 16#1000000 and 0 ne { % comb + 8 { pop } repeat (Combed form fields are not yet implemented.) = + } { % plain text + 3 1 roll sub add 2 div % MaxLen (V) Ff Q dx (dy-yy+desc)/2 + 0 exch moveto % MaxLen (V) Ff Q dx + 1 index 0 ne { + 3 index stringwidth pop % MaxLen (V) Ff Q dx w + sub exch 1 eq { 2 div } { 2 sub } ifelse % MaxLen (V) Ff (dx-w)/2 + 0 rmoveto % MaxLen (V) Ff + pop % MaxLen (V) + } { + pop pop pop % MaxLen (V) + 2 0 rmoveto + } ifelse + exch pop Show % - + } ifelse + } ifelse +} bdef + +end readonly put % GS_PDF_ProcSet + +.setglobal diff --git a/gs/Resource/Init/pdf_rbld.ps b/gs/Resource/Init/pdf_rbld.ps new file mode 100644 index 000000000..f86602a90 --- /dev/null +++ b/gs/Resource/Init/pdf_rbld.ps @@ -0,0 +1,332 @@ +% Copyright (C) 2002 Artifex Software, Inc. All rights reserved. +% +% This software is provided AS-IS with no warranty, either express or +% implied. +% +% This software is distributed under license and may not be copied, +% modified or distributed except as expressly authorized under the terms +% of the license contained in the file LICENSE in this distribution. +% +% For more information about licensing, please refer to +% http://www.ghostscript.com/licensing/. For information on +% commercial licensing, go to http://www.artifex.com/licensing/ or +% contact Artifex Software, Inc., 101 Lucas Valley Road #110, +% San Rafael, CA 94903, U.S.A., +1(415)492-9861. + +% $Id$ +% pdf_rbld.ps - Rebuilding of broken PDF files (xref errors) + +% This module contains routines that are used if we detect an error +% while reading the xref tables. These routines will scan the file and +% build an xref table by finding the objects. We also need to find the +% appropriate trailer dictionary. Note: One procedure is also used +% even if we do not need to rebuild a PDF file. +% +% This module cannot rebuild a PDF file which has had errors created inside +% of objects or binary data streams. It often succeeds with files that +% have had its end of lines converted between unix and dos versions. + +% if true --> we have an object with duplicate object and generation numbers. +/dup_obj_gen_num false def + +% Note: This procedure is also used by non-rebuild code. +% Store a line in the xref array (Actually Objects and Generations arrays) +% <obj num> (strm num> <obj loc> <gen num> <rebuild> +% setxrefentry <obj num> strm num> <obj loc> <gen num> +/setxrefentry +{ + 5 1 roll + dup 65535 or 65535 ne { + ( **** Warning: Generation number out of 0..65535 range, assuming 0.\n) + pdfformaterror + pop 0 + } if + % We store generation numbers as value + 1 + % We reserve 0 to indicate an free xref entry + 1 add % increment generation number + % To save space, generations numbers are stored in a lstring unless we + % find a generation number greater than 255. If so then transfer to + % an larray. + dup 255 gt { + Generations ltype /stringtype eq { % Convert Generations to an larray. + larray Generations llength lgrowto dup % Create new larray + 0 1 2 index llength 1 sub { % Copy from old lstring to new larray + Generations 1 index lget lput dup + } for + pop + /Generations exch store % Save new Generations larray + } if + } if + % Verify that the new values are for a new object. If the current + % entry is null then we have a new entry. + Objects 4 index lget null eq { + ObjectStream 4 index 4 index cvx lput % Save ObjectStream object number + Objects 4 index 3 index cvx lput % Save object location + Generations 4 index 2 index lput % Save geenration number + } { + % Verify that the new entry has at least as high a generaton number + % We accept equal entry number because we have found PDF files in + % which there are multiple objects with the same object and entry + % numbers. The normal xref logic only accepts the first such + % entry that it finds. However the 'rebuild PDF' logic can find + % both such entries. The correct one is usually the last one. + Generations 4 index lget 1 index le { + ObjectStream 4 index 4 index cvx lput % Save ObjectStream object number + Objects 4 index 3 index cvx lput % Save object location + Generations 4 index 2 index lput % Save geenration number + } if + % Set error flag if we have equal object and generation numbers + Generations 4 index lget 1 index eq { /dup_obj_gen_num true def } if + } 8 -1 roll { ifelse } { pop if } ifelse % Run 'else' only when rebuilding. +} bind def + +% Print the contents of the xref array. This actually consists of three +% arrays (Objects, Generations, and ObjectStream). All three are larrays. +% larrays are a special Ghostscript object which can be arrays with more +% than 64k elements. +/print_xref % - print_xref - +{ 0 1 Objects llength 1 sub % stack: 0 1 <number of objects - 1> + { dup =only % print object number + ( ) print + dup Generations exch lget 1 sub =only % print Generation number + ( ) print + dup ObjectStream exch lget ==only % print ObjectStream object number + ( ) print + Objects exch lget === % print object location + } for + flush +} bind def + +% Get token from string and check its type +% <string> <type> typed_token <false> % no token or not match +% <string> <type> typed_token <obj> <last> <true> % matching token type +% Where last is the string remainder +/typed_token +{ exch + token_nofail % get token + { + dup type % stack: type last token type + 4 -1 roll eq { % stack: last token bool + exch true % desired object found - set exit status + } { + pop pop false % not type - clear stack, set exit status + } ifelse + } { + pop false % no token - pop type, set exit status + } ifelse % check if we got token +} bind def + +% Allocate space for post_eof_count to be bound into procedures below. +/post_eof_count 0 def + +% We want the location of the trailer dictionary at the start of file. +% First we will find the xref. Then we will skip over the xref entries +% to the trailer. +/search_start_trailer % - search_start_trailer <trailer loc> +{ % Read the first 300 bytes and check for xref + PDFfile 0 setfileposition + PDFfile bytesavailable post_eof_count sub % location of end of data + 300 .min % block size to read + dup string 0 1 4 -1 roll 1 sub + { 2 copy PDFfile read pop put pop } for + (xref) search { + % found 'xref' + exch pop exch pop length 4 add PDFfile exch setfileposition + PDFfile token pop % get starting entry - or 'trailer' + (trailer) ne { % if we do not already have 'trailer' + PDFfile token pop % get number of entries + PDFfile token pop pop % this moves us into the middle of the first entry + 25 string exch % define working string for readline + { PDFfile 1 index readline pop pop + } repeat % skip entries + pop % pop working string + PDFfile token pop pop % get 'trailer' + PDFfile fileposition % get file position + } if + } { + pop search_end_trailer % no xref, should not happen, search end of file + } ifelse +} bind def + +% We want the location of the trailer dictionary at the end of file. +% We will read the last block of data and search for the final occurance +% of the word 'trailer' +/search_end_trailer % - search_end_trailer <trailer loc> +{ % Position to read block of data from the end of the file. Note: We ignore + % anything past the last %%EOF since this is not PDF data. + PDFfile 0 setfileposition + PDFfile bytesavailable post_eof_count sub % location of end of data + dup 65535 .min % block size to read + % stack: <file end pos> <block size> + % move file position to the start of the block + 2 copy sub PDFfile exch setfileposition + % read block of data + dup string 0 1 4 -1 roll 1 sub { 2 copy PDFfile read pop put pop } for + % search for last occurance of 'trailer' + (trailer) { search not { exit } if pop } loop + % determine where the trailer is in the file + % trailer loc = end loc - remaing string length + length sub +} bind def + +% We want to find the trailer dictionary. There is a trailer dictionary +% for each xref object list. We only want the trailer dictionary associated +% with the first xref object list. In theory this can be anywhere in the +% file. However since we are trying to repair a broken file, we cannot simply +% follow the xref links. So we are falling back to a simple strategy. We +% find the specified location of the first xref list. If its location is in +% the first half of the file then we search for the first trailer dictionary +% at the start of the file. Otherwise we search for the last trailer at the +% end of the file. +/search_trailer % - search_trailer - +{ % Find the 'startxref' and associated position at the end of the file. + % Position to read block of data from the end of the file. Note: We + % actually end at the end of the last %%EOF since this is the end of the + % useful PDF data. (Some files contain trailing garbage.) + PDFfile 0 setfileposition + PDFfile bytesavailable % size of file + post_eof_count sub dup % location of end of last %%EOF + dup 4096 .min % block size to read + % stack: <useful file size> <useful file size file> <block size> + % move file position to the start of the block + 2 copy sub PDFfile exch setfileposition + % read block of data + dup string 0 1 4 -1 roll 1 sub { 2 copy PDFfile read pop put pop } for + % search for last occurance of 'startxref' + false % Assume that startxref not present + exch (startxref) { + search not { exit } if % Exit loop when no more startxref's + pop 3 -1 roll pop true 3 1 roll % Idicate that we have found starxref + } loop + exch % Exch last string and 'found' flag + { + % determine where the startxref is in the file + % 'startxref' loc = end loc - remaing string length - 9 bytes + length sub 9 sub + % move the file to this position and read startxref and position + PDFfile exch setfileposition PDFfile token + pop pop PDFfile token pop + } { + % startxref not found. We will search the end of the file for trailer. + pop pop PDFfilelen + } ifelse + % compare xref position to 1/2 the length of the file and search for trailer + exch 2 div lt { search_start_trailer } { search_end_trailer } ifelse + % get the trailer + PDFfile exch setfileposition % set to the specified trailer location + /dictlevelcount 0 def + PDFfile traileropdict .pdfrun % read trailer info + /Trailer exch def +} bind def + +% This routine will determine if there is stuff after the %%EOF. There is +% supposed to be only a line termination. However many real life files +% contain some garbage. This routine checks how much. We then ignore this +% stuff when we are scanning for objects. +/determine_post_eof_count % - determine_post_eof_count <count> +{ % Position to read block of data from the end of the file. + PDFfilelen % size of file + dup 4096 .min % block size to read + % stack: <file size> <file size> <block size> + % move file position to the start of the block + 2 copy sub PDFfile exch setfileposition + % read block of data + dup string 0 1 4 -1 roll 1 sub { 2 copy PDFfile read pop put pop } for + % search for last occurance of '%%EOF' + (%%EOF) { search not { exit } if pop } loop + % how much is left = remaining string length + length exch pop % pop /%%EOF +} bind def + +% This routine will scan a file searaching for object locations to build +% an alternate version of the data in the xref tables. +% Its purpose is to provide a basis for an xref fixing facility. +/search_objects % - search_objects - +{ % Initialize the Objects, Generations, etc. larrays + initPDFobjects + % reset duplicate object and generation numbers error flag + /dup_obj_gen_num false def + % Determine how many bytes are in the file after the final %%EOF + /post_eof_count determine_post_eof_count def + % Start at the beginning of the file + PDFfile 0 setfileposition + % Create a working string (and also store its length on stack). We are + % using a maximum size string size the logic below wants a recovered object + % to fit into our working string. + 65535 dup string + { % Now loop through the entire file lloking for objects + PDFfile fileposition % save current file position + % When we get near the end of the file, we use a smaller interval of + % our working string to prevent reading past the end. (See comments on + % EOF testing below.) + PDFfile bytesavailable post_eof_count sub 10 sub dup 4 index lt { + 2 index 0 3 -1 roll getinterval % near EOF, use interval of string + } { pop 1 index % not near end, use full working string + }ifelse + % Read a line from file. If the line does not fit into our working string, + % or any other error, then we will discard it. + PDFfile exch { readline } .internalstopped + { pop pop false } if % indicate no string if we stopped + { % stack: <length> <working_str> <loc> <string> + % Now that we have line, get obj num, ref num, and 'obj'. Verify that each + % of these is correct type. + /integertype typed_token { % get obj number + /integertype typed_token { % get ref number + /nametype typed_token { % get 'obj' text + pop % pop remaining string + /obj eq { % verify name is 'obj' + % make sure we have room in the arrays. We work in increments + % of 20 each time we increase the size. + 1 index 20 add 20 idiv 20 mul + growPDFobjects + % save xref parameters into ObjectStream, Objects and Generations + 1 index 0 % rearrange parms for setxrefentry + 4 index PDFoffset sub 3 index + //true setxrefentry % save parameters + pop pop pop pop % clear parameters + } if % check if name is 'obj' + } if % check if we got 'obj" string + pop % remove ref number + } if % check if we got ref number + pop % remove obj number + } if % check if we got object number + } if % check if got a string from readline + pop % remove location + % Check if we are approaching the end of the file. We do not want to + % read past the end of the file since that closes it. We actually stop + % 10-20 bytes early since there cannot be an object that close to the end. + % (There is a Trailer dictionary, etc. at the end of the file.) + PDFfile bytesavailable post_eof_count sub 20 lt { exit } if + } loop % loop through the entire file + pop pop % remove working string and its length + % Output warning if we have two objects with the same object and generation + % numbers. + dup_obj_gen_num { + ( **** Warning: There are objects with matching object and generation\n) + pdfformaterror + ( **** numbers. The accuracy of the resulting image is unknown.\n) + pdfformaterror + } if +} bind def + +% Print warning message because we found a problem while reading the xref +% tables +/print_xref_warning +{ ( **** Warning: An error occurred while reading an XREF table.\n) + pdfformaterror + ( **** The file has been damaged. This may have been caused\n) + pdfformaterror + ( **** by a problem while converting or transfering the file.\n) + pdfformaterror + ( **** Ghostscript will attempt to recover the data.\n) + pdfformaterror +} bind def + +% Attempt to recover the XRef data. This is called if we have a failure +% while reading the normal XRef tables. This routine usually works +% only for pre PDF1.5 versions of PDF files. +/recover_xref_data % - recover_xref_data - +{ print_xref_warning % Print warning message + count pdfemptycount sub { pop } repeat % remove anything left by readxref + search_objects % Search for objects +} bind def diff --git a/gs/Resource/Init/pdf_sec.ps b/gs/Resource/Init/pdf_sec.ps new file mode 100644 index 000000000..98a09e236 --- /dev/null +++ b/gs/Resource/Init/pdf_sec.ps @@ -0,0 +1,469 @@ +% Copyright (C) 1996-1998 Geoffrey Keating. +% Copyright (C) 2001 Artifex Software, Inc. +% This file may be freely distributed with or without modifications, +% so long as modified versions are marked as such and copyright notices are +% not removed. + +% $Id$ +% Implementation of security hooks for PDF reader. + +% This file contains the procedures that have to take encryption into +% account when reading a PDF file. It replaces the stub version of this +% file that is shipped with GhostScript. It requires GhostScript 7.01 +% or later. + +% Documentation for using this file is available at +% http://www.ozemail.com.au/%7Egeoffk/pdfencrypt/ + +% Modified by Alex Cherepanov to work with GS 6.60 and higher. +% New versions of GS require explicit checks for /true , /false, and /null +% in .decpdfrun . This fix is backward-compatible. + +% Modified by Raph Levien and Ralph Giles to use the new C +% implementations of md5 and arcfour in ghostscript 7.01, and to +% be compatible with PDF 1.4 128-bit encryption. + +/.setlanguagelevel where { pop 2 .setlanguagelevel } if +.currentglobal true .setglobal +/pdfdict where { pop } { /pdfdict 100 dict def } ifelse +pdfdict begin + +% Older ghostscript versions do not have .pdftoken, so we use 'token' instead. +/.pdftoken where { pop } { /.pdftoken /token load def } ifelse + +% take a stream and arc4 decrypt it. +% <stream> <key> arc4decodefilter <stream> +/arc4decodefilter { + 1 dict begin + /Key exch def + currentdict end /ArcfourDecode filter +} bind def + +% <ciphertext> <key> arc4decode <plaintext> +/arc4decode { + %(key: ) print dup == (ct: ) print 1 index == + 1 index length 0 eq { + pop + } { + 1 index length string 3 1 roll arc4decodefilter exch readstring pop + } ifelse +} bind def + +/md5 { + 16 string dup /MD5Encode filter dup 4 3 roll writestring closefile +} bind def + +/md5_trunk { + md5 0 pdf_key_length getinterval +} bind def + + +/pdf_padding_string + <28bf4e5e4e758a41 64004e56fffa0108 + 2e2e00b6d0683e80 2f0ca9fe6453697a> +def + +% Pad a key out to 32 bytes. +/pdf_pad_key { % <key> pdf_pad_key <padded key> + dup length 32 gt { 0 32 getinterval } if + pdf_padding_string + 0 32 3 index length sub getinterval + concatstrings +} bind def + +/pdf_xorbytes { % <iter-num> <key> pdf_xorbytes <xored-key> + dup length dup string + exch 1 sub 0 1 3 2 roll { + % <iter-num> <key> <new-key> <byte-num> + dup 3 index exch get 4 index xor + % <iter-num> <key> <new-key> <byte-num> <byte> + 3 copy put pop pop + } for + 3 1 roll pop pop +} bind def + +% Get length of encryption key in bytes +/pdf_key_length { % pdf_key_length <key_length> + Trailer /Encrypt oget + dup /V knownoget not { 0 } if 1 eq + { pop 5 } % If V == 1 then always use 40 bits + { /Length knownoget { -3 bitshift } { 5 } ifelse } + ifelse +} bind def + +% Algorithm 3.2 +/pdf_compute_encryption_key { % <password> pdf_compute_encryption_key <key> + % Step 1. + pdf_pad_key + + % Step 2, 3. + Trailer /Encrypt oget dup /O oget + % <padded-key> <encrypt> <O> + + % Step 4. + exch /P oget 4 string exch + 2 copy 255 and 0 exch put + 2 copy -8 bitshift 255 and 1 exch put + 2 copy -16 bitshift 255 and 2 exch put + 2 copy -24 bitshift 255 and 3 exch put pop + % <padded-key> <O> <P> + + % Step 5. + Trailer /ID knownoget { 0 oget } { + () + ( **** ID key in the trailer is required for encrypted files.\n) pdfformaterror + } ifelse + 3 { concatstrings } repeat + % We will finish step 5 after possibly including step 6. + + % The following only executed for /R equal to 3 or more + Trailer /Encrypt oget dup /R oget dup 3 ge { + + % Step 6. If EncryptMetadata is false, pass 0xFFFFFFFF to md5 function + % The PDF 1.5 Spec says that EncryptMetadata is an undocumented + % feature of PDF 1.4. That implies that this piece of logic should + % be executed if R >= 3. However testing with Acrobat 5.0 and 6.0 shows + % that this step is not executed if R equal to 3. Thus we have a test for + % R being >= 4. + 4 ge { + /EncryptMetadata knownoget % Get EncryptMetadata (if present) + not { true } if % Default is true + not { % If EncryptMetadata is false + <ff ff ff ff> concatstrings % Add 0xFFFFFFFF to working string + } if + } { + pop % Remove Encrypt dict + } ifelse + md5_trunk % Finish step 5 and 6. + + % Step 7. Executed as part of step 6 + % Step 8. (This step is defintely a part of PDF 1.4.) + 50 { md5_trunk } repeat + } { + pop pop md5_trunk % Remove R, Encrypt dict, finish step 5 + } ifelse + + % Step 9 - Done in md5_trunk. +} bind def + +% Algorithm 3.4 +/pdf_gen_user_password_R2 { % <filekey> pdf_gen_user_password_R2 <U> + + % Step 2. + pdf_padding_string exch arc4decode +} bind def + +% Algorithm 3.5 +/pdf_gen_user_password_R3 { % <filekey> pdf_gen_user_password_R3 <U> + + % Step 2. + pdf_padding_string + + % Step 3. + Trailer /ID knownoget { 0 oget } { + () + ( **** ID key in the trailer is required for encrypted files.\n) pdfformaterror + } ifelse + concatstrings md5 + + % Step 4. + 1 index arc4decode + + % Step 5. + 1 1 19 { + 2 index pdf_xorbytes arc4decode + } for + exch pop + +} bind def + +/pdf_gen_user_password { % <password> pdf_gen_user_password <filekey> <U> + % common Step 1 of Algorithms 3.4 and 3.5. + pdf_compute_encryption_key dup + + Trailer /Encrypt oget + + /R oget dup 2 eq { + pop pdf_gen_user_password_R2 + } { + dup 3 eq { + pop pdf_gen_user_password_R3 + } { + dup 4 eq { % 4 uses the algorithm as 3 + pop pdf_gen_user_password_R3 + } { + ( **** This file uses an unknown standard security handler revision: ) + exch =string cvs concatstrings pdfformaterror printProducer + /pdf_check_user_password cvx /undefined signalerror + } ifelse + } ifelse + } ifelse +} bind def + +% Algorithm 3.6 +/pdf_check_user_password { % <password> pdf_check_user_password <filekey> true + % <password> pdf_check_user_password false + pdf_gen_user_password + + Trailer /Encrypt oget /U oget + + 0 2 index length getinterval eq { + true + } { + pop false + } ifelse +} bind def + +% Compute an owner key, ie the result of step 4 of Algorithm 3.3 +/pdf_owner_key % <password> pdf_owner_key <owner-key> +{ + % Step 1. + pdf_pad_key + + % Step 2. + md5_trunk + + % 3.3 Step 3. Only executed for /R equal to 3 or more + Trailer /Encrypt oget /R oget 3 ge { + 50 { md5_trunk } repeat + } if + + % Step 4 - Done in md5_trunk. +} bind def + +% Algorithm 3.7 +/pdf_check_owner_password { % <password> pdf_check_owner_password <filekey> true + % <password> pdf_check_owner_password false + % Step 1. + pdf_owner_key + + % Step 2. + Trailer /Encrypt oget dup /O oget 2 index arc4decode + % <encryption-key> <encrypt-dict> <decrypted-O> + + % Step 3. Only executed for /R equal to 3 or more + exch /R oget 3 ge { + 1 1 19 { + 2 index pdf_xorbytes arc4decode + } for + } if + exch pop + % <result-of-step-3> + + pdf_check_user_password +} bind def + +% Process the encryption information in the Trailer. +/pdf_process_Encrypt { + Trailer /Encrypt oget + /Filter oget /Standard eq not { + ( **** This file uses an unknown security handler.\n) pdfformaterror + printProducer + /pdf_process_Encrypt cvx /undefined signalerror + } if + () pdf_check_user_password + { + /FileKey exch def + } { + /PDFPassword where { + pop PDFPassword pdf_check_user_password + { + /FileKey exch def + } { + PDFPassword pdf_check_owner_password + { + /FileKey exch def + } { + ( **** Password did not work.\n) pdfformaterror + printProducer + /pdf_process_Encrypt cvx /invalidfileaccess signalerror + } ifelse + } ifelse + } { + ( **** This file requires a password for access.\n) pdfformaterror + printProducer + /pdf_process_Encrypt cvx /invalidfileaccess signalerror + } ifelse + } ifelse + +% Trailer /Encrypt oget /P oget 4 and 0 eq #? and +% { ( ****This owner of this file has requested you do not print it.\n) +% pdfformaterror printProducer +% /pdf_process_Encrypt cvx /invalidfileaccess signalerror +% } +% if +} bind def + +% Calculate the key used to decrypt an object (to pass to .decpdfrun or +% put into a stream dictionary). +/computeobjkey % <object#> <generation#> computeobjkey <keystring> +{ + exch + FileKey length 5 add string + dup 0 FileKey putinterval + exch + % stack: gen# string obj# + 2 copy 255 and FileKey length exch put + 2 copy -8 bitshift 255 and FileKey length 1 add exch put + 2 copy -16 bitshift 255 and FileKey length 2 add exch put + pop exch + 2 copy 255 and FileKey length 3 add exch put + 2 copy -8 bitshift 255 and FileKey length 4 add exch put + pop md5 0 FileKey length 5 add 2 index length .min getinterval +} bind def + +% As .pdfrun, but decrypt strings with key <key>. +/PDFScanRules_true << /PDFScanRules true >> def +/PDFScanRules_null << /PDFScanRules null >> def +/.decpdfrun % <file> <keystring> <opdict> .decpdfrun - + { % Construct a procedure with the file, opdict and key bound into it. + 2 index cvlit mark + /PDFScanRules .getuserparam //null eq { + //PDFScanRules_true { setuserparams } 0 get % force PDF scanning mode + mark 7 4 roll + } { + mark 5 2 roll + } ifelse + { .pdftoken not { (%%EOF) cvn cvx } if + dup xcheck + { PDFDEBUG { dup == flush } if + 3 -1 roll pop + 2 copy .knownget + { exch pop exch pop exec + } + { exch pop + dup /true eq + { pop //true + } + { dup /false eq + { pop //false + } + { dup /null eq + { pop //null + } + { ( **** Unknown operator: ) + exch =string cvs concatstrings (\n) concatstrings + pdfformaterror + } + ifelse + } + ifelse + } + ifelse + } + ifelse + } + { exch pop PDFDEBUG { dup ==only ( ) print flush } if + dup type /stringtype eq + { + % Check if we have encrypted strings R=4 allows for + % selection of encryption on streams and strings + Trailer /Encrypt oget % Get encryption dictionary + dup /R oget 4 lt % only 4 has selectable + { % R < 4 --> encrypted strings + pop 1 index arc4decode % Decrypt string + PDFDEBUG { (%Decrypted: ) print dup == flush } if + } { % Else R = 4 + /StrF knownoget % Get StrF (if present) + { % If StrF is present ... + /Identity eq not % Check if StrF != Identity + { 1 index arc4decode % Decrypt string + PDFDEBUG { (%Decrypted: ) print dup == flush } if + } + if % If StrF != identity + } + if % If StrF is known + } + ifelse % Ifelse R < 4 + } + if % If = stringtype + exch pop + } + ifelse + } + aload pop .packtomark cvx + { loop } 0 get 2 packedarray cvx + { stopped } 0 get + /PDFScanRules .getuserparam //null eq { + //PDFScanRules_null { setuserparams } 0 get % reset PDF scannig mode if it was off + } if + /PDFsource PDFsource + { store { stop } if } aload pop .packtomark cvx + /PDFsource 3 -1 roll store exec + } bind def +currentdict /PDFScanRules_true undef +currentdict /PDFScanRules_null undef + +% Run the code to resolve an object reference. +/pdf_run_resolve +{ /FileKey where % Check if the file is encrypted + { pop % File is encrypted + 2 copy computeobjkey dup 4 1 roll + PDFfile exch resolveopdict .decpdfrun + dup dup dup 5 2 roll + % stack: object object key object object + { % Use loop to provide an exitable context. + xcheck exch type /dicttype eq and % Check if executable dictionary + not { % If object is not ... + pop pop % ignore object + exit % Exit 'loop' context + } if % If not possible stream + % Starting with PDF 1.4 (R = 3), there are some extra features + % which control encryption of streams. The EncryptMetadata entry + % in the Encrypt dict controls the encryption of metadata streams. + Trailer /Encrypt oget % Get encryption dictionary + dup /R oget dup 3 lt % Only PDF 1.4 and higher has options + { % R < 3 --> all streams encrypted + pop pop /StreamKey exch put % Insert StreamKey in dictionary + exit % Exit 'loop' context + } if + % Check EncryptMeta. stack: object object key Encrypt R + exch dup /EncryptMetadata knownoget % Get EncryptMetadata (if present) + not { true } if % If not present default = true + not % Check if EncryptMetadata = false + { % if false we need to check the stream type + 3 index /Type knownoget % Get stream type (if present) + not { //null } if % If type not present use fake name + /Metadata eq % Check if the type is Metadata + { pop pop pop pop % Type == Metadata --> no encryption + exit % Exit 'loop' context + } if + } if + % PDF 1.5 encryption (R == 4) has selectable encryption handlers. If + % this is not PDF 1.5 encryption (R < 4) then we are done checking and + % we need to decrypt the stream. stack: object object key R Encrypt + exch 4 lt % Check for less than PDF 1.5 + { pop /StreamKey exch put % Insert StreamKey in dictionary + exit % Exit 'loop' context + } if + % Check if the stream encryption handler (StmF) == Identity. + /StmF knownoget % Get StmF (if present) + not { /Identity } if % If StmF not present default = Identity + /Identity eq % Check if StmF == Identity + { pop pop % Identity --> no encryption + exit % Exit 'loop' context + } if + % If we get here then we need to decrypt the stream. + /StreamKey exch put % Insert StreamKey into dictionary + exit % Exit 'loop' context, never loop + } loop % End of loop exitable context + } { % Else file is not encrypted + PDFfile resolveopdict .pdfrun + } ifelse % Ifelse encrypted +} bind def + +% Prefix a decryption filter to a stream if needed. +% Stack: readdata? dict parms file/string filternames +% (both before and after). +/pdf_decrypt_stream + { 3 index /StreamKey known % Check if the file is encrypted + { + exch + % Stack: readdata? dict parms filternames file/string + 3 index /StreamKey get arc4decodefilter + exch + } if + } bind def + +end % pdfdict +.setglobal diff --git a/gs/Resource/Init/xlatmap b/gs/Resource/Init/xlatmap new file mode 100644 index 000000000..964ed8fc6 --- /dev/null +++ b/gs/Resource/Init/xlatmap @@ -0,0 +1,49 @@ +% xlatmap - the map of translation tables for various kinds of fonts. +% +% It specifies Decoding resources to be used with FAPI-handled fonts. +% If a font contains multiple character mapping tables, this gives +% priorities for choosing a specific table from the font according to +% the order of entries of this map. + +% This file is intended to be customized by users. Please keep the +% obvious format of this file. Strings and names must not be empty +% and must not contain null ('\0') characters. + +% $Id$ + +% The map contains entries for each kind of font being handled by +% any font rendering plugin. The key of an entry is the font type +% and the value is array of pairs. +% The first element of pair is a string which encodes identifier of +% character mapping table. The format of the first element depends +% on the font type, and should be recognized by the font rendering +% plugins. The second element is name of the Decoding resource. If +% that resource is not available, definefont will fail. Note that +% currently we supply insufficient decoding resources, as well as +% insufficient entries in this map. + +/TrueType +[ % Each entry is pair : + % a string PlatformID.SpecificID and a name of Decoding resource. + (3.0) /Symbol % Symbol + (3.1) /Unicode % Unicode + (3.2) /ShiftJIS % Japanese + (3.3) /PRC % Simplified Chinese, GB2312 + (3.4) /Big5 % Traditional Chinese + (3.5) /Wansung % Korean + (3.6) /Johab % Korean + % todo : add more entries +] + +/PostScript +[ % Since PostScript fonts were designed especially for PostScript, + (*) /Unicode % fixme : other charsets +] + +/Intellifont +[ (*) /FCO_Unicode % fixme : other charsets +] + +/Microtype +[ (*) /FCO_Unicode % FCOfontmap may may overwrite this for a specific font. +] |