ó
º¶Y]c           @` sø   d  Z  d d l m Z m Z m Z m Z d d l Z d d l m Z d d l	 Z	 d d l
 Z
 d d l m Z d „  Z e Z d „  Z d	 „  Z d
 „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d e f d „  ƒ  YZ d S(   u4  
This is a python interface to Adobe Font Metrics Files.  Although a
number of other python implementations exist, and may be more complete
than this, it was decided not to go with them because they were
either:

  1) copyrighted or used a non-BSD compatible license

  2) had too many dependencies and a free standing lib was needed

  3) Did more than needed and it was easier to write afresh rather than
     figure out how to get just what was needed.

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

    >>> from matplotlib import rcParams
    >>> import os.path
    >>> afm_fname = os.path.join(rcParams['datapath'],
    ...                         'fonts', 'afm', 'ptmr8a.afm')
    >>>
    >>> from matplotlib.afm import AFM
    >>> with open(afm_fname, 'rb') as fh:
    ...     afm = AFM(fh)
    >>> afm.string_width_height('What the heck?')
    (6220.0, 694)
    >>> 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]

i    (   t   absolute_importt   divisiont   print_functiont   unicode_literalsN(   t   mapi   (   t	   uni2type1c         C` s   t  t |  ƒ ƒ S(   N(   t   intt   float(   t   x(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _to_int8   s    c         C` s   |  j  d ƒ S(   Nu   utf8(   t   decode(   R   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _to_str?   s    c         C` s5   |  j  d d ƒ }  g  |  j ƒ  D] } t | ƒ ^ q S(   Nt   ,t    (   t   replacet   splitR	   (   t   st   val(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _to_list_of_intsC   s    c         C` s#   g  |  j  ƒ  D] } t | ƒ ^ q S(   N(   R   t	   _to_float(   R   R   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _to_list_of_floatsH   s    c         C` s$   |  j  ƒ  j ƒ  d k r t St Sd  S(   Nt   falset   0t   no(   R   R   R   (   t   lowert   stript   Falset   True(   R   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _to_boolL   s    c         C` sR   |  j  ƒ  } z t |  ƒ } Wd |  j | d ƒ X| j d ƒ sN t d ƒ ‚ n  d S(   u[   
    Check if the file at least looks like AFM.
    If not, raise :exc:`RuntimeError`.
    Ni    t   StartFontMetricsu   Not an AFM file(   t   tellt   nextt   seekt
   startswitht   RuntimeError(   t   fht   post   line(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _sanity_checkS   s    c         C` s²  i t  d 6t d 6t d 6t d 6t d 6t  d 6t d 6t d 6t d	 6t d
 6t d 6t d 6t d 6t  d 6t  d 6t  d 6t  d 6t  d 6t  d 6t  d 6t d 6t d 6t d 6} i  } xò |  D]ê } | j ƒ  } | j d ƒ rÛ q´ n  | j d d ƒ } | d } t | ƒ d k r| d } n d } y | | | ƒ | | <WnW t	 k
 rct
 d | | d t j ƒq´ n+ t k
 rt
 d  | d t j ƒq´ n X| d k r´ | Sq´ Wt d! ƒ ‚ d" S(#   u=  
    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; e.g.:

        * '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    u"   Value error parsing header in AFM:t   fileu/   Found an unknown keyword in AFM header (was %r)u	   Bad parseN(   R   R   R   R   R	   t   rstripR!   R   t   lent
   ValueErrort   printt   syst   stderrt   KeyErrorR"   (   R#   t   headerConverterst   dR%   t   lstt   keyR   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _parse_headeri   s^    


c   	      C` s;  i  } i  } x|  D]} t  | j ƒ  ƒ } | j d ƒ rD | | f St d „  | j d ƒ Dƒ ƒ } d d d d h j | ƒ s‘ t d | ƒ ‚ n  t | d ƒ } t | d ƒ } | d } t	 | d ƒ } t
 t t | ƒ ƒ } | d	 k rõ d
 } n  | d k r| | | f | | <n  | | f | | <q Wt d ƒ ‚ d S(   uz  
    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, and *bbox* is a (*llx*, *lly*, *urx*, *ury*) tuple.

    This function is incomplete per the standard, but thus far parses
    all the sample afm files tried.
    u   EndCharMetricsc         s` s-   |  ]# } | r | j  ƒ  j d  d ƒ Vq d S(   u    i   N(   R   R   (   t   .0R   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pys	   <genexpr>Å   s    u   ;u   Cu   WXu   Nu   Bu   Bad char metrics line: %su   Euroi€   iÿÿÿÿu	   Bad parseN(   R   R@   R!   t   dictR   t   issubsetR"   R	   R   R   t   listR   R   (	   R#   t   ascii_dt   name_dR%   t   valst   numt   wxt   namet   bbox(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _parse_char_metrics±   s(    

	c         C` s  t  |  ƒ } | j d ƒ s. t d | ƒ ‚ n  i  } xÆ |  D]¾ } | j ƒ  } | sY q; n  | j d ƒ rv t  |  ƒ | S| j ƒ  } t | ƒ d k s¤ | d d k r· t d | ƒ ‚ n  t | d ƒ t | d	 ƒ t | d
 ƒ } } } | | | | f <q; Wt d ƒ ‚ d S(   ué   
    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   StartKernPairsu    Bad start of kern pairs data: %st   EndKernPairsi   i    t   KPXu   Bad kern pairs line: %si   i   i   u   Bad kern pairs parseN(   R   R!   R"   R@   R   RA   R   R   (   R#   R%   RH   RR   t   c1t   c2R   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _parse_kern_pairsÙ   s"    
"2c         C` s  i  } xé |  D]á } | j  ƒ  } | s+ q n  | j d ƒ r> | S| j d ƒ } | d j ƒ  } | d t | d ƒ } } g  } xc | d d !D]T } | j ƒ  }	 |	 d t |	 d ƒ t |	 d ƒ } }
 } | j | |
 | f ƒ qŒ W| | | <q Wt d ƒ ‚ d	 S(
   ux  
    Return a composites dictionary.  Keys are the names of the
    composites.  Values are a num parts list of composite information,
    with each element being a (*name*, *dx*, *dy*) tuple.  Thus 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) ]

    t   EndCompositest   ;i    i   i   iÿÿÿÿi   u   Bad composites parseN(   R@   R!   R   R	   R   t   appendR"   (   R#   RH   R%   RR   t   ccRU   t   numPartst   pccPartsR   t   pcct   dxt   dy(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _parse_compositesù   s"    ,c         C` sœ   i t  d 6t d 6} i i  d 6i  d 6} xY |  D]Q } | j ƒ  } | sM q/ n  | j ƒ  d } | | k r/ | | |  ƒ | | <q/ q/ W| d | d f } | S(   u  
    Parse the optional fields for kern pair data and composites

    return value is a (*kernDict*, *compositeDict*) which are the
    return values from :func:`_parse_kern_pairs`, and
    :func:`_parse_composites` if the data exists, or empty dicts
    otherwise
    t   StartKernDatat   StartCompositesi    (   R]   Rg   R@   R   (   R#   t   optionalRH   R%   RJ   t   l(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   _parse_optional  s    	
c         C` sO   t  |  ƒ t |  ƒ } t |  ƒ \ } } t |  ƒ } | | | | d | d f S(   uÓ  
    Parse the Adobe Font Metics file in file handle *fh*. Return value
    is a (*dhead*, *dcmetrics_ascii*, *dmetrics_name*, *dkernpairs*,
    *dcomposite*) tuple where
    *dhead* is a :func:`_parse_header` dict,
    *dcmetrics_ascii* and *dcmetrics_name* are the two resulting dicts
    from :func:`_parse_char_metrics`,
    *dkernpairs* is a :func:`_parse_kern_pairs` dict (possibly {}) and
    *dcomposite* is a :func:`_parse_composites` dict (possibly {})
    i    i   (   R&   RK   RW   Rl   (   R#   t   dheadt   dcmetrics_asciit   dcmetrics_namet	   doptional(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt	   parse_afm7  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 e d „  ƒ Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z d „  Z RS(   c         C` sL   t  | ƒ \ } } } } } | |  _ | |  _ | |  _ | |  _ | |  _ d S(   u8   
        Parse the AFM file in file object *fh*
        N(   Rq   t   _headert   _kernt   _metricst   _metrics_by_namet
   _composite(   t   selfR#   Rm   Rn   Ro   t
   dkernpairst
   dcomposite(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   __init__K  s    				c         C` s/   | s t  | ƒ } n  |  j | \ } } } | S(   N(   t   ordRu   (   Rx   t   ct   isordRT   RU   RV   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_bbox_charW  s    c         C` s  t  | ƒ s d Sd } d } d } d } xÍ | D]Å } | d k rG q/ n  |  j t | ƒ \ } } }	 |	 \ }
 } } } y |  j | | f } Wn t k
 r¥ d } n X| | | 7} | | } | | k rÓ | } n  | } | | k  rî | } n  | } q/ W| | | f S(   un   
        Return the string width (including kerning) and string height
        as a (*w*, *h*) tuple.
        i    g    eÍÍAu   
(   i    i    N(   RA   t   NoneRu   R|   Rt   RF   (   Rx   R   t   totalwt   namelastt   minyt   maxyR}   RT   RU   RV   Rk   t   bt   wt   ht   kpt   thismaxt   thismin(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   string_width_height]  s0    

		
c         C` sŒ  t  | ƒ s d Sd } d } d } d } d } t | t j ƒ sO t | ƒ } n  x"| D]} | d k rn qV n  t j t | ƒ d ƒ } y |  j	 | \ }	 }
 Wn* t
 k
 rÉ d } |  j	 | \ }	 }
 n X|
 \ } } } } | | k  rñ | } n  y |  j | | f } Wn t
 k
 r!d } n X| |	 | 7} | | } | | k rO| } n  | } | | k  rj| } n  | } qV W| | | | | | f S(   u0   
        Return the string bounding box
        i    g    eÍÍAu   
u   question(   i    i    i    i    N(   RA   R€   t
   isinstancet   sixt	   text_typeR   R   t   getR|   Rv   RF   Rt   (   Rx   R   R   R‚   Rƒ   R„   t   leftR}   RU   RT   RV   Rk   R…   R†   R‡   Rˆ   R‰   RŠ   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_str_bbox_and_descent‚  sD    	

		
c         C` s   |  j  | ƒ d  S(   u0   
        Return the string bounding box
        i   (   R‘   (   Rx   R   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_str_bbox¯  s    c         C` s/   | s t  | ƒ } n  |  j | \ } } } | S(   uI   
        Get the name of the character, i.e., ';' is 'semicolon'
        (   R|   Ru   (   Rx   R}   R~   RT   RU   RV   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_name_charµ  s    c         C` s/   | s t  | ƒ } n  |  j | \ } } } | S(   u[   
        Get the width of the character from the character metric WX
        field
        (   R|   Ru   (   Rx   R}   R~   RT   RU   RV   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_width_char¾  s    c         C` s   |  j  | \ } } | S(   uL   
        Get the width of the character from a type1 character name
        (   Rv   (   Rx   RU   RT   RV   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_width_from_char_nameÈ  s    c         C` s3   | s t  | ƒ } n  |  j | \ } } } | d S(   uu   
        Get the height of character *c* from the bounding box.  This
        is the ink height (space is 0)
        iÿÿÿÿ(   R|   Ru   (   Rx   R}   R~   RT   RU   RV   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_height_charÏ  s    c         C` s/   |  j  | ƒ |  j  | ƒ } } |  j | | ƒ S(   u_   
        Return the kerning pair distance (possibly 0) for chars *c1*
        and *c2*
        (   R“   t   get_kern_dist_from_name(   Rx   R[   R\   t   name1t   name2(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_kern_distÙ  s    c         C` s   |  j  j | | f d ƒ S(   ue   
        Return the kerning pair distance (possibly 0) for chars
        *name1* and *name2*
        i    (   Rt   R   (   Rx   R˜   R™   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyR—   á  s    c         C` s   |  j  d S(   u)   Return the font name, e.g., 'Times-Roman'R'   (   Rs   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_fontnameè  s    c         C` s2   |  j  j d ƒ } | d k r. |  j  d } n  | S(   u.   Return the font full name, e.g., 'Times-Roman'R(   R'   N(   Rs   R   R€   (   Rx   RU   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_fullnameì  s    c         C` sG   |  j  j d ƒ } | d k	 r" | S|  j ƒ  } d } t j | d | ƒ S(   u*   Return the font family name, e.g., 'Times'R)   uY   (?i)([ -](regular|plain|italic|oblique|bold|semibold|light|ultralight|extra|condensed))+$u    N(   Rs   R   R€   Rœ   t   ret   sub(   Rx   RU   t   extras(    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_familynameó  s    c         C` s
   |  j  ƒ  S(   N(   R    (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   family_nameÿ  s    c         C` s   |  j  d S(   u/   Return the font weight, e.g., 'Bold' or 'Roman'R*   (   Rs   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt
   get_weight  s    c         C` s   |  j  d S(   u   Return the fontangle as floatR+   (   Rs   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt	   get_angle  s    c         C` s   |  j  d S(   u   Return the cap height as floatR3   (   Rs   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_capheight  s    c         C` s   |  j  d S(   u   Return the xheight as floatR5   (   Rs   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_xheight  s    c         C` s   |  j  d S(   u'   Return the underline thickness as floatR/   (   Rs   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_underline_thickness  s    c         C` s   |  j  j d d ƒ S(   uu   
        Return the standard horizontal stem width as float, or *None* if
        not specified in AFM file.
        R8   N(   Rs   R   R€   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_horizontal_stem_width  s    c         C` s   |  j  j d d ƒ S(   us   
        Return the standard vertical stem width as float, or *None* if
        not specified in AFM file.
        R9   N(   Rs   R   R€   (   Rx   (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   get_vertical_stem_width  s    (   t   __name__t
   __module__R{   R   R   R‹   R‘   R’   R“   R”   R•   R–   Rš   R—   R›   Rœ   R    t   propertyR¡   R¢   R£   R¤   R¥   R¦   R§   R¨   (    (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyRr   I  s,   		%	-		
	
											(   t   __doc__t
   __future__R    R   R   R   R   t	   six.movesR   RD   R   t   _mathtext_dataR   R	   R   R   R   R   R   R   R&   RK   RW   R]   Rg   Rl   Rq   t   objectRr   (    (    (    s-   lib/python2.7/site-packages/matplotlib/afm.pyt   <module>#   s(   "							H	(	 	"		