
    hl3                        S r SSKr\R                  " S5      r\R                  " S5      r\R                  " S5      r\R                  " S5      r\R                  " S5      r/ SQr " S	 S
\	5      r
 " S S\5      rS rSS jr\S:X  a  SSKr\R"                  " 5       r\(       a  \" \5      rSr\R+                  \5      (       a  \" \\   5        Sr\R1                  \5      (       a  \" \\   5        \" \R2                  5        \" \R4                  5        \" \R7                  5       5        \" \5        \R9                  \S-   5        ggg)a  Module for reading and writing AFM (Adobe Font Metrics) files.

Note that this has been designed to read in AFM files generated by Fontographer
and has not been tested on many other files. In particular, it does not
implement the whole Adobe AFM specification [#f1]_ but, it should read most
"common" AFM files.

Here is an example of using `afmLib` to read, modify and write an AFM file:

        >>> from fontTools.afmLib import AFM
        >>> f = AFM("Tests/afmLib/data/TestAFM.afm")
        >>>
        >>> # Accessing a pair gets you the kern value
        >>> f[("V","A")]
        -60
        >>>
        >>> # Accessing a glyph name gets you metrics
        >>> f["A"]
        (65, 668, (8, -25, 660, 666))
        >>> # (charnum, width, bounding box)
        >>>
        >>> # Accessing an attribute gets you metadata
        >>> f.FontName
        'TestFont-Regular'
        >>> f.FamilyName
        'TestFont'
        >>> f.Weight
        'Regular'
        >>> f.XHeight
        500
        >>> f.Ascender
        750
        >>>
        >>> # Attributes and items can also be set
        >>> f[("A","V")] = -150 # Tighten kerning
        >>> f.FontName = "TestFont Squished"
        >>>
        >>> # And the font written out again (remove the # in front)
        >>> #f.write("testfont-squished.afm")

.. rubric:: Footnotes

.. [#f1] `Adobe Technote 5004 <https://www.adobe.com/content/dam/acom/en/devnet/font/pdfs/5004.AFM_Spec.pdf>`_,
   Adobe Font Metrics File Format Specification.

    Nz^([A-Za-z]+).*zl(-?\d+)\s*;\s*WX\s+(-?\d+)\s*;\s*N\s+([.A-Za-z0-9_]+)\s*;\s*B\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s+(-?\d+)\s*;\s*z0([.A-Za-z0-9_]+)\s+([.A-Za-z0-9_]+)\s+(-?\d+)\s*z([.A-Za-z0-9_]+)\s+(\d+)\s*;\s*z1PCC\s+([.A-Za-z0-9_]+)\s+(-?\d+)\s+(-?\d+)\s*;\s*)FontNameFullName
FamilyNameWeightItalicAngleIsFixedPitchFontBBoxUnderlinePositionUnderlineThicknessVersionNoticeEncodingScheme	CapHeightXHeightAscender	Descenderc                       \ rS rSrSrg)errorw    N)__name__
__module____qualname____firstlineno____static_attributes__r       B/var/www/html/env/lib/python3.13/site-packages/fontTools/afmLib.pyr   r   w   s    r   r   c                       \ rS rSrSr/ SQrSS jrS rS rS r	S r
S	 rSS
 jrS rS rS rS rS rS rS rS rS rS rS rS rS rS rSrg)AFM{   N)
StartFontMetricsEndFontMetricsStartCharMetricsEndCharMetricsStartKernDataStartKernPairsEndKernPairsEndKernDataStartCompositesEndCompositesc                     0 U l         0 U l        0 U l        0 U l        / U l        0 U l        Ub  U R                  U5        gg)zAFM file reader.

Instantiating an object with a path name will cause the file to be opened,
read, and parsed. Alternatively the path can be left unspecified, and a
file can be parsed later with the :meth:`read` method.N)_attrs_chars_kerning_index	_comments_compositesread)selfpaths     r   __init__AFM.__init__   sE     IIdO r   c                    [        U5      nU H  nUR                  5       (       d  M  [        R                  U5      nUc  [	        S[        U5      -   5      eUR                  S   S   nUSU nX5S R                  5       nX`R                  ;   a  M  US:X  a  U R                  U5        M  US:X  a  U R                  U5        M  US:X  a  U R                  U5        M  U R                  Xg5        M     g)zOpens, reads and parses a file.Nsyntax error in AFM file:    CKPXCC)	readlinesstripidentifierREmatchr   reprregs	_keywords	parsecharparsekernpairparsecomposite	parseattr)r3   r4   lineslinemposwordrests           r   r2   AFM.read   s    $D::<<""4(Ay84:EFF&&)A,C:D:##%D~~%s{t$""4(##D)t*' r   c                    [         R                  U5      nUc  [        S[        U5      -   5      e/ nUR                  SS   H  u  pEUR                  XU 5        M     US   nUS	 S U 5       u  pxppXxXX44U R                  U'   g )Nr8   r9      c              3   8   #    U  H  n[        U5      v   M     g 7fN)int).0things     r   	<genexpr> AFM.parsechar.<locals>.<genexpr>   s     %EfUc%jjfs   )charREr@   r   rA   rB   appendr-   )r3   rM   rJ   thingsfrtocharnamecharnumwidthlbrts                r   rD   AFM.parsechar   s    LL94tDzABBffQRjFBMM$"+& !!91I%Ef%E"a 'q <Hr   c                     [         R                  U5      nUc  [        S[        U5      -   5      e/ nUR                  SS   H  u  pEUR                  XU 5        M     Uu  pgn[        U5      nXR                  Xg4'   g )Nr8   r9   )kernREr@   r   rA   rB   rY   rS   r.   )	r3   rM   rJ   rZ   r[   r\   leftchar	rightcharvalues	            r   rE   AFM.parsekernpair   sw    LL94tDzABBffQRjFBMM$"+& !%+"UE
/4x+,r   c                 X   US:X  a?  UR                  5        Vs/ s H  n[        U5      PM     snu  pEpgXEXg4U R                  U'   g US:X  a  U R                  R	                  U5        g  [        U5      nXR                  U'   g s  snf ! [
        [        4 a    X R                  U'    g f = f)Nr	   Comment)splitrS   r,   r0   rY   
ValueErrorOverflowError)	r3   rL   rM   rU   r`   ra   rb   rc   ri   s	            r   rG   AFM.parseattr   s    :26**,?,#e*,?JA! !a
DKKYNN!!$'*D	 %*D! @ . )$(D!)s   B)B B)(B)c                 n   [         R                  U5      nUc  [        S[        U5      -   5      eUR	                  S5      n[        UR	                  S5      5      nXR                  S   S   S  n/ n [        R                  U5      nUc  [        S[        U5      -   5      eUR	                  S5      n[        UR	                  S5      5      n[        UR	                  S5      5      nUR                  XgU45        XR                  S   S   S  nU(       d  OM  [        U5      U:X  d   eXPR                  U'   g )Nr8   r9   rP   r      )compositeREr@   r   rA   grouprS   rB   componentRErY   lenr1   )	r3   rM   rJ   r]   ncomponents
componentsbasecharxoffsetyoffsets	            r   rF   AFM.parsecomposite   s   d#94tDzABB771:!''!*oFF1IaLN#
!!$'Ay84:EFFwwqzH!''!*oG!''!*oGx':;q	!'D  :+---%/"r   c                    SSK nSSUR                  SUR                  UR                  5       5      5      -  /nU R                   H  nUR	                  SU-   5        M     U R
                  n[         H9  nXv;   d  M
  Xg   nUS:X  a  SU-  nUR	                  US	-   [        U5      -   5        M;     [        UR                  5       5      n	U	 H1  u  pxU[        ;   a  M  UR	                  US	-   [        U5      -   5        M3     UR	                  S
[        [        U R                  5      5      -   5        U R                  R                  5        V
VVVs/ s H  u  n
u  pnXX44PM     n	nnn
nS nU	R                  US9  U	 H'  u  nu  pu  nnnnUR	                  SXXUUU4-  5        M)     UR	                  S5        UR	                  S5        UR	                  S[        [        U R                  5      5      -   5        [        U R                  R                  5       5      n	U	 H   u  u  nnnUR	                  SUUU4-  5        M"     UR	                  S5        UR	                  S5        U R                  (       a  [        U R                  R                  5       5      nUR	                  S[        U R                  5      -  5        U HJ  u  n
nSU
< S	[        U5      < S3nU H  u  nnnUSU< S	U< S	U< S3-   nM     UR	                  U5        ML     UR	                  S5        UR	                  S5        [!        XU5        gs  snnnn
f )z)Writes out an AFM font to the given path.r   NzStartFontMetrics 2.0z"Comment Generated by afmLib; at %sz%m/%d/%Y %H:%M:%SzComment r	   z%s %s %s %s zStartCharMetrics c                 (    U S   S:X  a  SU SS -   n U $ )zbCustom key function to make sure unencoded chars (-1)
end up at the end of the list after sorting.r   )i  r9   Nr   )as    r   myKeyAFM.write.<locals>.myKey  s$     trz!"%Hr   )keyz%C %d ; WX %d ; N %s ; B %d %d %d %d ;r$   r%   zStartKernPairs zKPX %s %s %dr'   r(   zStartComposites %szCC z ;z PCC r*   r"   )timestrftime	localtimer0   rY   r,   preferredAttributeOrderstrsorteditemsrA   rv   r-   sortr.   r1   
writelines)r3   r4   sepr   rH   commentattrsattrri   r   r]   r^   r_   boxr   r`   ra   rb   rc   rg   rh   
compositesrx   rI   ry   rz   r{   s                              r   write	AFM.write   s    #0}}0$..2MNP
 ~~GLLg-. &
 +D}:%)E1ETCZ#e*45 , u{{}% KD..LLc%j01 ! 	(4DKK0@+AAB 48;;3D3D3F
3F//73 ,-3F 	 

	 	

u
8=4G4h|1aLL781a89 9>
 	%& 	_%&c$--.@)AABt}}**,-,1(!Xy5LL8Y*FFG -2^$]# 0 0 6 6 89JLL-D4D4D0EEF(2$*'/ZA2<.Hgwx'"RRD 3=T"	 )3
 LL)%&4$U
s   L>
c                     XR                   ;   $ )z_Returns `True` if the given glyph pair (specified as a tuple) exists
in the kerning dictionary.)r.   )r3   pairs     r   has_kernpairAFM.has_kernpair;  s     }}$$r   c                 H    [        U R                  R                  5       5      $ )z;Returns a list of all kern pairs in the kerning dictionary.)listr.   keysr3   s    r   	kernpairsAFM.kernpairs@  s    DMM&&())r   c                     XR                   ;   $ )z5Returns `True` if the given glyph exists in the font.)r-   )r3   chars     r   has_charAFM.has_charD  s    {{""r   c                 H    [        U R                  R                  5       5      $ )z.Returns a list of all glyph names in the font.)r   r-   r   r   s    r   chars	AFM.charsH  s    DKK$$&''r   c                     U R                   $ )z#Returns all comments from the file.)r0   r   s    r   commentsAFM.commentsL  s    ~~r   c                 :    U R                   R                  U5        g)zAdds a new comment to the file.N)r0   rY   )r3   r   s     r   
addCommentAFM.addCommentP  s    g&r   c                      X R                   U'   g)zSpecifies that the glyph `glyphName` is made up of the given components.
The components list should be of the following form::

        [
                (glyphname, xOffset, yOffset),
                ...
        ]

N)r1   )r3   	glyphNamerx   s      r   addCompositeAFM.addCompositeT  s     '1#r   c                 T    XR                   ;   a  U R                   U   $ [        U5      erR   )r,   AttributeErrorr3   r   s     r   __getattr__AFM.__getattr__`  s&    ;;;;t$$ &&r   c                 P    US S S:X  a  X R                   U'   g X R                  U'   g Nr9   _)__dict__r,   )r3   r   ri   s      r   __setattr__AFM.__setattr__f  s'    8s?"'MM$ %KKr   c                     US S S:X  a   U R                   U	 g  U R                  U	 g ! [         a    [        U5      ef = f! [         a    [        U5      ef = fr   )r   KeyErrorr   r,   r   s     r   __delattr__AFM.__delattr__m  sh    8s?+MM$'+KK%	  +$T**+
  +$T**+s   ( A >Ac                 h    [        U[        5      (       a  U R                  U   $ U R                  U   $ rR   
isinstancetupler.   r-   r3   r   s     r   __getitem__AFM.__getitem__z  s/    c5!!==%% ;;s##r   c                 h    [        U[        5      (       a  X R                  U'   g X R                  U'   g rR   r   )r3   r   ri   s      r   __setitem__AFM.__setitem__  s)    c5!!!&MM#  %KKr   c                 d    [        U[        5      (       a  U R                  U	 g U R                  U	 g rR   r   r   s     r   __delitem__AFM.__delitem__  s)    c5!!c" C r   c                 ^    [        U S5      (       a  SU R                  -  $ S[        U 5      -  $ )Nr   z<AFM object for %s>z<AFM object at %x>)hasattrr   idr   s    r   __repr__AFM.__repr__  s-    4$$(4==88'"T(22r   )r,   r-   r0   r1   r/   r.   rR   )r   r   r   r   r,   rC   r5   r2   rD   rE   rG   rF   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   {   sy    FI+0
=	5*0,L%\%
*#('
1'&+$%!3r   r   c                     [        U SSS9 nUR                  5       nS S S 5        UR                  5       $ ! , (       d  f       WR                  5       $ = f)Nrb   ascii)encoding)openr2   
splitlines)r4   fdatas      r   r=   r=     sC    	dC'	*avvx 
+?? 
+	*??s	   5
Ac                     [        U SSUS9 nUR                  SR                  U5      S-   5        S S S 5        g ! , (       d  f       g = f)Nwr   )r   newline
)r   r   join)r4   rH   r   r   s       r   r   r     s8    	dC'3	71			% 4'( 
8	7	7s	   $:
A__main__A)r   Vz.muckr   )__doc__recompiler?   rX   rf   rs   ru   r   	Exceptionr   objectr   r=   r   r   EasyDialogsAskFileForOpenr4   afmr   r   printr   r   r   r   r   r   r   r   r   <module>r      sT  -^ 
 zz+, 

$ 

 jj jj (	I 	[3& [3|)
 z%%'D$i<<#d)D!!#d)ckkcjjclln 	c
		$.! 	 r   