Programmatically generate SVG (vector) images, animations, and interactive Jupyter widgets

Quick reference docs (#90)

added docs

jh fc5d923e 5e11115e

+1 -1
.gitignore
···
/MANIFEST
/dist
/*.egg-info
-
+
*.ipynb_checkpoints
+9
docs/img/01_circ.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="100" viewBox="0 0 300 100">
+
<defs>
+
</defs>
+
<circle cx="50" cy="50" r="40" />
+
<circle cx="150" cy="50" r="40" stroke="black" fill="none" />
+
<circle cx="250" cy="50" r="40" stroke="black" fill="none" stroke-width="15" />
+
</svg>
+9
docs/img/01_ellip.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="100" viewBox="0 0 300 100">
+
<defs>
+
</defs>
+
<ellipse cx="50" cy="50" rx="50" ry="30" />
+
<ellipse cx="160" cy="50" rx="50" ry="30" stroke="black" fill="none" />
+
<ellipse cx="250" cy="50" rx="30" ry="45" stroke="black" fill="none" />
+
</svg>
+7
docs/img/01_line.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="100" viewBox="0 0 100 100">
+
<defs>
+
</defs>
+
<path d="M30,30 L90,90" stroke="black" />
+
</svg>
+7
docs/img/01_multilines.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="100" viewBox="0 0 100 100">
+
<defs>
+
</defs>
+
<path d="M10,90 L10,10 L80,90 L80,10" fill="none" stroke="black" />
+
</svg>
+7
docs/img/01_multilines2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="100" viewBox="0 0 300 100">
+
<defs>
+
</defs>
+
<path d="M30,80 L40,20 L50,80 L60,20 L70,80 L80,20 L90,80 L100,20 L110,80 L120,20 L130,80 L140,20 L150,80 L160,20 L170,80 L180,20 L190,80 L200,20 L210,80 L220,20" stroke="black" stroke-width="5" fill="none" />
+
</svg>
+7
docs/img/01_polygon.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="100" viewBox="0 0 100 100">
+
<defs>
+
</defs>
+
<path d="M48,16 L16,96 L96,48 L0,48 L88,96 Z" stroke="black" fill="none" />
+
</svg>
+10
docs/img/01_rect.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="500" height="200" viewBox="0 0 500 200">
+
<defs>
+
</defs>
+
<rect x="10" y="10" width="90" height="150" />
+
<rect x="120" y="10" width="60" height="120" fill="none" stroke="black" />
+
<rect x="210" y="10" width="75" height="90" fill="#0000ff" stroke="red" stroke-width="7" stroke-opacity="0.5" />
+
<rect x="300" y="10" width="105" height="60" fill="yellow" fill-opacity="0.5" stroke="green" stroke-width="2" stroke-dasharray="5,2" />
+
</svg>
+11
docs/img/01_rectround.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="500" height="200" viewBox="0 0 500 200">
+
<defs>
+
</defs>
+
<rect x="10" y="10" width="80" height="180" rx="10" ry="10" stroke="black" fill="none" />
+
<rect x="110" y="10" width="80" height="180" ry="20" stroke="black" fill="none" />
+
<rect x="210" y="10" width="80" height="180" rx="40" stroke="black" fill="none" />
+
<rect x="310" y="10" width="80" height="180" rx="30" ry="10" stroke="black" fill="none" />
+
<rect x="410" y="10" width="80" height="180" rx="10" ry="30" stroke="black" fill="none" />
+
</svg>
+9
docs/img/02_dash.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="110" height="40" viewBox="0 0 110 40">
+
<defs>
+
</defs>
+
<path d="M10,10 L100,10" stroke="black" stroke-width="2" stroke-dasharray="9,5" />
+
<path d="M10,20 L100,20" stroke="black" stroke-width="2" stroke-dasharray="5,3,9,2" />
+
<path d="M10,30 L100,30" stroke="black" stroke-width="2" stroke-dasharray="9,3,5" />
+
</svg>
+16
docs/img/02_foso.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="100" viewBox="0 0 300 100">
+
<defs>
+
</defs>
+
<path d="M0,10 L290,10" stroke="black" stroke-width="5" stroke-opacity="0.1" />
+
<rect x="0" y="70" width="50" height="50" fill="red" fill-opacity="0.1" />
+
<path d="M0,20 L290,20" stroke="black" stroke-width="5" stroke-opacity="0.30000000000000004" />
+
<rect x="60" y="70" width="50" height="50" fill="red" fill-opacity="0.30000000000000004" />
+
<path d="M0,30 L290,30" stroke="black" stroke-width="5" stroke-opacity="0.5" />
+
<rect x="120" y="70" width="50" height="50" fill="red" fill-opacity="0.5" />
+
<path d="M0,40 L290,40" stroke="black" stroke-width="5" stroke-opacity="0.7" />
+
<rect x="180" y="70" width="50" height="50" fill="red" fill-opacity="0.7" />
+
<path d="M0,50 L290,50" stroke="black" stroke-width="5" stroke-opacity="0.9" />
+
<rect x="240" y="70" width="50" height="50" fill="red" fill-opacity="0.9" />
+
</svg>
+11
docs/img/02_fsc.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="60" viewBox="0 0 100 60">
+
<defs>
+
</defs>
+
<path d="M10,10 L80,10" stroke="red" stroke-width="5" />
+
<path d="M10,20 L80,20" stroke="#9f9" stroke-width="5" />
+
<path d="M10,30 L80,30" stroke="#9999ff" stroke-width="5" />
+
<path d="M10,40 L80,40" stroke="rgb(255,128,64)" stroke-width="5" />
+
<path d="M10,50 L80,50" stroke="rgb(60%,20%,60%)" stroke-width="5" />
+
</svg>
+12
docs/img/02_join.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="100" viewBox="0 0 300 100">
+
<defs>
+
</defs>
+
<path d="M0,20 L300,20" stroke="gray" />
+
<g stroke-width="20" stroke="black" fill="none">
+
<path d="M10,80 L50,20 L90,80" stroke-linejoin="miter" />
+
<path d="M110,80 L150,20 L190,80" stroke-linejoin="round" />
+
<path d="M210,80 L250,20 L290,80" stroke-linejoin="bevel" />
+
</g>
+
</svg>
+11
docs/img/02_linecap.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="150" height="100" viewBox="0 0 150 100">
+
<defs>
+
</defs>
+
<path d="M10,15 L50,15" stroke="black" stroke-width="15" stroke-linecap="butt" />
+
<path d="M10,45 L50,45" stroke="black" stroke-width="15" stroke-linecap="round" />
+
<path d="M10,75 L50,75" stroke="black" stroke-width="15" stroke-linecap="square" />
+
<path d="M10,0 L10,100" stroke="#999" />
+
<path d="M50,0 L50,100" stroke="#999" />
+
</svg>
+12
docs/img/02_mlimit.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="100" viewBox="0 0 300 100">
+
<defs>
+
</defs>
+
<path d="M0,30 L300,30" stroke="gray" />
+
<g stroke-width="20" stroke="black" fill="none" stroke-linejoin="miter">
+
<path d="M10,90 L40,30 L70,90" />
+
<path d="M100,90 L130,30 L160,90" stroke-miterlimit="2.3" />
+
<path d="M190,90 L220,30 L250,90" stroke-miterlimit="1" />
+
</g>
+
</svg>
+26
docs/img/02_strokewdth.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="320" height="100" viewBox="0 0 320 100">
+
<defs>
+
</defs>
+
<path d="M15,10 L15,90" stroke="black" stroke-width="11" />
+
<path d="M30,10 L30,90" stroke="black" stroke-width="10" />
+
<path d="M45,10 L45,90" stroke="black" stroke-width="9" />
+
<path d="M60,10 L60,90" stroke="black" stroke-width="8" />
+
<path d="M75,10 L75,90" stroke="black" stroke-width="7" />
+
<path d="M90,10 L90,90" stroke="black" stroke-width="6" />
+
<path d="M105,10 L105,90" stroke="black" stroke-width="5" />
+
<path d="M120,10 L120,90" stroke="black" stroke-width="4" />
+
<path d="M135,10 L135,90" stroke="black" stroke-width="3" />
+
<path d="M150,10 L150,90" stroke="black" stroke-width="2" />
+
<path d="M165,10 L165,90" stroke="black" stroke-width="1" />
+
<path d="M180,10 L180,90" stroke="black" stroke-width="2" />
+
<path d="M195,10 L195,90" stroke="black" stroke-width="3" />
+
<path d="M210,10 L210,90" stroke="black" stroke-width="4" />
+
<path d="M225,10 L225,90" stroke="black" stroke-width="5" />
+
<path d="M240,10 L240,90" stroke="black" stroke-width="6" />
+
<path d="M255,10 L255,90" stroke="black" stroke-width="7" />
+
<path d="M270,10 L270,90" stroke="black" stroke-width="8" />
+
<path d="M285,10 L285,90" stroke="black" stroke-width="9" />
+
<path d="M300,10 L300,90" stroke="black" stroke-width="10" />
+
</svg>
+10
docs/img/03_pA.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="400" height="200" viewBox="0 0 400 200" stroke-width="3" fill="none">
+
<defs>
+
</defs>
+
<path d="M125,75 A100,50,0,0,0,225,125" stroke="red" />
+
<path d="M125,75 A100,50,0,0,1,225,125" stroke="blue" />
+
<path d="M125,75 A100,50,0,1,0,225,125" stroke="rgb(0 80 255)" stroke-dasharray="5 3" />
+
<path d="M125,75 A100,50,0,1,1,225,125" stroke="rgb(255 80 0)" stroke-dasharray="5 3" />
+
</svg>
+48
docs/img/03_pC.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="650" height="100" viewBox="0 0 650 100">
+
<defs>
+
</defs>
+
<path d="M40,50 C10,10,140,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(0,0)" />
+
<g stroke="gray" fill="gray" stroke-width="1" transform="translate(0,0)">
+
<circle cx="10" cy="10" r="2" />
+
<circle cx="140" cy="10" r="2" />
+
<path d="M40,50 L10,10" />
+
<path d="M110,50 L140,10" />
+
</g>
+
<path d="M40,50 C60,10,90,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(100,0)" />
+
<g stroke="gray" fill="gray" stroke-width="1" transform="translate(100,0)">
+
<circle cx="60" cy="10" r="2" />
+
<circle cx="90" cy="10" r="2" />
+
<path d="M40,50 L60,10" />
+
<path d="M110,50 L90,10" />
+
</g>
+
<path d="M40,50 C110,10,40,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(200,0)" />
+
<g stroke="gray" fill="gray" stroke-width="1" transform="translate(200,0)">
+
<circle cx="110" cy="10" r="2" />
+
<circle cx="40" cy="10" r="2" />
+
<path d="M40,50 L110,10" />
+
<path d="M110,50 L40,10" />
+
</g>
+
<path d="M40,50 C110,10,40,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(300,0)" />
+
<g stroke="gray" fill="gray" stroke-width="1" transform="translate(300,0)">
+
<circle cx="110" cy="10" r="2" />
+
<circle cx="40" cy="10" r="2" />
+
<path d="M40,50 L110,10" />
+
<path d="M110,50 L40,10" />
+
</g>
+
<path d="M40,50 C60,10,90,90,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(400,0)" />
+
<g stroke="gray" fill="gray" stroke-width="1" transform="translate(400,0)">
+
<circle cx="60" cy="10" r="2" />
+
<circle cx="90" cy="90" r="2" />
+
<path d="M40,50 L60,10" />
+
<path d="M110,50 L90,90" />
+
</g>
+
<path d="M40,50 C110,10,40,90,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(500,0)" />
+
<g stroke="gray" fill="gray" stroke-width="1" transform="translate(500,0)">
+
<circle cx="110" cy="10" r="2" />
+
<circle cx="40" cy="90" r="2" />
+
<path d="M40,50 L110,10" />
+
<path d="M110,50 L40,90" />
+
</g>
+
</svg>
+8
docs/img/03_pHV.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="60" viewBox="0 0 100 60">
+
<defs>
+
</defs>
+
<path d="M10,10 H100 M10,20 H100 V50" stroke="black" fill="none" id="pathHV0" />
+
<use xlink:href="#pathHV0" />
+
</svg>
+11
docs/img/03_pL.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="70" viewBox="0 0 100 70">
+
<defs>
+
</defs>
+
<g stroke="black" fill="none">
+
<path d="M10,10 L100,10" />
+
<path d="M10,20 L100,20 L100,50" />
+
<path d="M40,60 L10,60 L40,42 M60,60 L90,60 L60,42" />
+
</g>
+
</svg>
+21
docs/img/03_pQ.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="700" height="130" viewBox="0 0 700 130">
+
<defs>
+
<path d="M30,75 Q240,30,300,120" stroke="black" fill="none" stroke-width="3" id="pathQ0" />
+
</defs>
+
<use xlink:href="#pathQ0" />
+
<use xlink:href="#pathQ0" x="300" y="0" />
+
<g stroke="gray" fill="gray">
+
<circle cx="330" cy="75" r="3" />
+
<circle cx="600" cy="120" r="3" />
+
<circle cx="540" cy="30" r="3" />
+
<path d="M330,75 L540,30" />
+
<path d="M540,30 L600,120" />
+
<path d="M330,75 L600,120" stroke-dasharray="5,5" />
+
<circle cx="435" cy="52.5" r="3" />
+
<circle cx="570" cy="75" r="3" />
+
<path d="M435,52.5 L570,75" />
+
<circle cx="502.5" cy="63.75" r="4" fill="none" />
+
</g>
+
</svg>
+16
docs/img/03_pS.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="250" height="150" viewBox="0 0 250 150">
+
<defs>
+
</defs>
+
<path d="M30,100 C50,30,70,50,100,100 S150,40,200,80" stroke="black" fill="none" stroke-width="3" />
+
<circle cx="30" cy="100" r="4" />
+
<circle cx="50" cy="30" r="2" stroke="gray" fill="gray" />
+
<path d="M30,100 L50,30" stroke="gray" />
+
<circle cx="100" cy="100" r="4" />
+
<circle cx="70" cy="50" r="2" stroke="gray" fill="gray" />
+
<path d="M100,100 L70,50" stroke="gray" />
+
<circle cx="200" cy="80" r="4" />
+
<circle cx="150" cy="40" r="2" stroke="gray" fill="gray" />
+
<path d="M200,80 L150,40" stroke="gray" />
+
</svg>
+8
docs/img/03_pT.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="400" height="100" viewBox="0 0 400 100">
+
<defs>
+
</defs>
+
<path d="M30,60 Q80,-10,100,60 Q130,25,200,40" stroke="black" fill="none" stroke-width="3" />
+
<path d="M30,60 Q80,-10,100,60 T200,40" stroke="black" fill="none" stroke-width="3" transform="translate(200,0)" />
+
</svg>
+8
docs/img/03_pZ.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="90" height="70" viewBox="0 0 90 70">
+
<defs>
+
</defs>
+
<path d="M10,10 h30 v50 h-30 Z M50,10 h30 v50 Z" stroke="black" fill="none" id="pathZ0" />
+
<use xlink:href="#pathZ0" />
+
</svg>
+16
docs/img/04_align.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="250" height="120" viewBox="0 0 250 120">
+
<defs>
+
</defs>
+
<path d="M75,100 L75,0" stroke="gray" />
+
<path d="M140,30 L250,30" stroke="gray" />
+
<path d="M140,60 L250,60" stroke="gray" />
+
<path d="M140,90 L250,90" stroke="gray" />
+
<text x="75" y="30" font-size="24" text-anchor="start">Start</text>
+
<text x="75" y="60" font-size="24" text-anchor="middle">Middle</text>
+
<text x="75" y="90" font-size="24" text-anchor="end">End</text>
+
<text x="150" y="30" font-size="24" dominant-baseline="bottom">Auto</text>
+
<text x="150" y="60" font-size="24" dominant-baseline="middle">Middle</text>
+
<text x="150" y="90" font-size="24" dominant-baseline="top">Hanging</text>
+
</svg>
+13
docs/img/04_fill.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="550" height="370" viewBox="0 0 550 370">
+
<defs>
+
</defs>
+
<path d="M20,0 V370 M10,60 H500 M10,120 H500 M10,180 H500 M10,240 H500 M10,300 H500 M10,360 H500" stroke="gray" />
+
<text x="20" y="60" font-size="50">Simplest Text</text>
+
<text x="20" y="120" font-size="50" stroke="black">Outline / Filled</text>
+
<text x="20" y="180" font-size="50" stroke="black" stroke-width="5">Too big stroke</text>
+
<text x="20" y="240" font-size="50" stroke="black" stroke-width="0.5" fill="none">Outlined only</text>
+
<text x="20" y="300" font-size="50" stroke="black" fill="red">Outlined and colored</text>
+
<text x="20" y="360" font-size="50" fill="blue">Colored fill only</text>
+
</svg>
docs/img/04_fonts1.png

This is a binary file and will not be displayed.

docs/img/04_fonts2.png

This is a binary file and will not be displayed.

+14
docs/img/04_len.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="400" height="200" viewBox="0 0 400 200">
+
<defs>
+
</defs>
+
<text x="20" y="30" font-size="20" textLength="250" lengthAdjust="spacing">Two words</text>
+
<text x="20" y="70" font-size="20" textLength="250" lengthAdjust="spacingAndGlyphs">Two words</text>
+
<text x="20" y="110" font-size="20">Two words (normal length)</text>
+
<text x="20" y="150" font-size="20" textLength="80" lengthAdjust="spacing">Two words</text>
+
<text x="20" y="190" font-size="20" textLength="80" lengthAdjust="spacingAndGlyphs">Two words</text>
+
<path d="M20,10 L20,195" stroke="gray" />
+
<path d="M270,80 L270,10" stroke="gray" />
+
<path d="M100,130 L100,195" stroke="gray" />
+
</svg>
+8
docs/img/04_multiline_text.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="100" viewBox="0 0 200 100">
+
<defs>
+
</defs>
+
<text x="50" y="20" font-size="14" text-anchor="middle"><tspan x="50" dy="0em">this is</tspan><tspan x="50" dy="1em">a</tspan><tspan x="50" dy="1em">multiline text</tspan><tspan x="50" dy="1em">given as a</tspan><tspan x="50" dy="1em">list</tspan></text>
+
<text x="150" y="20" font-size="14" text-anchor="middle"><tspan x="150" dy="0em">this is</tspan><tspan x="150" dy="1em">a</tspan><tspan x="150" dy="1em">multiline text</tspan><tspan x="150" dy="1em">given as a</tspan><tspan x="150" dy="1em">string</tspan></text>
+
</svg>
+8
docs/img/04_mutiline_text.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="100" viewBox="0 0 200 100">
+
<defs>
+
</defs>
+
<text x="50" y="20" font-size="14" text-anchor="middle"><tspan x="50" dy="0em">this is</tspan><tspan x="50" dy="1em">a</tspan><tspan x="50" dy="1em">multiline text</tspan><tspan x="50" dy="1em">given as a</tspan><tspan x="50" dy="1em">list</tspan></text>
+
<text x="150" y="20" font-size="14" text-anchor="middle"><tspan x="150" dy="0em">this is</tspan><tspan x="150" dy="1em">a</tspan><tspan x="150" dy="1em">multiline text</tspan><tspan x="150" dy="1em">given as a</tspan><tspan x="150" dy="1em">string</tspan></text>
+
</svg>
+31
docs/img/04_path.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="500" height="200" viewBox="0 0 500 200">
+
<defs>
+
<path d="M30,50 C50,20,70,20,120,50 S150,10,200,50" stroke="gray" fill="none" id="textpath0" />
+
<path d="M250,30 L300,30 A30,30,0,0,1,330,60 L330,110" stroke="gray" fill="none" id="textpath1" />
+
<path d="M30,110 L100,110 L100,160" stroke="gray" fill="none" id="textpath2" />
+
<path d="M150,110 A40,30,0,1,0,230,110 M250,110 L270,140" stroke="gray" fill="none" id="textpath3" />
+
<path d="M330,130 L330,160 A30,30,0,0,1,300,180 L200,180" stroke="gray" fill="none" id="textpath4" />
+
</defs>
+
<use xlink:href="#textpath0" />
+
<use xlink:href="#textpath1" />
+
<use xlink:href="#textpath2" />
+
<use xlink:href="#textpath3" />
+
<use xlink:href="#textpath4" />
+
<text font-size="14"><textPath xlink:href="#textpath0">
+
<tspan dy="0em">Following a cubic Bézier curve</tspan>
+
</textPath></text>
+
<text font-size="14"><textPath xlink:href="#textpath1">
+
<tspan dy="0em">Going 'round the bend</tspan>
+
</textPath></text>
+
<text font-size="14"><textPath xlink:href="#textpath2">
+
<tspan dy="0em">Making a quick turn</tspan>
+
</textPath></text>
+
<text font-size="14"><textPath xlink:href="#textpath3">
+
<tspan dy="0em">Text along a broken path</tspan>
+
</textPath></text>
+
<text font-size="14" offset="50%" text-anchor="middle"><textPath xlink:href="#textpath4" startOffset="50%">
+
<tspan dy="0em">centered</tspan>
+
</textPath></text>
+
</svg>
+8
docs/img/04_rot.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="100" viewBox="0 0 200 100">
+
<defs>
+
</defs>
+
<text x="20" y="20" font-size="20" letter-spacing="20" rotate="90">Rotate</text>
+
<text x="20" y="80" font-size="20" letter-spacing="20" rotate="0 90 180 270">Rotate</text>
+
</svg>
+7
docs/img/04_rot2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="80" viewBox="0 0 200 80">
+
<defs>
+
</defs>
+
<text x="20" y="50" font-size="20" letter-spacing="20"><tspan rotate="68">R</tspan><tspan rotate="50 20">OT</tspan><tspan rotate="291 32 130">ATE</tspan></text>
+
</svg>
+7
docs/img/04_tspan.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="600" height="50" viewBox="0 0 600 50">
+
<defs>
+
</defs>
+
<text x="10" y="40" font-size="24">Switch among <tspan font-style="italic">italic</tspan><tspan>, normal, and </tspan><tspan font-weight="bold">bold</tspan><tspan> text.</tspan></text>
+
</svg>
+7
docs/img/04_tspan2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="160" viewBox="0 0 300 160">
+
<defs>
+
</defs>
+
<text x="10" y="30" font-size="24">F<tspan dy="5">a</tspan><tspan dy="31" dx="21">l</tspan><tspan dy="89" dx="54">l</tspan></text>
+
</svg>
+7
docs/img/04_tspan3.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="160" viewBox="0 0 300 160">
+
<defs>
+
</defs>
+
<text x="10" y="30" font-size="24" dx="0,0,21,54" dy="0,5,21,54">Fall</text>
+
</svg>
+16
docs/img/04_weight.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="600" height="200" viewBox="0 0 600 200">
+
<defs>
+
</defs>
+
<text x="20" y="35" font-size="30" font-weight="bold">bold</text>
+
<text x="20" y="75" font-size="30" font-style="italic">italic</text>
+
<text x="20" y="115" font-size="30" text-decoration="underline">under</text>
+
<text x="20" y="155" font-size="30" text-decoration="overline">over</text>
+
<text x="20" y="195" font-size="30" text-decoration="line-through">through</text>
+
<text x="200" y="35" font-size="30">normal word space</text>
+
<text x="200" y="75" font-size="30" word-spacing="10">more word space</text>
+
<text x="200" y="115" font-size="30" word-spacing="-5">less word space</text>
+
<text x="200" y="155" font-size="30" letter-spacing="8">wide letter space</text>
+
<text x="200" y="195" font-size="30" letter-spacing="-2">narrow letter space</text>
+
</svg>
+12
docs/img/05_clip.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="200" viewBox="0 0 200 200">
+
<defs>
+
<clipPath id="clip0">
+
<rect x="100" y="100" width="100" height="100" />
+
</clipPath>
+
</defs>
+
<rect x="100" y="100" width="100" height="100" stroke="gray" fill="none" />
+
<circle cx="100" cy="100" r="100" fill="none" stroke="gray" stroke-dasharray="5 5" />
+
<circle cx="100" cy="100" r="100" fill="cyan" clip-path="url(#clip0)" />
+
</svg>
+12
docs/img/05_clip2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="600" height="200" viewBox="0 0 600 200">
+
<defs>
+
<path d="M150,150 L68,145 L32,65 L60,126 L230,120 L194,53 L48,124 L14,99 L221,155 L1,178 L228,68 L117,151 L52,81 L15,5 L13,166 L277,2 L195,175 L110,108 L14,135 L113,195 L224,126 L283,59 L176,59 L112,194 L235,74 L11,106 L284,164 L51,47 L151,30 L170,184 L256,108 L259,171 L97,77 L145,150 L255,129 L201,150 L17,122 L124,190 L206,106 L88,93 L280,179" stroke="black" stroke-width="2" fill="none" id="clip20" />
+
<clipPath id="clip21">
+
<circle cx="150" cy="100" r="75" />
+
</clipPath>
+
</defs>
+
<use xlink:href="#clip20" />
+
<use xlink:href="#clip20" x="300" y="0" clip-path="url(#clip21)" />
+
</svg>
+29
docs/img/05_clip3.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="300" viewBox="0 0 300 300">
+
<defs>
+
<g id="clip30">
+
<rect x="0" y="50" width="90" height="60" fill="#999" />
+
<circle cx="25" cy="25" r="25" fill="#666" />
+
<path d="M30,0 L80,0 L80,100 Z" fill="#ccc" />
+
</g>
+
<path d="M5,55 C25,5,45,-25,75,55 C85,85,20,105,40,55 Z" stroke="black" stroke-width="1" stroke-dasharray="3 2" fill="none" id="clip31" />
+
<clipPath id="clip32">
+
<use xlink:href="#clip31" x="0" y="0" />
+
</clipPath>
+
<text x="20" y="20" font-size="48" font-weight="bold" transform="rotate(60)" stroke="black" stroke-width="1" stroke-dasharray="3 2" fill="none" id="clip33">CLIP</text>
+
<clipPath id="clip34">
+
<use xlink:href="#clip33" x="0" y="0" />
+
</clipPath>
+
</defs>
+
<use xlink:href="#clip30" x="0" y="0" clip-path="url(#clip32)" />
+
<g transform="translate(100,0)">
+
<use xlink:href="#clip30" />
+
<use xlink:href="#clip31" x="0" y="0" />
+
</g>
+
<use xlink:href="#clip30" x="0" y="150" clip-path="url(#clip34)" />
+
<g transform="translate(100,150)">
+
<use xlink:href="#clip30" />
+
<use xlink:href="#clip33" x="0" y="0" />
+
</g>
+
</svg>
+11
docs/img/05_lingrad.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="80" viewBox="0 0 200 80">
+
<defs>
+
<linearGradient x1="150" y1="0" x2="0" y2="0" gradientUnits="userSpaceOnUse" id="grad10">
+
<stop offset="0" stop-color="green" />
+
<stop offset="1" stop-color="yellow" />
+
</linearGradient>
+
</defs>
+
<rect x="10" y="10" width="150" height="60" stroke="black" fill="url(#grad10)" />
+
</svg>
+15
docs/img/05_mask.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="100" viewBox="0 0 200 100">
+
<defs>
+
<linearGradient x1="0" y1="0" x2="1" y2="0" gradientUnits="objectBoundingBox" id="mask10">
+
<stop offset="0" stop-color="white" />
+
<stop offset="1" stop-color="black" />
+
</linearGradient>
+
<mask id="mask11">
+
<rect x="30" y="0" width="100" height="100" fill="url(#mask10)" />
+
</mask>
+
</defs>
+
<rect x="0" y="0" width="200" height="100" fill="cyan" stroke="blue" stroke-width="2" />
+
<rect x="0" y="0" width="200" height="100" fill="pink" stroke="red" stroke-width="2" mask="url(#mask11)" />
+
</svg>
+38
docs/img/05_mask2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="250" height="150" viewBox="0 0 250 150">
+
<defs>
+
<mask maskContentUnits="objectBoundingBox" id="mask20">
+
<rect x="0" y="0" width="1" height="1" fill="#f00" />
+
</mask>
+
<mask maskContentUnits="objectBoundingBox" id="mask21">
+
<rect x="0" y="0" width="1" height="1" fill="#0f0" />
+
</mask>
+
<mask maskContentUnits="objectBoundingBox" id="mask22">
+
<rect x="0" y="0" width="1" height="1" fill="#00f" />
+
</mask>
+
<mask maskContentUnits="objectBoundingBox" id="mask23">
+
<rect x="0" y="0" width="1" height="1" fill="#fff" />
+
</mask>
+
</defs>
+
<rect x="10" y="10" width="50" height="50" fill="#f00" />
+
<rect x="70" y="10" width="50" height="50" fill="#0f0" />
+
<rect x="130" y="10" width="50" height="50" fill="#00f" />
+
<rect x="190" y="10" width="50" height="50" fill="#fff" stroke="black" />
+
<g mask="url(#mask20)">
+
<circle cx="35" cy="115" r="25" fill="black" />
+
<text x="35" y="80" font-size="14" text-anchor="middle">Red</text>
+
</g>
+
<g mask="url(#mask21)">
+
<circle cx="95" cy="115" r="25" fill="black" />
+
<text x="95" y="80" font-size="14" text-anchor="middle">Green</text>
+
</g>
+
<g mask="url(#mask22)">
+
<circle cx="155" cy="115" r="25" fill="black" />
+
<text x="155" y="80" font-size="14" text-anchor="middle">Blue</text>
+
</g>
+
<g mask="url(#mask23)">
+
<circle cx="215" cy="115" r="25" fill="black" />
+
<text x="215" y="80" font-size="14" text-anchor="middle">White</text>
+
</g>
+
</svg>
+34
docs/img/05_mask3.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="250" height="100" viewBox="0 0 250 100">
+
<defs>
+
<mask maskContentUnits="objectBoundingBox" id="mask30">
+
<rect x="0" y="0" width="1" height="1" fill-opacity="1.0" fill="white" />
+
</mask>
+
<mask maskContentUnits="objectBoundingBox" id="mask31">
+
<rect x="0" y="0" width="1" height="1" fill-opacity="0.75" fill="white" />
+
</mask>
+
<mask maskContentUnits="objectBoundingBox" id="mask32">
+
<rect x="0" y="0" width="1" height="1" fill-opacity="0.5" fill="white" />
+
</mask>
+
<mask maskContentUnits="objectBoundingBox" id="mask33">
+
<rect x="0" y="0" width="1" height="1" fill-opacity="0.25" fill="white" />
+
</mask>
+
</defs>
+
<g mask="url(#mask30)">
+
<circle cx="35" cy="35" r="25" />
+
<text x="35" y="80" font-size="14" text-anchor="middle">100%</text>
+
</g>
+
<g mask="url(#mask31)">
+
<circle cx="95" cy="35" r="25" />
+
<text x="95" y="80" font-size="14" text-anchor="middle">50%</text>
+
</g>
+
<g mask="url(#mask32)">
+
<circle cx="155" cy="35" r="25" />
+
<text x="155" y="80" font-size="14" text-anchor="middle">50%</text>
+
</g>
+
<g mask="url(#mask33)">
+
<circle cx="215" cy="35" r="25" />
+
<text x="215" y="80" font-size="14" text-anchor="middle">25%</text>
+
</g>
+
</svg>
+11
docs/img/05_radgrad.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="400" height="200" viewBox="0 0 400 200">
+
<defs>
+
<radialGradient cx="200" cy="100" r="100" gradientUnits="userSpaceOnUse" id="grad20">
+
<stop offset="0" stop-color="green" stop-opacity="1" />
+
<stop offset="1" stop-color="orange" stop-opacity="1" />
+
</radialGradient>
+
</defs>
+
<rect x="0" y="0" width="100%" height="100%" fill="url(#grad20)" />
+
</svg>
+24
docs/img/06_group.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="240" height="120" viewBox="0 0 240 120">
+
<defs>
+
</defs>
+
<g id="house" fill="none" stroke="black">
+
<rect x="6" y="50" width="60" height="60" />
+
<path d="M6,50 L36,9 L66,50" />
+
<path d="M36,110 L36,80 L50,80 L50,110" />
+
</g>
+
<g id="man" fill="none" stroke="blue">
+
<circle cx="85" cy="56" r="10" />
+
<path d="M85,66 L85,80" />
+
<path d="M76,104 L85,80 L94,104" />
+
<path d="M76,70 L85,76 L94,70" />
+
</g>
+
<g id="woman" fill="none" stroke="red">
+
<circle cx="110" cy="56" r="10" />
+
<path d="M110,66 L110,80 L100,90 L120,90 L110,80" />
+
<path d="M104,104 L108,90" />
+
<path d="M112,90 L116,104" />
+
<path d="M101,70 L110,76 L119,70" />
+
</g>
+
</svg>
+7
docs/img/06_imag.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="200" viewBox="0 0 200 200">
+
<defs>
+
</defs>
+
<image x="0" y="0" width="200" height="200" xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAZAAAADICAYAAADGFbfiAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOydd3iTZduHzzTpbmlp2XvLBgEHigxxMRQUBFERFyoOcA8EnLwKTnCAiPqpiKAiKoKoqCBL9t4UKKtldM/s748raZN00JHZ3udx5Eiefbdpn99zX1ODnxN3g9Xq6zEEMqnLNRpfj0GhUAQcIYAVMJa2k847Y1EoFAqFB4kFIoBIoIbtFWlbFwtE2ZYjbcv2z9FAjMOxMbZ1OqA9sK+0iyoBUSgUCu8TDtS0vcIclsNK2VbSvnUArZvHlwTsv9BOSkAUCoWiZDQ4P7FHUfmn/SB3DzI6GiIi5BUTA5GRhcuxsYWfo6KgRg0ID5d9atSQdeHhsv2XX+DllwFYiZiwSkUJiEKhqGqU9wm+tH09csMPDZUbe3h44efYWAgLk5fj8oX2rVULdG66k2/dWvDx77LsrwREoVD4kuJu5uUx4zguxyPOX7cSGlq2G31YmDz9l7ZvzZqyzR+xWmHduoLFf8pyjBIQhUJRVsKpvL3ecVssYiJyK443b8ebeWlP9yXtW7s2aN3tXfBT9u6F8+cBOAEklOUYJSAKRdWlLDf6sopALSDY3QMs79N9aaLgz0/3gcDq1QUfy2S+AiUgCoW/4Pp0X9nonJqeGGRJT+yuN/PSnu7t22vUgCC3excUFWXNmoKPZTJfgRIQhaKiuMuMEw7UxgP/i8U5X8vzdO+4PS4OQtzuXVD4C2azk/9jZVmPUwKiqA5c6Om+Ik/7bsXVlFPa072ro7a4fWNiQNUgUJSVXbsgPR0Q30diWY9TAqLwR/w9yapMN/qyPt3Hx0Ow270LCkXZcfB/lNl8BUpAFJWnvE/3pYlCHOB2N+iFHLWlPd0Xt29srLtHqFD4FiUgirKikqwUCkUBJhNs2FCwuLI8x6p/rapPAirJSqFQlMC2bZCVBUjtq9PlOVYJSNWnheOCSrJSKBSOVNR8BUpAqjzr1qmne4VCUTJKQBQl0ratr0egUCj8FYMBNm0CpPLuqvIe7ykBcWeSlUJRLtq2TeLcubpO66KjM2nXbjcvvjiJXr1WuvV68fEWHn74XV577Wm3nleh8DSbN0NuLgC7gbPlPd7dAhIC6N18ToWiXFitQdSqdZa77poLQH5+GEePtuKPPwZxyy1/8t9/7WjR4rDbrtemzT7q1DlT4eOvu249OTlRrF3byW1j8sQ5FVWPitS/csTdAmKIiMAaEoKmRo3CJibR0UUbnkRESEOTyMjC5fDwwn0jI2W5+zg3j1BRLWjU6AQvvjjJad2cOY/x/PMz+eOPQTz00Ay3XWv9+g5uO5dC4U0c6l+trMjxbjdhnTzJbkA99ij8josu2guA2Vz4Z5+TE8WsWY/z99/Xc/jwRXTvvoHevf/mgQdmotWaAThwoD3z5t3LkiXDMBqD6dFjA9OmPUa9ehLxOGLEMm688UdGj56L0RjM1Kmv88svw0lPr0n//ssZMWIe1167rNgxjR69mH37OmI2axk8eBWzZ4+mUaPjLFw4mq++GsuRI61o334Xd975OTffvBCAV155k02bejJhwrSC8y5bNoRPPpnAwIE/sWZNv2LPqVA4oteLCQuwUAH/B3ggCQxQf6kKv8Js1nLwYDvef/95AG666YeCbS+88D7/+99rGAwhjBz5FWfP1uPFF99lxoznAEhPr8ngwatYtGgUAwf+TPv2u/jtt5sYNuz3gnOsWDGAAwfaAfDAA98wc+azNG6cyMCBP7NixQBGjVrCpk09ix1bkyZHCQvLJyTEQPPmhwkJMfDuuxMZN+4rDh5sx7XXLiM5uQH33beAWbMeB2DEiHls3nw5jz8+h+zsaNLS4njiiU/YvbsLQ4d+X+w5FQpX/vtPRATYBqRV5ByecKIrAVH4nG3belC/fh4gMw6TSf7UH3jgAxo3LqwV98MPtzNkyPd88cUIADIzY2jf/lTBDX/z5stJSanFSy89z4QJ0wD44ouHmDbtJU6ebOL0ZL9166X8/POtDB68mK++usV2vZn07buVxYtHcskl64uMc+rUJ9m0qSc5OVF88MF9JCU15O23J9Gly1aWL7+S0NB88vPDue669bzzziTuv/8j2rXbzbPPvsLrr0/l1VffIDc3knPn6vLpp7dTt25SkXMqFMVRkfLtrnhCQE544JwKRbmoUye5wIlusQRx4kRTVq/ux5w5j9Ghw05Gj5ZtBw/WJTjYyIkTTUlMbM6WLZdhNIYUCE7t2uIc//jjJ9HpTFx77TLuuWc299wzu8g116zpC8Btt31ZsK5z520sXDiImjVTyzTutWv7kJ8fTp8+Kzh5snHB+ksvXcfnn49j795OdOmylfHjp7N06c3MnfsIAEOGfM+wYd+W87ekqM5UJv/DjpqBKKokDRueZOLEyU7rUlPj6dVrJ1988VCBgCxbNoSXXprOmTP1AQn3NZsL0+u7dNnK1KlPMH36S0ye/DaTJ79Ns2ZHuOee2Tz22FtO509MbA5A27Z7nNaX5P8ojiNHWgEwc+azzJz5bJHt6enSJ0qnM/Hss68watQSAKZMeaHM11AocnKkhAlgAtaUvnfJKB+IotoQF5dC+/a72L69O+npNUlObsD48Z8RFpbP3Lmj2LKlFUeP1qRu3SSn48aNe58DB+ry889XM378dPLzw3jppeksXTrUab/wcAmoP3++jtP63bu7FAjDhYiOlqJEkydPZNWqi4u8evSQqncWSxDvvVcoGu+8M6nY8ykUxfHff2A0ArAZyKzoedwuIBqNEhCFf3LuXF02bepJx447iI1NY+nSoRgMIUyYMI1bbllA8+YJnDrVmKSkhgXHfPnlA3TvfpiMjFiuuuofXn75OWbNGgPAoUPOaf5t20qU19q1fQrW7dvXkT59tjFnzvgyjbFNm30AnDjRlE6dthe8fvzxNu6++wcMBqmHOWvWE2zceAXjx0+nV6+VzJ9/N7//PrjivxxFtcId5ivwgAkrNpZTaWmYPHFuhaKsnDzZmFdeebNg+ezZeqxYcQNZWTUYM2YOAL17S+7UL78Mo2PHHSQmNueNN14FRGxOn25E375/8uSTs3nggfmMHfsBDRqcZO7cR9BqzQwd+p3TNYcN+5apU1/jgw+eoXHjRIKDjQWRX/YQ3OKIiUln166uLF48kmuvXUbHjjtYsOAuQkIMXHvtMn766VYWLryL/v2XU7NmKocOteX111+nWbMjPP/8y5w+3ZBevXby+ONzWL++A7GxaU7nvOGGJQWzI4UC3CcgHml6mZpKItDEHedqdbvVHaepthyeX/36ml50UXKRUiYxMem0a7eb++//iFtuWVCw/vnnZ/Lll2PR68MIDjYyZswcwsNz+eCDZxg+fD5z5tzB1KmvM3v2BHJyogAICrIwYcI0Jk+eCEBcnJVHHnmH1157mh07unH33T8U+EM6d97G/fd/xJ13flbieL///g6efvpjsrJq8N9/7dFqTdx//wJ27OhWsE/v3n/z6aejqF37LNdfv45Nm3qyaNH19Ov3BwAffvg0U6a8xR13fMEHH9xb5Jz2mY1CkZkJLVuC2YwBaeKWU9FzeUpAVgO93HEuJSCVozoKSHnJzIxh//4OdOq0veBJ/cSJpkRFZRVET2VmxrBhg4TVtm59gPr1T5V4PqtVw5EjrQgONtKkybEyjSE/P5z09JoFyYkWSxAJCW04fbohjRsnVqj0ius5FQqA5cvh9tsBWA30rsy5PCUg3wC3u+NcSkAqhxIQRVVl7lx5ku7Xz9cjCSxefBFmzQLgVeClypzLE1FYoCKxFApFCVgs8Ntv8OijsKpCBTSEyZNhwQLndb/9Bjt2VG58VR13+T/AcwKikgkVCkWxZGbCHXfA/Pnw/fcVO0dqqpThqFfPef1jj8FLDs/UBw9Cjx6wrOypOFWatDTYK8GC+cB/lT2fmoEoFAqPkFlCdoHJVPj5t9+cl//5Bx5+GE47uG2SkuCSS+AzhziE5GR5twvIyZOwZIkIS+fOhfvt3w+nTkl1b4WUL7FYAFiHiEilUAKiUCjcyubNMGiQ+CeWLCm63S4YLVvKE/G6dYXbDh8Ws9QZh/YqOh0kJMBZh3ZHdgGpLwUEWLwYxkh6Dj/+CB99JJ9vugmOHIFebgnpCXzcab4CzwlI4oV3USgUVZGwMFi/HsxmGD8eTrgYtO0CctNN8r50aeG2iAh5z3EILLXPHrKzC9e5zkAefRTGjpXP11wD8fFi4rriCvj2W9AWVqcpltOnC57MqzSVbSDlikcEJC6ODCDDE+dWKBT+TceO0KyZfNbr4b77nM1U9s9du0KTJvDrr2C1BVtGSaqNk4CEh4NGU9B6FSgUkLq2dB+NBo4dk+Pfew9uu03KdezfL32/L8Stt8KNN5b3Jw0szp0TnxCQi5QwqTSemoGAMmMpFNWWQYPkfcQIMWlNnVq4zS4gOp3sl5RUUNivYAaS65I4HxRUvIDYTVgg0VedOomYAPz1l7z371/6WFetgn37nMOBly6FG24Q81dVYfXqAqH+F3BLkxglIAqFwu0MtpXlqlEDbrkFZs6Ev21GE7uABAcX7mf3lRRnwjp/XsxhjuuSk6UVdliYLJ85Iz6Srl0L9/n7b2jUCFq3Ln2ss2ZBaCjcfXfhunXrZPZSq1aZf2S/x93+D1AColAoPMAll0CdOmKeeu89MWmNGyc3eVsVWHQ6uOwyqF1b9oNCn8auA3BYC//p4C3b7S4xD1YFw3YtJCZDXYcQXnvuhz0C68wZCVe1zyoeekiEwtERD+Kc//NPGD68UCyysmTGtHGjCGBVwR0NpFzxpICoXBCFopoSFAQDB4pf4vhxyRrPyIAHH3QWkFQtdB4kN/LBx2FYN9DUg09nw6VPwMBJMPdpIAj25MPNUXB1Ddh1Fg42hvYxMDga3j1qO2dHMFM42+nfX2z/f/whGdgdOohYZEnVfObMEbPOQw8Vjn3oUCn1Uce5Kn9Ak5wsv2PEN73VXedVMxCFQuER7OapX3+Fiy+WBL9Vq2CirQ/Xg7HQJhb+GinL65bA8SCwfgM0BT4HfgJeAyYDVzicPAloAMlBsE4HG20zhbGvQ7MUeO1fCNJCs34yw9m/H776SkQtORmioyVPZf58uOoqERaAFSvEH9OunWd/N97GIeP/X0Rj3YInS64rAVEoqjFXXSUmoF9/hf4vwpGnIHQ9bLSZq5JCbDteDdwGdHdYTkBihcIo/jF3BxDqsHw3cADYCDlayPkLuAT6NoGLzDDECLcOgS8HF4brzpsnfhXH2cf06eKHefhhWd65Ez78EP73v8D2h3jCfAUeFBCNhuNWVQdRoai2WIOh7QDYuBCuOwu0BP4P6ApkA7G2HUMAl3bu4WaI00BsFtQ0gtYCFg1k6+SV1gJSQ6AgdSMCmGH7bABeBGwhvge0MF0L08PgYhPcYYBheWK+at4crr9e9lu5UiLGHntM8kgAXnhBclq6doW4OLjuOnkPNDzhQAcPVeMFsFrRpaWRRyVFSlXjrRyqGq/C22RrYHYozA2Fs4uB4cBbwNO2HZKBeCAYdBZolQ1ts+CiTHmvlw+hZTCymDRwLhSORUJCFByMht2xkB584WPDFkH+cHhyGkyyJSAOHCjO+O3bxey1eLHksAQHS25LQgLk50tE2YgRFfnN+IbERDEhAqlAbRx0t7J4cgZiSk3lNG5qLKVQKPwbPfB5KLwXDuftzy03AM8A1xXuF1ULeqbAVefgkhQIreDtTGeF+vny6pki66zA8UjYXBPW14KdsSI0ruTPBGrA++Ngfxj0+0MSDx9+WMQjPx+mTJHZxtKlcNFFEgRw882S9X799RJGHAg4mK9W4kbxAM+3nT2OEhCFokpjARaGwBvhcNLVXxEJTAeNFXqehxtPQ/c0mXl4Ag3QNEdew05Cjg5W14IV9WBbLFg1iNLFAWPBEg3LgGVvQ1AY9H5CzjNjhhRh/OwzEQ8QwejVS2YoZ84EjoB4ynwF3hEQhUJRRdmthaciYFMJd5JIE9yQBDefggZ53h1bwfWT5XU+FJbWh18bQMpih52yAT1YHoDbWkHfI7B+Jlx5pcw47JhMEhDQpo287Bw5IoLSo4eYu/wNJSAKhcKvyNbIjOPTUDAVsz3CBLeekFeE24JGK0ctPYw5BnckwtrasKAxHKgBRCHFzW35KSsnAgaIeQ/OBkEd22zps88kr2X6dFlOShKTlz1ENiYGRo6UJMQLFW/0FgkJMk7gLLDX3ef3tICoZEKFooqxIhgmREBSMeG1IRa46ZTcpGOM3h9bWdBZoc9ZeW2tCfObyjvBQCawARgLyy6B1VZ4Kh9GnoZp08ScdffdktE+cKAkST74oDjb//oLXn5ZEhOnTfPlT1jIv/8WfPwHcRG5FTUDUSgUZSJLA5PCYV5o8XeiXufg0cNQp9JtijzDmjVSbNHRd9EtTV47YmFuC9gTA+yjYDaSpYGXw+G9tyEjHT7/XDLo33hDopvi46UgZKtW8jIYZAby0kuFdb18iSfNV+DZTHRQAqJQVAlW66BXDfi6GPGonwdv7IRXd/uveKSkwKuvwvvvF7+9Szp8sBWm7oSmZiDaYeNOyPgUGAKLBsLRdOkx0qMHDBggpU8mTZLS9U2aiIgcOuSFH+oCWK2wdm3Bolv6f7ji6RmIaiylUAQwJsTXMSOsaPyn1gqjjsMdxyoeiusNPvxQypeYTDBkSOn79kyBS1NhSUP4ohlkBSOK2RN4B74JhWVZIhK33ipNrAYOhAkTpP5WXJxU9m3b1vM/14U4cEDqgAGnAY9ImkdnIKqxlEIRuJwIkkKF7xUjHk1z4MMtcO8R/xYPk0mcyPa2udu2FRZzLAmtFYaehHkb4MZToOkMrEYy6YG0GEADS2pDjkb6hqxdKyasdevgrrtERHyNg//jL09dw9MmLFBmLIUi4FgaDH1rwEYXG4UGGHwaZm+Bi7J8MrRyodNB377yuUcP2LpV1lmtF+5UGG2EJw7CzG3Q3KEXCU2Ba2HNC9B9A6zTSCjvc8/BJ5/AxIke+mHKiafqXzni8ToXqan8Cgyq6PGqlEnlqM6lTN58U24el1/u65EEDnqbo/yzYp6ga+lh4l7omu79cVWGceOk5/l330FeHsyeLU/nJhO0by8RVJ06lX4OUxAsaAJfNZXPpAM3AmuQOly50KIlrFpZ2MPdl1gsEjGWIhn6zYFjnriOmoEoqiTLl0u8/uDBElpZlr7Y1Z3DWrguunjx6J4KszcHnnjs3Su+gAEDpKvho49Kb5D+/cVvYTbD00/Dli2ln0dngTuPye+ghb0Q5GrENf0q8C3U2ALJ0aWdxXvs3l0gHol4SDzA8050ULkgbsdqysKccwBL7kHM2fsx5x7Gqk/CYkzBakjBaskDiwGrOYe4OAknDAmR9p9xcfKqWxdatpR2ny1biv02KsrXP1nlydXA95nwvwnyJDh0KHzwgfR5mD1biuIpivJNCDwXIb8/R3QWeOAIDDvhBXOFB1i8WHqkDxkizvTTp2VW+tRTsv366+GRR6RXSPfupZ4KgBY58NEW+KQV/NwQrP0AW9fD7cBAC2zPhHAfG04czFce83+AdwREzUAqg9WIKX0jxtS/MaX+izl7Lxb96XKdIjdXXiDRKCVRv75Me6+4Qno5dOvmn6UZSuOZCPj2PuAcvDoDHh0tPbkffRSuuUZEZOhQX4/Sf8jWSCmS70OKbquXD5P2QPtM74/LHaSlSZZ4z57Sl+Svv6SR1KpVMH68RFB16iQRU7//Lsds2CAl3e+7r7DfuiuhFhh/EK48D2+2hRSHGdvLeb4XD/B8/ocdJSB+iDlzG8aUPzGm/I0pbQ1Wc86FD3IDSUnyWrlSliMj5Z/vqqukt7S/P73PD4FvFwA/AoPg3YdAewB61oSPPhJTxf33ixO1USNfj9b3HIyG1zvAyWLE4yYDzMiHmBbeH5e7+O038XPce6/kaBiN0t+jf394/XUxYfXvL+VJGjeWnh+pqbLP4MEXDvntCgzNg8eDJOjgdgOM8gNTqdkslYVtrPTktTzuA9FolICUBYv+NPmJM8hYdzEZ67qRe+A5jOd/95p4FEdOjph+XnoJevcWZ/S0aVK+wd/I08BL54DxthXjIT0EJnWCmW0gPA6eeUaciw7hjdUSK/BDY3i0G5wMd94WYYUPcuD/ciDGD56kK0Pt2vKwMGUKZGfLujZtZNaxcCEsWyYz84SEwllpiE1MS2uG5+hPi7fC19nwaQ5Mz/XMz1FeduyQ0vPAQeCkJ6/l8RlIbCyn0tIweeNagYbVnIvhzCIMp77CmPo3WMsWUB+ChKS3BdoAFyGRhbWQPj0RSLdPeyWFXKSCdQ6QYnsdQ/66DgD7gSNII7fSOHhQBOTtt2VWctttcNNNJU/1vUmYBVqOgZQMpGXOjcCrYH0GfmootY7624Qj0Mxy7iQjGKa3g/XxRbddZIbPc6CdnxQ/rCw9eohI/PGHzKDj4sTX0b+/5Gm0by+RemfPQufOcow9f8NqlfWffy79QCZNEn/JqlViDp0/3zlya5gfzDzseMt8BV7yi6WmkkgF+4JUxTBeqymD/OMfkX/sfayGcxfcvyHSJrofcCXQAversQlpQ70W+av7G0lfvRC1a0tP6fvvF/uyr5g9W+Lvh4+ARjNhxnNg/RLoBowDagIPgjYLvvkW6tT03Vh9xfZY+F97KWvuyn16eD0PQqvev1sBP/0kIb3x8XDJJeLvOHdOBMbWsY9t20RgOnWS6C2DQWbenTtLMMrChbLf2rUQG1vytXzJ8OGSFY90ml/oyWt5S0BWA70qcmxVEhCr4Tz5ie+Tf/wjrMaS4yFDgAG2Vz9kluELDiBisgxYTkF9uWKJiYEHHpDKpN7uGX3wIPTpA7VqSfRJTAxs08Edf0Dyc4gygjQRmg2NBsMTB+DiNO+O01cYguDL5rCwsfQVd6SGFd7LhZv96Anak+zZA59+KuG9DRvKw89ll8HJk/DFF/D113D+vDwMjRwJ99wD7drBokWyr9kszaZGj/b1T1I8RqP0ec/NxQo0QBoIewxvCcg3wO0VObYqCIjVlElewmvoj88q1adxKTAaGIWYovyJc8AC4Ctgcyn7RUZKBMvTT3svLHjoUJm2//ijCImdHA28GA5fbUE6IQxDZiLIH/7A0zD2CNTw07Lj7mB/DXizHRwvpjLsZSax3Tfy41Iknuaff2DuXJmFWCwy21i/XpzsDz9cuN/ChTJ7qVVLZiU7d0pkl7+xYYPkvAB7AI+HvXgjkRCqcSSWIelbMla3Jf/o28WKRyzwHFJBegPwKP4nHiBuhceATci9+FmguI6eOTkwc6Y81S1eXMwOHmDmTHjrLWfxAIi0wvu5MK8z1L6PAvEAsL4LS9vCLXfBhM/g1Jmi583OvnDdJH9Fr4VPW8Bj3YqKRxDS42JJVvUWDxAT1rZt4s9buxa+/FLW6/WF+xw/Ds8+Kz6THTtETPxRPMC7/g/w3gzkYeCjihwbqDMQc+4hcvc+hvH878VurwU8AjyOiEggkgV8DkwDkkrYp1cvubnb+0r7ijQNvBQu1VSt54AeSPRBH+BL0ObAYx/BTQ6q+N57Uhzv88/lRrN1qxTO8/eEy/Xx8GEbSComuKGJBT7MgV7FtRFUkJYmibXPPScviwVuvFG++xUroEMHX4+wdIYOLYgyHIYEtHsUNQNxN1YjeYcmk7GmY7Hi0Qh4H6kv8DKBKx4gLRMmIHWi30UMrq6sWSOZv2++KTH5vqKmFWbmylN36zjEwbMMeBHYCOa68P4j8sT+w2FJLFu+XOzJ0dGwZAl8/DFk+nFS3ZkwmNIRXuxcVDw0wBg9rMlU4lEaQbY7on0GMnOmmLQmTfJ/8dDrYeNGQIoneyVYXQmIG7HknyBzYz/yEl4Hi7NXMhgxVR1Cbrp+0KzMbUQCTwCHgZcA1wdfvV7qUl1/vXRx8xVGIyx4GJJioU43CHkGEZJYoB2QDHt08PEBCVc2GiVL2WgUW3mHDtCgOJX0Arml5BikB8NHreCuy2BN7aLbG1jg+2xxlkcF5oTea0RFwZgx4udISpLOg717O/tD/JVNmyBfGnrtBM5745reEpAq31jKeHYJGWu7YkpbW2RbP+QbfZOiN9eqRDgyq9oF3FDM9m3bxE+xZIlXh1XAhx/CvHliohjeD+ovQYSjBxLsOBBRw+eRHyYO5n0D05fLzOO663wz7p9+gptvhjMufpocHfxfc7izJyxqDEaX/2Yd8HA+/JcJVweoL8fbaLViunz+efjzT3l4GDtW6mn5Ow71rzzSfbA4vCIgVbqxlMVA7v4nydo6BKsx1WlTI+B75Nv0gwZlXqMV8BtyT27osi0zE+6+GyZP9r6D+r//JFFsxQqJstm6EX5fDnWSbTeI6bYd3wfygPnAEfjL9vizPB2enSJhoOe98nwnNG8uv6ulS8UnczwEPmwNI6+Ar5pBrrboMZea4O9Mye1Qs47yExUl0UyNGsksJBBwqLDgFQc6eG8GAlXQjGU1ppG5qT/5x97DtVP0EGAHMNwXA/MTRiC/g8Eu661WqU11yy0FJRe8whVXiGnip59kWaOBo0fh7CkYey/83giuTAE+RGYl1yOhZktl/337YXMcLFgEd90P+0+VfK3jxyWi51Qp+5SVyEgpsTFvHkyaDPcAPzYqXjgaW+CjHPgtCzpWkYxyX1G7tvg//u//fD2SC5OXJ45+wIx0KfEKSkAqiEWfRObGfpjSnL8rHeIH+BHJW6vuxAO/IA/1rjX71q6Vp7zT5SsuXGHGjxfRGjsWunSR8hYPPww1a4rJ4hIT9H0PyIAez9v+Ob5D6sA8BawDfgbrH5CfCY9ug6e7ivnoWKTzI8Tu3SIgZ89WfLwHjsOYJ+HxN8FgF4t5YL2y6L61rfC/XNiYIQX9AsDiEhBERkqrA3/nv/8KanRtRdpdeQVv1qeqMgJiyT1C5ubrsOQmOK1vgiTb9fTJqPwXDRI4cCUwEpFSpwYAACAASURBVKm7ZWf/fhg4UDJ9W7b08Dg0Yn568UUxBWVnS1z/I49IWQp7t7p27eD3fnA4E276Es7WBOtLDieqJ2+WWKmxtdWWXxJjhI4ZEP4LJG2XdXXKWPX33w2w7C/QtoA6U2B/NBz6ASzbkefJBkgBtBU4peTWtcBYPTyol7wXRfXEIf/Da/4P8K6AVInGUqaMTWRtGVSkhlUfYDFOuWoKF3ogiYhDkWZudo4fFxFZuFBKanuaZs3kpddL+YolS+DJJyWLNyVFqrdqNBCcAGfWw133QRctzDfBFh2F/6JdnM+bEQxrawFzgfWybvRoiPkJal8FkSbI/gVSF4HhOIRcDLr7IesyyG8LfIMIRDDwNvAtUgDIPuPoizjVPoBuofCQXsquF1ONXVHN8HYCoR1lwioHpoxNZG3qX0Q8bkZqRSnxuDBxwO+Ij8iRc+ek/8L27d4bi92hPneuLNsjbb79VoTEXjjvzpFwjx7+zIJNmdDgSwiKBq4t4cTrkOiuVsBsyLgYDkfBjpmQMAbSVkFOc0j7Dc71h/xlQH1gFXA5knLbE0gDHio8bcwYIBuemQcrsmC4Eg8FMpPeuROQmqjrvHltJSBlxJx7mOwtN2I1ZTmtH4OYyatyeK67CQcWAQ+4rM/KgltvhcOHvTeWyMhC01mfPjBnjhTZi42F77+XbT16FO6vOQSnN8Com2CrQfwO1xtdemdYEDvdxYjHux6SJPM6Mos4gTjJtiFPHS/YjotDZiDXIv1RtdDsBhiXL07xXdfIeNfP89AvQxGQrFtXENG4ASkQ4TW8JiCB3FjKoj9N1qZrsRicA/GfA75ANTqpCFpgNhJw4EhKioiIa86Dtxg+XPwkRqOU9R471nn7d9/J+4gR0MwiZqRvsyEhHf7NhBm5MOowoIeoVg7/YEuRcsbDkH/xRCAbMU/tgZDTUmbkuhAYPs52jBnqDoJnk6XwYVSElKpYuxbeeadwhqSo3vjKfAVeFJDYWE4hU6yAwmrKIGvzQCx5x5zWT0ISA1W0S8XRIImHE13WJyZKtFS612JJihIWJtnoD7hMk777TmYovVyaEwQhYbOj9TB8t6yb1ghOp8GODBh2wLbjY0hyTDOgNfCDrP7zMGzPgAXZkP+5mNfGjBG/zI03iokPpKhfdDRMnVoYjqyo3jgkEHpdQLz28KzRYEpN5TQVbCzlEywGsrYMxpy1w2n1WOBV34yoSvI6cAb4zGHdvn3igP7xR//pIGg2w+OPS7ZyaZnJCbbgvFatxEfR2ALNI2Xd1KnSZ16nk59Lp5NXPVtk15kzUoNr4EDJiK5dWzpADhggv4smTSQ3IT1dosUU1ZuMDAkZR4LN13v7+t62vhwngAQk9+DzRfI8bgI+Rs083IkG+AQJXl/ksH7tWskYf+UV34zLFa0W7rrrwvsl2UoT16lTuK59e3k/dco50uyhh8SRv2ePLM+bJ0UnR46U5YkTpUHXiROSL9OkCdSvLy+FYs0aebBBxCPP29f3hYAEBMZzS8k/9r7Tuj5IeQ7l83A/WuBr4CzOIb4ffii9RQYO9M24KoJ9NjFihIQJt28PgwZJYcbPP5eCd717wzffSL2lMWMKe3H/9ZeYrK65pvB8Dz1U9BoKBfjWfAVefpBOTeUNpFRdmfFFPxBLXiIZ67o51bZqDmxBhep6mlQkeMnxSSMuDlatEt9DIGAyiSN+3z4pA26fiRw9Kl3tbCW3CQ6Wmca0aRAe7rvxKgKXXr2kPS/QG+dnL6/gbQEpd2MprwuI1UTmxr5OVXWDkRB9lWHuHTYCVwGOBfF79JBigv7iD6kMZ8+KmatZM+nfrlBUhPPnpVGb1UouEgSuv9Ax7sabeSAQACasvMOvFCnJPh0lHt7kUsSx7sjmzfDuu74YjfupU0dqcSnxUFSGtWulMCmwFh+IBygBccKce4i8o285rRuM1HFSeJenKZqt/v773k0yVCj8GV/mf9jxtoD4dWOp3D3jwFIo5I2Ar1ARV75Ag4T1OjYA1Oulaq5CoXDq/+HVAoqOeFVA/LmxlCFpPsaUv5zWvY9ymvuSeKSmoCN//w2//OKL0SgU/sOZMwWz8SykhLtP8PYMBPzQjGU1ZZK7/xmnddchVScUvmUU0N9l3XPPSd0shaK64jD7WI0UyfEJSkCAvMOvYtEXdjUKo5yhYgqP8iHOVWfPnJEsbYWiuuIP/g9QAoLVmIL+xCdO655DKnEr/IO2SENAR+bMkcKLCkV1xCGB0Gf+D/CNgPhVY6n8Y+9hNWcXLDeinJmOCq8wCWmZYSc3t7CPh0JRnTh1Co4dA6T6z45Sd/Yw1XoGYjVlkn/c2Vj1DKq3hz8SATzpsm7WLMjM9MVoFArfsWpVwceVgNlnA6GaC0h+4gdYjYU1w+OB+3w3HMUFGAfUdljOzJRaUwpFdcLX9a8c8XpdQI2G41bvl7cqgtWcS37iDKd1TwGRvhmOogxEAuOByQ7rPv4YHnxQ+ncoFAUYQXsAtAkQdAi0hyHoGGgyQZNre7dZrq1RYK0B1giwxoClKZhbg6UVmFuBuQ1Sz8hPWFtYKMPnAuL1HDmrFV1aGnmUUbw8VQtLf+orcnaNKViOAY4BsR65msJdZCC9mBx7TX3yiXQxVFRjzKDbDrp/QbcadBtA46bi5tZwMF0OpqvA1BtMXZDy0T7gyJGCFsspQB2kgbLP8MUMxC8aSxlOf+20/BBKPAKBGKShl2PBmQULlIBUV3RbIGQhhPwImsLi2Vg0sL827KgLu+tAQhwcj4HkKEgLg4ww2QdAa4EaeojPgzo50DQdWqRBx7PQNRnapEDwP/ICsNYCwy1gGAmmi73787pEX/lUPMBHVTpSU1kN9LrgjnhmBmLJP0X6qqZgLfQ/7UPCRRX+z16gg8NyUBDs2qWaLFUXNJkQ+gWEfCOmKTsH42FpG/irOaxpIiLhDmLy4arjcPVRGHRQBMWOuTUY7gD93WIG8zRjx8Ii6br2MDDL81csHV8JyDfA7WXZ1xMCkn/kTXIPvlCwfCmwwe1XUXiS7jjXb3j1VXj0UV+NRuENNCkQNhdCPwGNzYZ5LBa+7gILOsLe2i4HZDSB0z3gXHs4fxGkN4OcupBbC/JjwGqLIdJYICwdIs5D5FmoeRTiD0Kd3VB/K8Q4x/10PAu37YbRO6CJrTCTNUqEJP9xsNT13O+gfXtITgagHbDfc1cqG74SkHI3lnInV14pzX7sfACoe09g8T7whMNy27awbp2vRqPwJJpsCHsLQueKX8MK/N4KZl4m73ZTFLnxcHgAHL4BjvaDrAalnbbs1DgFzf6BVr9D62UQLrayICvccBjGb4DrDsvN1BoB+rGQ/zRY3RyRc/AgXH45AEk41xn1Gb4SkHI3lnIXO3dC376FyyHAKaCWLwajqDBngYaAyWHd6tXQoUMJBygCkpCfIPxFCEoSofihPbzeG3bZn/JNYbB3OOy8E470B4uDWzc0BeI2Qc2dUGM/RB6F8CQIOwfBmaCx/fVYdWCIAX0tyKsP2S0g6yJI6wKpPUAfX3jOICO0XAGd50G7H0GXD0CXZJiyCm7eJzfV3PdBf5d7fxeffQbPSMm++cAd7j17xfBVe2+f5YKsXOm8PAAlHoFIHeB6YKnDuj/+UAJSVQhKhIgnIHilLP/THJ66DrbZ/VyZjWDDeNh6L+TZbvBBBqj/BzRYCvVWQMzesl1MYxKxCU2BGgeg7krHjZDRHpL7w6nBcLYvHBogr/AU6D4XLpvJjnqnGTYSLjkFnx6EJh64vftL/StHfDUD6YyPUvCHD5eS4HZmAw/6YiCKSjMH5+/uiivg1199NRqFuwhZAhGPibM8OQoevwEWdrRtzGgM/06C7XeD2VZiM34jtPwMmvwAIYWhWGEmaJkqEVVNMqF+FsTnQoweIgygtblXzRrICRGne0o4JEfD8RpwpCYcjgO942O2IQ4SR8CReyHlElmn1UO3z6D3VCLCTrP5Sqh3uXt/J1artK89fx6QUn0J7r1CxfCVgMTgHMrvFYxGaN5c6ijZOQC08fZAFG7hONDUYVmng4QEiI721YgUlUIPEVMg9FNZ/LYTPDoQUsMBQySsngjrnwBTOGjM0OR7aPsuxG8qOEWzdLjsJHRPgjbnC0WiopiC4FA8bK4PGxpBomOsf8qlsO8pODEMrFoIzmX00EHM+GRl5S5aDHv2wFVXAVJL0KcpEI74rNleairpSFi/19iwAQYMKFxuhJ9VdlSUmw5IWK+dRYugXz9fjUZRUTTnIGoU6LZCdgg8PEiiqwA4NBB+nSVRVVih6ULoPAWiDwGSw3FNAlxzFBo7tqvTgLUOmBuBNR4stcFaEwgDaxhYbRMYjQE0+UA+BKWC5ry8tCdlXDiI0PEYWNFCXlmhtpWZ7WDnq2hTLiHhz3bUaOumDEYHZs+GiRMB+BK42+0XqCC+8oGAPEB28uYFHZqwAKDuM4FPL5wFZMMGJSCBRlAiRA+HoAR52h96my0k1xAJy9+HrffLjnGb4ZJHIV6C7utnwbB90O8ohNhSuqxhYO4AltZgblG2SChruLwALC65RJps0B6BoMOg3SNhu/dugzt3wd/NYVE7SK6xD3rdyjOaGGrm52E9CpaGODexqST+VP/KkWolIK5hnuo+E/hcifhC7Gzc6KuRKCqCdg9EDYegM7CqGdw8EtLCgbMd4Lsf4Hxb0OZDlxfhohmgMROXB3fuhKuP2ExUGqlXZe4Gpna49a5mjQJTZ6AzcCPo9oF2G4QcghsOycxnRUvY1gJuHy3TH00GaLPB0hisbihvYTY73btWVv6M7sPXAuJVDhxwXr7S2wNQuJ1LXZYPHvTJMBQVQLsHom+UpMCf2sKo4ZCvA/YPhR+/BkMUxO6CK0dBzB60FhiyD0btFgc5Grm5m/p6NnmvgGDb9TqL4OlWgm4X3HAE+g6AWjUd9jVL8UZrPFgaUSlnwa5dkC4e4wQgseJncj++FBCvuh+ys6UVqp0QoIU3B6DwCC2RQqn2ptBJSZCTA5GqrLJfE5QoMw9NumSRj75FHNZsfBR+myFZ4s3mwaUPgi6Xxhnw5HpoZQuyMrcB42CwxJd6GY9hqWurhXU1BJ2AkMYQGV50P02KBGmZm1Hhu61D+K5Puw8WR7WZgRw6JKFwdlri2x9e4R6CgeaAfeJhtUokVufOPhyUolQ052w+jzOwuJ2DeKyaDP+8Clih6wvQ/k0Ark2Ah7ZAiEnKrRsGg7m9T3+EAiy15VWvNFNVttTsMregQn4Rf8z/sFNtBOTwYedlVTix6tCWQgEB+a6VgPgpeom2CkqQgoe3D7OLxxT45xUJz73sfmjxf+gs8OAW8TUAmDqC8RawhpZ6BZ8Qd6F40nwREUvL8o3fZJLAEBurStnVJ/hMQLzdWMpVQC7y3qUVHsb1uzx0yEMXMiL/MT4Lfg98IiZLqO7hOBgyyubz2PhIoXhccQc0XUiYCSauhouTAB0YBkhPDn8lviwJCQaJ5jK3pswzkW3bICsLkILhpys6Pk/hMwGJjeVUWhomb40hwSVvUyUPVh1cBcT1uy4XRgg6BdpEcYLaX9pE2Za5uvTDFSUT8osURMwOkVDd1HDgwE3i88AKl90HTRcSaYCXV0Lb8xKWq79LugT6K9GREFrWjoVGCQs2t6JMdz5/Nl+Bb2cgXm0sdfas87If/z0qyonrd+n6XRehJJHYLy1QnSo0OpD/dGVHWn0JSoSI8fJ53GDYUwcJ1V00T7K4u0yCFl8SZoJXVsJF58EaDfp7vBRhVQnKNPtwJB+0x8DckgvOZpWAlM5xvCQgKSnOy6qAYtXBNRAnNbXoPrp1EPYuaI9K1ExJIlEahpsqMjoFSGFETaaUJ5nXGQnR/W4RGKIl2qrDVLQWeH61g3g8CJaaFzy1z6lVkXoa2RB02pZwWAIGA2ySKi1W4N+S9/QdQT6+vtcc6Wlpzstx3rqwwuOURUBMPcHSHIKOUiHxMLcEc8cL76coSshiqaqbHCW1rQBY/p40eYrdKaG6iMO8e5LNbDUmMMQjKAhqVrAToeacJB2WxObNBXX7diEdDPyOaiMgjgUUAVS9vaqD63fp+l0DoIHc6aC/r2LXMN5cseOqO5psCJ8kn5+4web3ODRQypNo8+DK20GXy7UJMOAQoLP5PAKkPXFsNGgrcRcNOg4Yit/m7+Yr8L2AeC2Z0ODyJbmxTI3Cx7hGRer1JexYCRGxNKBCM5fqTthb0gxqZTNJGMQQCUs/lo1dJkHMHhpnSJ4HgGGgfzvMXamQ+coRs/jjisNf61854msB8doMxGh0XlYCUnVwFRDXhwUnKigiEU9CbBuIHAfByynxqVFRiCYVQj8XA/7T19lWrnkB0ptKYcSLZqC1SIZ5iEnyPEyX+XLE5afcDvRi0GSIf8gRvV5MWIAZP/V/QDUSEIWigAqKiCYdQhZC1O0Q21aJyYUI+xg0OfBDB9jSAOkiuO5JwCpVdTVmhuyX8iTWGEkSDCSCdVDDTSVzgk4BlsLl//4rmElvB9KKPcgP8LWAeK0wWLBLnLb6n686uFqsQsoyvaykT8RJTNpDxAQI/gdl5rKhyYLQz2T28Vpv28p/J0kzqCbfQ/wG4vKkMCKAcZB/ZpiXRnwMaNyVVKqXull2AsF8BT4WkLg4MoBS4hDch+tNRQlI1cFVQELLeiMqg4hYGtrCSWuXcppUCP0aooYpM5ed0C/ENPNba9hVF5l9bLtHss07TwHgjp1SVdfcBkwB2MveHeYrR4LOUjALCQQHOvh+BgJeMmNFRDgvZ3njogqv4Ppdun7XpXIBETGMgtw3IGMvZC0rg5goMxcAIfPk/QO7T+O/CdLDvMl3UOMA9bOg/xFAI1V1AxF3CwhGeRjJyZESJsh8dk3pB/mWaiMgcS6JHynF76YIQM67LMeXt8R3KSJiGGL7oJVaTEpMLoxuixQOTIyFP1oCpjDYdq9sbPcuAMP3SjMoUyfflWSvDBFh8nI3QefE/2EL+tkMZJZ+hG+pNgLielNRAlJ1cP0uXR8WykQxImJuKe1Ri6DEpFRCFsr7153BogH2DoO8OIjfCHGbicmHvseQhlB9fTfOyuD22YcdPWws7Prhd/0/XPEHAfFKLkhtl39uv2rrpagUrk8grt91mXERkTIlDyoxccYkmecAC+2Z+zvvlPeWnwNwta2Hubm1/9e5KokLlm+vBHsKg3b92v8Bvq+FBV6agbRq5bx8oPjdFAHIfpdl1++6XNhEBBzMV2XFJiamy4HXQbcJQn6G4B/FNFHs5WxiErJQ+mcbr5frGq8mIJOVdNslmuhQPOyug8w8jvSHICM0/gGAa47IvuZuvhtnZdBoPDcDycmB5H0QBAYLrPfMVdyHP8xAlIAoKoXrd9m6dSVPaBORYs1XZaWazkx0tuihZfbv4NBAsARDnVUQmkKTdGiSIfWuTAHa1S06EkI89Oi9cydoLFBT/B85nrmK+/C5gGg0SkAUlcP1u6zUDMSOO5tGVSMxsQvIiha2FQnXynuDpQBcflIWzR2QfsQBSHwFiyeWBVv0FU1hQ+l7+gc+F5DYWE7hhfSrVq2ck35KafugCCCMwFGHZY0GWrQoaW8/oCqLiQF0G8Rxvraxbd3Rq+W93goAuiXLoqWys0QfUqu0/ueVxC4gV0kGut/jcwHRaDDhhVaNUVFQ18FhZ0BERBHYHEZExE79+hDppvISHqeKiYn2EGjy4GA8pIUDGY0lgTAkFWL3EGqSXh9owOzPIl8KWm3Fy7dfiKwsOHoUNGB4Bg5Z/cNHXSo+FxAbXjFjtXWxua71xkUVHmWjy/JFgdrsvgqIifawvG+vZ1uR1F3e4zcDVlqmgc4C1jpgDRSRd6FmNAS507zpwPbtYLFANGxvKN9ieVJifYK/KJxXBKRnT1i5snD5H+Beb1xY4TFc03QvvbSSJ9RL+fHieqJrUiBzoxdqNgVoNFfQIXnfaxe9s7Y43tgdALS0Nfoyl9KFz9/xWP4HhearOuJAh6KFpv2OaiUgffrAG28ULvt9kLXigrgKyGUXKgdukFaiBQKRDJrkQpEISkQqABaD/g4fFPwLIDHR2gTkkD1pN6WNvNeQQOvGtpxqa0XzdPwAbwhIl0IB8UCuu3vxFwHxSjLhxReLfTzHFhx3CongCVSrR3UnEecckOBg6NGj+H212yFqtIhHSQJxIYzDKnac2/BzMQmyPQYet99k05vJe5QkftS3FS2z1HLvdb1FSDBEe8iolJ4Ox49DEOQ+AHttq/1eQKqVDyQ4GC6/3HmdmoUELstdli+9VIIlisPcFfImUuHwXEsdMF5VsWM9gh/6TOz9vZPt30GWrS9thMTI1LK1GrYGQK/z4nBr+XYXtm0Dq1X8H/GFAaJ+H+hcrQQEoHdv5+Vl3rqwwu384rLcv3/p+xtGQe4MKiQixlsAbfmP8wp+IiaabHlPsz8359lsWaFS7jLGXnc/vOLX8CXeMF/VKzRfgf/cn0vEXwbotdJU/fo5Ly8HSpj9K/yYM8AfLuuuv/7Cx+nvkBtteTG3xqljnN/iKCZ7IHsR6EeDtZQCk45iEjaz4pe2C0iO3TRmsIVa6cRmHGZ7rg60xlF2PCkg221ZH92cBcRfH1kK8AsB8WZjqY4doX37wmUjsMAbF1a4lfk4J4J26gTt2pXtWP0DkDu1fNeLeApiOkHEC6D7r3zH+gwdGPvJrCv9QNlmJsYbK345TY64lwxawKoBczBghSADGivozLKfNQBrfEWGQ7iHhC8lBU6eBC1kj3N26ykBKQdeM2Pdeqvz8tfeurDCbbh+ZyNHlu94/TjIe6F8xwQlQegnED0QYrpC+CuFuQ9+TxnMXOa2YHZrRIndVmh1WqpoEIMv8eTsY+tWeY+GrRGBMc8toFoKyMiRklFqZxOwx1sXV1SavcA2h2WtFoYPL/958p+B/KcqNoag4xA2A2pcCtH9IWyWhAQHBCWYufSjK3daa6SIRLAZ0FhBawQ0YAnBqgGT7W6jMZZyEj/FG+ar+s7mKwCz567qHqqlgNSrV9SZ/pW3Lq6oNF+4LPftC3XqVOxceS9C/uMlb7c0A8NIsJYQ3QWg2wbhL0JMR4geAKGzQePaJtFfcTBz6cdV7lT231GU3REfYovbNUrtj1xbTJHGtYm9n6PRQJwXCiheqgSkUnglF8TOiBHOy7OBdG8OQFEhMoC5Lutuu61y58ybAvmPFr9NPwZyZkHGIcieb+sRUpIN3yLFBCMmQmw7iLoZQhaIb6A6YBeQ+Dzbigibiuol8SOjIDrLq8OqNDFREOyhjLnkZHlpIfM+Ke3miN+bs/xJQLw2AwEYMsS5c10m8JE3B6CoEDNwFvo6dWDQoMqfN+8V0LvWtdGAwdaV0BoKxhsg5wtxSOd8LEl5JabimiF4FUQ+DDGtIWqUJP35Q9FDT2G1mXnq2qKxiLLZ9PIkHyTFloSnSfPuuCqLN8xXMbC5GP+H3xv7qq2AhIXBOJcp+3tAdrF7K/yBHOADl3WPPCLfZaXRQO5boL+rcJXpMrA0KbqrNQYMt0H2t5CxE3L/J/uWlF+iyYfg3yHyHpecC783UJQPS1N5b2KPp4w9Ju/ZzQFIss1QSsqa91e8Ub69QVHzFUC+567sHvxGQLzVWMqR++6DWIc/jhSKmkcU/sNHgKNroWZNuOceN15AA7nvgMEWpWcoQ+kSSz3QPwRZv0HGdsh7yZYzUtIlHHIuYjoHWFjwBTDbGnm1shVNJN5WHCtTymCfsPkRAsY/BOi0YsLyFHYBuUIJSOXwVmMpR6KjYexY53VvE3Am2mpBDjJDdOTBB0suXVJhtGKeMtwKxpvKd6ilMeRPgMwNkLkO8p8TJ3xJBHRYcDHYm0R1sM8w6uyS9/QuACTYkhm1p7w7rspQs4bnyrefPAnnz4MOUu9x7otmx+/DDfxGQLzVWMqVhx5yvgmdAiqQqKzwMK8BjlGy0dHwwAMeupgWcmaXnnB3IcxtIe85yNhcmHNRWhVax7DgGj0hfFphccJAwT4D6Wr/ohpskffU7oCGhJoSyqs5W5i17u/U8kL5khjYHFx8dkyu567uHvxGQGx4/V+mZk0xZTkyHTjo7YEoSmQfxc8+Yj1om3ZbT/SgwpyL9L2QvfjCYcHaAxA2DWK6BVZYsLkNWMOhdQrE5gM1TkLMCdDHQ0Z79DrpVogVtMU9b/sh3qh/1ah481WuJgC6bld7AQF46ilphWpHD5QQ1anwAY/iHLzUsCFMmOCr0VQCLRj7VOGw4GARyyAr9LL/JzdbKe/J1wCwxfZ/Zm8+5c+EhkCUB3sC7pA+W/QpXkCyPHdl96EEBDFhvf6687o/ge99MRiFE98Af7use+ONAOp7XgJVNSzYZCt53/+IbUXL3+X91GAANjSSRe0e/D5I1ZPmq2PHIC0NguHcXcXf95SAVACvJhM6cvPNktHsyBNAanE7K7zCeeBpl3XXXAODB/tiNJ7DNSw4byqYLi55f6ew4PZS6NFfsAvIIPsMo/VvEGSEs31AH09iLCTGyM+g21/iafwCb5ivYqWSkitmlIBUCJ+6Dd9+G0IdKm6eAu4iIGu/BTxW4D6cHeehoc4tiasilnqQPw6y/oKMHWUIC06FUNfaLj7E1BWstcQP0uEsEJ4KLf4CSzAcl/jov1rIvtqtvhtnWYjzQgJh4+LNV2maAMhCByUgTrRoUdS2vhR41yejqd5Mp2jDqCefhJYtfTEa31DesGC/QFuYvT9qt21dF1uluQSJVlnRAgw66aEe5PW4y7IRFQFhHio7b7XCzp3y+ZriBSTFM1d2P/4mIF5rLFUSTz9dtO3t88A6n4ymerIBmOyyrmdPeOIJX4zGP3AKC/7V16MpHYOtNtnoHeJQp91iCE+B1B6QcilZofB3c8AKutW+HGnJeNJ8lZAAGRkQAqdHFE1d0GsCqCCGXwmINxtLlYROB59+CnEOq4x0kQAADiZJREFUHdxMwO0of4g3OA/cirN/tVYtmDtXvptqTxCYrvD1IErHdLGY3ZpkwA2HAV0+dLfVeNgnDptF7SQnRLfLP0ubeKP+VWzxs49AaQoA+JmA2PB5+lTDhjBrlpRxtpMIDEIyohWeIQ+4GedICo0GZsxwDrNW+D+GO+V9/AbbistmglYPJ4ZBZjuSo8SUhRWCl/pqlMXjrfLtTYsKiIEAMl+BEpASufZaePhh53X/AbcRANk9AYgZuANY47J+wgQYMMAHA1JUCv3dEl123WHokgxEn4Zun4NVCztfAWB+J+kRoj0Eut2lns6rxEZLDSxPYLHALluFl4FFBeSMJsBidpSAlMKUKXDllc7rfgUeIsC+ZT/HCtwPLHZZ37s3TJzogwEpKo01GvT3S0L/lFW2lVdNheBcOD4czl9BWriICMgsROMnpQM9ab46eBCysyEUjt8IZx026XGuFRoQ+KOA+CwXxJXgYJg/Hzp3dl7/GTDJJyOqmjwP/J/Luvbt4csvld8jkMkfJ21ub94HPU4DNU7BFW8DGtj0IVh1LGkj5U00mRDiJ5m7nkwgtPs/ahadfZwIlNBdR/xRQPxmBgJStO/774uGj/4PmICaiVQGK/AyErLrSLNm8OOPEOPBf2SF57HGFc5C3vld2qTTaxrUPAppF8O+J7EEwXs9IV8H2v2+L23vrfLtzZwFJF3j4+ChiqIEpAzUrg3ffefcwRBgJnA3yidSEczAg8ArLutr1RLBrmiPc4V/kf80WBpA70S4fRdiwhpsMwLvegXSO3GyBszuIfuH/ObbQovxMc7BM+7EZCrwf1hvLhQQM35kdSkvficgvmgsVRaaN4eFC2VG4shXwHBUD5HykAsMBT51WV/SbE8RuFgjpTQLwLu/Q61coOUf0GMOmMNg7QIwRfJXC/i1DWCCkK99l2DoSf/H/v2Qnw9hcLR/YVbAMY3fVTQrO34nIL5oLFVWunaFn38uOhP5GbgelSdSFs4D1yLBCI7Urg2//AJduvhgUAqPYhgCxv5QJwc+sofsXv8k1N4LGe1hw2eAhrndYEsD0Ogh9CsI8sE/lDfyP+IK61+d0UC6567oefxOQHzVWKqsdO0Kv/8uZU8cWQ10Bdb6YlABwkbgUopm9TdtCsuWKfGoyuS+C9ZYGLEH7t6OmLJGDoPQTEgcCbsnYw6CN3vBvtqgyYLQORDkxbS68FCIDPfc+e0C0lLMV9lIub2Axu8ExIZfmrHsNGsmN7xOnZzXnwD6Io7hgAun8CBWYAbQi6J9O9u1k9+lMltVbSyNIWcmoJFZSOczQK39MOx20Jhh58uQcB/5Oni5L+y1i8inEOQln4gnZx9GI+yWXBfLdbAeSAi0nI/iUAJSQerUgSVLiuaJmBDH8BACLKXUQ5xHMvgfp2j7h969YflylWVeXTAOBv0DEGGEnxbY/CFtlsLAxwANbPwEjt1BbjC81A82NZTckLAvQLfe8+PzZPXdPXvAYIAgODgANgVCt8GyoASkEtSoIeGmjz1WNHLjV6AzsMAXA/MT5iO/g99c1ms08Pjj8MMPRYMSFFWb3FfA1AOap4mIhBuBS2ZB/4mSpb7+S0i4n3wdTL0KllwEmCHkVwj9xrPJhp72fxiAA/BHIDvNXfFXAQmYsLbgYHjlFRESV+f6aWAU0A/Y64Ox+YpDSFDBHUCSy7b4eFiwQLL8VZJgNSREWvmaW8KVx2HhDxBsBq56o1BENsyB3VMwB2mY0x3eteeJ7IWwGZ4pexIdCaHB7j+vnQ074ACQKc1Oqwz+KiABMQNxpE8f+OcfKTvuykrEwT6BAKrTXAFyEf9PJ+CPYrZfcQX8+6/UGVNUX6y1IPsHsNSFGw/A/EUOIjJ4HGgsUi9r7bdgiuKf5vD4DXCgli1j/VsI/T/3VvH1ZPZ5vg4W7wOD5Hy4lnsLaJSAuJEGDSTM97nnnDsbgtj/ZwJtgHeoWlV9s4C3gBaI/0fvsj00FF54AX76Sfk7FIKlqYiINRaG74VF39nMWT1mw+03FUZnLd8I6Z04VQOevQY+7V5YgDFsBoQscE+klqfMV9basOYs5InRagsBHrbrir8KiM8bS1UUnU4EZN066d/tShLS57sp8rSe5tXRuZcsYBrQDHgWOFPMPr17y6zjmWeUyUrhjLmDNMey1JOZyIqvbI711stg7KVQZzdktoPfN8He57BodP/f3tnGtlWdcfzn2I4dJyF1mrShWdtRkr7wFl4KnTQQhK4UtjLB9gHGVk1I0ApE+QJCKlJBQohv5QManQCBNAFCBQ20Ai2wbLRJ+6GlAVqm0q5J2gIBSoudEidtSJzLh+de7CYkMY7te3z9/KQj2ye+vsdRcv/3nOc5/4cti2DtKtjWDCM+qScS/pvMSAL7GZ+pkQFlZRDNtX27X6pHjjZCR2rO8X6Oz+I6edq0P31iMfqAondD2rJFHGW/nGBnSw2wBrFEuaBww5oW/0PMD58DvpvgPY2N8MQTcPPNBRtWSRGtPft1vIh3sZZ9BlV/BH839ETh1tth/2xgOALvboS9awEfRD+GpeugXq7IsxPwh09h+REI2TlNVkiEabRJ4ixWBr5WM2vgyhz+81k1IhzYJXFXrIDOTgBuBN7N3Zncx2QB2Y8spxc9AwPw5JNS6TAxSRDkCmA1Eng3zQrqOPAKYt3y0STvq66GNWuk/GwkUpixlSJeEhAA30mo+hMEOmWJat1v4YXL7B923wBv/R3idgWqua/DJY9AjaSmVH8P1x+B33TDL8csEFmzIDlHlpKsOhitBSpEaKwQ4IeF82BBYw6+REiEw0qbzSQSssdpeJhhoBaPhUFNFpC3kC0EniEeh2efhWeegb5JVkIDSBbT75FblnmFGd44jgHvIFYt/2byxPVoVIRj7VqYMaMgwytpvCYgAAxB5FHZgQ7w2oVw7+/gZAQYroBdD0kbjkigfe7rsHgj1KUsfH/xHfzqC7j8S1j8rR2cn4Qz98KyG6fpwFsOo/VgzWRcUOC99+B2qRG/C9lL6ylMFpBNwD1ujyMfJBLw/POwaROcyCCT5ALkL+/XiBXI+UCuMw6HgW5gN/KX3gEczOC4+nq47z64806oyqMNtnI2nhQQm+CbUHk/+E7BN5XwwEp4+WKwfED/HOh4GDrvgqSdqVL7ISx4AeZvhlCqJlN5UvabnB+X+uwNCagbgJohiIxA+QiMPAitN2XpwBuC0VliWz/RlXTDBnj6aQAeBzZkcRajMVlA1iNlNzzLmTOym33zZtixA5JT3C05BIHzgCVIVtciJChfB8wEquz3ONfzBCIQCWR3/Akkze2Q3Q4iFiOZxh/9frjuOrjtNli1CsLhDA9UcoaXBQQkLhJ5AIL/kdc754mQ7HGWmvrPhT3roPNuGKyTPt8IzGqHOVuhoQ1mfCIzlUlob4GWK3/GwPwS47CiUnVxKlpbYd8+AJYD//0ZZyoKTBaQPwMvuT2OQnH8OLzxhtQdcUzXTGPRIrjlFrjjDpg71+3RlDZeFxCH8jeh4mEo6xXjqH8thseuhY+cdPCREBy8Ffb/BbpXQLI8dXDwFNR2SvD9nENQdQQqemWWEuwH/2kOrIDG+VMMIiLBeKdlmrt66hQ0NUEyyRAQxYNVH0wWkGuAdrfH4QYHDojjb1sbfPCBFKJxg0AAli2D5cth5UoxPlTMoFQEBMA3COGNEhvx2Ruo2hbAU8tgazMknQv6mRrougm6VsLRVuibShng620+KioBP1AGVgAI2wH2EFgVSFAyC95+G1avBmQvcWt2n2I2xgpIPM58y+Ko2+Nwm/5+2LsXdu+GPXvg8GHozZMJdGMjLFwIV10lwrF0qcY1FHPwxSD8nC0k9gaqL86BF1tg84Wwr2HMAf3nwldXwDcXwbfN0HceJBpkyWuoGkbCxGL5uwSuXy8JM8CjwGN5O5GLGCsglkUgHuc0Weu/dxkYgK4u6O4WQenpkSWwWEza4KDMWpyU4aoqmU1EIlBbK62hQaosNjfLNLupSdNuleLA1w+hf0D5y+A/lOrvicqMpG0BdMyHWAa1PWL352+cV18tqwnANXjMwsTBWAEBiMU4hntZrIqiGI7/Ywi9CsF/jvfG6qqVWMmndfL86Aw4USlpwYly8ajKl4CcPCkxQ8tiENn/MdbhxxOYfnf/GSogiqJMQPJSGLwUeBz8/4fAbghsh+D70BSTNhEjl0F/ngRk1y6wpFzUTjwqHlAcAqIoijI5ZZBcLG3or8Aw+LuklR22H4+Km69vQPaYWHnc8NrR8eNTz/lfpaMCoiiK9whCcok0N2hP5Y96WkBMdeN1KJrCUoqiKCAJLV1dgBhWf+juaPKL6QKiMxBFUYqKtNlHO1kZzBcPKiCKoig5pFTiH2B+DORYfb14RIVCUGHndTvPx/aFw6kGZ78e2zedz3P2VSiKooxlp4cLSI3F6H0giMGAS0YemTGR+Dh9mYhZet90Pk9t1BXFXXp74WKpYtSH+JtmaJFanJh+H50kJXIVQDjt0c2+auzf3dCQNJPQ2ZqiuMOOHT8+3Y7HxQPMF5B0TtvNpDLiJojZuD4TRQ10tqZ4n1JavgLzl7CU7DBGzEibrZmIztaUXNLSAp/L5oNLgE/cHU3+UQFRCsV0BCmbY6bqi+bma+UHna0VHz094mCN1GybjZQw8TR6v6MUCmcJEnQZcqI+ja0V8WwtbflqOyUgHqACoiimCVsAERJICUp6n1OxuNB9xolaIJCqV1NZCcGglFuurk71BQJnv88Rnp86NpvPSz+21OIfoEtYiqJkhlvCNVmfqSwBDro9iEKgAqIoSrFikpg5fV8Bc3L0/RRFURTFm/wAIrmtSq30ib0AAAAASUVORK5CYII=" />
+
</svg>
+14
docs/img/06_use.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="220" height="170" viewBox="0 0 220 170">
+
<defs>
+
<g id="house" fill="none" stroke="black">
+
<rect x="6" y="50" width="60" height="60" />
+
<path d="M6,50 L36,9 L66,50" />
+
<path d="M36,110 L36,80 L50,80 L50,110" />
+
</g>
+
</defs>
+
<use xlink:href="#house" />
+
<use xlink:href="#house" x="100" y="50" />
+
<use xlink:href="#house" x="150" y="20" />
+
</svg>
+9
docs/img/07_cart1.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="100" viewBox="0 0 100 100">
+
<defs>
+
</defs>
+
<path d="M0,100 L0,0 L100,0" fill="none" stroke="green" stroke-width="2" />
+
<path d="M40,40 L100,40 L70,70 L40,70" fill="silver" stroke="black" stroke-width="2" />
+
<text x="5" y="95" font-size="12">downward y</text>
+
</svg>
+11
docs/img/07_cart2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="100" viewBox="0 0 100 100">
+
<defs>
+
</defs>
+
<g transform="translate(0,100) scale(1,-1)">
+
<path d="M0,100 L0,0 L100,0" fill="none" stroke="green" stroke-width="2" />
+
<path d="M40,40 L100,40 L70,70 L40,70" fill="silver" stroke="black" stroke-width="2" />
+
<text x="5" y="95" font-size="12">upward y</text>
+
</g>
+
</svg>
+9
docs/img/07_cart3.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="100" height="100" viewBox="0 0 100 100" transform="scale(1,-1)">
+
<defs>
+
</defs>
+
<path d="M0,100 L0,0 L100,0" fill="none" stroke="green" stroke-width="2" />
+
<path d="M40,40 L100,40 L70,70 L40,70" fill="silver" stroke="black" stroke-width="2" />
+
<text x="5" y="95" font-size="12">upward y</text>
+
</svg>
+10
docs/img/07_rota.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="200" viewBox="0 0 200 200">
+
<defs>
+
</defs>
+
<rect x="0" y="0" width="200" height="200" stroke="gray" fill="none" />
+
<rect x="70" y="30" width="40" height="40" fill="silver" />
+
<rect x="70" y="30" width="40" height="40" fill="gray" transform="rotate(22.5)" />
+
<rect x="70" y="30" width="40" height="40" fill="black" transform="rotate(45)" />
+
</svg>
+17
docs/img/07_rota2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="200" viewBox="0 0 300 200">
+
<defs>
+
<g id="arrow">
+
<path d="M110,100 L160,100" />
+
<path d="M160,100 L155,95 L155,105" />
+
</g>
+
</defs>
+
<circle cx="100" cy="100" r="3" fill="black" />
+
<use xlink:href="#arrow" x="0" y="0" stroke="black" fill="black" />
+
<g stroke="red" fill="red">
+
<use xlink:href="#arrow" x="0" y="0" transform="rotate (60,100,100)" />
+
<use xlink:href="#arrow" x="0" y="0" transform="rotate (-90,100,100)" />
+
<use xlink:href="#arrow" x="0" y="0" transform="rotate (-150,100,100)" />
+
</g>
+
</svg>
+12
docs/img/07_scalcent.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="300" height="200" viewBox="0 0 300 200">
+
<defs>
+
<rect x="70" y="80" width="60" height="40" stroke="black" fill="none" id="scalecenter0" />
+
</defs>
+
<circle cx="100" cy="100" r="4" fill="black" />
+
<use xlink:href="#scalecenter0" />
+
<use xlink:href="#scalecenter0" x="0" y="0" transform="translate(-100,-100) scale(2)" stroke-width="0.5" />
+
<use xlink:href="#scalecenter0" x="0" y="0" transform="translate(-150,-150) scale(2.5)" stroke-width="0.4" />
+
<use xlink:href="#scalecenter0" x="0" y="0" transform="translate(-200,-200) scale(3)" stroke-width="0.33" />
+
</svg>
+9
docs/img/07_scale.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="200" viewBox="0 0 200 200">
+
<defs>
+
<rect x="0" y="0" width="40" height="40" fill="none" stroke-width="2" id="scale10" />
+
</defs>
+
<use xlink:href="#scale10" x="10" y="10" stroke="black" />
+
<use xlink:href="#scale10" x="10" y="10" stroke="red" transform="scale(2)" />
+
</svg>
+9
docs/img/07_scale2.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="100" viewBox="0 0 200 100">
+
<defs>
+
<rect x="0" y="0" width="40" height="40" fill="none" stroke-width="2" id="scale20" />
+
</defs>
+
<use xlink:href="#scale20" x="10" y="10" stroke="black" />
+
<use xlink:href="#scale20" x="10" y="10" stroke="red" transform="scale(3,1.5)" />
+
</svg>
+23
docs/img/07_skew.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="100" viewBox="0 0 200 100" id-srefix="skew">
+
<defs>
+
</defs>
+
<g stroke="gray" stroke-dasharray="4 4">
+
<path d="M0,0 L200,0" />
+
<path d="M20,0 L20,90" />
+
<path d="M120,0 L120,90" />
+
</g>
+
<g transform="translate(20,0)">
+
<g transform="skewX(30)">
+
<path d="M50,0 L0,0 L0,50" stroke="black" fill="none" stroke-width="2" />
+
<text x="0" y="60" font-size="16">skewX</text>
+
</g>
+
</g>
+
<g transform="translate(120,0)">
+
<g transform="skewY(30)">
+
<path d="M50,0 L0,0 L0,50" stroke="black" fill="none" stroke-width="2" />
+
<text x="0" y="60" font-size="16">skewY</text>
+
</g>
+
</g>
+
</svg>
+8
docs/img/07_trans.svg
···
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="200" viewBox="0 0 200 200">
+
<defs>
+
</defs>
+
<rect x="0" y="0" width="40" height="40" />
+
<rect x="0" y="0" width="40" height="40" fill="red" transform="translate(50,50)" />
+
</svg>
docs/img/example1.png

This is a binary file and will not be displayed.

+1307
docs/index.md
···
+
# Drawsvg Quick Reference
+
+
Repository: [https://github.com/cduck/drawsvg](https://github.com/cduck/drawsvg)
+
+
+
```python
+
import drawsvg as dw
+
```
+
+
+
## Canvas and Document Structure
+
+
```python
+
d = dw.Drawing(width, height, origin=(0, 0),
+
context: drawsvg.types.Context = None, animation_config=None,
+
id_prefix='d', **svg_args)
+
```
+
+
It is recommended to use a unique `id_prefix` for each svg if you embed multiple on a web page.
+
+
```python
+
d = dw.Drawing(400, 300, id_prefix='pic')
+
```
+
+
+
## Basic Shapes
+
+
### One Line
+
+
```python
+
dw.Line(sx, sy, ex, ey, **kwargs)
+
```
+
+
```python
+
line = dw.Line(30, 30, 90, 90, stroke='black')
+
d.append(line)
+
```
+
+
![svg](img/01_line.svg)
+
+
+
### Multiple Lines
+
+
This is SVG's `polyline` (but drawsvg renders as path with multiple L).
+
+
```python
+
dw.Lines(sx, sy, *points, close=False, **kwargs)
+
```
+
+
```python
+
lines = dw.Lines(10, 90, 10, 10, 80, 90, 80, 10,
+
fill='none', stroke='black')
+
d.append(lines)
+
```
+
+
![svg](img/01_multilines.svg)
+
+
+
```python
+
x = [30 + x*10 for x in range(20)]
+
y = [80, 20]*10
+
xy = [item for sublist in zip(x, y) for item in sublist]
+
d.append(dw.Lines(*xy, stroke='black', stroke_width=5, fill='none'))
+
```
+
+
![svg](img/01_multilines2.svg)
+
+
+
### Polygon
+
+
SVG `Polygon` is drawsvg `Lines` with `close=True`.
+
+
```python
+
polygon = dw.Lines(15, 10, 55, 10, 45, 20, 5, 20,
+
fill='red', stroke='black', close='true')
+
star = dw.Lines(48, 16, 16, 96, 96, 48, 0, 48, 88, 96,
+
stroke='black', fill='none', close='true')
+
d.append(star)
+
```
+
+
![svg](img/01_polygon.svg)
+
+
+
### Rectangle
+
+
```python
+
dw.Rectangle(x, y, width, height, **kwargs)
+
```
+
+
```python
+
# Black interior, no outline
+
d.append(dw.Rectangle(10, 10, 90, 150))
+
# No interior, black outline
+
d.append(dw.Rectangle(120, 10, 60, 120,
+
fill='none', stroke='black'))
+
# Blue interior, thick semi-transparent red outline
+
d.append(dw.Rectangle(210, 10, 75, 90,
+
fill='#0000ff', stroke='red',
+
stroke_width=7, stroke_opacity=0.5))
+
# Semi-transparent yellow interior, dashed green outline
+
d.append(dw.Rectangle(300, 10, 105, 60,
+
fill='yellow', fill_opacity=0.5,
+
stroke='green', stroke_width=2,
+
stroke_dasharray='5,2'))
+
```
+
+
![svg](img/01_rect.svg)
+
+
Rounded corners:
+
+
```python
+
# Define both rx and ry
+
d.append(dw.Rectangle(10, 10, 80, 180, rx='10', ry='10',
+
stroke='black', fill='none'))
+
# If only one is given, it applies to both
+
d.append(dw.Rectangle(110, 10, 80, 180, ry='20',
+
stroke='black', fill='none'))
+
d.append(dw.Rectangle(210, 10, 80, 180, rx='40',
+
stroke='black', fill='none'))
+
# Rx and ry unequal
+
d.append(dw.Rectangle(310, 10, 80, 180, rx='30', ry='10',
+
stroke='black', fill='none'))
+
d.append(dw.Rectangle(410, 10, 80, 180, rx='10', ry='30',
+
stroke='black', fill='none'))
+
```
+
+
![svg](img/01_rectround.svg)
+
+
+
### Circle
+
+
```python
+
dw.Circle(cx, cy, r, **kwargs)
+
```
+
+
cx and cy point to circle's center, r refer to its radius
+
+
```python
+
d.append(dw.Circle(50, 50, 40))
+
d.append(dw.Circle(150, 50, 40,
+
stroke='black', fill='none'))
+
d.append(dw.Circle(250, 50, 40,
+
stroke='black', fill='none',
+
stroke_width=15))
+
```
+
+
![svg](img/01_circ.svg)
+
+
+
### Ellipse
+
+
```python
+
dw.Ellipse(cx, cy, rx, ry, **kwarg)
+
```
+
(cx,cy) points to the center and (rx,ry) tells its radius
+
+
```python
+
d.append(dw.Ellipse(50, 50, 50, 30))
+
d.append(dw.Ellipse(160, 50, 50, 30,
+
stroke='black', fill='none'))
+
d.append(dw.Ellipse(250, 50, 30, 45,
+
stroke='black',fill='none'))
+
```
+
+
![svg](img/01_ellip.svg)
+
+
+
+
## Color and Painting Properties
+
+
For a full list, see [W3C specifications](https://www.w3.org/TR/SVG11/styling.html).
+
+
+
### fill and stroke\_color
+
+
Some color keyword names are:
+
aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow.
+
+
Also supported is `#rrggbb`, `#rgb` (hexadecimal), or `rgb(R,G,B)` with 0-255 or with 0-100% for each value.
+
+
```python
+
c = ['red', '#9f9', '#9999ff', 'rgb(255,128,64)', 'rgb(60%,20%,60%)']
+
for i in range(5):
+
y = (i + 1)*10
+
d.append(dw.Line(10, y, 80, y,
+
stroke=c[i], stroke_width=5))
+
```
+
+
![svg](img/02_fsc.svg)
+
+
+
### fill\_opacity and stroke\_opacity
+
+
Value range from 0 = transparent to 1 = solid.
+
+
```python
+
for i in range(5):
+
y = (i + 1)*10
+
d.append(dw.Line(0, y, 290, y,
+
stroke='black', stroke_width=5,
+
stroke_opacity=i/5 + 0.1))
+
d.append(dw.Rectangle(i*60, 70, 50, 50,
+
fill='red', fill_opacity=i/5+0.1))
+
```
+
+
![svg](img/02_foso.svg)
+
+
+
### stroke\_dasharray
+
+
```python
+
# Nine-pixel dash, five-pixel gap
+
d.append(dw.Line(10, 10, 100, 10,
+
stroke='black', stroke_width=2,
+
stroke_dasharray='9,5'))
+
# Five-pixel dash, three-pixel gap, nine-pixel dash, two-pixel gap
+
d.append(dw.Line(10, 20, 100, 20,
+
stroke='black', stroke_width=2,
+
stroke_dasharray='5,3,9,2'))
+
# Odd number of entries alternates dashes and gaps
+
d.append(dw.Line(10, 30, 100, 30,
+
stroke='black', stroke_width=2,
+
stroke_dasharray='9,3,5'))
+
```
+
+
![svg](img/02_dash.svg)
+
+
+
### stroke\_width
+
+
```python
+
for i in range(20):
+
d.append(dw.Line((i+1)*15, 10, (i+1)*15, 90,
+
stroke='black', stroke_width=abs(10-i)+1))
+
```
+
+
![svg](img/02_strokewdth.svg)
+
+
+
### stroke\_linecap
+
+
`stroke_linecap` can be set to `butt`, `round`, or `square`.
+
Note that the latter two extend beyond the end coordinates.
+
+
```python
+
d.append(dw.Line(10, 15, 50, 15,
+
stroke='black', stroke_width=15,
+
stroke_linecap='butt'))
+
d.append(dw.Line(10, 45, 50, 45,
+
stroke='black', stroke_width=15,
+
stroke_linecap='round'))
+
d.append(dw.Line(10, 75, 50, 75,
+
stroke='black', stroke_width=15,
+
stroke_linecap='square'))
+
# Guide lines
+
d.append(dw.Lines(10, 0, 10, 100, stroke='#999'))
+
d.append(dw.Lines(50, 0, 50, 100, stroke='#999'))
+
```
+
+
![svg](img/02_linecap.svg)
+
+
+
### stroke\_linejoin
+
+
Define the way lines connect at a corner with `stroke-linejoin`: `miter` (pointed), `round`, or `bevel` (flat).
+
+
```python
+
d.append(dw.Line(0, 20, 300, 20, stroke='gray'))
+
g = dw.Group(stroke_width=20, stroke='black', fill='none')
+
g.append(dw.Lines(10, 80, 50, 20, 90, 80,
+
stroke_linejoin='miter'))
+
g.append(dw.Lines(110, 80, 150, 20, 190, 80,
+
stroke_linejoin='round'))
+
g.append(dw.Lines(210, 80, 250, 20, 290, 80,
+
stroke_linejoin='bevel'))
+
d.append(g)
+
```
+
+
![svg](img/02_join.svg)
+
+
+
### stroke\_miterlimit
+
+
When two line segments meet at a sharp angle and miter joins have been specified for `stroke-linejoin`,
+
it is possible for the miter to extend far beyond the thickness of the line stroking the path.
+
The `stroke-miterlimit` imposes a limit on the ratio of the miter length to the `stroke-width`.
+
When the limit is exceeded, the join is converted from a miter to a bevel.
+
(From [W3C doc](https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty))
+
+
```python
+
d.append(dw.Line(0, 30, 300, 30, stroke='gray'))
+
g = dw.Group(stroke_width=20, stroke='black',
+
fill='none', stroke_linejoin='miter')
+
g.append(dw.Lines(10, 90, 40, 30, 70, 90))
+
g.append(dw.Lines(100, 90, 130, 30, 160, 90,
+
stroke_miterlimit=2.3))
+
g.append(dw.Lines(190, 90, 220, 30, 250, 90,
+
stroke_miterlimit=1))
+
d.append(g)
+
```
+
+
![svg](img/02_mlimit.svg)
+
+
+
## Path
+
+
```python
+
path = dw.Path(**kwargs)
+
```
+
+
The following Path specifiers are also available as lowercase characters.
+
In that case, their movements are relative to current location.
+
+
+
### M: moveto
+
+
```python
+
path.M(x, y)
+
```
+
+
Move to `x, y` (and draw nothing).
+
+
+
### L: lineto
+
+
```python
+
path.L(x, y)
+
```
+
+
Draw a straight line to `x, y`.
+
+
```python
+
g = dw.Group(stroke='black', fill='none')
+
+
p = dw.Path()
+
p.M(10, 10).L(100, 10)
+
g.append(p)
+
+
p = dw.Path()
+
p.M(10, 20).L(100, 20).L(100, 50)
+
g.append(p)
+
+
p = dw.Path()
+
p.M(40, 60).L(10, 60).L(40, 42)
+
p.M(60, 60).L(90, 60).L(60, 42)
+
g.append(p)
+
+
d.append(g)
+
```
+
+
![svg](img/03_pL.svg)
+
+
+
### H: horizontal line
+
+
```python
+
path.H(x)
+
```
+
+
Draw a horizontal line to the new `x` location.
+
+
+
### V: vertical line
+
+
```python
+
path.V(y)
+
```
+
+
Draw a vertical line to the new `y` location.
+
+
```python
+
p = dw.Path(stroke='black', fill='none')
+
d.append(p.M(10, 10).H(100))
+
d.append(p.M(10, 20).H(100).V(50))
+
```
+
![svg](img/03_pHV.svg)
+
+
+
### Q: quadratic Bézier curve (one control point)
+
+
```python
+
path.Q(x_ctl, y_ctl, x_end, y_end)
+
```
+
+
Draw a quadratic Bézier curve from current location to `x_end, y_end` by means of `x_ctl, y_ctl`.
+
+
```python
+
# Curve only (left)
+
p = dw.Path(stroke='black', fill='none', stroke_width=3)
+
d.append(p.M(30, 75).Q(240, 30, 300, 120))
+
# With control point and construction lines
+
d.append(dw.Use(p, 300, 0))
+
g = dw.Group(stroke='gray', fill='gray')
+
g.append(dw.Circle(330, 75, 3))
+
g.append(dw.Circle(600, 120, 3))
+
g.append(dw.Circle(540, 30, 3))
+
g.append(dw.Line(330, 75, 540, 30))
+
g.append(dw.Line(540, 30, 600, 120))
+
g.append(dw.Line(330, 75, 600, 120, stroke_dasharray='5,5'))
+
g.append(dw.Circle(435, 52.5, 3))
+
g.append(dw.Circle(570, 75, 3))
+
g.append(dw.Line(435, 52.5, 570, 75))
+
g.append(dw.Circle(502.5, 63.75, 4, fill='none'))
+
d.append(g)
+
```
+
+
![svg](img/03_pQ.svg)
+
+
+
### T: smooth quadratic Bézier curve (generated control point)
+
+
```python
+
path.T(x, y)
+
```
+
+
Draws a quadratic Bézier curve from the current point to (x, y).
+
The control point is assumed to be the reflection of the control point on the previous command relative to the current point.
+
If there is no previous command or if the previous command was not a Q, q, T or t, assume the control point is coincident with the current point.
+
(From [W3C Doc](https://www.w3.org/TR/SVG11/paths.html#PathDataQuadraticBezierCommands))
+
+
```python
+
# Curve sequence (left)
+
p = dw.Path(stroke='black', fill='none', stroke_width=3)
+
d.append(p.M(30, 60).Q(80, -10, 100, 60).Q(130, 25, 200, 40))
+
# With smooth continuation (right)
+
p = dw.Path(stroke='black', fill='none', stroke_width=3,
+
transform='translate(200,0)')
+
d.append(p.M(30, 60).Q(80, -10, 100, 60).T(200, 40))
+
```
+
+
![svg](img/03_pT.svg)
+
+
+
### C: cubic Bézier curve (two control points)
+
+
```python
+
path.C(x_ctl_1, y_ctl_1, x_ctl_2, y_ctl_2, x_end, y_end)
+
```
+
+
Draw a cubic Bézier curve by means of two control points (one for start and one for end).
+
+
```python
+
pnt_1 = (40, 50)
+
pnt_2 = (110, 50)
+
ctl_1_x = (10, 60, 110, 110, 60, 110)
+
ctls_2 = ((140, 10), (90, 10), (40, 10), (40, 10), (90, 90), (40, 90))
+
+
for i in range(6):
+
trans = f'translate({i*100},0)'
+
p = dw.Path(stroke='black', fill='none',
+
stroke_width=3, transform=trans)
+
ctl_1 = (ctl_1_x[i], 10)
+
ctl_2 = ctls_2[i]
+
p.M(*pnt_1)
+
p.C(*ctl_1, *ctl_2, *pnt_2)
+
d.append(p)
+
g = dw.Group(stroke='gray', fill='gray',
+
stroke_width=1, transform=trans)
+
g.append(dw.Circle(*ctl_1, 2))
+
g.append(dw.Circle(*ctl_2, 2))
+
g.append(dw.Line(*pnt_1, *ctl_1))
+
g.append(dw.Line(*pnt_2, *ctl_2))
+
d.append(g)
+
```
+
+
![svg](img/03_pC.svg)
+
+
+
### S: smooth cubic Bézier (one control point)
+
+
Similar to `T` in quadratic Bézier curve. The first control point is calculated as reflection of the previous second control point.
+
+
```python
+
path.S(x_ctl_2, y_ctl_2, x_end, y_end)
+
```
+
+
```python
+
pnt_1 = (30, 100)
+
pnt_2 = (100, 100)
+
pnt_3 = (200, 80)
+
ctl_1 = (50, 30)
+
ctl_2 = (70, 50)
+
ctl_3 = (150, 40)
+
+
p = dw.Path(stroke='black', fill='none', stroke_width=3)
+
p.M(*pnt_1)
+
p.C(*ctl_1, *ctl_2, *pnt_2)
+
p.S(*ctl_3, *pnt_3)
+
d.append(p)
+
+
for pnt, ctl in zip((pnt_1, pnt_2, pnt_3), (ctl_1, ctl_2, ctl_3)):
+
d.append(dw.Circle(*pnt, 4))
+
d.append(dw.Circle(*ctl, 2, stroke='gray', fill='gray'))
+
d.append(dw.Line(*pnt, *ctl, stroke='gray'))
+
```
+
+
![svg](img/03_pS.svg)
+
+
+
### A: elliptical Arc
+
+
```python
+
path.A(rx, ry, rot, largeArc, sweep, ex, ey)
+
+
rx, ry: radius
+
rot: x-axis rotation
+
largeArc: True or False
+
sweep: True (positive) or False (negative) angle
+
ex, ey: end point
+
```
+
+
```python
+
p = dw.Path(stroke='red')
+
d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=0, sweep=0, ex=225, ey=125))
+
p = dw.Path(stroke='blue')
+
d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=0, sweep=1, ex=225, ey=125))
+
p = dw.Path(stroke='rgb(0 80 255)',stroke_dasharray='5 3')
+
d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=1, sweep=0, ex=225, ey=125))
+
p = dw.Path(stroke='rgb(255 80 0)',stroke_dasharray='5 3')
+
d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=1, sweep=1, ex=225, ey=125))
+
```
+
+
![svg](img/03_pA.svg)
+
+
+
### Z: closepath
+
+
```python
+
path.Z()
+
```
+
+
Close the path.
+
+
```python
+
p = dw.Path(stroke='black', fill='none')
+
d.append(p.M(10, 10).h(30).v(50).h(-30).Z())
+
d.append(p.M(50, 10).h(30).v(50).Z())
+
```
+
+
![svg](img/03_pZ.svg)
+
+
+
## Text
+
```python
+
dw.Text(text, fontSize, x=None, y=None, *, center=False,
+
line_height=1, line_offset=0, path=None,
+
start_offset=None, path_args=None, tspan_args=None,
+
cairo_fix=True, **kwargs)
+
```
+
+
### Fill and Outline
+
+
Default is black as fill color and no outline.
+
+
```python
+
# Reference lines
+
l = dw.Path(stroke='gray')
+
l.M(20, 0).V(370)
+
for i in range(1, 7):
+
l.M(10, i*60).H(500)
+
d.append(l)
+
+
d.append(dw.Text('Simplest Text', font_size=50, x=20, y=60))
+
d.append(dw.Text('Outline / Filled', font_size=50, x=20, y=120, stroke='black'))
+
d.append(dw.Text('Too big stroke', font_size=50, x=20, y=180, stroke='black', stroke_width=5))
+
d.append(dw.Text('Outlined only', font_size=50, x=20, y=240, stroke='black', stroke_width=0.5, fill='none'))
+
d.append(dw.Text('Outlined and colored', font_size=50, x=20, y=300, stroke='black', fill='red'))
+
d.append(dw.Text('Colored fill only', font_size=50, x=20, y=360, fill='blue'))
+
```
+
+
![svg](img/04_fill.svg)
+
+
+
### Weight, Style, Decoration, Spacing
+
+
```python
+
d.append(dw.Text('bold', font_size=30, x=20, y=35, font_weight='bold'))
+
d.append(dw.Text('italic', font_size=30, x=20, y=75, font_style='italic'))
+
d.append(dw.Text('under', font_size=30, x=20, y=115, text_decoration='underline'))
+
d.append(dw.Text('over', font_size=30, x=20, y=155, text_decoration='overline'))
+
d.append(dw.Text('through', font_size=30, x=20, y=195, text_decoration='line-through'))
+
d.append(dw.Text('normal word space', font_size=30, x=200, y=35))
+
d.append(dw.Text('more word space', font_size=30, x=200, y=75, word_spacing=10))
+
d.append(dw.Text('less word space', font_size=30, x=200, y=115, word_spacing=-5))
+
d.append(dw.Text('wide letter space', font_size=30, x=200, y=155, letter_spacing=8))
+
d.append(dw.Text('narrow letter space', font_size=30, x=200, y=195, letter_spacing=-2))
+
```
+
+
![svg](img/04_weight.svg)
+
+
+
### Text Alignment
+
+
Horizontal alignment (`text_anchor`) can be `'start'`, `'middle'` or `'end'`.
+
+
Vertical alignment (`dominant_baseline`) can be `'auto'`, `'middle'` or `'hanging'`
+
(and more, see [here](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline)).
+
+
```python
+
d.append(dw.Line(75, 100, 75, 0, stroke='gray'))
+
d.append(dw.Line(140, 30, 250, 30, stroke='gray'))
+
d.append(dw.Line(140, 60, 250, 60, stroke='gray'))
+
d.append(dw.Line(140, 90, 250, 90, stroke='gray'))
+
d.append(dw.Text('Start', 24, 75, 30, text_anchor='start'))
+
d.append(dw.Text('Middle', 24, 75, 60, text_anchor='middle'))
+
d.append(dw.Text('End', 24, 75, 90, text_anchor='end'))
+
d.append(dw.Text('Auto', 24, 150, 30, dominant_baseline='bottom'))
+
d.append(dw.Text('Middle', 24, 150, 60, dominant_baseline='middle'))
+
d.append(dw.Text('Hanging', 24, 150, 90, dominant_baseline='top'))
+
```
+
+
![svg](img/04_align.svg)
+
+
+
### TSpan
+
+
Continues a `Text` element.
+
+
```python
+
txt = dw.Text('Switch among ', 24, 10, 40)
+
txt.append(dw.TSpan('italic', font_style='italic'))
+
txt.append(dw.TSpan(', normal, and '))
+
txt.append(dw.TSpan('bold', font_weight='bold'))
+
txt.append(dw.TSpan(' text.'))
+
d.append(txt)
+
```
+
+
![svg](img/04_tspan.svg)
+
+
+
```python
+
txt = dw.Text('F', 24, 10, 30)
+
txt.append(dw.TSpan('a', dy=5))
+
txt.append(dw.TSpan('l', dy=31, dx=21))
+
txt.append(dw.TSpan('l', dy=89, dx=54))
+
d.append(txt)
+
```
+
+
![svg](img/04_tspan2.svg)
+
+
The same could be achieved by a list of dx/dy values:
+
+
```python
+
d.append(dw.Text('Fall', 24, 10, 30,
+
dx='0,0,21,54', dy='0,5,21,54'))
+
```
+
+
![svg](img/04_tspan3.svg)
+
+
+
### Rotate
+
+
Either one angle (degrees), or a list which is applied to all characters.
+
If the list is smaller than the number of characters, the last angle persists.
+
+
```python
+
d.append(dw.Text('Rotate', 20, 20, 20, letter_spacing=20, rotate='90'))
+
d.append(dw.Text('Rotate', 20, 20, 80, letter_spacing=20, rotate='0 90 180 270'))
+
```
+
+
![svg](img/04_rot.svg)
+
+
`TSpan` can also be used:
+
+
```python
+
import random
+
random.seed(1)
+
+
txt = dw.Text('', 20, 20, 50, letter_spacing=20)
+
txt.append(dw.TSpan('R', rotate=random.randrange(360)))
+
txt.append(dw.TSpan('OT', rotate='50 20'))
+
rotate = ' '.join([str(random.randrange(360)) for i in range(3)])
+
txt.append(dw.TSpan('ATE', rotate=rotate))
+
d.append(txt)
+
```
+
+
![svg](img/04_rot2.svg)
+
+
+
### Setting Text Length
+
+
```python
+
s = 'Two words'
+
d.append(dw.Text(s, 20, 20, 30, textLength=250, lengthAdjust='spacing'))
+
d.append(dw.Text(s, 20, 20, 70, textLength=250, lengthAdjust='spacingAndGlyphs'))
+
d.append(dw.Text(s+' (normal length)', 20, 20, 110))
+
d.append(dw.Text(s, 20, 20, 150, textLength=80, lengthAdjust='spacing'))
+
d.append(dw.Text(s, 20, 20, 190, textLength=80, lengthAdjust='spacingAndGlyphs'))
+
+
d.append(dw.Line(20, 10, 20, 195, stroke='gray'))
+
d.append(dw.Line(270, 80, 270, 10, stroke='gray'))
+
d.append(dw.Line(100, 130, 100, 195, stroke='gray'))
+
```
+
+
![svg](img/04_len.svg)
+
+
+
### Text on a Path
+
+
```python
+
curve_path = dw.Path(stroke='gray', fill='none')
+
curve_path.M(30, 50).C(50, 20, 70, 20, 120, 50).S(150, 10, 200, 50)
+
+
round_corner = dw.Path(stroke='gray', fill='none')
+
round_corner.M(250, 30).L(300, 30).A(30, 30, 0, 0, 1, 330, 60).L(330, 110)
+
+
sharp_corner = dw.Path(stroke='gray', fill='none')
+
sharp_corner.M(30, 110).L(100, 110).L(100, 160)
+
+
discontinuous = dw.Path(stroke='gray', fill='none')
+
discontinuous.M(150, 110).A(40, 30, 0, 1, 0, 230, 110).M(250, 110).L(270, 140)
+
+
center_curve = dw.Path(stroke='gray', fill='none')
+
center_curve.M(330, 130).L(330, 160).A(30, 30, 0, 0, 1, 300, 180).L(200, 180)
+
+
d.append(curve_path)
+
d.append(round_corner)
+
d.append(sharp_corner)
+
d.append(discontinuous)
+
d.append(center_curve)
+
+
t_cp = dw.Text('Following a cubic Bézier curve', 14, path=curve_path)
+
t_rc = dw.Text("Going 'round the bend", 14, path=round_corner)
+
t_sc = dw.Text('Making a quick turn', 14, path=sharp_corner)
+
t_dc = dw.Text('Text along a broken path', 14, path=discontinuous)
+
t_ct = dw.Text('centered', 14, path=center_curve, offset='50%', text_anchor='middle')
+
+
d.append(t_cp)
+
d.append(t_rc)
+
d.append(t_sc)
+
d.append(t_dc)
+
d.append(t_ct)
+
```
+
+
![svg](img/04_path.svg)
+
+
+
### Multi Line Text
+
+
This is a particular feature of drawsvg: A list of strings as input for Text()
+
is rendered as multi-line text.
+
+
```python
+
tl = ['this is', 'a', 'multiline text', 'given as a', 'list']
+
d.append(dw.Text(tl, 14, 50, 20, text_anchor='middle'))
+
+
ts = 'this is\na\nmultiline text\ngiven as a\nstring'
+
d.append(dw.Text(ts, 14, 150, 20, text_anchor='middle'))
+
```
+
+
![svg](img/04_multiline_text.svg)
+
+
+
### Fonts
+
+
Specify fonts via `font_family`.
+
+
```python
+
d.append(dw.Text('Some text in Times New Roman.', 30, 10, 35, font_family='Times New Roman'))
+
d.append(dw.Text('Some text in Arial Black.', 30, 10, 75, font_family='Arial Black'))
+
d.append(dw.Text('Some text in Georgia.', 30, 10, 115, font_family='Georgia'))
+
```
+
+
![png](img/04_fonts1.png)
+
+
Specify a default font.
+
+
```python
+
d = dw.Drawing(600, 120, font_family='Times New Roman')
+
d.append(dw.Text('Some text in global setting (Times New Roman).', 30, 10, 35))
+
d.append(dw.Text('Some text in Arial Black.', 30, 10, 75, font_family='Arial Black'))
+
d.append(dw.Text('Some text in Georgia.', 30, 10, 115, font_family='Georgia'))
+
```
+
+
![png](img/04_fonts2.png)
+
+
+
+
## Gradient, Clip, Mask
+
+
### Linear Gradient
+
+
```python
+
gradient = dw.LinearGradient(x1, y1, x2, y2, gradientUnits='userSpaceOnUse', **kwargs)
+
gradient.add_stop(offset, color, opacity=None)
+
```
+
+
```python
+
grad = dw.LinearGradient(150, 0, 0, 0)
+
grad.add_stop(0, 'green')
+
grad.add_stop(1, 'yellow')
+
d.append(dw.Rectangle(10, 10, 150, 60,
+
stroke='black', fill=grad))
+
```
+
+
![svg](img/05_lingrad.svg)
+
+
+
### Radial Gradient
+
+
```python
+
gradient = dw.RadialGradient(cx, cy, r, **kwargs)
+
gradient.add_stop(offset, color, opacity=None)
+
```
+
+
```python
+
gradient = dw.RadialGradient(200, 100, 100)
+
gradient.add_stop(0, 'green', 1)
+
gradient.add_stop(1, 'orange', 1)
+
bg = dw.Rectangle(x=0, y=0, width='100%', height='100%', fill=gradient)
+
d.append(bg)
+
```
+
+
![svg](img/05_radgrad.svg)
+
+
+
### Clip
+
+
```python
+
clip_name = dw.ClipPath()
+
```
+
+
To add shape as Clip, use `.append()` method.
+
To apply Clip, fill `clip_path` argument with `clip_name`.
+
+
```python
+
# Show both shapes as they are
+
d.append(dw.Rectangle(100, 100, 100, 100,
+
stroke='gray', fill='none'))
+
d.append(dw.Circle(100, 100, 100,
+
fill='none', stroke='gray', stroke_dasharray='5 5'))
+
# Apply rect as clip to circle
+
clip = dw.ClipPath()
+
clip.append(dw.Rectangle(100, 100, 100, 100))
+
d.append(dw.Circle(100, 100, 100,
+
fill='cyan', clip_path=clip))
+
```
+
+
![svg](img/05_clip.svg)
+
+
Another example:
+
+
```python
+
# Draw a random path in the left half of the canvas
+
p = dw.Path(stroke='black', stroke_width=2, fill='none')
+
p.M(150, 150)
+
import random
+
random.seed(1)
+
for i in range(40):
+
p.L(random.randint(0, 300), random.randint(0, 200))
+
d.append(p)
+
+
# Circle as clipping shape
+
circ = dw.Circle(150, 100, 75)
+
c = dw.ClipPath()
+
c.append(circ)
+
+
# Repeat lines in the right half and apply clipping
+
d.append(dw.Use(p, 300, 0, clip_path=c))
+
```
+
+
![svg](img/05_clip2.svg)
+
+
Complex clip path:
+
+
```python
+
curve1 = dw.Path(stroke='black', stroke_width=1, stroke_dasharray='3 2', fill='none')
+
curve1.M(5, 55).C(25, 5, 45, -25, 75, 55).C(85, 85, 20, 105, 40, 55).Z()
+
+
curveClip = dw.ClipPath()
+
curveClip.append(dw.Use(curve1, 0, 0))
+
+
text1 = dw.Text('CLIP', 48, 20, 20, font_weight='bold', transform='rotate(60)',
+
stroke='black', stroke_width=1, stroke_dasharray='3 2', fill='none')
+
textClip = dw.ClipPath()
+
textClip.append(dw.Use(text1, 0, 0))
+
+
shapes = dw.Group()
+
shapes.append(dw.Rectangle(0, 50, 90, 60, fill='#999'))
+
shapes.append(dw.Circle(25, 25, 25, fill='#666'))
+
shapes.append(dw.Lines(30, 0, 80, 0, 80, 100, close='true', fill='#ccc'))
+
+
# draw shapes with clip path
+
d.append(dw.Use(shapes, 0, 0, clip_path=curveClip))
+
+
# show clip path
+
g = dw.Group(transform='translate(100,0)')
+
g.append(shapes)
+
g.append(dw.Use(curve1, 0, 0))
+
d.append(g)
+
+
# draw shapes with text as clip path
+
d.append(dw.Use(shapes, 0, 150, clip_path=textClip))
+
+
# show text clip path
+
g = dw.Group(transform='translate(100,150)')
+
g.append(shapes)
+
g.append(dw.Use(text1, 0, 0))
+
d.append(g)
+
```
+
+
![svg](img/05_clip3.svg)
+
+
+
### Mask
+
+
```python
+
mask_name = dw.Mask()
+
```
+
+
The transparency of the masking object is transfered to the masked object.
+
Opaque pixels of the mask produce opaque pixels of the masked object.
+
Transparent parts of the mask make the corresponding parts of the masked object invisible.
+
+
```python
+
gradient = dw.LinearGradient(*[0,0], *[1,0], gradientUnits='objectBoundingBox')
+
gradient.add_stop(0, 'white')
+
gradient.add_stop(1, 'black')
+
+
mask = dw.Mask()
+
box = dw.Rectangle(30, 0, 100, 100, fill=gradient)
+
mask.append(box)
+
+
# Initial shape
+
rect = dw.Rectangle(0, 0, 200, 100,
+
fill='cyan', stroke='blue', stroke_width=2)
+
d.append(rect)
+
+
# After mask
+
rect = dw.Rectangle(0, 0, 200, 100,
+
fill='pink', stroke='red', stroke_width=2,
+
mask=mask)
+
d.append(rect)
+
```
+
+
![svg](img/05_mask.svg)
+
+
Mask using opaque colors:
+
+
```python
+
# Define the masks
+
redmask = dw.Mask(maskContentUnits='objectBoundingBox')
+
redmask.append(dw.Rectangle(0, 0, 1, 1, fill='#f00'))
+
greenmask = dw.Mask(maskContentUnits='objectBoundingBox')
+
greenmask.append(dw.Rectangle(0, 0, 1, 1, fill='#0f0'))
+
bluemask = dw.Mask(maskContentUnits='objectBoundingBox')
+
bluemask.append(dw.Rectangle(0, 0, 1, 1, fill='#00f'))
+
whitemask = dw.Mask(maskContentUnits='objectBoundingBox')
+
whitemask.append(dw.Rectangle(0, 0, 1, 1, fill='#fff'))
+
+
# Display the colors
+
d.append(dw.Rectangle(10, 10, 50, 50, fill='#f00'))
+
d.append(dw.Rectangle(70, 10, 50, 50, fill='#0f0'))
+
d.append(dw.Rectangle(130, 10, 50, 50, fill='#00f'))
+
d.append(dw.Rectangle(190, 10, 50, 50, fill='#fff', stroke='black'))
+
+
# Mask
+
g = dw.Group(mask=redmask)
+
g.append(dw.Circle(35,115,25,fill='black'))
+
g.append(dw.Text('Red',14,35,80,text_anchor='middle'))
+
d.append(g)
+
g = dw.Group(mask=greenmask)
+
g.append(dw.Circle(95, 115, 25, fill='black'))
+
g.append(dw.Text('Green', 14, 95, 80, text_anchor='middle'))
+
d.append(g)
+
g = dw.Group(mask=bluemask)
+
g.append(dw.Circle(155, 115, 25, fill='black'))
+
g.append(dw.Text('Blue', 14, 155, 80, text_anchor='middle'))
+
d.append(g)
+
g = dw.Group(mask=whitemask)
+
g.append(dw.Circle(215, 115, 25, fill='black'))
+
g.append(dw.Text('White', 14, 215, 80, text_anchor='middle'))
+
d.append(g)
+
```
+
+
![svg](img/05_mask2.svg)
+
+
Mask alpha using opacity only:
+
+
```python
+
fullmask = dw.Mask(maskContentUnits='objectBoundingBox')
+
fullmask.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=1.0, fill='white'))
+
three_fourths = dw.Mask(maskContentUnits='objectBoundingBox')
+
three_fourths.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=0.75, fill='white'))
+
one_half = dw.Mask(maskContentUnits='objectBoundingBox')
+
one_half.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=0.5, fill='white'))
+
one_fourth = dw.Mask(maskContentUnits='objectBoundingBox')
+
one_fourth.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=0.25, fill='white'))
+
+
g = dw.Group(mask=fullmask)
+
g.append(dw.Circle(35, 35, 25))
+
g.append(dw.Text('100%', 14, 35, 80, text_anchor='middle'))
+
d.append(g)
+
g = dw.Group(mask=three_fourths)
+
g.append(dw.Circle(95, 35, 25))
+
g.append(dw.Text('50%', 14, 95, 80, text_anchor='middle'))
+
d.append(g)
+
g = dw.Group(mask=one_half)
+
g.append(dw.Circle(155, 35, 25))
+
g.append(dw.Text('50%', 14, 155, 80, text_anchor='middle'))
+
d.append(g)
+
g = dw.Group(mask=one_fourth)
+
g.append(dw.Circle(215, 35, 25))
+
g.append(dw.Text('25%', 14, 215, 80, text_anchor='middle'))
+
d.append(g)
+
```
+
+
![svg](img/05_mask3.svg)
+
+
+
## Group, Use, Defs, Image
+
+
### Group
+
+
```python
+
dw.Group(**kwargs)
+
```
+
+
Any style specified in the g tag will apply to all child elements in the group.
+
+
```python
+
g_house = dw.Group(id='house', fill='none', stroke='black')
+
g_house.append(dw.Rectangle(6, 50, 60, 60))
+
g_house.append(dw.Lines(6, 50, 36, 9, 66, 50))
+
g_house.append(dw.Lines(36, 110, 36, 80, 50, 80, 50, 110))
+
d.append(g_house)
+
+
g_man = dw.Group(id='man', fill='none', stroke='blue')
+
g_man.append(dw.Circle(85, 56, 10))
+
g_man.append(dw.Line(85, 66, 85, 80))
+
g_man.append(dw.Lines(76, 104, 85, 80, 94, 104))
+
g_man.append(dw.Lines(76, 70, 85, 76, 94, 70))
+
d.append(g_man)
+
+
g_woman = dw.Group(id='woman', fill='none', stroke='red')
+
g_woman.append(dw.Circle(110, 56, 10))
+
g_woman.append(dw.Lines(110, 66, 110, 80, 100, 90, 120, 90, 110, 80))
+
g_woman.append(dw.Line(104, 104, 108, 90))
+
g_woman.append(dw.Line(112, 90, 116, 104))
+
g_woman.append(dw.Lines(101, 70, 110, 76, 119, 70))
+
d.append(g_woman)
+
```
+
+
![svg](img/06_group.svg)
+
+
+
### Use
+
+
```python
+
dw.Use(other_elem, x, y, **kwargs)
+
```
+
+
```python
+
g_house = dw.Group(id='house', fill='none', stroke='black')
+
g_house.append(dw.Rectangle(6, 50, 60, 60))
+
g_house.append(dw.Lines(6, 50, 36, 9, 66, 50))
+
g_house.append(dw.Lines(36, 110, 36, 80, 50, 80, 50, 110))
+
d.append(g_house)
+
+
# Use id which is set
+
d.append(dw.Use('house', 100, 50))
+
# Or use variable name
+
d.append(dw.Use(g_house, 150, 20))
+
```
+
+
![svg](img/06_use.svg)
+
+
+
### Defs
+
+
Elements that are not appended to the drawing but are referenced by other elements will automatically be included in `<defs></defs>`.
+
([source](https://github.com/cduck/drawsvg/issues/46))
+
+
```python
+
d = dw.Drawing(200, 200, id_prefix='defs')
+
+
# Do not append `bond` to the drawing
+
bond = dw.Line(0, 0, 10, 10, stroke='black')
+
+
# `bond` is automatically added into <defs>
+
# A default `id` is generated if one isn't set
+
d.append(dw.Use(bond, 20, 50))
+
d.append(dw.Use(bond, 50, 50))
+
d.append(dw.Use(bond, 80, 50))
+
+
print(d.as_svg())
+
```
+
+
Output:
+
+
```svg
+
<?xml version="1.0" encoding="UTF-8"?>
+
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+
width="200" height="200" viewBox="0 0 200 200">
+
<defs>
+
<path d="M0,0 L10,10" stroke="black" id="defs0" />
+
</defs>
+
<use xlink:href="#defs0" x="20" y="50" />
+
<use xlink:href="#defs0" x="50" y="50" />
+
<use xlink:href="#defs0" x="80" y="50" />
+
</svg>
+
```
+
+
+
### Image
+
+
```python
+
dw.Image(x, y, width, height, path=None, data=None,
+
embed=False, mimeType=None, **kwargs)
+
```
+
+
```python
+
d.append(dw.Image(0, 0, 200, 200, 'example1.png', embed=True))
+
```
+
+
![svg](img/06_imag.svg)
+
+
+
## Transformations
+
+
### Translate
+
+
```python
+
transform = 'translate(x,y)'
+
```
+
+
This attribute can be added to many objects. Simple example:
+
+
```python
+
d.append(dw.Rectangle(0, 0, 40, 40))
+
d.append(dw.Rectangle(0, 0, 40, 40, fill='red', transform='translate(50,50)'))
+
```
+
+
![svg](img/07_trans.svg)
+
+
+
### Scale
+
+
```python
+
transform = 'scale(x_mult[, y_mult])'
+
```
+
+
Note that scaling also affects stroke width.
+
+
```python
+
square = dw.Rectangle(0, 0, 40, 40, fill='none', stroke_width=2)
+
d.append(dw.Use(square, 10, 10, stroke='black'))
+
d.append(dw.Use(square, 10, 10, stroke='red', transform='scale(2)'))
+
```
+
+
![svg](img/07_scale.svg)
+
+
It is possible to specify x and y scale separately:
+
+
```python
+
square = dw.Rectangle(0, 0, 40, 40, fill='none', stroke_width=2)
+
d.append(dw.Use(square, 10, 10, stroke='black'))
+
d.append(dw.Use(square, 10, 10, stroke='red', transform='scale(3,1.5)'))
+
```
+
+
![svg](img/07_scale2.svg)
+
+
Scaling around a center point:
+
+
```python
+
# Center of scaling: (100, 100)
+
d.append(dw.Circle(100, 100, 4, fill='black'))
+
# Non-scaled rectangle
+
rect = dw.Rectangle(70, 80, 60, 40, stroke='black', fill='none')
+
d.append(rect)
+
# Scaled rectangles
+
d.append(dw.Use(rect, 0, 0, transform='translate(-100,-100) scale(2)', stroke_width=0.5))
+
d.append(dw.Use(rect, 0, 0, transform='translate(-150,-150) scale(2.5)', stroke_width=0.4))
+
d.append(dw.Use(rect, 0, 0, transform='translate(-200,-200) scale(3)', stroke_width=0.33))
+
```
+
+
![svg](img/07_scalcent.svg)
+
+
+
### Rotate
+
+
```python
+
transform = 'rotate(angle,cx=0,cy=0)'
+
```
+
+
`angle` counts clockwise in degrees.
+
`cx`/`cy` are the center of rotation.
+
+
```python
+
# Show frame border
+
d.append(dw.Rectangle(0, 0, 200, 200, stroke='gray', fill='none'))
+
# Rotation is around (0, 0)
+
d.append(dw.Rectangle(70, 30, 40, 40, fill='silver'))
+
d.append(dw.Rectangle(70, 30, 40, 40, fill='gray', transform='rotate(22.5)'))
+
d.append(dw.Rectangle(70, 30, 40, 40, fill='black', transform='rotate(45)'))
+
```
+
+
![svg](img/07_rota.svg)
+
+
```python
+
# Center of rotation
+
d.append(dw.Circle(100, 100, 3, fill='black'))
+
# Non-rotated arrow
+
arrow = dw.Group(id='arrow')
+
arrow.append(dw.Line(110, 100, 160, 100))
+
arrow.append(dw.Lines(160, 100, 155, 95, 155, 105))
+
d.append(dw.Use(arrow, 0, 0, stroke='black', fill='black'))
+
# Rotated arrows
+
g = dw.Group(stroke='red', fill='red')
+
g.append(dw.Use(arrow, 0, 0, transform='rotate (60,100,100)'))
+
g.append(dw.Use(arrow, 0, 0, transform='rotate (-90,100,100)'))
+
g.append(dw.Use(arrow, 0, 0, transform='rotate (-150,100,100)'))
+
d.append(g)
+
```
+
+
![svg](img/07_rota2.svg)
+
+
+
### Skew
+
+
```python
+
transform = 'skewX(angle)'
+
transform = 'skewY(angle)'
+
```
+
+
```python
+
g = dw.Group(stroke='gray', stroke_dasharray='4 4')
+
g.append(dw.Line(0, 0, 200, 0))
+
g.append(dw.Line(20, 0, 20, 90))
+
g.append(dw.Line(120, 0, 120, 90))
+
d.append(g)
+
+
h = dw.Group(transform='translate(20,0)')
+
h1 = dw.Group(transform='skewX(30)')
+
h1.append(dw.Lines(50, 0, 0, 0, 0, 50,
+
stroke='black', fill='none', stroke_width=2))
+
h1.append(dw.Text('skewX', 16, 0, 60))
+
h.append(h1)
+
d.append(h)
+
+
i = dw.Group(transform='translate(120,0)')
+
i1 = dw.Group(transform='skewY(30)')
+
i1.append(dw.Lines(50, 0, 0, 0, 0, 50,
+
stroke='black', fill='none', stroke_width=2))
+
i1.append(dw.Text('skewY', 16, 0, 60))
+
i.append(i1)
+
d.append(i)
+
```
+
+
![svg](img/07_skew.svg)
+
+
+
### Cartesian Coordinates
+
+
A drawing which can be translated to Cartesian coordinates
+
(where y-coordinates increase upward, not downward)
+
by setting the translate-y value to the drawing's height, and also applying `scale(1,-1)`.
+
+
Trapezoid with origin to top left (the default):
+
+
```python
+
d.append(dw.Lines(0, 100, 0, 0, 100, 0,
+
fill='none', stroke='green', stroke_width=2))
+
d.append(dw.Lines(40, 40, 100, 40, 70, 70, 40, 70,
+
fill='silver', stroke='black', stroke_width=2))
+
d.append(dw.Text('downward y', 12, 5, 95))
+
```
+
+
![svg](img/07_cart1.svg)
+
+
Translated origin to bottom left and upward-y:
+
+
```python
+
g = dw.Group(transform='translate(0,100) scale(1,-1)')
+
g.append(dw.Lines(0, 100, 0, 0, 100, 0,
+
fill='none', stroke='green', stroke_width=2))
+
g.append(dw.Lines(40, 40, 100, 40, 70, 70, 40, 70,
+
fill='silver', stroke='black', stroke_width=2))
+
g.append(dw.Text('upward y', 12, 5, 95))
+
d.append(g)
+
```
+
+
![svg](img/07_cart2.svg)
+
+
Alternatively, apply `scale(1,-1)` to the whole drawing:
+
+
```python
+
d = dw.Drawing(100, 100, id_prefix='cart3', transform='scale(1,-1)')
+
d.append(dw.Lines(0, 100, 0, 0, 100, 0,
+
fill='none', stroke='green', stroke_width=2))
+
d.append(dw.Lines(40, 40, 100, 40, 70, 70, 40, 70,
+
fill='silver', stroke='black', stroke_width=2))
+
d.append(dw.Text('upward y', 12, 5, 95))
+
```
+
+
![svg](img/07_cart3.svg)
+
+
+
## Credits
+
+
Written by joachim heintz 2023. Edited by Casey Duckering.
+
+
Most examples are based on J. David Eisenberg, SVG Essentials, O'Reilly 2002.
+
+
Thanks to [Ahmad Aufar Husaini](https://github.com/aufarah) for his fork (draw2Svg) and for providing some documentation [here](https://draw2svg.netlify.app/) (some examples are used in this Quick Reference).
+
+
Thanks to [Casey Duckering](https://github.com/cduck) for drawsvg and many helpful explanations on its [discussion page](https://github.com/cduck/drawsvg/discussions).
+4
mkdocs.yml
···
+
site_name: Drawsvg Quick Reference
+
nav:
+
- Home: index.md
+
theme: readthedocs