o
    e*x                     @   sb  d Z dZddl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mZmZmZmZmZmZ ddlmZmZ ddlmZmZ dd	lmZ d
Zej  ejZejZi Zi Zi Z i Z!G dd de"Z#G dd de"Z$dd Z%G dd dZ&dMddZ'dd Z(G dd dZ)g Z*G dd dZ+e,dZ-e,dZ.e,dZ/e,dZ0dd  Z1da2G d!d" d"e&Z3d#d$ Z4d%d& Z5dNd'd(Z6d)d* Z7d+d, Z8d-d. Z9d/d0 Z:d1d2 Z;e;d3Z<e*=e;d4e<g dMd5d6Z>dMd7d8Z?dMd9d:Z@d;d< ZAdOd>d?ZBd@dA ZCdBdC ZDdDdE ZEdFdG ZFeGeH eH e H e!H dHfdIdJZIddKlmJZJ eJeI [JeKdLkr/eF  eE  dS dS )Pz3.3.0a  This provides a database of font metric information and
efines Font, Encoding and TypeFace classes aimed at end users.

There are counterparts to some of these in pdfbase/pdfdoc.py, but
the latter focus on constructing the right PDF objects.  These
classes are declarative and focus on letting the user construct
and query font objects.

The module maintains a registry of font objects at run time.

It is independent of the canvas or any particular context.  It keeps
a registry of Font, TypeFace and Encoding objects.  Ideally these
would be pre-loaded, but due to a nasty circularity problem we
trap attempts to access them and do it on first access.
    N)	_fontdata)warnOnce)	rl_isfilerl_globrl_isdiropen_and_readopen_and_readlinesfindInPathsisSeqisStr)defaultEncodingT1SearchPath)
unicode2T1instanceStringWidthT1)	rl_codecs   nc                   @      e Zd ZdS )	FontErrorN__name__
__module____qualname__ r   r   LD:\Projects\ConvertPro\env\Lib\site-packages\reportlab/pdfbase/pdfmetrics.pyr   '       r   c                   @   r   )FontNotFoundErrorNr   r   r   r   r   r   )   r   r   c              	   C   s  t | d}t|dkr |r|d d}t|dkr td|  i }g }dd |D }dd |D }d}|D ]}|dd	 d
krCd}q6|dd dkrNd}q6|r|d}dd |D }|dd \}}}	| \}
}|
dksuJ d| t|}| \}
}|
dksJ d| zt|}W n ty   t|}Y nw |	 \}
}|
dksJ d| |}||||f q6d}|D ]G}|dd	 dkrd}|dd	 d
krd}q|r|dd dkrz
|dd\}}W n   td| |f zt|}W n   Y |||< q||fS )a  Quick and dirty - gives back a top-level dictionary
    with top-level items, and a 'widths' key containing
    a dictionary of glyph names and widths.  Just enough
    needed for embedding.  A better parser would accept
    options for what data you wwanted, and preserve the
    order.r   r   zAFM file %s hasn't enough datac                 S      g | ]}|  qS r   strip.0lr   r   r   
<listcomp>=       z parseAFMFile.<locals>.<listcomp>c                 S   s   g | ]}|  d s|qS )comment)lower
startswithr"   r   r   r   r%   >   s       ZStartCharMetrics   ZEndCharMetrics;c                 S   r   r   r    )r#   chunkr   r   r   r%   H   r&      Czbad line in font file %sZWXNZStartFontMetrics   Comment z-Header information error in afm %s: line='%s')r   lensplit
ValueErrorintfloatappend)afmFileNamelinestopLevelZ
glyphLevelZ	inMetricslinechunksZcidChunkZ
widthChunkZ	nameChunkr$   r   cidwidthnameZinHeaderleftrightr   r   r   parseAFMFile,   sj   

rD   c                   @   s.   e Zd Zdd Zdd Zdd Zddd	Zd
S )TypeFacec                 C   s|   || _ g | _i | _d| _d| _d | _d| _d| _|dkr d| _n|dkr(d| _nd | _|t	v r9d| _
| | d S d| _
d S )Nr   ZapfDingbatsZZapfDingbatsEncodingSymbolZSymbolEncodingr   )rA   
glyphNamesglyphWidthsascentdescent
familyNamebolditalicrequiredEncodingstandardFontsbuiltIn_loadBuiltInDataselfrA   r   r   r   __init__v   s"   
zTypeFace.__init__c                 C   s:   t |}tj| | _t| j | _tj| \| _| _	dS )zCalled for the built in 14 fonts.  Gets their glyph data.
        We presume they never change so this can be a shared reference.N)
strr   ZwidthsByFontGlyphrI   listkeysrH   Zascent_descentrJ   rK   rS   r   r   r   rR      s   zTypeFace._loadBuiltInDatac                 C   s   g S )z=Info function, return list of the font files this depends on.r   rT   r   r   r   getFontFiles   s   zTypeFace.getFontFiles.pfbc                 C   s   |  | f}t| dr'tj| jd }|D ]}t|| r&||   S qzt	| j
}W n5   t| j
}|rb|  dkrY|D ]}tj|d | }t|rU|}qBd }qBn|  dkra|}nd }Y |d u rrtd|| j
f  |S )NpfbFileNamer   r[   z.afmzCan't find %s for face '%s')r(   upperhasattrospathsplitextr\   r   r   
findT1FilerA   bruteForceSearchForAFMr   )rT   extZpossible_extsZ
r_basenameer   afmpfbr   r   r   rb      s6   

zTypeFace.findT1FileN)r[   )r   r   r   rU   rR   rZ   rb   r   r   r   r   rE   u   s
    rE   c                 C   sb   |d u r
ddl m} t| r| S tj| }|D ]}t|sqtj||}t|r.|  S q| S )Nr   r   )reportlab.rl_configr   r   r_   r`   basenamer   join)fnZ
searchPathZbfndirnameZtfnr   r   r   bruteForceSearchForFile   s   
rn   c           
   
   C   s   ddl m} |D ]D}t|sqt|tj d }|D ]1}zt|\}}|d | kr0|W     S W q   t \}}}	d	t
t|jd|   f|_ qdS )zcLooks in all AFM files on path for face with given name.

    Returns AFM file name or None.  Ouch!r   rh   z*.[aA][fF][mM]FontNamer3   z, while looking for faceName=%rN)ri   r   r   r   r_   seprD   sysexc_infork   maprV   args)
faceNamer   rm   Z	possiblespossibleZtopDictZ	glyphDicttvbr   r   r   rc      s    
rc   c                   @   sR   e Zd Z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 )Encodingz1Object to help you create and refer to encodings.Nc                 C   s   || _ d| _|tv r|d u sJ d|| _tj| | _d S |d kr,t| _tjt | _d S t|rBt	|}|j | _|jd d  | _d S t
|rRt| _|d d  | _d S t|tre|j | _|jd d  | _d S d S )Nr   z2Can't have a base encoding for a standard encoding)rA   frozenstandardEncodingsbaseEncodingNamer   	encodingsvectorr   r   getEncodingr
   
isinstancerz   )rT   rA   basebaseEncr   r   r   rU      s(   
zEncoding.__init__c                 C   s
   | j | S )z.Return glyph name for that code point, or None)r   )rT   indexr   r   r   __getitem__   s   
zEncoding.__getitem__c                 C   sD   | j dks	J d| j| |kr t| j}|||< t|| _d S d S )Nr   Cannot modify a frozen encoding)r{   r   rW   tuple)rT   r   valueLr   r   r   __setitem__   s   
zEncoding.__setitem__c                 C   s   t | j| _d| _d S Nr   )r   r   r{   rY   r   r   r   freeze   s   
zEncoding.freezec                 C   s    | j |j kot| jt|jkS N)rA   r   r   )rT   otherr   r   r   isEqual  s    zEncoding.isEqualc                 C   s6   | j dks	J d|}|D ]}|| j|< |d }qdS )zASet a group of character names starting at the code point 'base'.r   r   r   N)r{   r   )rT   r   ZnewNamesidxrA   r   r   r   modifyRange  s   

zEncoding.modifyRangec                 C   sv   g }d}t t| jD ]&}| j| }||j| kr#|r"|| g }q|r+|| q|r1||g}q|r9|| |S )aZ  
        Return a compact list of the code points differing between two encodings

        This is in the Adobe format: list of
           [[b1, name1, name2, name3],
           [b2, name4]]
           
        where b1...bn is the starting code point, and the glyph names following
        are assigned consecutive code points.
        
        N)ranger4   r   r9   )rT   ZotherEncrangesZcurRangeiZglyphr   r   r   getDifferences  s"   


zEncoding.getDifferencesc           
      C   s   ddl m} i }| j}t|}| |}|g kr||S g }|D ]}||d  |dd D ]}|dur=|d|  q0q!|||d< |dv rQ|||d< |d	|d
< ||}	|	S )z&Returns a PDF Object representing selfr   pdfdocr   N/ZDifferences)ZMacRomanEncodingZMacExpertEncodingZWinAnsiEncodingZBaseEncodingrz   Type)	reportlab.pdfbaser   r}   r   r   PDFNamer9   PDFArrayPDFDictionary)
rT   r   Dr}   r   ZdifferencesZ	diffArrayr   	glyphNameZPDr   r   r   makePDFObject,  s*   


zEncoding.makePDFObjectr   )r   r   r   __doc__rU   r   r   r   r   r   r   r   r   r   r   r   rz      s    
rz   c                   @   sL   e Zd ZdZdZdZdddZdddZd	d
 Zdd Z	dd Z
dd ZdS )FontaD  Represents a font (i.e combination of face and encoding).

    Defines suitable machinery for single byte fonts.  This is
    a concrete class which can handle the basic built-in fonts;
    not clear yet if embedded ones need a new font class or
    just a new typeface class (which would do the job through
    composition)r   Nc                 C   sf   || _ t| }| _t|| _|| _|jr|jd u rtn|pg | _	| 
  t| _|dkr.| p/t| _d S )NrF   )fontNamegetTypeFacefacer   encodingencNamerQ   rO   standardT1SubstitutionFontssubstitutionFonts_calcWidths_notdefChar_notdefFont)rT   rA   ru   r   r   r   r   r   r   rU   ]  s   

zFont.__init__utf8c                 C   s   t | |||dS )Nr   )r   )rT   textsizer   r   r   r   stringWidthi  s   zFont.stringWidthc                 C   s   d| j j| jjf S )Nz<%s %s>)	__class__r   r   rA   rY   r   r   r   __repr__l  s   zFont.__repr__c              	   C   s   dgd }| j j}| jj}tdD ]2}|| }|durCz
|| }|||< W q tyB   ddl}|jjr?t	d| j j
|f  n	 Y qw q|| _dS )z)Vector of widths for stringWidth functionr      Nz3typeface "%s" does not have a glyph "%s", bad font!)r   rI   r   r   r   KeyErrorri   Z	rl_configZwarnOnMissingFontGlyphsprintrA   widths)rT   wZgwZvecr   r   r@   Z	reportlabr   r   r   r   o  s$   


zFont._calcWidthsc                 C   sV   d}t dD ]"}|d tt| j| d }|dkr|d }|d dkr(|d	 }q|S )
z<returns a pretty block in PDF Array format to aid inspection   [r       r      s    ]r*         
)r   bytesrV   r   )rT   r   r   r   r   r   _formatWidths  s   zFont._formatWidthsc                 C   s   ddl m} dtt|jd  }| }||_| jj|_	d| j
 |_| j }t|r0|dv r3||_| jjtvrMd|_d|_|| j|_| j||_|||}|jd j}|||< d	| |j| j
< d
S )zMakes and returns one or more PDF objects to be added
        to the document.  The caller supplies the internal name
        to be used (typically F1, F2... in sequence) r   r   Fr   zFont %s)z/MacRomanEncodingz/MacExpertEncodingz/WinAnsiEncodingr   Z
BasicFontsr   N)r   r   reprr4   ZfontMappingZPDFType1FontNamer   rA   ZBaseFontr   Z__Comment__r   r   r   rz   rP   Z	FirstCharZLastCharr   r   ZWidths
addObjectsZFontDescriptor	ReferenceZ
idToObjectdict)rT   docr   ZinternalNameZpdfFontre   refZfontDictr   r   r   r     s$   

zFont.addObjectsr   r   )r   r   r   r   
_multiByte_dynamicFontrU   r   r   r   r   r   r   r   r   r   r   Q  s    

r      r      r.   c              
   C   s   t ||  tkst || d  |kr(td|ttt|| ||  || d  f |tkr.d S | d } || d  d> || d  d> B || d  B d> ||  B }| d } | | t|krftd|| |t|f | | | fS )Nr   zGBad pfb file'%s' expected chr(%d)chr(%d) at char %d, got chr(%d)chr(%d)r   r.         z1Bad pfb file'%s' needed %d+%d bytes have only %d!)chr
PFB_MARKERr6   ordPFB_EOFr4   )pdmrl   r$   r   r   r   	_pfbCheck  s   $,8r   c                   @   s8   e Zd ZdZdd Zdd Zdd Zdd	 Zd
d ZdS )EmbeddedType1FacezcA Type 1 font other than one of the basic 14.

    Its glyph data will be embedded in the PDF file.c                 C   sZ   t | d  t|t}t|t}tj|| _tj|| _d | _	| 
| | | d S r   )rE   rU   r	   r   r_   r`   abspathr:   r\   rO   _loadGlyphs_loadMetrics)rT   r:   r\   r   r   r   rU     s   


zEmbeddedType1Face.__init__c                 C   s   | j | jgS r   )r:   r\   rY   r   r   r   rZ     s   zEmbeddedType1Face.getFontFilesc           	      C   s   t |}t|sJ d| t|d}td|t|\}}t||t|\}}t||t|\}}t||t| ||| |||  |||  | _t| j| _	|| | _
|| | _|| | _dS )ziLoads in binary glyph data, and finds the four length
        measurements needed for the font descriptorzfile %s not foundry   r   N)rn   r   r   r   	PFB_ASCII
PFB_BINARYr   _binaryDatar4   _length_length1_length2_length3)	rT   r\   r   s1l1s2l2Zs3l3r   r   r   r     s   
&

zEmbeddedType1Face._loadGlyphsc                 C   s  t |}t|\}}|d | _|d | _|dd| _|dd| _|dd| _|dd| _|d	d| _	|d
d| _
|dg d}| }g | _|D ]
}| jt| qOi }|D ]	\}}	}
|	||
< q^|| _t| | _| j  |dddkrtdu rzddlm} |a~W n	   i atddgd }i }i }|D ]'\}}	}
d|  krdkrn q|
||< t|
d}|dur|||< |||< qtd| j }tj||| || _t||}t| dS dS )z Loads in and parses font metricsro   Z
FamilyNameZAscender  Z	Descenderr   	CapHeightItalicAnglestemVXHeightFontBBox)r   r   r   r   ZEncodingSchemeNZFontSpecific)_glyphname2unicodezcannot import module reportlab.pdfbase._glyphlist module
you can obtain a version from here
https://www.reportlab.com/ftp/_glyphlist.py
r   r   zrl-dynamic-%s-encoding) rn   rD   rA   rL   getrJ   rK   	capHeightitalicAngler   xHeightr5   bboxr9   r7   rI   rW   rX   rH   sort_postScriptNames2UnicodeZreportlab.pdfbase._glyphlistr   r6   r~   normalize_encodingr   	RL_CodecsZadd_dynamic_codecrO   rz   registerEncoding)rT   r:   r<   Z	glyphDataZstrBboxtokenstokrI   r?   r@   rA   r   namesexrexcodeur   encr   r   r   r     sb   





zEmbeddedType1Face._loadMetricsc                 C   s   ddl m} | }| j|_| j|jd< | j|jd< | j|jd< |	|d| j
 }|d| j| j| jd|| j|| j| j| j| j|d	}|	|d
| j }|S )zFAdd whatever needed to PDF file, and return a FontDescriptor referencer   r   ZLength1ZLength2ZLength3z	fontFile:z/FontDescriptor"   )r   ZAscentr   ZDescentFlagsr   ro   r   ZStemVr   ZFontFilezfontDescriptor:)r   r   Z	PDFStreamr   contentr   
dictionaryr   r   r   r\   r   rJ   r   rK   r   r   r   rA   r   r   r   )rT   r   r   ZfontFileZfontFileRefZfontDescriptorZfontDescriptorRefr   r   r   r   $  s,   

zEmbeddedType1Face.addObjectsN)	r   r   r   r   rU   rZ   r   r   r   r   r   r   r   r     s    =r   c                 C   s<   t | tsJ d|  | t| j< | jtvrt| j d S d S )NzNot a TypeFace: %s)r   rE   
_typefacesrA   rP   registerFontFamily)r   r   r   r   registerTypeFaceB  s
   

r  c                 C   s`   t | tsJ d|  | jtv r%| t| j r|   d S td| j | t| j< |   d S )NzNot an Encoding: %sz>Encoding "%s" already registered with a different name vector!)r   rz   rA   
_encodingsr   r   r   )r   r   r   r   r   J  s   

r   c                 C   s   ddl m} |s
| }|  } |s|p|p|}|s|}|s|}|| dd| || dd| || dd| || dd| d S )Nr   )fontsr   )Zreportlab.libr  r(   Z
addMapping)familynormalrM   rN   Z
boldItalicr  r   r   r   r  W  s   r  c                 C   s   | j }| jr0| jj}|tvr/|tv r't| }|js"td|| |f |t|< n|  t|< t|< n| t|< | jr>t| j  dS dS )zGRegisters a font, including setting up info for accelerated stringWidthz+Attempt to register fonts %r %r for face %rN)	r   r   r   rA   _fonts_dynFaceNamesr6   r   r  )fontr   ru   Zofontr   r   r   registerFontc  s   
r  c                 C   s   zt |  W S  tyZ   | tv r't| }tj|  \|_|_|_t	| | Y S t
| }|rYdD ]}tj|d | }t|rA nq/t|sLJ d| t||}t	| | Y S  w )z-Lazily construct known typefaces if not found)r[   z.PFBr   zfile %s not found!)r  r   rP   rE   r   ZstandardFontAttributesrL   rM   rN   r  rc   r_   r`   ra   r   r   )ru   r   rf   re   rg   r   r   r   r   {  s&   

r   c                 C   s<   zt |  W S  ty   | tv rt| }t| | Y S  w )z-Lazily construct known encodings if not found)r  r   r|   rz   r   )r   r   r   r   r   r     s   
r   c                 C   sZ   t | } t| t u sJ dt|  t| }|jr!t| | |j}nt| | t}t| |S )z-search for and register a font given its namez$fontName=%s is not required type str)rV   typeasciir   rO   r   r   r  )r   r   r  r   r   r   findFontAndRegister  s   r  c                 C   s&   zt |  W S  ty   t|  Y S w )zLazily constructs known fonts if not found.

    Names of form 'face-encoding' will be built if
    face and encoding are known.  Also if the name is
    just one of the standard 14, it will make up a font
    in the default encoding.)r  r   r  )r   r   r   r   getFont  s
   
r  rF   rG   c                 C   sV   t | }z|j}|j}W n   |jj}|jj}Y |r'|d }|| || fS ||fS )Ng     @@)r  rJ   rK   r   )r   fontSizer  rJ   rK   Znormr   r   r   getAscentDescent  s   

r  c                 C      t | |d S )Nr   r  r   r  r   r   r   	getAscent     r  c                 C   r  r   r  r  r   r   r   
getDescent  r  r  c                  C   s   t t } |   | S )zReturns what's in there)rW   r  rX   r   )regr   r   r   getRegisteredFontNames  s   r  r   c                 C   s   t |j| ||dS )zjCompute width of string in points;
    not accelerated as fast enough because of instanceStringWidthT1/TTFr   )r  r   )r   r   r  r   r   r   r   r     s   r   c                  C   s   t d tt } |   | D ]}t d| qt   t d tt }|  |D ]}t d| q+t   t d tt }|  |D ]}t| }t d|j|jj	|j
j	f  qFd S )NzRegistered Encodings:z   zRegistered Typefaces:zRegistered Fonts:z    %s (%s/%s))r   rW   r  rX   r   r  r  r   r   rA   r   )rX   r   Zfacesru   kkeyr  r   r   r   dumpFontData  s&   r  c           
      C   s   dd l }tdd D ]K}|  }t|j}| D ]}d}|D ]
}||t|  }qq|  }td||   |  }| D ]
}t||d}	q;|  }td||   t  q
d S )Nr   r   zslow stringWidth took %0.4f
   z'class lookup and stringWidth took %0.4f)timerP   r  r   r   r   r   )
Ztextsr!  r   t0r   r   r   cht1r   r   r   r   test3widths  s$   
r%  c                  C   sl   t d } tdt|   td t| g t  |  }tdt|dt|  t| f  t| d S )Nz-../../rlextra/rml2pdf/doc/rml_user_guide.prepzrawdata length %dztest one huge string...z7test %d shorter strings (average length %0.2f chars)...g      ?)openreadr   r4   r%  r5   )rawdatawordsr   r   r   testStringWidthAlgorithms  s   
$r*  c                  C   sF   t d} t|  t| jdd  t d}t|j t| t  d S )NZ	Helveticar      ZWombat)rE   r  r   rH   r  )ZhelvZwombatr   r   r   test  s   

r,  )r  r  r  r  c                 C   s<   |   D ]\}}t | }|  || qtj  d S r   )itemsglobalsclearupdater   r   Zreset_dynamic_codecs)Zinitial_dictsr  rx   r   r   r   r   _reset'  s
   
r1  )register_reset__main__r   )NNNNr   )L__version__r   r_   rq   r~   r   r   Zreportlab.lib.loggerr   Zreportlab.lib.utilsr   r   r   r   r   r	   r
   r   ri   r   r   Zreportlab.lib.rl_accelr   r   r   r   r   registerrP   r|   r  r  r  r  	Exceptionr   r   rD   rE   rn   rc   rz   r   r   r   r   r   r   r   r   r   r   r  r   r  r  r   r   r  r  r   extendr  r  r  r  r   r  r%  r*  r,  r   copyr1  r2  r   r   r   r   r   <module>   s   (
I
B
w_ 







