o
    Ðùawâ  ã                   @   sH  d dl mZ d dlmZmZ d dlZd dlmZmZ d dl	Z	d dl
Z
d dlmZ d dl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G dd„ deƒ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eƒZ#dS )*é    )ÚLogMixin)ÚtobytesÚtostrN)ÚBytesIOÚStringIO)Úetree)Úplistlib)ÚDesignSpaceDocumentErrorÚDesignSpaceDocumentÚSourceDescriptorÚInstanceDescriptorÚAxisDescriptorÚRuleDescriptorÚBaseDocReaderÚBaseDocWriterz&{http://www.w3.org/XML/1998/namespace}Úlangc                 C   s@   t j|  tjj¡Ž }|  d¡rd| }|S |  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   úC/usr/lib/python3/dist-packages/fontTools/designspaceLib/__init__.pyÚposix   s   

ýr   c                    s"   ‡ fdd„}‡ fdd„}t ||ƒS )Nc                    s
   t | ˆ ƒS ©N)Úgetattr©Úself©Úprivate_namer   r   Úgetter+   ó   
z"posixpath_property.<locals>.getterc                    s    |d urt |ƒ}t| ˆ |ƒ d S r   )r   Úsetattr)r!   Úvaluer"   r   r   Úsetter/   s   z"posixpath_property.<locals>.setter)Úproperty)r#   r$   r(   r   r"   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)r!   r+   r,   r   r   r   Ú__init__9   s   
z!DesignSpaceDocumentError.__init__c                 C   s$   t | jƒ| jd urd| j  S d S )Nz: %rÚ )Ústrr+   r,   r    r   r   r   Ú__str__=   s
   ÿÿz DesignSpaceDocumentError.__str__r   )Ú__name__Ú
__module__Ú__qualname__r-   r0   r   r   r   r   r	   8   s    
r	   c                   @   s   e Zd Zdd„ ZdS )ÚAsDictMixinc                 C   s\   i }| j  ¡ D ]$\}}| d¡rqt|dƒr| ¡ }nt|tƒr'dd„ |D ƒ}|||< q|S )NÚ_Úasdictc                 S   s"   g | ]}t |d ƒr| ¡ n|‘qS )r6   )Úhasattrr6   ©Ú.0Úvr   r   r   Ú
<listcomp>L   s    ÿz&AsDictMixin.asdict.<locals>.<listcomp>)Ú__dict__Úitemsr   r7   r6   Ú
isinstanceÚlist)r!   ÚdÚattrr'   r   r   r   r6   D   s   



ÿ
zAsDictMixin.asdictN)r1   r2   r3   r6   r   r   r   r   r4   B   s    r4   c                   @   s   e Zd ZdZdd„ ZdS )ÚSimpleDescriptorz% Containers for a bunch of attributesc                 C   sZ   | j D ]'}zt| |ƒt||ƒksJ ‚W q ty*   td|t| |ƒdt||ƒƒ Y qw d S )Nzfailed attributez!=)Ú_attrsr   ÚAssertionErrorÚprint)r!   ÚotherrA   r   r   r   ÚcompareX   s   
 ÿýzSimpleDescriptor.compareN)r1   r2   r3   Ú__doc__rG   r   r   r   r   rB   S   s    rB   c                   @   sV   e Zd ZdZdZg d¢Zddddddddddddddddœdd„Zed	ƒZed
ƒZ	dS )r   z/Simple container for data related to the sourceÚsource)Úfilenamer   ÚnameÚ	layerNameÚlocationÚcopyLibÚ
copyGroupsÚcopyFeaturesÚmuteKerningÚmuteInfoÚmutedGlyphNamesÚ
familyNameÚ	styleNameNF©rJ   r   ÚfontrK   rM   rL   rT   rU   rN   ÚcopyInforO   rP   rQ   rR   rS   c                C   sh   || _ 	 || _	 || _	 || _|| _|| _|| _|| _|	| _|
| _	|| _
|| _|| _|| _|p0g | _d S r   rV   )r!   rJ   r   rW   rK   rM   rL   rT   rU   rN   rX   rO   rP   rQ   rR   rS   r   r   r   r-   k   s$   zSourceDescriptor.__init__Ú_pathÚ	_filename)
r1   r2   r3   rH   ÚflavorrC   r-   r*   r   rJ   r   r   r   r   r   a   s,    
ï3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

    .. code-block:: 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>
    ©rK   ÚconditionSetsÚsubsNc                C   s   || _ |pg | _|pg | _d S r   r\   )r!   rK   r]   r^   r   r   r   r-   ¶   s   
zRuleDescriptor.__init__)r1   r2   r3   rH   rC   r-   r   r   r   r   r   ¢   s    r   c                    s   t ‡ fdd„| jD ƒƒS )zK Return True if any of the rule's conditionsets matches the given location.c                 3   s    | ]}t |ˆ ƒV  qd S r   )ÚevaluateConditions)r9   Úc©rM   r   r   Ú	<genexpr>À   s   € zevaluateRule.<locals>.<genexpr>)Úanyr]   )ÚrulerM   r   ra   r   ÚevaluateRule¾   s   re   c                 C   s†   | D ]>}||d  }|  d¡du r||d kr dS q|  d¡du r,|d |kr+ dS q|d |  kr<|d ks@ dS   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.
    rK   ÚminimumNÚmaximumFT)Úget)Ú
conditionsrM   Úcdr'   r   r   r   r_   Ã   s    ÿÿÿÿr_   c           	      C   sl   g }| D ]/}t ||ƒr3|D ]!}d}|jD ]\}}||kr d} nq|r)| |¡ q| |¡ q|}g }q|S )zY Apply these rules at this location to these glyphnames
        - rule order matters
    FT)re   r^   Úappend)	ÚrulesrM   Z
glyphNamesZnewNamesrd   rK   ZswapÚaÚbr   r   r   ÚprocessRulesÕ   s"   
þ€ro   c                   @   s°   e Zd ZdZdZdZg d¢Zdddddddddddddddddddœdd	„Zed
ƒZ	edƒZ
ddd„Zddd„Zddd„Zddd„Zddd„Zddd„Zddd„Zddd„ZdS )r   z1Simple container for data related to the instanceÚinstanceÚen)r   rK   rM   rT   rU   ÚpostScriptFontNameÚstyleMapFamilyNameÚstyleMapStyleNameÚkerningÚinfoÚlibNT©rJ   r   rW   rK   rM   rT   rU   rr   rs   rt   ÚlocalisedFamilyNameÚlocalisedStyleNameÚlocalisedStyleMapFamilyNameÚlocalisedStyleMapStyleNameÚglyphsru   rv   rw   c                C   sˆ   || _ || _|| _|| _|| _|| _|| _|| _|	| _|
| _	|p!i | _
|p&i | _|p+i | _|p0i | _|p5i | _|| _|| _|p@i | _d S r   rx   )r!   rJ   r   rW   rK   rM   rT   rU   rr   rs   rt   ry   rz   r{   r|   r}   ru   rv   rw   r   r   r   r-   û   s&   





zInstanceDescriptor.__init__rY   rZ   c                 C   ó   t |ƒ| j|< d S r   )r   rz   )r!   rU   ÚlanguageCoder   r   r   ÚsetStyleName,  ó   zInstanceDescriptor.setStyleNamec                 C   ó   | j  |¡S r   )rz   rh   ©r!   r   r   r   r   ÚgetStyleName/  ó   zInstanceDescriptor.getStyleNamec                 C   r~   r   )r   ry   )r!   rT   r   r   r   r   ÚsetFamilyName2  r   z InstanceDescriptor.setFamilyNamec                 C   r‚   r   )ry   rh   rƒ   r   r   r   ÚgetFamilyName5  r…   z InstanceDescriptor.getFamilyNamec                 C   r~   r   )r   r|   )r!   rt   r   r   r   r   ÚsetStyleMapStyleName8  r   z'InstanceDescriptor.setStyleMapStyleNamec                 C   r‚   r   )r|   rh   rƒ   r   r   r   ÚgetStyleMapStyleName;  r…   z'InstanceDescriptor.getStyleMapStyleNamec                 C   r~   r   )r   r{   )r!   rs   r   r   r   r   ÚsetStyleMapFamilyName>  r   z(InstanceDescriptor.setStyleMapFamilyNamec                 C   r‚   r   )r{   rh   rƒ   r   r   r   ÚgetStyleMapFamilyNameA  r…   z(InstanceDescriptor.getStyleMapFamilyName©rq   )r1   r2   r3   rH   r[   Z_defaultLanguageCoderC   r-   r*   r   rJ   r€   r„   r†   r‡   rˆ   r‰   rŠ   r‹   r   r   r   r   r   ë   sD    ì.






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 r-||  ¡  S t| ƒdk r>| ddt| ƒ   }n| d d… }|t | dfS )NZwghtZWeightrŒ   ZwdthZWidthZopszzOptical SizeZslntZSlantZitalZItalic)ZweightÚwidthZopticalZslantZitalicé   Ú*)ÚdictÚlowerÚlen)rK   ÚnamesÚtagr   r   r   ÚtagForAxisNameE  s   ûr•   c                	   @   sP   e Zd ZdZdZg d¢Zdddddddddœdd„Zd	d
„ Zdd„ Zdd„ Z	dS )r   zH Simple container for the axis data
        Add more localisations?
    Úaxis)r”   rK   rg   rf   ÚdefaultÚmapNF)r”   rK   Ú
labelNamesrf   r—   rg   Úhiddenr˜   c          	      C   s<   || _ || _|p	i | _|| _|| _|| _|| _|pg | _d S r   )r”   rK   r™   rf   rg   r—   rš   r˜   )	r!   r”   rK   r™   rf   r—   rg   rš   r˜   r   r   r   r-   ^  s   
zAxisDescriptor.__init__c              
   C   s(   t | j| j| j| j| j| j| j| jdS )N)r”   rK   r™   rg   rf   r—   rš   r˜   )	r   r”   rK   r™   rg   rf   r—   rš   r˜   r    r   r   r   Ú	serializev  s   øzAxisDescriptor.serializec                 C   ó,   ddl m} | js|S ||dd„ | jD ƒƒS )Nr   ©ÚpiecewiseLinearMapc                 S   s   i | ]\}}||“qS r   r   ©r9   Úkr:   r   r   r   Ú
<dictcomp>ˆ  ó    z.AxisDescriptor.map_forward.<locals>.<dictcomp>©ÚfontTools.varLib.modelsrž   r˜   ©r!   r:   rž   r   r   r   Úmap_forwardƒ  ó   zAxisDescriptor.map_forwardc                 C   rœ   )Nr   r   c                 S   s   i | ]\}}||“qS r   r   rŸ   r   r   r   r¡     r¢   z/AxisDescriptor.map_backward.<locals>.<dictcomp>r£   r¥   r   r   r   Úmap_backwardŠ  r§   zAxisDescriptor.map_backward)
r1   r2   r3   rH   r[   rC   r-   r›   r¦   r¨   r   r   r   r   r   W  s     ör   c                   @   s¤   e Zd Zd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„ Zd!dd„Zd"dd„Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ ZdS )#r   z    c                 C   ó   |   ¡ S r   )ÚaxisDescriptorClass©Úclsr   r   r   ÚgetAxisDecriptor™  ó   zBaseDocWriter.getAxisDecriptorc                 C   r©   r   )ÚsourceDescriptorClassr«   r   r   r   ÚgetSourceDescriptor  r®   z!BaseDocWriter.getSourceDescriptorc                 C   r©   r   )ÚinstanceDescriptorClassr«   r   r   r   ÚgetInstanceDescriptor¡  r®   z#BaseDocWriter.getInstanceDescriptorc                 C   r©   r   )ÚruleDescriptorClassr«   r   r   r   ÚgetRuleDescriptor¥  r®   zBaseDocWriter.getRuleDescriptorc                 C   s<   || _ || _d| _t d¡| _| j| jjd< g | _g | _d S )Nz4.1ZdesignspaceÚformat)	r   ÚdocumentObjectZdocumentVersionÚETÚElementÚrootÚattribÚ_axesÚ_rules)r!   ÚdocumentPathr¶   r   r   r   r-   ©  s   
zBaseDocWriter.__init__TúUTF-8c           
      C   s"  | j jr| j t d¡¡ | j jD ]}|  |¡ q| j jr5t| j ddƒr)ddi}ni }| j t d|¡¡ | j jD ]}|  	|¡ q9| j j
rN| j t d¡¡ | j j
D ]}|  |¡ qR| j jrg| j t d¡¡ | j jD ]}|  |¡ qk| j jr~|  | j j¡ t | j¡}	|	j| j|d	||d
 d S )NÚaxesÚrulesProcessingLastFÚ
processingÚlastrl   ÚsourcesÚ	instancesZxml)ÚencodingÚmethodÚxml_declarationZpretty_print)r¶   r¿   r¹   rk   r·   r¸   Ú_addAxisrl   r   Ú_addRulerÃ   Ú
_addSourcerÄ   Ú_addInstancerw   Ú_addLibZElementTreeÚwriter   )
r!   ZprettyrÅ   rÇ   Ú
axisObjectZ
attributesÚ
ruleObjectÚsourceObjectÚinstanceObjectÚtreer   r   r   rÍ   ²  s:   

ûzBaseDocWriter.writeNc           
      C   sÆ   t  d¡}|dur||jd< | j ¡ }| ¡ D ]\}}||v r#|||< q| ¡ D ]6\}}t  d¡}	||	jd< t|ƒtkrQ|  |d ¡|	jd< |  |d ¡|	jd< n|  |¡|	jd< | 	|	¡ q(||fS )	z, Convert Location dict to a locationElement.rM   NrK   Z	dimensionr   Úxvalueé   Úyvalue)
r·   r¸   rº   r¶   ÚnewDefaultLocationr=   ÚtypeÚtupleÚ
intOrFloatrk   )
r!   ZlocationObjectrK   Z
locElementZvalidatedLocationZaxisNameZ	axisValueZdimensionNameZdimensionValueZ
dimElementr   r   r   Ú_makeLocationElement×  s"   


€

z"BaseDocWriter._makeLocationElementc                 C   s   t |ƒ|kr
d| S d| S )Nz%dz%f©Úint)r!   Znumr   r   r   rÙ   ì  s   zBaseDocWriter.intOrFloatc           	      C   sJ  | j  |¡ t d¡}|jd ur|j|jd< |jD ]Z}t d¡}|D ]G}| d¡d u r3| d¡d u r3q"t d¡}| d¡|jd< | d¡d urR|  | d¡¡|jd< | d¡d urd|  | d¡¡|jd< | |¡ q"t	|ƒrs| |¡ q|j
D ]}t d¡}|d |jd< |d	 |jd
< | |¡ qwt	|ƒr£| j d¡d  |¡ d S d S )Nrd   rK   Zconditionsetrf   rg   Z	conditionÚsubr   rÔ   Úwithú.rules)r¼   rk   r·   r¸   rK   rº   r]   rh   rÙ   r’   r^   r¹   Úfindall)	r!   rÏ   ÚruleElementri   ZconditionsetElementÚcondÚconditionElementrÝ   Ú
subElementr   r   r   rÉ   ñ  s6   





€

ÿzBaseDocWriter._addRulec           	      C   s  | j  |¡ t d¡}|j|jd< |j|jd< |  |j¡|jd< |  |j	¡|jd< |  |j
¡|jd< |jr:d|jd< t|j ¡ ƒD ]\}}t d	¡}||jt< ||_| |¡ qA|jr}|jD ]\}}t d
¡}|  |¡|jd< |  |¡|jd< | |¡ q^| j d¡d  |¡ d S )Nr–   r”   rK   rf   rg   r—   Ú1rš   Ú	labelnamer˜   ÚinputÚoutputz.axesr   )r»   rk   r·   r¸   r”   rº   rK   rÙ   rf   rg   r—   rš   Úsortedr™   r=   ÚXML_LANGÚtextr˜   r¹   rà   )	r!   rÎ   ÚaxisElementr   Z	labelNameZlanguageElementÚ
inputValueÚoutputValueÚ
mapElementr   r   r   rÈ     s*   




zBaseDocWriter._addAxisc                 C   s*  t  d¡}|jd ur|j|jd< |jd ur|j|jd< |jd ur&|j|jd< |jrSt|j ¡ ƒ}| 	¡  |D ]}|dkr=q6t  d¡}||jt
< | |¡|_| |¡ q6|jr€t|j ¡ ƒ}| 	¡  |D ]}|dkrjqct  d¡}||jt
< | |¡|_| |¡ qc|jr­t|j ¡ ƒ}| 	¡  |D ]}|dkr—qt  d¡}||jt
< | |¡|_| |¡ q|jrÚt|j ¡ ƒ}| 	¡  |D ]}|dkrÄq½t  d¡}||jt
< | |¡|_| |¡ q½|jd urí|  |j¡\}	|_| |	¡ |jd urø|j|jd< |jd ur|j|jd	< |jd ur|j|jd< |jd ur|j|jd< |jrS| d
¡g kr2t  d¡}
| |
¡ | d
¡d }
t|j ¡ ƒD ]\}}|  ||||¡}|
 |¡ q@|jrat  d¡}| |¡ |j rot  d¡}| |¡ |j!rˆt  d¡}| t"j#|j!dd¡ | |¡ | j$ d¡d  |¡ d S )Nrp   rK   Ú
familynameÚ	stylenamerq   ÚstylemapstylenameÚstylemapfamilynamerJ   Úpostscriptfontnamez.glyphsr}   r   ru   rv   rw   rŽ   ©Zindent_levelz
.instances)%r·   r¸   rK   rº   rT   rU   rz   r?   ÚkeysÚsortrê   r„   rë   rk   ry   r‡   r|   r‰   r{   r‹   rM   rÚ   rJ   rr   rs   rt   r}   rà   ré   r=   Ú_writeGlyphElementru   rv   rw   r   Útotreer¹   )r!   rÑ   ÚinstanceElementZlanguageCodesÚcodeZlocalisedStyleNameElementZlocalisedFamilyNameElementZ!localisedStyleMapStyleNameElementZ"localisedStyleMapFamilyNameElementÚlocationElementZglyphsElementÚ	glyphNameÚdataÚglyphElementÚkerningElementÚinfoElementÚ
libElementr   r   r   rË   %  sš   






















zBaseDocWriter._addInstancec                 C   sÈ  t  d¡}|jd ur|j|jd< |jd ur#|j d¡dkr#|j|jd< |jd ur.|j|jd< |jd ur9|j|jd< |jd urD|j|jd< |j	rVt  d	¡}d
|jd< | 
|¡ |jrht  d¡}d
|jd< | 
|¡ |jrzt  d¡}d
|jd< | 
|¡ |js€|jršt  d¡}|jrd
|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¡\}
|_| 
|
¡ | j d¡d  
|¡ d S )NrI   rJ   Ztemp_masterr   rK   rð   rñ   Úlayerrw   rå   ÚcopyÚgroupsZfeaturesrv   Úmuteru   Úglyphz.sources)r·   r¸   rJ   rº   rK   ÚfindrT   rU   rL   rN   rk   rO   rP   rX   rR   rQ   rS   rÚ   rM   r¹   rà   )r!   rÐ   ÚsourceElementr  ÚgroupsElementÚfeaturesElementr  r   rK   rÿ   rü   r   r   r   rÊ   v  sX   


























zBaseDocWriter._addSourcec                 C   s.   t  d¡}| tj|dd¡ | j |¡ d S )Nrw   é   rõ   )r·   r¸   rk   r   rù   r¹   )r!   r   r  r   r   r   rÌ   ¥  s   
zBaseDocWriter._addLibc                 C   sr  t  d¡}| d¡rd|jd< | d¡d ur&d dd„ | d¡D ƒ¡|jd< | d	¡d ur>|  | d	¡¡\}|d	< | |¡ |d urG||jd
< | d¡d ur^t  d¡}| d¡|_| |¡ | d¡d ur·t  d¡}| d¡D ]B}	t  d¡}
|	 d¡d ur…|	 d¡|
jd< |	 d¡d ur”|	 d¡|
jd< |	 d¡d ur¬|  |	 d¡¡\}|	d< |
 |¡ | |
¡ qo| |¡ |S )Nr  r  rå   Úunicodesú c                 S   s   g | ]}t |ƒ‘qS r   )Úhex©r9   Úur   r   r   r;   ¯  s    z4BaseDocWriter._writeGlyphElement.<locals>.<listcomp>ÚunicodeÚinstanceLocationrK   ÚnoteÚmastersZmasterrý   Ú	glyphnamerW   rI   rM   )r·   r¸   rh   rº   r   rÚ   rk   rë   )r!   rú   rÑ   rý   rþ   rÿ   rü   ÚnoteElementZmastersElementÚmÚmasterElementr   r   r   rø   ª  s8   


 







z BaseDocWriter._writeGlyphElement)Tr¾   Tr   )r1   r2   r3   Z_whiteSpacer   r³   r   rª   r   r¯   r   r±   Úclassmethodr­   r°   r²   r´   r-   rÍ   rÚ   rÙ   rÉ   rÈ   rË   rÊ   rÌ   rø   r   r   r   r   r   ’  s0    




	
%Q/r   c                   @   s¦   e Zd 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„ 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!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º   rh   ÚformatVersionr»   rl   rÃ   rÄ   ÚaxisDefaultsÚ_strictAxisNames)r!   r½   r¶   rÒ   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¶   Úfr!   r   r   r   Ú
fromstringÜ  s   
zBaseDocReader.fromstringc                 C   s,   |   ¡  |  ¡  |  ¡  |  ¡  |  ¡  d S r   )ÚreadAxesÚ	readRulesÚreadSourcesÚreadInstancesÚreadLibr    r   r   r   Úreadã  s
   zBaseDocReader.readc                 C   s  g }| j  d¡}|d ur#|j dd¡}|dvrtd| ƒ‚|dk| j_| j  d¡D ]Z}|  ¡ }|j d¡ }|_	|  
||¡}|rL|j |¡ | j d	¡ | d
¡D ]}|  
||¡}	|	d urc|j |	¡ qQ| d¡D ]}
|
jd }|
jd }|j ||f¡ qi| |¡ q)|| j_d S )Nrß   rÁ   Úfirst>   rÂ   r)  zO<rules> processing attribute value is not valid: %r, expected 'first' or 'last'rÂ   z.rules/rulerK   zWFound stray rule conditions outside a conditionset. Wrapped them in a new conditionset.z.conditionsetz.subrÞ   )r¹   r  rº   rh   r	   r¶   rÀ   rà   r³   rK   Ú_readConditionElementsr]   rk   Úlogrv   r^   rl   )r!   rl   ZrulesElementZprocessingValuerá   rÏ   ÚruleNameZexternalConditionsZconditionSetElementZconditionSeträ   rm   rn   r   r   r   r$  ê  sJ   ÿÿþÿþ€

zBaseDocReader.readRulesNc                 C   sÆ   g }|  d¡D ]Y}i }|j d¡}|d urt|ƒ|d< nd |d< |j d¡}|d ur1t|ƒ|d< nd |d< |j d¡|d< | d¡d u r[| d¡d u r[td|d urWd|  ƒ‚d ƒ‚| |¡ q|S )Nz
.conditionrf   rg   rK   z5condition missing required minimum or maximum in rulez '%s'r.   )rà   rº   rh   Úfloatr	   rk   )r!   ZparentElementr,  Zcdsrã   rj   ZcdMinZcdMaxr   r   r   r*    s.   ÿÿÿÿz$BaseDocReader._readConditionElementsc           
      C   s"  | j  d¡}|s
d S |D ]‚}|  ¡ }|j d¡|_t|j d¡ƒ|_t|j d¡ƒ|_|j dd¡r5d|_	t|j d¡ƒ|_
|j d	¡|_| d
¡D ]}t|jd ƒ}t|jd ƒ}|j ||f¡ qJ| d¡D ]}| ¡ D ]\}}	|tkr~t|jƒ|j|	< qnqh| jj |¡ |j
| j|j< qd S )Nz
.axes/axisrK   rf   rg   rš   FTr—   r”   r˜   rç   rè   ræ   )r¹   rà   rª   rº   rh   rK   r-  rf   rg   rš   r—   r”   r˜   rk   r=   rê   r   rë   r™   r¶   r¿   r  )
r!   ZaxisElementsrì   rÎ   rï   rm   rn   ZlabelNameElementÚkeyr   r   r   r   r#  +  s2   €þìzBaseDocReader.readAxesc                 C   s  t | j d¡ƒD ]\}}|j d¡}|d ur-| jd ur-tj tj tj 	| j¡|¡¡}nd }|j d¡}|d u r=d| }|  
¡ }||_||_||_|j d¡}|d urW||_|j d¡}|d urd||_|  |¡|_|j d¡}	|	d urw|	|_| d¡D ]}
|
j d	¡d
kr‰d|_q|| d¡D ]}|j d	¡d
krœd|_q| d¡D ]}|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 ràqÓ|j d¡d
krî|j |¡ qÓ| d¡D ]}|j d¡d
krd|_qô| jj |¡ qd S )Nz.sources/sourcerJ   rK   ztemp_master.%drð   rñ   r  ú.libr  rå   Tz.groupsz.infor  z	.featuresz.glyphz.kerning)Ú	enumerater¹   rà   rº   rh   r   r   Úabspathr   Údirnamer¯   rJ   rK   rT   rU   ÚlocationFromElementrM   rL   rN   rO   rX   rR   rP   rS   rk   rQ   r¶   rÃ   )r!   ZsourceCountr	  rJ   Z
sourcePathZ
sourceNamerÐ   rT   rU   rL   r  r
  r  r  rÿ   rý   r   r   r   r   r%  F  sj   "€€€€€€ÑzBaseDocReader.readSourcesc                 C   s&   d }|  d¡D ]	}|  |¡} |S |S )Nz	.location)rà   ÚreadLocationElement)r!   ÚelementZelementLocationrü   r   r   r   r3  x  s
   
z!BaseDocReader.locationFromElementc              	   C   sî   | j r| jjstdƒ‚i }| d¡D ]b}|j d¡}| j r*|| jvr*| j 	d|¡ qd }}z|j d¡}t
|ƒ}W n tyJ   | j 	d|¡ Y nw z|j d¡}|durZt
|ƒ}W n	 tyd   Y nw |durp||f||< q|||< q|S )	z Format 0 location reader zNo axes definedz
.dimensionrK   z#Location with undefined axis: "%s".NrÓ   z%KeyError in readLocation xValue %3.3frÕ   )r  r¶   r¿   r	   rà   rº   rh   r  r+  Zwarningr-  Ú
ValueError)r!   rü   ÚlocZdimensionElementZdimNameZxValueZyValuer   r   r   r4    s6   ÿ€ÿ
z!BaseDocReader.readLocationElementTc                 C   s,   | j  d¡}|D ]}| j||||d qd S )Nz.instances/instance)Ú
makeGlyphsÚmakeKerningÚmakeInfo)r¹   rà   Ú_readSingleInstanceElement)r!   r8  r9  r:  ZinstanceElementsrú   r   r   r   r&  œ  s   ÿzBaseDocReader.readInstancesc                 C   sd  |j  d¡}|d ur| jjd urtj tj | jj¡|¡}nd }|  ¡ }||_||_|j  d¡}|d ur7||_	|j  d¡}	|	d urD|	|_
|j  d¡}
|
d urQ|
|_|j  d¡}|d ur^||_|j  d¡}|d urk||_|j  d¡}|d urx||_| d¡D ]}| ¡ D ]\}}|tkr”|j}| ||¡ qƒq}| d¡D ]}| ¡ D ]\}}|tkr²|j}| ||¡ q¡q›| d¡D ]}| ¡ D ]\}}|tkrÐ|j}| ||¡ q¿q¹| d¡D ]}| ¡ D ]\}}|tkrî|j}| ||¡ qÝq×|  |¡}|d urü||_| d¡D ]	}|  ||¡ q| d	¡D ]	}|  ||¡ q| d
¡D ]	}|  ||¡ q| jj |¡ d S )NrJ   rK   rð   rñ   rô   ró   rò   z.glyphs/glyphrv   rw   )rº   rh   r¶   r   r   r   r2  r±   rJ   rK   rT   rU   rr   rs   rt   rà   r=   rê   rë   r€   r†   rˆ   rŠ   r3  rM   ÚreadGlyphElementÚreadInfoElementÚreadLibElementrÄ   rk   )r!   rú   r8  r9  r:  rJ   ZinstancePathrÑ   rK   rð   rñ   rr   rs   rt   ZstyleNameElementr.  r   rU   ZfamilyNameElementrT   ZstyleMapStyleNameElementZstyleMapFamilyNameElementr  rÿ   r  r  r   r   r   r;  ¡  s~   €ý€ý€ý€ý
z(BaseDocReader._readSingleInstanceElementc                 C   s   t  |d ¡|_dS )z,Read the lib element for the given instance.r   N)r   Úfromtreerw   )r!   r  rÑ   r   r   r   r>  Ü  s   zBaseDocReader.readLibElementc                 C   s
   d|_ dS )z Read the info element.TN)rv   )r!   r  rÑ   r   r   r   r=  à  r%   zBaseDocReader.readInfoElementc                 C   s   |   |¡}| |¡ dS )z Read the kerning element.N)r3  Z
addKerning)r!   r   rÑ   ZkerningLocationr   r   r   ÚreadKerningElementä  s   
z BaseDocReader.readKerningElementc                 C   sD  i }|j  d¡}|du rtdƒ‚|j  d¡}|dkrd|d< |j  d¡}|durFzdd	„ | d
¡D ƒ}||d< W n tyE   td| ƒ‚w | d¡D ]}|j|d<  |  |¡}|dur`||d< d}	| d¡D ]+}
|
j  d¡}|  |
¡}|
j  d¡}|du r€|}t|||d}|	du rg }	|	 	|¡ qg|	dur›|	|d< ||j
|< dS )a÷  
        Read the glyph element:

        .. 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>
        rK   Nz#Glyph object without name attributer  rå   Tr  c                 S   s   g | ]}t |d ƒ‘qS )é   rÛ   r  r   r   r   r;     r¢   z2BaseDocReader.readGlyphElement.<locals>.<listcomp>r  r  z"unicode values %s are not integersz.noter  r  z.masters/masterrI   r  )rW   rM   rý   r  )rº   rh   r	   r   r6  rà   rë   r3  r   rk   r}   )r!   rÿ   rÑ   Ú	glyphDatarý   r  r  r  r  ZglyphSourcesr  ZfontSourceNameZsourceLocationZmasterGlyphNamer@   r   r   r   r<  é  sL   ÿ


þ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¹   rà   r   r?  r¶   rw   )r!   r  r   r   r   r'  !  s   ÿzBaseDocReader.readLibr   )TTT)r1   r2   r3   r   r³   r   rª   r   r¯   r   r±   r-   r  r"  r(  r$  r*  r#  r%  r3  r4  r&  r;  r>  r=  r@  r<  r'  r   r   r   r   r   É  s,    

(2

;8r   c                   @   sú   e Zd ZdZd;dd„Zed;dd„ƒZed;dd„ƒZd<d	d
„Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd „ Zd!d"„ Zd#d$„ Zd=d'd(„Zd)d*„ Zd+d,„ Zd-d.„ Zd/d0„ Zd1d2„ Zd3d4„ Zd5d6„ Zd7d8„ Zd9d:„ ZdS )>r
   z+ Read, write data from the designspace fileNc                 C   sr   d | _ d | _	 d | _g | _g | _g | _g | _d| _d | _i | _		 |d ur(|| _
nt| _
|d ur4|| _d S t| _d S )NF)r   rJ   r  rÃ   rÄ   r¿   rl   rÀ   r—   rw   ÚreaderClassr   ÚwriterClassr   )r!   rC  rD  r   r   r   r-   )  s$   

zDesignSpaceDocument.__init__c                 C   s   | ||d}|  |¡ |S ©N)rC  rD  )r(  )r¬   r   rC  rD  r!   r   r   r   ÚfromfileI  s   
zDesignSpaceDocument.fromfilec                 C   s4   | ||d}|j  ||¡}| ¡  |jr| ¡  |S rE  )rC  r"  r(  rÃ   ÚfindDefault)r¬   r   rC  rD  r!   Úreaderr   r   r   r"  O  s   zDesignSpaceDocument.fromstringc                 C   sv   |t u s|d ur| ¡ dkrtƒ }d}n|d u s|dkr$tƒ }d}d}ntd| ƒ‚|  || ¡}|j||d | ¡ S )Nr  Fr  r¾   Tzunsupported encoding: '%s')rÅ   rÇ   )r/   r‘   r   r   r6  rD  rÍ   Úgetvalue)r!   rÅ   r!  rÇ   Úwriterr   r   r   ÚtostringX  s   ÿ
ÿzDesignSpaceDocument.tostringc                 C   sP   t |dƒr	| ¡ }|| _tj |¡| _|  || ¡}| ¡  | jr&|  	¡  d S d S ©NÚ
__fspath__)
r7   rM  r   r   ÚbasenamerJ   rC  r(  rÃ   rG  )r!   r   rH  r   r   r   r(  h  s   
ÿzDesignSpaceDocument.readc                 C   sF   t |dƒr	| ¡ }|| _tj |¡| _|  ¡  |  || ¡}| ¡  d S rL  )	r7   rM  r   r   rN  rJ   ÚupdatePathsrD  rÍ   )r!   r   rJ  r   r   r   rÍ   r  s   
zDesignSpaceDocument.writec                 C   s    t j |t j | j¡¡}t|ƒS r   )r   r   Úrelpathr2  r   )r!   Z	otherPathZ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Ä   rQ  rJ   )r!   Ú
descriptorr   r   r   rO    s   *
€ýzDesignSpaceDocument.updatePathsc                 C   ó   | j  |¡ d S r   )rÃ   rk   )r!   ÚsourceDescriptorr   r   r   Ú	addSource¯  ó   zDesignSpaceDocument.addSourcec                 K   ó    | j jdi |¤Ž}|  |¡ |S ©Nr   )rD  r¯   rU  )r!   ÚkwargsrI   r   r   r   ÚaddSourceDescriptor²  ó   
z'DesignSpaceDocument.addSourceDescriptorc                 C   rS  r   )rÄ   rk   )r!   ZinstanceDescriptorr   r   r   ÚaddInstance·  rV  zDesignSpaceDocument.addInstancec                 K   rW  rX  )rD  r±   r\  )r!   rY  rp   r   r   r   ÚaddInstanceDescriptorº  r[  z)DesignSpaceDocument.addInstanceDescriptorc                 C   rS  r   )r¿   rk   )r!   ÚaxisDescriptorr   r   r   ÚaddAxis¿  rV  zDesignSpaceDocument.addAxisc                 K   rW  rX  )rD  rª   r_  )r!   rY  r–   r   r   r   ÚaddAxisDescriptorÂ  r[  z%DesignSpaceDocument.addAxisDescriptorc                 C   rS  r   )rl   rk   )r!   ZruleDescriptorr   r   r   ÚaddRuleÇ  rV  zDesignSpaceDocument.addRulec                 K   rW  rX  )rD  r³   ra  )r!   rY  rd   r   r   r   ÚaddRuleDescriptorÊ  r[  z%DesignSpaceDocument.addRuleDescriptorc                 C   s*   t  ¡ }| jD ]}| |j¡||j< q|S )z(Return default location in design space.)ÚcollectionsÚOrderedDictr¿   r¦   r—   rK   )r!   r7  r^  r   r   r   rÖ   Ï  s   
ÿz&DesignSpaceDocument.newDefaultLocationTFc                 C   sx   |r| j D ]}|jd ur|sq| jd ur|  |j¡|_q|r8| jD ]}|jd ur+|s+q!| jd ur7|  |j¡|_q!d S d S r   )rÃ   rJ   r   rQ  rÄ   )r!   r  rÄ   ZforcerR  r   r   r   ÚupdateFilenameFromPathÚ  s    

€

€ûz*DesignSpaceDocument.updateFilenameFromPathc                 C   ó
   | j  ¡ S r   )rD  r­   r    r   r   r   ÚnewAxisDescriptorê  r%   z%DesignSpaceDocument.newAxisDescriptorc                 C   rf  r   )rD  r°   r    r   r   r   ÚnewSourceDescriptorî  r%   z'DesignSpaceDocument.newSourceDescriptorc                 C   rf  r   )rD  r²   r    r   r   r   ÚnewInstanceDescriptorò  r%   z)DesignSpaceDocument.newInstanceDescriptorc                 C   s    g }| j D ]}| |j¡ q|S r   )r¿   rk   rK   )r!   r“   r^  r   r   r   ÚgetAxisOrderö  s   
z DesignSpaceDocument.getAxisOrderc                 C   s"   | j D ]}|j|kr|  S qd S r   )r¿   rK   )r!   rK   r^  r   r   r   ÚgetAxisü  s
   

ÿzDesignSpaceDocument.getAxisc                 C   s6   d| _ |  ¡ }| jD ]}|j|kr|| _ |  S q
dS )z­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.
        N)r—   rÖ   rÃ   rM   )r!   Zdefault_location_designrT  r   r   r   rG    s   

þzDesignSpaceDocument.findDefaultc                    sv   ddl m} i }| jD ]-‰ ˆ j|vrq|ˆ j }t|tƒr!|d }‡ fdd„ˆ jˆ jˆ jfD ƒ}|||ƒ|ˆ j< q|S )Nr   )ÚnormalizeValuec                    s   g | ]}ˆ   |¡‘qS r   )r¦   r8   ©r–   r   r   r;   !  s    
ÿz9DesignSpaceDocument.normalizeLocation.<locals>.<listcomp>)	r¤   rl  r¿   rK   r>   rØ   rf   r—   rg   )r!   rM   rl  Únewr'   Ztripler   rm  r   ÚnormalizeLocation  s   




ÿz%DesignSpaceDocument.normalizeLocationc              
   C   sè  | j D ]	}|  |j¡|_q| jD ],}|j ¡ D ]\}}|  |d ¡|d< |d D ]}|  |d ¡|d< q(q|  |j¡|_q| jD ]T}g }|jD ]\}}|  |j|i¡ 	|j¡}	| 
||	f¡ qG|rd||_|  |j|ji¡ 	|j¡}
|  |j|ji¡ 	|j¡}|  |j|ji¡ 	|j¡}|
|_||_||_q@| jD ]Y}g }|jD ]N}g }|D ]B}| 	d¡d ur¿|  |d |d i¡ 	|d ¡}
nd }
| 	d¡d urÙ|  |d |d i¡ 	|d ¡}nd }| 
t|d |
|d¡ q¥| 
|¡ qŸ||_q˜d S )Nr  r  rM   rf   rK   rg   )rK   rf   rg   )rÃ   ro  rM   rÄ   r}   r=   r¿   r˜   rK   rh   rk   rf   rg   r—   rl   r]   r   )r!   Úitemr5   rB  ZglyphMasterr–   ZnewMaprí   rî   ZnewOutputValuerf   rg   r—   rd   ZnewConditionSetsri   ZnewConditionsrâ   r   r   r   Ú	normalize'  sJ   

ÿ


""ñzDesignSpaceDocument.normalizec                 K   s   i }g }| j D ]>}|jdur| |j¡ q|j|v r!||j |_n|jdu r/td|jp,d ƒ‚||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Ã   rW   rk   r   r	   rK   )r!   ZopenerrY  ZloadedZfontsrI   r   r   r   ÚloadSourceFontsY  s$   



ÿÿz#DesignSpaceDocument.loadSourceFonts)NNr   )TTF) r1   r2   r3   rH   r-   r  rF  r"  rK  r(  rÍ   rQ  rO  rU  rZ  r\  r]  r_  r`  ra  rb  rÖ   re  rg  rh  ri  rj  rk  rG  ro  rq  rr  r   r   r   r   r
   '  s>    
 

	0
2r
   )$ZfontTools.misc.loggingToolsr   ZfontTools.misc.textToolsr   r   rc  Úior   r   r   r   ZfontTools.miscr   r·   r   Ú__all__ZXML_NSrê   r   r*   Ú	Exceptionr	   Úobjectr4   rB   r   r   re   r_   ro   r   r•   r   r   r   r
   r   r   r   r   Ú<module>   s@   
AZ;  9  `