B
    0ufK              
   @   s|  d 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
 ddlZddlmZ ddlZeeZG d	d
 d
eZdZdZdddddddddd	ZefddZG dd deZdZeeZdZeeZdZeeZdZ ee Z!dZ"ee"Z#G d d! d!eZ$G d"d# d#e$Z%G d$d% d%e$Z&G d&d' d'Z'd(d) Z(d*d+ Z)d,d- Z*ed.krxddl+Z+ddl,Z,e+-e,. j/ dS )/a  ttLib/sfnt.py -- low-level module to deal with the sfnt file format.

Defines two public classes:
	SFNTReader
	SFNTWriter

(Normally you don't have to use these classes explicitly; they are
used automatically by ttLib.TTFont.)

The reading and writing of sfnt files is separated in two distinct
classes, since whenever the number of tables changes or whenever
a table's length changes you need to rewrite the whole file anyway.
    )BytesIO)SimpleNamespace)Tag)sstruct)
TTLibErrorN)OrderedDictc               @   sZ   e Zd Zdd ZdddZdd ZeZd	d
 Zdd Zdd Z	dd Z
dd Zdd ZdS )
SFNTReaderc             O   s^   |rT| t krT|d }|d t|d}|d |dkrTddlm} t|S t| S )zb Return an instance of the SFNTReader sub-class which is compatible
		with the input file type.
		r      ZwOF2)WOFF2Reader)r   seekr   readfontTools.ttLib.woff2r
   object__new__)clsargskwargsinfilesfntVersionr
    r   V/home/ankuromar296_gmail_com/myenv/lib/python3.7/site-packages/fontTools/ttLib/sfnt.pyr      s    


zSFNTReader.__new__r   c             C   s  || _ || _d | _d | _t| _| j d | j d| _| j d | jdkrt	| j }|j
}d|  krr|k sn td|d  || _
| j |j|  | j t}t|tkrtdtt||  nz| jdkrd| _t| _| j t}t|tkrtd	tt||  n0| j t}t|tkr8td
tt||  t| j| _| jdkrftdi }x:t| jD ],}|  }	|	| j  t|	j}
|	||
< qvW tt| dd d| _| jdkrt| | _d S )Nr   r	   s   ttcfz2specify a font number between 0 and %d (inclusive)   z'Not a Font Collection (not enough data)s   wOFFwoffz!Not a WOFF font (not enough data)z1Not a TrueType or OpenType font (not enough data))z   ZOTTOtruez1Not a TrueType or OpenType font (bad sfntVersion)c             S   s
   | d j S )Nr   )offset)ir   r   r   <lambda>Y       z%SFNTReader.__init__.<locals>.<lambda>)key)filecheckChecksumsflavor
flavorDataSFNTDirectoryEntryDirectoryEntryr   r   r   readTTCHeadernumFontsr   offsetTablesfntDirectorySizelenr   unpacksfntDirectoryFormatWOFFDirectoryEntrywoffDirectorySizewoffDirectoryFormatr   range	numTablesfromFiletagr   sorteditemstablesWOFFFlavorData)selfr    r!   Z
fontNumberheaderr'   datar6   r   entryr3   r   r   r   __init__.   sT    


zSFNTReader.__init__c             C   s
   || j kS )N)r6   )r8   r3   r   r   r   has_key_   s    zSFNTReader.has_keyc             C   s
   | j  S )N)r6   keys)r8   r   r   r   r>   d   s    zSFNTReader.keysc             C   s   | j t| }|| j}| jr|dkrJt|dd d |dd  }nt|}| jdkrt||jkstd| n||jkrt	d| |S )zFetch the raw table data.headN   s          r   zbad checksum for '%s' table)
r6   r   loadDatar    r!   calcChecksumcheckSumAssertionErrorlogwarning)r8   r3   r;   r:   checksumr   r   r   __getitem__g   s    "

zSFNTReader.__getitem__c             C   s   | j t|= d S )N)r6   r   )r8   r3   r   r   r   __delitem__y   s    zSFNTReader.__delitem__c             C   s   | j   d S )N)r    close)r8   r   r   r   rK   |   s    zSFNTReader.closec             C   s@   t | jtr| jS | j }|d= | jj|d< | j |d< |S )Nr    	_filename_filepos)
isinstancer    r   __dict__copynametell)r8   stater   r   r   __getstate__   s    
zSFNTReader.__getstate__c             C   s<   d|kr,t |dd| _| j|d | j| d S )Nr    rL   rbrM   )openpopr    r   rO   update)r8   rS   r   r   r   __setstate__   s    zSFNTReader.__setstate__N)r   r   )__name__
__module____qualname__r   r<   r=   __contains__r>   rI   rJ   rK   rT   rY   r   r   r   r   r      s   
1	r      Fr         r@   
         2   d   )	r      r_   r	   r`   r^      r@   	   c             C   sd   d|  krdks"n t d| tr.|dkrDddlm} || |S ddlm} || t| dS dS )a7   Compress 'data' to Zlib format. If 'USE_ZOPFLI' variable is True,
	zopfli is used instead of the zlib module.
	The compression 'level' must be between 0 and 9. 1 gives best speed,
	9 gives best compression (0 gives no compression at all).
	The default value is a compromise between speed and compression (6).
	r   rh   zBad compression level: %s)compress)ZnumiterationsN)
ValueError
USE_ZOPFLIzlibri   Zzopfli.zlibZOPFLI_LEVELS)r:   levelri   r   r   r   ri      s    
ri   c               @   sV   e Zd Zdd Zd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 )
SFNTWriterc             O   sb   d}|rd|kr|d }n|r2t |dkr2|d }| tkrX|dkrXddlm} t|S t| S )ze Return an instance of the SFNTWriter sub-class which is compatible
		with the specified 'flavor'.
		Nr"   r_   Zwoff2r   )WOFF2Writer)r*   ro   r   rp   r   r   )r   r   r   r"   rp   r   r   r   r      s    

zSFNTWriter.__new__   Nc             C   s   || _ || _t|| _|| _|| _| jdkrTt| _t| _	t
| _d| _t|t  | _nH| jrhtd| j t| _t| _	t| _ddlm} ||d\| _| _| _| j  | _| j| j	 || jj  | _| j | j | j d| j| j     t | _d S )Nr   ZwOFFzUnknown flavor '%s'r   )getSearchRange       ) r    r1   r   r   r"   r#   r/   directoryFormatr.   directorySizer-   r%   	signaturer)   sfntDirectoryEntrySizeorigNextTableOffsetrE   r,   r$   fontTools.ttLibrr   searchRangeentrySelector
rangeShiftrR   directoryOffset
formatSizenextTableOffsetr   writer   r6   )r8   r    r1   r   r"   r#   rr   r   r   r   r<      s,    

zSFNTWriter.__init__c             C   s$   || j krtd| || j |< d S )Nzcannot rewrite '%s' table)r6   r   )r8   r3   r;   r   r   r   setEntry   s    
zSFNTWriter.setEntryc             C   s   || j krtd| |  }||_| j|_|dkrdt|dd d |dd  |_|| _d|_	n
t||_|
| j| | jdkr| j|_|  j|jd	 d
@ 7  _| j|jd	 d
@  | _| jd| j| j    | j| j kst| || dS )zWrite raw table data to disk.zcannot rewrite '%s' tabler?   Nr@   s       rA   Tr   r_   rt   )r6   r   r%   r3   r   r   rC   rD   	headTableuncompressedsaveDatar    r"   ry   
origOffset
origLengthlengthr   rR   rE   r   )r8   r3   r:   r;   r   r   r   __setitem__   s$    
"

zSFNTWriter.__setitem__c             C   s
   | j | S )N)r6   )r8   r3   r   r   r   rI     s    zSFNTWriter.__getitem__c       
      C   s  t | j }t|| jkr2td| jt|f | jdkrd| _d| _d| _	|  j	dt| 7  _	x(|D ] \}}|  j	|j
d d@ 7  _	qlW | jr| jnt }|jd	k	r|jd	k	r|j| _|j| _n6t| d
rtd| jdd \| _| _nd | _| _|jrNt|j| _| jdd | j | _t|j}t|| _| j| nd | _ | _| _|jr| jdd | j }|d d@ }| jd||   | j | _t|j| _| j|j nd | _| _| jdd | j | _n| jrt d| j t!"| j#| }| j| j$| j%  d}	x,|D ]$\}}|dkrHd}	||&  }q2W |	rj| '| | j| j$ | j| d	S )zHAll tables must have been written to disk. Now write the
		directory.
		z-wrong number of tables; expected %d, found %dr   s   wOFFr   rA   rs   r_   r   Nr   z>HHr	   r@   rf    zUnknown flavor '%s'r?   r   )(r4   r6   r5   r*   r1   r   r"   rw   reservedZtotalSfntSizer   r#   r7   majorVersionminorVersionhasattrstructr+   r   metaDatametaOrigLengthr    r   rR   
metaOffsetri   
metaLengthr   privData
privOffset
privLengthr   rE   r   packru   r~   rv   toStringwriteMasterChecksum)
r8   r6   r3   r;   r:   ZcompressedMetaDataoffZ	paddedOff	directoryZseenHeadr   r   r   rK     s`    

 




zSFNTWriter.closec             C   s  t | j }g }x*tt|D ]}|| j||  j q W | jtkrddl	m
} || jd\| _| _| _tt| }t| j }xB|D ]:\}}t }	|j|	_|j|	_|j|	_|j|	_||	  }qW tt| jt  }
|
t|kst|t| t|d@ }d| d@ }|S )Nr   )rr   rs   l    l   /ac )listr6   r>   r0   r*   appendrD   r%   r$   rz   rr   r1   r{   r|   r}   r   r   r,   r4   r5   r3   r   r   r   r   r   r)   rx   rE   rC   sum)r8   r   tagsZ	checksumsr   rr   r6   r3   r;   Z	sfntEntryZdirectory_endrH   checksumadjustmentr   r   r   _calcMasterChecksum^  s,    
zSFNTWriter._calcMasterChecksumc             C   s:   |  |}| j| jd jd  | jtd| d S )Nr?   r@   z>L)r   r    r   r6   r   r   r   r   )r8   r   r   r   r   r   r   |  s    
zSFNTWriter.writeMasterChecksumc             C   s   dS )NFr   )r8   r   r   r   reordersTables  s    zSFNTWriter.reordersTables)rq   NN)rZ   r[   r\   r   r<   r   r   rI   rK   r   r   r   r   r   r   r   ro      s    
!Bro   a  
		> # big endian
		TTCTag:                  4s # "ttcf"
		Version:                 L  # 0x00010000 or 0x00020000
		numFonts:                L  # number of fonts
		# OffsetTable[numFonts]: L  # array with offsets from beginning of file
		# ulDsigTag:             L  # version 2.0 only
		# ulDsigLength:          L  # version 2.0 only
		# ulDsigOffset:          L  # version 2.0 only
z
		> # big endian
		sfntVersion:    4s
		numTables:      H    # number of tables
		searchRange:    H    # (max2 <= numTables)*16
		entrySelector:  H    # log2(max2 <= numTables)
		rangeShift:     H    # numTables*16-searchRange
zc
		> # big endian
		tag:            4s
		checkSum:       L
		offset:         L
		length:         L
ab  
		> # big endian
		signature:      4s   # "wOFF"
		sfntVersion:    4s
		length:         L    # total woff file size
		numTables:      H    # number of tables
		reserved:       H    # set to 0
		totalSfntSize:  L    # uncompressed size
		majorVersion:   H    # major version of WOFF file
		minorVersion:   H    # minor version of WOFF file
		metaOffset:     L    # offset to metadata block
		metaLength:     L    # length of compressed metadata
		metaOrigLength: L    # length of uncompressed metadata
		privOffset:     L    # offset to private data block
		privLength:     L    # length of private data block
z
		> # big endian
		tag:            4s
		offset:         L
		length:         L    # compressed length
		origLength:     L    # original length
		checkSum:       L    # original checksum
c               @   sT   e Z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 )r%   c             C   s
   d| _ d S )NF)r   )r8   r   r   r   r<     s    zDirectoryEntry.__init__c             C   s   t | j|| j|  d S )N)r   r+   formatr   r   )r8   r    r   r   r   r2     s    zDirectoryEntry.fromFilec             C   s   t | j||  d S )N)r   r+   r   )r8   strr   r   r   
fromString  s    zDirectoryEntry.fromStringc             C   s   t | j| S )N)r   r   r   )r8   r   r   r   r     s    zDirectoryEntry.toStringc             C   s:   t | dr"d| jj| jt| f S d| jjt| f S d S )Nr3   z<%s '%s' at %x>z
<%s at %x>)r   	__class__rZ   r3   id)r8   r   r   r   __repr__  s    
zDirectoryEntry.__repr__c             C   sD   | | j || j}t|| jks*tt| jdr@| |}|S )N
decodeData)	r   r   r   r   r*   rE   r   r   r   )r8   r    r:   r   r   r   rB     s    
zDirectoryEntry.loadDatac             C   s:   t | jdr| |}t|| _|| j || d S )N
encodeData)r   r   r   r*   r   r   r   r   )r8   r    r:   r   r   r   r     s
    

zDirectoryEntry.saveDatac             C   s   |S )Nr   )r8   rawDatar   r   r   r     s    zDirectoryEntry.decodeDatac             C   s   |S )Nr   )r8   r:   r   r   r   r     s    zDirectoryEntry.encodeDataN)rZ   r[   r\   r<   r2   r   r   r   rB   r   r   r   r   r   r   r   r%     s   r%   c               @   s   e Zd ZeZeZdS )r$   N)rZ   r[   r\   sfntDirectoryEntryFormatr   rx   r   r   r   r   r   r$     s   r$   c                   s4   e Zd ZeZeZ fddZdd Zdd Z	  Z
S )r-   c                s"   t t|   ttdst| _d S )NzlibCompressionLevel)superr-   r<   r   ZLIB_COMPRESSION_LEVELr   )r8   )r   r   r   r<     s    
zWOFFDirectoryEntry.__init__c             C   sJ   dd l }| j| jkr|}n,| j| jk s*t||}t|| jksFt|S )Nr   )rl   r   r   rE   
decompressr*   )r8   r   rl   r:   r   r   r   r     s    
zWOFFDirectoryEntry.decodeDatac             C   sP   t || _| jst|| j}| js0t || jkr>|}| j| _n|}t || _|S )N)r*   r   r   ri   r   r   )r8   r:   ZcompressedDatar   r   r   r   r     s    


zWOFFDirectoryEntry.encodeData)rZ   r[   r\   woffDirectoryEntryFormatr   woffDirectoryEntrySizer   r<   r   r   __classcell__r   r   )r   r   r-     s
   
r-   c               @   s"   e Zd ZdZdddZdd ZdS )r7   r   Nc             C   s   d | _ d | _d | _d | _|r|j | _ |j| _|jr|j|j |j|j}t	||jks`t
| |}t	||jks|t
|| _|jr|j|j |j|j}t	||jkst
|| _d S )N)r   r   r   r   r   r    r   r   r   r*   rE   _decompressr   r   r   )r8   readerr   r:   r   r   r   r<   "  s&    
zWOFFFlavorData.__init__c             C   s   dd l }||S )Nr   )rl   r   )r8   r   rl   r   r   r   r   7  s    zWOFFFlavorData._decompress)N)rZ   r[   r\   ZFlavorr<   r   r   r   r   r   r7     s   
r7   c             C   s   t | d }|r | dd|  7 } d}d}|d dks8txPtdt | |D ]<}| |||  }tdt |d  |}|t| d@ }qJW |S )zCalculate the checksum for an arbitrary block of data.

	If the data length is not a multiple of four, it assumes
	it is to be padded with null byte.

		>>> print(calcChecksum(b"abcd"))
		1633837924
		>>> print(calcChecksum(b"abcdxyz"))
		3655064932
	r	   rt   r   i   z>%dLl    )r*   rE   r0   r   r+   r   )r:   	remaindervalueZ	blockSizer   blockZlongsr   r   r   rC   <  s    rC   c             C   s   |  d | t}t|tkr(tdt }tt|| |j	dkrNtd|j
dksp|j
dksptd|j
 td|j | |jd	 |_|j
dkr|S )
Nr   z'Not a Font Collection (not enough data)ttcfzNot a Font Collectioni   i   zunrecognized TTC version 0x%08xz>%dLr	   )r   r   ttcHeaderSizer*   r   r   r   r+   ttcHeaderFormatTTCTagVersionrE   r   r'   r(   )r    r:   r8   r   r   r   r&   S  s    


" 
r&   c             C   sd   t  }d|_d|_||_| d | tt| | 	 }| t
jd|j fdg|j   |S )Nr   i   r   z>%dL)r   r   r   r'   r   r   r   r   r   rR   r   )r    r'   r8   r   r   r   r   writeTTCHeaderb  s    
$r   __main__)0__doc__ior   typesr   ZfontTools.misc.textToolsr   ZfontTools.miscr   rz   r   r   collectionsr   logging	getLoggerrZ   rF   r   r   r   rk   rm   ri   ro   r   calcsizer   r,   r)   r   rx   r/   r.   r   r   r%   r$   r-   r7   rC   r&   r   sysdoctestexittestmodfailedr   r   r   r   <module>   sZ   
} R
	


	
)'
