summaryrefslogtreecommitdiff
path: root/gs/Resource
diff options
context:
space:
mode:
authorRay Johnston <ray.johnston@artifex.com>2008-08-08 04:22:38 +0000
committerRay Johnston <ray.johnston@artifex.com>2008-08-08 04:22:38 +0000
commit34f0b7f064072fabdbe47ab1a15d4f1341a0417d (patch)
tree5079325b87674bd54b7f244203f2364817a6ce1f /gs/Resource
parent7a31db6d4142087d29c17e875ef2de1727b9f8b2 (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')
-rw-r--r--gs/Resource/Init/FCOfontmap-PCLPS2107
-rw-r--r--gs/Resource/Init/Fontmap4
-rw-r--r--gs/Resource/Init/Fontmap.GS402
-rw-r--r--gs/Resource/Init/cidfmap28
-rw-r--r--gs/Resource/Init/gs_agl.ps1069
-rw-r--r--gs/Resource/Init/gs_btokn.ps331
-rw-r--r--gs/Resource/Init/gs_cet.ps61
-rw-r--r--gs/Resource/Init/gs_cff.ps848
-rw-r--r--gs/Resource/Init/gs_cidcm.ps446
-rw-r--r--gs/Resource/Init/gs_ciddc.ps214
-rw-r--r--gs/Resource/Init/gs_cidfm.ps129
-rw-r--r--gs/Resource/Init/gs_cidfn.ps412
-rw-r--r--gs/Resource/Init/gs_cidtt.ps141
-rw-r--r--gs/Resource/Init/gs_ciecs2.ps147
-rw-r--r--gs/Resource/Init/gs_ciecs3.ps137
-rw-r--r--gs/Resource/Init/gs_cmap.ps549
-rw-r--r--gs/Resource/Init/gs_cspace.ps1022
-rw-r--r--gs/Resource/Init/gs_css_e.ps114
-rw-r--r--gs/Resource/Init/gs_dbt_e.ps59
-rw-r--r--gs/Resource/Init/gs_devcs.ps250
-rw-r--r--gs/Resource/Init/gs_devn.ps218
-rw-r--r--gs/Resource/Init/gs_devpxl.ps78
-rw-r--r--gs/Resource/Init/gs_diskf.ps224
-rw-r--r--gs/Resource/Init/gs_diskn.ps214
-rw-r--r--gs/Resource/Init/gs_dpnxt.ps134
-rw-r--r--gs/Resource/Init/gs_dps.ps224
-rw-r--r--gs/Resource/Init/gs_dps1.ps139
-rw-r--r--gs/Resource/Init/gs_dps2.ps247
-rw-r--r--gs/Resource/Init/gs_dscp.ps118
-rw-r--r--gs/Resource/Init/gs_epsf.ps243
-rw-r--r--gs/Resource/Init/gs_fapi.ps344
-rw-r--r--gs/Resource/Init/gs_fntem.ps432
-rw-r--r--gs/Resource/Init/gs_fonts.ps1223
-rw-r--r--gs/Resource/Init/gs_frsd.ps81
-rw-r--r--gs/Resource/Init/gs_icc.ps340
-rw-r--r--gs/Resource/Init/gs_il1_e.ps66
-rw-r--r--gs/Resource/Init/gs_img.ps862
-rw-r--r--gs/Resource/Init/gs_indxd.ps205
-rw-r--r--gs/Resource/Init/gs_init.ps2192
-rw-r--r--gs/Resource/Init/gs_l2img.ps184
-rw-r--r--gs/Resource/Init/gs_lev2.ps1014
-rw-r--r--gs/Resource/Init/gs_ll3.ps379
-rw-r--r--gs/Resource/Init/gs_mex_e.ps66
-rw-r--r--gs/Resource/Init/gs_mgl_e.ps64
-rw-r--r--gs/Resource/Init/gs_mro_e.ps61
-rw-r--r--gs/Resource/Init/gs_patrn.ps309
-rw-r--r--gs/Resource/Init/gs_pdf_e.ps44
-rw-r--r--gs/Resource/Init/gs_pdfwr.ps874
-rw-r--r--gs/Resource/Init/gs_res.ps1118
-rw-r--r--gs/Resource/Init/gs_resmp.ps531
-rw-r--r--gs/Resource/Init/gs_sepr.ps268
-rw-r--r--gs/Resource/Init/gs_setpd.ps924
-rw-r--r--gs/Resource/Init/gs_statd.ps374
-rw-r--r--gs/Resource/Init/gs_std_e.ps73
-rw-r--r--gs/Resource/Init/gs_sym_e.ps83
-rw-r--r--gs/Resource/Init/gs_trap.ps103
-rw-r--r--gs/Resource/Init/gs_ttf.ps1947
-rw-r--r--gs/Resource/Init/gs_typ32.ps133
-rw-r--r--gs/Resource/Init/gs_typ42.ps62
-rw-r--r--gs/Resource/Init/gs_type1.ps238
-rw-r--r--gs/Resource/Init/gs_wan_e.ps46
-rw-r--r--gs/Resource/Init/pdf_base.ps1066
-rw-r--r--gs/Resource/Init/pdf_cslayer.ps121
-rw-r--r--gs/Resource/Init/pdf_font.ps1663
-rw-r--r--gs/Resource/Init/pdf_main.ps1884
-rw-r--r--gs/Resource/Init/pdf_ops.ps852
-rw-r--r--gs/Resource/Init/pdf_rbld.ps332
-rw-r--r--gs/Resource/Init/pdf_sec.ps469
-rw-r--r--gs/Resource/Init/xlatmap49
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.
+]