⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pf2afm.ps

📁 GhostScript的源代码
💻 PS
字号:
%!
% This is a PostScript program for making an AFM file from
% PFB / PFA and (optionally) PFM files.
%
% Written in BOP s.c., Gda\'nsk, Poland
% e-mail contact: B.Jackowski@GUST.ORG.PL
% version 0.5 (18 XII 1997)

% Usage:
%   gs [-sDEVICE=nullpage] -- pf2afm.ps disk_font_name
%
% The result is written to the file disk_font_name.afm, provided such
% a file does not exist; otherwise program quits.
%
% The font can be either *.pfa or *.pfb; if no extension is supplied, first
% disk_font_name.pfb is examined, then disk_font_name.pfa. Moreover, if there
% is a *.pfm file in the same directory, i.e., disk_font_name.pfm, kern pairs
% from it are extracted, as well as additional font parameters,
% usually absent from Type 1 fonts.

% Tribute:
% The program is based on James Clark's <jjc@jclark.uucp> printafm.ps
% (with alterations by d.love@dl.ac.uk and L. Peter Deutsch) from
% Ghostscript 5.10 distribution.

/onechar 1 string def

% charnumber print-charname -
% prints the name of the encoded character
/print-charname {
  PFBencoding exch get =string cvs dup
  (.notdef) eq {
    /was.notdef true def
  } if
  print.to.ofi ( ) print.to.ofi
} def

/printquit {print flush quit} def

% redirecting GS output to ``ofi'' file
/eolch (\r\n) def
/=only.to.ofi {ofi exch write=only} def          % replaces GS's `=only'
/print.to.ofi  {ofi exch writestring} def        % replaces `print'
/=to.ofi { =only.to.ofi eolch print.to.ofi } def % replaces `='

% read and skip: byte, short, word, double and long
/readb-p {currPFMfile read not {(Unexpected EOF) printquit} if} def
/readw-p {readb-p readb-p 256 mul add} def
/reads-p {readw-p dup 32768 ge {65536 sub} if} def
/readd-p {readb-p readb-p readb-p readb-p 256 mul add 256 mul add 256 mul add} def
/readl-p /readd-p load def % double word is, in fact, long integer in GS
/skipb-p {readb-p pop} def
/skipw-p {skipb-p skipb-p} def
/skips-p /skipw-p load def
/skipd-p {skipb-p skipb-p skipb-p skipb-p} def
/skipl-p /skipd-p load def
/skipa-p { {skipb-p} repeat} def

% PFMfile readPFMheader -
% defines currPFMfile, PFMExtMetricOffset, PFMPairKernTableOffset

/readPFMheader {
  currPFMfile bytesavailable
  % ---------------
  % PFM MAIN HEADER
  % ---------------
  skipw-p % PFM: version
  readd-p % PFM: size (size is dword, not word as the documentation says)
  ne {(Wrong file size) printquit} if
  60 skipa-p  % PFM: copyright
  skipw-p % PFM: Type
  skipw-p % PFM: Points
  skipw-p % PFM: VertRes
  skipw-p % PFM: HorizRes
  skipw-p % PFM: Ascent
  skipw-p % PFM: InternalLeading
  skipw-p % PFM: ExternalLeading
  skipb-p % PFM: Italic
  skipb-p % PFM: Underline
  skipb-p % PFM: Stikeout
  skipw-p % PFM: Weight
  skipb-p % PFM: CharSet
  skipw-p % PFM: PixWidth
  skipw-p % PFM: PixHeight
  skipb-p % PFM: PitchAndFamily
  skipw-p % PFM: AvgWidth
  skipw-p % PFM: MaxWidth
  skipb-p % PFM: FirstChar
  skipb-p % PFM: LastChar
  skipb-p % PFM: DefaultChar
  skipb-p % PFM: BreakChar
  skipw-p % PFM: WidthBytes
  skipd-p % PFM: Device
  skipd-p % PFM: Face
  skipd-p % PFM: BitsPointer
  skipd-p % PFM: BitsOffset
  % here we assume that it is a PostScript font, i.e., it always uses
  % the extended width table, therefore the normal width table is empty
  % -------------
  % PFM EXTENSION
  % -------------
  skipw-p % PFMEX: SizeFields
  readd-p % PFMEX: ExtMetricOffset
    /PFMExtMetricOffset exch def
  skipd-p % PFMEX: ExtentTable
  skipd-p % PFMEX: OriginTable
  readd-p % PFMEX: PairKernTable
    /PFMPairKernTableOffset exch def
  skipd-p % PFMEX: TrackKernTable
  skipd-p % PFMEX: DriverInfo
  skipd-p % PFMEX: Reserved
} def

% requires that currPFMfile, PFMExtMetricOffset are defined
% readPFMExtMetric -
% defines PFMNumberofKernPairs

/readPFMExtMetric {
  currPFMfile PFMExtMetricOffset setfileposition
  skips-p % EXTT: Size
  skips-p % EXTT: PointSize
  skips-p % EXTT: Orientation
  skips-p % EXTT: MasterHeight
  skips-p % EXTT: MinScale
  skips-p % EXTT: MaxScale
  skips-p % EXTT: MasterUnit
  reads-p % EXTT: CapHeight
   /PFMCapHeight exch def
  reads-p % EXTT: XHeight
   /PFMXHeight exch def
  reads-p % EXTT: LowerCaseAscent
   /PFMLowerCaseAscent exch def
  reads-p % EXTT: LowerCaseDescent
   neg /PFMLowerCaseDescent exch def
  skips-p % EXTT: Slant
  skips-p % EXTT: SuperScript
  skips-p % EXTT: SubScript
  skips-p % EXTT: SuperScriptSize
  skips-p % EXTT: SubScriptSize
  skips-p % EXTT: UnderlineOffset
  skips-p % EXTT: UnderlineWidth
  skips-p % EXTT: DoubleUpperUnderlineOffset
  skips-p % EXTT: DoubleLowerUnderlineOffset
  skips-p % EXTT: DoubleUpperUnderlineWidth
  skips-p % EXTT: DoubleLowerUnderlineWidth
  skips-p % EXTT: StrikeOutOffset
  skips-p % EXTT: StrikeOutWidth
  readw-p % EXTT: KernPairs
    /PFMNumberofKernPairs exch def
  skipw-p % EXTT: KernTracks
} def

% requires that currPFMfile, PFMPairKernTableOffset, PFMNumberofKernPairs are defined
% readPFMExtMetric -
% prints kern pairs table in the AFM format

/readPFMKernPairs {
  currPFMfile () ne {
    PFMdict begin
    PFMPairKernTableOffset 0 ne {
      currPFMfile PFMPairKernTableOffset setfileposition
      readw-p % undocumented kern count (although all remaining structures are
              % explicitly preceded by their sizes); if it were a stable
             % feature, EXTTEXTMETRICS could be skipped
      PFMNumberofKernPairs
%     2 copy = =
      ne {
        (Inconsistent number of kern pairs) printquit
      } if
      (StartKernData) =to.ofi
      (StartKernPairs ) print.to.ofi
      PFMNumberofKernPairs =to.ofi
      % ---------
      % MAIN LOOP
      % ---------
      /was.notdef false def
      PFMNumberofKernPairs {
        (KPX ) print.to.ofi
        readb-p  % first  char
        print-charname
        readb-p  % second char
        print-charname
        reads-p  % kern amount
        =to.ofi
      } repeat
      was.notdef {
        (.notdef character ocurred among kern pairs) =
        (you'd better check the resulting AFM file.) =
      } if
      (EndKernPairs) =to.ofi
      (EndKernData)  =to.ofi
    } if
    end
  } if
} def

% alias (for ``compatibility'' with J. Clark):
/printkernpairs /readPFMKernPairs load def

% printcharmetrics -

/printcharmetrics {
  (StartCharMetrics ) print.to.ofi
  /PFBencoding currfont /Encoding get dup length array copy def
  /PFBcharstrings currfont /CharStrings get def
  PFBcharstrings length  
  PFBcharstrings /.notdef known { 1 sub } if =to.ofi
  currfont 1000 scalefont setfont
  % checking Encoding array and CharStrings dictionary for 
  % the consistency of names
  /was.inconsitent false def
  0 1 255 {
    dup PFBencoding exch get 
    PFBcharstrings exch known {
      pop 
    } {
%     dup PFBencoding exch get =
      PFBencoding exch /.notdef put % fix Encoding array
      /was.inconsitent true def
    } ifelse
  } for
  was.inconsitent {
    (Encoding array contains name(s) absent from CharStrings dictionary) =
  } if
  % print metric data for each character in PFB encoding vector
  0 1 255 {
    dup PFBencoding exch get
    dup /.notdef ne {
      exch dup printmetric
    } {
      pop pop
    } ifelse
  } for
  % xPFBencoding contains an entry for each name in the original
  % encoding vector
  /xPFBencoding 256 dict def
  PFBencoding {
    xPFBencoding exch true put
  } forall
  % NewPFBencoding is the new encoding vector
  /NewPFBencoding 256 array def
  0 1 255 {
    NewPFBencoding exch /.notdef put
  } for
  % fill up NewPFBencoding with names from CharStrings dictionary that 
  % are not used in the original PFBencoding (only up to 256 not encoded 
  % characters)
  /i 0 def
  PFBcharstrings {
    pop
    i 255 le {
      dup xPFBencoding exch known not {
        NewPFBencoding i 3 -1 roll put
        /i i 1 add def
      } {
        pop
      } ifelse
    } {
      pop
    } ifelse
  } forall
  % define a new font with NewPFBencoding as its encoding vector
  currfont maxlength dict /NewTMPfont exch def
  currfont {
    exch dup dup /FID ne exch /Encoding ne and {
      exch NewTMPfont 3 1 roll put
    } {
      pop pop
    } ifelse
  } forall
  NewTMPfont /Encoding NewPFBencoding put
  NewTMPfont /FontName /TMPFontName put
  % make this new font the current font
  /TMPFontName NewTMPfont definefont 1000 scalefont setfont
  % print metric data for each character in the newly created encoding vector
  0 1 255 {
    dup NewPFBencoding exch get
    dup /.notdef ne {
      exch -1 printmetric
    } {
      pop pop
    } ifelse
  } for
  (EndCharMetrics) =to.ofi
} def

% name actual_code normal_code printmetric -

/printmetric {
  (C ) print.to.ofi =only.to.ofi
  ( ; WX ) print.to.ofi
  onechar 0 3 -1 roll put
  onechar stringwidth pop round cvi =only.to.ofi
  ( ; N ) print.to.ofi =only.to.ofi
  ( ; B ) print.to.ofi
  newpath 0 0 moveto
  onechar false charpath flattenpath pathbbox
  newpath
  round cvi /ury exch def round cvi /urx exch def
  round cvi /lly exch def round cvi /llx exch def
  ury lly eq {/ury 0 def /lly 0 def} if % normalize degenrated BB
  urx llx eq {/urx 0 def /llx 0 def} if %
  llx =only.to.ofi ( ) print.to.ofi lly =only.to.ofi ( ) print.to.ofi
  urx =only.to.ofi ( ) print.to.ofi ury =only.to.ofi ( ) print.to.ofi
  (;) =to.ofi
} def

/printinfoitem {
  3 1 roll 2 copy known {
    get =string cvs exch
    print.to.ofi ( ) print.to.ofi =to.ofi
  } {
    pop pop pop
  } ifelse
} def

/printfontinfo {
  (Comment AFM Generated by Ghostscript/pf2afm) =to.ofi
  currfont /FontName  (FontName) printinfoitem
  %
  currfont /FontInfo get
  dup /FullName           (FullName)           printinfoitem
  dup /FamilyName         (FamilyName)         printinfoitem
  dup /Weight             (Weight)             printinfoitem
  dup /Notice             (Notice)             printinfoitem
  dup /ItalicAngle        (ItalicAngle)        printinfoitem
  dup /isFixedPitch       (IsFixedPitch)       printinfoitem
  dup /UnderlinePosition  (UnderlinePosition)  printinfoitem
  dup /UnderlineThickness (UnderlineThickness) printinfoitem
      /version            (Version)            printinfoitem
  %
  (EncodingScheme FontSpecific) =to.ofi
  %
  (FontBBox) print.to.ofi
  currfont /FontBBox get {
    ( ) print.to.ofi round cvi =only.to.ofi
  } forall
  eolch print.to.ofi
  %
  currPFMfile () ne {
    PFMdict
    dup /PFMCapHeight        (CapHeight) printinfoitem
    dup /PFMXHeight          (XHeight)   printinfoitem
    dup /PFMLowerCaseDescent (Descender) printinfoitem
        /PFMLowerCaseAscent  (Ascender)  printinfoitem
  } if
} def

/readPFBfile {
  % make a shot of the actual font directory:
  /oldFontDirectory FontDirectory dup length dict copy def
  isPFB {% defined in `makeafm'
    (r) file true /PFBDecode filter cvx % true is better (see gs_type1.ps)
    mark exch exec
  } {
    (r) file mark exch run
  } ifelse
  cleartomark
  % make a shot of the updated font directory:
  /newFontDirectory FontDirectory dup length dict copy def
  % spot the added font:
  oldFontDirectory  {pop newFontDirectory exch undef} forall
  newFontDirectory length 1 ne {(Weird PFB file?) printquit} if
  newFontDirectory {pop} forall
  findfont /currfont exch def
} def

/readPFMfile {
  dup () ne {
    (r) file /currPFMfile exch def
    10 dict dup /PFMdict exch def begin
    readPFMheader
    readPFMExtMetric
    end
  } {
    pop /currPFMfile () def
  } ifelse
} def

% pfmfilename pf[ba]filename filetype printafm -
% where filetype=(a) or (b)

/printafm {
  readPFBfile
  readPFMfile
  (StartFontMetrics 2.0) =to.ofi
  printfontinfo
  printcharmetrics
  printkernpairs
  (EndFontMetrics) =to.ofi
} def

% pf[ba]filename makeafm -

/makeafm {
  count 0 eq {(Missing font file name) printquit} if
  /ifn exch def
  ifn length 0 eq {(Empty font file name) printquit} if
% the following piece of the code does, in fact, the job of a system shell,
% i.e., it analyses the supplied names, appends extensions if needed,
% and check files:
  /pfbn () def /pfan () def /pfmn () def % initialisation
  ifn (.pfb) search {
    3 -1 roll length 0 eq {% file name extension = ".pfb"
      ifn dup length string copy /pfbn exch def
      /ifn exch def
    } {pop} ifelse
  } if pop
  ifn (.pfa) search {
    3 -1 roll length 0 eq {% file name extension = ".pfa"
      ifn dup length string copy /pfan exch def
      /ifn exch def
    } {pop} ifelse
  } if pop
  pfbn () eq pfan () eq and dup {% no extension was supplied, try ".pfb"
    /pfbn ifn length 4 add string def
    pfbn 0 ifn putinterval pfbn ifn length (.pfb) putinterval
  } if
  pfbn () ne {% check whether "filename.pfb" exists
    pfbn status {pop pop pop pop /isPFB true def} {/pfbn () def} ifelse
  } if
  pfbn () eq and {% checking "filename.pfb" unsuccessful, try ".pfa"
    /pfan ifn length 4 add string def
    pfan 0 ifn putinterval pfan ifn length (.pfa) putinterval
  } if
  pfan () ne {% check whether "filename.pfa" exists
    pfan status {pop pop pop pop /isPFB false def} {/pfan () def} ifelse
  } if

  pfbn () eq pfan () eq and {
    (Neither pfa nor pfb found) printquit
  } if

  /ofn ifn length 4 add string def
  ofn 0 ifn putinterval ofn ifn length (.afm) putinterval
  ofn status {
    pop pop pop pop (Resulting file exists) printquit
  } if
  /ofi ofn (w) file def

  /pfmn ifn length 4 add string def
  pfmn 0 ifn putinterval pfmn ifn length (.pfm) putinterval
  pfmn status {
    pop pop pop pop
  } {
    /pfmn () def (pfm file not found -- ignored) print
  } ifelse

  pfmn
  isPFB {pfbn} {pfan} ifelse
  printafm

} def

% Check for command line arguments.
[ shellarguments
  { ] dup length 1 eq {
       0 get makeafm
     } {
       (Usage: gs [-sDEVICE=nullpage] -- pf2afm.ps disk_font_name\n)
       printquit
     } ifelse
  }
  {pop}
ifelse

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -