U
    Dvfj                     @   s  d dl mZ d dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZmZ d dlmZ d dlZd dlZd d	lmZ d
dddddddddddddddddddgZedZdd d!d"d#d$d%d&d'd(d)d*d+d,d-d.d/d0d1gZd2d3d4d5d6d7d8d9d:d;d<d=d>d?d@gZedAdB edCdDD ZdEdFdGdHdIdJdKdLdMdNdOdPdQdRdSdTdUdVdWdXdYdZgZdHZd[d Zd\d Zd]d Z d^d Z!d_d Z"dqd`dZ#drdadZ$dsdbdZ%dcd Z&ddd Z'ded Z(dtdfdZ)dudhd
Z*dvdidZ+dwdjdZ,dxdkdZ-dld Z.dmd Z/dydndZ0dzdodZ1e2dpkrd dl3Z3e34e1  dS ){    )newTable)Axis)AreaPen)NullPen)StatisticsPen)piecewiseLinearMapnormalizeValue)makeOutputFileNameN)pformatplanWeightAxisplanWidthAxisplanSlantAxisplanOpticalSizeAxisplanAxissanitizeWeightsanitizeWidthsanitizeSlantmeasureWeightmeasureWidthmeasureSlantnormalizeLinearnormalizeLognormalizeDegreesinterpolateLinearinterpolateLogprocessAxismakeDesignspaceSnippetaddEmptyAvarmainzfontTools.varLib.avarPlanner2   d            i,  i^  i  i  i  i&  iX  i  i  i  i   iR  i  i  g      9@g     B@g      I@g     @O@g     R@g     U@g      Y@g      \@g     @_@g     0a@g     b@g     Pd@g     e@g     pg@g      i@c                 c   s"   | ]}t t |d  V  qdS )g      4@N)mathdegreesatan.0d r*   @/tmp/pip-unpacked-wheel-qlge9rch/fontTools/varLib/avarPlanner.py	<genexpr>M   s     r,   i               	   
                     $   0   <   H   `   x            i   c                 C   s   | | ||  S )zOLinearly normalize value in [rangeMin, rangeMax] to [0, 1], with extrapolation.r*   )valuerangeMinrangeMaxr*   r*   r+   r   l   s    c                 C   s   || ||   S )zALinear interpolation between a and b, with t typically in [0, 1].r*   )tabr*   r*   r+   r   q   s    c                 C   s*   t |}t |}t | | ||  S )zVLogarithmically normalize value in [rangeMin, rangeMax] to [0, 1], with extrapolation.)r$   log)rC   rD   rE   logMinlogMaxr*   r*   r+   r   v   s    

c                 C   s*   t |}t |}t || ||   S )zFLogarithmic interpolation between a and b, with t typically in [0, 1].)r$   rI   exp)rF   rG   rH   ZlogAZlogBr*   r*   r+   r   }   s    

c                 C   s<   t t |}t t |}t t | | ||  S )zPAngularly normalize value in [rangeMin, rangeMax] to [0, 1], with extrapolation.)r$   tanradians)rC   rD   rE   ZtanMinZtanMaxr*   r*   r+   r      s    c           
      C   s   t |tr|}ndd |D }d }}|D ]h}|dk	rN||d}|dkrRq*nd}| | }t| d}|| |j| }	||	t|j 7 }||	7 }q*|| S )z:Measure the perceptual average weight of the given glyphs.c                 S   s   i | ]
}|d qS    r*   r(   gr*   r*   r+   
<dictcomp>   s      z!measureWeight.<locals>.<dictcomp>r   NrP   glyphset)
isinstancedictgetr   drawwidthabsrC   )
rU   glyphsfrequenciesZwght_sumwdth_sum
glyph_name	frequencyglyphpenmultr*   r*   r+   r      s"    




c           	      C   s   t |tr|}ndd |D }d}d}|D ]V}|dk	rN||d}|dkrRq*nd}| | }t }|| ||j| 7 }||7 }q*|| S )z.Measure the average width of the given glyphs.c                 S   s   i | ]
}|d qS rO   r*   rQ   r*   r*   r+   rS      s      z measureWidth.<locals>.<dictcomp>r   NrP   )rV   rW   rX   r   rY   rZ   )	rU   r\   r]   r^   freq_sumr_   r`   ra   rb   r*   r*   r+   r      s"    


c           
      C   s   t |tr|}ndd |D }d}d}|D ]d}|dk	rN||d}|dkrRq*nd}| | }t| d}|| |j| }	||	|j 7 }||	7 }q*tt	||  S )z?Measure the perceptual average slant angle of the given glyphs.c                 S   s   i | ]
}|d qS rO   r*   rQ   r*   r*   r+   rS      s      z measureSlant.<locals>.<dictcomp>r   NrP   rT   )
rV   rW   rX   r   rY   rZ   Zslantr$   r%   r&   )
rU   r\   r]   Zslnt_sumrd   r_   r`   ra   rb   rc   r*   r*   r+   r      s$    




c           	      C   s   ||d  ||d  ||d    }}}| d ||  }| d ||  }t jd|   t d|| d | t|| d  | d  dkst|| d  | d  dkrt d t jd|   t d	|| d | d
S dS )zSanitize the width axis limits.r   rP      $Original width axis limits: %g:%g:%gz&Calculated width axis limits: %g:%g:%g皙?z6Calculated width axis min/max do not match user input.%  Current width axis limits: %g:%g:%gz'  Suggested width axis limits: %g:%g:%gFT)rf   )rh   rI   infor[   warning)	
userTripledesignTriplepinsmeasurementsminVal
defaultValmaxValcalculatedMinValcalculatedMaxValr*   r*   r+   r      s>    




 c                 C   s,  t t| dk rdS ||d  ||d  ||d    }}}t|}t|}t|}	| d | d  | d | d   }
t||
|	|   }|| ||  }
| d |
| d | d    }tjd|   td| d || d  t|| d  | d  dkr(td	 tjd|   td| d || d  | d | d  | d | d   }
t||
||   }|| ||  }
| d |
| d | d    }td| d | d | | d | d  | d | d   }
t|	|
||	   }|| ||  }
| d |
| d | d    }td|| d | d  dS dS )z Sanitize the weight axis limits.   Tr   rP   re   %Original weight axis limits: %g:%g:%gz'Calculated weight axis limits: %g:%g:%grg   z9Calculated weight axis default does not match user input.&  Current weight axis limits: %g:%g:%gz:  Suggested weight axis limits, changing default: %g:%g:%gz:  Suggested weight axis limits, changing maximum: %g:%g:%gz:  Suggested weight axis limits, changing minimum: %g:%g:%gF)rv   )rw   )lensetr$   rI   rL   rj   r[   rk   )rl   rm   rn   ro   rp   rq   rr   rJ   Z
logDefaultrK   rF   yZcalculatedDefaultValrt   rs   r*   r*   r+   r   	  sn    






 
   c                 C   s   t jd|   t d||d  ||d  ||d   t||d  | d  dkst||d  | d  dkst||d  | d  dkrt d t jd|   t d||d  ||d  ||d   d	S d
S )zSanitize the slant axis limits.$Original slant axis limits: %g:%g:%gz&Calculated slant axis limits: %g:%g:%gr   rP   re   z>Calculated slant axis min/default/max do not match user input.%  Current slant axis limits: %g:%g:%gz'  Suggested slant axis limits: %g:%g:%gFT)r{   )r|   ri   )rl   rm   rn   ro   r*   r*   r+   r   P  s6    



 


c           $   	      s  t |tr|j|j|jf}|\}}}|dkr0t}|dkrD|i  }|
dkrRi }
n|
 }
t	d||| |||f}|	dk	rtj	d|	  n|}	|
rt	dt
|
  |
||	d ||	d ||	d i i }i }i }t
|||ht|
 B D ](}|||id}|
| }| ||||< q|dk	r>t	d	| |||	|
| td
t| ttt
|
 dd tt
|
 dd D ]\\}\ } fdd|D }|sqt|}t |}t||	}t||	}t	dt
| t	d|  | }td|d D ]P}  | |d   }td| |||id}t||
}| ||||< qtdt| i }t
|D ]}|||| < q|||< |||< t
|D ]}|| } || || || }!t|!|}"td||"f  |"||< ||    ||   }#||"| ||  ||   ||#< q|| < |||< qt	d|t| t	d|t| tdd | D rt	d| i }i }||fS )a@  Plan an axis.

    measureFunc: callable that takes a glyphset and an optional
    list of glyphnames, and returns the glyphset-wide measurement
    to be used for the axis.

    normalizeFunc: callable that takes a measurement and a minimum
    and maximum, and normalizes the measurement into the range 0..1,
    possibly extrapolating too.

    interpolateFunc: callable that takes a normalized t value, and a
    minimum and maximum, and returns the interpolated value,
    possibly extrapolating too.

    glyphSetFunc: callable that takes a variations "location" dictionary,
    and returns a glyphset.

    axisTag: the axis tag string.

    axisLimits: a triple of minimum, default, and maximum values for
    the axis. Or an `fvar` Axis object.

    values: a list of output values to map for this axis.

    samples: the number of samples to use when sampling. Default 8.

    glyphs: a list of glyph names to use when sampling. Defaults to None,
    which will process all glyphs.

    designLimits: an optional triple of minimum, default, and maximum values
    represenging the "design" limits for the axis. If not provided, the
    axisLimits will be used.

    pins: an optional dictionary of before/after mapping entries to pin in
    the output.

    sanitizeFunc: an optional callable to call to sanitize the axis limits.
    Nz(Axis limits min %g / default %g / max %g/Axis design-limits min %g / default %g / max %gzPins %sr   rP   re   )locationz/Sanitizing axis limit values for the `%s` axis.zCalculated average value:
%sc                    s(   h | ] }|  k r k rn q|qS r*   r*   r(   wrE   rD   r*   r+   	<setcomp>  s
      
  zplanAxis.<locals>.<setcomp>zPlanning target values %s.z"Sampling %u points in range %g,%g.zSampling value %g.zSampled average value:
%szPlanned mapping value %g to %g.z%Planned mapping for the `%s` axis:
%sz0Planned normalized mapping for the `%s` axis:
%sc                 s   s"   | ]\}}t || d k V  qdS )g{Gz?N)r[   )r(   kvr*   r*   r+   r,     s     zplanAxis.<locals>.<genexpr>z6Detected identity mapping for the `%s` axis. Dropping.)r}   )rV   fvarAxisminValuedefaultValuemaxValueSAMPLESkeyscopyrI   rj   sorteditemsupdatery   debugr
   ziplistr   ranger   all)$ZmeasureFuncZnormalizeFuncZinterpolateFuncglyphSetFuncaxisTag
axisLimitsvaluessamplesr\   designLimitsrn   sanitizeFuncr   r   r   ZtripleoutZoutNormalizedZaxisMeasurementsrC   rU   ZdesignValueZ	targetMinZ	targetMaxZtargetValuesZnormalizedMinZnormalizedMaxZnormalizedTargetMinZnormalizedTargetMaxZvalueMeasurementssampleZmeasurementValuerF   ZtargetMeasurementZtargetValueZvalueNormalizedr*   r   r+   r   q  s    5

   
   





  
Fc                 C   s4   |dkrt }tttt| d|||||||r,tnddS )a  Plan a weight (`wght`) axis.

    weights: A list of weight values to plan for. If None, the default
    values are used.

    This function simply calls planAxis with values=weights, and the appropriate
    arguments. See documenation for planAxis for more information.
    Nwghtr   r   r\   r   rn   r   )WEIGHTSr   r   r   r   r   )r   r   weightsr   r\   r   rn   sanitizer*   r*   r+   r     s     
c                 C   s4   |dkrt }tttt| d|||||||r,tnddS )a  Plan a width (`wdth`) axis.

    widths: A list of width values (percentages) to plan for. If None, the default
    values are used.

    This function simply calls planAxis with values=widths, and the appropriate
    arguments. See documenation for planAxis for more information.
    Nwdthr   )WIDTHSr   r   r   r   r   )r   r   widthsr   r\   r   rn   r   r*   r*   r+   r   :  s     
c                 C   s4   |dkrt }tttt| d|||||||r,tnddS )a  Plan a slant (`slnt`) axis.

    slants: A list slant angles to plan for. If None, the default
    values are used.

    This function simply calls planAxis with values=slants, and the appropriate
    arguments. See documenation for planAxis for more information.
    Nslntr   )SLANTSr   r   r   r   r   )r   r   slantsr   r\   r   rn   r   r*   r*   r+   r   `  s     
c                 C   s*   |dkrt }tttt| d||||||dS )a  Plan a optical-size (`opsz`) axis.

    sizes: A list of optical size values to plan for. If None, the default
    values are used.

    This function simply calls planAxis with values=sizes, and the appropriate
    arguments. See documenation for planAxis for more information.
    Nopsz)r   r   r\   r   rn   )SIZESr   r   r   r   )r   r   sizesr   r\   r   rn   r   r*   r*   r+   r     s    c                 C   sX   d| |f|  }|r|d7 }n|d7 }|  D ]\}}|d||f 7 }q.|rT|d7 }|S )z-Make a designspace snippet for a single axis.zC    <axis tag="%s" name="%s" minimum="%g" default="%g" maximum="%g"z>
z/>z$      <map input="%g" output="%g"/>
z    </axis>)r   )r   axisNameZ	axisLimitmappingdesignspaceSnippetkeyrC   r*   r*   r+   r     s    

c                 C   s,   t d | d< }tjD ]}i |j|j< qdS )z&Add an empty `avar` table to the font.avarN)r   fvaraxessegmentsr   )fontr   axisr*   r*   r+   r     s    
c              
      s  d}| d j D ]}|j|kr|} q&q|dkr2dS |j|j|jf}td| d| krt| d j| }i | d j|< nd}|dk	rt|t	rdd |
 D }|dk	rt|t	rdd tj
d	D }t|d
kr|d |d   kr|d ksn tnd}|dk	rJt|t	rJi }|
 D ]$}|
d	\}}t||t|< q|}~|| j|||||||	d\} |
rddlm} |t  fddt D  |  |dk	rtd|t| |rd| krt|   | d j|< nd| kr i | d j|< t||||}|S )zProcess a single axis.Nr    zPlanning %s axis.r   c                 S   s   g | ]}t |qS r*   floatr   r*   r*   r+   
<listcomp>  s     zprocessAxis.<locals>.<listcomp>c                 S   s   g | ]}t |qS r*   r   r'   r*   r*   r+   r     s     :ru   r   rP   re   )r   r\   r   rn   r   )pyplotc                    s   g | ]} | qS r*   r*   )r(   r   ZmappingNormalizedr*   r+   r     s     zExisting %s mapping:
%s)r   r   r   r   r   rI   rj   r   rV   strsplitoptionsr   rx   AssertionErrorr   ZgetGlyphSetZ
matplotlibr   plotr   showr
   r   r   )r   ZplanFuncr   r   r   r   r\   r   rn   r   r   r   r   ZexistingMappingZnewPinsZpinbeforeafterr   r   r   r*   r   r+   r     s    

 



c                 C   s  | dkrddl }|jdd } ddlm} ddlm} ddl}|jddd}|jd	d
dd |jddt	dd |jdt	dd |jdt	dd |jdt	dd |jdt	dd |jdt
dd |jddddd |jd d!t	d"d |jd#t	d$d |jd%t	d&d |jd't	d(d |jd)t	d*d |jd+t	d,d |jd-t	d.d |jd/t	d0d |jd1t	d2d |jd3d4dd5d |jd6d7}|jd8d9dd:d |jd;d<dd=d || }||jrd>n|jrd?nd@dA ||j}dB|krtdC dS |jdk	rZ|j }	dD|jkr^i }	|j D ]4}
dD|
krL|
dD\}}t||	|< ndE|	|
< q"nd}	g }|t|tdFdG|j|j|	|j|j|j|jdH |t|tdIdJ|j|j|	|j |j!|j|jdH |t|t"dKdL|j#|j|	|j$|j%|j|jdH |t|t&dMdN|j'|j|	|j(|j)|j|jdH t*dO |D ]}|r0t+| q0|j,dkrdt-|jdPdQdR}n|j,}|rt*dS| |.| dS )Tz3Plan the standard axis mappings for a variable fontNr   rP   )configLogger)TTFontzfonttools varLib.avarPlannerz#Plan `avar` table for variable font)descriptionr   zvarfont.ttfzVariable-font file.)metavarhelpz-oz--output-filezOutput font file name.)typer   z	--weightsz+Space-separate list of weights to generate.z--widthsz*Space-separate list of widths to generate.z--slantsz*Space-separate list of slants to generate.z--sizesz1Space-separate list of optical-sizes to generate.z	--sampleszNumber of samples.z-sz
--sanitize
store_truezSanitize axis limits)actionr   z-gz--glyphsz2Space-separate list of glyphs to use for sampling.z--weight-design-limitsz4min:default:max in design units for the `wght` axis.z--width-design-limitsz4min:default:max in design units for the `wdth` axis.z--slant-design-limitsz4min:default:max in design units for the `slnt` axis.z--optical-size-design-limitsz4min:default:max in design units for the `opsz` axis.z--weight-pinsz=Space-separate list of before:after pins for the `wght` axis.z--width-pinsz=Space-separate list of before:after pins for the `wdth` axis.z--slant-pinsz=Space-separate list of before:after pins for the `slnt` axis.z--optical-size-pinsz=Space-separate list of before:after pins for the `opsz` axis.z-pz--plotzPlot the resulting mapping.F)requiredz-vz	--verbosezRun more verbosely.z-qz--quietzTurn verbosity off.DEBUGWARNINGINFO)levelr   zNot a variable font.r   g      ?r   ZWeight)r   r   r\   r   rn   r   r   r   ZWidthr   ZSlantr   ZOpticalSizezDesignspace snippet:Tz.avar)Z	overWritesuffixz	Saving %s)/sysargvZ	fontToolsr   fontTools.ttLibr   argparseArgumentParseradd_argumentr   intadd_mutually_exclusive_group
parse_argsverbosequietr   rI   errorr\   r   r   appendr   r   r   r   Zweight_design_limitsZweight_pinsr   r   r   r   Zwidth_design_limitsZ
width_pinsr   r   Zslant_design_limitsZ
slant_pinsr   r   Zoptical_size_design_limitsZoptical_size_pinsrj   printZoutput_filer	   save)argsr   r   r   r   parserZlogging_groupr   r   r\   rR   ra   r`   ZdesignspaceSnippetsZsnippetoutfiler*   r*   r+   r   #  s                       






__main__)N)N)N)NNNNN)NNNNNF)NNNNNF)NNNNNF)NNNNNF)NNNNFF)N)5r   r   ZfontTools.ttLib.tables._f_v_a_rr   r   ZfontTools.pens.areaPenr   ZfontTools.pens.basePenr   ZfontTools.pens.statisticsPenr   ZfontTools.varLib.modelsr   r   ZfontTools.misc.cliToolsr	   r$   loggingpprintr
   __all__	getLoggerrI   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   __name__r   exitr*   r*   r*   r+   <module>   s0  



)G)     
 '      
)      
)      
)      
%      
\
 G
