o
    nĎiX                     @  s  d Z ddlmZ g dZddlmZ ddlmZ ddlm	Z	 er(ddlm
Z
mZ d	d
 Zdd Zd1ddZd1ddZdd Z	d2d3ddZ	d2ddd4d%d&Zd5d(d)ZG d*d+ d+eZd,d- Zd1d.d/Zed0krddlZddlZeejdkr~ee  ee j dS dS )6z%Variation fonts interpolation models.    )annotations)normalizeValuenormalizeLocationsupportScalarpiecewiseLinearMapVariationModel)TYPE_CHECKING)noRound   )VariationModelError)MappingSequencec                 C  s   dd | D S )Nc                 S  s   g | ]}|d ur|qS N .0lr   r   S/home/jeff/fluffinator/venv/lib/python3.10/site-packages/fontTools/varLib/models.py
<listcomp>       znonNone.<locals>.<listcomp>r   lstr   r   r   nonNone   s   r   c                 C  s   t dd | D S )Nc                 s  s    | ]}|d u V  qd S r   r   r   r   r   r   	<genexpr>       zallNone.<locals>.<genexpr>allr   r   r   r   allNone   s   r   Nc                   s>   d u rt fdd|D S  t  fdd|D S )Nc                 3  s    | ]} |kV  qd S r   r   r   item)refr   r   r       r   zallEqualTo.<locals>.<genexpr>c                 3  s    | ]	} |kV  qd S r   r   r   )mappedmapperr   r   r   #       r   )r    r   r"   r   )r!   r"   r    r   
allEqualTo   s   r$   c                 C  s@   | sdS t | }zt|}W n
 ty   Y dS w t|||dS )NT)r"   )iternextStopIterationr$   )r   r"   itfirstr   r   r   allEqual&   s   r*   c                 C  s(   t | t |ks
J dd t|| D S )Nc                 S  s   g | ]\}}|r|qS r   r   )r   r   tr   r   r   r   3   r   zsubList.<locals>.<listcomp>lenzip)truthr   r   r   r   subList1   s   r0   FvfloattripleSequence[float]extrapolateboolreturnc              
   C  s   |\}}}||  kr|ks n t d|dd|dd|d|s*tt| ||} | |ks2||kr4dS | |k r<||ksD| |krL||krL| | ||  S | |krT||ksm| |k r\||ksmJ d|  d| d| d| 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,         zOoops... v=z
, triple=())
ValueErrormaxmin)r1   r3   r5   lowerdefaultupperr   r   r   r   6   s,   
 r   )validatelocationMapping[str, float]axes(Mapping[str, tuple[float, float, float]]r@   dict[str, float]c                C  st   |rt |  t | ksJ t |  t |  i }| D ]\}}| ||d }t|||d||< q"|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
   )r5   )setkeysitemsgetr   )rA   rC   r5   r@   outtagr3   r1   r   r   r   r   W   s   -&r   Tc                 C  s  |r
|du r
t dd}| D ]\}\}}}	|r7|dkrq||ks&||	kr'q|dk r0|	dkr0q| |d}
n
|| v s=J | | }
|
|krFq|r|| \}}|
|k ry||kry||kri||	k ri||
|	 ||	  9 }q||k rx||
| ||  9 }qn*||
k r||	kr||kr||k r||
| ||  9 }q||k r||
|	 ||	  9 }q|
|ks|	|
krd} |S |
|k r||
| ||  9 }q||
|	 ||	  9 }q|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      ?r8   )	TypeErrorrH   rI   )rA   supportotr5   
axisRangesscalaraxisr=   peakr?   r1   axisMinaxisMaxr   r   r   r      sR   "r   c                   @  s   e Zd ZdZ	d(d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dd Zedd Zed d! Zd"d# Zedd$d%Zedd&d'ZdS ))r   a5  Locations must have the base master at the origin (ie. 0).

    If axis-ranges are not provided, values are assumed to be normalized to
    the range [-1, 1].

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

      >>> from pprint import pprint
      >>> axisRanges = {'wght': (-180, +180), 'wdth': (-1, +1)}
      >>> 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'], axisRanges=axisRanges)
      >>> 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}]
    NF)rO   c                  s   t tdd  D t  krtd _|d ur|ng _|_|d u r<|r. }ndd  D }dd |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 r   )tuplesortedrH   r   r   r   r   r     s    z*VariationModel.__init__.<locals>.<genexpr>zLocations must be unique.c                 S     h | ]}|  D ]}|qqS r   rG   r   locrQ   r   r   r   	<setcomp>      z*VariationModel.__init__.<locals>.<setcomp>c                 S  s   i | ]}|d qS ))r
   r   r   rQ   r   r   r   
<dictcomp>       z+VariationModel.__init__.<locals>.<dictcomp>c                 S     g | ]}d d |  D qS )c                 S     i | ]\}}|d kr||qS r8   r   r   kr1   r   r   r   r_   #  r\   z6VariationModel.__init__.<locals>.<listcomp>.<dictcomp>rH   r   rZ   r   r   r   r   #  r\   z+VariationModel.__init__.<locals>.<listcomp>	axisOrder)keyc                      g | ]} j |qS r   	locationsindexr   selfr   r   r   *  r   c                      g | ]}  |qS r   rn   r   rm   r   r   r   +      )r-   rF   r   origLocationsri   r5   computeAxisRangesrO   getMasterLocationsSortKeyFuncrV   rm   mappingreverseMapping_computeMasterSupports
_subModels)rp   rm   ri   r5   rO   allAxeskeyFuncr   )rm   rp   r   __init__  s(   
zVariationModel.__init__c                 C  sb   d|vr| |fS t dd |D }| j|}|du r*tt|| j| j}|| j|< |t||fS )zReturn a sub-model and the items that are not None.

        The sub-model is necessary for working with the subset
        of items when some are None.

        The sub-model is cached.Nc                 s  s    | ]}|d uV  qd S r   r   r   r1   r   r   r   r   9  r   z-VariationModel.getSubModel.<locals>.<genexpr>)rU   r{   rI   r   r0   ru   ri   )rp   rH   rj   subModelr   r   r   getSubModel0  s   
zVariationModel.getSubModelc                 C  sb   i }dd | D }| D ]#}|D ]}| |d}| |||f\}}t||t||f||< qq|S )Nc                 S  rW   r   rX   rY   r   r   r   r[   C  r\   z3VariationModel.computeAxisRanges.<locals>.<setcomp>r   )rI   r<   r;   )rm   rO   r|   rZ   rQ   valuerS   rT   r   r   r   rv   @  s   z VariationModel.computeAxisRangesc                 C  s   i | vrt di }| D ]2}t|dkrqtt|}|| }||vr(dh||< ||| vs7J d|||f || | qdd }|||}|S )NzBase master not found.r
   r8   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   r1   r   r   r   sign]  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 | ]\}}| v r| | v r|qS r   r   )r   rQ   r   )
axisPointsr   r   r   b  s
    z]VariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.key.<locals>.<listcomp>c                   s   g | ]}| v r|qS r   r   r^   rZ   r   r   r   g  r   c                   s   g | ]}| vr|qS r   r   r^   rh   r   r   r   i  r   c                 3  s&    | ]}| v r  |nd V  qdS )i   Nrr   r^   rh   r   r   r   n  s
    
z\VariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.key.<locals>.<genexpr>c                 3  s    | ]	} | V  qd S r   r   r^   )rZ   r   r   r   r   s      
c                 3  s    | ]	}t  | V  qd S r   )absr^   r   r   r   r   v  r   )r-   rH   extendrV   rG   rU   )rZ   rankonPointAxesorderedAxesri   r   r   r   r   rj   `  s*   
zIVariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey.<locals>.keyr   )r   ri   rj   r   r   r   getKey\  s   z<VariationModel.getMasterLocationsSortKeyFunc.<locals>.getKey)r   r-   r&   r%   add)rm   ri   r   rZ   rQ   r   r   retr   r   r   rw   K  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         z1VariationModel.reorderMasters.<locals>.<listcomp>c                   s   g | ]} j | qS r   )ru   r   ro   r   r   r     rt   c                 S  ra   )c                 S  rb   rc   r   rd   r   r   r   r_     r\   z<VariationModel.reorderMasters.<locals>.<listcomp>.<dictcomp>rf   rg   r   r   r   r     s    c                   rk   r   rl   r   ro   r   r   r     r   c                   rq   r   rr   r   rs   r   r   r     rt   )ru   rx   rm   ry   r{   )rp   r   rx   new_listr   )rm   r   rp   r   reorderMasters  s   zVariationModel.reorderMastersc                 C  s  g | _ |  }t|D ]\}}t| }|d | D ]}t| |kr&qd}| D ]"\}\}}	}
|| d |	ksN||| d   k rI|
k sNn d} nq,|sRqi }d}| D ]L}|| d }||v shJ || \}}}
||
}}||k r|}|| ||  }n||k r|}|| |
|  }nqZ||kri }|}||kr|||f||< qZ| D ]\}}|||< qq| j | q|   d S )NTr
   Fr]   )supports_locationsToRegions	enumeraterF   rG   rH   append_computeDeltaWeights)rp   regionsiregionlocAxesprev_regionrelevantrQ   r=   rR   r?   bestAxes	bestRatiovallocVnewLowernewUpperratior3   r   r   r   rz     sR   	

z%VariationModel._computeMasterSupportsc                 C  st   | j }| j}g }|D ]-}i }| D ]\}}|dkr&d||| d f||< q|| d |df||< q|| q
|S )Nr   r
   )rm   rO   rH   r   )rp   rm   rO   r   rZ   r   rQ   r   r   r   r   r     s   z"VariationModel._locationsToRegionsc                 C  s`   g | _ t| jD ]%\}}i }t| jd | D ]\}}t||}|r&|||< q| j | qd S r   )deltaWeightsr   rm   r   r   r   )rp   r   rZ   deltaWeightjrM   rP   r   r   r   r     s   
z#VariationModel._computeDeltaWeightsroundc          
      C  s   t |t | jksJ t |t | jf| j}g }t| jD ]-\}}|||  }| D ]\}}	|	dkr;||| 8 }q,||| |	 8 }q,||| q|S )Nr
   )r-   r   ry   r   rH   r   )
rp   masterValuesr   rx   rJ   r   weightsdeltar   weightr   r   r   	getDeltas  s   zVariationModel.getDeltasc                C  s"   |  |\}}|j||d|jfS )Nr   )r   r   r   )rp   rH   r   modelr   r   r   getDeltasAndSupports  s   z#VariationModel.getDeltasAndSupportsc                   s    fddj D S )zReturn scalars for each delta, for the given location.
        If interpolating many master-values at the same location,
        this function allows speed up by fetching the scalars once
        and using them with interpolateFromMastersAndScalars().c                   s    g | ]}t  |jjd qS ))r5   rO   )r   r5   rO   )r   rM   rZ   rp   r   r   r     s    z-VariationModel.getScalars.<locals>.<listcomp>)r   )rp   rZ   r   r   r   
getScalars  s   zVariationModel.getScalarsc                   sp    | tttjD ]\}}| D ]\}} |   | | 8  < qq fddtt D   S )a  Return multipliers for each master, for the given location.
        If interpolating many master-values at the same location,
        this function allows speed up by fetching the scalars once
        and using them with interpolateFromValuesAndScalars().

        Note that the scalars used in interpolateFromMastersAndScalars(),
        are *not* the same as the ones returned here. They are the result
        of getScalars().c                   s   g | ]	} j |  qS r   )rx   )r   r   rJ   rp   r   r   r     s    z3VariationModel.getMasterScalars.<locals>.<listcomp>)r   reversedlistr   r   rH   ranger-   )rp   targetLocationr   r   r   r   r   r   r   getMasterScalars   s   
	zVariationModel.getMasterScalarsc                 C  sT   d}t | t |ksJ t| |D ]\}}|sq|| }|du r#|}q||7 }q|S )aV  Interpolate from values and scalars coefficients.

        If the values are master-values, then the scalars should be
        fetched from getMasterScalars().

        If the values are deltas, then the scalars should be fetched
        from getScalars(); in which case this is the same as
        interpolateFromDeltasAndScalars().
        Nr,   )valuesscalarsr1   r   rP   contributionr   r   r   interpolateFromValuesAndScalars  s   
z.VariationModel.interpolateFromValuesAndScalarsc                 C  s   t | |S )z>Interpolate from deltas and scalars fetched from getScalars().)r   r   )deltasr   r   r   r   interpolateFromDeltasAndScalars(  s   z.VariationModel.interpolateFromDeltasAndScalarsc                 C  s   |  |}| ||S )z)Interpolate from deltas, at location loc.)r   r   )rp   rZ   r   r   r   r   r   interpolateFromDeltas-     
z$VariationModel.interpolateFromDeltasc                C  s   |  |}| ||S )z0Interpolate from master-values, at location loc.)r   r   )rp   rZ   r   r   r   r   r   r   interpolateFromMasters2  r   z%VariationModel.interpolateFromMastersc                C  s   | j ||d}| ||S )zInterpolate from master-values, and scalars fetched from
        getScalars(), which is useful when you want to interpolate
        multiple master-values with the same location.r   )r   r   )rp   r   r   r   r   r   r   r    interpolateFromMastersAndScalars7  s   z/VariationModel.interpolateFromMastersAndScalars)NF)__name__
__module____qualname____doc__r~   r   staticmethodrv   rw   r   rz   r   r   r	   r   r   r   r   r   r   r   r   r   r   r   r   r   r      s4    2

48

r   c                   s   |  }|s S  |v r|  S t|} |k r  ||  | S t|} |kr0 ||  | S t fdd|D }t fdd|D }|| }|| }|||  |  ||   S )Nc                 3  s    | ]	}| k r|V  qd S r   r   r   re   r   r   r   r   L  r#   z%piecewiseLinearMap.<locals>.<genexpr>c                 3  s    | ]	}| kr|V  qd S r   r   r   r   r   r   r   M  r#   )rG   r<   r;   )r1   rx   rG   re   abvavbr   r   r   r   ?  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r|ddlm} | }|| j dd |jD }td || |  td dd |jD }|| nd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)descriptionz
--loglevelLEVELINFOz Logging level (defaults to INFO))metavarr>   helpT)requiredz-dz--designspaceDESIGNSPACE)r   typez-lz--locationsLOCATION+zFMaster locations as comma-separate coordinates. One must be all zeros.)r   nargsr   )level)pprint)DesignSpaceDocumentc                 S     g | ]}|j qS r   rA   r   sr   r   r   r   w  r`   zmain.<locals>.<listcomp>zOriginal locations:zNormalized locations:c                 S  r   r   r   r   r   r   r   r   |  r`   c                 S  s   g | ]}t |qS r   )chr)r   cr   r   r   r     r   AZr
   c              	     s*   g | ]}t t d d |dD qS )c                 s  s    | ]}t |V  qd S r   )r2   r   r   r   r   r     r   z"main.<locals>.<listcomp>.<genexpr>,)dictr.   splitr   rC   r   r   r     s    zSorted locations:z	Supports:)	fontToolsr   argparseArgumentParsermainr   add_argumentadd_mutually_exclusive_groupstr
parse_argsloglevelr   designspacefontTools.designspaceLibr   readsourcesprint	normalizer   ordrm   r   r   )
argsr   r   parsergroupr   r   doclocsr   r   r   r   r   S  sX   

 

r   __main__r   )F)r1   r2   r3   r4   r5   r6   r7   r2   )
rA   rB   rC   rD   r5   r6   r@   r6   r7   rE   )TFN) r   
__future__r   __all__typingr   fontTools.misc.roundToolsr	   errorsr   r   r   r   r   r$   r*   r0   r   r   r   objectr   r   r   r   doctestsysr-   argvexittestmodfailedr   r   r   r   <module>   s>    

$
8Q  a
8