home *** CD-ROM | disk | FTP | other *** search
/ PC World 2001 April / PCWorld_2001-04_cd.bin / Software / Vyzkuste / gs / gs650w32.exe / gs6.50 / lib / pdf_font.ps < prev    next >
Text File  |  2000-12-05  |  25KB  |  778 lines

  1. %    Copyright (C) 1994, 2000 Aladdin Enterprises.  All rights reserved.
  2. % This file is part of AFPL Ghostscript.
  3. % AFPL Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author or
  4. % distributor accepts any responsibility for the consequences of using it, or
  5. % for whether it serves any particular purpose or works at all, unless he or
  6. % she says so in writing.  Refer to the Aladdin Free Public License (the
  7. % "License") for full details.
  8. % Every copy of AFPL Ghostscript must include a copy of the License, normally
  9. % in a plain ASCII text file named PUBLIC.  The License grants you the right
  10. % to copy, modify and redistribute AFPL Ghostscript, but only under certain
  11. % conditions described in the License.  Among other things, the License
  12. % requires that the copyright notice and this notice be preserved on all
  13. % copies.
  14.  
  15. % $Id: pdf_font.ps,v 1.12.2.2 2000/11/28 19:03:16 alexcher Exp $
  16. % pdf_font.ps
  17. % PDF font operations.
  18.  
  19. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  20. .currentglobal true .setglobal
  21. /pdfdict where { pop } { /pdfdict 100 dict def } ifelse
  22. GS_PDF_ProcSet begin
  23. pdfdict begin
  24.  
  25. % We cache the PostScript font in an additional element of the
  26. % font resource dictionary, called PSFont.
  27.  
  28. % ---------------- Encodings ---------------- %
  29.  
  30. % Apply a list of differences to an Encoding.
  31. % Note that the differences may cause the array to grow.
  32. /updateencoding {    % <encoding> <differences> updateencoding <enc'>
  33.     % Calculate the length of the result.
  34.   exch 0 2 index {
  35.     dup type /nametype ne { exch pop } { pop 1 add } ifelse
  36.   } forall
  37.   1 index length .max array dup 0 4 -1 roll putinterval
  38.   exch 0 exch {
  39.         % Stack: enc' code element
  40.     dup type /nametype ne
  41.       { exch pop }
  42.       { 3 copy put pop 1 add }
  43.     ifelse
  44.   } forall pop
  45. } bdef
  46.  
  47. % Get the Encoding for a font.
  48. /getencoding        % <base-encoding> <font-resource> getencoding <enc>
  49.  { /Encoding knownoget
  50.     { dup type /nametype eq
  51.        {
  52.          % The published PDF specification says the Encoding name
  53.          % "must be" one of the 3 predefined Encodings, implying
  54.          % that an error should occur if it isn't.  However, Acrobat
  55.          % Reader simply ignores unknown names, and since there are
  56.          % some buggy applications that rely on this, we do the same.
  57.  
  58.          dup dup dup /MacRomanEncoding eq
  59.          exch /MacExpertEncoding eq or 
  60.          exch /WinAnsiEncoding eq or
  61.            { exch pop findencoding
  62.            }
  63.            { pop
  64.            }
  65.          ifelse
  66.        }
  67.        { dup /BaseEncoding knownoget
  68.       { findencoding 3 -1 roll pop exch
  69.       }
  70.      if
  71.      /Differences knownoget { updateencoding } if
  72.        }
  73.       ifelse
  74.     }
  75.    if
  76.  } bdef
  77.  
  78. % Rename a font with a generated name.
  79. /renamefont {        % <fontdict> renamefont <font'>
  80.   dup /FontName 2 copy get genfontname dup 5 1 roll put definefont
  81. } bind def
  82.  
  83. % Adjust a font according to the Encoding and Widths in the font resource.
  84. /adjustfont {        % <font-resource> <font> adjustfont <font'>
  85.         % Hack required by the PDF specification: if the
  86.         % font resource has Subtype = /TrueType but the actual
  87.         % (installed) font is not a TrueType font, ignore the
  88.         % Encoding in the font resource.
  89.   1 index /Subtype oget /TrueType eq
  90.   1 index /FontType get 42 ne and {
  91.     null
  92.   } {
  93.     getfontencoding
  94.   } ifelse
  95.   getfontmetrics 4 -1 roll pop .updatefont { renamefont } if
  96. } bind def
  97.  
  98. % Get the (possibly modified) encoding of a font.
  99. /getfontencoding {    % <font-resource> <font> getfontencoding
  100.             %   <font-resource> <font> <Encoding|null>
  101.   1 index /Encoding known {
  102.     dup /Encoding .knownget { 2 index getencoding } { null } ifelse
  103.   } {
  104.     null
  105.   } ifelse
  106. } bdef
  107.  
  108. % Get the metrics of a font, if specified.
  109. /getfontmetrics {    % <font-resource> <font> <Encoding|null> getfontmetrics
  110.             %   <font-resource> <font> <Encoding|null>
  111.             %   <Metrics|null>
  112.   2 index /Widths known {
  113.     dup null eq { pop dup /Encoding get } if
  114.     4 dict begin
  115.       /Encoding exch def
  116.       /Metrics Encoding length dict def
  117.       exch
  118.       dup /Widths oget /Widths exch def
  119.         % Stack: font font-res
  120.         % Note that widths are always based on a 1000-unit
  121.         % character space, but the FontMatrix may specify
  122.         % some other scale factor.  Compensate for this here,
  123.         % by scaling the Widths if necessary.
  124.       0.001 2 index /FontMatrix get 0 get div
  125.         % Stack: font font-res mscale
  126.       1 index /FirstChar oget dup 1 4 index /LastChar oget
  127.        {    % Stack: font font-res mscale first-char index
  128.      Encoding 1 index get
  129.      Widths 2 index 4 index sub get
  130.          % Stack: font font-res mscale first-char index charname width
  131.      4 index mul
  132.         % There is a hack here to deal with encodings where the
  133.         % same character appears more than once, because the Metrics
  134.         % dictionary works by character name, not by character code.
  135.         % Because of this, we can't deal with Width vectors that
  136.         % specify different widths for the same character name
  137.         % appearing multiple times in the Encoding.
  138.      Metrics 2 index .knownget not { 0 } if 0 ne {
  139.        pop pop
  140.      } {
  141.         % Work around a bug in pdfTeX, which can generate Encoding
  142.         % vectors containing nulls.
  143.        1 index null ne {
  144.          Metrics 3 1 roll put
  145.        } {
  146.          pop pop
  147.        } ifelse
  148.      }
  149.      ifelse pop
  150.        }
  151.       for pop
  152.         % Now fill in the MissingWidth for any encoded characters
  153.         % that aren't in Metrics already.  Note that built-in
  154.         % fonts may have Widths/FirstChar/LastChar but no
  155.         % FontDescriptor, so we must check for this.
  156.         % Stack: font font-res mscale
  157.       1 index /FontDescriptor knownoget {
  158.     Metrics exch
  159.     /MissingWidth knownoget { 2 index mul } { 0 } ifelse exch
  160.     Encoding {
  161.         % Stack: font font-res mscale missing-width metrics charname
  162.         % Work around the abovementioned pdfTeX bug.
  163.       dup null ne {
  164.         2 copy known not { 2 copy 4 index put } if pop
  165.       } {
  166.         pop
  167.       } ifelse
  168.     } forall pop pop pop
  169.       } {
  170.     pop
  171.       } ifelse
  172.     exch Encoding Metrics end
  173.   } {
  174.     null
  175.   } ifelse
  176. } bdef
  177.  
  178. % ---------------- Descriptors ---------------- %
  179.  
  180. % Partial descriptors for the 14 built-in fonts.  Note that
  181. % from PDF 1.1 to PDF 1.2, the meaning of the Flag 6 in the FontDescriptor
  182. % object has undergone a subtle change in its meaning which has serious
  183. % consequences for searching with Acrobat:
  184. % In PDF 1.1, the flag meant: Font has StandardEncoding
  185. % In PDF 1.2, the flag means: Font has (subset of) StandardRomanCharacterSet
  186. /standardfontdescriptors mark
  187.   /Courier mark /Flags 16#23 .dicttomark
  188.   /Courier-Oblique 1 index
  189.   /Courier-Bold 1 index
  190.   /Courier-BoldOblique 1 index
  191.   /Helvetica mark /Flags 16#20 .dicttomark
  192.   /Helvetica-Oblique 1 index
  193.   /Helvetica-Bold 1 index
  194.   /Helvetica-BoldOblique 1 index
  195.   /Times-Roman mark /Flags 16#22 .dicttomark
  196.   /Times-Bold 1 index
  197.   /Times-Italic mark /Flags 16#62 .dicttomark
  198.   /Times-BoldItalic 1 index
  199.   /Symbol mark /Flags 16#4 .dicttomark
  200.   /ZapfDingbats 1 index
  201. .dicttomark readonly def
  202.  
  203. % ---------------- Utilities ---------------- %
  204.  
  205. % Fabricate a font name by adding ?'s on the end.
  206. /genfontname        % <name> genfontname <name>
  207.  { dup length string cvs
  208.     { (?) concatstrings
  209.       dup cvn FontDirectory exch known not { cvn exit } if
  210.     }
  211.    loop
  212.  } bdef
  213.  
  214. % Find a font, and adjust its encoding if necessary.
  215. /.pdfdfndict mark
  216.   /defaultfontname /Helvetica
  217. .dicttomark readonly def
  218. /pdffindfont {        % <font-resource> <fontname> pdffindfont <font>
  219.         % If the font isn't available, synthesize one based on
  220.         % its descriptor.
  221.   dup /Font resourcestatus {
  222.     pop pop findfont
  223.   } {
  224.     1 index /FontDescriptor knownoget {
  225.         % Stack: font-res fontname fontdesc
  226.       dup /Flags oget
  227.       dup 16#40 and -6 bitshift        % 1, oblique/italic
  228.       1 index 16#40000 and -17 bitshift add    % 2, bold
  229.       exch 16#2 and 2 bitshift add    % 8, serif
  230.         % We should look at the fixed flag, too.
  231.         % Stack: font-res fontname fontdesc properties
  232.       1 index /FontName oget exch
  233.         % Analyzes font name and extract "Narrow" property
  234.         % which is not described by the FontDescriptor Flags.
  235.       0 2 index .fontnameproperties 4 and or
  236.         % Rebind the default font name to Helvetica so that
  237.         % fonts with no properties are handled correctly.
  238.       //.pdfdfndict begin .substitutefontname end
  239.         % Stack: font-res fontname fontdesc substname|null
  240.       Fontmap 1 index known not {
  241.         % No available good substitution, use the standard one.
  242.     pop 1 index .substitutefont
  243.       } if
  244.       QUIET not {
  245.     (Substituting font ) print dup =only
  246.     ( for ) print 2 index =only (.) = flush
  247.       } if
  248.       3 -1 roll pop findfont
  249.         % Stack: font-res fontdesc font
  250.         % If this is a small-caps font, replace the CharString
  251.         % entries for a..z.
  252.       exch /Flags oget 16#20000 and 0 ne {
  253.     true .copyfontdict
  254.     dup /CharStrings 2 copy get dup length dict .copydict
  255.     4 index /FirstChar get 97 .max
  256.     5 index /LastChar get 122 .min 1 exch {
  257.         % Stack: font-res font' font' /CharStrings charstrings code
  258.         % Note that this only remaps a-z, not accented characters.
  259.       5 index /Widths oget 1 index 7 index /FirstChar get sub oget
  260.       1 string dup 0 5 -1 roll put
  261.         % Stack: font-res font' font' /CharStrings charstrings code
  262.         %   width (x)
  263.       2 index exch dup cvn exch
  264.       dup 0 2 copy get 32 sub put 4 -1 roll {
  265.             % Stack: operand (X) width
  266.         0 setcharwidth exch pop
  267.         currentfont /FontMatrix get matrix invertmatrix concat
  268.         0.7 dup scale 0 0 moveto show
  269.       } /exec cvx 4 packedarray cvx put
  270.     } for put
  271.     renamefont
  272.       } if
  273.     } {
  274.         % No descriptor available, use the default algorithm.
  275.       findfont
  276.     } ifelse
  277.   } ifelse adjustfont
  278. } bdef
  279.  
  280. % ---------------- Type 1 fonts ---------------- %
  281.  
  282. /buildType1        % <Type1-font-resource> buildType1 <font>
  283.  { dup /BaseFont get pdffindfont
  284.  } bdef
  285.  
  286. % The state dictionary for the embedded Type 1 font reading procedure
  287. % has the following keys and values:
  288. %    data - stream (filter)
  289. %    buffer, buffer2 - string
  290. %    hexify - procedure to convert buffer to hex if needed
  291. %    leftstr - string containing (non-negative) integer
  292. %    sectionstr - string containing a character 0 .. 2
  293. %    stream - (stream) dictionary
  294. %    proc - procedure of the form {-dict- type1read}
  295. % When the procedure is executing, this dictionary is current.
  296. % leftstr and sectionstr are strings so that we can change their values
  297. % reliably in case the font executes a restore!
  298. % We also have to do something special about embedded fonts that
  299. % execute definefont more than once -- that is the function of topFontDict.
  300.  
  301. % Read an embedded Type 1 font.
  302. /readfontfilter {    % <proc> readfontfilter <filter>
  303.   0 () /SubFileDecode filter
  304. } bdef
  305. /readtype1dict 5 dict dup begin
  306.   /definefont {
  307.     dup topFontDict eq topFontDict null eq or {
  308.       dup wcheck not { dup length dict copy } if
  309.       exch pop savedFontName exch
  310.     } if
  311.     //systemdict /definefont get exec
  312.   } bdef
  313.   /eexec {
  314.         % Assume the font dictionary is on the top of the stack.
  315.     count 0 gt { /topFontDict 1 index cvlit store } if
  316.     55665 /eexecDecode filter
  317.     //systemdict begin readtype1dictcopy begin cvx stopped
  318.     currentdict readtype1dictcopy eq { end } if
  319.     currentdict //systemdict eq { end } if
  320.      { stop } if
  321.   } bdef
  322. end readonly def
  323. /readtype1 {        % <font-resource> <stream-dict> readtype1 <font>
  324.         % Read the definition, using a procedure-based filter
  325.         % that turns binary/hex conversion on and off
  326.         % at the right times.
  327.    1 index exch
  328.    PDFfile fileposition 3 1 roll
  329.    10 dict begin
  330.      /leftstr (          ) 10 string copy def
  331.        dup /Length1 oget leftstr cvs pop
  332.      /sectionstr <00> 1 string copy def
  333.      /stream 1 index def
  334.      true resolvestream /data exch def
  335.      /buffer 1000 string def        % arbitrary
  336.      /buffer2 buffer length 2.1 div cvi 1 sub string def
  337.      /hexify /buf2hex load def
  338.    currentdict end
  339.    /type1read cvx 2 array astore cvx dup 0 get /proc 2 index put
  340.    readfontfilter
  341.         % Some buggy embedded fonts leave extra junk on the stack,
  342.         % so we have to make a closure that records the stack depth
  343.         % in a fail-safe way.
  344.    //systemdict begin
  345.         % The PDF specification is somewhat muddy about whether
  346.         % an embedded font's name is supposed to be the BaseFont
  347.         % from the Font object or the FontName from the descriptor.
  348.         % Acrobat Distiller requires the former.  Save away the
  349.         % name so we can substitute it at definefont time.
  350.    //readtype1dict dup length 3 add dict copy begin
  351.    1 index /BaseFont oget /savedFontName exch def
  352.    /topFontDict null def
  353.    /readtype1dictcopy currentdict def
  354.     { run } aload pop count 1 sub 2 packedarray cvx exec
  355.    end end
  356.    count exch sub { pop } repeat
  357.    PDFfile 3 -1 roll setfileposition
  358.    /BaseFont oget findfont
  359.    adjustfont
  360.  } bdef
  361.  
  362. % Execute the appropriate reading procedure.
  363. /type1read        % <dict> type1read <string>
  364.  { begin leftstr cvi
  365.     { type1read1 type1read2 type1read3 } sectionstr 0 get get exec
  366.    (          ) leftstr copy cvs pop end
  367.  } bdef
  368.  
  369. % Read the next block of data into the buffer.
  370. /type1readdata        % <left> <buffer> type1readdata <substring> <left'>
  371.  { 0 2 index 2 index length min getinterval
  372.         % Adobe requires readstring to signal an error if given
  373.         % an empty string.  Work around this nonsense here.
  374.    dup length 0 ne { data exch readstring pop } if
  375.    dup length 3 -1 roll exch sub
  376.    DEBUG
  377.     { dup =only ( read ) print
  378.       1 index length =only (: ) print
  379.       1 index == flush
  380.     } if
  381.  } bdef
  382.  
  383. % Read the next block of the initial text portion.
  384. /type1read1 {        % <left> type1read1 <string> <left'>
  385.   DEBUG { (read1 ) print } if
  386.   dup 0 eq {
  387.     pop sectionstr 0 1 put
  388.     stream /Length2 oget
  389.             % Determine whether to hexify data for eexec.
  390.     dup 8 lt {
  391.       type1read2    % Hexify.
  392.     } {
  393.       DEBUG { (read2 ) print } if
  394.       buffer2 type1readdata exch
  395.             % The check doesn't have to be 100% accurate:
  396.             % hexifying is always OK.
  397.       dup 0 8 getinterval 0 exch { or } forall
  398.       128 ge {
  399.     /hexify { } store
  400.     /buffer2 buffer def    % We don't need an intermediate buffer.
  401.       } if hexify exch
  402.     } ifelse
  403.   } {
  404.     buffer type1readdata
  405.   } ifelse
  406. } bdef
  407.  
  408. % Convert a string from binary to hex for eexec.
  409. % Free variables: buffer.
  410. /buf2hex {        % <string> buf2hex <hexstring>
  411.   buffer /ASCIIHexEncode filter dup 3 -1 roll writestring closefile
  412.   buffer (>) search pop exch pop exch pop
  413. } bdef
  414.  
  415. % Read the next block of the encrypted portion.
  416. /type1trailer
  417. (0000000000000000000000000000000000000000000000000000000000000000\n\
  418. 0000000000000000000000000000000000000000000000000000000000000000\n\
  419. 0000000000000000000000000000000000000000000000000000000000000000\n\
  420. 0000000000000000000000000000000000000000000000000000000000000000\n\
  421. 0000000000000000000000000000000000000000000000000000000000000000\n\
  422. 0000000000000000000000000000000000000000000000000000000000000000\n\
  423. 0000000000000000000000000000000000000000000000000000000000000000\n\
  424. 0000000000000000000000000000000000000000000000000000000000000000\n\
  425. cleartomark\n)
  426. readonly def
  427. /type1read2 {        % <left> type1read2 <string> <left'>
  428.   DEBUG { (read2 ) print } if
  429.    dup 0 eq
  430.     { pop sectionstr 0 2 put
  431.       stream /Length3 oget
  432.       dup 0 eq
  433.        { DEBUG { (trailer ) print } if
  434.      type1trailer exch
  435.        }
  436.        { type1read3
  437.        }
  438.       ifelse
  439.     }
  440.     { buffer2 type1readdata exch hexify exch
  441.     }
  442.    ifelse
  443. } bdef
  444.  
  445. % Read the next block of the final text portion.
  446. % When finished, this procedure returns an empty string.
  447. /type1read3        % <left> type1read3 <string> <left'>
  448.  { DEBUG { (read3 ) print } if
  449.    buffer type1readdata
  450.  } bdef
  451.  
  452. % ---------------- Type 3 fonts ---------------- %
  453.  
  454. /.notdefEncoding 256 { /.notdef } repeat 256 packedarray def
  455.  
  456. /buildType3 {        % <Type3-font-resource> buildType3 <font>
  457.   8 dict begin
  458.     /FontType 3 def
  459.     /Resources 1 index /Resources knownoget { oforce } { 0 dict } ifelse def
  460.     /FontBBox 1 index /FontBBox get cvx def
  461.     /FontMatrix 1 index /FontMatrix oget def
  462.     /CharProcs 1 index /CharProcs oget def
  463.     1 index /Widths knownoget {
  464.       /Widths exch def
  465.       /FirstChar 1 index /FirstChar oget def
  466.       /LastChar 1 index /LastChar oget def
  467.     } if
  468.     /FontName 1 index /Name get genfontname def
  469.     /Encoding .notdefEncoding 2 index getencoding def
  470.         % We have to define BuildChar rather than BuildGlyph:
  471.         % there is no PDF equivalent of glyphshow, and we need
  472.         % the character code to access the Widths.
  473.     /BuildChar {
  474.         % Stack: font charcode
  475.       1 index begin 3 dict begin
  476.       /Font 3 -1 roll def /CharCode 1 index def
  477.       Encoding exch get CharProcs exch oget
  478.       PDFfile fileposition exch
  479.       false resolvestream
  480.         % Stack: filepos stream
  481.         % Don't let setgcolor set the color inside the BuildGlyph
  482.         % procedure, because this causes an /undefined error.
  483.       q null /FillColor gput null /StrokeColor gput
  484.       Font /Resources get exch pdfopdict .pdfruncontext
  485.       Q
  486.       PDFfile exch setfileposition
  487.       end end
  488.     } bdef
  489.     FontName currentdict end definefont exch pop
  490. } bdef
  491. /.adjustcharwidth {    % <wx> <wy> .adjustcharwidth <wx'> <wy'>
  492.   /Widths where {
  493.     begin
  494.     CharCode FirstChar ge CharCode LastChar le and {
  495.       exch pop Widths CharCode FirstChar sub get exch
  496.     } if end
  497.   } if
  498. } bdef
  499.  
  500. % ---------------- TrueType fonts ---------------- %
  501.  
  502. /TTfonts mark
  503.   /Arial /Helvetica
  504.   /Arial,Italic /Helvetica-Oblique
  505.   /Arial,Bold /Helvetica-Bold
  506.   /Arial,BoldItalic /Helvetica-BoldOblique
  507.   /CourierNew /Courier
  508.   /CourierNew,Bold /Courier-Bold
  509.   /TimesNewRoman /Times-Roman
  510.   /TimesNewRoman,Italic /Times-Italic
  511.   /TimesNewRoman,Bold /Times-Bold
  512.   /TimesNewRoman,BoldItalic /Times-BoldItalic
  513. .dicttomark readonly def
  514.  
  515. /buildTrueType {    % <TrueType-font-resource> buildTrueType <font>
  516.   dup /BaseFont get
  517.   dup TTfonts exch .knownget {
  518.     exch pop
  519.         % Hack required by the PDF specification: if the
  520.         % font resource has Subtype = /TrueType but the actual
  521.         % (installed) font is not a TrueType font, ignore the
  522.         % Encoding in the font resource.  However, all current
  523.         % versions of Acrobat Reader have the 14 base TrueType
  524.         % fonts built in, so this produces incorrect output for
  525.         % badly designed PDF files that specify these file names
  526.         % with /Subtype = /TrueType but no embedded definition.
  527.         % Compensate for this by removing the /Subtype key when
  528.         % looking up the font.
  529.     exch dup length dict copy dup /Subtype null put exch
  530.   } if pdffindfont
  531. } bdef
  532.  
  533. % Read an embedded TrueType font.
  534. /readtruetype {        % <font-resource> <stream-dict> readtruetype <font>
  535.         % This is much simpler than readtype1, because we don't
  536.         % have to deal with the tripartite .PFB format.
  537.   1 index exch
  538.   PDFfile fileposition 3 1 roll
  539.   true resolvestream readfontfilter
  540.         % Stack: filepos fontres stream
  541.   1 index /Subtype get /CIDFontType2 eq {
  542.     .loadttcidfont
  543.   } {
  544.     null 2 index getencoding .loadpdfttfont
  545.   } ifelse
  546.   exch pop
  547.   PDFfile 3 -1 roll setfileposition
  548.         % Ignore both the Encoding and the Widths.
  549.   exch pop
  550. } bdef
  551.  
  552. % ---------------- Type 0 fonts ---------------- %
  553.  
  554. % Predefine the known CMaps, but only create them on demand.
  555. /knownCMaps mark
  556.   /Identity-H { /Identity-H 0 makeIdentityCMap }
  557.   /Identity-V { /Identity-V 1 makeIdentityCMap }
  558. .dicttomark def
  559.  
  560. /makeIdentityCMap {        % <cmapname> <wmode> .makeIdentityCMap -
  561.   .currentglobal true .setglobal 3 1 roll
  562.   /CIDInit /ProcSet findresource begin
  563.   12 dict begin
  564.     begincmap
  565.     /WMode exch def
  566.     /CMapName exch def
  567.     /CIDSystemInfo 3 dict dup begin
  568.       /Registry (Adobe) def
  569.       /Ordering (Japan1) def
  570.       /Supplement 0 def
  571.     end def
  572.     %/CMapName (see above)
  573.     /CMapVersion 1 def
  574.     /CMapType 1 def
  575.     %WMode (see above)
  576.     % The PDF documentation says that these CMaps map CIDs
  577.     % "1 to 65,536".  This is a misprint for 0 to 65,535.
  578.     1 begincodespacerange
  579.     % <0001> <00ff>  <0100> <ffff>
  580.       <0000> <ffff>
  581.     endcodespacerange
  582.     1 begincidrange
  583.     % <0001> <00ff> 1   <0100> <ffff> 256
  584.       <0000> <ffff> 0
  585.     endcidrange
  586.     endcmap
  587.     CMapName currentdict /CMap defineresource
  588.     knownCMaps CMapName 2 index put
  589.   end        % CMap
  590.   end        % CIDInit ProcSet
  591.   exch .setglobal
  592. } bdef
  593.  
  594. /buildType0 {        % <Type0-font-resource> buildType0 <font>
  595.   dup /BaseFont get    % FontName
  596.   1 index /Encoding oget
  597.   dup type /nametype eq {
  598.     dup /CMap resourcestatus {
  599.     pop pop /CMap findresource
  600.     } {
  601.     knownCMaps 1 index .knownget
  602.       { exch pop exec } { /undefined signalerror } ifelse
  603.     } ifelse
  604.   } {
  605.     resolvestream
  606.   } ifelse        % CMap
  607.   [
  608.     3 index /DescendantFonts oget { exec resourcefont } forall
  609.   ]            % subfonts
  610.   composefont
  611.         % Stack: fontres font
  612.   1 index /FontMatrix knownoget {
  613.     dup aload pop true {0 0 1 0 0 1} {3 -1 roll eq and} forall {
  614.       1 index exch makefont exch /FontName get exch definefont
  615.     } {
  616.       pop
  617.     } ifelse
  618.   } if exch pop
  619. } bdef
  620.  
  621. % ---------------- CIDFontType0/2 fonts ---------------- %
  622.  
  623. % Insert metrics into a CIDFont, by saving the PDF W, W2, DW, and DW2
  624. % arrays and using a (currently very inefficient) CDevProc.
  625. /addCIDmetrics {    % <CIDFont-resource> <CIDFont> addCIDmetrics <fontdict>
  626.   dup length 5 add dict .copydict
  627.   dup /FID undef
  628.   dup /UniqueID undef
  629.   dup /XUID undef
  630.     % Insert the widths into the font.
  631.   {W W2 DW DW2} {
  632.     % Stack: pdfresource newfont key
  633.     2 index 1 index .knownget {
  634.       2 index 3 1 roll put
  635.     } {
  636.       pop
  637.     } ifelse
  638.   } forall
  639.   dup /CDevProc 1 index /CIDWProc load /exec load 3 packedarray cvx put
  640.   exch pop
  641. } bdef
  642.  
  643. % Apply the [D]W[2] metrics to a character before displaying.
  644. /CIDWProc {        % <w0x> <w0y> <llx> <lly> <urx> <ury>
  645.             %   <w1x> <w1y> <vx> <vy> <cid> <font> CIDWproc
  646.             %   <w0x'> ... <vy'>
  647.   begin
  648.     % Look up and apply [D]W
  649.   10 index
  650.   currentdict /DW .knownget { 1000 div exch pop } if
  651.   currentdict /W .knownget {
  652.     % Search the W array for the CID.
  653.     % ****** NOT IMPLEMENTED YET ******
  654.     pop
  655.   } if
  656.   0 13 2 roll 11 -2 roll pop pop
  657.     % Look up and apply [D]W2
  658.     % ****** NOT IMPLEMENTED YET ******
  659.   pop end
  660. } bdef
  661.  
  662. /buildCIDType0 {    % <CIDFontType0-font-resource> buildCIDType0 <font>
  663.   dup /BaseFont get /CIDFont findresource
  664.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  665. } bdef
  666.  
  667. /buildCIDType2 {    % <CIDFontType2-font-resource> buildCIDType2 <font>
  668.   dup /BaseFont get /CIDFont findresource
  669.   addCIDmetrics
  670.     %****** Handle CIDToGIDMap ******
  671.   dup /BaseFont get exch /CIDFont defineresource
  672. } bdef
  673.  
  674. % ---------------- Other embedded fonts ---------------- %
  675.  
  676. /fontloadprocs mark
  677.   /Type1C /readType1C cvx
  678.   /CIDFontType0C /readCIDFontType0C cvx
  679. .dicttomark readonly def
  680.  
  681. % Read an embedded compressed font.
  682. /readType1C {        % <font-resource> <stream-dict> readType1C <font>
  683.   1 index exch
  684.   PDFfile fileposition 3 1 roll
  685.   dup true resolvestream dup readfontfilter
  686.         % Stack: pos resource streamdict stream filter
  687.   3 index /FontDescriptor oget /FontName oget
  688.   1 index FRD
  689.   closefile closefile pop
  690.   PDFfile 3 -1 roll setfileposition
  691.   /FontDescriptor oget /FontName oget findfont
  692.   adjustfont
  693. } bdef
  694.  
  695. % Read an embedded CFF CIDFont.
  696. /readCIDFontType0C {  % <font-resource> <stream-dict> readCIDFontType0C <font>
  697.   PDFfile fileposition 3 1 roll
  698.   dup true resolvestream dup readfontfilter
  699.         % Stack: pos resource streamdict stream filter
  700.   3 index /FontDescriptor oget /FontName oget
  701.   1 index FRD
  702.   closefile closefile pop
  703.   PDFfile 3 -1 roll setfileposition
  704.         % Some broken Adobe software produces PDF files in which
  705.         % the FontName of the CFF font and the FontName in the
  706.         % FontDescriptor don't match the BaseFont in the font.
  707.         % Use the FontName, rather than the BaseFont, here.
  708.   dup /FontDescriptor oget /FontName oget /CIDFont findresource
  709.   addCIDmetrics dup /CIDFontName get exch /CIDFont defineresource
  710. } bdef
  711.  
  712. % ---------------- Font lookup ---------------- %
  713.  
  714. /fonttypeprocs mark        % <font-resource> -proc- <font>
  715.   /Type0 /buildType0 cvx
  716.   /Type1 /buildType1 cvx
  717.   /MMType1 1 index
  718.   /Type3 /buildType3 cvx
  719.   /TrueType /buildTrueType cvx
  720.   /CIDFontType0 /buildCIDType0 cvx
  721.   /CIDFontType2 /buildCIDType2 cvx
  722. .dicttomark readonly def
  723.  
  724. /resourcefont            % <font-resource> resourcefont <font>
  725.  { dup /PSFont .knownget
  726.     { /FID .knownget { type /fonttype eq } { false } ifelse }
  727.     { false }
  728.    ifelse
  729.     { /PSFont get
  730.     }
  731.     { dup dup /FontDescriptor knownoget
  732.        {    % Stack: font-res font-res font-desc
  733.      dup /FontFile knownoget
  734.       { exch pop readtype1 true }
  735.       { dup /FontFile2 knownoget
  736.          { exch pop readtruetype true }
  737.          { /FontFile3 knownoget
  738.         { dup /Subtype get fontloadprocs exch get exec true }
  739.         { false }
  740.            ifelse
  741.          }
  742.         ifelse
  743.       }
  744.      ifelse
  745.        }
  746.        { false }
  747.       ifelse
  748.         % Stack: font-res font-res false
  749.         %  -or-: font-res font true
  750.       not
  751.        { dup /Subtype get fonttypeprocs exch get exec }
  752.       if
  753.       2 copy /PSFont exch put
  754.       exch pop
  755.     }
  756.    ifelse
  757.  } bdef
  758.  
  759. drawopdict begin
  760.   /d0 {
  761.     .adjustcharwidth setcharwidth
  762.   } bdef
  763.   /d1 {
  764.     6 -2 roll .adjustcharwidth 6 2 roll setcachedevice
  765.   } bdef
  766.   /Tf {
  767.     1 index Page /Font rget not { 1 index /invalidfont signalerror } if
  768.     resourcefont exch Tf pop
  769.   } bdef
  770. end
  771.  
  772. end            % pdfdict
  773. end            % GS_PDF_ProcSet
  774. .setglobal
  775.