
     #eX                       d dl mZ d dlZd dlZd dlmZmZmZmZm	Z	m
Z
mZmZmZmZmZ d dlZd dlZd dlmZmZ d dlmZmZmZ d dlmZ d dlmZ d dlmZ d d	l m!Z! d d
l"m#Z# d dl$m%Z% d dl&m'Z' d dl(m)Z)m*Z* d dl+m,Z, d dl-m.Z. d dl/m0Z0m1Z1m2Z2m3Z3m4Z4m5Z5 d dl6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z< d dl=m>Z> d dl?m@Z@mAZAmBZB d dZCd!dZDd"dZEd#dZFd$dZGd%dZHd&dZId'dZJe> ed       G d d                    ZKy)(    )annotationsN)AnyDictIterableIteratorKeysViewListMappingMutableMappingOptionalSequencecast)definefield)UFOFileStructure	UFOReader	UFOWriter)DEFAULT_LAYER_NAME)DataSet)Features)Glyph)	Guideline)ImageSet)Info)KerningKerningPair)Layer)LayerSet)Lib_convert_Lib_get_lib_get_tempLib_set_lib_set_tempLib)BoundingBox_deepcopy_unlazify_attrs_getstate_unlazify_attrs_object_lib_prune_object_libs_setstate_attrs)serde)HasIdentifierPathLikeTc                P    t        | t              r| S t        j                  |       S N)
isinstancer   from_iterablevalues    6/usr/lib/python3/dist-packages/ufoLib2/objects/font.py_convert_LayerSetr6   6   s!    uh/5RX5K5KE5RR    c                <    t        | t              r| S t        di | S )N )r1   r   r3   s    r5   _convert_Infor:   :   s    ud+5>>r7   c                <    t        | t              r| S t        |       S r0   )r1   r   r3   s    r5   _convert_DataSetr<   >       ug.5BGENBr7   c                <    t        | t              r| S t        |       S r0   )r1   r   r3   s    r5   _convert_ImageSetr?   B       uh/5DXe_Dr7   c                <    t        | t              r| S t        |       S r0   )r1   r   r3   s    r5   _convert_FeaturesrB   F   r@   r7   c                <    t        | t              r| S t        |       S r0   )r1   r   r3   s    r5   _convert_KerningrD   J   r=   r7   Fontc                    | j                   S r0   )_kerningselfs    r5   _get_kerningrJ   N   s    ==r7   c                $    t        |      | _        y r0   )rD   rG   rI   r4   s     r5   _set_kerningrM   R   s    $U+DMr7   T)kw_onlyc                     e Zd ZU dZ eej                  eddi      Zde	d<   	  ee
e      Zde	d	<   	  eee      Zd
e	d<   	  ee      Zde	d<   	  eee      Zde	d<   	  eee      Zde	d<   	  eee      Zde	d<   	  eee      Zde	d<   	  eee      Zde	d<   	  eddd      Zde	d<    eddd      Z de	d<    eddd      Z!de	d <    eddd      Z"d!e	d"<   e#dEdFd#       Z$e#dGdHd$       Z%dId%Z&dJd&Z'dKd'Z(dLd(Z)dMd)Z*dNd*Z+dOdPd+Z,dQd,Z-dRd-Z.dSd.Z/dTd/Z0dUd0Z1dVd1Z2dVd2Z3e4dWd3       Z5dRd4Z6e7Z8e9Z:e;Z<e4dXd5       Z=e=j|                  dYd6       Z=e4dZd7       Z?e?j|                  d[d8       Z? e4e@eA      ZB e4eCeD      ZE e4eFeG      ZHd\d9ZIe4d]d:       ZJe4d^d;       ZKe4d^d<       ZLd_d=ZMdKd>ZNd`d?ZOdadbd@ZPdadbdAZQdcdBZRdOdddCZS	 	 	 	 	 de	 	 	 	 	 	 	 	 	 	 	 dfdDZTy)grE   a  A data class representing a single Unified Font Object (UFO).

    Font uses :class:`fontTools.ufoLib.UFOReader` and
    :class:`fontTools.ufoLib.UFOWriter` to read and write UFO data from and to disk.
    It will default to reading lazily, loading glyphs, data and images as they are
    accessed. Copying a font implicitly loads everything eagerly before.

    The data model is formally specified at
    http://unifiedfontobject.org/versions/ufo3/index.html.

    Parameters:
        layers (LayerSet): A mapping of layer names to Layer objects.
        info (Info): The font Info object.
        features (Features): The font Features object.
        groups (Dict[str, List[str]]): A mapping of group names to a list of glyph
            names.
        kerning (Dict[Tuple[str, str], float]): A mapping of a tuple of first and
            second kerning pair to a kerning value.
        lib (Dict[str, Any]): A mapping of keys to arbitrary values.
        data (DataSet): A mapping of data file paths to arbitrary data.
        images (ImageSet): A mapping of image file paths to arbitrary image data.
        tempLib (Dict[str, Any]): A temporary mapping of keys to arbitrary values
            which unlike lib are *not* saved to disk.

    Behavior:
        The Font object has some dict-like behavior for quick access to glyphs on the
        the default layer. For example, to get a glyph by name from the default layer::

            glyph = font["aGlyphName"]

        To iterate over all glyphs in the default layer::

            for glyph in font:
                pass

        To get the number of glyphs in the default layer::

            glyphCount = len(font)

        To find out if a font contains a particular glyph in the default layer by name::

            exists = "aGlyphName" in font

        To remove a glyph from the default layer by name::

            del font["aGlyphName"]

        To replace a glyph in the default layer with another :class:`.Glyph` object::

            font["aGlyphName"] = otherGlyph

        To copy a font::

            import copy
            fontCopy = copy.deepcopy(font)

        Layers behave the same, for when you're working on something other than the
        default layer.
    omit_if_defaultF)factory	convertermetadatar   layers)rQ   rR   r   infor   features)rQ   zDict[str, List[str]]groupsr   rG   r   _libr   datar   images_tempLibN)defaulteqinitzOptional[PathLike]_path)r\   r^   r]   zOptional[bool]_lazyzOptional[UFOReader]_readerzOptional[UFOFileStructure]_fileStructurec                x    t        ||      }| j                  ||      }||_        |s|j                          |S )a  Instantiates a new Font object from a path to a UFO.

        Args:
            path: The path to the UFO to load.
            lazy: If True, load glyphs, data files and images as they are accessed. If
                False, load everything up front.
            validate: If True, enable UFO data model validation during loading. If
                False, load whatever is deserializable.
        )validatelazy)r   readr_   close)clspathrf   rd   readerrI   s         r5   openz	Font.open   s:     4(3xxTx*
LLNr7   c                    | t        j                  ||      t        j                  ||      t        j                  ||      t	        j                  |      t        |j                               |j                         t        |j                               t        |j                                     }||_        |j                  |_        |r||_        |S )a  Instantiates a Font object from a :class:`fontTools.ufoLib.UFOReader`.

        Args:
            path: The path to the UFO to load.
            lazy: If True, load glyphs, data files and images as they are accessed. If
                False, load everything up front.
        re   )rT   rY   rZ   rU   rV   rW   kerninglib)r   rg   r   r   r   r   readFeatures
readGroupsr   readKerningr   readLibr`   fileStructurerb   ra   )ri   rk   rf   rI   s       r5   rg   z	Font.read   s     ==d3f40==d36"f1134$$&F..01FNN$%	
 
$22!DLr7   c                2    || j                   j                  v S r0   rT   _defaultLayerrI   names     r5   __contains__zFont.__contains__   s    t{{0000r7   c                2    | j                   j                  |= y r0   rv   rx   s     r5   __delitem__zFont.__delitem__   s    KK%%d+r7   c                4    | j                   j                  |   S r0   rv   rx   s     r5   __getitem__zFont.__getitem__   s    {{((..r7   c                6    || j                   j                  |<   y r0   rv   )rI   ry   glyphs      r5   __setitem__zFont.__setitem__   s    */!!$'r7   c                @    t        | j                  j                        S r0   )iterrT   rw   rH   s    r5   __iter__zFont.__iter__   s    DKK--..r7   c                @    t        | j                  j                        S r0   )lenrT   rw   rH   s    r5   __len__zFont.__len__   s    4;;,,--r7   c                N    | j                   j                  j                  ||      S )zwReturn the :class:`.Glyph` object for name if it is present in the
        default layer, otherwise return ``default``.)rT   rw   get)rI   ry   r\   s      r5   r   zFont.get   s!     {{((,,T7;;r7   c                J    | j                   j                  j                         S )z2Return a list of glyph names in the default layer.)rT   rw   keysrH   s    r5   r   z	Font.keys   s    {{((--//r7   c                R    | j                   | j                   j                          yy)z\Closes the UFOReader if it still exists to finalize any outstanding
        file operations.N)ra   rh   rH   s    r5   rh   z
Font.close  s#     <<#LL  $r7   c                    | S r0   r9   rH   s    r5   	__enter__zFont.__enter__
  s    r7   c                $    | j                          y r0   )rh   )rI   exc_type	exc_valueexc_tbs       r5   __exit__zFont.__exit__  s    

r7   c           
     d   t        t        d | j                  j                  | j                  j                  g            }|r dj                  dj                  |            nd}dj                  | j                  j                  | j                  j                  |t        t        |                   S )Nz '{}'  z<{}.{}{} at {}>)listfilterrU   
familyName	styleNameformatjoin	__class__
__module____name__hexid)rI   namesfontNames      r5   __repr__zFont.__repr__  s    VD499#7#79L9L"MNO6;7>>#((5/2 ''NN%%t~~'>'>#bQUh-
 	
r7   c           	        |j                   | j                   urt        S t        t        |      }| |fD ]  }|j                  s|j                          ! | j                  | j                  | j                  | j                  | j                  | j                  | j                  | j                  f|j                  |j                  |j                  |j                  |j                  |j                  |j                  |j                  fk(  S r0   )r   NotImplementedr   rE   r`   unlazifyrT   rU   rV   rW   rn   ro   rY   rZ   )rI   otherfonts      r5   __eq__zFont.__eq__  s     ??$..0!!T5!5M 	 Dzz	 
 KKIIMMKKLLHHIIKK	
 LLJJNNLLMMIIJJLL	

 	
r7   c                F    | j                  |      }|t        u rt        S | S r0   )r   r   )rI   r   results      r5   __ne__zFont.__ne__8  s&    U#^#!!zr7   c                    | j                   S )z;Returns the underlying :class:`fontTools.ufoLib.UFOReader`.)ra   rH   s    r5   rk   zFont.reader>  s     ||r7   c                    | j                   r\| j                  J | j                  j                          | j                  j                          | j
                  j                          d| _         y)z`Load all glyphs, data files and images if the Font object loaded
        them lazily previously.NF)r`   ra   rT   r   rY   rZ   rH   s    r5   r   zFont.unlazifyC  sR     ::<<+++KK  "II KK  "
r7   c           	     v    t        t        t        t           | j                  j                  dg                   S )a  The font's glyph order.

        See http://unifiedfontobject.org/versions/ufo3/lib.plist/#publicglyphorder for
        semantics.

        Getter:
            Return the font's glyph order, if it is set in lib, or an empty list.

        Note:
            The getter always returns a new list, modifications to it do not change
            the lib content.

        Setter:
            Sets the font's glyph order. If ``value`` is None or an empty list, the
            glyph order key will be deleted from the lib if it exists.
        public.glyphOrder)r   r   r   strro   r   rH   s    r5   
glyphOrderzFont.glyphOrderR  s*    $ D#5H"(MNOOr7   c                |    |t        |      dk(  rd| j                  v r| j                  d= y y || j                  d<   y )Nr   r   )r   ro   rL   s     r5   r   zFont.glyphOrderf  s@    =CJ!O"dhh.HH01 / -2DHH()r7   c                ^    | j                   j                  g S | j                   j                  S )zThe font's global guidelines.

        Getter:
            Returns the font's global guidelines or an empty list.

        Setter:
            Appends the list of Guidelines to the global Guidelines.
                XXX Should it replace them?
        )rU   
guidelinesrH   s    r5   r   zFont.guidelinesn  s)     99'Iyy###r7   c                V    g | j                   _        |D ]  }| j                  |        y r0   )rU   r   appendGuideline)rI   r4   	guidelines      r5   r   zFont.guidelines}  s+    !		 	,I  +	,r7   c                .    t        | j                  |      S )a  Return the lib for an object with an identifier, as stored in a font's lib.

        If the object does not yet have an identifier, a new one is assigned to it. If
        the font lib does not yet contain the object's lib, a new one is inserted and
        returned.

        .. doctest::

            >>> from ufoLib2.objects import Font, Guideline
            >>> font = Font()
            >>> font.guidelines = [Guideline(x=100)]
            >>> guideline_lib = font.objectLib(font.guidelines[0])
            >>> guideline_lib["com.test.foo"] = 1234
            >>> guideline_id = font.guidelines[0].identifier
            >>> assert guideline_id is not None
            >>> assert font.lib["public.objectLibs"][guideline_id] is guideline_lib
        )r(   ro   )rI   objects     r5   	objectLibzFont.objectLib  s    & 488V,,r7   c                    | j                   S )z3Return the path of the UFO, if it was set, or None.)r_   rH   s    r5   rj   z	Font.path  s     zzr7   c                B    | j                   j                  j                  S )zReturns the (xMin, yMin, xMax, yMax) bounding box of the default
        layer, taking the actual contours into account.

        |defcon_compat|
        )rT   rw   boundsrH   s    r5   r   zFont.bounds  s     {{((///r7   c                B    | j                   j                  j                  S )zReturns the (xMin, yMin, xMax, yMax) bounding box of the layer,
        taking only the control points into account.

        |defcon_compat|
        )rT   rw   controlPointBoundsrH   s    r5   r   zFont.controlPointBounds  s     {{((;;;r7   c                N    | j                   j                  j                  |       y)zAppends glyph object to the default layer unless its name is already
        taken.

        Note:
            Call the method on the layer directly if you want to overwrite entries
            with the same name or append copies of the glyph.
        N)rT   rw   addGlyph)rI   r   s     r5   r   zFont.addGlyph  s     	!!**51r7   c                L    | j                   j                  j                  |      S )zRCreates and returns new :class:`.Glyph` object in default layer with
        name.)rT   rw   newGlyphrx   s     r5   r   zFont.newGlyph  s     {{((11$77r7   c                <     | j                   j                  |fi |S )zCreates and returns a new :class:`.Layer`.

        Args:
            name: The name of the new layer.
            kwargs: The arguments passed to the Layer object constructor.
        )rT   newLayer)rI   ry   kwargss      r5   r   zFont.newLayer  s      $t{{##D3F33r7   c                R    | j                   j                  j                  |||       y)a4  Renames a :class:`.Glyph` object in the default layer.

        Args:
            name: The old name.
            newName: The new name.
            overwrite: If False, raises exception if newName is already taken.
                If True, overwrites (read: deletes) the old :class:`.Glyph` object.
        N)rT   rw   renameGlyphrI   ry   newName	overwrites       r5   r   zFont.renameGlyph  s      	!!--dGYGr7   c                >    | j                   j                  |||       y)a  Renames a :class:`.Layer`.

        Args:
            name: The old name.
            newName: The new name.
            overwrite: If False, raises exception if newName is already taken.
                If True, overwrites (read: deletes) the old :class:`.Layer` object.
        N)rT   renameLayerr   s       r5   r   zFont.renameLayer  s     	gy9r7   c                6   t        |t              s=t        |t              s"t        ddt	        |      j
                         t        di |}| j                  j                  g | j                  _        | j                  j                  j                  |       y)a  Appends a guideline to the list of the font's global guidelines.

        Creates the global guideline list unless it already exists.

        Args:
            guideline: A :class:`.Guideline` object or a mapping for the Guideline
                constructor.
        z/Expected Guideline object or a Mapping for the zGuideline constructor, found Nr9   )	r1   r   r
   	TypeErrortyper   rU   r   append)rI   r   s     r5   r   zFont.appendGuideline  s     )Y/i1E3DO4L4L3MN  ".I.I99'#%DII 		##I.r7   c                   || j                   |u}| j                  j                  j                  t        k7  rt        | j                  j
                  vsJ |j                  | j                  j                         |j                  | j                         |j                  | j                         |j                  | j                         t        | j                   | j"                  D ch c]  }|j$                  |j$                   c}       |j'                  | j                          | j                  j)                  ||       | j*                  j)                  ||       | j,                  j)                  ||       yc c}w )ac  Writes this Font to a :class:`fontTools.ufoLib.UFOWriter`.

        Args:
            writer: The :class:`fontTools.ufoLib.UFOWriter` to write to.
            saveAs: If True, tells the writer to save out-of-place. If False, tells the
                writer to save in-place. This affects how resources are cleaned before
                writing.
        NsaveAs)ra   rT   rw   ry   r   
layerOrderwriteFeaturesrV   textwriteGroupsrW   	writeInforU   writeKerningrn   r)   ro   r   
identifierwriteLibwriterY   rZ   )rI   writerr   gs       r5   r   z
Font.write  s    >\\/F;;$$))-??%T[[-C-CCCCT]]//04;;'#DLL)HH#'??Oaall6NQ\\O	
 	!&0		v.&0 Ps   *F
<F
c                >   |dk7  rt        d|       |t        |      }n| j                  | j                  }|Vt        |t        j
                  j                        s2t        j                  j                  t        j                  |            }dx}}|du}|rt        |t              rt        j                  j                  |      r|rO|}t        j                  j                         }|j                  t        j                  j!                  |            }n@ddl}	t%        |	j&                  d|z        | j                  t)        d      | j                  }	 t+        |||      5 }
| j-                  |
|       ddd       
j/                          |t        |t              sJ t        j                  j1                  |      rt3        j4                  |       n4t        j                  j7                  |      rt        j8                  |       t3        j:                  ||       |}	 ||j?                          	 t        |t        j
                  j                        s|| _         yy# 1 sw Y   xY w# t<        $ r  w xY w# ||j?                          w w xY w)	a  Saves the font to ``path``.

        Args:
            path: The target path. If it is None, the path from the last save (except
                when that was a ``fs.base.FS``) or when the font was first opened will
                be used.
            formatVersion: The version to save the UFO as. Only version 3 is supported
                currently.
            structure (fontTools.ufoLib.UFOFileStructure): How to store the UFO.
                Can be either None, "zip" or "package". If None, it tries to use the
                same structure as the original UFO at the output path. If "zip", the
                UFO will be saved as compressed archive. If "package", it is saved as
                a regular folder or "package".
            overwrite: If False, raises OSError when the target path exists. If True,
                overwrites the target path.
            validate: If True, will validate the data in Font before writing it out. If
                False, will write out whatever is serializable.
           zunsupported format version: Nr   zpath %r already existsz)'path' is required when saving a new Font)	structurerd   r   )!NotImplementedErrorr   rb   r1   fsbaseFSosrj   normpathfspathr   existstempfsTempFS
getsyspathbasenameerrnoOSErrorEEXISTr   r   r   setModificationTimeisdirshutilrmtreeisfileremovemove	Exceptionrh   r_   )rI   rj   formatVersionr   r   rd   overwritePathtmpr   r   r   s              r5   savez	Font.save  s   4 A%(D]O&TUU  (3I  ,++I JtRWWZZ$@77##BIIdO4D""T!$$)=$(M))**,C>>"''*:*:4*@AD !%,,0H40OPPYYGHH99D	49xH 2F

6&
12&&( (!$,,, 77==/MM-0WW^^M2IIm,D-0$ 		 $

+DJ ,52 2  		 		 s7   I9 +I-?I9 BJ -I62I9 9JJ J)TT)rj   r-   rf   boolrd   r   returnrE   )T)rk   r   rf   r   r  rE   )ry   r   r  r   )ry   r   r  None)ry   r   r  r   )ry   r   r   r   r  r  )r  zIterator[Glyph])r  intr0   )ry   r   r\   zT | Noner  zT | Glyph | None)r  zKeysView[str])r  r  )r  rE   )r   r   r   r   r   r   r  r  )r  r   )r   r   r  r   )r  zUFOReader | None)r  z	list[str])r4   zlist[str] | Noner  r  )r  zlist[Guideline])r4   z'Iterable[Guideline | Mapping[str, Any]]r  r  )r   r,   r  zdict[str, Any])r  zPathLike | None)r  zBoundingBox | None)r   r   r  r  )ry   r   r   r   r  r   )F)ry   r   r   r   r   r   r  r  )r   zGuideline | Mapping[str, Any]r  r  )r   r   r   zbool | Noner  r  )Nr   NFT)rj   zPathLike | fs.base.FS | Noner   r  r   zUFOFileStructure | Noner   r   rd   r   r  r  )Ur   r   __qualname____doc__r   r   r\   r6   rT   __annotations__r   r:   rU   r   rB   rV   dictrW   r   rD   rG   r   r    rX   r   r<   rY   r   r?   rZ   r[   r_   r`   ra   rb   classmethodrl   rg   rz   r|   r~   r   r   r   r   r   rh   r   r   r   r   r   propertyrk   r   r&   __deepcopy__r'   __getstate__r*   __setstate__r   setterr   rJ   rM   rn   r!   r#   ro   r"   r$   tempLibr   rj   r   r   r   r   r   r   r   r   r   r   r9   r7   r5   rE   rE   V   s	   :x   ##U+FH 
 ?t}=D$=%x;LMHhM-#(#6F 6Rg9IJHgJ  c\:D#:Q'5EFD'FBX9JKFHKJ#>Hc>O !&du5 IEI!$UuEE>E#(Ee#LG L165U2N.   "  21,/0/.<
0!

@   ,L+L"LP P& 2 2 $ $ , ,
 |\2G
8X
&C|\2G-*   0 0 < <28
4	H	:/(1@ .2-1V*V V +	V
 V V 
Vr7   )r4   zLayerSet | Iterable[Layer]r  r   )r4   zInfo | Mapping[str, Any]r  r   )r4   z$DataSet | MutableMapping[str, bytes]r  r   )r4   z%ImageSet | MutableMapping[str, bytes]r  r   )r4   zFeatures | strr  r   )r4   Mapping[KerningPair, float]r  r   )rI   rE   r  r   )rI   rE   r4   r  r  r  )L
__future__r   r   r   typingr   r   r   r   r   r	   r
   r   r   r   r   fs.baser   	fs.tempfsattrsr   r   fontTools.ufoLibr   r   r   ufoLib2.constantsr   ufoLib2.objects.dataSetr   ufoLib2.objects.featuresr   ufoLib2.objects.glyphr   ufoLib2.objects.guideliner   ufoLib2.objects.imageSetr   ufoLib2.objects.infor   ufoLib2.objects.kerningr   r   ufoLib2.objects.layerr   ufoLib2.objects.layerSetr   ufoLib2.objects.libr   r    r!   r"   r#   r$   ufoLib2.objects.miscr%   r&   r'   r(   r)   r*   ufoLib2.serder+   ufoLib2.typingr,   r-   r.   r6   r:   r<   r?   rB   rD   rJ   rM   rE   r9   r7   r5   <module>r$     s    " 	        C C 0 + - ' / - % 8 ' -     5 5S?CEEC, S S  Sr7   