B
    ScM                 @   s   d Z ddddgZddlmZ ddlmZ d	d
 Zdd ZdddZd ddZ	dd Z
d!ddZd"ddZd#ddZG dd deZdd Zd$ddZedkrddlZddlZeejdkree  ee j dS )%z%Variation fonts interpolation models.normalizeValuenormalizeLocationsupportScalarVariationModel    )noRound   )VariationModelErrorc             C   s   dd | D S )Nc             S   s   g | ]}|d k	r|qS )N ).0lr	   r	   6lib/python3.7/site-packages/fontTools/varLib/models.py
<listcomp>   s    znonNone.<locals>.<listcomp>r	   )lstr	   r	   r   nonNone   s    r   c             C   s   t dd | D S )Nc             s   s   | ]}|d kV  qd S )Nr	   )r
   r   r	   r	   r   	<genexpr>   s    zallNone.<locals>.<genexpr>)all)r   r	   r	   r   allNone   s    r   Nc                s>   d krt fdd|D S  t  fdd|D S )Nc             3   s   | ]} |kV  qd S )Nr	   )r
   item)refr	   r   r      s    zallEqualTo.<locals>.<genexpr>c             3   s   | ]} |kV  qd S )Nr	   )r
   r   )mappedmapperr	   r   r      s    )r   )r   r   r   r	   )r   r   r   r   
allEqualTo   s    r   c             C   s@   | sdS t | }yt|}W n tk
r0   dS X t|||dS )NT)r   )iternextStopIterationr   )r   r   itfirstr	   r	   r   allEqual   s    r   c             C   s(   t | t |kstdd t|| D S )Nc             S   s   g | ]\}}|r|qS r	   r	   )r
   r   tr	   r	   r   r   +   s    zsubList.<locals>.<listcomp>)lenAssertionErrorzip)truthr   r	   r	   r   subList)   s    r#   Fc          
   C   s   |\}}}||  kr|ks@n t d|dd|dd|d|sTtt| ||} | |ksd||krhdS | |k rx||ks| |kr||kr| | ||  S | |kr||ks| |k r||kstd|  d| d| d| d	| | ||  S dS )	zNormalizes value based on a min/default/max triple.

      >>> normalizeValue(400, (100, 400, 900))
      0.0
      >>> normalizeValue(100, (100, 400, 900))
      -1.0
      >>> normalizeValue(650, (100, 400, 900))
      0.5
    z8Invalid axis values, must be minimum, default, maximum: z3.3fz, g        zOoops... v=z
, triple=()N)
ValueErrormaxminr    )vtripleextrapolatelowerdefaultupperr	   r	   r   r   .   s    

  c             C   s@   i }x6|  D ]*\}}| ||d }t|||d||< qW |S )a  Normalizes location based on axis min/default/max values from axes.

      >>> axes = {"wght": (100, 400, 900)}
      >>> normalizeLocation({"wght": 400}, axes)
      {'wght': 0.0}
      >>> normalizeLocation({"wght": 100}, axes)
      {'wght': -1.0}
      >>> normalizeLocation({"wght": 900}, axes)
      {'wght': 1.0}
      >>> normalizeLocation({"wght": 650}, axes)
      {'wght': 0.5}
      >>> normalizeLocation({"wght": 1000}, axes)
      {'wght': 1.0}
      >>> normalizeLocation({"wght": 0}, axes)
      {'wght': -1.0}
      >>> axes = {"wght": (0, 0, 1000)}
      >>> normalizeLocation({"wght": 0}, axes)
      {'wght': 0.0}
      >>> normalizeLocation({"wght": -1}, axes)
      {'wght': 0.0}
      >>> normalizeLocation({"wght": 1000}, axes)
      {'wght': 1.0}
      >>> normalizeLocation({"wght": 500}, axes)
      {'wght': 0.5}
      >>> normalizeLocation({"wght": 1001}, axes)
      {'wght': 1.0}
      >>> axes = {"wght": (0, 1000, 1000)}
      >>> normalizeLocation({"wght": 0}, axes)
      {'wght': -1.0}
      >>> normalizeLocation({"wght": -1}, axes)
      {'wght': -1.0}
      >>> normalizeLocation({"wght": 500}, axes)
      {'wght': -0.5}
      >>> normalizeLocation({"wght": 1000}, axes)
      {'wght': 0.0}
      >>> normalizeLocation({"wght": 1001}, axes)
      {'wght': 0.0}
    r   )r*   )itemsgetr   )locationaxesr*   outtagr)   r(   r	   r	   r   r   M   s
    'Tc             C   s  |r|dkrt dd}x| D ]\}\}}}	|rt|dkrBq$||ks$||	krTq$|dk rf|	dkrfq$| |d}
n|| kst| | }
|
|krq$|r\|| \}}|
|k r||kr||kr||	k r||
|	 ||	  9 }q$n||k r||
| ||  9 }q$n`||
k r\||	kr\||kr<||k r<||
| ||  9 }q$n ||k r\||
|	 ||	  9 }q$|
|ksp|	|
krvd}P |
|k r||
| ||  9 }q$||
|	 ||	  9 }q$W |S )a  Returns the scalar multiplier at location, for a master
    with support.  If ot is True, then a peak value of zero
    for support of an axis means "axis does not participate".  That
    is how OpenType Variation Font technology works.

    If extrapolate is True, axisRanges must be a dict that maps axis
    names to (axisMin, axisMax) tuples.

      >>> supportScalar({}, {})
      1.0
      >>> supportScalar({'wght':.2}, {})
      1.0
      >>> supportScalar({'wght':.2}, {'wght':(0,2,3)})
      0.1
      >>> supportScalar({'wght':2.5}, {'wght':(0,2,4)})
      0.75
      >>> supportScalar({'wght':2.5, 'wdth':0}, {'wght':(0,2,4), 'wdth':(-1,0,+1)})
      0.75
      >>> supportScalar({'wght':2.5, 'wdth':.5}, {'wght':(0,2,4), 'wdth':(-1,0,+1)}, ot=False)
      0.375
      >>> supportScalar({'wght':2.5, 'wdth':0}, {'wght':(0,2,4), 'wdth':(-1,0,+1)})
      0.75
      >>> supportScalar({'wght':2.5, 'wdth':.5}, {'wght':(0,2,4), 'wdth':(-1,0,+1)})
      0.75
      >>> supportScalar({'wght':3}, {'wght':(0,1,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
      -1.0
      >>> supportScalar({'wght':-1}, {'wght':(0,1,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
      -1.0
      >>> supportScalar({'wght':3}, {'wght':(0,2,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
      1.5
      >>> supportScalar({'wght':-1}, {'wght':(0,2,2)}, extrapolate=True, axisRanges={'wght':(0, 2)})
      -0.5
    Nz2axisRanges must be passed when extrapolate is Trueg      ?g        )	TypeErrorr.   r/   r    )r0   supportZotr*   
axisRangesscalaraxisr+   peakr-   r(   axisMinaxisMaxr	   r	   r   r   {   sN    "

c               @   s   e Zd ZdZd#ddZdd Zedd	 Zeg fd
dZdd Z	dd Z
dd Zdd ZedddZedddZdd Zedd Zdd Zeddd Zedd!d"ZdS )$r   az  Locations must have the base master at the origin (ie. 0).

    If the extrapolate argument is set to True, then values are extrapolated
    outside the axis range.

      >>> from pprint import pprint
      >>> locations = [       {'wght':100},       {'wght':-100},       {'wght':-180},       {'wdth':+.3},       {'wght':+120,'wdth':.3},       {'wght':+120,'wdth':.2},       {},       {'wght':+180,'wdth':.3},       {'wght':+180},       ]
      >>> model = VariationModel(locations, axisOrder=['wght'])
      >>> pprint(model.locations)
      [{},
       {'wght': -100},
       {'wght': -180},
       {'wght': 100},
       {'wght': 180},
       {'wdth': 0.3},
       {'wdth': 0.3, 'wght': 180},
       {'wdth': 0.3, 'wght': 120},
       {'wdth': 0.2, 'wght': 120}]
      >>> pprint(model.deltaWeights)
      [{},
       {0: 1.0},
       {0: 1.0},
       {0: 1.0},
       {0: 1.0},
       {0: 1.0},
       {0: 1.0, 4: 1.0, 5: 1.0},
       {0: 1.0, 3: 0.75, 4: 0.25, 5: 1.0, 6: 0.6666666666666666},
       {0: 1.0,
        3: 0.75,
        4: 0.25,
        5: 0.6666666666666667,
        6: 0.4444444444444445,
        7: 0.6666666666666667}]
    NFc                s   t tdd  D t  kr&td _|d k	r8|ng _|_|rR nd _dd  D  j jd}t	 |d_
fdd D _ fd	dj
D _  i _d S )
Nc             s   s   | ]}t t| V  qd S )N)tuplesortedr.   )r
   r   r	   r	   r   r      s    z*VariationModel.__init__.<locals>.<genexpr>zLocations must be unique.c             S   s   g | ]}d d |  D qS )c             S   s   i | ]\}}|d kr||qS )g        r	   )r
   kr(   r	   r	   r   
<dictcomp>  s    z6VariationModel.__init__.<locals>.<listcomp>.<dictcomp>)r.   )r
   locr	   r	   r   r     s    z+VariationModel.__init__.<locals>.<listcomp>)	axisOrder)keyc                s   g | ]} j |qS r	   )	locationsindex)r
   r   )selfr	   r   r     s    c                s   g | ]}  |qS r	   )rD   )r
   r   )rC   r	   r   r     s    )r   setr   origLocationsrA   r*   computeAxisRangesr6   getMasterLocationsSortKeyFuncr=   rC   mappingreverseMapping_computeMasterSupports
_subModels)rE   rC   rA   r*   ZkeyFuncr	   )rC   rE   r   __init__   s    zVariationModel.__init__c             C   sb   d |kr| |fS t dd |D }| j|}|d krTtt|| j| j}|| j|< |t||fS )Nc             s   s   | ]}|d k	V  qd S )Nr	   )r
   r(   r	   r	   r   r     s    z-VariationModel.getSubModel.<locals>.<genexpr>)r<   rM   r/   r   r#   rG   rA   )rE   r.   rB   ZsubModelr	   r	   r   getSubModel  s    
zVariationModel.getSubModelc             C   sj   i }dd | D }xR| D ]J}xD|D ]<}| |d}| |||f\}}t||t||f||< q"W qW |S )Nc             S   s   h | ]}|  D ]}|qqS r	   )keys)r
   r@   r8   r	   r	   r   	<setcomp>  s    z3VariationModel.computeAxisRanges.<locals>.<setcomp>r   )r/   r'   r&   )rC   r6   ZallAxesr@   r8   valuer:   r;   r	   r	   r   rH     s    

 z VariationModel.computeAxisRangesc             C   s   i | krt di }xl| D ]d}t|dkr,qtt|}|| }||krRdh||< ||| ksptd|||f || | qW dd }|||}|S )NzBase master not found.r   g        z&Value "%s" in axisPoints["%s"] -->  %sc                s   dd  fdd}|S )Nc             S   s   | dk rdS | dkrdS dS )Nr   r   r	   )r(   r	   r	   r   sign8  s    zJVariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.signc          	      s   t  }fdd  D } fddD }|fddt  D  |t | tfdd|D t|t fdd|D t fdd|D fS )	Nc                s(   g | ] \}}| kr| | kr|qS r	   r	   )r
   r8   rR   )
axisPointsr	   r   r   >  s   z]VariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.key.<locals>.<listcomp>c                s   g | ]}| kr|qS r	   r	   )r
   r8   )r@   r	   r   r   B  s    c                s   g | ]}| kr|qS r	   r	   )r
   r8   )rA   r	   r   r   D  s    c             3   s$   | ]}| kr  |nd V  qdS )i   N)rD   )r
   r8   )rA   r	   r   r   J  s   z\VariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.key.<locals>.<genexpr>c             3   s   | ]} | V  qd S )Nr	   )r
   r8   )r@   rT   r	   r   r   O  s    c             3   s   | ]}t  | V  qd S )N)abs)r
   r8   )r@   r	   r   r   R  s    )r   r.   extendr=   rP   r<   )r@   ZrankZonPointAxesZorderedAxes)rA   rU   rT   )r@   r   rB   ;  s     

zIVariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.keyr	   )rU   rA   rB   r	   )rA   rU   rT   r   getKey7  s    z<VariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey)r   r   r   r   r    add)rC   rA   rU   r@   r8   rR   rX   Zretr	   r	   r   rI   &  s     

!
z,VariationModel.getMasterLocationsSortKeyFuncc                sj   fdd|D }fdd|D _ dd j D  fdd D _ fddjD _i _|S )Nc                s   g | ]} | qS r	   r	   )r
   idx)master_listr	   r   r   ^  s    z1VariationModel.reorderMasters.<locals>.<listcomp>c                s   g | ]} j | qS r	   )rG   )r
   rZ   )rE   r	   r   r   _  s    c             S   s   g | ]}d d |  D qS )c             S   s   i | ]\}}|d kr||qS )g        r	   )r
   r>   r(   r	   r	   r   r?   a  s    z<VariationModel.reorderMasters.<locals>.<listcomp>.<dictcomp>)r.   )r
   r@   r	   r	   r   r   a  s    c                s   g | ]} j |qS r	   )rC   rD   )r
   r   )rE   r	   r   r   c  s    c                s   g | ]}  |qS r	   )rD   )r
   r   )rC   r	   r   r   d  s    )rG   rJ   rC   rK   rM   )rE   r[   rJ   Znew_listr	   )rC   r[   rE   r   reorderMasters[  s    zVariationModel.reorderMastersc             C   s  g | _ |  }xt|D ]\}}t| }x^|d | D ]L}t| |sZq@d}xV| D ]J\}\}}	}
||ks|| d |	ksh||| d   k r|
k shn d}P qhW |sq@i }d}x| D ]}|| d }||kst|| \}}}
||
 }}||k r"|}|| ||  }n ||k r|}|| |
|  }nq||krTi }|}||kr|||f||< qW x| D ]\}}|||< qxW q@W | j | qW | 	  d S )NTr   FrS   )
supports_locationsToRegions	enumeraterF   rP   issubsetr.   r    append_computeDeltaWeights)rE   regionsiregionZlocAxesZprev_regionZrelevantr8   r+   r9   r-   ZbestAxesZ	bestRatiovallocVZnewLowerZnewUpperZratior)   r	   r	   r   rL   h  sN    	


z%VariationModel._computeMasterSupportsc             C   s   | j }i }i }xN|D ]F}x@| D ]4\}}t||||||< t||||||< q"W qW g }x^|D ]V}i }	xB| D ]6\}
}|dkrd|||
 f|	|
< qz||
 |df|	|
< qzW ||	 qhW |S )Nr   )rC   r.   r'   r/   r&   ra   )rE   rC   ZminVZmaxVr   r>   r(   rc   r@   re   r8   rg   r	   r	   r   r^     s     

z"VariationModel._locationsToRegionsc             C   sh   g | _ x\t| jD ]N\}}i }x4t| jd | D ]\}}t||}|r2|||< q2W | j | qW d S )N)deltaWeightsr_   rC   r]   r   ra   )rE   rd   r@   ZdeltaWeightjr5   r7   r	   r	   r   rb     s    
z#VariationModel._computeDeltaWeights)roundc      
      C   s   t |t | jkst| j}g }xlt| jD ]^\}}|||  }x:| D ].\}}	|	dkrh||| 8 }qJ||| |	 8 }qJW ||| q,W |S )Nr   )r   rh   r    rK   r_   r.   ra   )
rE   masterValuesrj   rJ   r2   rd   Zweightsdeltari   Zweightr	   r	   r   	getDeltas  s    zVariationModel.getDeltasc            C   s"   |  |\}}|j||d|jfS )N)rj   )rO   rm   r]   )rE   r.   rj   modelr	   r	   r   getDeltasAndSupports  s    z#VariationModel.getDeltasAndSupportsc                s    fddj D S )Nc                s    g | ]}t  |jjd qS ))r*   r6   )r   r*   r6   )r
   r5   )r@   rE   r	   r   r     s   z-VariationModel.getScalars.<locals>.<listcomp>)r]   )rE   r@   r	   )r@   rE   r   
getScalars  s    zVariationModel.getScalarsc             C   sX   d }t | t |kstx:t| |D ],\}}|s2q$|| }|d krH|}q$||7 }q$W |S )N)r   r    r!   )deltasscalarsr(   rl   r7   Zcontributionr	   r	   r   interpolateFromDeltasAndScalars  s    z.VariationModel.interpolateFromDeltasAndScalarsc             C   s   |  |}| ||S )N)rp   rs   )rE   r@   rq   rr   r	   r	   r   interpolateFromDeltas  s    
z$VariationModel.interpolateFromDeltasc            C   s   | j ||d}| ||S )N)rj   )rm   rt   )rE   r@   rk   rj   rq   r	   r	   r   interpolateFromMasters  s    z%VariationModel.interpolateFromMastersc            C   s   | j ||d}| ||S )N)rj   )rm   rs   )rE   rk   rr   rj   rq   r	   r	   r    interpolateFromMastersAndScalars  s    z/VariationModel.interpolateFromMastersAndScalars)NF)__name__
__module____qualname____doc__rN   rO   staticmethodrH   rI   r\   rL   r^   rb   r   rm   ro   rp   rs   rt   ru   rv   r	   r	   r	   r   r      s"   ,

48c                s   |  }|s S  |kr |  S t|} |k r@ ||  | S t|} |kr` ||  | S t fdd|D }t fdd|D }|| }|| }|||  |  ||   S )Nc             3   s   | ]}| k r|V  qd S )Nr	   )r
   r>   )r(   r	   r   r     s    z%piecewiseLinearMap.<locals>.<genexpr>c             3   s   | ]}| kr|V  qd S )Nr	   )r
   r>   )r(   r	   r   r     s    )rP   r'   r&   )r(   rJ   rP   r>   abZvaZvbr	   )r(   r   piecewiseLinearMap  s     r~   c       
         s\  ddl m} ddl}|jdtjd}|jdddd	d
 |jdd}|jdddtd |jdddddd |	| } || j
d ddlm} | jrddlm} | }|| j dd |jD }td || |  td dd |jD }|| n4dd ttd td!d" D   fd#d| jD }t|}	td$ ||	j td% ||	j dS )&z*Normalize locations on a given designspacer   )configLoggerNzfonttools varLib.models)Zdescriptionz
--loglevelZLEVELINFOz Logging level (defaults to INFO))metavarr,   helpT)Zrequiredz-dz--designspaceZDESIGNSPACE)r   typez-lz--locationsZLOCATION+zFMaster locations as comma-separate coordinates. One must be all zeros.)r   nargsr   )level)pprint)DesignSpaceDocumentc             S   s   g | ]
}|j qS r	   )r0   )r
   sr	   r	   r   r   .  s    zmain.<locals>.<listcomp>zOriginal locations:zNormalized locations:c             S   s   g | ]
}|j qS r	   )r0   )r
   r   r	   r	   r   r   3  s    c             S   s   g | ]}t |qS r	   )chr)r
   cr	   r	   r   r   6  s    AZr   c          	      s*   g | ]"}t t d d |dD qS )c             s   s   | ]}t |V  qd S )N)float)r
   r(   r	   r	   r   r   8  s    z"main.<locals>.<listcomp>.<genexpr>,)dictr!   split)r
   r   )r1   r	   r   r   8  s    zSorted locations:z	Supports:)Z	fontToolsr   argparseArgumentParsermainrz   add_argumentZadd_mutually_exclusive_groupstr
parse_argsZloglevelr   ZdesignspaceZfontTools.designspaceLibr   readZsourcesprintZ	normalizerangeordrC   r   r]   )
argsr   r   parsergroupr   r   docZlocsrn   r	   )r1   r   r   
  sN    


 
r   __main__)N)N)F)F)TFN)N)rz   __all__ZfontTools.misc.roundToolsr   errorsr   r   r   r   r   r#   r   r   r   objectr   r~   r   rw   Zdoctestsysr   argvexitZtestmodZfailedr	   r	   r	   r   <module>   s0   



.
Q  ,
8