
    i92i                     8   S r SSKrSSKrSSKrSSKrSSKJr  SSKJr  SSK	J
r
JrJr  SSKJr  SSKJr   SS	KJr  SSKJr  SSKJrJrJr  SSKJrJrJ r J!r!J"r"J#r#J$r$  SSK%J&r&J'r'  SSK(J)r)  \RT                  " \+5      r,SS0r-S r.SSS.r/\R`                  " S5      r1\R`                  " S5      r2\R`                  " S\Rf                  5      r4\R`                  " S5      r5S r6\. " S S\75      5       r8\R`                  " S5      r91 Skr:SS S!SS"S#S$S%.r;\Rx                  S&-  \Rx                  S'-  S\Rx                  S(.r=\.SbS) j5       r>\.ScS* j5       r?\.S+ 5       r@\.S, 5       rA\.S- 5       rB\A" S.S/S0S1S2S3S45      rC\.S5 5       rD\.S6 5       rE\.S7 5       rF\.S8 5       rG\.S9 4S: j5       rH\.S; 4S< j5       rIS= S> S? S@ SA SB SC SD SE SF SG SH.rJ\.SdSI j5       rKSJ\LSK\M4SL jrNSSM.SN\OSO\MSK\O4SP jjrPSQ\OSR\OSK\O4SS jrQ SdST\OSJ\\L   SK\\O   4SU jjrR SdSJ\\L   SK\\\O   \O\\7   \O4   4SV jjrS  SeSJ\\L   SW\\7   SK\\7\7\7\74   4SX jjrTSY rU\. " SZ S[5      5       rV\.S\ 5       rW\.S] 5       rX " S^ S_5      rY " S` Sa\
5      rZg! \ a    \R*                  " S
5        SS	KJr   GN\f = f)faA  
Utilities to parse SVG graphics into fpdf.drawing objects.

The contents of this module are internal to fpdf2, and not part of the public API.
They may change at any time without prior warning or any deprecation period,
in non-backward-compatible ways.

Usage documentation at: <https://py-pdf.github.io/fpdf2/SVG.html>
    N)deepcopy)Number)
NamedTupleOptionalTuple)
parse_path   )PathPaintRule)
fromstringzYdefusedxml could not be imported - fpdf2 will not be able to sanitize SVG images provided)html)color_from_hex_stringcolor_from_rgb_string	Transform)GraphicsContextGraphicsStylePaintedPathPathPenClippingPathTextTextRun)
ImageCacheVectorImageInfo)stream_content_for_raster_imageforce_nodocumentFc                 ,    S[         U R                  '   U $ )zQA decorator that forces pdoc not to document the decorated item (class or method)F)__pdoc____qualname__)items    B/home/james-whalen/.local/lib/python3.13/site-packages/fpdf/svg.pyr   r   1   s    "'HTK    zhttp://www.w3.org/2000/svgzhttp://www.w3.org/1999/xlink)svgxlinkz(?:\s+,\s+|\s+,|,\s+|\s+|,)zf(matrix|rotate|scale|scaleX|scaleY|skew|skewX|skewY|translate|translateX|translateY)\(([\d\.,\s+-]+)\)z	/\*.*?\*/z(?s)([^{}]+)\{([^{}]*)\}c                 l    U c  g [        U [        5      (       a  U R                  5       nU(       d  g U$ U $ N)
isinstancestrstrip)valuestrippeds     r   _normalize_css_valuer*   G   s2    }%;;=Lr    c                       \ rS rSrSrSrg)PercentR   z$class to represent percentage values N)__name__
__module__r   __firstlineno____doc____static_attributes__r.   r    r   r,   r,   R   s    .r    r,   z2\s*(?P<value>[-+]?[\d\.]+)\s*(?P<unit>%|[a-zA-Z]*)>   %chemexiclhvbvhvivwcapremrlhvmaxvminH   gbX<@gjZ@   g      ?gjZ?)incmmmptpcpxQih  i  )deggradradturnc                 (   [         R                  U 5      nUc  [        SU  S35      SeUR                  5       u  p4U(       d  Un [	        U5      [
        U   -  $ ! [         a-    U[        ;   a  [        U  SU 35      Se[        U  SU 35      Sef = f)z7Convert a length unit to our canonical length unit, pt.NzUnable to parse 'z' as a lengthz" uses unsupported relative length z contains unrecognized unit )unit_splittermatch
ValueErrorgroupsfloatabsolute_length_unitsKeyErrorrelative_length_units)
length_strdefault_unitrR   r(   units        r   resolve_lengthr\      s     
+E},ZLFGTQ,,.KEVU|3D999 V((,@G J<'CD6JKQUUVs   A 7Bc                     [         R                  U 5      R                  5       u  p#U(       d  Un [        U5      [        U   -  $ ! [
         a    [        SU  SU 35      Sef = f)z;Convert an angle value to our canonical angle unit, radianszangle z has unknown unit N)rQ   rR   rT   rU   angle_unitsrW   rS   )	angle_strrZ   r(   r[   s       r   resolve_angler`      sm      %%i0779KEQU|k$/// Q6),>tfEFDPQs   A A"c                 N     S[         U     S3n U  U 3$ ! [         a    Sn  Nf = f)zECreate an XML namespace string representation for the given tag name.{} )_HANDY_NAMESPACESrW   )spacenames     r   xmlnsrh      sC    &u-.b1 WTF  s    $$c                 >    0 nU H  nX2[        X5      '   X2U'   M     U$ )z>Create a lookup for the given name in the given XML namespace.)rh   )rf   namesresultrg   s       r   xmlns_lookuprl      s.     F%)uU!"t  Mr    c                 B    U R                  S5      nUS:  a  XS-   S $ U $ )z8Remove the xmlns namespace from a qualified XML tag namerc   r   r	   N)index)qualified_tagis     r   
without_nsrq      s0     	C AAvUW%%r    r!   rectcircleellipselinepolylinepolygonc                      [         R                  U    n U R                  S5      (       a  [	        U 5      $ U R                  S5      (       a  [        U 5      $ [        SU  35      e! [         a     N\f = f)N#rgbz unsupported color specification )r   
COLOR_DICTrW   
startswithr   r   rS   colorstrs    r   svgcolorr      sv    ??8, 3$X..5!!$X..
7zB
CC  s   A% %
A21A2c                 T    [        U 5      nUS:  a  [        SU  S35      eUS:X  a  g U$ )Nr   zstroke width z cannot be negative)r\   rS   incomingvals     r   convert_stroke_widthr      s7    

"C
Qw=
2EFGG
axJr    c                 F    [        U 5      nUS:  a  [        SU  S35      eU$ )N      ?zmiter limit z cannot be less than 1)rU   rS   r   s     r   convert_miterlimitr      s,    
/C
Sy<z1GHIIJr    c                    ^ ^ UU 4S jnU$ )Nc                 >   > [        U 5      nUT:  a  T$ UT:  a  T$ U$ r$   rU   )r(   r   max_valmin_vals     r   	converterclamp_float.<locals>.converter   s)    El=N=N
r    r.   )r   r   r   s   `` r   clamp_floatr      s     r    c                     U $ r$   r.   )r(   s    r   <lambda>r      s    ur    c                 >    U S;   a  [         R                  $ U" U 5      $ )N)inheritcurrentColor)r   INHERITr(   r   s     r   inheritabler      s"    ++$$$Ur    c                     U $ r$   r.   )noops    r   r   r     s    4r    c                     U c  g [        U [        5      (       a  U R                  5       (       d  g U S:X  a  g [        X5      $ )Nnone)r%   r&   r'   r   r   s     r   optionalr     s;     }%ekkmmu((r    c                 &    S[        U [        5      4$ )N
fill_colorr   r   r}   s    r   r   r     s    lHXx,HIr    c                     S[        U 5      4$ )Nintersection_ruler   )fillrulestrs    r   r   r     s    &9;{;S%Tr    c                 2    S[        U [        SS5      5      4$ )Nfill_opacity        r   r   r   )filopstrs    r   r   r     s    Hk#s34&r    c                 &    S[        U [        5      4$ )Nstroke_colorr   r}   s    r   r   r   !  s    80LMr    c                 &    S[        U [        5      4$ )Nstroke_width)r   r   )valuestrs    r   r   r   #  s    H23&r    c                      S[        U S 5      4$ )Nstroke_dash_patternc                 z    [         R                  U 5       Vs/ s H  o(       d  M  [        U5      PM     sn$ s  snf r$   )NUMBER_SPLITsplitrU   )dar   s     r   r   <lambda>.<locals>.<lambda>,  s+    0B0B20FO0F$d0FOOs   
88)r   )	dasharrays    r   r   r   (  s    O	
+r    c                 &    S[        U [        5      4$ )Nstroke_dash_phase)r   rU   )dashoffs    r   r   r   1  s    GU#*r    c                     S[        U 5      4$ )Nstroke_cap_styler   )capstrs    r   r   r   6  s    &8+f:M%Nr    c                     S[        U 5      4$ )Nstroke_join_styler   )joinstrs    r   r   r   8  s    (;[=Q'Rr    c                 &    S[        U [        5      4$ )Nstroke_miter_limit)r   r   )limstrs    r   r   r   :  s    F./)r    c                 2    S[        U [        SS5      5      4$ )Nstroke_opacityr   r   r   )stropstrs    r   r   r   ?  s    Hk#s34(r    )fillz	fill-rulezfill-opacitystrokezstroke-widthzstroke-dasharrayzstroke-dashoffsetzstroke-linecapzstroke-linejoinzstroke-miterlimitzstroke-opacityc                 .   Ub  UnO]0 n[         R                  " UR                  R                  SS5      5      R	                  5        H  u  pE[        U5      nUc  M  XcU'   M     SU R                  l        [        R	                  5        Hg  u  px[        UR                  U5      5      nUc$  [        UR                  R                  U5      5      nUc  MK  [        U R                  /U" U5      Q76   Mi     [        UR                  S5      5      n	U	c$  [        UR                  R                  S5      5      n	U	b+  [        U	5      n	XR                  l        XR                  l        UR                  R                  S5      n
U
(       a  [        U
5      U l        gg)zKApply the known styles from `svg_element` to the pdf path/group `stylable`.Nstylerd   Fopacity	transform)r   parse_css_styleattribgetitemsr*   r   
auto_closesvg_attr_mapsetattrrU   r   r   convert_transformsr   )stylablesvg_elementcomputed_styler   keyr(   
norm_value	attr_namer   r   tfstrs              r   apply_stylesr   F  s\    !..""7B/

%'JC .e4J%'c
 !&HNN , 2 2 4	$UYYy%9:=(););)?)?	)JKEHNN6Yu%56 !5 #599Y#78G&{'9'9'='=i'HI.&-#(/%"";/E/6 r    	style_mapreturnc                     U R                  S5      =(       d    SR                  5       nUS;   a  gUR                  R                  S5      nUS:H  $ )Nwhite-spacerd   )prezpre-wrapzbreak-spacesTz+{http://www.w3.org/XML/1998/namespace}spacepreserve)r   r'   r   )r   tagws	xml_spaces       r   _preserve_wsr   k  sH    
--
&
,"	3	3	5B	00

LMI
""r    r   sr   c                L    U c  gU(       a  U $ [         R                  " SSU 5      $ )z
Collapse sequences of whitespace characters (spaces, tabs, etc.) to a single space
In some cases, like with `pre` tags, whitespace should be preserved.
rd   z\s+ )resub)r   r   s     r   _collapse_wsr   t  s'    
 	y66&#q!!r    
font_stylefont_weightc                 J   SnSnU(       aO  UR                  5       R                  5       nUS;   =(       d%    UR                  5       =(       a    [        U5      S:  nU (       a#  U R                  5       R                  5       nUS;   nU(       a  U(       a  gU(       a  gU(       a  gg)	NF)boldbolderiX  )italicobliqueBIBIrd   )r'   lowerisdigitint)r   r   brp   fwfss         r   _svg_font_style_to_emphasisr     s    AA &&($$I)H#b'S.%%'''Qr    rg   c                 2   Ub  [        UR                  U5      5      nUb  U$ UcO  [        R                  " U R                  R                  SS5      5      n[        UR                  U5      5      nUb  U$ [        U R                  R                  U5      5      $ )zJReturn the value for a given attribute, honoring computed style overrides.r   rd   )r*   r   r   r   r   )r   rg   r   r(   inlines        r   _get_attr_or_styler     s     $Y]]4%89L%%cjjnnWb&AB$VZZ%56L

t 455r    c                 r   [        U SU5      nU(       a  / nUR                  S5       HM  nUR                  5       R                  SS5      R                  SS5      nU(       d  M<  UR	                  U5        MO     U(       a  SR                  U5      OSnOSn[        U SU5      =(       d    Sn[        U SU5      =(       d    Sn[        Xx5      n	[        U S	U5      n
U
b  [        U
5      OSn[        U S
U5      =(       d    SR                  5       R                  5       nUS;  a  SnXiUb  [        U5      U4$ SU4$ )zUReturns (font_family or None, font_style_emphasis, font_size_pt or None, text_anchor)font-family,"rd   'N
font-stylefont-weight	font-sizetext-anchorstart)r	  middleend)
r   r   r'   replaceappendjoinr   r\   r   rU   )r   r   family_valuecleanedr   r)   familyr   r   emphasisr   size_pttas                r   _parse_font_attrsr    s(    &c=)DL &&s+Dzz|++C4<<S"EHxx( , '.'"4 $CyAGRJ$S-CIrK*:CH 
Ci	8B nr$ 
 S-
;
Fw	M	M	O	U	U	WB	++w/BU7^bPPbPPr    	font_sizec                    ^ ^^ S[         4S[        S[        4UUU 4S jjjnU" SS5      nU" SS5      nU" SS5      nU" SS5      nXEXg4$ )	z0x,y (default 0,0) and optional dx,dy (default 0)r   rg   defaultc                   > S nT
b  U T
;   a  T
U    nOU TR                   ;   a  TR                   U    nU(       d  U$ [        R                  UR                  5       5      nU(       a
  US   (       d  U$ US   n[        R                  U5      nU(       a  UR                  S5      nUR                  S5      =(       d    SR                  5       nUR                  5       S;   a6  T	c$  [        R                  SUTR                  U 5        U$  [        U5      T	-  $ UR                  5       S:X  a8  T	c#  [        R                  STR                  U 5        U$  [        U5      T	-  S	-  $  [        U" U5      5      $ ! [        [        4 a    Us $ f = f! [        [        4 a    Us $ f = f! [         a'    [        R                  S
UTR                  U 5        Us $ f = f)Nr   r(   r[   rd   >   r6   r?   zCIgnoring relative %s length on <%s %s> because font size is unknownr7   zCIgnoring relative ex length on <%s %s> because font size is unknowng      ?z+Ignoring unsupported length '%s' on <%s %s>)r   r   r   r'   rQ   	fullmatchgroupr   LOGGERwarningr   rU   	TypeErrorrS   )rg   r  resolverattrpartstokenrR   	value_strr[   r  r   r   s            r   first_number%_parse_xy_delta.<locals>.first_number  s    TY%6T?DSZZ::d#DN""4::<0E!HNa''.G,IKK'-2446Dzz|},$NN]	 #N# +i77 zz|t#$NN]
 #N# +i7#==		%)) ":. #"N# ":. #"N#  	NN=	 N	s6   E3 F "F# 3FFF F #.GGxydxdy)r\   r&   rU   )r   r   r  r$  r&  r'  r(  r)  s   ```     r   _parse_xy_deltar*    s_     25~ 23 2 2 2h 	S#AS#A	dC	 B	dC	 B<r    c                 p   / nU (       d  U$ [         R                  SU 5      n[        R                  U5       H  u  p4[        R
                  " U5      nU(       d  M$  0 nUR                  5        H  u  px[        U5      n	U	c  M  XU'   M     U(       d  M\  UR                  S5       V
s/ s H  oR                  5       PM     nn
U Hf  n
U
R                  S5      (       d  M  U
SS  R                  SS5      S   R                  5       nU(       d  MJ  UR                  U[        U5      45        Mh     M     U$ s  sn
f )Nrd   r  .r	   :r   )CSS_COMMENT_REr   CSS_BLOCK_REfindallr   r   r   r*   r   r'   r|   r  dict)css_textstylesr  selector_blockbodydeclarations
normalizedr   r(   r   selector	selectors
class_names                r   _extract_css_class_stylesr;  	  s   F  X.G , 4 4W =++D1
&,,.JC-e4J%",3 / 6D6J6J36OP6O(^^%6O	P!H&&s++!!"++C3A6<<>JMM:tJ'789 " !>& M Qs   &D3c                       \ rS rSrSr\SS\4S jj5       r\SS\4S jj5       r	\SS\4S jj5       r
\SS\4S jj5       r\S 5       r\S	 5       r\SS\4S
 jj5       rSrg)ShapeBuilderi%  zNA namespace within which methods for converting basic shapes can be looked up.clipping_pathc                 R    [        5       nU(       a
  [        5       n[        X 5        U$ )z.Create a new path with the appropriate styles.)r   r   r   )r   r>  paths      r   new_pathShapeBuilder.new_path)  s"     }>DTr    c                    [        UR                  R                  SS5      5      n[        UR                  R                  SS5      5      nUR                  R                  SS5      nUR                  S5      (       a  [	        USS 5      nO[        U5      nUR                  R                  SS5      nUR                  S5      (       a  [	        USS 5      nO[        U5      nUR                  R                  S	S
5      nUR                  R                  SS
5      nUS:X  a  SnUS:X  a  SnXxs=:X  a  S
:X  a  O  OS=pxO<US
:X  a  [        U5      =pxO)US
:X  a  [        U5      =pO[        U5      n[        U5      nUS:  d  US:  d  US:  d  US:  a  [        SU 35      eUS:X  d  US:X  a
  [        5       $ XuS-  :  a  US-  nXS-  :  a  US-  nU R                  X5      n	U	R                  X4XVXx5        U	$ )z&Convert an SVG <rect> into a PDF path.r&  0r'  widthr4   Nheightrxautoryr   r   z	bad rect    )
r\   r   r   endswithr,   rU   rS   r   rA  	rectangle)
clsr   r>  r&  r'  rE  rG  rH  rJ  r@  s
             r   rr   ShapeBuilder.rect2  s    3::>>#s343::>>#s34

w,>>#E#2J'E"5)E#.??3VCR[)F#F+FZZ^^D&)ZZ^^D&)<B<BvKB6\BiB6\BiBrBrBAI6A:26rAvy.//QJFaK= B!!B||C/qUB3r    c                    [        UR                  R                  SS5      5      n[        UR                  R                  SS5      5      n[        UR                  S   5      nU R                  X5      nUR	                  X4U5        U$ )z(Convert an SVG <circle> into a PDF path.cxr   cyr)rU   r   r   rA  rs   )rN  r   r>  rQ  rR  rS  r@  s          r   rs   ShapeBuilder.circlec  si     3::>>$*+3::>>$*+#**S/"||C/BAr    c                     [        UR                  R                  SS5      5      n[        UR                  R                  SS5      5      nUR                  R                  SS5      nUR                  R                  SS5      nU R                  X5      nXVs=:X  a  S:X  d  O  US:X  d  US:X  a  U$ US:X  a  [        U5      =pVO)US:X  a  [        U5      =pVO[        U5      n[        U5      nUR	                  X4XV5        U$ )z)Convert an SVG <ellipse> into a PDF path.rQ  r   rR  rH  rI  rJ  )rU   r   r   rA  rt   )rN  r   r>  rQ  rR  rH  rJ  r@  s           r   rt   ShapeBuilder.ellipsen  s     3::>>$*+3::>>$*+ZZ^^D&)ZZ^^D&)||C/B!GqK<BiB6\BiBrBrBRR$r    c                 ,   [        UR                  S   5      n[        UR                  S   5      n[        UR                  S   5      n[        UR                  S   5      nU R                  U5      nUR                  X#5        UR	                  XE5        U$ )z&Convert an SVG <line> into a PDF path.x1y1x2y2)rU   r   rA  move_toline_to)rN  r   rX  rY  rZ  r[  r@  s          r   ru   ShapeBuilder.line  s{     3::d#$3::d#$3::d#$3::d#$||C RRr    c                 b    U R                  U5      nSUR                  S   -   n[        X#5        U$ )z*Convert an SVG <polyline> into a PDF path.MpointsrA  r   svg_path_converter)rN  r   r@  ra  s       r   rv   ShapeBuilder.polyline  s2     ||C szz(++4(r    c                 h    U R                  X5      nSUR                  S   -   S-   n[        X45        U$ )z)Convert an SVG <polygon> into a PDF path.r`  ra  Zrb  )rN  r   r>  r@  ra  s        r   rw   ShapeBuilder.polygon  s7     ||C/szz(++c14(r    r.   N)F)r/   r0   r   r1   r2   staticmethodboolrA  classmethodrr   rs   rt   ru   rv   rw   r3   r.   r    r   r=  r=  %  s    XT   .d . .`      0 
 
     r    r=  c           	      2   [         R                  U 5      n[        R                  " 5       nU GH  u  p4UR	                  5       nUS:X  a;  [        S [        R                  U5       5       5      u  pVpxp[        XVXxX5      U-  nMW  US:X  a  [        R                  U5      tp[        U5      n[        R                  " US9nU(       aL  [        U5      S:X  a+  UR                  [        US   5      [        US   5      5      nO[        SU S	U S
35      eX-  nM  US:X  a  [        R                  U5      n[        U5      S:X  a  [        US   5      n[        US   5      nO-[        U5      S:X  a  [        US   5      =pO[        SU  35      e[        R                  " XS9U-  nGMy  US:X  a$  [        R                  " [        U5      SS9U-  nGM  US:X  a$  [        R                  " S[        U5      S9U-  nGM  US:X  a  [        R                  U5      n[        U5      S:X  a  [        US   5      n[        US   5      nO.[        U5      S:X  a  [        US   5      nSnO[        SU  35      e[        R                  " [         R"                  " U5      [         R"                  " U5      S9U-  nGM  US:X  a8  [        R                  " [         R"                  " [        U5      5      SS9U-  nGM  US:X  a8  [        R                  " S[         R"                  " [        U5      5      S9U-  nGM  US:X  a  [        R                  U5      n[        U5      S:X  a  [%        US   5      n[%        US   5      nO.[        U5      S:X  a  [%        US   5      nSnO[        SU  35      e[        R&                  " UUS9U-  nGM  US:X  a$  [        R&                  " [%        U5      SS9U-  nGM  US:X  d  GM  [        R&                  " S[%        U5      S9U-  nGM     U$ )z8Convert SVG/CSS transform functions into PDF transforms.matrixc              3   8   #    U  H  n[        U5      v   M     g 7fr$   r   ).0ns     r   	<genexpr>%convert_transforms.<locals>.<genexpr>  s     $P7O!U1XX7Os   rotate)thetarK  r   r	   zrotation transform (z) is malformedscalezbad scale transform r&  r'  scaleXscaleYskewzbad skew transform skewXskewY	translatezbad translation transform 
translateX
translateY)TRANSFORM_GETTERr0  r   identityr'   tupler   r   r`   rotationlenaboutrU   rS   scalingshearingmathtanr\   translation)r   parsedr   tf_typeargsar   cdefrs  r  r  sxsyr&  r'  s                     r   r   r     s    %%e,F""$Izz|h$$P|7I7I$7O$PPA!!!a3i?I (..t4ME!%(E ))6H u:?'~~eE!HouU1XOH$-gYav^L  !,I%%d+D4yA~47^47^TaQ.(R #7w!?@@!))B5	AI !))E$K1=	II !))At=	II%%d+D4yA~"47+"47+Ta"47+ #6ug!>??!**TXXb\TXXb\JYVI""TXXmD.A%BaH9T  ""Q$((=3F*GH9T  #%%d+D4yA~"47+"47+Ta"47+ #=eW!EFF!--Q7)CI$!--t0DJYVI$!--^D5IJYVIg  j r    c                 h    [        U 5      n[        X5        UR                  (       d  [        S5      eg )Nz"Path does not start with move item)r   r   first_is_moverS   )pdf_pathsvg_pathpens      r   rc  rc  	  s.    
(
Cx=>> r    c                   :   \ rS rSrSr\SS.S j5       rSS\4S jjr\	S	 5       r
S
 rS r\	S 5       r\	S 5       rSS jr SS jrSS jr\	S 5       r\	S 5       r\	SS j5       r\	S 5       r\	S 5       r\	S 5       r\	SS j5       r\	S 5       r\	SS j5       rSrg) 	SVGObjecti  zM
A representation of an SVG that has been converted to a PDF representation.
zutf-8encodingc                    [        USUS9 nU " UR                  5       /UQ70 UD6sSSS5        $ ! , (       d  f       g= f)a  
Create an `SVGObject` from the contents of the file at `filename`.

Args:
    filename (path-like): the path to a file containing SVG data.
    *args: forwarded directly to the SVGObject initializer. For subclass use.
    encoding (str): optional charset encoding to use when reading the file.
    **kwargs: forwarded directly to the SVGObject initializer. For subclass use.

Returns:
    A converted `SVGObject`.
rS  r  N)openread)rN  filenamer  r  kwargssvgfiles         r   	from_fileSVGObject.from_file  s6     (C(3ww||~777 433s   0
>Nimage_cachec                    X l         0 U l        0 U l        [        U5      nUR                  [        SS5      ;  a  [        SUR                   35      eU R                  U5        U R                  U5        U R                  U5        g )Nr!   zroot tag must be svg, not )
r  cross_referencescss_class_stylesparse_xml_strr   rl   rS   _collect_css_stylesextract_shape_infoconvert_graphics)selfsvg_textr  svg_trees       r   __init__SVGObject.__init__'  sx    & " " !*<<|E5999(,,HII  *)h'r    c                 j    U(       a,  UR                  S5      (       d  SU-   OUnX R                  U'   g g )Nry   )r|   r  )r  r   
referenceds      r   update_xrefSVGObject.update_xref6  s1    #&>>##6#6#)CC)3!!#& r    c                 <   UR                  5        H  nUR                  [        SS5      ;   d  M  SR                  UR	                  5       =(       d    / 5      n[        U5       H2  u  pEU R                  R                  U0 5      nUR                  U5        M4     M     g )Nr!   r   rd   )	iterr   rl   r  itertextr;  r  
setdefaultupdate)r  root_tagnoder2  r:  r6  existings          r   r  SVGObject._collect_css_styles<  su    MMODxx<w77774==?#8b90I(0S,J#44??
BOHOOL1 1T $r    c                    0 nU R                   (       an  UR                  R                  S5      nU(       aL  UR                  5        H8  nU R                   R                  U5      nU(       d  M'  UR	                  U5        M:     [
        R                  " UR                  R                  SS5      5      nUR                  5        H2  u  px[        U5      n	U	b  XU'   M  Xr;   d  M   UR                  US 5        M4     Sn
U
 HN  nXR                  ;   d  M  [        UR                  R                  U5      5      n	U	c  M=  UR                  X5        MP     U$ )Nclassr   rd   )r  r  r  r  r  r   )r  r   r   r   r  r   r   r   r*   popr  )r  r   r   
class_attrr:  class_stylesr   r   r(   r   inheritable_attrsr   s               r   _style_map_forSVGObject._style_map_forD  s   	  0J","2"2"4J#'#8#8#<#<Z#HL#|!((6 #5 %%cjjnnWb&AB ,,.JC-e4J%!+#!c4( )
 &Dzz!1#**..2FG
)((:	 &
 r    c                    UR                  S5      nUR                  S5      nUR                  S5      nUR                  SS5      nUS:X  a  SU l        OSU l        SU l        UbJ  UR                  5         UR	                  S5      (       a  [        USS	 5      U l        O[        U5      U l        SU l        UbJ  UR                  5         UR	                  S5      (       a  [        USS	 5      U l        O[        U5      U l        Uc  SU l        gUR                  5       n[        R                  U5       Vs/ s H  n[        U5      PM     snu  pxpU	S
:  d  U
S
:  a  [        SU 35      eXxX/U l        gs  snf )z&Collect shape info from the given SVG.rE  rG  viewBoxpreserveAspectRatioTr   Nr4   rF  r   z)invalid negative width/height in viewbox )r   preserve_arrE  r'   rL  r,   r\   rG  viewboxr   r   rU   rS   )r  r  rE  rG  r  r  numvxvyr=   r;   s              r   r  SVGObject.extract_shape_infoc  sO    W%h',,y)ll#8$?& #D#D
KKM~~c""$U3BZ0
+E2
LLNs##%fSbk2,V4?DLmmoG4@4F4Fw4OP4OSeCj4OPNBBQBF #LWI!VWWB+DL	 Qs   5E4c                     [        5       nSUR                  l        SUR                  l        SUR                  l        U R                  X5        X l        g)zFConvert the graphics contained in the SVG into the PDF representation.NFbutt)r   r   r   r   r   build_group
base_group)r  r  r  s      r   r  SVGObject.convert_graphics  sI     %&
(,
%&+
#,2
).$r    c                 f    U R                  UR                  UR                  UR                  U5      $ )a  
Size the converted SVG paths to the page viewport.

The SVG document size can be specified relative to the rendering viewport
(e.g. width=50%). If the converted SVG sizes are relative units, then this
computes the appropriate scale transform to size the SVG to the correct
dimensions for a page in the current PDF document.

If the SVG document size is specified in absolute units, then it is not scaled.

Args:
    pdf (fpdf.fpdf.FPDF): the pdf to use the page size of.
    align_viewbox (bool): if True, mimic some of the SVG alignment rules if the
        viewbox aspect ratio does not match that of the viewport.

Returns:
    The same thing as `SVGObject.transform_to_rect_viewport`.
)transform_to_rect_viewportkepweph)r  pdfalign_viewboxs      r   transform_to_page_viewport$SVGObject.transform_to_page_viewport  s'    ( ..suucggswwVVr    c                    U(       a  UnOY[        U R                  [        5      (       a%  U(       d  [        S5      eU R                  U-  S-  nOU R                  =(       d    UnU(       a  UnOY[        U R                  [        5      (       a%  U(       d  [        S5      eU R                  U-  S-  nOU R                  =(       d    UnUS:X  a  [
        R                  " 5       nO[
        R                  " SU-  5      nU R                  (       a  U R                  u  ppUS:X  d  US:X  a  SS[        5       4$ Xk-  nX|-  nU(       d"  U R                  (       a  X:w  a  [        X5      =pU[
        R                  " U	* U
* S9-  [
        R                  " XS9-  nU(       a0  U[
        R                  " US-  US-  U-  -
  US-  US-  U-  -
  S9-  nXR                  l        Xa-  Xq-  U R                  4$ )a  
Size the converted SVG paths to an arbitrarily sized viewport.

The SVG document size can be specified relative to the rendering viewport
(e.g. width=50%). If the converted SVG sizes are relative units, then this
computes the appropriate scale transform to size the SVG to the correct
dimensions for a page in the current PDF document.

Args:
    scale (Number): the scale factor from document units to PDF points.
    width (Number): the width of the viewport to scale to in document units.
    height (Number): the height of the viewport to scale to in document units.
    align_viewbox (bool): if True, mimic some of the SVG alignment rules if the
        viewbox aspect ratio does not match that of the viewport.
    ignore_svg_top_attrs (bool): ignore <svg> top attributes like "width", "height"
        or "preserveAspectRatio" when figuring the image dimensions.
        Require width & height to be provided as parameters.

Returns:
    A tuple of (width, height, `fpdf.drawing.GraphicsContext`), where width and
    height are the resolved width and height (they may be 0. If 0, the returned
    `fpdf.drawing.GraphicsContext` will be empty). The
    `fpdf.drawing.GraphicsContext` contains all of the paths that were
    converted from the SVG, scaled to the given viewport size.
z?SVG "width" is a percentage, hence a viewport width is requiredd   zASVG "height" is a percentage, hence a viewport height is requiredr	   r   rv  rK  )r%   rE  r,   rS   rG  r   r  r  r  r   r  minr  r  r   )r  ru  rE  rG  r  ignore_svg_top_attrsvp_width	vp_heightr   r  r  r=   r;   w_ratioh_ratios                  r   r  $SVGObject.transform_to_rect_viewport  s   :  H

G,, U  zzE)C/Hzz*UHIW-- W  f,s2I-vIA:!**,I!))!e)4I<<!\\NBBaR1W!_...mGnG'D,<,<'BT$'$99 ''2#"56##g9:  %	(=(=lb1f%77!mrAv&88) 	
 %.!!2DOOCCr    c                 n   UR                   U l         U R                  U5      u    pVUR                  UR                  p Ub=  Ub:  UR	                  SS5        UR
                  [        R                  " X#5      -  Ul        UR                  Xd5        UR	                  Xx5        g! UR	                  Xx5        f = f)a  
Directly draw the converted SVG to the given PDF's current page.

The page viewport is used for sizing the SVG.

Args:
    pdf (fpdf.fpdf.FPDF): the document to which the converted SVG is rendered.
    x (Number): abscissa of the converted SVG's top-left corner.
    y (Number): ordinate of the converted SVG's top-left corner.
    debug_stream (io.TextIO): the stream to which rendering debug info will be
        written.
Nr   )	r  r  r&  r'  set_xyr   r   r  	draw_path)	r  r  r&  r'  debug_stream_r@  old_xold_ys	            r   draw_to_pageSVGObject.draw_to_page  s     ??44S9
1uuceeu	%}

1a !%)2G2G2M!MMM$- JJu$CJJu$s   AB! !B4c                 8   U GH  nUR                   [        SS5      ;   a  U R                  U5        M1  UR                   [        SS5      ;   a(  [        R	                  S5        U R                  U5        Ms  UR                   [        SS5      ;   a  U R                  U5        M  UR                   [        SS5      ;   a  U R                  U5        M  UR                   [        ;   a  U R                  U5        M  UR                   [        SS5      ;   a-   UR                  S   nU H  nU R                  XC5        M     GM;  UR                   [        SS
5      ;   a  GMX  [        R	                  S[        UR                   5      5        GM     g	! [         a    S	n Nwf = f)z:Produce lookups for groups and paths inside the <defs> tagr!   gr  SIgnoring unsupported SVG tag: <a> (contributions are welcome to add support for it)r@  imageclipPathidNr   TIgnoring unsupported SVG tag: <%s> (contributions are welcome to add support for it))r   rl   r  r  r  
build_pathbuild_image
shape_tagsbuild_shaper   rW   build_clipping_pathrq   )r  defschildclip_idchild_s        r   handle_defsSVGObject.handle_defs  sD    EyyL44  'l5#66 i   'l5&99&l5'::  'j(  'l5*==##ll40G $F,,V= $l5'::juyy)7 &   #"G#s   F

FFc                 ^   U R                  U5      n[        5       n[        X1U5        [        SSS5       H  n UR                  U   n  O   [        SU S35      e UR                  U R                  U   5        SUR                  ;   d  S	UR                  ;   ab  [        UR                  R                  SS
5      5      [        UR                  R                  S	S
5      5      pv[        R                  " XgS9Ul        U$ ! [
         a     M  f = f! [
         a    [        SU SU 35      Sef = f)z?Resolve a cross-reference to an already-seen SVG element by ID.r"   hrefr  zuse z% doesn't contain known xref attributez references nonexistent ref id Nr&  r'  r   rv  )r  r   r   rl   r   rW   rS   add_itemr  rU   r   r   r  r   )r  xrefr   	pdf_group	candidaterefr&  r'  s           r   
build_xrefSVGObject.build_xrefC  s.    ''-	#%	Yi0%gvt<Ikk), = tD6)NOPP	t44S9: $++!3 a015a9P3Qq"+"7"7!"AI '    	tf;C5A	s   C>D >
DDD,c                    U R                  U5      n[        U=(       d    0 5      nUR                  U5        Uc
  [        5       n[	        X!U5        U Vs/ s H   ofR
                  [        SS5      ;   d  M  UPM"     sn H  nU R                  U5        M     U GH9  nUR
                  [        SS5      ;   a  U R                  U5        M1  UR
                  [        SS5      ;   a  MM  UR
                  [        SS5      ;   a%  UR                  U R                  USU5      S5        M  UR
                  [        SS5      ;   a:  [        R                  S5        UR                  U R                  USU5      S5        M  UR
                  [        SS	5      ;   a$  UR                  U R                  U5      S5        GM  UR
                  [        ;   a$  UR                  U R                  U5      S5        GMV  UR
                  [        SS
5      ;   a$  UR                  U R                  U5      S5        GM  UR
                  [        SS5      ;   a$  UR                  U R!                  U5      S5        GM  UR
                  [        SS5      ;   a$  UR                  U R#                  Xe5      S5        GM  [        R                  S[%        UR
                  5      5        GM<     U R'                  UR(                  R+                  S5      U5        U$ s  snf )z+Handle nested items within a group <g> tag.Nr!   r  r   r  Fr  r  r@  user  textr  r  )r  r1  r  r   r   r   rl   r   r  r  r  r  r  r  r  r	  r  
build_textrq   r  r   r   )r  r  r  inherited_stylelocal_stylemerged_styler  s          r   r  SVGObject.build_groupc  sf    ))%0O1r2K(')IY|4  %
$e		\%5P(PEu
E U#

 EyyL77  'l5'::l5#66""4#3#3E4#NPUVl5#66 i ""4#3#3E4#NPUVl5&99""4??5#95Aj(""4#3#3E#:EBl5%88""4??5#95Al5'::""4#3#3E#:EBl5&99""4??5#GOjuyy)5 > 	))$/;M
s   L5Lc                     U R                  U5      n[        5       n[        X1U5        U R                  X1U5        UR                  R                  S5      nUb  [        X45        U R                  UR                  R                  S5      U5        U$ )z1Convert an SVG <path> tag into a PDF path object.r  r  )r  r   r   apply_clipping_pathr   r   rc  r  )r  r@  r   r  r  s        r   r  SVGObject.build_path  sw     ''-	=XY/  ;;;??3'x2.9r    c                    U R                  U5      n[        [        [        UR                     5      nU" U5      n[        XAU5        U R                  XAU5        U R                  UR                  R                  S5      U5        U$ )zConvert an SVG shape tag into a PDF path object. Necessary to make xref (because ShapeBuilder doesn't have access to this object.)r  )
r  getattrr=  r  r   r   r  r  r   r   )r  shaper   shape_builder
shape_paths        r   r  SVGObject.build_shape  sr     ''.	j.CD"5)
Z	2  I>))$/<r    c                 2   UR                   [        ;   aH  U R                  U5      n[        [        [        UR                      5      nU" US5      n[        XQU5        OUR                   [        SS5      ;   af  U R                  U5      n[        5       n[        XQU5        [        R                  Ul
        UR                  R                  S5      nUb  [        XV5        O*[        R                  S[!        UR                   5      5        g U R#                  X%5        g )NTr!   r@  r  zaIgnoring unsupported <clipPath> child tag: <%s> (contributions are welcome to add support for it))r   r  r  r  r=  r   rl   r   r
   
DONT_PAINT
paint_ruler   r   rc  r  r  rq   r  )r  r  r  r   r  clipping_path_shaper  s          r   r  SVGObject.build_clipping_path  s    99
"++E2I#L*UYY2GHM"/t"<,Y?YY,uf55++E2I"--,Y?-:-E-E*||'',H#"#6ANNs599% 6r    c                     S nU(       a  SU;   a  US   nUc  UR                   R                  S5      nU(       a/  [        R                  " SU5      nU R                  US      Ul        g g )Nz	clip-pathzurl\((\#\w+)\)r	   )r   r   r   searchr  r>  )r  r   r   r   
clip_valueclipping_path_ids         r   r  SVGObject.apply_clipping_path  sj    
	1";/J$++//<J!yy):JG%)%:%:;KA;N%OH" r    c           
         S n[        SS5       H#  nX1R                  ;   d  M  UR                  U   n  O   U(       d  [        S5      e[        UR                  R	                  SS5      5      n[        UR                  R	                  SS5      5      nSUR                  ;   a  [
        R                  S5        S	UR                  ;   a  [
        R                  S
5        SUR                  ;   a  [
        R                  S5        [        U[        UR                  R	                  SS5      5      [        UR                  R	                  SS5      5      UUU S9nU R                  UR                  R	                  S5      U5        U$ )Nr"   r  z#<image> is missing a href attributerE  r   rG  r  zu"preserveAspectRatio" defined on <image> is currently not supported (contributions are welcome to add support for it)r   zg"style" defined on <image> is currently not supported (contributions are welcome to add support for it)r   zk"transform" defined on <image> is currently not supported (contributions are welcome to add support for it)r&  rD  r'  r  r&  r'  rE  rG  svg_objr  )	rl   r   rS   rU   r   r  r  SVGImager  )r  r  r  r   rE  rG  	svg_images          r   r  SVGObject.build_image  sC   0Cll"||C( 1 BCCell&&w23u||''!45 ELL0NN H ell"NNy %,,&NN} ELL$$S#./ELL$$S#./
	 	))$/;r    c                   ^"^#^$^%^&^'^( U R                  U5      n[        U=(       d    0 5      nUR                  U5        [        5       n[	        XQU5        U R                  XQU5        [        XA5      n[        X5      u  m$m#pxT$c  Sm$Ub  UO
[        S5      m%[        XT%S9u  ppX-   nX-   n/ m(Sm&Sm'S m"      SS[        S[        [           S	[        [           S
[        [           S[        S[        S[        S[        [           S[        [           4U"U#U$U%U&U'U(4S jjjnU" UR                  =(       d    ST$T#UUSSS9  U GHO  nUR                  [!        SS5      ;   Ga0  U R                  U5      n[        U5      nUR                  U5        [        UU5      u  nnnnUb  UOT%n[        UUUS9u  nnnn[        UU5      nSR#                  UR%                  5       5      nUR&                  =(       d    SnU(       a&  UR)                  U5      (       a  US[+        U5      *  nOUnSn Sn!SUR,                  ;   d	  Ub  SU;   a  Un SUR,                  ;   d	  Ub  SU;   a  Un!U" UUUUUUUU U!UUS9  U" UR&                  =(       d    ST$T#UUSSS9  GMO  GMR     T((       a#  UR/                  [1        UU[3        T(5      US9SS9  U R5                  UR,                  R7                  S5      U5        U$ )z
Convert <text> (and simple <tspan>) into a PaintedPath with Text runs.
- Uses Text baseline at (x,y)
- Honors x/y and dx/dy on <text> and direct child <tspan>
- Flattens nested tspans; advanced per-character positioning is not implemented
N
sans-serif16px)r  r   c                    ^ U b  Uc  g [        5       m[        TX5        [        R                  TR                  l        [        U4S j[        R                   5       5      nU(       d  g [        TR                  5      $ )Nc              3   p   >#    U  H+  n[        TR                  U5      [        R                  Lv   M-     g 7fr$   )r  r   r   r   )rn  propcontexts     r   rp  ?SVGObject.build_text.<locals>._style_for_run.<locals>.<genexpr>  s.      :D t,M4I4II:s   36)	r   r   r   r   r   r   anyMERGE_PROPERTIESr   )r   style_map_for_tag	overridesr2  s      @r   _style_for_run,SVGObject.build_text.<locals>._style_for_run  si    {/7%'G#9'4'<'<GMM$ ):: I GMM**r    raw_textr  r  sizer   dx_extrady_extraabs_xabs_yc                 H  > U =(       d    Sn[        XS9nU(       a  UnOUR                  5       nU(       a=  UnUS S R                  5       (       a  SU-   nUSS  R                  5       (       a  US-   nO<US S R                  5       (       d  USS  R                  5       (       a
  T(       a  SnOSnU(       d  TU-  mTU-  mg Ub  UOTnU=(       d    T=(       d    SnUb  UOT=(       d    SnTU-   nTU-   nSmSmT" X5      nTR                  [	        UUUUUUUUUS9	5        g )	Nrd   r   r	   r   rF  r-  r   )	r  r  r  r;  r(  r)  r>  r?  	run_style)r   r'   isspacer  r   )r:  r  r  r;  r   r<  r=  r>  r?  	style_tagr6  raw	collapsedcontenttrimmedrun_size
run_familyrun_emphasisrun_dxrun_dyrA  r8  	base_emphbase_familydefault_font_size
pending_dx
pending_dy	text_runss                        r   _add_run&SVGObject.build_text.<locals>._add_run$  sC    .bC$S<I##//+%G2Aw(("%-23x''))")C-BQ))SX-=-=-?-?Y"%"$h&
h&
#/t5FH>;>,J(0(<H)RPRL(*F(*FJJ&yDI %)!'
r    rd   )r   rC  r6  r!   tspanr&  r'  )r   r<  r=  r>  r?  rC  r6  )r&  r'  rR  text_anchorF)_copyr  )r   r   NNNN)r  r1  r  r   r   r  r   r  r\   r*  r&   r   rU   ri  r  r   rl   r  r  tailrL  r  r   add_path_elementr   r  r  r   ))r  text_tagr  r  effective_styler@  preserve_parent	base_sizebase_anchorbase_xbase_ybase_dxbase_dyanchor_xanchor_yrS  r  child_local_stylechild_effective_stylefamemphr;  _anchorrun_font_sizer&  r'  r(  r)  child_preserveraw_itertext	tail_textrun_textr>  r?  r8  rM  rN  rO  rP  rQ  rR  s)                                     @@@@@@@r   r  SVGObject.build_text  se    ))(34"5{+}T[1  A&A9J:
6Y	 &K".IN64J 	 ,;1B,
( ###%	

	+( "!%)%)"9	9	SM9	 sm9	 5/	9	
 9	 9	 9	 E?9	 E?9	 9	x 	MMR$"	
 EyyL88$($7$7$>!(,_(=%%,,->?+<0,(T4 )-(8>O.0M 1b" "..CU!K!wwu~~'78!JJ,"	!6!6y!A!A+,=s9~o>H+H%,,&%1c=N6NE%,,&%1c=N6NE+#&7 JJ$","&* s v !!#I. +	  "  	,,T2D9r    )r  r  r  rG  r  r  r  rE  r$   )T)TF)NNNNN)r/   r0   r   r1   r2   rj  r  r   r  r   r  r  r  r  r  r  r  r  r   r	  r  r  r  r  r  r  r  r3   r.   r    r   r  r    sF    18 8 8 (j ( 4 4
2> %, %,N 	% 	%W. NSRDh%:    H  > 0 0d 
 
   7 7, P P    D } }r    r  c                   x    \ rS rSr% \\S'   \\S'   \\S'   \\S'   \\S'   \\S'   S r\	S	 5       r
\	S
 5       rSrg)r)  i  r  r&  r'  rE  rG  r(  c           	          [        U R                  U R                  U R                  U R                  U R
                  U R                  S9$ )Nr'  )r)  r  r&  r'  rE  rG  r(  )r  _memos     r   __deepcopy__SVGImage.__deepcopy__  s9    ffff**;;LL
 	
r    c           	         U R                   =(       a    U R                   R                  nU(       d  [        S5      eSSKJn  U" XPR
                  5      u    px[        U[        5      (       a  [        R                  S5        SX44$ UR                  U R                  U R                  5      u  p[        UU R                  U R                  U	U
SS9nXU4$ )NzHfpdf2 bug - Cannot render a raster image without a SVGObject.image_cacher	   )preload_imagez{Inserting .svg vector graphics in <image> tags is currently not supported (contributions are welcome to add support for it)rd   T)infor&  r'  whkeep_aspect_ratio)r(  r  AssertionErrorimage_parsingrw  r  r%   r   r  r  size_in_document_unitsrE  rG  r   r&  r'  )r  _resource_registry_style	last_iteminitial_pointr  rw  r  rx  ry  rz  stream_contents               r   renderSVGImage.render  s    ll?t||'?'? Z  	1";		:
1dO,,NN N y//**4::t{{C8ffff"
 -77r    c                 v    U R                  XX45      u  psnUR                  U R                   SU S35        XsU4$ )Nz rendered as: 
)r  writer  )r  resource_registryr   r  r  r  _pfxr  s           r   render_debugSVGImage.render_debug  sI     48;;i4
0= 	dii[~6FbIJ-77r    r.   N)r/   r0   r   r1   r&   __annotations__r   r  rt  r   r  r  r3   r.   r    r   r)  r)    sN    
IIIMN	
 8 88 8 8r    r)  )rH   )rL   r$   rp  )[r2   loggingr  r   warningscopyr   numbersr   typingr   r   r   fontTools.svgLib.pathr   enumsr
   defusedxml.ElementTreer   r  ImportErrorwarnxml.etree.ElementTreerd   r   drawing_primitivesr   r   r   drawingr   r   r   r   r   r   r   image_datastructuresr   r   outputr   	getLoggerr/   r  r   r   re   compiler   r  DOTALLr.  r/  r*   rU   r,   rQ   rX   rV   taur^   r\   r`   rh   rl   rq   r  r   r   r   r   r   r   r   r   r1  ri  r   r&   r   r   r   r  r*  r;  r=  r   rc  r  r)  r.   r    r   <module>r     s"   # "   . . ,  BB  W W   > 3			8	$& (+ 
 zz89::m  L"))4zz56 /e / / 

PQ * 




		  88c>HHsNHH	 V V( 	Q 	Q       	68Y
I

 D D     	 	 !4   / 	) 	)  JT
 N

 OR
S-` !7 !7H#D #$ # .3 	"C 	"d 	"s 	"C c c * 1566'~6c]6" &*QTNQ
8C=#x34QH !%!%@~@ @ 5%%&	@F8 | | |~ ` `F ? ?`
 `
F88z 88},  BMMc BABs   I7 7JJ