U
    {c                     @   s  d Z ddlZddlZddlZddlZddlZddlZddlZddlZddl	Z	ddl
Z
ddlZddlmZmZ ddlmZ ddlmZ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mZm Z m!Z!m"Z"m#Z# ddl$m%Z% dd	l&m'Z'm(Z( dd
l)m*Z* zddl+m,Z, W n" e-k
r*   ddlm,Z, Y nX ddl.m/Z/ ddl0Z0ddl1Z1ddl2m3Z3m4Z4m5Z5 ddl6m7Z7m8Z8m9Z9m:Z:m;Z; ddl6m<Z=m>Z? dHddZ<dIddZ>dZ@dZAdZBdZCdZDeE ZFeGeHZIedddddgZJeKd jLZMG d!d" d"eZNG d#d$ d$eZOG d%d& d&e0jPZQG d'd( d(ZRG d)d* d*eRZSG d+d, d,e0jTZUG d-d. d.eVZWG d/d0 d0ZXG d1d2 d2ZYG d3d4 d4ZZG d5d6 d6eZZ[dJd8d9Z\d:d; Z]dKd<d=Z^d>d? Z_dLd@dAZ`dMdBdCZadDdE ZbdFdG Zcec  dS )Na  A library for reading and converting SVG.

This is a converter from SVG to RLG (ReportLab Graphics) drawings.
It converts mainly basic shapes, paths and simple text. The intended
usage is either as module within other projects:

    from svglib.svglib import svg2rlg
    drawing = svg2rlg("foo.svg")

or from the command-line where it is usable as an SVG to PDF converting
tool named sv2pdf (which should also handle SVG files compressed with
gzip and extension .svgz).
    N)defaultdict
namedtuple)stringWidth)FILL_EVEN_ODDFILL_NON_ZERO)PDFImage)
_CLOSEPATHCircleDrawingEllipseGroupImageLinePathPolyLinePolygonRect
SolidShapeString)colors)picatoLength)
haveImages)mmult)etree   )bezier_arc_from_end_pointsconvert_quadratic_to_cubic_pathnormalise_svg_path)get_global_font_mapDEFAULT_FONT_NAMEDEFAULT_FONT_WEIGHTDEFAULT_FONT_STYLEDEFAULT_FONT_SIZE)register_font	find_fontnormalc                 C   s   t | ||||S N)_fonts_register_font)	font_nameZ	font_pathweightstyleZrlgFontName r,   J/home/ubuntu/graampay/app_env/lib/python3.8/site-packages/svglib/svglib.pyr$   B   s    r$   c                 C   s   t | ||S r'   )_fonts_find_font)r)   r*   r+   r,   r,   r-   r%   F   s    r%   z1.5.1zLGPL 3zDinu Ghermanz
2023-01-07z$http://www.w3.org/XML/1998/namespaceBoxxywidthheightz[^ \t\r\n\f]+c                       s,   e Zd ZdZ fddZ fddZ  ZS )NoStrokePathzg
    This path object never gets a stroke width whatever the properties it's
    getting assigned.
    c                    s6   | dd }t j|| |r2| jt|j d S )N	copy_from)popsuper__init____dict__updatecopydeepcopyselfargskwargsr5   	__class__r,   r-   r8   `   s    zNoStrokePath.__init__c                    s2   t  j||}d|krd|d< d|kr.d |d< |S )NstrokeWidthr   strokeColor)r7   getPropertiesr>   r?   r@   propsrA   r,   r-   rE   f   s    zNoStrokePath.getProperties)__name__
__module____qualname____doc__r8   rE   __classcell__r,   r,   rA   r-   r4   [   s   r4   c                   @   s   e Zd Zdd Zdd ZdS )ClippingPathc                 O   s@   | dd }tj| f|| |r6| jt|j d| _d S )Nr5   r   )r6   r   r8   r9   r:   r;   r<   Z
isClipPathr=   r,   r,   r-   r8   q   s
    zClippingPath.__init__c                 O   s6   t j| f||}d|kr"d |d< d|kr2d |d< |S )N	fillColorrD   )r   rE   rF   r,   r,   r-   rE   x   s    zClippingPath.getPropertiesN)rH   rI   rJ   r8   rE   r,   r,   r,   r-   rM   p   s   rM   c                   @   s   e Zd Zdd ZdS )
CSSMatcherc           	      C   s   t j|ddd}|D ]h}|jr|jdkr*qt|j}t |j}dd t |jdD }||f}|D ]}| 	|| qjqd S )NT)Zskip_commentsZskip_whitespacezat-rulec                 S   s6   i | ].}d |kr| d d  | d d  qS ):r   r   )splitstrip.0attrr,   r,   r-   
<dictcomp>   s    z)CSSMatcher.add_styles.<locals>.<dictcomp>;)
tinycss2Zparse_stylesheetZpreludetype
cssselect2Zcompile_selector_list	serializecontentrQ   Zadd_selector)	r>   Zstyle_contentrulesZrule	selectorsZselector_stringZcontent_dictpayloadselectorr,   r,   r-   
add_styles   s       zCSSMatcher.add_stylesN)rH   rI   rJ   ra   r,   r,   r,   r-   rO      s   rO   c                   @   sH   e Zd 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S )AttributeConverterzEAn abstract class to locate and convert attributes in a DOM instance.c                 C   s   d | _ d | _d S r'   )	css_rulesmain_boxr>   r,   r,   r-   r8      s    zAttributeConverter.__init__c                 C   s
   || _ d S r'   )rd   )r>   rd   r,   r,   r-   set_box   s    zAttributeConverter.set_boxc                 C   sd   | d}dd |D }tdd |}i }|D ]0}| d\}}dd ||fD \}}|||< q.|S )znTry parsing compound attribute string.

        Return a dictionary with single attributes in 'line'.
        rW   c                 S   s   g | ]}|  qS r,   rR   rT   ar,   r,   r-   
<listcomp>   s     z;AttributeConverter.parseMultiAttributes.<locals>.<listcomp>c                 S   s   t | dkS Nr   )len)ri   r,   r,   r-   <lambda>       z9AttributeConverter.parseMultiAttributes.<locals>.<lambda>rP   c                 S   s   g | ]}|  qS r,   rg   )rT   sr,   r,   r-   rj      s     )rQ   filter)r>   lineattrsZ	new_attrsri   kvr,   r,   r-   parseMultiAttributes   s    

z'AttributeConverter.parseMultiAttributesc                 C   s   |j ddsr| jdk	r$|| j |j drr| |j d}| D ]\}}|dsJ||j |< qJd|j d< |j |d }|r|dkr|S |jdk	r| 	|j|S dS )	zSearch an attribute with some name in some node or above.

        First the node is searched, then its style attribute, then
        the search continues in the node's parent node. If no such
        attribute is found, '' is returned.
        __rules_appliedFNr+   -1 Zinherit)
attribgetrc   apply_rulesru   items
startswithrR   parentfindAttr)r>   svgNodenamerr   keyvalZ
attr_valuer,   r,   r-   r      s    




zAttributeConverter.findAttrc                 C   st   i }t | dkr(|| |  |jd}|rL| |}|| |j D ]\}}|dkrV|||< qV|S )zJReturn a dictionary of all attributes of svgNode or those inherited by it.gr+   )	node_nameZ	getparentr:   getAllAttributesrz   r{   ru   r}   )r>   r   dictr+   dr   valuer,   r,   r-   r      s    


z#AttributeConverter.getAllAttributesc                 C   s   |S )zReturn attribute as is.r,   r>   svgAttrr,   r,   r-   id   s    zAttributeConverter.idc              	   C   s~  |  }|dd }g }g }t|D ]\}}|dkr$|| q$tdt|dD ]}|| ||d   }}	||d |	 }
|
  }
|
dd}
tdd|
}
z:d|
kr|td	d
 |
	dD  n|t
|
 W n tk
r   Y qPY nX |d| d|	| d   ||	d d  }qP|dd	 }t|t|krPtd| g S g }t|D ]\}}|||| f q\|S )zParse transform attribute string.

        E.g. "scale(2) translate(10,20)"
             -> [("scale", 2), ("translate", (10,20))]
        Nz()r      r   , z[ ]+c                 s   s   | ]}t |V  qd S r'   float)rT   numr,   r,   r-   	<genexpr>  s     z6AttributeConverter.convertTransform.<locals>.<genexpr>z'Unable to parse transform expression %r)rR   	enumerateappendrangerl   replaceresubtuplerQ   r   
ValueErrorloggerwarning)r>   r   rq   ZopsZbracketsindicesiZlinZbiZbjZsublineresultopr,   r,   r-   convertTransform   s8     
.z#AttributeConverter.convertTransformN)rH   rI   rJ   rK   r8   rf   ru   r   r   r   r   r,   r,   r,   r-   rb      s   rb   c                       s   e Zd ZdZd fdd	Zedd Zedd Zedd	f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dZ  ZS )!Svg2RlgAttributeConverterz*A concrete SVG to RLG attribute converter.Nc                    s&   t    |p| j| _|pt | _d S r'   )r7   r8   identity_color_convertercolor_converterr   	_font_map)r>   r   font_maprA   r,   r-   r8     s    
z"Svg2RlgAttributeConverter.__init__c                 C   s   | S r'   r,   )cr,   r,   r-   r     s    z2Svg2RlgAttributeConverter.identity_color_converterc                 C   s   t |  ddS )Nr   r   )shlexrQ   rR   r   rU   r,   r,   r-   split_attr_list   s    z)Svg2RlgAttributeConverter.split_attr_list        c                    s  | dd }|sS d|kr> fdd|D S |drjdkrltd t|dd S  dkrtd	 t|dd S  d
krjj}n. dkrjj	}ntd  t|dd S t|dd d | S |drt|dd t
 S |dr&t|dd d S |drFt|dd  S |drbt|dd S |drt|dd  d S |drt|dd  d S | }t|}|S )zConvert length to points.r   r   c                    s   g | ]}j | d qS ))em_base	attr_namedefaultconvertLengthrT   r   r   r   r   r>   r,   r-   rj   ,  s   z;Svg2RlgAttributeConverter.convertLength.<locals>.<listcomp>%Nz4Unable to resolve percentage unit without a main boxz?Unable to resolve percentage unit without knowing the node name)r0   cxx1x2r2   )r1   cyy1y2r3   z.Unable to detect if node %r is width or heightd   Zpcptg      ?ZemZpxexr   ch)r   rR   r   endswithrd   r   errorr   r2   r3   r   r   )r>   r   r   r   r   textfulllengthr,   r   r-   r   $  sH    





z'Svg2RlgAttributeConverter.convertLengthc                    s    fdd  |D S )zConvert a list of lengths.c                    s   g | ]}  |qS r,   r   rh   re   r,   r-   rj   X  s     z?Svg2RlgAttributeConverter.convertLengthList.<locals>.<listcomp>)r   r   r,   re   r-   convertLengthListV  s    z+Svg2RlgAttributeConverter.convertLengthListc                 C   s   t |S r'   r   r   r,   r,   r-   convertOpacityZ  s    z(Svg2RlgAttributeConverter.convertOpacityc                 C   s   t td|dS )N)nonzeroZevenoddry   )r   r   r{   r   r,   r,   r-   convertFillRule]  s     z)Svg2RlgAttributeConverter.convertFillRulec                 C   sT  |}|r|dkrdS |dkr dS t |dkrP|d dkrPtj|t |dkd}nt |d	kr|d dkrtdd
|d   d
|d
   d
|d   }nt |dkr|d dkrtjdd
|d   d
|d
   d
|d   d
|d	   dd}n>t|}|dkr.ztt| }W n tk
r,   Y nX |dkrFtd| n
| 	|S dS )z$Convert string to a RL color object.noneNcurrentColor)   	   r   #r   )ZhasAlpha   r   r         TzCan't handle color: %s)
rl   r   ZHexColorZcssParsegetattrcloneAttributeErrorr   r   r   )r>   r   r   colorr,   r,   r-   convertColorc  s.    02 


z&Svg2RlgAttributeConverter.convertColorc                 C   s   dddd| S )Nr   r   r   )ZmiterroundZbevelr,   r   r,   r,   r-   convertLineJoin  s    z)Svg2RlgAttributeConverter.convertLineJoinc                 C   s   dddd| S )Nr   r   r   )Zbuttr   Zsquarer,   r   r,   r,   r-   convertLineCap  s    z(Svg2RlgAttributeConverter.convertLineCapc                 C   s   |  |}|S r'   )r   )r>   r   strokeDashArrayr,   r,   r-   convertDashArray  s    
z*Svg2RlgAttributeConverter.convertDashArrayc                 C   s   |  |}|S r'   r   )r>   r   ZstrokeDashOffsetr,   r,   r-   convertDashOffset  s    
z+Svg2RlgAttributeConverter.convertDashOffsetr&   c                 C   s~   |sdS |  |}g }|D ]2}| j|||\}}|r>|  S |r|| q|rZ|d S td| d| d|  tS d S )Nry   r   z0Unable to find a suitable font for 'font-family:z
', weight:z, style:)r   r   r%   r   r   r   r    )r>   ZfontAttrZ
weightAttrZ	styleAttrZ
font_namesZnon_exact_matchesr)   exactr,   r,   r-   convertFontFamily  s     
z+Svg2RlgAttributeConverter.convertFontFamily)NN)r&   r&   )rH   rI   rJ   rK   r8   staticmethodr   r   r#   r   r   r   r   r   r   r   r   r   r   rL   r,   r,   rA   r-   r     s    

2!r   c                       s@   e Zd ZdZ fddZdd Zdd Zdd	 Zd
d Z  Z	S )NodeTrackerzAn object wrapper keeping track of arguments to certain method calls.

    Instances wrap an object and store all arguments to one special
    method, getAttribute(name), in a list of unique elements, usedAttrs.
    c                    s   t  j|| g | _d S r'   )r7   r8   	usedAttrs)r>   r?   r@   rA   r,   r-   r8     s    zNodeTracker.__init__c                 C   s   d| j  dS )Nz<NodeTracker for node >)etree_elementre   r,   r,   r-   __repr__  s    zNodeTracker.__repr__c                 C   s&   || j kr| j | | jj|dS Nry   )r   r   r   rz   r{   r>   r   r,   r,   r-   getAttribute  s    
zNodeTracker.getAttributec                 C   s   t | j|S r'   )r   r   r   r,   r,   r-   __getattr__  s    zNodeTracker.__getattr__c              
   C   sj   | | }|D ]H}|d d }| D ].\}}z|| jj|< W q& tk
rR   Y q&X q&q| jdd d S )Nr   r   rv   rx   )matchr}   r   rz   r   set)r>   r]   matchesr   Z	attr_dictrU   r   r,   r,   r-   r|     s    

zNodeTracker.apply_rules)
rH   rI   rJ   rK   r8   r   r   r   r|   rL   r,   r,   rA   r-   r     s   r   c                   @   s   e Zd ZdS )CircularRefErrorN)rH   rI   rJ   r,   r,   r,   r-   r     s   r   c                   @   s   e Zd Zdd Zdd ZdS )ExternalSVGc                 C   s,   t || _t||j|jg d| _d| _d S )N)parent_svgsF)load_svg_file	root_nodeSvgRenderer_parent_chainsource_pathrendererrendered)r>   pathr   r,   r,   r-   r8     s    
 zExternalSVG.__init__c                 C   s(   | j s| j| j d| _ | jj|S )NT)r   r   renderr   definitionsr{   )r>   fragmentr,   r,   r-   get_fragment  s    zExternalSVG.get_fragmentN)rH   rI   rJ   r8   r   r,   r,   r,   r-   r     s   r   c                   @   s   e Zd ZdZd$ddZdd Zd%ddZd	d
 Zdd Zdd Z	d&ddZ
dd Zdd Zd'ddZd(ddZd)ddZdd Zdd Zd d! Zd*d"d#ZdS )+r   zRenderer that renders an SVG file on a ReportLab Drawing instance.

    This is the base class for walking over an SVG DOM document and
    transforming it into a ReportLab Drawing instance.
    Nc                 C   s\   || _ |pg | _t||d| _t|| j| _| j | _i | _t	t
| _i | _t | j_d S )N)r   r   )r   r   r   attrConverterSvg2RlgShapeConvertershape_converterget_handled_shapeshandled_shapesr   r   listwaiting_use_nodes_external_svgsrO   rc   )r>   r   r   r   r   r,   r,   r-   r8     s    
 
zSvgRenderer.__init__c           	      C   s   t |}| j|dd}| j| | j|dd}| j D ]}t	d| q<|
d|j |j |j  | jj|dd|j|jfd\}}t||}|| |S )	NTdefault_box)	outermostz(Ignoring unavailable object width ID %r.r   r2   r3   defaults)r   from_xml_rootget_boxr   rf   	renderSvgr  keysr   debug	translater0   r3   r1   r   convert_length_attrsr2   r
   add)	r>   svg_nodenodeview_boxZ
main_groupZxlinkr2   r3   drawingr,   r,   r-   r     s     
   



zSvgRenderer.renderc                 C   s  | d}d}d }t|}| |}|dkrD| |}|| n|dkrTd}n|dkrt| |}|| nz|dkr| d}| j||d	}|d
kr|| nD|dkr| | n.|dkr| |}|j	
dr|| n|dd n|dkr| j||d	}|| n|dkr2| |}n|| jkr|dkr| |}	|	d kr`d S t|	trt }
|	\}}|j||
d | ||
 ||
 d S |	|_| j|||}| d}|r|d
kr|| nd}td| |s|rN|rN|| j|< |d|i dd |j	 D }t|dkrN|\}|d|i || j kr| j|}|D ]\}}| j||d qn|  | d S )Nr   FZsvgdefsTri   r   display)clippingr   r+   symbolZ	_renderedrx   useZclipPathimager   zIgnoring node: %sZsvgidc                 S   s   g | ]\}}d |kr|qS )labelr,   )rT   rs   rt   r,   r,   r-   rj   Q  s      z*SvgRenderer.renderNode.<locals>.<listcomp>r   r  group)!r   r   get_clippathr  r  renderArenderGrenderStylerenderSymbolrz   r{   r   	renderUser   xlink_href_target
isinstancer   r   
renderNodeapply_node_attr_to_group_resolved_targetr   convertShaper   r  r   ZsetPropertiesr}   rl   r  r  r6   print_unused_attributes)r>   r  r   Znidignoreditemr   r  r  targetgrr   Zimg_nodeZlabel_attrsr  Z	to_renderZuse_noder  r,   r,   r-   r'    s|    













zSvgRenderer.renderNodec                    s
   fdd  fdd| d}|s.dS td|}|sBdS | d }|jkrhtd	| dS j| }t|tr|	 \}}}}	t
 }
|
|| |
|| |
||	 |
||	 |
  t||
 |
S t|trt
|d
S |rtd|jj dS )zo
        Return the clipping Path object referenced by the node 'clip-path'
        attribute, if any.
        c                    s8   | j D ],}t|tr  |  S t|tr|  S qd S r'   )contentsr&  r   r   )r  elem)get_shape_from_groupr,   r-   r2  `  s
    


z6SvgRenderer.get_clippath.<locals>.get_shape_from_groupc                    s   |   D ]v}t|dkr4jd|}|jd   S t|dkrV|} |  S t|dkrrj|  S |  S qd S )Nr   r   r  Zrect)iter_childrenr   r   r*  r0  r$  convertRect)r  childr  grpr2  get_shape_from_noder>   r,   r-   r8  g  s    
z5SvgRenderer.get_clippath.<locals>.get_shape_from_nodez	clip-pathNzurl\(#([^\)]*)\)r   z)Unable to find a clipping path with id %sr5   z&Unsupported shape type %s for clipping)r   r   r   groupsr   r   r   r&  r   Z	getBoundsrM   moveTolineTo	closePathcopy_shape_propertiesr   loggingr   rB   rH   )r>   r  Z	clip_pathmrefshaper   r   r   r   Zcpr,   r7  r-   r  [  s6    





zSvgRenderer.get_clippathc                    sN   t jtjkrd S | j j } fdd|D }|rJt dt	 | d S )Nc                    s   g | ]}| j kr|qS r,   )r   rS   r  r,   r-   rj     s     
 z7SvgRenderer.print_unused_attributes.<locals>.<listcomp>zUnused attrs: %s %s)
r   levelr?  DEBUGr   r   r   r  r  r   )r>   r  Z	all_attrsZunused_attrsr,   rC  r-   r+    s    z#SvgRenderer.print_unused_attributesc                 C   sR   |j }t|d\}}}|s|r<|d|p(d d|p2d d7 }|rN| j|| d S )N)	transformr0   r1   z translate(r   z, ))r   mapr   applyTransformOnGroup)r>   r  r  getAttrrF  r0   r1   r,   r,   r-   r(    s    z$SvgRenderer.apply_node_attr_to_groupc              	   C   sB  |j dp|j d}|s dS td|}|r| d }t||dd d d d}t	j
d| d	\}}t|d
}	|	| W 5 Q R X t| |S d|kr|dd\}
}n
|d }
}|
r0t| jtstd|
 dS tjtjtj| j|
}t|tjs dS || jkr0d}
|
r|dr|| jkr^td t || jkrzt|| | j|< | j| }|j dk	r|r|!|}|dk	r|j"|fS n|j"t#$|j fS n:zt%|dd W n$ t&k
r   td| Y dS X |S n8|r>|| j'kr&| | j'| fS | j(| )||f t*S dS )a  
        Return either:
            - a tuple (renderer, node) when the the xlink:href attribute targets
              a vector file or node
            - the path to an image file for any raster image targets
            - None if any problem occurs
        z"{http://www.w3.org/1999/xlink}hrefZhrefNz^data:image/(jpe?g|png);base64r   r   ascii.)suffixwbr   zLUnable to resolve image path %r as the SVG source is not a file system path.z.svgz$Circular reference detected in file.z(Unable to read the image %s. Skipping...)+rz   r{   r   r   r:  base64decodebytesspanencodetempfilemkstempopenwriteoscloserQ   r&  r   strr   r   r   normpathjoindirnameaccessR_OKr   r   r   r  r   r   r   r   r   r	  r   OSErrorr   r  r   DELAYED)r>   r  r  Z
xlink_hrefr   Z
img_formatZ
image_dataZfile_indicatorr   ZfhZirir   Zext_svgZext_fragr,   r,   r-   r%    sh    	&

 



zSvgRenderer.xlink_href_targetc                 C   s   d S r'   r,   r>   r  r,   r,   r-   renderTitle_  s    zSvgRenderer.renderTitle_c                 C   s   d S r'   r,   ra  r,   r,   r-   renderDesc_  s    zSvgRenderer.renderDesc_Fc                 C   s^   | d}|r"| j|}t| S |rZt|j d\}}t| jj||f\}}tdd||S d S )NZviewBox)r2   r3   r   )r   r   r   r/   rH  r   )r>   r  r  r  r2   r3   r,   r,   r-   r
    s    
zSvgRenderer.get_boxc                 C   s  | j j}|dt ddk| j _| j|dd}| jj}|rH| j| |j	d }|
 D ](}|j|rtd| dndkr\| | q\t }| D ]}	| |	| q|| j _| j| |s| j |dd	\}
}|
s|r||
pd
|pd
 |s|r|dd n|rd\}}| j j|dddd\}}|d k	rN|j|krN||j }|d k	rn|j|krn||j }||||rdnd  |S )N{}spacepreserveTr  z}defsr  r0   r1   r   r   r   )r   r   r2   r3   )NNr  )r   preserve_spacer   XML_NSr
  r   rd   rf   Znsmapr{   Ziter_subtreetagr!  r   r3  r'  r  r  scaler3   r2   )r>   r  r  Z_saved_preserve_spacer  Z
_saved_boxZsvg_nsZdef_noder  r5  r0   r1   Zx_scaleZy_scaler2   r3   r,   r,   r-   r    sF       


zSvgRenderer.renderSvgc                 C   sZ   |j }t|d\}}t }|r(|| | D ]}| j||d q0|rV| j|| |S )N)r   rF  r  )r   rH  r   r  r3  r'  r   rI  )r>   r  r  rJ  r   rF  r/  r5  r,   r,   r-   r!  2  s    
zSvgRenderer.renderGc                 C   s   | j j|jpd d S r   )r   rc   ra   r   ra  r,   r,   r-   r"  @  s    zSvgRenderer.renderStylec                 C   s
   |  |S r'   r!  ra  r,   r,   r-   r#  C  s    zSvgRenderer.renderSymbolc                 C   s
   |  |S r'   rk  ra  r,   r,   r-   r   F  s    zSvgRenderer.renderAc                 C   s   |d krt  }z| j||d}W n( tk
rH   |jj|j | Y S X |d krVd S t|trnt	d d S |t
krz|S |d }|r|| t| dkr|t| | jt| d |d | || |S )Nr  z/<use> nodes cannot reference bitmap image filesr   r   r   r  )r   r%  r   r   r   remover&  rY  r   r   r`  r  rl   getchildrenr   r;   r<   r'  r  r3  r(  )r>   r  r  r  r-  r,   r,   r-   r$  K  s,    



zSvgRenderer.renderUse)NNN)N)N)F)F)N)NN)rH   rI   rJ   rK   r8   r   r'  r  r+  r(  r%  rb  rc  r
  r  r!  r"  r#  r   r$  r,   r,   r,   r-   r     s"   

P7
S


+
r   c                   @   s&   e Zd ZdZdddZedd ZdS )SvgShapeConvertera;  An abstract SVG shape converter.

    Implement subclasses with methods named 'convertX(node)', where
    'X' should be the capitalised name of an SVG node element for
    shapes, like 'Rect', 'Circle', 'Line', etc.

    Each of these methods should return a shape object appropriate
    for the target format.
    Nc                 C   s   |pt  | _|| _d| _d S )NF)r   r   Zsvg_source_filerg  )r>   r   r   r,   r,   r-   r8   r  s    zSvgShapeConverter.__init__c                 C   s   dd t | D S )ztDynamically determine a list of handled shape elements based on
           convert<shape> method existence.
        c                 S   s&   g | ]}| d r|dd  qS )convertr   N)r~   lower)rT   r   r,   r,   r-   rj   |  s     
 z8SvgShapeConverter.get_handled_shapes.<locals>.<listcomp>)dir)clsr,   r,   r-   r   w  s    z$SvgShapeConverter.get_handled_shapes)N)rH   rI   rJ   rK   r8   classmethodr   r,   r,   r,   r-   rn  h  s   	
rn  c                   @   s   e Zd ZdZdddZe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d Zdd Zdd Zd ddZdS )!r   z=Converter from SVG shapes to RLG (ReportLab Graphics) shapes.Nc                 C   s   d|   }t| ||}|s$d S |dkr8| || |d}|sN|sN|S t }|rd| || |rr|| || |S d S )Nro  )r   polyliner   rF  )
capitalizer   applyStyleOnShaper   r   rI  r  )r>   r   r  r  method_namerB  rF  r  r,   r,   r-   r*    s     


z"Svg2RlgShapeConverter.convertShaper   c                   sT   t drjn
fdd| jj |ddt| } fddt||D S )Nr   c                    s    j | dS r   )rz   r{   r   rC  r,   r-   rm     rn   z<Svg2RlgShapeConverter.convert_length_attrs.<locals>.<lambda>r  )r   c                    s$   g | ]\}} |||d qS ))r   r   r   r,   )rT   rU   r   )
convLengthr   rJ  r,   r-   rj     s   z>Svg2RlgShapeConverter.convert_length_attrs.<locals>.<listcomp>)hasattrr   r   r   r{   rl   zip)r>   r  r   rr   r@   r  r,   )ry  r   rJ  r  r-   r    s    
z*Svg2RlgShapeConverter.convert_length_attrsc                 C   s"   |  |dddd}t| t| S )Nr   r   r   r   )r  nudge_pointsr   )r>   r  pointsr,   r,   r-   convertLine  s    z!Svg2RlgShapeConverter.convertLinec              	   C   sx   |  |dddddd\}}}}}}||d kr6|d }||d krJ|d }|rX|sX|}n|rd|sd|}t||||||dS )	Nr0   r1   r2   r3   rxryr   )r  r  )r  r   )r>   r  r0   r1   r2   r3   r  r  r,   r,   r-   r4    s$          z!Svg2RlgShapeConverter.convertRectc                 C   s"   |  |ddd\}}}t|||S )Nr   r   r)r  r	   )r>   r  r   r   r  r,   r,   r-   convertCircle  s    z#Svg2RlgShapeConverter.convertCirclec                 C   s2   |  |dddd\}}}}|| }}t||||S )Nr   r   r  r  )r  r   )r>   r  r   r   r  r  r2   r3   r,   r,   r-   convertEllipse  s    
z$Svg2RlgShapeConverter.convertEllipsec                 C   s   | d}|dd}| }tt| jj|}t|d dksLt|dkrPd S t| t	|}| 
|| | j|ddk}|rt }t|}| 
|| d |_|| || |S |S )Nr}  r   r   r   r   fill)ry   r   )r   r   rQ   r  rH  r   r   rl   r|  r   rv  r   r   r   rD   r  )r>   r  r}  rt  Zhas_fillr  Zpolygonr,   r,   r-   convertPolyline  s&    


z%Svg2RlgShapeConverter.convertPolylinec                 C   sd   | d}|dd}| }tt| jj|}t|d dksLt|dkrPd S t| t	|}|S )Nr}  r   r   r   r   )
r   r   rQ   r  rH  r   r   rl   r|  r   )r>   r  r}  rB  r,   r,   r-   convertPolygon  s    
z$Svg2RlgShapeConverter.convertPolygonc           (   	   C   s  | j }|dt d}|r&|dk}n| j}t }g }d\}}d\}	}
||dpTt}||dpdt}||dptt}|	|||}||dpt
t}||}| j|d	d
|d\}}t||D ]\}}}|sqd\}}d\}}d}|sj| j|d	d
dd|d\}	}
}}|jd	ddk|jd
ddk }}|t|trH|d n| }|t|trd|d n| }|jdd}|dkr| d |d dd| }n|j||d}|t||| tdd |	|
||fD rV|rt|	tr|	n|	g}n|| t|d d  g}|r0t|
tr(|
n|
g}n
|| g}t|trJ|n|g}t|tr`|n|g}|d |d d  }}}t|||||D ]\} }!}"}#}$|$d kr q|"d krd}"|#d krd}#|"| d kr|t||| n|  }%|#|!d kr|n|! }&t|%|&|  |$}'| |'| t|dkr:| |'| ||' |%}|&}|$}qq|rd|	| n|| t|d d  }%|r|
| n|| }&t|%|&|  |}'| |'| t|dkr| |'| ||' q|dd |S )Nrd  re  rf  )r   r   font-familyfont-weight
font-style	font-sizer0   r1   rx  )FFr   dxdyry   zbaseline-shift0)r   r7   Zbaseliner   c                 s   s   | ]}t |tV  qd S r'   )r&  r  r   r,   r,   r-   r     s     z4Svg2RlgShapeConverter.convertText.<locals>.<genexpr>r   Ztspanr   )r   r   rh  rg  r   r   r    r!   r"   r   rY  r#   r   r  iter_text_noderz   r{   r&  r  r   r   anysum	itertoolszip_longestr   rv  r   r  rj  )(r>   r  ZattrConvZ	xml_spacerg  r/  Zfrag_lengthsZdx0Zdy0r   r   ZfffwZfstylefsr0   r1   subnoder   Zis_tailZhas_xZhas_yr  r  ZbaseLineShiftZxlistZylistZdxlistZdylistZlast_xZlast_yZ	last_charZchar_xZchar_yZchar_dxZchar_dycharZnew_xZnew_yrB  r,   r,   r-   convertText  s    

&

    




&z!Svg2RlgShapeConverter.convertTextc           $      C   s  | d}|sd S t|}t }|j}g }g }d}d }	tdt|dD ]}
||
|
d  \}}|dkr|
dkr|jd tkr|t|j |dkr|j	|  |dd  }n^|d	kr|j
|  nH|d
krBt|dkr(|dkr|}n|dd  }|d |d  |d |d   }}|	|| n
|j	|  |dd  }n|dkr~|d |d  |d |d   }}|
|| n|dkr|
|d |d  nn|dkr|
|d |d  nL|dkr|
|d |d  |d  n"|dkr|
|d |d |d   n|dkr.|j|  n|dkr|\}}}}t|dk s\|dkrv|dd  d \}}}}n|dd  \}}}}|||  |||   }}||||||| nR|dkr|dd  \}}|\}}}}}}||| || || || || ||  n|dkr|\}}}}t|dk sD|dkr^|dd  d \}}}}n|dd  \}}}}|||  |||   }}||||| || || ||  nZ|dkr*|dd  \}}|\}}}}||f}	t||f||f||f\\}}\}}\}}\}}||||||| n|dkr|	d k	rH|	\}}n|dd  \}}|dd  \}}|||  |||   }}||f}	|\}}t||f||f||f\\}}\}}\}}\}}||||||| n4|dkrt|dd  \}}|\}}}}|| || || || f\}}}}||f}	t||f||f||f\\}}\}}\}}\}}||||||| n|dkr4|	d k	r|	\}}n|dd  \}}|dd  \}}|\}}|| ||  }}|||  |||   }}||f}	t||f||f||f\\}}\}}\}}\}}||||||| n|dkr|\}}}}}}}|dd  \}}|dkrz||7 }||7 }t|dkst|dkr|
|| nHt|||||||||	}|D ]*\} } }}}}}}||||||| qn |dkr|  ntd | |d!krd }	|}qFt }!| || |jd tkrT|t|j |r|jd k	rt|d"}"t|D ]}#|"j|#t qx|!|" d |_|!| |!S )#Nr   ry   r   r   )r@  Mr   r  r   Lr@  )Zzr   lHVhrt   CSr   >   r  r   ro   r  r   ro   QTqt)Ari   ri   g|=zSuspicious path operator: %s)r  r  r  r  r9  )r{   r   r   r}  r   rl   Z	operatorsr   r   r;  r<  ZcurveTor   absr   r=  r   r  r   rv  rN   r4   reversedinsertr  )$r>   r  r   ZnormPathr   r}  Zunclosed_subpath_pointersZsubpath_startZlastopZlast_quadratic_cpr   r   numsZstarting_pointZxnZynr   r   xpZypZx0Zy0xiyir   r   r  r  phiZfAZfSZbp_r/  Zclosed_pathpointerr,   r,   r-   convertPath>  s    


"

"


 
 


0
(




$










z!Svg2RlgShapeConverter.convertPathc                 C   s   t std d S | |dddd\}}}}|j}tt|t|| t|t||}t|}|d|| d  |	dd	 |S )
NzFUnable to handle embedded images. Maybe the pillow library is missing?r0   r1   r2   r3   r   r   r   r   )
r   r   r   r  r)  r   intr   r  rj  )r>   r  r0   r1   r2   r3   r  r  r,   r,   r-   convertImage  s    $z"Svg2RlgShapeConverter.convertImagec           	      C   s:  | j |}|D ]"\}}|dkr@t|ts4||f}|j|  q|dkrjt|ttfr^|df}|j|  q|dkrt|trt|dkr|	| n<t|dkr|\}}}||| |	| || |  q|dkr|
|d q|dkr|
d| q|d	kr&t|d
kr&t|j||_qtd|| qdS )a6  Apply an SVG transformation to a RL Group shape.

        The transformation is the value of an SVG transform attribute
        like transform="scale(1, -1) translate(10, 30)".

        rotate(<angle> [<cx> <cy>]) is equivalent to:
          translate(<cx> <cy>) rotate(<angle>) translate(-<cx> -<cy>)
        rj  r  r   rotater   r   ZskewXZskewYZmatrix   zIgnoring transform: %s %sN)r   r   r&  r   rj  r  r   r  rl   r  Zskewr   rF  r   r  )	r>   rF  r  trr   valuesZangler   r   r,   r,   r-   rI    s2    



z+Svg2RlgShapeConverter.applyTransformOnGroupFc                 C   s  dgdddgfdgdddgfd	gd
ddgfdgdddgfdgdddgfdgdddgfdgdddgfdgdddgfdgdddgff	}d d!d"gd#d$t ttgfd%gd&dttgfd'gd(d)d*gff}|jtkr|jD ]}| j|||d+ qd,S | j	}||fD ]t}|jt
kr||krq|D ]P\}	}
}}g }t|	D ]\}}|||}|d-kr|rXq0|dkrt|dd,d,k	rt|jd.ddkr|jj}nB|dkrt|dd,d,k	rt|jd.ddkr|jj}n|| }|d/kr||jd0p|| }t|tr|d1d- }|| q0zt||}t||
||  W n& tttfk
rd   td2 Y nX qqt|dd,d,k	r|jr|j|j_t|dd,d3krd,|_d,S )4z
        Apply styles from an SVG element to an RLG shape.
        If only_explicit is True, only attributes really present are applied.
        r  rN   r   Zblackzfill-opacityfillOpacityr   r   z	fill-rule	_fillRuler   r   ZstrokerD   r   zstroke-widthrC   r   rx   zstroke-opacityZstrokeOpacityzstroke-linejoinZstrokeLineJoinr   r  zstroke-linecapZstrokeLineCapr   zstroke-dasharrayr   r   r  r  r  ZfontNamer   r  ZfontSizeztext-anchorZ
textAnchorr   start)only_explicitNry   alphar   r   z
!importantz"Exception during applyStyleOnShaper   )r    r!   r"   rY  r#   rB   r   r0  rv  r   r   r   r   r   rN   r  rD   r   r&  r   rR   r   setattrr   KeyErrorr   r   r  r  )r>   rB  r  r  ZmappingNZmappingFZsubshapeZacmappingZsvgAttrNamesZrlgAttrfuncr  ZsvgAttrValuesindexZsvgAttrNameZsvgAttrValuemethr,   r,   r-   rv    s|     








z'Svg2RlgShapeConverter.applyStyleOnShape)N)F)rH   rI   rJ   rK   r*  r#   r  r~  r4  r  r  r  r  r  r  r  rI  rv  r,   r,   r,   r-   r     s   
V +&r   Fc           	   
   K   s   t | tjrt| } d}t | trtj| d  dkrt	| d0}t	| dd d}t
|| W 5 Q R X W 5 Q R X | dd } d}t| |d	}|dkrdS t| f|}||}|rt|  |S )
z
    Convert an SVG file to an RLG Drawing object.
    `path` can be a file, a file-like, or a file path as str or pathlib.Path.
    Fr   z.svgzrbNr   rN  T)resolve_entities)r&  pathlibr   rY  rW  r   splitextrp  gziprU  shutilcopyfileobjr   r   r   rl  )	r   r  r@   ZunzippedZf_inZf_outsvg_rootZsvgRendererr  r,   r,   r-   svg2rlgr  s     "" 

r  c                 C   sv   | sdS t | dk rdS | d }| d }tdt | d dD ]$}|| | ks\|| |d  kr< qrq<| d  d9  < dS )z Nudge first coordinate if all coordinate pairs are identical.

    This works around reportlab's decision to hide shapes of size zero, even
    when the stroke should be visible.
    Nr   r   r   r   g  ?)rl   r   )r}  r0   r1   r   r,   r,   r-   r|    s    r|  c              
   C   sb   t jdd|d}zt j| |d}| }W n. tk
rX } ztd| W 5 d }~X Y nX |S d S )NT)Zremove_commentsZrecoverr  )parserzFailed to load input file! (%s))r   Z	XMLParserparseZgetroot	Exceptionr   r   )r   r  r  docr  excr,   r,   r-   r     s      r   c                 C   s,   z| j dd W S  tk
r&   Y nX dS )z3Return lxml node name without the namespace prefix.}r   N)ri  rQ   r   rC  r,   r,   r-   r     s    r   c                 c   s   |dk}| j r0t| j |||o*t|  dkdnd}| |dfV  |  D ]}t|||d dE dH  qH|dkr|dko|  dk}| jrt| j||dnd}|dkr| j|d	fV  dS )
zW
    Recursively iterate through text node and its children, including node tails.
    r   )strip_start	strip_endNFr   )rD  )r  r   T)	r   
clean_textrl   rm  r3  r  Zgetnexttailr   )r  rg  rD  Zlevel0r   r5  r  r  r,   r,   r-   r    s$       r  c                 C   s^   | dkrdS |  dd dd dd} |sZ|r8|  } |rD|  } d| krZ|  dd} qD| S )zCText cleaning as per https://www.w3.org/TR/SVG/text.html#WhiteSpaceNz
r   
	z  )r   lstriprstrip)r   rg  r  r  r,   r,   r-   r    s    r  c              	   C   s@   |    D ].\}}zt||| W q tk
r8   Y qX qd S r'   )rE   r}   r  r   )Zsource_shapeZ
dest_shapepropr   r,   r,   r-   r>    s
    r>  c                     sL   ddl m}  ddlm} |jfdd}||_| j  fdd}|| _dS )	z
    https://bitbucket.org/rptlab/reportlab/issues/95/
    ReportLab always use 'Even-Odd' filling mode for paths, this patch forces
    RL to honor the path fill rule mode (possibly 'Non-Zero Winding') instead.
    r   )Canvas)shapesc                    s6   z| j |d j_W n tk
r&   Y nX  | |f|S rk   )r  __self__fillModer   )r   Z	drawFuncsr@   )original_renderPathr,   r-   patchedRenderPath  s
    z0monkeypatch_reportlab.<locals>.patchedRenderPathc                    s8   | j }t|dr|j| _ nt| _  | |f| || _ d S )Nr  )Z	_fillModerz  r  r   )r>   r   r@   current)original_drawPathr,   r-   patchedDrawPath  s    

z.monkeypatch_reportlab.<locals>.patchedDrawPathN)reportlab.pdfgen.canvasr  Zreportlab.graphicsr  Z_renderPathZdrawPath)r  r  r  r  r,   )r  r  r-   monkeypatch_reportlab  s    r  )Nr&   r&   N)r&   r&   )F)F)r   )FF)drK   rO  r;   r  r  r?  rW  r  r   rS  r   r  collectionsr   r   Zreportlab.pdfbase.pdfmetricsr   r  r   r   Zreportlab.pdfgen.pdfimagesr   Zreportlab.graphics.shapesr   r	   r
   r   r   r   r   r   r   r   r   r   r   Zreportlab.libr   Zreportlab.lib.unitsr   r   Zreportlab.lib.utilsr   Zreportlab.graphics.transformr   ImportErrorZlxmlr   rZ   rX   utilsr   r   r   Zfontsr   r    r!   r"   r#   r$   r(   r%   r.   __version____license__
__author____date__rh  objectr`  	getLoggerrH   r   r/   compilefindallZsplit_whitespacer4   rM   MatcherrO   rb   r   ZElementWrapperr   r  r   r   r   rn  r   r  r|  r   r   r  r  r>  r  r,   r,   r,   r-   <module>   s   <


| &      v
 
	

"