U
    '1et                     @   s^  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 dOd5d6Z>dPd7d8Z?dQd9d:Z@d;d< ZAdRd>d?ZBd@dA ZCdBdC ZDdDdE ZEdFdG ZFeGeH eH e H e!H dHfdIdJZIddKlmJZJ eJeI [JeKdLkrZeF  eE  dS )Sz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                   @   s   e Zd ZdS )	FontErrorN__name__
__module____qualname__ r   r   @/tmp/pip-unpacked-wheel-109iniqw/reportlab/pdfbase/pdfmetrics.pyr   '   s   r   c                   @   s   e Zd ZdS )FontNotFoundErrorNr   r   r   r   r   r   )   s   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rd}ql|dd dkrd}ql|rl|d}dd |D }|dd \}}}	| \}
}|
dkstd| t|}| \}
}|
dkstd| zt|}W n tk
r@   t|}Y nX |	 \}
}|
dksdtd| |}||||f qld}|D ]}|dd	 dkrd}|dd	 d
krd}nl|r|dd dkrz|dd\}}W n   td| |f Y nX zt|}W n   Y nX |||< 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   s   g | ]}|  qS r   strip.0lr   r   r   
<listcomp>=   s     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   s   g | ]}|  qS r   r   )r    chunkr   r   r   r"   H   s        Czbad line in font file %sZWXNZStartFontMetrics   Comment z-Header information error in afm %s: line='%s')r   lensplit
ValueErrorAssertionErrorintfloatappend)afmFileNamelinestopLevelZ
glyphLevelZ	inMetricslinechunksZcidChunkZ
widthChunkZ	nameChunkr!   r   cidwidthnameZinHeaderleftrightr   r   r   parseAFMFile,   sf    
 

rA   c                   @   s.   e Zd Zdd Zdd Zdd Zddd	Zd
S )TypeFacec                 C   sz   || _ g | _i | _d| _d| _d | _d| _d| _|dkr@d| _n|dkrPd| _nd | _|t	krpd| _
| | nd| _
d S )Nr   ZapfDingbatsZZapfDingbatsEncodingSymbolZSymbolEncodingr   )r>   
glyphNamesglyphWidthsascentdescent
familyNamebolditalicrequiredEncodingstandardFontsbuiltIn_loadBuiltInDataselfr>   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widthsByFontGlyphrF   listkeysrE   Zascent_descentrG   rH   rP   r   r   r   rO      s    zTypeFace._loadBuiltInDatac                 C   s   g S )z=Info function, return list of the font files this depends on.r   rQ   r   r   r   getFontFiles   s    zTypeFace.getFontFiles.pfbc                 C   s   |  | f}t| drNtj| jd }|D ]}t|| r0||   S q0zt	| j
}W nn   t| j
}|r|  dkr|D ]*}tj|d | }t|r|}qd }qq|  dkr|}nd }Y nX |d krtd|| j
f  |S )NpfbFileNamer   rX   z.afmzCan't find %s for face '%s')r$   upperhasattrospathsplitextrY   r   r   
findT1Filer>   bruteForceSearchForAFMr   )rQ   extZpossible_extsZ
r_basenameer   afmpfbr   r   r   r_      s.    


zTypeFace.findT1FileN)rX   )r   r   r   rR   rO   rW   r_   r   r   r   r   rB   u   s   rB   c                 C   sb   |d krddl m} t| r | S tj| }|D ],}t|s>q0tj||}t|r0|  S q0| S )Nr   r   )reportlab.rl_configr   r   r\   r]   basenamer   join)fnZ
searchPathZbfndirnameZtfnr   r   r   bruteForceSearchForFile   s        
rk   c           
   
   C   s   ddl m} |D ]}t|sqt|tj d }|D ]j}z*t|\}}|d | kr`|W     S W q4   t \}}}	d	t
t|jd|   f|_ Y q4X q4qdS )zcLooks in all AFM files on path for face with given name.

    Returns AFM file name or None.  Ouch!r   re   z*.[aA][fF][mM]FontNamer/   z, while looking for faceName=%rN)rf   r   r   r   r\   seprA   sysexc_inforh   maprS   args)
faceNamer   rj   Z	possiblespossibleZtopDictZ	glyphDicttvbr   r   r   r`      s     r`   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kr8|d ks$td|| _tj| | _n|d krTt| _tjt | _njt	|r~t
|}|j | _|jd d  | _n@t|rt| _|d d  | _n"t|tr|j | _|jd d  | _d S )Nr   z2Can't have a base encoding for a standard encoding)r>   frozenstandardEncodingsr3   baseEncodingNamer   	encodingsvectorr   r   getEncodingr
   
isinstancerw   )rQ   r>   basebaseEncr   r   r   rR      s&    
zEncoding.__init__c                 C   s
   | j | S )z.Return glyph name for that code point, or None)r|   )rQ   indexr   r   r   __getitem__   s    zEncoding.__getitem__c                 C   s@   | j dkstd| j| |kr<t| j}|||< t|| _d S )Nr   Cannot modify a frozen encoding)rx   r3   r|   rT   tuple)rQ   r   valueLr   r   r   __setitem__   s
    
zEncoding.__setitem__c                 C   s   t | j| _d| _d S Nr   )r   r|   rx   rV   r   r   r   freeze   s    zEncoding.freezec                 C   s    | j |j kot| jt|jkS N)r>   r   r|   )rQ   otherr   r   r   isEqual  s    zEncoding.isEqualc                 C   s6   | j dkstd|}|D ]}|| j|< |d }qdS )zASet a group of character names starting at the code point 'base'.r   r   r   N)rx   r3   r|   )rQ   r   ZnewNamesidxr>   r   r   r   modifyRange  s
    
zEncoding.modifyRangec                 C   sv   g }d}t t| jD ]L}| j| }||j| krF|rb|| g }q|rV|| q|r||g}q|rr|| |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)ranger0   r|   r6   )rQ   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k	r`|d|  q`qB|||d< |dkr|||d< |d	|d
< ||}	|	S dS )z&Returns a PDF Object representing selfr   pdfdocr   N/ZDifferences)ZMacRomanEncodingZMacExpertEncodingZWinAnsiEncodingZBaseEncodingrw   Type)	reportlab.pdfbaser   rz   r}   r   PDFNamer6   PDFArrayPDFDictionary)
rQ   r   Drz   r   ZdifferencesZ	diffArrayr   	glyphNameZPDr   r   r   makePDFObject,  s&    


zEncoding.makePDFObject)N)r   r   r   __doc__rR   r   r   r   r   r   r   r   r   r   r   r   rw      s   
rw   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r8|jd kr8tn|p>g | _	| 
  t| _|dkr\| p^t| _d S )NrC   )fontNamegetTypeFacefacer}   encodingencNamerN   rL   standardT1SubstitutionFontssubstitutionFonts_calcWidths_notdefChar_notdefFont)rQ   r>   rr   r   r   r   r   r   r   rR   ]  s    
zFont.__init__utf8c                 C   s   t | |||dS )Nr   )r   )rQ   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   r>   rV   r   r   r   __repr__l  s    zFont.__repr__c              	   C   s   dgd }| j j}| jj}tdD ]d}|| }|dk	r"z|| }|||< W q" tk
r   ddl}|jjrt	d| j j
|f  n Y q"X q"|| _dS )z)Vector of widths for stringWidth functionr      Nz3typeface "%s" does not have a glyph "%s", bad font!)r   rF   r   r|   r   KeyErrorrf   Z	rl_configZwarnOnMissingFontGlyphsprintr>   widths)rQ   wZgwZvecr   r   r=   Z	reportlabr   r   r   r   o  s    
zFont._calcWidthsc                 C   sV   d}t d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   bytesrS   r   )rQ   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|r`|dkrf||_| jjtkrd|_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   reprr0   ZfontMappingZPDFType1FontNamer   r>   ZBaseFontr   Z__Comment__r   r   r   rw   rM   Z	FirstCharZLastCharr   r   ZWidths
addObjectsZFontDescriptor	ReferenceZ
idToObjectdict)rQ   docr   ZinternalNameZpdfFontrb   refZfontDictr   r   r   r     s$    

zFont.addObjects)N)r   )r   r   r   r   
_multiByte_dynamicFontrR   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rPtd|ttt|| ||  || d  f |tkr\d S | d } || d  d> || d  d> B || d  B d> ||  B }| d } | | t|krt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_MARKERr2   ordPFB_EOFr0   )pdmri   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   )rB   rR   r	   r   r\   r]   abspathr7   rY   rL   _loadGlyphs_loadMetrics)rQ   r7   rY   r   r   r   rR     s    


zEmbeddedType1Face.__init__c                 C   s   | j | jgS r   )r7   rY   rV   r   r   r   rW     s    zEmbeddedType1Face.getFontFilesc           	      C   s   t |}t|st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 foundrv   r   N)rk   r   r3   r   r   	PFB_ASCII
PFB_BINARYr   _binaryDatar0   _length_length1_length2_length3)	rQ   rY   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ddddg}| }g | _|D ]}| jt| qi }|D ]\}}	}
|	||
< q|| _t| | _| j  |dddkrtdkr>zddlm} |a~W n   i atdY nX dgd }i }i }|D ]V\}}	}
d|  krvdkrTn n.|
||< t|
d}|dk	rT|||< |||< qTtd| j }tj||| || _t||}t| dS )z Loads in and parses font metricsrl   Z
FamilyNameZAscenderi  Z	Descenderr   	CapHeightItalicAnglestemVXHeightFontBBoxZ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) rk   rA   r>   rI   getrG   rH   	capHeightitalicAngler   xHeightr1   bboxr6   r4   rF   rT   rU   rE   sort_postScriptNames2UnicodeZreportlab.pdfbase._glyphlistr   r2   r{   normalize_encodingr   	RL_CodecsZadd_dynamic_codecrL   rw   registerEncoding)rQ   r7   r9   Z	glyphDataZstrBboxtokenstokrF   r<   r=   r>   r   namesexZrexcodeur   encr   r   r   r     s^    








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DescentZFlagsr   rl   r   ZStemVr   ZFontFilezfontDescriptor:)r   r   Z	PDFStreamr   contentr   
dictionaryr   r   r   rY   r   rG   r   rH   r   r   r   r>   r   r   r   )rQ   r   r   ZfontFileZfontFileRefZfontDescriptorZfontDescriptorRefr   r   r   r   $  s,    

zEmbeddedType1Face.addObjectsN)	r   r   r   r   rR   rW   r   r   r   r   r   r   r   r     s   =r   c                 C   s8   t | tstd|  | t| j< | jtkr4t| j d S )NzNot a TypeFace: %s)r~   rB   r3   
_typefacesr>   rM   registerFontFamily)r   r   r   r   registerTypeFaceB  s    

r   c                 C   s`   t | tstd|  | jtkrJ| t| j r:|   q\td| j n| t| j< |   d S )NzNot an Encoding: %sz>Encoding "%s" already registered with a different name vector!)r~   rw   r3   r>   
_encodingsr   r   r   )r   r   r   r   r   J  s    


r   c                 C   s   ddl m} |s| }|  } |s,|p*|p*|}|s4|}|s<|}|| dd| || dd| || dd| || dd| d S )Nr   )fontsr   )Zreportlab.libr  r$   Z
addMapping)familynormalrJ   rK   Z
boldItalicr  r   r   r   r   W  s        r   c                 C   s~   | j }| jrb| jj}|tkrj|tkrPt| }|jsFtd|| |f q`|t|< qj|  t|< t|< n| t|< | jrzt| j  dS )zGRegisters a font, including setting up info for accelerated stringWidthz+Attempt to register fonts %r %r for face %rN)	r   r   r   r>   _fonts_dynFaceNamesr2   r   r   )fontr   rr   Zofontr   r   r   registerFontc  s    
r  c                 C   s   z
t |  W S  tk
r   | tkrPt| }tj|  \|_|_|_t	| | Y S t
| }|rdD ]$}tj|d | }t|r` qq`t|std| t||}t	| | Y S  Y nX dS )z-Lazily construct known typefaces if not found)rX   z.PFBr   zfile %s not found!N)r   r   rM   rB   r   ZstandardFontAttributesrI   rJ   rK   r   r`   r\   r]   r^   r   r3   r   )rr   r   rc   rb   rd   r   r   r   r   {  s&    
 
r   c                 C   sF   z
t |  W S  tk
r@   | tkr:t| }t| | Y S  Y nX dS )z-Lazily construct known encodings if not foundN)r   r   ry   rw   r   )r   r   r   r   r   r}     s    
r}   c                 C   sZ   t | } t| t ks$tdt|  t| }|jrBt| | |j}nt| | t}t| |S )z-search for and register a font given its namez$fontName=%s is not required type str)	rS   typer3   asciir   rL   r   r   r  )r   r   r  r   r   r   findFontAndRegister  s    r
  c                 C   s,   z
t |  W S  tk
r&   t|  Y S X dS )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.N)r  r   r
  )r   r   r   r   getFont  s    
r  rC   rD   c                 C   s^   t | }z|j}|j}W n   |jj}|jj}Y nX |rR|d }|| || fS ||fS d S )Ng     @@)r  rG   rH   r   )r   fontSizer  rG   rH   Znormr   r   r   getAscentDescent  s    
r  c                 C   s   t | |d S )Nr   r  r   r  r   r   r   	getAscent  s    r  c                 C   s   t | |d S r   r  r  r   r   r   
getDescent  s    r  c                  C   s   t t } |   | S )zReturns what's in there)rT   r  rU   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| qVt   t d tt }|  |D ](}t| }t d|j|jj	|j
j	f  qd S )NzRegistered Encodings:z   zRegistered Typefaces:zRegistered Fonts:z    %s (%s/%s))r   rT   r   rU   r   r   r  r   r   r>   r   )rU   r   Zfacesrr   kkeyr  r   r   r   dumpFontData  s$    r  c           
      C   s   dd l }tdd D ]}|  }t|j}| D ]"}d}|D ]}||t|  }q:q.|  }td||   |  }| D ]}t||d}	qv|  }td||   t  qd S )Nr   r   zslow stringWidth took %0.4f
   z'class lookup and stringWidth took %0.4f)timerM   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   r0   r  r1   )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)rB   r   r   rE   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  ru   r   r   r   r   _reset'  s
    
r(  )register_reset__main__)N)NNNN)N)N)N)r   )L__version__r   r\   rn   r{   r   r   Zreportlab.lib.loggerr   Zreportlab.lib.utilsr   r   r   r   r   r	   r
   r   rf   r   r   Zreportlab.lib.rl_accelr   r   r   r   r   registerrM   ry   r   r   r  r  	Exceptionr   r   rA   rB   rk   r`   rw   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   copyr(  r)  r   r   r   r   r   <module>   s   (
IB

w_ 






