% Copyright (C) 1990, 1995, 1996 Aladdin Enterprises. All rights reserved.% % This file is part of Aladdin Ghostscript.% % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author% or distributor accepts any responsibility for the consequences of using it,% or for whether it serves any particular purpose or works at all, unless he% or she says so in writing. Refer to the Aladdin Ghostscript Free Public% License (the "License") for full details.% % Every copy of Aladdin Ghostscript must include a copy of the License,% normally in a plain ASCII text file named PUBLIC. The License grants you% the right to copy, modify and redistribute Aladdin Ghostscript, but only% under certain conditions described in the License. Among other things, the% License requires that the copyright notice and this notice be preserved on% all copies. % $Id: bdftops.ps,v 1.1 2000/03/09 08:40:39 lpd Exp $% bdftops.ps% Convert a BDF file (possibly with (an) associated AFM file(s))% to a PostScript Type 1 font (without eexec encryption).% The resulting font will work with any PostScript language interpreter,% but not with ATM or other font rasterizers lacking a complete interpreter. /envBDF 120 dict defenvBDF begin % "Import" the image-to-path package.% This also brings in the Type 1 opcodes (type1ops.ps). (impath.ps) runlibfile % "Import" the font-writing package. (wrfont.ps) runlibfile wrfont_dict begin /binary_CharStrings false def /binary_tokens false def /encrypt_CharStrings true def /standard_only true def end /lenIV 0 def % Invert the StandardEncoding vector. 256 dict dup begin 0 1 255 { dup StandardEncoding exch get exch def } for end /StandardDecoding exch def % Define the properties copied to FontInfo. mark (COPYRIGHT) /Notice (FAMILY_NAME) /FamilyName (FULL_NAME) /FullName (WEIGHT_NAME) /Weight .dicttomark /properties exch def % Define the character sequences for synthesizing missing composite% characters in the standard encoding. mark /AE [/A /E] /OE [/O /E] /ae [/a /e] /ellipsis [/period /period /period] /emdash [/hyphen /hyphen /hyphen] /endash [/hyphen /hyphen] /fi [/f /i] /fl [/f /l] /germandbls [/s /s] /guillemotleft [/less /less] /guillemotright [/greater /greater] /oe [/o /e] /quotedblbase [/comma /comma] .dicttomark /composites exch def % Define the procedure for synthesizing composites.% This must not be bound. /compose { exch pop FontMatrix Private /composematrix get invertmatrix concat 0 0 moveto dup gsave false charpath pathbbox currentpoint grestore 6 2 roll setcachedevice show } def% Define the CharString procedure that calls compose, with the string% on the stack. This too must remain unbound. /compose_proc { Private /compose get exec } def % Define aliases for missing characters similarly. mark /acute /quoteright /bullet /asterisk /cedilla /comma /circumflex /asciicircum /dieresis /quotedbl /dotlessi /i /exclamdown /exclam /florin /f /fraction /slash /grave /quoteleft /guilsinglleft /less /guilsinglright /greater /hungarumlaut /quotedbl /periodcentered /asterisk /questiondown /question /quotedblleft /quotedbl /quotedblright /quotedbl /quotesinglbase /comma /quotesingle /quoteright /tilde /asciitilde .dicttomark /aliases exch def % Define overstruck characters that can be synthesized with seac. mark [ /Aacute /Acircumflex /Adieresis /Agrave /Aring /Atilde /Ccedilla /Eacute /Ecircumflex /Edieresis /Egrave /Iacute /Icircumflex /Idieresis /Igrave /Lslash /Ntilde /Oacute /Ocircumflex /Odieresis /Ograve /Otilde /Scaron /Uacute /Ucircumflex /Udieresis /Ugrave /Yacute /Ydieresis /Zcaron /aacute /acircumflex /adieresis /agrave /aring /atilde /ccedilla /eacute /ecircumflex /edieresis /egrave /iacute /icircumflex /idieresis /igrave /lslash /ntilde /oacute /ocircumflex /odieresis /ograve /otilde /scaron /uacute /ucircumflex /udieresis /ugrave /yacute /ydieresis /zcaron ] { dup =string cvs [ exch dup 0 1 getinterval cvn exch dup length 1 sub 1 exch getinterval cvn ] } forall /cent [/c /slash] /daggerdbl [/bar /equal] /divide [/colon /hyphen] /sterling [/L /hyphen] /yen [/Y /equal] .dicttomark /accentedchars exch def % ------ Output utilities ------ % /ws {psfile exch writestring} bind def /wl {ws (\n) ws} bind def /wt {=string cvs ws ( ) ws} bind def % ------ BDF file parsing utilities ------ % % Define a buffer for reading the BDF file. /buffer 400 string def % Read a line from the BDF file into the buffer.% Ignore empty (zero-length) lines.% Define /keyword as the first word on the line.% Define /args as the remainder of the line.% If the keyword is equal to commentword, skip the line.% (If commentword is equal to a space, never skip.) /nextline { { bdfile buffer readline not { (Premature EOF\n) print stop } if dup length 0 ne { exit } if pop } loop ( ) search { /keyword exch def pop } { /keyword exch def () } ifelse /args exch def keyword commentword eq { nextline } if } bind def % Get a word argument from args. We do *not* copy the string. /warg % warg -> string { args ( ) search { exch pop exch } { () } ifelse /args exch def } bind def % Get an integer argument from args. /iarg % iarg -> int { warg cvi } bind def % Get a numeric argument from args. /narg % narg -> int|real { warg cvr dup dup cvi eq { cvi } if } bind def % Convert the remainder of args into a string. /remarg % remarg -> string { args copystring } bind def % Get a string argument that occupies the remainder of args. /sarg % sarg -> string { args (") anchorsearch { pop /args exch def } { pop } ifelse args args length 1 sub get (") 0 get eq { args 0 args length 1 sub getinterval /args exch def } if args copystring } bind def % Check that the keyword is the expected one. /checkline % (EXPECTED-KEYWORD) checkline -> { dup keyword ne { (Expected ) print = (Line=) print keyword print ( ) print args print (\n) print stop } if pop } bind def % Read a line and check its keyword. /getline % (EXPECTED-KEYWORD) getline -> { nextline checkline } bind def % Find the first/last non-zero bit of a non-zero byte. /fnzb { 0 { exch dup 128 ge { pop exit } { dup add exch 1 add } ifelse } loop } bind def /lnzb { 7 { exch dup 1 and 0 ne { pop exit } { -1 bitshift exch 1 sub } ifelse } loop } bind def % ------ Type 1 encoding utilities ------ % % Parse the side bearing and width information that begins a CharString.% Arguments: charstring. Result: sbx sby wx wy substring. /parsesbw { mark exch lenIV { % stack: mark ... string dropcount dup 2 index length exch sub getinterval dup 0 get dup 32 lt { pop exit } if dup 246 le { 139 sub exch 1 } { dup 250 le { 247 sub 8 bitshift 108 add 1 index 1 get add exch 2 } { dup 254 le { 251 sub 8 bitshift 108 add 1 index 1 get add neg exch 2 } { pop dup 1 get 128 xor 128 sub 8 bitshift 1 index 2 get add 8 bitshift 1 index 3 get add 8 bitshift 1 index 4 get add exch 5 } ifelse } ifelse } ifelse } loop counttomark 3 eq { 0 3 1 roll 0 exch } if 6 -1 roll pop } bind def % Find the side bearing and width information that begins a CharString.% Arguments: charstring. Result: charstring sizethroughsbw. /findsbw { dup parsesbw 4 { exch pop } repeat skipsbw } bind def /skipsbw % charstring sbwprefix -> sizethroughsbw { length 1 index length exch sub 2 copy get 12 eq { 2 } { 1 } ifelse add } bind def % Encode a number, and append it to a string.% Arguments: str num. Result: newstr. /concatnum { dup dup -107 ge exch 107 le and { 139 add 1 string dup 0 3 index put } { dup dup -1131 ge exch 1131 le and { dup 0 ge { 16#f694 } { neg 16#fa94 } ifelse add 2 string dup 0 3 index -8 bitshift put dup 1 3 index 255 and put } { 5 string dup 0 255 put exch 2 copy 1 exch -24 bitshift 255 and put 2 copy 2 exch -16 bitshift 255 and put 2 copy 3 exch -8 bitshift 255 and put 2 copy 4 exch 255 and put exch } ifelse } ifelse exch pop concatstrings } bind def % ------ Point arithmetic utilities ------ % /ptadd { exch 4 -1 roll add 3 1 roll add } bind def /ptexch { 4 2 roll } bind def /ptneg { neg exch neg exch } bind def /ptpop { pop pop } bind def /ptsub { ptneg ptadd } bind def % ------ The main program ------ % /readBDF % <infilename> <outfilename> <fontname> % <encodingname> <uniqueID> <xuid> readBDF -> <font> { /xuid exch def % may be null /uniqueID exch def % may be -1 /encodingname exch def /encoding encodingname cvx exec def /fontname exch def /psname exch def /bdfname exch def gsave % so we can set the CTM to the font matrix % Open the input files. We don't open the output file until% we've done a minimal validity check on the input. bdfname (r) file /bdfile exch def /commentword ( ) def % Check for the STARTFONT. (STARTFONT) getline args (2.1) ne { (Not version 2.1\n) print stop } if % Initialize the font. /Font 20 dict def Font begin /FontName fontname def /PaintType 0 def /FontType 1 def uniqueID 0 gt { /UniqueID uniqueID def } if xuid null ne { /XUID xuid def } if /Encoding encoding def /FontInfo 20 dict def /Private 20 dict def currentdict end currentdict end exch begin begin % insert font above environment % Initialize the Private dictionary in the font. Private begin /-! {string currentfile exch readhexstring pop} readonly def /-| {string currentfile exch readstring pop} readonly def /|- {readonly def} readonly def /| {readonly put} readonly def /BlueValues [] def /lenIV lenIV def /MinFeature {16 16} def /password 5839 def /UniqueID uniqueID def end % Private % Invert the Encoding, for synthesizing composite characters. /decoding encoding length dict def 0 1 encoding length 1 sub { dup encoding exch get exch decoding 3 1 roll put } for % Now open the output file. psname (w) file /psfile exch def % Put out a header compatible with the Adobe "standard". (%!FontType1-1.0: ) ws fontname wt (000.000) wl (% This is a font description converted from ) ws bdfname wl (% by bdftops running on ) ws statusdict /product get ws ( revision ) ws revision =string cvs ws (.) wl % Copy the initial comments, up to FONT. true { nextline keyword (COMMENT) ne {exit} if { (% Here are the initial comments from the BDF file:\n%) wl } if false (%) ws remarg wl } loop pop () wl /commentword (COMMENT) def % do skip comments from now on % Read and process the FONT, SIZE, and FONTBOUNDINGBOX. % If we cared about FONT, we'd use it here. If the BDF files % from MIT had PostScript names rather than X names, we would % care; but what's there is unusable, so we discard FONT. % The FONTBOUNDINGBOX may not be reliable, so we discard it too. (FONT) checkline (SIZE) getline /pointsize iarg def /xres iarg def /yres iarg def (FONTBOUNDINGBOX) getline nextline % Initialize the font bounding box bookeeping. /fbbxo 1000 def /fbbyo 1000 def /fbbxe -1000 def /fbbye -1000 def % Read and process the properties. We only care about a few of them. keyword (STARTPROPERTIES) eq { iarg { nextline properties keyword known { FontInfo properties keyword get sarg readonly put } if } repeat (ENDPROPERTIES) getline nextline } if % Compute and set the FontMatrix. Font /FontMatrix [ 0.001 0 0 0.001 xres mul yres div 0 0 ] readonly dup setmatrix put % Read and process the header for the bitmaps. (CHARS) checkline /ccount iarg def % Initialize the CharStrings dictionary. /charstrings ccount composites length add aliases length add accentedchars length add 1 add dict def % 1 add for .notdef /isfixedwidth true def /fixedwidth null def /subrcount 0 def /subrs [] def % Read the bitmap data. This reads the remainder of the file.% We do this before processing the bitmaps so that we can compute% the correct FontBBox first. /chardata ccount dict def ccount -1 1 { (STARTCHAR) getline /charname remarg def (ENCODING) getline /eindex iarg def eindex 0 ge { charname /charname StandardEncoding eindex get def charname /.notdef eq eindex 0 gt and { /charname (A) eindex =string cvs concatstrings cvn def } if (/) print charname =string cvs print (,) print print } { (/) print charname print } ifelse 10 mod 1 eq { (\n) print flush } if (SWIDTH) getline /swx iarg pointsize mul 1000 div xres mul 72 div def /swy iarg pointsize mul 1000 div xres mul 72 div def (DWIDTH) getline % Ignore, use SWIDTH instead (BBX) getline /bbw iarg def /bbh iarg def /bbox iarg def /bboy iarg def nextline keyword (ATTRIBUTES) eq { nextline } if (BITMAP) checkline % Update the font bounding box. /fbbxo fbbxo bbox min def /fbbyo fbbyo bboy min def /fbbxe fbbxe bbox bbw add max def /fbbye fbbye bboy bbh add max def % Read the bits for this character. /raster bbw 7 add 8 idiv def /cbits raster bbh mul string def 0 raster cbits length raster sub { cbits exch raster getinterval bdfile buffer readline not { (EOF in bitmap\n) print stop } if % stack has <cbits.interval> <buffer.interval> 0 () /SubFileDecode filter exch 2 copy readhexstring pop pop pop closefile } for (ENDCHAR) getline % Save the character data. chardata charname [swx swy bbw bbh bbox bboy cbits] put } for (ENDFONT) getline % Allocate the buffers for the bitmap and the outline,% according to the font bounding box. /fbbw fbbxe fbbxo sub def /fbbh fbbye fbbyo sub def /fraster fbbw 7 add 8 idiv def /bits fraster fbbh mul 200 max 65535 min string def /outline bits length 6 mul 65535 min string def % Process the characters. chardata { exch /charname exch def aload pop /cbits exch def /bboy exch def /bbox exch defLines 1–500 of 794. Load more
% Copyright (C) 1990, 1995, 1996 Aladdin Enterprises. All rights reserved. % % This file is part of Aladdin Ghostscript. % % Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND. No author % or distributor accepts any responsibility for the consequences of using it, % or for whether it serves any particular purpose or works at all, unless he % or she says so in writing. Refer to the Aladdin Ghostscript Free Public % License (the "License") for full details. % % Every copy of Aladdin Ghostscript must include a copy of the License, % normally in a plain ASCII text file named PUBLIC. The License grants you % the right to copy, modify and redistribute Aladdin Ghostscript, but only % under certain conditions described in the License. Among other things, the % License requires that the copyright notice and this notice be preserved on % all copies. % $Id: bdftops.ps,v 1.1 2000/03/09 08:40:39 lpd Exp $ % bdftops.ps % Convert a BDF file (possibly with (an) associated AFM file(s)) % to a PostScript Type 1 font (without eexec encryption). % The resulting font will work with any PostScript language interpreter, % but not with ATM or other font rasterizers lacking a complete interpreter. /envBDF 120 dict def envBDF begin % "Import" the image-to-path package. % This also brings in the Type 1 opcodes (type1ops.ps). (impath.ps) runlibfile % "Import" the font-writing package. (wrfont.ps) runlibfile wrfont_dict begin /binary_CharStrings false def /binary_tokens false def /encrypt_CharStrings true def /standard_only true def end /lenIV 0 def % Invert the StandardEncoding vector. 256 dict dup begin 0 1 255 { dup StandardEncoding exch get exch def } for end /StandardDecoding exch def % Define the properties copied to FontInfo. mark (COPYRIGHT) /Notice (FAMILY_NAME) /FamilyName (FULL_NAME) /FullName (WEIGHT_NAME) /Weight .dicttomark /properties exch def % Define the character sequences for synthesizing missing composite % characters in the standard encoding. mark /AE [/A /E] /OE [/O /E] /ae [/a /e] /ellipsis [/period /period /period] /emdash [/hyphen /hyphen /hyphen] /endash [/hyphen /hyphen] /fi [/f /i] /fl [/f /l] /germandbls [/s /s] /guillemotleft [/less /less] /guillemotright [/greater /greater] /oe [/o /e] /quotedblbase [/comma /comma] .dicttomark /composites exch def % Define the procedure for synthesizing composites. % This must not be bound. /compose { exch pop FontMatrix Private /composematrix get invertmatrix concat 0 0 moveto dup gsave false charpath pathbbox currentpoint grestore 6 2 roll setcachedevice show } def % Define the CharString procedure that calls compose, with the string % on the stack. This too must remain unbound. /compose_proc { Private /compose get exec } def % Define aliases for missing characters similarly. mark /acute /quoteright /bullet /asterisk /cedilla /comma /circumflex /asciicircum /dieresis /quotedbl /dotlessi /i /exclamdown /exclam /florin /f /fraction /slash /grave /quoteleft /guilsinglleft /less /guilsinglright /greater /hungarumlaut /quotedbl /periodcentered /asterisk /questiondown /question /quotedblleft /quotedbl /quotedblright /quotedbl /quotesinglbase /comma /quotesingle /quoteright /tilde /asciitilde .dicttomark /aliases exch def % Define overstruck characters that can be synthesized with seac. mark [ /Aacute /Acircumflex /Adieresis /Agrave /Aring /Atilde /Ccedilla /Eacute /Ecircumflex /Edieresis /Egrave /Iacute /Icircumflex /Idieresis /Igrave /Lslash /Ntilde /Oacute /Ocircumflex /Odieresis /Ograve /Otilde /Scaron /Uacute /Ucircumflex /Udieresis /Ugrave /Yacute /Ydieresis /Zcaron /aacute /acircumflex /adieresis /agrave /aring /atilde /ccedilla /eacute /ecircumflex /edieresis /egrave /iacute /icircumflex /idieresis /igrave /lslash /ntilde /oacute /ocircumflex /odieresis /ograve /otilde /scaron /uacute /ucircumflex /udieresis /ugrave /yacute /ydieresis /zcaron ] { dup =string cvs [ exch dup 0 1 getinterval cvn exch dup length 1 sub 1 exch getinterval cvn ] } forall /cent [/c /slash] /daggerdbl [/bar /equal] /divide [/colon /hyphen] /sterling [/L /hyphen] /yen [/Y /equal] .dicttomark /accentedchars exch def % ------ Output utilities ------ % /ws {psfile exch writestring} bind def /wl {ws (\n) ws} bind def /wt {=string cvs ws ( ) ws} bind def % ------ BDF file parsing utilities ------ % % Define a buffer for reading the BDF file. /buffer 400 string def % Read a line from the BDF file into the buffer. % Ignore empty (zero-length) lines. % Define /keyword as the first word on the line. % Define /args as the remainder of the line. % If the keyword is equal to commentword, skip the line. % (If commentword is equal to a space, never skip.) /nextline { { bdfile buffer readline not { (Premature EOF\n) print stop } if dup length 0 ne { exit } if pop } loop ( ) search { /keyword exch def pop } { /keyword exch def () } ifelse /args exch def keyword commentword eq { nextline } if } bind def % Get a word argument from args. We do *not* copy the string. /warg % warg -> string { args ( ) search { exch pop exch } { () } ifelse /args exch def } bind def % Get an integer argument from args. /iarg % iarg -> int { warg cvi } bind def % Get a numeric argument from args. /narg % narg -> int|real { warg cvr dup dup cvi eq { cvi } if } bind def % Convert the remainder of args into a string. /remarg % remarg -> string { args copystring } bind def % Get a string argument that occupies the remainder of args. /sarg % sarg -> string { args (") anchorsearch { pop /args exch def } { pop } ifelse args args length 1 sub get (") 0 get eq { args 0 args length 1 sub getinterval /args exch def } if args copystring } bind def % Check that the keyword is the expected one. /checkline % (EXPECTED-KEYWORD) checkline -> { dup keyword ne { (Expected ) print = (Line=) print keyword print ( ) print args print (\n) print stop } if pop } bind def % Read a line and check its keyword. /getline % (EXPECTED-KEYWORD) getline -> { nextline checkline } bind def % Find the first/last non-zero bit of a non-zero byte. /fnzb { 0 { exch dup 128 ge { pop exit } { dup add exch 1 add } ifelse } loop } bind def /lnzb { 7 { exch dup 1 and 0 ne { pop exit } { -1 bitshift exch 1 sub } ifelse } loop } bind def % ------ Type 1 encoding utilities ------ % % Parse the side bearing and width information that begins a CharString. % Arguments: charstring. Result: sbx sby wx wy substring. /parsesbw { mark exch lenIV { % stack: mark ... string dropcount dup 2 index length exch sub getinterval dup 0 get dup 32 lt { pop exit } if dup 246 le { 139 sub exch 1 } { dup 250 le { 247 sub 8 bitshift 108 add 1 index 1 get add exch 2 } { dup 254 le { 251 sub 8 bitshift 108 add 1 index 1 get add neg exch 2 } { pop dup 1 get 128 xor 128 sub 8 bitshift 1 index 2 get add 8 bitshift 1 index 3 get add 8 bitshift 1 index 4 get add exch 5 } ifelse } ifelse } ifelse } loop counttomark 3 eq { 0 3 1 roll 0 exch } if 6 -1 roll pop } bind def % Find the side bearing and width information that begins a CharString. % Arguments: charstring. Result: charstring sizethroughsbw. /findsbw { dup parsesbw 4 { exch pop } repeat skipsbw } bind def /skipsbw % charstring sbwprefix -> sizethroughsbw { length 1 index length exch sub 2 copy get 12 eq { 2 } { 1 } ifelse add } bind def % Encode a number, and append it to a string. % Arguments: str num. Result: newstr. /concatnum { dup dup -107 ge exch 107 le and { 139 add 1 string dup 0 3 index put } { dup dup -1131 ge exch 1131 le and { dup 0 ge { 16#f694 } { neg 16#fa94 } ifelse add 2 string dup 0 3 index -8 bitshift put dup 1 3 index 255 and put } { 5 string dup 0 255 put exch 2 copy 1 exch -24 bitshift 255 and put 2 copy 2 exch -16 bitshift 255 and put 2 copy 3 exch -8 bitshift 255 and put 2 copy 4 exch 255 and put exch } ifelse } ifelse exch pop concatstrings } bind def % ------ Point arithmetic utilities ------ % /ptadd { exch 4 -1 roll add 3 1 roll add } bind def /ptexch { 4 2 roll } bind def /ptneg { neg exch neg exch } bind def /ptpop { pop pop } bind def /ptsub { ptneg ptadd } bind def % ------ The main program ------ % /readBDF % <infilename> <outfilename> <fontname> % <encodingname> <uniqueID> <xuid> readBDF -> <font> { /xuid exch def % may be null /uniqueID exch def % may be -1 /encodingname exch def /encoding encodingname cvx exec def /fontname exch def /psname exch def /bdfname exch def gsave % so we can set the CTM to the font matrix % Open the input files. We don't open the output file until % we've done a minimal validity check on the input. bdfname (r) file /bdfile exch def /commentword ( ) def % Check for the STARTFONT. (STARTFONT) getline args (2.1) ne { (Not version 2.1\n) print stop } if % Initialize the font. /Font 20 dict def Font begin /FontName fontname def /PaintType 0 def /FontType 1 def uniqueID 0 gt { /UniqueID uniqueID def } if xuid null ne { /XUID xuid def } if /Encoding encoding def /FontInfo 20 dict def /Private 20 dict def currentdict end currentdict end exch begin begin % insert font above environment % Initialize the Private dictionary in the font. Private begin /-! {string currentfile exch readhexstring pop} readonly def /-| {string currentfile exch readstring pop} readonly def /|- {readonly def} readonly def /| {readonly put} readonly def /BlueValues [] def /lenIV lenIV def /MinFeature {16 16} def /password 5839 def /UniqueID uniqueID def end % Private % Invert the Encoding, for synthesizing composite characters. /decoding encoding length dict def 0 1 encoding length 1 sub { dup encoding exch get exch decoding 3 1 roll put } for % Now open the output file. psname (w) file /psfile exch def % Put out a header compatible with the Adobe "standard". (%!FontType1-1.0: ) ws fontname wt (000.000) wl (% This is a font description converted from ) ws bdfname wl (% by bdftops running on ) ws statusdict /product get ws ( revision ) ws revision =string cvs ws (.) wl % Copy the initial comments, up to FONT. true { nextline keyword (COMMENT) ne {exit} if { (% Here are the initial comments from the BDF file:\n%) wl } if false (%) ws remarg wl } loop pop () wl /commentword (COMMENT) def % do skip comments from now on % Read and process the FONT, SIZE, and FONTBOUNDINGBOX. % If we cared about FONT, we'd use it here. If the BDF files % from MIT had PostScript names rather than X names, we would % care; but what's there is unusable, so we discard FONT. % The FONTBOUNDINGBOX may not be reliable, so we discard it too. (FONT) checkline (SIZE) getline /pointsize iarg def /xres iarg def /yres iarg def (FONTBOUNDINGBOX) getline nextline % Initialize the font bounding box bookeeping. /fbbxo 1000 def /fbbyo 1000 def /fbbxe -1000 def /fbbye -1000 def % Read and process the properties. We only care about a few of them. keyword (STARTPROPERTIES) eq { iarg { nextline properties keyword known { FontInfo properties keyword get sarg readonly put } if } repeat (ENDPROPERTIES) getline nextline } if % Compute and set the FontMatrix. Font /FontMatrix [ 0.001 0 0 0.001 xres mul yres div 0 0 ] readonly dup setmatrix put % Read and process the header for the bitmaps. (CHARS) checkline /ccount iarg def % Initialize the CharStrings dictionary. /charstrings ccount composites length add aliases length add accentedchars length add 1 add dict def % 1 add for .notdef /isfixedwidth true def /fixedwidth null def /subrcount 0 def /subrs [] def % Read the bitmap data. This reads the remainder of the file. % We do this before processing the bitmaps so that we can compute % the correct FontBBox first. /chardata ccount dict def ccount -1 1 { (STARTCHAR) getline /charname remarg def (ENCODING) getline /eindex iarg def eindex 0 ge { charname /charname StandardEncoding eindex get def charname /.notdef eq eindex 0 gt and { /charname (A) eindex =string cvs concatstrings cvn def } if (/) print charname =string cvs print (,) print print } { (/) print charname print } ifelse 10 mod 1 eq { (\n) print flush } if (SWIDTH) getline /swx iarg pointsize mul 1000 div xres mul 72 div def /swy iarg pointsize mul 1000 div xres mul 72 div def (DWIDTH) getline % Ignore, use SWIDTH instead (BBX) getline /bbw iarg def /bbh iarg def /bbox iarg def /bboy iarg def nextline keyword (ATTRIBUTES) eq { nextline } if (BITMAP) checkline % Update the font bounding box. /fbbxo fbbxo bbox min def /fbbyo fbbyo bboy min def /fbbxe fbbxe bbox bbw add max def /fbbye fbbye bboy bbh add max def % Read the bits for this character. /raster bbw 7 add 8 idiv def /cbits raster bbh mul string def 0 raster cbits length raster sub { cbits exch raster getinterval bdfile buffer readline not { (EOF in bitmap\n) print stop } if % stack has <cbits.interval> <buffer.interval> 0 () /SubFileDecode filter exch 2 copy readhexstring pop pop pop closefile } for (ENDCHAR) getline % Save the character data. chardata charname [swx swy bbw bbh bbox bboy cbits] put } for (ENDFONT) getline % Allocate the buffers for the bitmap and the outline, % according to the font bounding box. /fbbw fbbxe fbbxo sub def /fbbh fbbye fbbyo sub def /fraster fbbw 7 add 8 idiv def /bits fraster fbbh mul 200 max 65535 min string def /outline bits length 6 mul 65535 min string def % Process the characters. chardata { exch /charname exch def aload pop /cbits exch def /bboy exch def /bbox exch def