o
    hYo                     @   s   d Z ddlZddl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mZ edZg dZG d	d
 d
ejZG dd dZG dd dZdddZedkr_ddlZee  dS dS )u6  MS VOLT ``.vtp`` to AFDKO ``.fea`` OpenType Layout converter.

Usage
-----

To convert a VTP project file:


.. code-block:: sh

    $ fonttools voltLib.voltToFea input.vtp output.fea

It is also possible convert font files with `TSIV` table (as saved from Volt),
in this case the glyph names used in the Volt project will be mapped to the
actual glyph names in the font files when written to the feature file:

.. code-block:: sh

    $ fonttools voltLib.voltToFea input.ttf output.fea

The ``--quiet`` option can be used to suppress warnings.

The ``--traceback`` can be used to get Python traceback in case of exceptions,
instead of suppressing the traceback.


Limitations
-----------

* Not all VOLT features are supported, the script will error if it it
  encounters something it does not understand. Please report an issue if this
  happens.
* AFDKO feature file syntax for mark positioning is awkward and does not allow
  setting the mark coverage. It also defines mark anchors globally, as a result
  some mark positioning lookups might cover many marks than what was in the VOLT
  file. This should not be an issue in practice, but if it is then the only way
  is to modify the VOLT file or the generated feature file manually to use unique
  mark anchors for each lookup.
* VOLT allows subtable breaks in any lookup type, but AFDKO feature file
  implementations vary in their support; currently AFDKO’s makeOTF supports
  subtable breaks in pair positioning lookups only, while FontTools’ feaLib
  support it for most substitution lookups and only some positioning lookups.
    N)StringIO)ast)TTFont
TTLibError)ParserzfontTools.voltLib.voltToFea)GDEFGSUBGPOSc                   @   s   e Zd ZdddZdS )MarkClassDefinition c                 C   s.   d}t | dds|d7 }|tj| |7 }|S )Nr   usedF#)getattrr   r
   asFea)selfindentres r   o/var/www/html/construction_image-detection-poc/venv/lib/python3.10/site-packages/fontTools/voltLib/voltToFea.pyr   =   s
   zMarkClassDefinition.asFeaN)r   )__name__
__module____qualname__r   r   r   r   r   r
   <   s    r
   c                   @   s   e Zd Zdd Zdd ZdS )Groupc                 C   s$   |j  | _ dd |jjD | _d S )Nc                 S   s"   g | ]}t |tjr|j qS r   )
isinstanceVAst	GroupNamegrouplower).0xr   r   r   
<listcomp>I   s
    z"Group.__init__.<locals>.<listcomp>)namer   enumgroups)r   r   r   r   r   __init__G   s   zGroup.__init__c                 C   sH   | j |jv rdS |j | jv rdS | jr|jsdS | js |jr"dS d S d S )NTF)r!   r#   )r   otherr   r   r   __lt__M   s   zGroup.__lt__N)r   r   r   r$   r&   r   r   r   r   r   F   s    r   c                   @   s   e Zd ZedZedZd0ddZdd Zdd	 Z	d
d Z
dd Zd0d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+ Zd,d- Zd.d/ ZdS )1	VoltToFeaz[^A-Za-z_0-9.]z[^A-Za-z_0-9.\-]Nc                 C   s`   || _ || _i | _d | _i | _i | _i | _i | _t | _	i | _
i | _i | _i | _i | _i | _d S N)_file_or_path_font
_glyph_map_glyph_order_gdef_glyphclasses	_features_lookupsset_marks
_ligatures_markclasses_anchors	_settings_lookup_names_class_names)r   file_or_pathfontr   r   r   r$   \   s   
zVoltToFea.__init__c                 C   P   || j vr#| jd|}|| j  v r|d7 }|| j  v s|| j |< | j | S N_)r7   _NOT_LOOKUP_NAME_REsubvaluesr   r!   r   r   r   r   _lookupNames      


zVoltToFea._lookupNamec                 C   r;   r<   )r8   _NOT_CLASS_NAME_REr?   r@   rA   r   r   r   
_className{   rC   zVoltToFea._classNamec                 C   s  dd |j D }t|dd dD ]}| | q|j D ]G}t|tjr)| | qt|tjr9d|v r8| | qt|tj	rE| 
| qt|tjrLqt|tjrX| | qt|tjsbt|q|j D ]}t|tjr|jrvd|vrvqf|jr~d|vr~qf| | qfd S )Nc                 S   s   g | ]
}t |tjr|qS r   )r   r   GroupDefinition)r   sr   r   r   r           z0VoltToFea._collectStatements.<locals>.<listcomp>c                 S   s   t | S r(   )r   )r   r   r   r   <lambda>   s    z.VoltToFea._collectStatements.<locals>.<lambda>keyr	   r   )
statementssorted_groupDefinitionr   r   GlyphDefinition_glyphDefinitionAnchorDefinition_anchorDefinitionSettingDefinition_settingDefinitionrF   ScriptDefinition_scriptDefinitionLookupDefinitionNotImplementedErrorposr?   _lookupDefinition)r   doctablesr#   	statementr   r   r   _collectStatements   s8   



zVoltToFea._collectStatementsc              	      s  t  }|j} jr|t d | j   jr4|t d |dd t	 j
 D   jrU|t d  j D ]}|t|dg  || qD j }|D ]7}|| }|D ]#}|| }	|	D ]}
 fdd|	|
 D |	|
< qld	d
 |	
 D ||< qddd
 |
 D ||< q\dd
 |
 D }|r|t d |
 D ]a\}}t |}t	|dd d}|D ]H}|jt | t	|| dd d}|D ]0}
|
dkrdnd}|jt j|
|d || |
 D ]} j|  }t |}|j| qqq|| q jr[d|v r[g }dD ],}| jv rAd|  }t | j| }|| |t | q|d  qt d}|jt j|  || |S )Nz# Glyph classesz
# Mark classesc                 s   s    | ]}|d  V  qdS )   Nr   )r   cr   r   r   	<genexpr>   s    z.VoltToFea._buildFeatureFile.<locals>.<genexpr>z

# Lookupstargetsc                    s   g | ]}|   jv r|qS r   )r   r0   r   lr   r   r   r       s    z/VoltToFea._buildFeatureFile.<locals>.<listcomp>c                 S      i | ]	\}}|r||qS r   r   )r   trd   r   r   r   
<dictcomp>       z/VoltToFea._buildFeatureFile.<locals>.<dictcomp>c                 S   rf   r   r   )r   rg   rG   r   r   r   rh      ri   c                 S   rf   r   r   )r   rg   fr   r   r   rh      ri   z
# Featuresc                 S      | dkrdS dS )NDFLTr   r_   r   kr   r   r   rI          z-VoltToFea._buildFeatureFile.<locals>.<lambda>rJ   c                 S   rk   )Ndfltr   r_   r   rm   r   r   r   rI      ro   rp   TF)include_defaultr   BASEMARKLIGATURE	COMPONENTGDEF_)r   FeatureFilerL   r.   appendCommentextendr@   r4   rM   itemsr0   r   r/   copyFeatureBlockScriptStatementLanguageStatementr   LookupReferenceStatementr-   GlyphClassDefinitionGlyphClassName
TableBlockGlyphClassDefStatement)r   r\   r[   rL   lookupfeaturesftagscriptsstaglangsltagfeaturestagsltagsrq   r!   	lookuprefclasses	classname
glyphclassgdefr   re   r   _buildFeatureFile   sp   


	


zVoltToFea._buildFeatureFilec                 C   sN   t | j }|d u rt}| jd ur| j | _| || | |}|	 S r(   )

VoltParserr)   parseTABLESr*   getGlyphOrderr,   r^   r   r   )r   r\   r[   fear   r   r   convert   s   

zVoltToFea.convertc                 C   s6   z|j }W n ty   |}Y nw t| j||S r(   )glyphAttributeErrorr   	GlyphNamer+   get)r   r   r!   r   r   r   
_glyphName      
zVoltToFea._glyphNamec                 C   s6   z|j }W n ty   |}Y nw t| j|  S r(   )r   r   r   r   r.   r   )r   r   r!   r   r   r   
_groupName   r   zVoltToFea._groupNamec                 C   s   g }|D ]B}t |tjr|| | qt |tjr$|| | qt |tjr3|| | qt |tj	rC||j
|jf qt||S r(   )r   r   r   ry   r   r   r   Enum_enumRangestartendrX   )r   coverager|   itemr   r   r   	_coverage   s   zVoltToFea._coveragec                 C   s   t | |jS r(   )r   
GlyphClassr   r"   )r   r"   r   r   r   r     s   zVoltToFea._enumc                 C   s:   g }|D ]}|  |}t|ttfs|g}|| q|S r(   )r   r   tuplelistr{   )r   contextoutr   r   r   r   r   _context  s   
zVoltToFea._contextc                 C   s8   |  |j}| |j}t||}|| j|j < d S r(   )rE   r!   r   r"   r   r   r.   r   )r   r   r!   glyphsr   r   r   r   rN     s   zVoltToFea._groupDefinitionc                 C   s   z| j |j | j|j< W n	 ty   Y nw |jdv r7|j| jvr)t | j|j< | j|j j	
| |j |jdkrE| j|j d S |jdkrS|j| j|j< d S d S )Nrr   rt   ru   )r,   idr+   r!   	TypeErrortyper-   r   r   r   ry   r   r2   add
componentsr3   )r   r   r   r   r   rP   "  s   


zVoltToFea._glyphDefinitionc                 C   s   |j }|jD ]D}|j }|jD ];}dd |jD }|j }|| jvr%i | j|< || j| vr3i | j| |< || j| | vs>J | | j| | |< qqd S )Nc                 S   s   i | ]
}| d d dqS )\r   T)splitrc   r   r   r   rh   7  rH   z/VoltToFea._scriptDefinition.<locals>.<dictcomp>)tagr   r   lookupsr/   keys)r   scriptr   langr   r   r   r   r   r   r   rV   2  s   



zVoltToFea._scriptDefinitionc                 C   s4   |j dr|j| j|j < d S td|j   d S )N	COMPILER_zUnsupported setting ignored: )r!   
startswithvaluer6   logwarning)r   settingr   r   r   rT   @  s   zVoltToFea._settingDefinitionc                 C   sV   |\}}}}}}|r|  pd }|r|  pd }	|r|  pd }
tj||||	|
|dS )N)
xPlacement
yPlacementxAdvance
xPlaDevice
yPlaDevice
xAdvDevice)r|   r   ValueRecord)r   
adjustmentadvdxdyadv_adjust_bydx_adjust_bydy_adjust_by
adv_device	dx_device	dy_devicer   r   r   _adjustmentF  s   zVoltToFea._adjustmentc           
      C   sZ   |\}}}}}}|rJ |r|  pd }|r|  pd }	tj|p!d|p$d|p'd |	p*d dS )Nr   )xDeviceTableyDeviceTable)r|   r   Anchor)
r   r   r   r   r   r   r   r   r   r   r   r   r   _anchorV  s   zVoltToFea._anchorc           	      C   s   |j }|j}| |j}|dr9d|ddd  }t| 	|}| 
|}t|||}|| j||f< d S || jvrCi | j|< || j| vrQi | j| |< || j| | |j< d S )NMARK_r=   r_   )r!   
glyph_namer   rY   r   joinr   r   	MarkClassrE   r   r
   r4   r5   	component)	r   	anchordef
anchorname	glyphnameanchorr!   	markclassr   markdefr   r   r   rR   d  s   



zVoltToFea._anchorDefinitionc           &   
   C   s2  |j }|j}t|tjrp|j D ]\\\}}\}}|j|d  }	|j|d  }
d}|	|
 D ]
}t|tj	s7d}q-| 
|	}| 
|
}| |}| |}t|dksTJ t|dks\J |tj|d ||d ||d qd S t|tjr|jD ]&\}}| 
|}| |}t|dksJ |t|d |fgg g d qyd S t|tjri }|jD ]F\}}|D ]}| D ]}|d| f}d| j| _qqt| |}|jD ]}| D ]}||vrg ||< ||| vr|| | qqq|D ]}d}|| jv r| j| }g }|| D ]B}t| |}td|d D ]/}t||k r+|g  d }|| j| | v r@| j| | | }||d  ||f qq| |}|| jv rct ||d }n|| jv rpt!||}nt"||d }|| qd S t|tj#rg } |j$D ]}!|!D ]}| D ]}| | qqqg }"|j%D ]}!|!D ]}| D ]}|"| qqq| D ]3}| |}#| j| d d }$d }%||"v r| j| d d }%|"&|"'| |t(|#|$|% q|"D ]}| |}#| j| d d }%|t(|#d |% qd S t)|)	Nr_   FTr   )
enumeratedr   entryexit)*rL   rY   r   r   PositionAdjustPairDefinitionadjust_pairr|   coverages_1coverages_2r   r   r   lenry   r   PairPosStatementPositionAdjustSingleDefinitionadjust_singleSinglePosStatementPositionAttachDefinitioncoverage_toglyphSetr4   r   r   rE   r   r3   ranger5   r   r2   MarkMarkPosStatementMarkLigPosStatementMarkBasePosStatementPositionAttachCursiveDefinitioncoverages_entercoverages_exitpopindexCursivePosStatementrX   )&r   r   	fealookuprL   rY   idx1idx2pos1pos2
coverage_1
coverage_2r   r   glyphs1glyphs2record1record2abr   recordanchorsmarksr   markr!   rK   r   baser   r   r   enter_coverager   exit_coverager   r   r   r   r   r   _gposLookupv  s   














zVoltToFea._gposLookupc                 C   s  |j }|jrJ |j}t|tjrj|j D ]Q\\}	}
\}}| |j	|	d  }| |j
|
d  }t|dks:J t|dksBJ |d |d f}|rVt|||fg}n||f}t||||}|| qd S t|tjrt g}|jD ]\}}| |}|d | qx|rt|||fg}n	t||||g}|| d S t|tjrt g}|jD ]\}}|d | | q|rt|||fg}n	t||||g}|| d S t|)Nr_   r   )rL   reversalrY   r   r   r   r   r|   r   r   r   r   r   IgnorePosStatementChainContextPosStatementry   r   r   r   r{   r   r   rX   )r   r   prefixsuffixignorer   targetlookuprL   rY   r   r   r  r  r  r  r   r]   r   r	  r
  r   r   r=   r   r   r   _gposContextLookup  sP   





zVoltToFea._gposContextLookupc              	   C   s  |j }|j}|j D ]\}	}
|	r|
s(|j\}}}t| d| d| d qd }| |	}| |
}|rB|||f}t	|g}nwt
|tjrbt|dksPJ t|dksXJ t|||||}nWt
|tjrt|dkspJ t|dksxJ t||||}n8t
|tjrt|dksJ t||d |||}nt
|tjrt|dksJ t||||d |}nt||| qd S )N:z: Ignoring empty substitutionr_   r   )rL   r?   mappingr|   locationr   r   r   r   IgnoreSubstStatementr   r   SubstitutionSingleDefinitionr   SingleSubstStatement+SubstitutionReverseChainingSingleDefinition ReverseChainSingleSubstStatementSubstitutionMultipleDefinitionMultipleSubstStatementSubstitutionLigatureDefinitionLigatureSubstStatementrX   ry   )r   r   r  r  r  chainr   rL   r?   rK   valpathlinecolumnr]   r   replacementschain_contextr   r   r   _gsubLookup  sL   



zVoltToFea._gsubLookupc              	   C   s  d }d }d}|j dkr|dO }|js|dO }|js|dO }nt|jtr+| |j}n|jd ur6| |j}d }|sB|d usB|d urIt|||}d|j	v r|j	
dd }| | jvr|t| |}|d uro|j| |jtd|j	  n| j|  }|jt  |jtd|j	  || j| < nt| |j	}|d ur|j| || j|j	 < |jd ur|jtd|j  g }|jr|jD ]0}	| |	j}
| |	j}|	jdk}||
||d	g |rt|jdkr|g g d	d
g qn	|g g d	d	g d }|D ]m\}
}}}|jd ur)| ||
|||| |jd ur| jdr9d
|_|
sE|sE|sE|ry|sm|d u rm| |j	d }t|}t |dg |_!|j!| | "|| | #||
|||| q| "|| qd S )Nr   RTLr_         r   z# EXCEPT_CONTEXTFTCOMPILER_USEEXTENSIONLOOKUPSz targetrb   )$	directionprocess_baseprocess_marksr   strr   mark_glyph_setr   LookupFlagStatementr!   r   r   r0   LookupBlockrB   rL   ry   rz   SubtableStatementcommentsr   r   leftrightex_or_inr   r?   r.  rY   r6   r   use_extensionr   rb   r  r  )r   r   mark_attachementmark_filteringflagslookupflagsr!   r   contextsr   r  r  r  r  r'  
targetnamer   r   r   rZ   A  s   








zVoltToFea._lookupDefinitionr(   )r   r   r   recompiler>   rD   r$   rB   rE   r^   r   r   r   r   r   r   r   rN   rP   rV   rT   r   r   rR   r  r  r.  rZ   r   r   r   r   r'   X   s2    


!
B	n4)r'   c                 C   s  ddl }ddlm} ddlm} |jdtjd}|jdd|d	d
 |jdd|dd
 |jdddt	ddd |jddddd |jdddd |
| }||jrQdndd |j}d}zt|}d|v rnt|d jd}ntd  W d!S W n	 ty   Y nw t||}z||j}	W nC ty }
 z7|jr t|
jd d"d}d#|
 d$}|r|\}}}t| d%| d%| d&|  nt| W Y d}
~
d!S d}
~
ww t|jd'}||	 W d   dS 1 sw   Y  dS )(z'Convert MS VOLT to AFDKO feature files.r   N)Path)configLoggerzfonttools voltLib.voltToFea)descriptioninputINPUTzinput font/VTP file to process)metavarr   helpfeaturefileOUTPUTzoutput feature filez-tz--tablery   r\   z:List of tables to write, by default all tables are written)actionchoicesdestrO  z-qz--quiet
store_truezSuppress non-error messages)rR  rO  z--tracebacku   Don’t catch exceptionsERRORINFO)levelTSIVzutf-8z6"TSIV" table is missing, font was not saved from VOLT?r_   r  "z" is not supportedr  z: w)argparsepathlibrI  	fontToolsrJ  ArgumentParsermain__doc__add_argumentr   
parse_argsquietrL  r   r   datadecoder   errorr   r'   r   r\   rX   	tracebackr   argsopenrP  write)ri  r\  rI  rJ  parseroptionsr9   r:   	converterr   er  messager)  r*  r+  feafiler   r   r   r`    st   



"
"r`  __main__r(   )ra  loggingrG  ior   fontTools.feaLibr   fontTools.ttLibr   r   fontTools.voltLibr   fontTools.voltLib.parserr   r   	getLoggerr   r   r
   r   r'   r`  r   sysr   r   r   r   r   <module>   s,    -

    
AB