
    <`lL              
       |   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j        e          Z G d	 d
e          ZdZdZdddddddddd	ZefdZ G d de          ZdZ ej        e          ZdZ ej        e          ZdZ ej        e          ZdZ  ej        e           Z!dZ" ej        e"          Z# G d d e          Z$ G d! d"e$          Z% G d# d$e$          Z& G d% d&          Z'd' Z(d( Z)d) Z*ed*k    r,ddl+Z+ddl,Z, e+j-         e,j.                    j/                   dS 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 to number of tables changes or whenever
a table's length chages you need to rewrite the whole file anyway.
    )BytesIO)SimpleNamespace)Tag)sstruct)
TTLibErrorN)OrderedDictc                   J    e Zd Zd ZddZd ZeZd Zd Zd Z	d	 Z
d
 Zd ZdS )
SFNTReaderc                 @   |r| t           u rz|d         }|                    d           t          |                    d                    }|                    d           |dk    r d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      wOF2)WOFF2Reader)r
   seekr   readfontTools.ttLib.woff2r   object__new__)clsargskwargsinfilesfntVersionr   s         4lib/python3.11/site-packages/fontTools/ttLib/sfnt.pyr   zSFNTReader.__new__   s     
 'cZG6	;;q>>>V[[^^$$;	;;q>>>V111111>>+&&&			    r   c                 >   || _         || _        d | _        d | _        t          | _        | j                             d           | j                             d          | _        | j                             d           | j        dk    rt          | j                   }|j
        }d|cxk    r|k     sn t          d|dz
  z            || _
        | j                             |j        |                    | j                             t                    }t          |          t          k    rt          d          t          j        t"          ||            n| j        dk    rud| _        t$          | _        | j                             t&                    }t          |          t&          k    rt          d	          t          j        t(          ||            na| j                             t                    }t          |          t          k    rt          d
          t          j        t"          ||            t+          | j                  | _        | j        dvrt          d          i }t-          | j                  D ]I}|                                 }	|	                    | j                    t+          |	j                  }
|	||
<   Jt5          t7          |                                d                     | _        | j        dk    rt=          |           | _        d S d S )Nr   r   s   ttcfz2specify a font number between 0 and %d (inclusive)   'Not a Font Collection (not enough data)   wOFFwoffz!Not a WOFF font (not enough data)z1Not a TrueType or OpenType font (not enough data))   OTTOtruez1Not a TrueType or OpenType font (bad sfntVersion)c                     | d         j         S )Nr   )offset)is    r   <lambda>z%SFNTReader.__init__.<locals>.<lambda>Y   s    1 r   )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*   
fontNumberheaderr0   datar?   r&   entryr<   s              r   __init__zSFNTReader.__init__.   s   $)&$$+$/*$)..Y^^A&&$)..	  $)$$6o8
z
$
$
$
$H
$
$
$
$
IXXY\Z
[
[[4=9>>&$Z0111
)..*
+
+4	$ii$$$
>
?
??
>%tT22227""4;+4
)..*
+
+4	$ii$$$
8
9
99
>%tT2222
)..*
+
+4	$ii$$$
H
I
II
>%tT222)**$	AAA	G	H	HH&    a  5>>$)	UY36#;;F6<<>>7L7LMMMNN$+ 
[F#D))4??? r   c                     || j         v S Nr?   rA   r<   s     r   has_keyzSFNTReader.has_key_   s    		r   c                 4    | j                                         S rH   )r?   keysrA   s    r   rM   zSFNTReader.keysd   s    					r   c                    | j         t          |                   }|                    | j                  }| j        r|dk    r&t          |dd         dz   |dd         z             }nt          |          }| j        dk    r||j        k    sJ d|z              n&||j        k    rt                              d|           |S )zFetch the raw table data.headN             r   zbad checksum for '%s' table)	r?   r   loadDatar)   r*   calcChecksumcheckSumlogwarning)rA   r<   rE   rD   checksums        r   __getitem__zSFNTReader.__getitem__g   s    
+c#hh
%		#	#$	 4	VmmD!H{2T"##Y>??HHD!!H
Au~%%%'Ds'J%%%%EN""KK-s333	+r   c                 0    | j         t          |          = d S rH   )r?   r   rJ   s     r   __delitem__zSFNTReader.__delitem__y   s    
k#c((r   c                 8    | j                                          d S rH   )r)   closerN   s    r   r^   zSFNTReader.close|   s    )//r   c                     t          | j        t                    r| j        S | j                                        }|d= | j        j        |d<   | j                                        |d<   |S )Nr)   	_filename_filepos)
isinstancer)   r   __dict__copynametellrA   states     r   __getstate__zSFNTReader.__getstate__   sc    	7## 
- -



%Fmy~%inn&&%
	,r   c                     d|vrUt          |                    d          d          | _        | j                            |                    d                     | j                            |           d S )Nr)   r`   rbra   )openpopr)   r   rc   updaterg   s     r   __setstate__zSFNTReader.__setstate__   sf    5EIIk**D11499>>%))J''(((-ur   N)r   r   )__name__
__module____qualname__r   rF   rK   __contains__rM   rZ   r\   r^   ri   ro    r   r   r
   r
      s           /* /* /* /*b       $    
 
 
    r   r
      Fr         rQ   
         2   d   )	r      rv   r   rw   ru      rQ   	   c                     d|cxk    rdk    sn t          d|z            t          r|dk    rddlm}  || |          S ddlm}  || t
          |                   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   r   zBad compression level: %s)compress)numiterations)
ValueError
USE_ZOPFLIzlibr   zopfli.zlibZOPFLI_LEVELS)rD   levelr   s      r   r   r      s     
eq.6777 <eqjj	$		""""""	$mE&:	;	;	;;r   c                   J    e Zd Zd Z	 	 ddZd Zd Zd Zd Zd	 Z	d
 Z
d ZdS )
SFNTWriterc                     d}|rd|v r	|d         }n|rt          |          dk    r|d         }| t          u r&|dk    r ddlm} t                              |          S t                              |           S )ze Return an instance of the SFNTWriter sub-class which is compatible
		with the specified 'flavor'.
		Nr+   rv   woff2r   )WOFF2Writer)r3   r   r   r   r   r   )r   r   r   r+   r   s        r   r   zSFNTWriter.__new__   s     & F""866 D		AG6J111111>>+&&&			r   r!   Nc                 &   || _         || _        t          |          | _        || _        || _        | j        dk    rCt          | _        t          | _	        t          | _        d| _        t          |t          z  z   | _        nb| j        rJ d| j        z              t           | _        t          | _	        t"          | _        ddlm}  ||d          \  | _        | _        | _        | j                                         | _        | j        | j	        z   || j        j        z  z   | _        | j                             | j                   | j                             d| j        | j                                         z
  z             t;                      | _        d S )Nr    wOFFUnknown flavor '%s'r   getSearchRange       )r)   r:   r   r   r+   r,   r8   directoryFormatr7   directorySizer6   r.   	signaturer2   sfntDirectoryEntrySizeorigNextTableOffsetr5   r-   fontTools.ttLibr   searchRangeentrySelector
rangeShiftrf   directoryOffset
formatSizenextTableOffsetr   writer   r?   )rA   r)   r:   r   r+   r,   r   s          r   rF   zSFNTWriter.__init__   sf   $)$.%%$$+$/	[F-4)4+44> 0)>T2TT4k>>04;>>>>-4)4+4------;I>)UW;X;X84T'))$-0BBYQUQdQoEoo$)..%&&&)//%4/$)..2B2BBCDDD$+++r   c                 P    || j         v rt          d|z            || j         |<   d S )Ncannot rewrite '%s' table)r?   r   )rA   r<   rE   s      r   setEntryzSFNTWriter.setEntry   s5    DK	/#5	6	66$+cr   c                    || j         v rt          d|z            |                                 }||_        | j        |_        |dk    r9t          |dd         dz   |dd         z             |_        || _        d|_	        nt          |          |_        |
                    | j        |           | j        dk    r'| j        |_        | xj        |j        d	z   d
z  z  c_        | j        |j        d	z   d
z  z   | _        | j                            d| j        | j                                        z
  z             | j        | j                                        k    sJ |                     ||           dS )zWrite raw table data to disk.r   rP   NrQ   rR   rS   Tr    rv   r   )r?   r   r.   r<   r   r%   rU   rV   	headTableuncompressedsaveDatar)   r+   r   
origOffset
origLengthlengthr   rf   r   )rA   r<   rD   rE   s       r   __setitem__zSFNTWriter.__setitem__   sl   DK	/#5	6	66




%%)%%,F]] bqbK!7$rss)!CDD5>4>5 &&5>..D!!!	[F.5 01 4::-%,2Bb1HI$
 )//%4/$)..2B2BBCDDD		!1!1	1	1	1	1--Ur   c                     | j         |         S rH   rI   rJ   s     r   rZ   zSFNTWriter.__getitem__  s    	S	r   c                    t          | j                                                  }t          |          | j        k    r&t          d| j        t          |          fz            | j        dk    rd| _        d| _        d| _	        | xj	        dt          |          z  z  c_	        |D ] \  }}| xj	        |j
        dz   dz  z  c_	        !| j        r| j        nt                      }|j         |j        |j        | _        |j        | _        nNt          | d
          r0t!          j        d| j        dd                   \  | _        | _        ndx| _        | _        |j        rt          |j                  | _        | j                            dd           | j                                        | _        t3          |j                  }t          |          | _        | j                            |           ndx| _        x| _        | _        |j        r| j                            dd           | j                                        }|dz   dz  }| j                            d||z
  z             | j                                        | _        t          |j                  | _        | j                            |j                   ndx| _        | _        | j                            dd           | j                                        | _        n| j        rJ d| j        z              	 tA          j!        | j"        |           }| j                            | j#        | j$        z              d}	|D ]$\  }}|dk    rd}	||%                                z   }%|	r| &                    |           | 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    r   r   rS   r   rv   r   Nr   z>HHr   rQ   r}    r   rP   r   )'r=   r?   r>   r3   r:   r   r+   r   reservedtotalSfntSizer   r,   r@   majorVersionminorVersionhasattrstructr4   r   metaDatametaOrigLengthr)   r   rf   
metaOffsetr   
metaLengthr   privData
privOffset
privLengthr   r   packr   r   r   toStringwriteMasterChecksum)
rA   r?   r<   rE   rD   compressedMetaDataoff	paddedOff	directoryseenHeads
             r   r^   zSFNTWriter.close  s    $+##%%&&&[[DN""	Ct~WZ[aWbWbFcc	d	dd	[F4>4=4c&kk)) 6 6zsE5+a/255!_
B$//.2B2B4
#(9(E)D)Dt[!! /,2M%PQRSPSAT,U,U)T))-..T*
m @dm,,DINN1Qinn&&DO!$-00,--DOIOO&''''>??DO?do(;
m 	*INN1Q
)..

CqBIIOODIO,---inn&&DO$-((DOIOODM""""())DOdo9>>!A!!4;; k>>04;>>>>l4/66))..%(::;;;( , ,jc5	VmmH5>>+++99 'I&&&)..%&&&)//)r   c                    t          | j                                                  }g }t          t	          |                    D ]-}|                    | j        ||                  j                   .| j        t          k    rddl	m
}  || j        d          \  | _        | _        | _        t          j        t"          |           }t%          | j                                                  }|D ]Z\  }}t                      }	|j        |	_        |j        |	_        |j        |	_        |j        |	_        ||	                                z   }[t4          t	          | j                  t6          z  z   }
|
t	          |          k    sJ |                    t9          |                     t;          |          dz  }d|z
  dz  }|S )Nr   r   r       l   /ac )listr?   rM   r9   r3   appendrV   r.   r-   r   r   r:   r   r   r   r   r   r5   r=   r>   r<   r   r%   r   r   r   r2   r   rU   sum)rA   r   tags	checksumsr&   r   r?   r<   rE   	sfntEntrydirectory_endrY   checksumadjustments                r   _calcMasterChecksumzSFNTWriter._calcMasterChecksum^  s   	dk  	!	!$)T 3 3aDKQ(12222	...------;I>$.Z\;];]84T'|/6694;$$&&''6 1 1zsE"$$IIIMI'I'II..000II#c$+&6&69O&OO-	#i..	(	(	(	(<	**+++^^j(("X-;	r   c                     |                      |          }| j                            | j        d         j        dz              | j                            t          j        d|                     d S )NrP   rQ   z>L)r   r)   r   r?   r%   r   r   r   )rA   r   r   s      r   r   zSFNTWriter.writeMasterChecksum|  s`    //	::)..V$+a/000)//&+d$67788888r   c                     dS NFrt   rN   s    r   reordersTableszSFNTWriter.reordersTables  s    	r   )r!   NN)rp   rq   rr   r   rF   r   r   rZ   r^   r   r   r   rt   r   r   r   r      s          " 2D       D    <  @ @ @D  <9 9 9    r   r   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                   D    e Zd Zd Zd Zd Zd Zd Zd Zd Z	d Z
d	 Zd
S )r.   c                     d| _         d S r   )r   rN   s    r   rF   zDirectoryEntry.__init__  s    $r   c                 l    t          j        | j        |                    | j                  |            d S rH   )r   r4   formatr   r   )rA   r)   s     r   r;   zDirectoryEntry.fromFile  s,    	.dii88$?????r   c                 <    t          j        | j        ||            d S rH   )r   r4   r   )rA   strs     r   
fromStringzDirectoryEntry.fromString  s    	.c4(((((r   c                 6    t          j        | j        |           S rH   )r   r   r   rN   s    r   r   zDirectoryEntry.toString  s    	dk4	(	((r   c                     t          | d          r$d| j        j        | j        t	          |           fz  S d| j        j        t	          |           fz  S )Nr<   z<%s '%s' at %x>z
<%s at %x>)r   	__class__rp   r<   idrN   s    r   __repr__zDirectoryEntry.__repr__  sN    T5 =
t~6"T((K
KK
$.12d88<
<<r   c                     |                     | j                   |                    | j                  }t	          |          | j        k    sJ t          | j        d          r|                     |          }|S )N
decodeData)r   r%   r   r   r3   r   r   r   rA   r)   rD   s      r   rT   zDirectoryEntry.loadData  sl    ))DK	4;		$	Tdk	!	!	!	!T^\**  
//$

4	+r   c                     t          | j        d          r|                     |          }t          |          | _        |                    | j                   |                    |           d S )N
encodeData)r   r   r   r3   r   r   r%   r   r   s      r   r   zDirectoryEntry.saveData  s`    T^\**  
//$

4D		$+))DK**Tr   c                     |S rH   rt   )rA   rawDatas     r   r   zDirectoryEntry.decodeData  s    	.r   c                     |S rH   rt   )rA   rD   s     r   r   zDirectoryEntry.encodeData  s    	+r   N)rp   rq   rr   rF   r;   r   r   r   rT   r   r   r   rt   r   r   r.   r.     s          @ @ @) ) )) ) )= = =          r   r.   c                       e Zd ZeZeZdS )r-   N)rp   rq   rr   sfntDirectoryEntryFormatr   r   r   rt   r   r   r-   r-     s        
"$r   r-   c                   2     e Zd ZeZeZ fdZd Zd Z	 xZ
S )r6   c                     t          t          |                                            t          t          d          st          | _        d S d S )NzlibCompressionLevel)superr6   rF   r   ZLIB_COMPRESSION_LEVELr   )rA   r   s    r   rF   zWOFFDirectoryEntry.__init__  sN    D!!**,,, 
#%;	<	< 6546 6r   c                     dd l }| j        | j        k    r|}nA| j        | j        k     sJ |                    |          }t	          |          | j        k    sJ |S Nr   )r   r   r   
decompressr3   )rA   r   r   rD   s       r   r   zWOFFDirectoryEntry.decodeData  se    +++	[DO##
44
+
'
'
'
'
//'
"
"4
d))t
&
&
&
&	+r   c                     t          |          | _        | j        st          || j                  }| j        st          |          | j        k    r|}| j        | _        n|}t          |          | _        |S rH   )r3   r   r   r   r   r   )rA   rD   compressedDatar   s       r   r   zWOFFDirectoryEntry.encodeData  sr    II$/		 >T4#<==>	 #n--@@74;;7W4;	.r   )rp   rq   rr   woffDirectoryEntryFormatr   woffDirectoryEntrySizer   rF   r   r   __classcell__)r   s   @r   r6   r6     s`        
"$	6 	6 	6 	6 	6        r   r6   c                        e Zd ZdZddZd ZdS )r@   r    Nc                 r   d | _         d | _        d | _        d | _        |r|j         | _         |j        | _        |j        r|j                            |j                   |j                            |j                  }t          |          |j        k    sJ | 
                    |          }t          |          |j        k    sJ || _        |j        rc|j                            |j                   |j                            |j                  }t          |          |j        k    sJ || _        d S d S d S rH   )r   r   r   r   r   r)   r   r   r   r3   _decompressr   r   r   )rA   readerr   rD   s       r   rF   zWOFFFlavorData.__init__"  s=   $$$-$- *4*4 
KV&'''kv011Gw<<6,,,,,G$$Dt99-----DM 
KV&''';F-..Dt99)))))DMMM  r   c                 4    dd l }|                    |          S r   )r   r   )rA   r   r   s      r   r   zWOFFFlavorData._decompress7  s    +++		!	!!r   rH   )rp   rq   rr   FlavorrF   r   rt   r   r   r@   r@     s<        
   *" " " " "r   r@   c                 8   t          |           dz  }|r| dd|z
  z  z  } d}d}|dz  dk    sJ t          dt          |           |          D ]L}| |||z            }t          j        dt          |          dz  z  |          }|t	          |          z   dz  }M|S )aw  Calculate the checksum for an arbitrary block of data.
	Optionally takes a 'start' argument, which allows you to
	calculate a checksum in chunks by feeding it a previous
	result.

	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   r   r   i   >%dLr   )r3   r9   r   r4   r   )rD   	remaindervalue	blockSizer&   blocklongss          r   rU   rU   <  s     YY] "%1y=
!!$	
A
3t99i
(
( , ,Q
q9}
%
-#e**/2E
:
:%3u::
+%%r   c                    |                      d           |                     t                    }t          |          t          k    rt	          d          t                      }t          j        t          ||           |j	        dk    rt	          d          |j
        dk    s|j
        dk    sJ d|j
        z              t          j        d|j        z  |                     |j        d	z                      |_        |j
        dk    r	 |S )
Nr   r   ttcfzNot a Font Collection   i   zunrecognized TTC version 0x%08xr   r   )r   r   ttcHeaderSizer3   r   r   r   r4   ttcHeaderFormatTTCTagVersionr   r0   r1   )r)   rD   rA   s      r   r/   r/   V  s    1		-  II<===t,,,K6*+++
""dlj&@&@&@BcfjfrBr&@&@&@M&4="8$))DMTUDU:V:VWWLJr   c                 d   t                      }d|_        d|_        ||_        |                     d           |                     t          j        t          |                     | 	                                }|                     t          j        d|j        z  gdg|j        z  R             |S )Nr  r  r   r   )r   r
  r  r0   r   r   r   r   r	  rf   r   )r)   r0   rA   r%   s       r   writeTTCHeaderr  e  s    1GL$//000
))++FK.G1#2EGGGHHHr   __main__)0__doc__ior   typesr   fontTools.misc.py23r   fontTools.miscr   r   r   r   collectionsr   logging	getLoggerrp   rW   r   r
   r   r   r   r   r   r	  calcsizer  r5   r2   r   r   r8   r7   r   r   r.   r-   r6   r@   rU   r/   r  sysdoctestexittestmodfailedrt   r   r   <module>r     s          ! ! ! ! ! ! # # # # # # " " " " " " & & & & & &  # # # # # #  g!!y y y y y y y yz   
   0 < < < <"C C C C C C C CP	 ! 11  %G$%899   *)*BCC  " %G$%899   *)*BCC ' ' ' ' 'V ' ' 'R% % % % % % % %
% % % % % % % %N" " " " " " " "<  4  	 	 	 z	/'/


"##### r   