%! % POSTSCRIPT PFB TO PFA FONT FILE CONVERTER % ========================================= % by Don Lancaster v1.3 7 Mar 97 % Copyright c. 1996 by Don Lancaster and Synergetics, Box 809, % Thatcher AZ, 85552 (520) 428-4073. synergetics@tinaja.com % All commercial rights and all electronic media rights *fully* % reserved. Linking welcome. Reposting is expressly forbidden. % Further support on www.tinaja.com % Consulting services available via don@tinaja.com % ==================================== % WARNING: Preliminary code. Use at your own risk. % Report all problems to don@tinaja.com % ==================================== % The PostScript general purpose computing language is ideal for % disk-based font and format coversions. This example takes PC-based % binary .PFB font files and converts them to hex-ascii .PFA files. % .PFA files are normally used for serial and other comm apps that % are not eight bit clean. .PFB files are normally used internally % and where a clean 8 bit comm channel is available. More details % on these file formats appear in Adobe Technical note #5040 on % Supporting Downloadable PostScript Language Fonts. % This utility may be used with GhostScript or with a PostScript % printer having an internal hard drive. But it is easiest to use % by routing it to Acrobat distiller 3.0 or higher. First view this % utility with an editor or word processor, changing the filenames % as needed. Distiller will then do the format conversion for you. % A .PFB file recognizes three different types of data blocks. Each % type has a six byte id and length header. Type I is ordinary ASCII % text, which is passed on as is. Type II is binary, which gets % converted to HEX-ASCII pairs of suitable line lenghts. Type III is % an optional end of file marker. % .PFA Files are written with carriage returns only. To convert to % cr-lf pairs on a PC, bring the .PFA file up in Netscape, copy it to % the clipboard, then paste it to Wordpad. Then resave. % Note that any existing .PFA file with target filename is deleted. % Note also that an "empty file" error is normal and expected. Because % distiller is being tricked into PostScript computing, rather than % generating a .PDF file. % defaults /pfbfilename (c:\\Windows\\Desktop\\fontpf~1\\Geb_____.PFB) def % source /pfafilename (c:\\Windows\\Desktop\\fontpf~1\\Geb_____.PFA) def % target /hexpairsperline 32 def % hex character pairs before a return /datatype 0 def % internal type marker /datalength 0 def % internal data length marker /reportheaders true def % report the headers for debug? % -readpbfheader- gets six characters and evaluates them. The first % should be $10. The second will be $01 for ASCII, $02 for binary, and % $03 for end of file. The remaining four bytes hold length info ... /readpfbheader { source (XXXXXX) readstring { /header exch store} % read six bytes { 0 reporterror exit} ifelse % report end of file reportheaders {(\r\n)print % optional debug report header {==} forall (\r\n) print} if header 0 get 128 ne {1 reporterror exit} if % verify 128 = first header 1 get dup dup 1 ge exch 3 le and % find data type {/datatype exch store} % and save {2 reporterror exit} ifelse % or complain header 5 get 256 mul % calculate segment size header 4 get 256 mul add header 3 get 256 mul add header 2 get cvi add /datalength exch store % and save datalength 1000000 gt {3 reporterror exit} if % sanity check reportheaders {(datalength is ) print % optionally report flush datalength == (\r\n) print} if [{}{processascii}{processbinary}{processeof}] % execute data block datatype get exec } def % /processascii just passes on ASCII text as is... /processascii {{datalength 4096 gt % break long segments {source 4096 string readstring % read 4096 chars pop target exch writestring % and rewrite /datalength datalength 4096 sub def} % shorten remaining segment {source datalength string readstring % read final segment chunk pop target exch % and rewrite writestring exit} ifelse } loop % continue till empty } def % /processbinary converts a segment to hex-ascii pairs. A carriage % return is added every hexpairsperline characters... /processbinary {{datalength hexpairsperline % break long segments gt {source hexpairsperline string readstring % read one line pop target exch writehexstring % write as hex target (\r) writestring % add cr /datalength datalength hexpairsperline % shorten remaining sub def} {source datalength string % read final segment chunk readstring pop target exch % write as hex writehexstring target (\r) writestring % add cr exit} ifelse } loop % continue till empty } def % /processeof is currently a null proc. Could be used to add a % system dependent [D] to the end of file... /processeof {} def % null for now % /reporterror handles certain file misreads. This can be further % expanded by replacing pop's above with ifelse loops... /reporterror { (\r\n) print % print cr to log file [ % list of reportable errors (Reached end of file.) (Error: First header byte invalid.) (Error: Unknown segment type.) (Error: Segment longer than one million characters.) ( )( ) ( ) ( ) ( ) ( ) ] exch get print % print reportable errors (\r\n) print flush } def % This is the actual conversion loop. It reads one .pfb header at a % time, converting binary to hex-ascii pairs when needed... /convertpfb2pfa { save /pfbsnap exch store mark % save state pfafilename status % erase old .pfa file {pop pop pop pop pfafilename deletefile} if pfbfilename (r) file /source exch store % open read file pfafilename (w) file /target exch store % open write file {readpfbheader} loop % service loop cleartomark pfbsnap restore % restore state } def %%%%%%%%%%%%%%%%%%% USE EXAMPLE %%%%%%%%%%%%%%%%%%%% % IMPORTANT: Enter "\\" any time you mean "\" in the filename!!! /pfbfilename (c:\\Windows\\Desktop\\fontpf~1\\Geb_____.PFB) def % source /pfafilename (c:\\Windows\\Desktop\\fontpf~1\\Geb_____.PFA) def % target /hexpairsperline 32 def % hex characters before a carriage return convertpfb2pfa % do conversion % quit % uncomment quit if distiller 3.0 not used.