a
    w=icÔ ã                   @  s6  d dl mZ d dlZd dlZd dlZd dlZd dlZd dlZd dlm	Z	m
Z
 d dlmZ d dlmZmZmZmZmZ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mZ g d
¢ZdZ e d Z!dd„ Z"dd„ Z#G dd„ de$ƒZ%G dd„ de&ƒZ'G dd„ de'ƒZ(G dd„ de(ƒZ)G dd„ de(ƒZ*dd„ Z+dd„ Z,dd „ Z-ee.ee/ee/e/f f f Z0ee.e/f Z1G d!d"„ d"e(ƒZ2d#d$„ Z3G d%d&„ d&e(ƒZ4G d'd(„ d(e4ƒZ5G d)d*„ d*e4ƒZ6G d+d,„ d,e(ƒZ7G d-d.„ d.e(ƒZ8G d/d0„ d0e(ƒZ9G d1d2„ d2e(ƒZ:G d3d4„ d4e(ƒZ;G d5d6„ d6e&ƒZ<G d7d8„ d8eƒZ=G d9d:„ d:ee'ƒZ>dS );é    )ÚannotationsN)ÚBytesIOÚStringIO)Úindent)ÚAnyÚDictÚListÚMutableMappingÚOptionalÚTupleÚUnionÚcast)Úetree)Úplistlib)ÚLogMixin)ÚtobytesÚtostr)ÚAxisDescriptorÚAxisLabelDescriptorÚBaseDocReaderÚBaseDocWriterÚDesignSpaceDocumentÚDesignSpaceDocumentErrorÚDiscreteAxisDescriptorÚInstanceDescriptorÚLocationLabelDescriptorÚRangeAxisSubsetDescriptorÚRuleDescriptorÚSourceDescriptorÚValueAxisSubsetDescriptorÚVariableFontDescriptorz&{http://www.w3.org/XML/1998/namespace}Úlangc                 C  s>   t j|  tjj¡Ž }|  d¡r(d| }n|  d¡r:d| }|S )z<Normalize paths using forward slash to work also on Windows.ú/z\\z//)Ú	posixpathÚjoinÚsplitÚosÚpathÚsepÚ
startswith)r'   Únew_path© r+   úr/home/droni/.local/share/virtualenvs/DPS-5Je3_V2c/lib/python3.9/site-packages/fontTools/designspaceLib/__init__.pyÚposix/   s    


r-   c                   s"   ‡ fdd„}‡ fdd„}t ||ƒS )zBGenerate a propery that holds a path always using forward slashes.c                   s
   t | ˆ ƒS ©N)Úgetattr©Úself©Úprivate_namer+   r,   Úgetter=   s    z"posixpath_property.<locals>.getterc                   s    |d urt |ƒ}t| ˆ |ƒ d S r.   )r-   Úsetattr©r1   Úvaluer2   r+   r,   ÚsetterA   s    z"posixpath_property.<locals>.setter)Úproperty)r3   r4   r8   r+   r2   r,   Úposixpath_property;   s    r:   c                   @  s   e Zd Zddd„Zdd„ ZdS )r   Nc                 C  s   || _ || _d S r.   )ÚmsgÚobj)r1   r;   r<   r+   r+   r,   Ú__init__K   s    z!DesignSpaceDocumentError.__init__c                 C  s"   t | jƒ| jd urd| j nd S )Nz: %rÚ )Ústrr;   r<   r0   r+   r+   r,   Ú__str__O   s    ÿz DesignSpaceDocumentError.__str__)N)Ú__name__Ú
__module__Ú__qualname__r=   r@   r+   r+   r+   r,   r   J   s   
r   c                   @  s   e Zd Zdd„ ZdS )ÚAsDictMixinc                 C  s\   i }| j  ¡ D ]H\}}| d¡r"qt|dƒr6| ¡ }nt|tƒrNdd„ |D ƒ}|||< q|S )NÚ_Úasdictc                 S  s"   g | ]}t |d ƒr| ¡ n|‘qS )rF   )ÚhasattrrF   ©Ú.0Úvr+   r+   r,   Ú
<listcomp>^   s   z&AsDictMixin.asdict.<locals>.<listcomp>)Ú__dict__Úitemsr)   rG   rF   Ú
isinstanceÚlist)r1   ÚdÚattrr7   r+   r+   r,   rF   V   s    



ÿ
zAsDictMixin.asdictN)rA   rB   rC   rF   r+   r+   r+   r,   rD   T   s   rD   c                   @  s    e Zd ZdZdd„ Zdd„ ZdS )ÚSimpleDescriptorz% Containers for a bunch of attributesc                 C  s\   | j D ]P}zt| |ƒt||ƒks$J ‚W q tyT   td|t| |ƒdt||ƒƒ Y q0 qd S )Nzfailed attributez!=)Ú_attrsr/   ÚAssertionErrorÚprint)r1   ÚotherrQ   r+   r+   r,   Úcomparej   s
    
zSimpleDescriptor.comparec                   s8   ‡ fdd„ˆ j D ƒ}td |¡dƒ}ˆ jj› d|› dS )Nc                   s&   g | ]}|› d t tˆ |ƒƒ› d‘qS )ú=ú,)Úreprr/   )rI   Úar0   r+   r,   rK   s   ó    z-SimpleDescriptor.__repr__.<locals>.<listcomp>Ú
ú    z(
z
))rS   r   r$   Ú	__class__rA   )r1   Úattrsr+   r0   r,   Ú__repr__r   s    zSimpleDescriptor.__repr__N)rA   rB   rC   Ú__doc__rW   ra   r+   r+   r+   r,   rR   e   s   rR   c                   @  sž   e Zd ZdZdZg d¢ZedƒZedƒZddddddddddddddddddœd	d
„Z	e
dd„ ƒZejddœdd„ƒZddd„Zddd„Zdddœdd„ZdS )r   u  Simple container for data related to the source

    .. code:: python

        doc = DesignSpaceDocument()
        s1 = SourceDescriptor()
        s1.path = masterPath1
        s1.name = "master.ufo1"
        s1.font = defcon.Font("master.ufo1")
        s1.location = dict(weight=0)
        s1.familyName = "MasterFamilyName"
        s1.styleName = "MasterStyleNameOne"
        s1.localisedFamilyName = dict(fr="CaractÃ¨re")
        s1.mutedGlyphNames.append("A")
        s1.mutedGlyphNames.append("Z")
        doc.addSource(s1)

    Úsource)Úfilenamer'   ÚnameÚ	layerNameÚlocationÚcopyLibÚ
copyGroupsÚcopyFeaturesÚmuteKerningÚmuteInfoÚmutedGlyphNamesÚ
familyNameÚ	styleNameÚlocalisedFamilyNameÚ	_filenameÚ_pathNF)rd   r'   Úfontre   rg   ÚdesignLocationrf   rn   ro   rp   rh   ÚcopyInfori   rj   rk   rl   rm   c                C  s|   || _ || _|| _|| _|d ur$|n|p*i | _|| _|| _|	| _|
pFi | _|| _	|| _
|| _|| _|| _|| _|ptg | _d S r.   )rd   r'   rs   re   rt   rf   rn   ro   rp   rh   ru   ri   rj   rk   rl   rm   )r1   rd   r'   rs   re   rg   rt   rf   rn   ro   rp   rh   ru   ri   rj   rk   rl   rm   r+   r+   r,   r=   –   s"    
	
zSourceDescriptor.__init__c                 C  s   | j S )zÕdict. Axis values for this source, in design space coordinates.

        MutatorMath + Varlib.

        .. deprecated:: 5.0
           Use the more explicit alias for this property :attr:`designLocation`.
        ©rt   r0   r+   r+   r,   rg     s    	zSourceDescriptor.locationú!Optional[AnisotropicLocationDict]©rg   c                 C  s   |pi | _ d S r.   rv   ©r1   rg   r+   r+   r,   rg   )  s    Úenc                 C  s   t |ƒ| j|< dS )zNSetter for :attr:`localisedFamilyName`

        .. versionadded:: 5.0
        N©r   rp   ©r1   rn   ÚlanguageCoder+   r+   r,   ÚsetFamilyName-  s    zSourceDescriptor.setFamilyNamec                 C  s   | j  |¡S )zNGetter for :attr:`localisedFamilyName`

        .. versionadded:: 5.0
        ©rp   Úget©r1   r}   r+   r+   r,   ÚgetFamilyName4  s    zSourceDescriptor.getFamilyNameú'DesignSpaceDocument'ÚAnisotropicLocationDict©ÚdocÚreturnc                 C  sF   i }|j D ]6}|j| jv r.| j|j ||j< q
| |j¡||j< q
|S )z¢Get the complete design location of this source, from its
        :attr:`designLocation` and the document's axis defaults.

        .. versionadded:: 5.0
        )Úaxesre   rt   Úmap_forwardÚdefault)r1   r†   ÚresultÚaxisr+   r+   r,   ÚgetFullDesignLocation<  s    
z&SourceDescriptor.getFullDesignLocation)rz   )rz   )rA   rB   rC   rb   ÚflavorrS   r:   rd   r'   r=   r9   rg   r8   r~   r‚   r   r+   r+   r+   r,   r   x   s>   í 	



r   c                   @  s*   e Zd ZdZg d¢Zddddœdd„ZdS )r   aË  Represents the rule descriptor element: a set of glyph substitutions to
    trigger conditionally in some parts of the designspace.

    .. code:: python

        r1 = RuleDescriptor()
        r1.name = "unique.rule.name"
        r1.conditionSets.append([dict(name="weight", minimum=-10, maximum=10), dict(...)])
        r1.conditionSets.append([dict(...), dict(...)])
        r1.subs.append(("a", "a.alt"))

    .. code:: xml

        <!-- optional: list of substitution rules -->
        <rules>
            <rule name="vertical.bars">
                <conditionset>
                    <condition minimum="250.000000" maximum="750.000000" name="weight"/>
                    <condition minimum="100" name="width"/>
                    <condition minimum="10" maximum="40" name="optical"/>
                </conditionset>
                <sub name="cent" with="cent.alt"/>
                <sub name="dollar" with="dollar.alt"/>
            </rule>
        </rules>
    ©re   ÚconditionSetsÚsubsNc                C  s   || _ |pg | _|pg | _d S r.   r   )r1   re   r   r‘   r+   r+   r,   r=   h  s    

zRuleDescriptor.__init__)rA   rB   rC   rb   rS   r=   r+   r+   r+   r,   r   K  s   r   c                   s   t ‡ fdd„| jD ƒƒS )zJReturn True if any of the rule's conditionsets matches the given location.c                 3  s   | ]}t |ˆ ƒV  qd S r.   )ÚevaluateConditions)rI   Úcrx   r+   r,   Ú	<genexpr>€  r\   zevaluateRule.<locals>.<genexpr>)Úanyr   )Úrulerg   r+   rx   r,   ÚevaluateRule~  s    r—   c                 C  s‚   | D ]x}||d  }|  d¡du r6||d kr| dS q|  d¡du rX|d |kr| dS q|d |  krt|d ksn  dS qdS )z·Return True if all the conditions matches the given location.

    - If a condition has no minimum, check for < maximum.
    - If a condition has no maximum, check for > minimum.
    re   ÚminimumNÚmaximumFT)r€   )Ú
conditionsrg   Úcdr7   r+   r+   r,   r’   ƒ  s    r’   c           	      C  sl   g }| D ]^}t ||ƒr|D ]B}d}|jD ]\}}||kr(d} qBq(|rR| |¡ q| |¡ q|}g }q|S )z—Apply these rules at this location to these glyphnames.

    Return a new list of glyphNames with substitutions applied.

    - rule order matters
    FT)r—   r‘   Úappend)	Úrulesrg   Z
glyphNamesZnewNamesr–   re   Zswapr[   Úbr+   r+   r,   ÚprocessRules–  s    
rŸ   c                   @  s  e Zd ZdZdZdZg d¢ZedƒZedƒZ	dddddddddddddddddddddd	œd
d„Z
edd„ ƒZejddœdd„ƒZd0dd„Zd1dd„Zd2dd„Zd3dd„Zd4dd„Zd5dd„Zd6dd„Zd7dd „Zd8d!d"œd#d$„Zd%d&d'œd(d)„Zd%d*d'œd+d,„Zd%d-d'œd.d/„ZdS )9r   a€  Simple container for data related to the instance


    .. code:: python

        i2 = InstanceDescriptor()
        i2.path = instancePath2
        i2.familyName = "InstanceFamilyName"
        i2.styleName = "InstanceStyleName"
        i2.name = "instance.ufo2"
        # anisotropic location
        i2.designLocation = dict(weight=500, width=(400,300))
        i2.postScriptFontName = "InstancePostscriptName"
        i2.styleMapFamilyName = "InstanceStyleMapFamilyName"
        i2.styleMapStyleName = "InstanceStyleMapStyleName"
        i2.lib['com.coolDesignspaceApp.specimenText'] = 'Hamburgerwhatever'
        doc.addInstance(i2)
    Úinstancerz   )rd   r'   re   ÚlocationLabelrt   ÚuserLocationrn   ro   ÚpostScriptFontNameÚstyleMapFamilyNameÚstyleMapStyleNamerp   ÚlocalisedStyleNameÚlocalisedStyleMapFamilyNameÚlocalisedStyleMapStyleNameÚglyphsÚkerningÚinfoÚlibrq   rr   NT)rd   r'   rs   re   rg   r¡   rt   r¢   rn   ro   r£   r¤   r¥   rp   r¦   r§   r¨   r©   rª   r«   r¬   c                C  s¨   || _ || _|| _|| _|| _|d ur*|n|p0i | _|p:i | _|	| _|
| _|| _	|| _
|| _|pbi | _|pli | _|pvi | _|p€i | _|pŠi | _|| _|| _|p i | _d S r.   )rd   r'   rs   re   r¡   rt   r¢   rn   ro   r£   r¤   r¥   rp   r¦   r§   r¨   r©   rª   r«   r¬   )r1   rd   r'   rs   re   rg   r¡   rt   r¢   rn   ro   r£   r¤   r¥   rp   r¦   r§   r¨   r©   rª   r«   r¬   r+   r+   r,   r=   ß  s*    







zInstanceDescriptor.__init__c                 C  s   | j S )zºdict. Axis values for this instance.

        MutatorMath + Varlib.

        .. deprecated:: 5.0
           Use the more explicit alias for this property :attr:`designLocation`.
        rv   r0   r+   r+   r,   rg   u  s    	zInstanceDescriptor.locationrw   rx   c                 C  s   |pi | _ d S r.   rv   ry   r+   r+   r,   rg   €  s    c                 C  s   t |ƒ| j|< dS )z8These methods give easier access to the localised names.N)r   r¦   )r1   ro   r}   r+   r+   r,   ÚsetStyleName„  s    zInstanceDescriptor.setStyleNamec                 C  s   | j  |¡S r.   )r¦   r€   r   r+   r+   r,   ÚgetStyleNameˆ  s    zInstanceDescriptor.getStyleNamec                 C  s   t |ƒ| j|< d S r.   r{   r|   r+   r+   r,   r~   ‹  s    z InstanceDescriptor.setFamilyNamec                 C  s   | j  |¡S r.   r   r   r+   r+   r,   r‚   Ž  s    z InstanceDescriptor.getFamilyNamec                 C  s   t |ƒ| j|< d S r.   )r   r¨   )r1   r¥   r}   r+   r+   r,   ÚsetStyleMapStyleName‘  s    z'InstanceDescriptor.setStyleMapStyleNamec                 C  s   | j  |¡S r.   )r¨   r€   r   r+   r+   r,   ÚgetStyleMapStyleName”  s    z'InstanceDescriptor.getStyleMapStyleNamec                 C  s   t |ƒ| j|< d S r.   )r   r§   )r1   r¤   r}   r+   r+   r,   ÚsetStyleMapFamilyName—  s    z(InstanceDescriptor.setStyleMapFamilyNamec                 C  s   | j  |¡S r.   )r§   r€   r   r+   r+   r,   ÚgetStyleMapFamilyNameš  s    z(InstanceDescriptor.getStyleMapFamilyNamezOptional[str])ÚaxisNamec                 C  sd   d| _ |du ri | _i | _nD| jdu r,i | _|| jv r>| j|= | jdu rNi | _|| jv r`| j|= dS )a•  Clear all location-related fields. Ensures that
        :attr:``designLocation`` and :attr:``userLocation`` are dictionaries
        (possibly empty if clearing everything).

        In order to update the location of this instance wholesale, a user
        should first clear all the fields, then change the field(s) for which
        they have data.

        .. code:: python

            instance.clearLocation()
            instance.designLocation = {'Weight': (34, 36.5), 'Width': 100}
            instance.userLocation = {'Opsz': 16}

        In order to update a single axis location, the user should only clear
        that axis, then edit the values:

        .. code:: python

            instance.clearLocation('Weight')
            instance.designLocation['Weight'] = (34, 36.5)

        Args:
          axisName: if provided, only clear the location for that axis.

        .. versionadded:: 5.0
        N)r¡   rt   r¢   )r1   r³   r+   r+   r,   ÚclearLocation  s    



z InstanceDescriptor.clearLocationrƒ   ú!Optional[LocationLabelDescriptor]r…   c                 C  s@   | j du rdS | | j ¡}|du r<td| j › d| j› dƒ‚|S )zÉGet the :class:`LocationLabelDescriptor` instance that matches
        this instances's :attr:`locationLabel`.

        Raises if the named label can't be found.

        .. versionadded:: 5.0
        NzIInstanceDescriptor.getLocationLabelDescriptor(): unknown location label `z` in instance `z`.)r¡   ÚgetLocationLabelr   re   )r1   r†   Úlabelr+   r+   r,   ÚgetLocationLabelDescriptorÇ  s    
ÿÿÿz-InstanceDescriptor.getLocationLabelDescriptorr„   c                 C  sŠ   |   |¡}|dur| |j¡S i }|jD ]\}|j| jv rL| j|j ||j< q(|j| jv rr| | j|j ¡||j< q(| |j¡||j< q(|S )a!  Get the complete design location of this instance, by combining data
        from the various location fields, default axis values and mappings, and
        top-level location labels.

        The source of truth for this instance's location is determined for each
        axis independently by taking the first not-None field in this list:

        - ``locationLabel``: the location along this axis is the same as the
          matching STAT format 4 label. No anisotropy.
        - ``designLocation[axisName]``: the explicit design location along this
          axis, possibly anisotropic.
        - ``userLocation[axisName]``: the explicit user location along this
          axis. No anisotropy.
        - ``axis.default``: default axis value. No anisotropy.

        .. versionadded:: 5.0
        N)r¸   r‰   r¢   rˆ   re   rt   rŠ   )r1   r†   r·   r‹   rŒ   r+   r+   r,   r   Ù  s    

z(InstanceDescriptor.getFullDesignLocationÚSimpleLocationDictc                 C  s   |  |  |¡¡S )zGet the complete user location for this instance.

        .. seealso:: :meth:`getFullDesignLocation`

        .. versionadded:: 5.0
        )Úmap_backwardr   ©r1   r†   r+   r+   r,   ÚgetFullUserLocationø  s    z&InstanceDescriptor.getFullUserLocation)rz   )rz   )rz   )rz   )rz   )rz   )rz   )rz   )N)rA   rB   rC   rb   rŽ   Z_defaultLanguageCoderS   r:   rd   r'   r=   r9   rg   r8   r­   r®   r~   r‚   r¯   r°   r±   r²   r´   r¸   r   r¼   r+   r+   r+   r,   r   ³  sZ   é 









*r   c                 C  s–   dt ddfdt ddfdt ddfdt d	dfd
t ddfdœ}|  ¡ |v rZ||  ¡  S t| ƒdk r|| ddt| ƒ   }n| d d… }|t | dfS )NZwghtZWeight)rz   ZwdthZWidthZopszzOptical SizeZslntZSlantZitalZItalic)ÚweightÚwidthZopticalZslantÚitalicé   Ú*)ÚdictÚlowerÚlen)re   ÚnamesÚtagr+   r+   r,   ÚtagForAxisName  s    ûrÇ   c                   @  s*   e Zd ZdZddddddddœdd„ZdS )ÚAbstractAxisDescriptorrŒ   NF©rÆ   re   Ú
labelNamesÚhiddenÚmapÚaxisOrderingÚ
axisLabelsc                C  s:   || _ || _|pi | _|| _|p"g | _|| _|p2g | _d S r.   rÉ   )r1   rÆ   re   rÊ   rË   rÌ   rÍ   rÎ   r+   r+   r,   r=     s    


zAbstractAxisDescriptor.__init__)rA   rB   rC   rŽ   r=   r+   r+   r+   r,   rÈ     s   ÷rÈ   c                      sX   e Zd ZdZg d¢Zdddddddddddœ
‡ fdd„
Zdd	„ Zd
d„ Zdd„ Z‡  Z	S )r   u0   Simple container for the axis data.

    Add more localisations?

    .. code:: python

        a1 = AxisDescriptor()
        a1.minimum = 1
        a1.maximum = 1000
        a1.default = 400
        a1.name = "weight"
        a1.tag = "wght"
        a1.labelNames['fa-IR'] = "Ù‚Ø·Ø±"
        a1.labelNames['en'] = "WÃ©Ã­ght"
        a1.map = [(1.0, 10.0), (400.0, 66.0), (1000.0, 990.0)]
        a1.axisOrdering = 1
        a1.axisLabels = [
            AxisLabelDescriptor(name="Regular", userValue=400, elidable=True)
        ]
        doc.addAxis(a1)
    )rÆ   re   r™   r˜   rŠ   rÌ   rÍ   rÎ   NF)
rÆ   re   rÊ   r˜   rŠ   r™   rË   rÌ   rÍ   rÎ   c       
      	     s0   t ƒ j||||||	|
d || _|| _|| _d S ©NrÉ   )Úsuperr=   r˜   r™   rŠ   )r1   rÆ   re   rÊ   r˜   rŠ   r™   rË   rÌ   rÍ   rÎ   ©r_   r+   r,   r=   j  s    ù	zAxisDescriptor.__init__c                 C  s0   t | j| j| j| j| j| j| j| j| j	| j
d
S )N)
rÆ   re   rÊ   r™   r˜   rŠ   rË   rÌ   rÍ   rÎ   )rÂ   rÆ   re   rÊ   r™   r˜   rŠ   rË   rÌ   rÍ   rÎ   r0   r+   r+   r,   Ú	serialize’  s    özAxisDescriptor.serializec                 C  s,   ddl m} | js|S ||dd„ | jD ƒƒS )z?Maps value from axis mapping's input (user) to output (design).r   ©ÚpiecewiseLinearMapc                 S  s   i | ]\}}||“qS r+   r+   ©rI   ÚkrJ   r+   r+   r,   Ú
<dictcomp>§  r\   z.AxisDescriptor.map_forward.<locals>.<dictcomp>)ÚfontTools.varLib.modelsrÔ   rÌ   ©r1   rJ   rÔ   r+   r+   r,   r‰   ¡  s    zAxisDescriptor.map_forwardc                 C  s>   ddl m} t|tƒr|d }| js(|S ||dd„ | jD ƒƒS )z?Maps value from axis mapping's output (design) to input (user).r   rÓ   c                 S  s   i | ]\}}||“qS r+   r+   rÕ   r+   r+   r,   r×   ±  r\   z/AxisDescriptor.map_backward.<locals>.<dictcomp>)rØ   rÔ   rN   ÚtuplerÌ   rÙ   r+   r+   r,   rº   ©  s    
zAxisDescriptor.map_backward)
rA   rB   rC   rb   rS   r=   rÒ   r‰   rº   Ú__classcell__r+   r+   rÑ   r,   r   R  s    ô(r   c                
      sN   e Zd ZdZdZdZddddddddddœ	‡ fdd„
Zd	d
„ Zdd„ Z‡  Z	S )r   a—  Container for discrete axis data.

    Use this for axes that do not interpolate. The main difference from a
    continuous axis is that a continuous axis has a ``minimum`` and ``maximum``,
    while a discrete axis has a list of ``values``.

    Example: an Italic axis with 2 stops, Roman and Italic, that are not
    compatible. The axis still allows to bind together the full font family,
    which is useful for the STAT table, however it can't become a variation
    axis in a VF.

    .. code:: python

        a2 = DiscreteAxisDescriptor()
        a2.values = [0, 1]
        a2.default = 0
        a2.name = "Italic"
        a2.tag = "ITAL"
        a2.labelNames['fr'] = "Italique"
        a2.map = [(0, 0), (1, -11)]
        a2.axisOrdering = 2
        a2.axisLabels = [
            AxisLabelDescriptor(name="Roman", userValue=0, elidable=True)
        ]
        doc.addAxis(a2)

    .. versionadded:: 5.0
    rŒ   )rÆ   re   ÚvaluesrŠ   rÌ   rÍ   rÎ   NF)	rÆ   re   rÊ   rÜ   rŠ   rË   rÌ   rÍ   rÎ   c       	   
   	     s.   t ƒ j|||||||	d || _|p&g | _d S rÏ   )rÐ   r=   rŠ   rÜ   )
r1   rÆ   re   rÊ   rÜ   rŠ   rË   rÌ   rÍ   rÎ   rÑ   r+   r,   r=   Õ  s    ù	
zDiscreteAxisDescriptor.__init__c                   s   t ‡ fdd„| jD ƒˆ ƒS )zðMaps value from axis mapping's input to output.

        Returns value unchanged if no mapping entry is found.

        Note: for discrete axes, each value must have its mapping entry, if
        you intend that value to be mapped.
        c                 3  s   | ]\}}|ˆ kr|V  qd S r.   r+   rÕ   ©r7   r+   r,   r”     r\   z5DiscreteAxisDescriptor.map_forward.<locals>.<genexpr>)ÚnextrÌ   r6   r+   rÝ   r,   r‰   û  s    z"DiscreteAxisDescriptor.map_forwardc                   s,   t ˆ tƒrˆ d ‰ t‡ fdd„| jD ƒˆ ƒS )zðMaps value from axis mapping's output to input.

        Returns value unchanged if no mapping entry is found.

        Note: for discrete axes, each value must have its mapping entry, if
        you intend that value to be mapped.
        r   c                 3  s   | ]\}}|ˆ kr|V  qd S r.   r+   rÕ   rÝ   r+   r,   r”     r\   z6DiscreteAxisDescriptor.map_backward.<locals>.<genexpr>)rN   rÚ   rÞ   rÌ   r6   r+   rÝ   r,   rº     s    
z#DiscreteAxisDescriptor.map_backward)
rA   rB   rC   rb   rŽ   rS   r=   r‰   rº   rÛ   r+   r+   rÑ   r,   r   ´  s   õ&
r   c                   @  sP   e Zd ZdZdZdZdddddddœdd„Zd	d
œdd„Zedd
œdd„ƒZ	dS )r   a§  Container for axis label data.

    Analogue of OpenType's STAT data for a single axis (formats 1, 2 and 3).
    All values are user values.
    See: `OTSpec STAT Axis value table, format 1, 2, 3 <https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-1>`_

    The STAT format of the Axis value depends on which field are filled-in,
    see :meth:`getFormat`

    .. versionadded:: 5.0
    r·   ©ÚuserMinimumÚ	userValueÚuserMaximumre   ÚelidableÚolderSiblingÚlinkedUserValuerÊ   NF)rà   râ   rã   rä   rå   rÊ   c          	      C  s8   || _ || _|| _|| _|| _|| _|| _|p0i | _d S r.   rß   )	r1   re   rá   rà   râ   rã   rä   rå   rÊ   r+   r+   r,   r=   "  s    
zAxisLabelDescriptor.__init__Úint©r‡   c                 C  s*   | j durdS | jdus"| jdur&dS dS )uD  Determine which format of STAT Axis value to use to encode this label.

        ===========  =========  ===========  ===========  ===============
        STAT Format  userValue  userMinimum  userMaximum  linkedUserValue
        ===========  =========  ===========  ===========  ===============
        1            âœ…          âŒ            âŒ            âŒ
        2            âœ…          âœ…            âœ…            âŒ
        3            âœ…          âŒ            âŒ            âœ…
        ===========  =========  ===========  ===========  ===============
        Né   é   é   )rå   rà   râ   r0   r+   r+   r,   Ú	getFormatG  s
    
zAxisLabelDescriptor.getFormatr?   c                 C  s   | j  d¡p| jS ©zDReturn the English name from :attr:`labelNames` or the :attr:`name`.rz   ©rÊ   r€   re   r0   r+   r+   r,   ÚdefaultNameX  s    zAxisLabelDescriptor.defaultName)
rA   rB   rC   rb   rŽ   rS   r=   rë   r9   rî   r+   r+   r+   r,   r     s   ö%r   c                   @  sL   e Zd ZdZdZdZddddœdd„Zed	d
œdd„ƒZdddœdd„Z	dS )r   a@  Container for location label data.

    Analogue of OpenType's STAT data for a free-floating location (format 4).
    All values are user values.

    See: `OTSpec STAT Axis value table, format 4 <https://docs.microsoft.com/en-us/typography/opentype/spec/stat#axis-value-table-format-4>`_

    .. versionadded:: 5.0
    r·   )re   rã   rä   r¢   rÊ   FN)rã   rä   rÊ   c                C  s*   || _ |pi | _|| _|| _|p"i | _d S r.   ©re   r¢   rã   rä   rÊ   )r1   re   r¢   rã   rä   rÊ   r+   r+   r,   r=   l  s    	

z LocationLabelDescriptor.__init__r?   rç   c                 C  s   | j  d¡p| jS rì   rí   r0   r+   r+   r,   rî   Ž  s    z#LocationLabelDescriptor.defaultNamerƒ   r¹   r…   c                   s   ‡ fdd„|j D ƒS )z¨Get the complete user location of this label, by combining data
        from the explicit user location and default axis values.

        .. versionadded:: 5.0
        c                   s"   i | ]}|j ˆ j |j |j¡“qS r+   )re   r¢   r€   rŠ   ©rI   rŒ   r0   r+   r,   r×   ™  s   ÿz?LocationLabelDescriptor.getFullUserLocation.<locals>.<dictcomp>©rˆ   r»   r+   r0   r,   r¼   “  s    
þz+LocationLabelDescriptor.getFullUserLocation)
rA   rB   rC   rb   rŽ   rS   r=   r9   rî   r¼   r+   r+   r+   r,   r   ^  s   
ù"r   c                   @  s2   e Zd ZdZdZdZedƒZddddœdd„ZdS )r    aò  Container for variable fonts, sub-spaces of the Designspace.

    Use-cases:

    - From a single DesignSpace with discrete axes, define 1 variable font
      per value on the discrete axes. Before version 5, you would have needed
      1 DesignSpace per such variable font, and a lot of data duplication.
    - From a big variable font with many axes, define subsets of that variable
      font that only include some axes and freeze other axes at a given location.

    .. versionadded:: 5.0
    úvariable-font)rd   ÚaxisSubsetsr¬   rq   Nc                C  s$   || _ || _|pg | _|pi | _d S r.   ©re   rd   ró   r¬   )r1   re   rd   ró   r¬   r+   r+   r,   r=   ²  s
    

zVariableFontDescriptor.__init__)	rA   rB   rC   rb   rŽ   rS   r:   rd   r=   r+   r+   r+   r,   r    Ÿ  s
   r    c                   @  s0   e Zd ZdZdZdZej dejdœdd„ZdS )r   zZSubset of a continuous axis to include in a variable font.

    .. versionadded:: 5.0
    úaxis-subset©re   rà   ÚuserDefaultrâ   N)rà   r÷   râ   c                C  s   || _ || _|| _|| _d S r.   rö   )r1   re   rà   r÷   râ   r+   r+   r,   r=   Ò  s
    z"RangeAxisSubsetDescriptor.__init__)	rA   rB   rC   rb   rŽ   rS   ÚmathÚinfr=   r+   r+   r+   r,   r   Ê  s   r   c                   @  s    e Zd ZdZdZdZdd„ ZdS )r   zhSingle value of a discrete or continuous axis to use in a variable font.

    .. versionadded:: 5.0
    rõ   ©re   rá   c                C  s   || _ || _d S r.   rú   )r1   re   rá   r+   r+   r,   r=   î  s    z"ValueAxisSubsetDescriptor.__init__N)rA   rB   rC   rb   rŽ   rS   r=   r+   r+   r+   r,   r   æ  s   r   c                   @  s,  e Zd ZdZeZeZeZ	e
ZeZeZeZeZeZeZedd„ ƒZedd„ ƒZedd„ ƒZedd	„ ƒZd
dœdd„Zd=dd„Zdd„ Zd>dd„Z dd„ Z!dd„ Z"dd„ Z#dddd œd!d"„Z$d#d$„ Z%dd%dd&œd'd(„Z&ddd)œd*d+d)œd,d-„Z'd.d/„ Z(d0d1„ Z)dd2dd3œd4d5„Z*dd6d7dd8œd9d:„Z+d;d<„ Z,dS )?r   r^   c                 C  s   |   ¡ S r.   )ÚaxisDescriptorClass©Úclsr+   r+   r,   ÚgetAxisDecriptor  s    zBaseDocWriter.getAxisDecriptorc                 C  s   |   ¡ S r.   )ÚsourceDescriptorClassrü   r+   r+   r,   ÚgetSourceDescriptor  s    z!BaseDocWriter.getSourceDescriptorc                 C  s   |   ¡ S r.   )ÚinstanceDescriptorClassrü   r+   r+   r,   ÚgetInstanceDescriptor  s    z#BaseDocWriter.getInstanceDescriptorc                 C  s   |   ¡ S r.   )ÚruleDescriptorClassrü   r+   r+   r,   ÚgetRuleDescriptor  s    zBaseDocWriter.getRuleDescriptorr   )ÚdocumentObjectc                 C  s&   || _ || _|  ¡ | _t d¡| _d S )NZdesignspace)r'   r  Ú_getEffectiveFormatTupleÚeffectiveFormatTupleÚETÚElementÚroot)r1   ÚdocumentPathr  r+   r+   r,   r=     s    
zBaseDocWriter.__init__TúUTF-8c                 C  sî  d  dd„ | jD ƒ¡| jjd< | jjs2| jjd urbt d¡}| jjd urV| jj|jd< | j 	|¡ | jjD ]}|  
|¡ qj| jjr²t d¡}| jjD ]}|  ||¡ q”| j 	|¡ | jjrêt| jdd	ƒrÒd
di}ni }| j 	t d|¡¡ | jjD ]}	|  |	¡ qò| jjr| j 	t d¡¡ | jjD ]}
|  |
¡ q&| jjrtt d¡}| jjD ]}|  ||¡ qT| j 	|¡ | jjr| j 	t d¡¡ | jjD ]}|  |¡ q˜| jjrÈ|  | j| jjd¡ t | j¡}|j| j|d||d d S )NÚ.c                 s  s   | ]}t |ƒV  qd S r.   )r?   ©rI   Úir+   r+   r,   r”     r\   z&BaseDocWriter.write.<locals>.<genexpr>Úformatrˆ   ÚelidedfallbacknameÚlabelsÚrulesProcessingLastFÚ
processingÚlastr   Úsourceszvariable-fontsÚ	instancesré   Úxml)ÚencodingÚmethodÚxml_declarationZpretty_print)r$   r  r
  Úattribr  rˆ   ÚelidedFallbackNamer  r	  rœ   Ú_addAxisÚlocationLabelsÚ_addLocationLabelr   r/   Ú_addRuler  Ú
_addSourceÚvariableFontsÚ_addVariableFontr  Ú_addInstancer¬   Ú_addLibZElementTreeÚwriter'   )r1   Úprettyr  r  ÚaxesElementÚ
axisObjectÚlabelsElementZlabelObjectÚ
attributesÚ
ruleObjectÚsourceObjectZvariableFontsElementÚvariableFontÚinstanceObjectÚtreer+   r+   r,   r'    sV    







ûzBaseDocWriter.writec                 C  sj   | j j}tdd„ | j jD ƒƒsZ| j jsZtdd„ | j jD ƒƒsZ| j jsZtdd„ | j jD ƒƒrf|dk rfd}|S )z”Try to use the version specified in the document, or a sufficiently
        recent version to be able to encode what the document contains.
        c                 s  s(   | ] }t |d ƒp|jdup|jV  qdS )rÜ   N)rG   rÍ   rÎ   rð   r+   r+   r,   r”   V  s
   ý
ÿz9BaseDocWriter._getEffectiveFormatTuple.<locals>.<genexpr>c                 s  s   | ]}|j V  qd S r.   )rp   ©rI   rc   r+   r+   r,   r”   ]  s   ÿc                 s  s   | ]}|j p|jV  qd S r.   )r¡   r¢   )rI   r    r+   r+   r,   r”   b  s   þ©é   r   )r  ÚformatTupler•   rˆ   r  r  r#  r  )r1   Z
minVersionr+   r+   r,   r  P  s(    üÿùþøôýóz&BaseDocWriter._getEffectiveFormatTupleNc           
      C  sÆ   t  d¡}|dur||jd< | j ¡ }| ¡ D ]\}}||v r.|||< q.| ¡ D ]l\}}t  d¡}	||	jd< t|ƒtkr¢|  |d ¡|	jd< |  |d ¡|	jd< n|  |¡|	jd< | 	|	¡ qP||fS )	z, Convert Location dict to a locationElement.rg   Nre   Ú	dimensionr   Úxvaluerê   Úyvalue)
r  r	  r  r  ÚnewDefaultLocationrM   ÚtyperÚ   Ú
intOrFloatrœ   )
r1   ZlocationObjectre   Ú
locElementZvalidatedLocationr³   Z	axisValueZdimensionNameZdimensionValueÚ
dimElementr+   r+   r,   Ú_makeLocationElementl  s     





z"BaseDocWriter._makeLocationElementc                 C  s(   t |ƒ|krd| S d|  d¡ d¡S )Nz%dz%fÚ0r  )ræ   Úrstrip)r1   Únumr+   r+   r,   r;    s    zBaseDocWriter.intOrFloatc           	      C  s<  t  d¡}|jd ur |j|jd< |jD ]´}t  d¡}|D ]Ž}| d¡d u rZ| d¡d u rZq8t  d¡}| d¡|jd< | d¡d ur˜|  | d¡¡|jd< | d¡d ur¼|  | d¡¡|jd< | |¡ q8t|ƒr&| |¡ q&|j	D ]4}t  d¡}|d |jd< |d	 |jd
< | |¡ qât|ƒr8| j
 d¡d  |¡ d S )Nr–   re   Zconditionsetr˜   r™   Ú	conditionÚsubr   rê   Úwithú.rules)r  r	  re   r  r   r€   r;  rœ   rÄ   r‘   r
  Úfindall)	r1   r-  ÚruleElementrš   ZconditionsetElementÚcondÚconditionElementrC  Ú
subElementr+   r+   r,   r!  †  s0    







zBaseDocWriter._addRulec                   sf  t  d¡}|j|jd< |j|jd< ˆ  ||j¡ |jrz|jD ]<\}}t  d¡}ˆ  |¡|jd< ˆ  |¡|jd< | 	|¡ q<|j
s†|jrÌt  d¡}|j
d urªt|j
ƒ|jd< |jD ]}ˆ  ||¡ q°| 	|¡ t|d	ƒrüˆ  |j¡|jd	< ˆ  |j¡|jd
< n,t|dƒr(d ‡ fdd„|jD ƒ¡|jd< ˆ  |j¡|jd< |jrLd|jd< ˆ j d¡d  	|¡ d S )NrŒ   rÆ   re   rÌ   ÚinputÚoutputr  Úorderingr˜   r™   rÜ   ú c                 3  s   | ]}ˆ   |¡V  qd S r.   )r;  rH   r0   r+   r,   r”   ¸  r\   z)BaseDocWriter._addAxis.<locals>.<genexpr>rŠ   Ú1rË   ú.axesr   )r  r	  rÆ   r  re   Ú_addLabelNamesrÊ   rÌ   r;  rœ   rÍ   rÎ   r?   Ú_addAxisLabelrG   r˜   r™   r$   rÜ   rŠ   rË   r
  rF  )r1   r*  ÚaxisElementÚ
inputValueÚoutputValueÚ
mapElementr+  r·   r+   r0   r,   r  ¢  s4    






 
zBaseDocWriter._addAxisú
ET.Elementr   ÚNone)rS  r·   r‡   c                 C  s¸   t  d¡}|  |j¡|jd< |jd ur8|  |j¡|jd< |jd urT|  |j¡|jd< |j|jd< |jrpd|jd< |j	r€d|jd< |j
d urœ|  |j
¡|jd	< |  ||j¡ | |¡ d S )
Nr·   Ú	uservalueÚuserminimumÚusermaximumre   Útruerã   ÚoldersiblingÚlinkeduservalue)r  r	  r;  rá   r  rà   râ   re   rã   rä   rå   rQ  rÊ   rœ   )r1   rS  r·   ÚlabelElementr+   r+   r,   rR  ¾  s    





zBaseDocWriter._addAxisLabelc                 C  s>   t | ¡ ƒD ],\}}t d¡}||jt< ||_| |¡ qd S )NÚ	labelname)ÚsortedrM   r  r	  r  ÚXML_LANGÚtextrœ   )r1   ÚparentElementrÊ   r}   Z	labelNameZlanguageElementr+   r+   r,   rQ  Ï  s
    

zBaseDocWriter._addLabelNamesr   )rd  r·   r‡   c                 C  sb   t  d¡}|j|jd< |jr&d|jd< |jr6d|jd< |  ||j¡ | j||j	d | 
|¡ d S )Nr·   re   r\  rã   r]  ©r¢   )r  r	  re   r  rã   rä   rQ  rÊ   Ú_addLocationElementr¢   rœ   )r1   rd  r·   r_  r+   r+   r,   r   Ö  s    


zBaseDocWriter._addLocationLabel©rt   r¢   r„   r¹   c                C  s   t  d¡}| jjD ]Ò}|d ur˜|j|v r˜t  d¡}|j|jd< ||j }t|tƒr||  |d ¡|jd< |  |d ¡|jd< n|  |¡|jd< | 	|¡ q|d ur|j|v rt  d¡}|j|jd< ||j }|  |¡|jd< | 	|¡ qt
|ƒdkrü| 	|¡ d S )	Nrg   r6  re   r   r7  rê   r8  rY  )r  r	  r  rˆ   re   r  rN   rÚ   r;  rœ   rÄ   )r1   rd  rt   r¢   r<  rŒ   r=  r7   r+   r+   r,   rf  á  s&    





z!BaseDocWriter._addLocationElementc                 C  sn  t  d¡}|jd ur |j|jd< |jd ur6|j|jd< |jd urL|j|jd< |jd urb|j|jd< |jr¼t|j 	¡ ƒ}| 
¡  |D ]8}|dkrq‚t  d¡}||jt< | |¡|_| |¡ q‚|jrt|j 	¡ ƒ}| 
¡  |D ]8}|dkrìqÞt  d¡}||jt< | |¡|_| |¡ qÞ|jrzt|j 	¡ ƒ}| 
¡  |D ]>}|dkrLq:t  d¡}||jt< | |¡|_| |¡ q:|jrÜt|j 	¡ ƒ}| 
¡  |D ]>}|dkr®qœt  d¡}||jt< | |¡|_| |¡ qœ| jd	kr
|jd u r2| j||j|jd
 n(|jd ur2|  |j¡\}	|_| |	¡ |jd urJ|j|jd< |jd urb|j|jd< |jd urz|j|jd< |jd ur’|j|jd< | jd	k rD|jr|  d¡g krÊt  d¡}
| |
¡ |  d¡d }
t!|j "¡ ƒD ]$\}}|  #||||¡}|
 |¡ qæ|j$r(t  d¡}| |¡ |j%rDt  d¡}| |¡ |  &||j'd¡ | j(  d¡d  |¡ d S )Nr    re   rg   Ú
familynameÚ	stylenamerz   ÚstylemapstylenameÚstylemapfamilynamer3  rg  rd   Úpostscriptfontnamez.glyphsr©   r   rª   r«   rÀ   z
.instances))r  r	  re   r  r¡   rn   ro   r¦   rO   ÚkeysÚsortrb  r®   rc  rœ   rp   r‚   r¨   r°   r§   r²   r  rf  rt   r¢   rg   r>  rd   r£   r¤   r¥   r©   rF  ra  rM   Ú_writeGlyphElementrª   r«   r&  r¬   r
  )r1   r0  ÚinstanceElementÚlanguageCodesÚcodeZlocalisedStyleNameElementÚlocalisedFamilyNameElementZ!localisedStyleMapStyleNameElementZ"localisedStyleMapFamilyNameElementÚlocationElementZglyphsElementÚ	glyphNameÚdataÚglyphElementÚkerningElementÚinfoElementr+   r+   r,   r%  ý  s¨    














ý






zBaseDocWriter._addInstancec                 C  sT  t  d¡}|jd ur |j|jd< |jd urF|j d¡dkrF|j|jd< |jd ur\|j|jd< |jd urr|j|jd< |jd urˆ|j|jd< |j	rât
|j	 ¡ ƒ}| ¡  |D ]8}|d	kr¶q¨t  d¡}||jt< | |¡|_| |¡ q¨|jrt  d
¡}d|jd< | |¡ |jr.t  d¡}d|jd< | |¡ |jrTt  d¡}d|jd< | |¡ |jsd|jrœt  d¡}	|jr€d|	jd< |jr’d|	jd< | |	¡ |jrÂt  d¡}
d|
jd< | |
¡ |jr |jD ].}t  d¡}||jd< d|jd< | |¡ qÐ| jdkr| j||jd n|  |j¡\}|_| |¡ | j d¡d  |¡ d S )Nrc   rd   Ztemp_masterr   re   rh  ri  Úlayerrz   r¬   rO  ÚcopyÚgroupsÚfeaturesr«   Úmuterª   Úglyphr3  rv   z.sources)r  r	  rd   r  re   Úfindrn   ro   rf   rp   rO   rm  rn  rb  r‚   rc  rœ   rh   ri   rj   ru   rl   rk   rm   r  rf  rg   r>  r
  rF  )r1   r.  ÚsourceElementrq  rr  rs  Ú
libElementÚgroupsElementÚfeaturesElementry  rx  re   rw  rt  r+   r+   r,   r"  Y  sp    




























zBaseDocWriter._addSourcer    )rd  Úvfr‡   c                 C  s(  t  d¡}|j|jd< |jd ur,|j|jd< |jr
t  d¡}|jD ]º}t  d¡}|j|jd< t|dƒrÎtt|ƒ}|j	t
j kr’|  |j	¡|jd< |jt
jkr°|  |j¡|jd< |jd urô|  |j¡|jd	< n&t|d
ƒrôtt|ƒ}|  |j¡|jd< | |¡ qD| |¡ |  ||jd¡ | |¡ d S )Nrò   re   rd   zaxis-subsetsrõ   rà   rZ  r[  Úuserdefaultrá   rY  rÀ   )r  r	  re   r  rd   ró   rG   r   r   rà   rø   rù   r;  râ   r÷   r   rá   rœ   r&  r¬   )r1   rd  r…  Z	vfElementZsubsetsElementZsubsetZsubsetElementr+   r+   r,   r$  —  s0    










zBaseDocWriter._addVariableFontr   ræ   )rd  rv  Úindent_levelr‡   c                 C  s4   |sd S t  d¡}| tj||d¡ | |¡ d S )Nr¬   )r‡  )r  r	  rœ   r   Ztotree)r1   rd  rv  r‡  r‚  r+   r+   r,   r&  ´  s
    
zBaseDocWriter._addLibc                 C  sz  t  d¡}| d¡rd|jd< | d¡d urLd dd„ | d¡D ƒ¡|jd< | d	¡d ur||  | d	¡¡\}|d	< | |¡ |d urŽ||jd
< | d¡d ur¼t  d¡}| d¡|_| |¡ | d¡d urvt  d¡}| d¡D ]Š}	t  d¡}
|	 d¡d ur|	 d¡|
jd< |	 d¡d ur.|	 d¡|
jd< |	 d¡d ur`|  |	 d¡¡\}|	d< |
 |¡ | |
¡ qà| |¡ |S )Nr  r~  rO  ÚunicodesrN  c                 S  s   g | ]}t |ƒ‘qS r+   )Úhex©rI   Úur+   r+   r,   rK   À  r\   z4BaseDocWriter._writeGlyphElement.<locals>.<listcomp>ÚunicodeÚinstanceLocationre   ÚnoteÚmastersZmasterru  Ú	glyphnamers   rc   rg   )r  r	  r€   r  r$   r>  rœ   rc  )r1   rp  r0  ru  rv  rw  rt  ÚnoteElementZmastersElementÚmÚmasterElementr+   r+   r,   ro  »  s8    


 







z BaseDocWriter._writeGlyphElement)Tr  T)N)-rA   rB   rC   Z_whiteSpacer   rû   r   ÚdiscreteAxisDescriptorClassr   ÚaxisLabelDescriptorClassr   ÚlocationLabelDescriptorClassr   r  r   rÿ   r    ÚvariableFontDescriptorClassr   ÚvalueAxisSubsetDescriptorClassr   ÚrangeAxisSubsetDescriptorClassr   r  Úclassmethodrþ   r   r  r  r=   r'  r  r>  r;  r!  r  rR  rQ  r   rf  r%  r"  r$  r&  ro  r+   r+   r+   r,   r   ÷  sJ   




6
û\>r   c                   @  sâ   e Zd ZeZeZeZe	Z
eZeZeZeZeZeZdd„ Zedd„ ƒZdd„ Zdd„ Zd+d
d„Zdd„ Zddœdd„Zdd„ Zdd„ Z ddœdd„Z!dd„ Z"dd„ Z#dd„ Z$d,dd „Z%d-d!d"„Z&d#d$„ Z'd%d&„ Z(d'd(„ Z)d)d*„ Z*d	S ).r   c                 C  s^   || _ || _t | j ¡}| ¡ | _| jj dd¡| j_g | _	g | _
g | _g | _i | _d| _d S )Nr  z3.0T)r'   r  r  ÚparseZgetrootr
  r  r€   ÚformatVersionZ_axesr   r  r  ÚaxisDefaultsÚ_strictAxisNames)r1   r  r  r1  r+   r+   r,   r=   æ  s    
zBaseDocReader.__init__c                 C  s$   t t|ddƒ}| ||ƒ}d |_|S )Núutf-8)r  )r   r   r'   )rý   Ústringr  Úfr1   r+   r+   r,   Ú
fromstringó  s    
zBaseDocReader.fromstringc                 C  s<   |   ¡  |  ¡  |  ¡  |  ¡  |  ¡  |  ¡  |  ¡  d S r.   )ÚreadAxesÚ
readLabelsÚ	readRulesÚreadVariableFontsÚreadSourcesÚreadInstancesÚreadLibr0   r+   r+   r,   Úreadú  s    zBaseDocReader.readc                 C  s  g }| j  d¡}|d urF|j dd¡}|dvr:td| ƒ‚|dk| j_| j  d¡D ]´}|  ¡ }|j d¡ }|_	|  
||¡}|r˜|j |¡ | j d	¡ | d
¡D ]$}|  
||¡}	|	d ur¢|j |	¡ q¢| d¡D ](}
|
jd }|
jd }|j ||f¡ qÒ| |¡ qR|| j_d S )NrE  r  Úfirst>   r«  r  zO<rules> processing attribute value is not valid: %r, expected 'first' or 'last'r  z.rules/rulere   zWFound stray rule conditions outside a conditionset. Wrapped them in a new conditionset.z.conditionsetz.subrD  )r
  r€  r  r€   r   r  r  rF  r  re   Ú_readConditionElementsr   rœ   Úlogr«   r‘   r   )r1   r   ZrulesElementZprocessingValuerG  r-  ÚruleNameZexternalConditionsZconditionSetElementZconditionSetrJ  r[   rž   r+   r+   r,   r¥    sH    ÿÿþÿþ

zBaseDocReader.readRulesNc                 C  sÂ   g }|  d¡D ]®}i }|j d¡}|d ur8t|ƒ|d< nd |d< |j d¡}|d urbt|ƒ|d< nd |d< |j d¡|d< | d¡d u r²| d¡d u r²td|d urªd| nd ƒ‚| |¡ q|S )Nz
.conditionr˜   r™   re   z5condition missing required minimum or maximum in rulez '%s'r>   )rF  r  r€   Úfloatr   rœ   )r1   rd  r®  ZcdsrI  r›   ZcdMinZcdMaxr+   r+   r,   r¬  +  s(    ÿÿz$BaseDocReader._readConditionElementsc                 C  sæ  | j  d¡}|d ur,d|jv r,|jd | j_| j  d¡}|s@d S |D ]š}| jjdkr†d|jv r†|  ¡ }dd„ |jd  d¡D ƒ|_	n,|  
¡ }t|j d	¡ƒ|_t|j d
¡ƒ|_t|j d¡ƒ|_|j d¡|_|j dd¡ræd|_|j d¡|_| d¡D ]0}t|jd ƒ}t|jd ƒ}|j ||f¡ qþ| d¡D ]4}| ¡ D ]$\}	}
|	tkrFt|jƒ|j|
< qFq:| d¡}|d urÄd|jv r t|jd ƒ|_| d¡D ]}|j |  |¡¡ qª| jj |¡ |j| j|j< qDd S )NrP  r  z
.axes/axisr3  rÜ   c                 S  s   g | ]}t |ƒ‘qS r+   )r¯  )rI   Úsr+   r+   r,   rK   O  r\   z*BaseDocReader.readAxes.<locals>.<listcomp>rN  r˜   r™   rŠ   re   rË   FTrÆ   rÌ   rK  rL  r`  z.labelsrM  z.label) r
  r€  r  r  r  rF  r5  r”  r%   rÜ   rû   r¯  r€   r˜   r™   rŠ   re   rË   rÆ   rÌ   rœ   rM   rb  r   rc  rÊ   ræ   rÍ   rÎ   ÚreadAxisLabelrˆ   r  )r1   r)  ZaxisElementsrS  r*  rV  r[   rž   ZlabelNameElementÚkeyr!   r_  r·   r+   r+   r,   r£  D  sD    



zBaseDocReader.readAxesrW  )Úelementc              
   C  s  h d£}t |jƒ| }|r.tdd |¡› ƒ‚| d¡}|d u rHtdƒ‚| d¡}|d u rbtdƒ‚t|ƒ}| d¡}|d ur„t|ƒnd }| d	¡}	|	d ur¢t|	ƒnd }
| d
¡}|d urÀt|ƒnd }| d¡dkrÖdnd}| d¡dkrìdnd}dd„ | d¡D ƒ}| j||||
||||dS )N>   r[  r^  r]  re   rY  rZ  rã   z+label element contains unknown attributes: ú, re   ú)label element must have a name attribute.rY  z.label element must have a uservalue attribute.rZ  r[  r^  rã   r\  TFr]  c                 S  s2   i | ]*}|  ¡ D ]\}}|tkr||jp*d “qqS ©r>   ©rM   rb  rc  ©rI   Z
label_namerQ   r!   r+   r+   r,   r×     s   ýz/BaseDocReader.readAxisLabel.<locals>.<dictcomp>r`  )re   rá   rà   râ   rã   rä   rå   rÊ   )Úsetr  r   r$   r€   r¯  rF  r•  )r1   r³  Ú	xml_attrsÚunknown_attrsre   ZvalueStrr7   Z
minimumStrr˜   Z
maximumStrr™   ZlinkedValueStrZlinkedValuerã   rä   rÊ   r+   r+   r,   r±  l  s@    




þøzBaseDocReader.readAxisLabelc                 C  sò   | j jdk rd S h d£}| j d¡D ]È}t|jƒ| }|rNtdd |¡› ƒ‚| d¡}|d u rhtdƒ‚|  	|¡\}}|rŠtd|› d	ƒ‚| d
¡dkrœdnd}| d¡dkr²dnd}dd„ | d¡D ƒ}	| j
|||||	d}
| j j |
¡ q$d S )Nr3  >   rã   re   r]  z.labels/labelz+Label element contains unknown attributes: r´  re   rµ  z<label> element "z5" must only have user locations (using uservalue="").rã   r\  TFr]  c                 S  s2   i | ]*}|  ¡ D ]\}}|tkr||jp*d “qqS r¶  r·  r¸  r+   r+   r,   r×   ¦  s   ýz,BaseDocReader.readLabels.<locals>.<dictcomp>r`  rï   )r  r5  r
  rF  r¹  r  r   r$   r€   ÚlocationFromElementr–  r  rœ   )r1   rº  r_  r»  re   rt   r¢   rã   rä   rÊ   r¡   r+   r+   r,   r¤  ”  s4    
þûzBaseDocReader.readLabelsc                 C  sú   | j jdk rd S ddh}| j d¡D ]Ð}t|jƒ| }|rNtdd |¡› ƒ‚| d¡}|d u rhtdƒ‚| d¡}| 	d¡}|d u rŒtd	ƒ‚g }| 
d
¡D ]}| |  |¡¡ qšd }	| 	d¡}
|
d urÔt |
d ¡}	| j||||	d}| j j |¡ q$d S )Nr3  re   rd   z.variable-fonts/variable-fontz3variable-font element contains unknown attributes: r´  z1variable-font element must have a name attribute.z.axis-subsetsz;variable-font element must contain an axis-subsets element.z.axis-subsetú.libr   rô   )r  r5  r
  rF  r¹  r  r   r$   r€   r€  Ziterfindrœ   ÚreadAxisSubsetr   ÚfromtreeÚvariableFontsDescriptorClassr#  )r1   rº  ZvariableFontElementr»  re   rd   ZaxisSubsetsElementró   Z
axisSubsetr¬   r‚  r/  r+   r+   r,   r¦  ·  s8    



üzBaseDocReader.readVariableFontsc           
      C  sV  d|j v r‚ddh}t|j ƒ| }|r8tdd |¡› ƒ‚| d¡}|d u rRtdƒ‚| d¡}|d u rltdƒ‚t|ƒ}| j||dS h d£}t|j ƒ| }|r°tdd |¡› ƒ‚| d¡}|d u rÊtdƒ‚| d	¡}| d
¡}| d¡}	|d ur$|d ur$|	d ur$| j|t|ƒt|ƒt|	ƒdS tdd„ |||	fD ƒƒrJ| j|dS tdƒ‚d S )NrY  re   z1axis-subset element contains unknown attributes: r´  z/axis-subset element must have a name attribute.zNThe axis-subset element for a discrete subset must have a uservalue attribute.rú   >   r†  r[  rZ  re   rZ  r†  r[  rö   c                 s  s   | ]}|d u V  qd S r.   r+   rH   r+   r+   r,   r”     r\   z/BaseDocReader.readAxisSubset.<locals>.<genexpr>©re   zDaxis-subset element must have min/max/default values or none at all.)	r  r¹  r   r$   r€   r¯  r˜  r™  Úall)
r1   r³  rº  r»  re   ZuserValueStrrá   rà   r÷   râ   r+   r+   r,   r¾  Û  sJ    


ÿ



üÿzBaseDocReader.readAxisSubsetc                 C  s’  t | j d¡ƒD ]z\}}|j d¡}|d urZ| jd urZtj tj tj 	| j¡|¡¡}nd }|j d¡}|d u rzd| }|  
¡ }||_||_||_|j d¡}|d ur®||_|j d¡}|d urÈ||_| d¡D ]0}	|	 ¡ D ]"\}
}|
tkrÞ|	j}| ||¡ qÞqÒ|  |¡\}}|r(td|› dƒ‚||_|j d	¡}|d urJ||_| d
¡D ]}|j d¡dkrTd|_qT| d¡D ]}|j d¡dkr~d|_q~| d¡D ]6}|j d¡dkrÄd|_|j d¡dkr¨d|_q¨| d¡D ]}|j d¡dkrêd|_qê| d¡D ]>}|j d¡}|d u r2q|j d¡dkr|j |¡ q| d¡D ]}|j d¡dkr^d|_q^| jj  |¡ qd S )Nz.sources/sourcerd   re   ztemp_master.%drh  ri  z<source> element "ú4" must only have design locations (using xvalue="").rz  r½  r{  rO  Tz.groupsz.infor~  z	.featuresz.glyphz.kerning)!Ú	enumerater
  rF  r  r€   r'   r&   Úabspathr$   Údirnamerÿ   rd   re   rn   ro   rM   rb  rc  r~   r¼  r   rg   rf   rh   ri   ru   rl   rj   rm   rœ   rk   r  r  )r1   ZsourceCountr  rd   Z
sourcePathZ
sourceNamer.  rn   ro   ÚfamilyNameElementr²  r!   rt   r¢   rf   r‚  rƒ  ry  r„  rw  ru  rx  r+   r+   r,   r§  	  sl    "






zBaseDocReader.readSourcesc                 C  s&   d}|  d¡D ]}|  |¡} q"q|S )z¨Read a nested ``<location>`` element inside the given ``element``.

        .. versionchanged:: 5.0
           Return a tuple of (designLocation, userLocation)
        )NNz	.location)rF  ÚreadLocationElement)r1   r³  ZelementLocationrt  r+   r+   r,   r¼  C  s
    
z!BaseDocReader.locationFromElementc           	   	   C  sÆ  | j r| jjstdƒ‚i }i }| d¡D ]’}|j d¡}| j rZ|| jvrZ| j 	d|¡ q(d } }}z |j d¡}|dur„t
|ƒ}W n  ty¦   | j 	d|¡ Y n0 z |j d¡}|durÆt
|ƒ}W n  tyè   | j 	d	|¡ Y n0 z"|j d
¡}|dur
t
|ƒ}W n" ty.   | j 	d|¡ Y n0 |d  u rT|  krTdu rhn ntd|› dƒ‚|dur |du r’td|› d|› dƒ‚||f||< q(|dur´|||< q(|||< q(||fS )z„Read a ``<location>`` element.

        .. versionchanged:: 5.0
           Return a tuple of (designLocation, userLocation)
        zNo axes definedz
.dimensionre   z#Location with undefined axis: "%s".NrY  z*ValueError in readLocation userValue %3.3fr7  z'ValueError in readLocation xValue %3.3fr8  z'ValueError in readLocation yValue %3.3fzRExactly one of uservalue="" or xvalue="" must be provided for location dimension "ú"z.Missing xvalue="" for the location dimension "z"" with yvalue=")rž  r  rˆ   r   rF  r  r€   r  r­  Úwarningr¯  Ú
ValueError)	r1   rt  ZuserLocZ	designLocZdimensionElementZdimNamerá   ZxValueZyValuer+   r+   r,   rÈ  O  sL    
(




z!BaseDocReader.readLocationElementTc                 C  s,   | j  d¡}|D ]}| j||||d qd S )Nz.instances/instance)Ú
makeGlyphsÚmakeKerningÚmakeInfo)r
  rF  Ú_readSingleInstanceElement)r1   rÌ  rÍ  rÎ  ZinstanceElementsrp  r+   r+   r,   r¨  ~  s    zBaseDocReader.readInstancesc                 C  s¸  |j  d¡}|d ur<| jjd ur<tj tj | jj¡|¡}nd }|  ¡ }||_||_|j  d¡}|d urn||_	|j  d¡}	|	d urˆ|	|_
|j  d¡}
|
d ur¢|
|_|j  d¡}|d ur¼||_|j  d¡}|d urÖ||_|j  d¡}|d urð||_| d¡D ]4}| ¡ D ]&\}}|tkr|j}| ||¡ qqú| d¡D ]6}| ¡ D ]&\}}|tkrF|j}| ||¡ qFq:| d¡D ]6}| ¡ D ]&\}}|tkrˆ|j}| ||¡ qˆq|| d¡D ]6}| ¡ D ]&\}}|tkrÊ|j}| ||¡ qÊq¾|  |¡\}}|j  d¡}|s|r.|d ur.td	ƒ‚||_|p<i |_|pHi |_| d
¡D ]}|  ||¡ qV| d¡D ]}|  ||¡ qt| d¡D ]}|  ||¡ q’| jj  |¡ d S )Nrd   re   rh  ri  rl  rk  rj  rg   zeinstance element must have at most one of the location="..." attribute or the nested location elementz.glyphs/glyphr«   r¬   )!r  r€   r  r'   r&   r$   rÆ  r  rd   re   rn   ro   r£   r¤   r¥   rF  rM   rb  rc  r­   r~   r¯   r±   r¼  r   r¡   r¢   rt   ÚreadGlyphElementÚreadInfoElementÚreadLibElementr  rœ   )r1   rp  rÌ  rÍ  rÎ  rd   ZinstancePathr0  re   rh  ri  r£   r¤   r¥   ZstyleNameElementr²  r!   ro   rÇ  rn   ZstyleMapStyleNameElementZstyleMapFamilyNameElementrt   r¢   r¡   rw  ry  r‚  r+   r+   r,   rÏ  ƒ  sv    



z(BaseDocReader._readSingleInstanceElementc                 C  s   t  |d ¡|_dS )z,Read the lib element for the given instance.r   N)r   r¿  r¬   )r1   r‚  r0  r+   r+   r,   rÒ  Â  s    zBaseDocReader.readLibElementc                 C  s
   d|_ dS )z Read the info element.TN)r«   )r1   ry  r0  r+   r+   r,   rÑ  Æ  s    zBaseDocReader.readInfoElementc                 C  s„  i }|j  d¡}|du r tdƒ‚|j  d¡}|dkr<d|d< |j  d¡}|durz dd	„ | d
¡D ƒ}||d< W n tyŽ   td| ƒ‚Y n0 | d¡D ]}|j|d<  q®qš|  |¡\}}	|	rÐtd|› dƒ‚|durà||d< d}
| d¡D ]t}|j  d¡}|  |¡\}}	|	r"td|› dƒ‚|j  d¡}|du r<|}t|||d}|
du rXg }
|
 	|¡ qî|
durv|
|d< ||j
|< dS )a$  
        Read the glyph element, which could look like either one of these:

        .. code-block:: xml

            <glyph name="b" unicode="0x62"/>

            <glyph name="b"/>

            <glyph name="b">
                <master location="location-token-bbb" source="master-token-aaa2"/>
                <master glyphname="b.alt1" location="location-token-ccc" source="master-token-aaa3"/>
                <note>
                    This is an instance from an anisotropic interpolation.
                </note>
            </glyph>
        re   Nz#Glyph object without name attributer~  rO  TrŒ  c                 S  s   g | ]}t |d ƒ‘qS )é   ©ræ   rŠ  r+   r+   r,   rK   ç  r\   z2BaseDocReader.readGlyphElement.<locals>.<listcomp>rN  rˆ  z"unicode values %s are not integersz.noterŽ  z<glyph> element "rÃ  r  z.masters/masterrc   z<master> element "r  )rs   rg   ru  r  )r  r€   r   r%   rË  rF  rc  r¼  rÂ   rœ   r©   )r1   rw  r0  Ú	glyphDataru  r~  rˆ  r‘  rt   r¢   ZglyphSourcesr“  ZfontSourceNameZmasterGlyphNamerP   r+   r+   r,   rÐ  Ê  sR    

þ

zBaseDocReader.readGlyphElementc                 C  s(   | j  d¡D ]}t |d ¡| j_qdS )z,Read the lib element for the whole document.r½  r   N)r
  rF  r   r¿  r  r¬   )r1   r‚  r+   r+   r,   r©  	  s    zBaseDocReader.readLib)N)TTT)TTT)+rA   rB   rC   r   rû   r   r”  r   r•  r   r–  r   r  r   rÿ   r    rÀ  r   r˜  r   r™  r   r  r=   rš  r¢  rª  r¥  r¬  r£  r±  r¤  r¦  r¾  r§  r¼  rÈ  r¨  rÏ  rÒ  rÑ  rÐ  r©  r+   r+   r+   r,   r   Ú  s<   
	(
((#$.:/

?>r   c                   @  s   e Zd ZdZdfdd„Zedgdd„ƒZedhdd„ƒZdid	d
„Zdd„ Z	dd„ Z
dd„ Zdd„ Zddœdd„Zdd„ Zddœdd„Zdd„ Zdd œd!d"„Zd#d$„ Zd%d&œd'd(„Zd)d*„ Zd+d,œd-d.„Zd/d0„ Zd1d2œd3d4„Zd5d6„ Zd7d8„ Zd9d:d;œd<d=„Zdjd@dA„ZdBdC„ ZdDdE„ ZdFdG„ ZdHdI„ ZdJdK„ Z dLd:dMœdNdO„Z!d9d9d;œdPdQ„Z"dRd9dSœdTdU„Z#dVdW„ Z$dXdY„ Z%dZd[„ Z&d\d]„ Z'e(d^d_„ ƒZ)d`daœdbdc„Z*ddde„ Z+dS )kr   a”  The DesignSpaceDocument object can read and write ``.designspace`` data.
    It imports the axes, sources, variable fonts and instances to very basic
    **descriptor** objects that store the data in attributes. Data is added to
    the document by creating such descriptor objects, filling them with data
    and then adding them to the document. This makes it easy to integrate this
    object in different contexts.

    The **DesignSpaceDocument** object can be subclassed to work with
    different objects, as long as they have the same attributes. Reader and
    Writer objects can be subclassed as well.

    **Note:** Python attribute names are usually camelCased, the
    corresponding `XML <document-xml-structure>`_ attributes are usually
    all lowercase.

    .. code:: python

        from fontTools.designspaceLib import DesignSpaceDocument
        doc = DesignSpaceDocument.fromfile("some/path/to/my.designspace")
        doc.formatVersion
        doc.elidedFallbackName
        doc.axes
        doc.locationLabels
        doc.rules
        doc.rulesProcessingLast
        doc.sources
        doc.variableFonts
        doc.instances
        doc.lib

    Nc                 C  s~   d | _ d | _d | _d | _g | _g | _g | _d| _g | _g | _	g | _
i | _d | _|d ur^|| _nt| _|d urt|| _nt| _d S )NF)r'   rd   rœ  r  rˆ   r  r   r  r  r#  r  r¬   rŠ   ÚreaderClassr   ÚwriterClassr   )r1   rÖ  r×  r+   r+   r,   r=   /	  s&    	zDesignSpaceDocument.__init__c                 C  s   | ||d}|  |¡ |S )z\Read a designspace file from ``path`` and return a new instance of
        :class:.
        ©rÖ  r×  )rª  )rý   r'   rÖ  r×  r1   r+   r+   r,   Úfromfile†	  s    
zDesignSpaceDocument.fromfilec                 C  s4   | ||d}|j  ||¡}| ¡  |jr0| ¡  |S )NrØ  )rÖ  r¢  rª  r  ÚfindDefault)rý   r   rÖ  r×  r1   Úreaderr+   r+   r,   r¢  	  s    zDesignSpaceDocument.fromstringc                 C  sv   |t u s|dur(| ¡ dkr(tƒ }d}n,|du s8|dkrHtƒ }d}d}ntd| ƒ‚|  || ¡}|j||d | ¡ S )	z@Returns the designspace as a string. Default encoding ``utf-8``.NrŒ  FrŸ  r  Tzunsupported encoding: '%s')r  r  )r?   rÃ   r   r   rË  r×  r'  Úgetvalue)r1   r  r¡  r  Úwriterr+   r+   r,   Útostring˜	  s    ÿ
ÿzDesignSpaceDocument.tostringc                 C  sL   t |dƒr| ¡ }|| _tj |¡| _|  || ¡}| ¡  | jrH|  	¡  dS )zjRead a designspace file from ``path`` and populates the fields of
        ``self`` with the data.
        Ú
__fspath__N)
rG   rß  r'   r&   Úbasenamerd   rÖ  rª  r  rÚ  )r1   r'   rÛ  r+   r+   r,   rª  ©	  s    
zDesignSpaceDocument.readc                 C  sF   t |dƒr| ¡ }|| _tj |¡| _|  ¡  |  || ¡}| ¡  dS )z#Write this designspace to ``path``.rß  N)	rG   rß  r'   r&   rà  rd   ÚupdatePathsr×  r'  )r1   r'   rÝ  r+   r+   r,   r'  ¶	  s    
zDesignSpaceDocument.writec                 C  s    t j |t j | j¡¡}t|ƒS r.   )r&   r'   ÚrelpathrÆ  r-   )r1   Z	otherPathÚrelativer+   r+   r,   Ú_posixRelativePathÀ	  s    z&DesignSpaceDocument._posixRelativePathc                 C  s<   | j dusJ ‚| j| j D ]}|j dur|  |j ¡|_qdS )a  
        Right before we save we need to identify and respond to the following situations:
        In each descriptor, we have to do the right thing for the filename attribute.

        ::

            case 1.
            descriptor.filename == None
            descriptor.path == None

            -- action:
            write as is, descriptors will not have a filename attr.
            useless, but no reason to interfere.


            case 2.
            descriptor.filename == "../something"
            descriptor.path == None

            -- action:
            write as is. The filename attr should not be touched.


            case 3.
            descriptor.filename == None
            descriptor.path == "~/absolute/path/there"

            -- action:
            calculate the relative path for filename.
            We're not overwriting some other value for filename, it should be fine


            case 4.
            descriptor.filename == '../somewhere'
            descriptor.path == "~/absolute/path/there"

            -- action:
            there is a conflict between the given filename, and the path.
            So we know where the file is relative to the document.
            Can't guess why they're different, we just choose for path to be correct and update filename.
        N)r'   r  r  rä  rd   )r1   Ú
descriptorr+   r+   r,   rá  Ä	  s    *
zDesignSpaceDocument.updatePathsr   )ÚsourceDescriptorc                 C  s   | j  |¡ dS )z6Add the given ``sourceDescriptor`` to ``doc.sources``.N)r  rœ   )r1   ræ  r+   r+   r,   Ú	addSourceô	  s    zDesignSpaceDocument.addSourcec                 K  s    | j jf i |¤Ž}|  |¡ |S )zvInstantiate a new :class:`SourceDescriptor` using the given
        ``kwargs`` and add it to ``doc.sources``.
        )r×  rÿ   rç  )r1   Úkwargsrc   r+   r+   r,   ÚaddSourceDescriptorø	  s    
z'DesignSpaceDocument.addSourceDescriptorr   )ÚinstanceDescriptorc                 C  s   | j  |¡ dS )z:Add the given ``instanceDescriptor`` to :attr:`instances`.N)r  rœ   )r1   rê  r+   r+   r,   ÚaddInstance 
  s    zDesignSpaceDocument.addInstancec                 K  s    | j jf i |¤Ž}|  |¡ |S )zzInstantiate a new :class:`InstanceDescriptor` using the given
        ``kwargs`` and add it to :attr:`instances`.
        )r×  r  rë  )r1   rè  r    r+   r+   r,   ÚaddInstanceDescriptor
  s    
z)DesignSpaceDocument.addInstanceDescriptorz-Union[AxisDescriptor, DiscreteAxisDescriptor])ÚaxisDescriptorc                 C  s   | j  |¡ dS )z1Add the given ``axisDescriptor`` to :attr:`axes`.N)rˆ   rœ   )r1   rí  r+   r+   r,   ÚaddAxis
  s    zDesignSpaceDocument.addAxisc                 K  s<   d|v r| j jf i |¤Ž}n| j jf i |¤Ž}|  |¡ |S )a  Instantiate a new :class:`AxisDescriptor` using the given
        ``kwargs`` and add it to :attr:`axes`.

        The axis will be and instance of :class:`DiscreteAxisDescriptor` if
        the ``kwargs`` provide a ``value``, or a :class:`AxisDescriptor` otherwise.
        rÜ   )r×  r”  rû   rî  )r1   rè  rŒ   r+   r+   r,   ÚaddAxisDescriptor
  s
    
z%DesignSpaceDocument.addAxisDescriptorr   )ÚruleDescriptorc                 C  s   | j  |¡ dS )z2Add the given ``ruleDescriptor`` to :attr:`rules`.N)r   rœ   )r1   rð  r+   r+   r,   ÚaddRule
  s    zDesignSpaceDocument.addRulec                 K  s    | j jf i |¤Ž}|  |¡ |S )zrInstantiate a new :class:`RuleDescriptor` using the given
        ``kwargs`` and add it to :attr:`rules`.
        )r×  r  rñ  )r1   rè  r–   r+   r+   r,   ÚaddRuleDescriptor"
  s    
z%DesignSpaceDocument.addRuleDescriptorr    )ÚvariableFontDescriptorc                 C  s   | j  |¡ dS )zjAdd the given ``variableFontDescriptor`` to :attr:`variableFonts`.

        .. versionadded:: 5.0
        N)r#  rœ   )r1   ró  r+   r+   r,   ÚaddVariableFont*
  s    z#DesignSpaceDocument.addVariableFontc                 K  s    | j jf i |¤Ž}|  |¡ |S )z¡Instantiate a new :class:`VariableFontDescriptor` using the given
        ``kwargs`` and add it to :attr:`variableFonts`.

        .. versionadded:: 5.0
        )r×  r—  rô  )r1   rè  r/  r+   r+   r,   ÚaddVariableFontDescriptor1
  s    
z-DesignSpaceDocument.addVariableFontDescriptorr   )ÚlocationLabelDescriptorc                 C  s   | j  |¡ dS )zlAdd the given ``locationLabelDescriptor`` to :attr:`locationLabels`.

        .. versionadded:: 5.0
        N)r  rœ   )r1   rö  r+   r+   r,   ÚaddLocationLabel;
  s    z$DesignSpaceDocument.addLocationLabelc                 K  s    | j jf i |¤Ž}|  |¡ |S )z£Instantiate a new :class:`LocationLabelDescriptor` using the given
        ``kwargs`` and add it to :attr:`locationLabels`.

        .. versionadded:: 5.0
        )r×  r–  r÷  )r1   rè  r¡   r+   r+   r,   ÚaddLocationLabelDescriptorB
  s    
z.DesignSpaceDocument.addLocationLabelDescriptorc                 C  s*   t  ¡ }| jD ]}| |j¡||j< q|S )zDReturn a dict with the default location in design space coordinates.)ÚcollectionsÚOrderedDictrˆ   r‰   rŠ   re   )r1   Úlocrí  r+   r+   r,   r9  L
  s    
ÿz&DesignSpaceDocument.newDefaultLocationr¹   rµ   )r¢   r‡   c                   s   t ‡ fdd„| jD ƒdƒS )zŸReturn the :class:`LocationLabel` that matches the given
        ``userLocation``, or ``None`` if no such label exists.

        .. versionadded:: 5.0
        c                 3  s   | ]}|j ˆ kr|V  qd S r.   re  )rI   r·   re  r+   r,   r”   ^
  r\   z;DesignSpaceDocument.labelForUserLocation.<locals>.<genexpr>N)rÞ   r  ©r1   r¢   r+   re  r,   ÚlabelForUserLocationW
  s    ÿz(DesignSpaceDocument.labelForUserLocationTFc                 C  st   |r8| j D ],}|jdur|sq
| jdur
|  |j¡|_q
|rp| jD ],}|jdurV|sVqB| jdurB|  |j¡|_qBdS )z†Set a descriptor filename attr from the path and this document path.

        If the filename attribute is not None: skip it.
        N)r  rd   r'   rä  r  )r1   r  r  Úforcerå  r+   r+   r,   ÚupdateFilenameFromPatha
  s    



z*DesignSpaceDocument.updateFilenameFromPathc                 C  s
   | j  ¡ S )z5Ask the writer class to make us a new axisDescriptor.)r×  rþ   r0   r+   r+   r,   ÚnewAxisDescriptors
  s    z%DesignSpaceDocument.newAxisDescriptorc                 C  s
   | j  ¡ S )z7Ask the writer class to make us a new sourceDescriptor.)r×  r   r0   r+   r+   r,   ÚnewSourceDescriptorw
  s    z'DesignSpaceDocument.newSourceDescriptorc                 C  s
   | j  ¡ S )z9Ask the writer class to make us a new instanceDescriptor.)r×  r  r0   r+   r+   r,   ÚnewInstanceDescriptor{
  s    z)DesignSpaceDocument.newInstanceDescriptorc                 C  s    g }| j D ]}| |j¡ q
|S )zJReturn a list of axis names, in the same order as defined in the document.)rˆ   rœ   re   )r1   rÅ   rí  r+   r+   r,   ÚgetAxisOrder
  s    
z DesignSpaceDocument.getAxisOrderc                 C  s"   | j D ]}|j|kr|  S qdS )zLReturn the axis with the given ``name``, or ``None`` if no such axis exists.N)rˆ   re   )r1   re   rí  r+   r+   r,   ÚgetAxis†
  s    


zDesignSpaceDocument.getAxisr?   )re   r‡   c                 C  s"   | j D ]}|j|kr|  S qdS )z‘Return the top-level location label with the given ``name``, or
        ``None`` if no such label exists.

        .. versionadded:: 5.0
        N)r  re   )r1   re   r·   r+   r+   r,   r¶   
  s    


z$DesignSpaceDocument.getLocationLabelc                   s   ‡ fdd„| j D ƒS )zíMap a user location to a design location.

        Assume that missing coordinates are at the default location for that axis.

        Note: the output won't be anisotropic, only the xvalue is set.

        .. versionadded:: 5.0
        c              	     s&   i | ]}|j | ˆ  |j |j¡¡“qS r+   )re   r‰   r€   rŠ   rð   re  r+   r,   r×   ¡
  s   ÿz3DesignSpaceDocument.map_forward.<locals>.<dictcomp>rñ   rü  r+   re  r,   r‰   ˜
  s    	
þzDesignSpaceDocument.map_forwardr„   )rt   r‡   c                   s   ‡ fdd„| j D ƒS )zñMap a design location to a user location.

        Assume that missing coordinates are at the default location for that axis.

        When the input has anisotropic locations, only the xvalue is used.

        .. versionadded:: 5.0
        c                   s0   i | ](}|j |j ˆ v r&| ˆ |j  ¡n|j“qS r+   )re   rº   rŠ   rð   rv   r+   r,   r×   ¯
  s
   ûÿz4DesignSpaceDocument.map_backward.<locals>.<dictcomp>rñ   )r1   rt   r+   rv   r,   rº   ¦
  s    	
úz DesignSpaceDocument.map_backwardc                 C  s:   d| _ |  ¡ }| jD ] }| | ¡|kr|| _ |  S qdS )aÒ  Set and return SourceDescriptor at the default location or None.

        The default location is the set of all `default` values in user space
        of all axes.

        This function updates the document's :attr:`default` value.

        .. versionchanged:: 5.0
           Allow the default source to not specify some of the axis values, and
           they are assumed to be the default.
           See :meth:`SourceDescriptor.getFullDesignLocation()`
        N)rŠ   r9  r  r   )r1   ZdefaultDesignLocationræ  r+   r+   r,   rÚ  ¸
  s    

zDesignSpaceDocument.findDefaultc                   sv   ddl m} i }| jD ]Z‰ ˆ j|vr&q|ˆ j }t|tƒrB|d }‡ fdd„ˆ jˆ jˆ jfD ƒ}|||ƒ|ˆ j< q|S )z*Return a dict with normalized axis values.r   )ÚnormalizeValuec                   s   g | ]}ˆ   |¡‘qS r+   )r‰   rH   ©rŒ   r+   r,   rK   ß
  s   z9DesignSpaceDocument.normalizeLocation.<locals>.<listcomp>)	rØ   r  rˆ   re   rN   rÚ   r˜   rŠ   r™   )r1   rg   r  Únewr7   Útripler+   r  r,   ÚnormalizeLocationÒ
  s    




ÿz%DesignSpaceDocument.normalizeLocationc              
   C  sò  | j D ]}|  |j¡|_q| jD ]X}|j ¡ D ]:\}}|  |d ¡|d< |d D ]}|  |d ¡|d< qPq.|  |j¡|_q | jD ]¨}g }|jD ].\}}|  |j|i¡ 	|j¡}	| 
||	f¡ qŽ|rÈ||_|  |j|ji¡ 	|j¡}
|  |j|ji¡ 	|j¡}|  |j|ji¡ 	|j¡}|
|_||_||_q€| jD ]¼}g }|jD ]¤}g }|D ]Š}| 	d¡dur€|  |d |d i¡ 	|d ¡}
nd}
| 	d¡dur¶|  |d |d i¡ 	|d ¡}nd}| 
t|d |
|d¡ qJ| 
|¡ q>||_q0dS )	zÞ
        Normalise the geometry of this designspace:

        - scale all the locations of all masters and instances to the -1 - 0 - 1 value.
        - we need the axis data to do the scaling, so we do those last.
        r  r  rg   r˜   Nre   r™   )re   r˜   r™   )r  r	  rg   r  r©   rM   rˆ   rÌ   re   r€   rœ   r˜   r™   rŠ   r   r   rÂ   )r1   ÚitemrE   rÕ  ZglyphMasterrŒ   ZnewMaprT  rU  ZnewOutputValuer˜   r™   rŠ   r–   ZnewConditionSetsrš   ZnewConditionsrH  r+   r+   r,   Ú	normalizeå
  sF    




""zDesignSpaceDocument.normalizec                 K  s   i }g }| j D ]|}|jdur*| |j¡ q|j|v rB||j |_n<|jdu r^td|jpXd ƒ‚||jfi |¤Ž|_|j||j< | |j¡ q|S )a¢  Ensure SourceDescriptor.font attributes are loaded, and return list of fonts.

        Takes a callable which initializes a new font object (e.g. TTFont, or
        defcon.Font, etc.) from the SourceDescriptor.path, and sets the
        SourceDescriptor.font attribute.
        If the font attribute is already not None, it is not loaded again.
        Fonts with the same path are only loaded once and shared among SourceDescriptors.

        For example, to load UFO sources using defcon:

            designspace = DesignSpaceDocument.fromfile("path/to/my.designspace")
            designspace.loadSourceFonts(defcon.Font)

        Or to load masters as FontTools binary fonts, including extra options:

            designspace.loadSourceFonts(ttLib.TTFont, recalcBBoxes=False)

        Args:
            opener (Callable): takes one required positional argument, the source.path,
                and an optional list of keyword arguments, and returns a new font object
                loaded from the path.
            **kwargs: extra options passed on to the opener function.

        Returns:
            List of font objects in the order they appear in the sources list.
        Nz/Designspace source '%s' has no 'path' attributez	<Unknown>)r  rs   rœ   r'   r   re   )r1   Úopenerrè  ZloadedÚfontsrc   r+   r+   r,   ÚloadSourceFonts  s$    



ÿÿz#DesignSpaceDocument.loadSourceFontsc                 C  s>   | j du rdS dd„ | j  d¡D ƒ}t|ƒ}t|dƒ}||fS )z^Return the formatVersion as a tuple of (major, minor).

        .. versionadded:: 5.0
        Nr3  c                 s  s   | ]}t |ƒV  qd S r.   rÔ  r  r+   r+   r,   r”   Q  r\   z2DesignSpaceDocument.formatTuple.<locals>.<genexpr>r  r   )rœ  r%   rÞ   )r1   ÚnumbersÚmajorÚminorr+   r+   r,   r5  I  s    

zDesignSpaceDocument.formatTuplezList[VariableFontDescriptor]rç   c           	   
   C  s  | j r| j S g }g }g }| jD ]6}t|dƒrBtt|ƒ}| |¡ q| t|jd¡ qtj	dd„ |D ƒŽ }|D ]¤}d}| j
dur–tj | j
¡d d }| jdur¾tj tj | j¡¡d d }|du rÊd}d	 d
d„ t||ƒD ƒ¡}| t|› |› |dd„ t||ƒD ƒ d¡ qn|S )a  Return all variable fonts defined in this document, or implicit
        variable fonts that can be built from the document's continuous axes.

        In the case of Designspace documents before version 5, the whole
        document was implicitly describing a variable font that covers the
        whole space.

        In version 5 and above documents, there can be as many variable fonts
        as there are locations on discrete axes.

        .. seealso:: :func:`splitInterpolable`

        .. versionadded:: 5.0
        rÜ   rÁ  c                 S  s   g | ]
}|j ‘qS r+   )rÜ   rð   r+   r+   r,   rK   t  r\   z8DesignSpaceDocument.getVariableFonts.<locals>.<listcomp>Nr   z-VFZVFr>   c                 S  s    g | ]\}}d |j › |› ‘qS )ú-)rÆ   ©rI   rŒ   r7   r+   r+   r,   rK   }  r\   c                 S  s   g | ]\}}t |j|d ‘qS )rú   )r   re   r  r+   r+   r,   rK   €  s   ÿ)re   ró   )r#  rˆ   rG   r   r   rœ   r   re   Ú	itertoolsÚproductrd   r&   r'   Úsplitextrà  r$   Úzipr    )	r1   r#  ZdiscreteAxesZrangeAxisSubsetsrŒ   ZvalueCombinationsrÜ   rà  Z	axisNamesr+   r+   r,   ÚgetVariableFontsV  s6    





þþ
z$DesignSpaceDocument.getVariableFontsc              	   C  s    dd„ | j D ƒ}zl| j D ]
}d|_qt | ¡}t|j |ƒD ]\}}||_q:|W t| j |ƒD ]\}}||_qZS ]\}}||_qlnt| j |ƒD ]\}}||_qŠ0 dS )zñAllow deep-copying a DesignSpace document without deep-copying
        attached UFO fonts or TTFont objects. The :attr:`font` attribute
        is shared by reference between the original and the copy.

        .. versionadded:: 5.0
        c                 S  s   g | ]
}|j ‘qS r+   )rs   r2  r+   r+   r,   rK   Ž  r\   z;DesignSpaceDocument.deepcopyExceptFonts.<locals>.<listcomp>N)r  rs   r{  Údeepcopyr  )r1   r  rc   Úresrs   r+   r+   r,   ÚdeepcopyExceptFonts‡  s    

ý
ÿz'DesignSpaceDocument.deepcopyExceptFonts)NN)NN)NN)N)TTF),rA   rB   rC   rb   r=   rš  rÙ  r¢  rÞ  rª  r'  rä  rá  rç  ré  rë  rì  rî  rï  rñ  rò  rô  rõ  r÷  rø  r9  rý  rÿ  r   r  r  r  r  r¶   r‰   rº   rÚ  r	  r  r  r9   r5  r  r  r+   r+   r+   r,   r   	  sT    
W

0



5/
1r   )?Ú
__future__r   rù  r{  r  rø   r&   r#   Úior   r   Útextwrapr   Útypingr   r   r   r	   r
   r   r   r   ZfontTools.miscr   r  r   ZfontTools.misc.loggingToolsr   ZfontTools.misc.textToolsr   r   Ú__all__ZXML_NSrb  r-   r:   Ú	Exceptionr   ÚobjectrD   rR   r   r   r—   r’   rŸ   r?   r¯  r„   r¹   r   rÇ   rÈ   r   r   r   r   r    r   r   r   r   r   r+   r+   r+   r,   Ú<module>   sf   (
 T3  Q>b^LA+   f    8