o
    %ej                     @   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 g d
ZedZg dZg dZedd eddD Zg dZdZ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"d#Z%d$d% Z&d&d' Z'd(d) Z(					d?d*d+Z)						,d@d-d.Z*						,d@d/d0Z+						,d@d1d2Z,						,d@d3d4Z-d5d6 Z.d7d8 Z/					,	,dAd9d:Z0d>d;d<Z1e2d=krd dl3Z3e34e1  dS dS )B    )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.avarPlanner)2   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*   O/var/www/html/venv/lib/python3.10/site-packages/fontTools/varLib/avarPlanner.py	<genexpr>M      " r,   i   )            	   
                     $   0   <   H   `   x            i   r2   c                 C   s   | | ||  S )zOLinearly normalize value in [rangeMin, rangeMax] to [0, 1], with extrapolation.r*   )valuerangeMinrangeMaxr*   r*   r+   r   l      r   c                 C   s   || ||   S )zALinear interpolation between a and b, with t typically in [0, 1].r*   )tabr*   r*   r+   r   q   rG   r   c                 C   s*   t |}t |}t | | ||  S )zVLogarithmically normalize value in [rangeMin, rangeMax] to [0, 1], with extrapolation.)r$   log)rD   rE   rF   logMinlogMaxr*   r*   r+   r   v      

r   c                 C   s*   t |}t |}t || ||   S )zFLogarithmic interpolation between a and b, with t typically in [0, 1].)r$   rK   exp)rH   rI   rJ   logAlogBr*   r*   r+   r   }   rN   r   c                 C   s<   t t |}t t |}t t | | ||  S )zPAngularly normalize value in [rangeMin, rangeMax] to [0, 1], with extrapolation.)r$   tanradians)rD   rE   rF   tanMintanMaxr*   r*   r+   r      s   r   c           
      C   s   t |tr|}ndd |D }d }}|D ]4}|dur'||d}|dkr&qnd}| | }t| d}|| |j| }	||	t|j 7 }||	7 }q|| S )z:Measure the perceptual average weight of the given glyphs.c                 S      i | ]}|d qS    r*   r(   gr*   r*   r+   
<dictcomp>       z!measureWeight.<locals>.<dictcomp>r   NrX   glyphset)
isinstancedictgetr   drawwidthabsrD   )
r^   glyphsfrequencieswght_sumwdth_sum
glyph_name	frequencyglyphpenmultr*   r*   r+   r      s$   




r   c           	      C   s   t |tr|}ndd |D }d}d}|D ]+}|dur'||d}|dkr&qnd}| | }t }|| ||j| 7 }||7 }q|| S )z.Measure the average width of the given glyphs.c                 S   rV   rW   r*   rY   r*   r*   r+   r[      r\   z measureWidth.<locals>.<dictcomp>r   NrX   )r_   r`   ra   r   rb   rc   )	r^   re   rf   rh   freq_sumri   rj   rk   rl   r*   r*   r+   r      s$   


r   c           
      C   s   t |tr|}ndd |D }d}d}|D ]2}|dur'||d}|dkr&q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   rV   rW   r*   rY   r*   r*   r+   r[      r\   z measureSlant.<locals>.<dictcomp>r   NrX   r]   )
r_   r`   ra   r   rb   rc   slantr$   r%   r&   )
r^   re   rf   slnt_sumrn   ri   rj   rk   rl   rm   r*   r*   r+   r      s&   




r   c           	      C   s   ||d  ||d  ||d  }}}| d ||  }| d ||  }t jdg| R   t d|| d | t|| d  | d  dksSt|| d  | d  dkrmt d t jdg| R   t d	|| d | d
S dS )zSanitize the width axis limits.r   rX      z$Original width axis limits: %g:%g:%gz&Calculated width axis limits: %g:%g:%g皙?z6Calculated width axis min/max do not match user input.z%  Current width axis limits: %g:%g:%gz'  Suggested width axis limits: %g:%g:%gFTrK   inford   warning)	
userTripledesignTriplepinsmeasurementsminVal
defaultValmaxValcalculatedMinValcalculatedMaxValr*   r*   r+   r      s:   




r   c                 C   s4  t t| dk r
dS ||d  ||d  ||d  }}}t|}t|}t|}	| d | d  | d | d   }
t||
|	|   }|| ||  }
| d |
| d | d    }tjdg| R   td| d || d  t|| d  | d  dkrtd	 tjd
g| R   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   rX   rq   z%Original weight axis limits: %g:%g:%gz'Calculated weight axis limits: %g:%g:%grr   z9Calculated weight axis default does not match user input.z&  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)lensetr$   rK   rO   rt   rd   ru   )rv   rw   rx   ry   rz   r{   r|   rL   
logDefaultrM   rH   ycalculatedDefaultValr~   r}   r*   r*   r+   r   	  sn   






 
  r   c                 C   s   t jdg| R   t d||d  ||d  ||d   t||d  | d  dksGt||d  | d  dksGt||d  | d  dkrkt d t jdg| R   t d||d  ||d  ||d   d	S d
S )zSanitize the slant axis limits.z$Original slant axis limits: %g:%g:%gz&Calculated slant axis limits: %g:%g:%gr   rX   rq   z>Calculated slant axis min/default/max do not match user input.z%  Current slant axis limits: %g:%g:%gz'  Suggested slant axis limits: %g:%g:%gFTrs   )rv   rw   rx   ry   r*   r*   r+   r   P  s0   






r   c           $   	      s  t |tr|j|j|jf}|\}}}|du rt}|du r"|i  }|
du r)i }
n|
 }
t	d||| |||f}|	durHtj	dg|	R   n|}	|
rVt	dt
|
  |
||	d ||	d ||	d i i }i }i }t
|||ht|
 B D ]}|||id}|
| }| ||||< qz|durt	d	| |||	|
| td
t| ttt
|
 dd tt
|
 dd D ]\\}\ } fdd|D }|sqt|}t |}t||	}t||	}t	dt
| t	d|  | }td|d D ](}  | |d   }td| |||id}t||
}| ||||< qtdt| i }t
|D ]	}|||| < q<||< |||< t
|D ]C}|| } || || || }!t|!|}"td||"f  |"||< ||    ||   }#||"| ||  ||   ||#< qR|| < |||< 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 %gz/Axis design-limits min %g / default %g / max %gzPins %sr   rX   rq   )locationz/Sanitizing axis limit values for the `%s` axis.zCalculated average value:
%sc                    s(   h | ]}|  k r k rn n|qS r*   r*   r(   wrF   rE   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)rd   )r(   kvr*   r*   r+   r,     r-   zplanAxis.<locals>.<genexpr>z6Detected identity mapping for the `%s` axis. Dropping.)r_   fvarAxisminValuedefaultValuemaxValueSAMPLESkeyscopyrK   rt   sorteditemsupdater   debugr
   ziplistr   ranger   all)$measureFuncnormalizeFuncinterpolateFuncglyphSetFuncaxisTag
axisLimitsvaluessamplesre   designLimitsrx   sanitizeFuncr   r   r   tripleoutoutNormalizedaxisMeasurementsrD   r^   designValue	targetMin	targetMaxtargetValuesnormalizedMinnormalizedMaxnormalizedTargetMinnormalizedTargetMaxvalueMeasurementssamplemeasurementValuerH   targetMeasurementtargetValuevalueNormalizedr*   r   r+   r   q  s   
5








r   Fc                 C   8   |du rt }tttt| d|||||||rtdS 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   re   r   rx   r   )WEIGHTSr   r   r   r   r   )r   r   weightsr   re   r   rx   sanitizer*   r*   r+   r     $   r   c                 C   r   )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   re   r   rx   r   r*   r*   r+   r   :  r   r   c                 C   r   )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   re   r   rx   r   r*   r*   r+   r   `  r   r   c                 C   s*   |du 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   re   r   rx   )SIZESr   r   r   r   )r   r   sizesr   re   r   rx   r   r*   r*   r+   r     s   r   c                 C   sX   d| |f|  }|r|d7 }n|d7 }|  D ]\}}|d||f 7 }q|r*|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   axisName	axisLimitmappingdesignspaceSnippetkeyrD   r*   r*   r+   r     s   

r   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   
r   c              
      s  d}| d j D ]}|j|kr|} nq|du rdS |j|j|jf}td| d| v r:| d j| }i | d j|< nd}|durNt|t	rNdd |
 D }|dur}t|t	r}dd tj
d	D }t|d
krz|d |d   kry|d ks|J  J nd}|durt|t	ri }|
 D ]}|
d	\}}t||t|< q|}~|| j|||||||	d\} |
rddlm} |t  fddt D  |  |durtd|t| |rd| vrt|   | d j|< nd| v ri | d j|< t||||}|S )zProcess a single axis.Nr    zPlanning %s axis.r   c                 S      g | ]}t |qS r*   floatr   r*   r*   r+   
<listcomp>      zprocessAxis.<locals>.<listcomp>c                 S   r   r*   r   r'   r*   r*   r+   r     r   :r   r   rX   rq   )r   re   r   rx   r   )pyplotc                    s   g | ]} | qS r*   r*   )r(   r   mappingNormalizedr*   r+   r     r   zExisting %s mapping:
%s)r   r   r   r   r   rK   rt   r   r_   strsplitoptionsr   r   r   getGlyphSet
matplotlibr   plotr   showr
   r   r   )r   planFuncr   r   r   r   re   r   rx   r   r   r   r   existingMappingnewPinspinbeforeafterr   r   r   r*   r   r+   r     sx   
*
r   c                 C   s  | du 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|vrtdC dS |jdur+|j }	dD|jv r*i }	|j D ]}
dD|
v r$|
dD\}}t||	|< q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 ]
}|rt+| q|j,du rt-|jdPdQdR}n|j,}|rt*dS| |.| dS dS )Tz3Plan the standard axis mappings for a variable fontNr   rX   )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   Weight)r   r   re   r   rx   r   r   r   Widthr   Slantr   OpticalSizezDesignspace snippet:Tz.avar)	overWritesuffixz	Saving %s)/sysargv	fontToolsr   fontTools.ttLibr   argparseArgumentParseradd_argumentr   intadd_mutually_exclusive_group
parse_argsverbosequietr   rK   errorre   r   r   appendr   r   r   r   weight_design_limitsweight_pinsr   r   r   r   width_design_limits
width_pinsr   r   slant_design_limits
slant_pinsr   r   optical_size_design_limitsoptical_size_pinsrt   printoutput_filer	   save)argsr   r   r   r  parserlogging_groupr   r   re   rZ   rk   rj   designspaceSnippetssnippetoutfiler*   r*   r+   r   #  sj  





r   __main__)N)NNNNN)NNNNNF)NNNNFF)5r   r   fontTools.ttLib.tables._f_v_a_rr   r   fontTools.pens.areaPenr   fontTools.pens.basePenr   fontTools.pens.statisticsPenr   fontTools.varLib.modelsr   r   fontTools.misc.cliToolsr	   r$   loggingpprintr
   __all__	getLoggerrK   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>   s    



)G)
 '
)
)
)
%

\ G