³ò
@wOGc           @   s  d  Z  d d k Z d d k Z d d k l Z e Z e Z e	 Z
 d „  Z d „  Z d „  Z d „  Z d „  Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d d d „  ƒ  YZ e d j o` d Z xW e i e ƒ D]B Z e e i i e e ƒ ƒ Z e e ƒ Z e i d ƒ \ Z  Z! qÐ Wn d S(   sÒ  
This is a python interface to Adobe Font Metrics Files.  Although a
number of other python implementations exist (and may be more complete
than mine) I decided not to go with them because either they were
either

  1) copyighted or used a non-BSD compatible license

  2) had too many dependencies and I wanted a free standing lib

  3) Did more than I needed and it was easier to write my own than
     figure out how to just get what I needed from theirs

It is pretty easy to use, and requires only built-in python libs

    >>> from afm import AFM
    >>> fh = file('ptmr8a.afm')
    >>> afm = AFM(fh)
    >>> afm.string_width_height('What the heck?')
    (6220.0, 683)
    >>> afm.get_fontname()
    'Times-Roman'
    >>> afm.get_kern_dist('A', 'f')
    0
    >>> afm.get_kern_dist('A', 'y')
    -92.0
    >>> afm.get_bbox_char('!')
    [130, -9, 238, 676]
    >>> afm.get_bbox_font()
    [-168, -218, 1000, 898]


AUTHOR:
  John D. Hunter <jdhunter@ace.bsd.uchicago.edu>
iÿÿÿÿN(   t	   uni2type1c         C   s=   |  i  d d ƒ }  g  } |  i ƒ  D] } | t | ƒ q# ~ S(   Nt   ,t    (   t   replacet   splitt   _to_int(   t   st   _[1]t   val(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _to_list_of_ints-   s    c         C   s+   g  } |  i  ƒ  D] } | t | ƒ q ~ S(   N(   R   t	   _to_float(   R   R   R   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _to_list_of_floats1   s    c         C   s)   |  i  ƒ  i ƒ  d j o t Sn t Sd  S(   Nt   falset   0t   no(   s   falseR   s   no(   t   lowert   stript   Falset   True(   R   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _to_bool3   s    !c         C   sT   |  i  ƒ  } z |  i ƒ  } Wd |  i | d ƒ X| i d ƒ p t d ƒ ‚ n d S(   sU   
    Check if the file at least looks like AFM. 
    If not, raise RuntimeError.
    Ni    t   StartFontMetricss   Not an AFM file(   t   tellt   readlinet   seekt
   startswitht   RuntimeError(   t   fht   post   line(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _sanity_check8   s    c         C   sô  h  t  d <t d <t d <t d <t d <t  d <t d <t d <t d	 <t d
 <t d <t d <t d <t  d <t  d <t  d <t  d <t  d <t  d <t  d <t d <t d <t d <} h  } x|  i ƒ  } | p Pn | i ƒ  } | i d ƒ o qÞ n | i d d ƒ } | d } t	 | ƒ d j o | d } n d } y | | | ƒ | | <WnU t
 j
 o# t i d I| I| IJqÞ n( t j
 o t i d | IJqÞ n X| d j o | SqÞ qÞ t d  ƒ ‚ d! S("   s  
    Reads the font metrics header (up to the char metrics) and returns
    a dictionary mapping key to val.  val will be converted to the
    appropriate python type as necessary; eg 'False'->False, '0'->0,
    '-168 -218 1000 898'-> [-168, -218, 1000, 898]

    Dictionary keys are

      StartFontMetrics, FontName, FullName, FamilyName, Weight,
      ItalicAngle, IsFixedPitch, FontBBox, UnderlinePosition,
      UnderlineThickness, Version, Notice, EncodingScheme, CapHeight,
      XHeight, Ascender, Descender, StartCharMetrics

    R   t   FontNamet   FullNamet
   FamilyNamet   Weightt   ItalicAnglet   IsFixedPitcht   FontBBoxt   UnderlinePositiont   UnderlineThicknesst   Versiont   Noticet   EncodingSchemet	   CapHeightt	   Capheightt   XHeightt   Ascendert	   Descendert   StdHWt   StdVWt   StartCharMetricst   CharacterSett
   Characterst   CommentR   i   i    i   t    s"   Value error parsing header in AFM:s/   Found an unknown keyword in AFM header (was %s)s	   Bad parseN(   R
   t   _to_strR   R	   R   R   t   rstripR   R   t   lent
   ValueErrort   syst   stderrt   KeyErrorR   (   R   t   headerConverterst   dR   t   lstt   keyR   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _parse_headerM   sX    																						
c   	      C   sE  h  } h  } x&|  i  ƒ  } | p Pn | i ƒ  } | i d ƒ o | | f Sn | i d ƒ d  } t | ƒ d j o t d | ƒ ‚ n t | d i ƒ  d ƒ } t | d i ƒ  d ƒ } | d i ƒ  d } t | d d ƒ } | d	 j o
 d
 } n | d j o | | | f | | <n | | f | | <q t d ƒ ‚ d S(   s^  
    Return a character metric dictionary.  Keys are the ASCII num of
    the character, values are a (wx, name, bbox) tuple, where

      wx is the character width
      name is the postscript language name
      bbox (llx, lly, urx, ury)

    This function is incomplete per the standard, but thus far parse
    all the sample afm files I have
    t   EndCharMetricst   ;i   s   Bad char metrics line: %si    i   i   i   t   Euroi€   iÿÿÿÿs	   Bad parseN(	   R   R7   R   R   R8   R   R   R
   R	   (	   R   t   ascii_dt   name_dR   t   valst   numt   wxt   namet   bbox(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _parse_char_metricsŽ   s&    '
c         C   s&  |  i  ƒ  } | i d ƒ p t d | ƒ ‚ n h  } xÝ |  i  ƒ  } | p Pn | i ƒ  } t | ƒ d j o q9 n | i d ƒ o |  i  ƒ  | Sn | i ƒ  } t | ƒ d j p | d d j o t d | ƒ ‚ n | d | d	 t | d
 ƒ } } } | | | | f <q9 t d ƒ ‚ d S(   sâ   
    Return a kern pairs dictionary; keys are (char1, char2) tuples and
    values are the kern pair value.  For example, a kern pairs line like

      KPX A y -50

    will be represented as

      d[ ('A', 'y') ] = -50

    t   StartKernPairss    Bad start of kern pairs data: %si    t   EndKernPairsi   t   KPXs   Bad kern pairs line: %si   i   i   s   Bad kern pairs parseN(   R   R   R   R7   R8   R   R
   (   R   R   R>   RG   t   c1t   c2R   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _parse_kern_pairs±   s$    
$&c         C   s"  h  } x	|  i  ƒ  } | p Pn | i ƒ  } t | ƒ d j o q	 n | i d ƒ o | Sn | i d ƒ } | d i ƒ  } | d t | d ƒ } } g  } xc | d d !D]T } | i ƒ  }	 |	 d t |	 d ƒ t |	 d ƒ } }
 } | i | |
 | f ƒ q­ W| | | <q	 t d ƒ ‚ d	 S(
   sq  
    Return a composites dictionary.  Keys are the names of the
    composites.  vals are a num parts list of composite information,
    with each element being a (name, dx, dy) tuple.  Thus if a
    composites line reading:

      CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 170 ;

    will be represented as

      d['Aacute'] = [ ('A', 0, 0), ('acute', 160, 170) ]

    i    t   EndCompositesRC   i   i   iÿÿÿÿi   s   Bad composites parseN(	   R   R7   R8   R   R   R   R
   t   appendR   (   R   R>   R   RG   t   ccRJ   t   numPartst   pccPartsR   t   pcct   dxt   dy(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _parse_compositesÒ   s&     ,c         C   sÄ   h  t  d <t d <} h  h  d <h  d <} xy |  i ƒ  } | p Pn | i ƒ  } t | ƒ d j o q3 n | i ƒ  d } | i | ƒ o | | |  ƒ | | <q3 q3 | d | d f } | S(   sñ   
    Parse the optional fields for kern pair data and composites

    return value is a kernDict, compositeDict which are the return
    values from parse_kern_pairs, and parse_composites if the data
    exists, or empty dicts otherwise
    t   StartKernDatat   StartCompositesi    (   RR   R[   R   R7   R8   R   t   has_key(   R   t   optionalR>   R   R@   t   l(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   _parse_optionalô   s    	+c         C   sO   t  |  ƒ t |  ƒ } t |  ƒ \ } } t |  ƒ } | | | | d | d f S(   s@  
    Parse the Adobe Font Metics file in file handle fh
    Return value is a (dhead, dcmetrics, dkernpairs, dcomposite) tuple where

    dhead : a parse_header dict
    dcmetrics :  a parse_composites dict
    dkernpairs : a parse_kern_pairs dict, possibly {}
    dcomposite : a parse_composites dict , possibly {}
    i    i   (   R   RA   RL   Ra   (   R   t   dheadt   dcmetrics_asciit   dcmetrics_namet	   doptional(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt	   parse_afm  s
    

t   AFMc           B   sÑ   e  Z d  „  Z e d „ Z d „  Z d „  Z d „  Z e d „ Z e d „ Z	 d „  Z
 e d „ Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   c         C   sL   t  | ƒ \ } } } } } | |  _ | |  _ | |  _ | |  _ | |  _ d S(   s6   
        Parse the AFM file in file object fh
        N(   Rf   t   _headert   _kernt   _metricst   _metrics_by_namet
   _composite(   t   selfR   Rb   Rc   Rd   t
   dkernpairst
   dcomposite(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   __init__!  s    				c         C   s1   | p t  | ƒ } n |  i | \ } } } | S(   N(   t   ordRj   (   Rm   t   ct   isordRI   RJ   RK   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_bbox_char.  s    c         C   s  t  | ƒ p d Sn d } d } d } d } xÏ | D]Ç } | d j o q4 n |  i t | ƒ \ } } }	 |	 \ }
 } } } y |  i | | f } Wn t j
 o d } n X| | | 7} | | } | | j o
 | } n | } | | j  o
 | } q4 q4 W| | | f S(   sf   
        Return the string width (including kerning) and string height
        as a w,h tuple
        i    g    eÍÍAs   
(   i    i    N(   R8   t   NoneRj   Rq   Ri   R<   (   Rm   R   t   totalwt   namelastt   minyt   maxyRr   RI   RJ   RK   R`   t   bt   wt   ht   kpt   thismaxt   thismin(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   string_width_height3  s$     
c      
   C   s–  t  | ƒ p d Sn d } d } d } d } d } t | t ƒ p | i ƒ  } n x(| D] } | d j o qZ n t i t | ƒ d ƒ } y |  i | \ }	 }
 Wn, t	 j
 o  d } |  i | \ }	 }
 n X|
 \ } } } } | | j  o
 | } n y |  i
 | | f } Wn t	 j
 o d } n X| |	 | 7} | | } | | j o
 | } n | } | | j  o
 | } qZ qZ W| | | | | | f S(   s0   
        Return the string bounding box
        i    g    eÍÍAs   
t   question(   i    i    i    i    N(   R8   Ru   t
   isinstancet   unicodet   decodeR    t   getRq   Rk   R<   Ri   (   Rm   R   Rv   Rw   Rx   Ry   t   leftRr   RJ   RI   RK   R`   Rz   R{   R|   R}   R~   R   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_str_bbox_and_descentQ  s6     
c         C   s   |  i  | ƒ d  S(   s0   
        Return the string bounding box
        i   (   R‡   (   Rm   R   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_str_bboxw  s    c         C   s1   | p t  | ƒ } n |  i | \ } } } | S(   sG   
        Get the name of the character, ie, ';' is 'semicolon'
        (   Rq   Rj   (   Rm   Rr   Rs   RI   RJ   RK   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_name_char}  s    c         C   s1   | p t  | ƒ } n |  i | \ } } } | S(   s[   
        Get the width of the character from the character metric WX
        field
        (   Rq   Rj   (   Rm   Rr   Rs   RI   RJ   RK   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_width_char…  s    c         C   s   |  i  | \ } } | S(   sL   
        Get the width of the character from a type1 character name
        (   Rk   (   Rm   RJ   RI   RK   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_width_from_char_nameŽ  s    c         C   s5   | p t  | ƒ } n |  i | \ } } } | d S(   ss   
        Get the height of character c from the bounding box.  This is
        the ink height (space is 0)
        iÿÿÿÿ(   Rq   Rj   (   Rm   Rr   Rs   RI   RJ   RK   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_height_char•  s    c         C   s/   |  i  | ƒ |  i  | ƒ } } |  i | | ƒ S(   s[   
        Return the kerning pair distance (possibly 0) for chars c1 and
        c2
        (   R‰   t   get_kern_dist_from_name(   Rm   RP   RQ   t   name1t   name2(    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_kern_distž  s    c         C   s'   y |  i  | | f SWn d Sn Xd S(   s[   
        Return the kerning pair distance (possibly 0) for chars c1 and
        c2
        i    N(   Ri   (   Rm   RŽ   R   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyR   ¦  s    c         C   s   |  i  d S(   s%   Return the font name, eg, Times-RomanR   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_fontname®  s    c         C   s   |  i  d S(   s*   Return the font full name, eg, Times-RomanR   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_fullname²  s    c         C   s   |  i  d S(   s&   Return the font family name, eg, TimesR    (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_familyname¶  s    c         C   s   |  i  d S(   s-   Return the font weight, eg, 'Bold' or 'Roman'R!   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt
   get_weightº  s    c         C   s   |  i  d S(   s   Return the fontangle as floatR"   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt	   get_angle¾  s    c         C   s   |  i  d S(   s   Return the cap height as floatR*   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_capheightÂ  s    c         C   s   |  i  d S(   s   Return the xheight as floatR,   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_xheightÆ  s    c         C   s   |  i  d S(   s'   Return the underline thickness as floatR&   (   Rh   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_underline_thicknessÊ  s    c         C   s   |  i  i d d ƒ S(   ss   
        Return the standard horizontal stem width as float, or None if
        not specified in AFM file.
        R/   N(   Rh   R…   Ru   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_horizontal_stem_widthÎ  s    c         C   s   |  i  i d d ƒ S(   sq   
        Return the standard vertical stem width as float, or None if
        not specified in AFM file.
        R0   N(   Rh   R…   Ru   (   Rm   (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyt   get_vertical_stem_widthÕ  s    (   t   __name__t
   __module__Rp   R   Rt   R€   R‡   Rˆ   R‰   RŠ   R‹   RŒ   R   R   R‘   R’   R“   R”   R•   R–   R—   R˜   R™   Rš   (    (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pyRg     s*   			&															t   __main__s!   /usr/local/share/fonts/afms/adobes   John Hunter is the Man!(    ("   t   __doc__R:   t   ost   _mathtext_dataR    t   intR   t   floatR
   t   strR6   R	   R   R   R   RA   RL   RR   R[   Ra   Rf   Rg   R›   t   pathnamet   listdirt   fnamet   filet   patht   joinR   t   afmR€   R{   R|   (    (    (    s7   /Users/cmoad/workspace/matplotlib/lib/matplotlib/afm.pys   <module>#   s.   					A	#	!	"		¾ 