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

Quick reference docs (#90)

added docs

authored by joachimheintz.tngl.sh and committed by cduck.me fc5d923e 5e11115e

+2072 -1
+1 -1
.gitignore
··· 3 3 /MANIFEST 4 4 /dist 5 5 /*.egg-info 6 - 6 + *.ipynb_checkpoints
+9
docs/img/01_circ.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="100" viewBox="0 0 300 100"> 4 + <defs> 5 + </defs> 6 + <circle cx="50" cy="50" r="40" /> 7 + <circle cx="150" cy="50" r="40" stroke="black" fill="none" /> 8 + <circle cx="250" cy="50" r="40" stroke="black" fill="none" stroke-width="15" /> 9 + </svg>
+9
docs/img/01_ellip.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="100" viewBox="0 0 300 100"> 4 + <defs> 5 + </defs> 6 + <ellipse cx="50" cy="50" rx="50" ry="30" /> 7 + <ellipse cx="160" cy="50" rx="50" ry="30" stroke="black" fill="none" /> 8 + <ellipse cx="250" cy="50" rx="30" ry="45" stroke="black" fill="none" /> 9 + </svg>
+7
docs/img/01_line.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="100" viewBox="0 0 100 100"> 4 + <defs> 5 + </defs> 6 + <path d="M30,30 L90,90" stroke="black" /> 7 + </svg>
+7
docs/img/01_multilines.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="100" viewBox="0 0 100 100"> 4 + <defs> 5 + </defs> 6 + <path d="M10,90 L10,10 L80,90 L80,10" fill="none" stroke="black" /> 7 + </svg>
+7
docs/img/01_multilines2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="100" viewBox="0 0 300 100"> 4 + <defs> 5 + </defs> 6 + <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" /> 7 + </svg>
+7
docs/img/01_polygon.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="100" viewBox="0 0 100 100"> 4 + <defs> 5 + </defs> 6 + <path d="M48,16 L16,96 L96,48 L0,48 L88,96 Z" stroke="black" fill="none" /> 7 + </svg>
+10
docs/img/01_rect.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="500" height="200" viewBox="0 0 500 200"> 4 + <defs> 5 + </defs> 6 + <rect x="10" y="10" width="90" height="150" /> 7 + <rect x="120" y="10" width="60" height="120" fill="none" stroke="black" /> 8 + <rect x="210" y="10" width="75" height="90" fill="#0000ff" stroke="red" stroke-width="7" stroke-opacity="0.5" /> 9 + <rect x="300" y="10" width="105" height="60" fill="yellow" fill-opacity="0.5" stroke="green" stroke-width="2" stroke-dasharray="5,2" /> 10 + </svg>
+11
docs/img/01_rectround.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="500" height="200" viewBox="0 0 500 200"> 4 + <defs> 5 + </defs> 6 + <rect x="10" y="10" width="80" height="180" rx="10" ry="10" stroke="black" fill="none" /> 7 + <rect x="110" y="10" width="80" height="180" ry="20" stroke="black" fill="none" /> 8 + <rect x="210" y="10" width="80" height="180" rx="40" stroke="black" fill="none" /> 9 + <rect x="310" y="10" width="80" height="180" rx="30" ry="10" stroke="black" fill="none" /> 10 + <rect x="410" y="10" width="80" height="180" rx="10" ry="30" stroke="black" fill="none" /> 11 + </svg>
+9
docs/img/02_dash.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="110" height="40" viewBox="0 0 110 40"> 4 + <defs> 5 + </defs> 6 + <path d="M10,10 L100,10" stroke="black" stroke-width="2" stroke-dasharray="9,5" /> 7 + <path d="M10,20 L100,20" stroke="black" stroke-width="2" stroke-dasharray="5,3,9,2" /> 8 + <path d="M10,30 L100,30" stroke="black" stroke-width="2" stroke-dasharray="9,3,5" /> 9 + </svg>
+16
docs/img/02_foso.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="100" viewBox="0 0 300 100"> 4 + <defs> 5 + </defs> 6 + <path d="M0,10 L290,10" stroke="black" stroke-width="5" stroke-opacity="0.1" /> 7 + <rect x="0" y="70" width="50" height="50" fill="red" fill-opacity="0.1" /> 8 + <path d="M0,20 L290,20" stroke="black" stroke-width="5" stroke-opacity="0.30000000000000004" /> 9 + <rect x="60" y="70" width="50" height="50" fill="red" fill-opacity="0.30000000000000004" /> 10 + <path d="M0,30 L290,30" stroke="black" stroke-width="5" stroke-opacity="0.5" /> 11 + <rect x="120" y="70" width="50" height="50" fill="red" fill-opacity="0.5" /> 12 + <path d="M0,40 L290,40" stroke="black" stroke-width="5" stroke-opacity="0.7" /> 13 + <rect x="180" y="70" width="50" height="50" fill="red" fill-opacity="0.7" /> 14 + <path d="M0,50 L290,50" stroke="black" stroke-width="5" stroke-opacity="0.9" /> 15 + <rect x="240" y="70" width="50" height="50" fill="red" fill-opacity="0.9" /> 16 + </svg>
+11
docs/img/02_fsc.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="60" viewBox="0 0 100 60"> 4 + <defs> 5 + </defs> 6 + <path d="M10,10 L80,10" stroke="red" stroke-width="5" /> 7 + <path d="M10,20 L80,20" stroke="#9f9" stroke-width="5" /> 8 + <path d="M10,30 L80,30" stroke="#9999ff" stroke-width="5" /> 9 + <path d="M10,40 L80,40" stroke="rgb(255,128,64)" stroke-width="5" /> 10 + <path d="M10,50 L80,50" stroke="rgb(60%,20%,60%)" stroke-width="5" /> 11 + </svg>
+12
docs/img/02_join.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="100" viewBox="0 0 300 100"> 4 + <defs> 5 + </defs> 6 + <path d="M0,20 L300,20" stroke="gray" /> 7 + <g stroke-width="20" stroke="black" fill="none"> 8 + <path d="M10,80 L50,20 L90,80" stroke-linejoin="miter" /> 9 + <path d="M110,80 L150,20 L190,80" stroke-linejoin="round" /> 10 + <path d="M210,80 L250,20 L290,80" stroke-linejoin="bevel" /> 11 + </g> 12 + </svg>
+11
docs/img/02_linecap.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="150" height="100" viewBox="0 0 150 100"> 4 + <defs> 5 + </defs> 6 + <path d="M10,15 L50,15" stroke="black" stroke-width="15" stroke-linecap="butt" /> 7 + <path d="M10,45 L50,45" stroke="black" stroke-width="15" stroke-linecap="round" /> 8 + <path d="M10,75 L50,75" stroke="black" stroke-width="15" stroke-linecap="square" /> 9 + <path d="M10,0 L10,100" stroke="#999" /> 10 + <path d="M50,0 L50,100" stroke="#999" /> 11 + </svg>
+12
docs/img/02_mlimit.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="100" viewBox="0 0 300 100"> 4 + <defs> 5 + </defs> 6 + <path d="M0,30 L300,30" stroke="gray" /> 7 + <g stroke-width="20" stroke="black" fill="none" stroke-linejoin="miter"> 8 + <path d="M10,90 L40,30 L70,90" /> 9 + <path d="M100,90 L130,30 L160,90" stroke-miterlimit="2.3" /> 10 + <path d="M190,90 L220,30 L250,90" stroke-miterlimit="1" /> 11 + </g> 12 + </svg>
+26
docs/img/02_strokewdth.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="320" height="100" viewBox="0 0 320 100"> 4 + <defs> 5 + </defs> 6 + <path d="M15,10 L15,90" stroke="black" stroke-width="11" /> 7 + <path d="M30,10 L30,90" stroke="black" stroke-width="10" /> 8 + <path d="M45,10 L45,90" stroke="black" stroke-width="9" /> 9 + <path d="M60,10 L60,90" stroke="black" stroke-width="8" /> 10 + <path d="M75,10 L75,90" stroke="black" stroke-width="7" /> 11 + <path d="M90,10 L90,90" stroke="black" stroke-width="6" /> 12 + <path d="M105,10 L105,90" stroke="black" stroke-width="5" /> 13 + <path d="M120,10 L120,90" stroke="black" stroke-width="4" /> 14 + <path d="M135,10 L135,90" stroke="black" stroke-width="3" /> 15 + <path d="M150,10 L150,90" stroke="black" stroke-width="2" /> 16 + <path d="M165,10 L165,90" stroke="black" stroke-width="1" /> 17 + <path d="M180,10 L180,90" stroke="black" stroke-width="2" /> 18 + <path d="M195,10 L195,90" stroke="black" stroke-width="3" /> 19 + <path d="M210,10 L210,90" stroke="black" stroke-width="4" /> 20 + <path d="M225,10 L225,90" stroke="black" stroke-width="5" /> 21 + <path d="M240,10 L240,90" stroke="black" stroke-width="6" /> 22 + <path d="M255,10 L255,90" stroke="black" stroke-width="7" /> 23 + <path d="M270,10 L270,90" stroke="black" stroke-width="8" /> 24 + <path d="M285,10 L285,90" stroke="black" stroke-width="9" /> 25 + <path d="M300,10 L300,90" stroke="black" stroke-width="10" /> 26 + </svg>
+10
docs/img/03_pA.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="400" height="200" viewBox="0 0 400 200" stroke-width="3" fill="none"> 4 + <defs> 5 + </defs> 6 + <path d="M125,75 A100,50,0,0,0,225,125" stroke="red" /> 7 + <path d="M125,75 A100,50,0,0,1,225,125" stroke="blue" /> 8 + <path d="M125,75 A100,50,0,1,0,225,125" stroke="rgb(0 80 255)" stroke-dasharray="5 3" /> 9 + <path d="M125,75 A100,50,0,1,1,225,125" stroke="rgb(255 80 0)" stroke-dasharray="5 3" /> 10 + </svg>
+48
docs/img/03_pC.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="650" height="100" viewBox="0 0 650 100"> 4 + <defs> 5 + </defs> 6 + <path d="M40,50 C10,10,140,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(0,0)" /> 7 + <g stroke="gray" fill="gray" stroke-width="1" transform="translate(0,0)"> 8 + <circle cx="10" cy="10" r="2" /> 9 + <circle cx="140" cy="10" r="2" /> 10 + <path d="M40,50 L10,10" /> 11 + <path d="M110,50 L140,10" /> 12 + </g> 13 + <path d="M40,50 C60,10,90,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(100,0)" /> 14 + <g stroke="gray" fill="gray" stroke-width="1" transform="translate(100,0)"> 15 + <circle cx="60" cy="10" r="2" /> 16 + <circle cx="90" cy="10" r="2" /> 17 + <path d="M40,50 L60,10" /> 18 + <path d="M110,50 L90,10" /> 19 + </g> 20 + <path d="M40,50 C110,10,40,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(200,0)" /> 21 + <g stroke="gray" fill="gray" stroke-width="1" transform="translate(200,0)"> 22 + <circle cx="110" cy="10" r="2" /> 23 + <circle cx="40" cy="10" r="2" /> 24 + <path d="M40,50 L110,10" /> 25 + <path d="M110,50 L40,10" /> 26 + </g> 27 + <path d="M40,50 C110,10,40,10,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(300,0)" /> 28 + <g stroke="gray" fill="gray" stroke-width="1" transform="translate(300,0)"> 29 + <circle cx="110" cy="10" r="2" /> 30 + <circle cx="40" cy="10" r="2" /> 31 + <path d="M40,50 L110,10" /> 32 + <path d="M110,50 L40,10" /> 33 + </g> 34 + <path d="M40,50 C60,10,90,90,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(400,0)" /> 35 + <g stroke="gray" fill="gray" stroke-width="1" transform="translate(400,0)"> 36 + <circle cx="60" cy="10" r="2" /> 37 + <circle cx="90" cy="90" r="2" /> 38 + <path d="M40,50 L60,10" /> 39 + <path d="M110,50 L90,90" /> 40 + </g> 41 + <path d="M40,50 C110,10,40,90,110,50" stroke="black" fill="none" stroke-width="3" transform="translate(500,0)" /> 42 + <g stroke="gray" fill="gray" stroke-width="1" transform="translate(500,0)"> 43 + <circle cx="110" cy="10" r="2" /> 44 + <circle cx="40" cy="90" r="2" /> 45 + <path d="M40,50 L110,10" /> 46 + <path d="M110,50 L40,90" /> 47 + </g> 48 + </svg>
+8
docs/img/03_pHV.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="60" viewBox="0 0 100 60"> 4 + <defs> 5 + </defs> 6 + <path d="M10,10 H100 M10,20 H100 V50" stroke="black" fill="none" id="pathHV0" /> 7 + <use xlink:href="#pathHV0" /> 8 + </svg>
+11
docs/img/03_pL.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="70" viewBox="0 0 100 70"> 4 + <defs> 5 + </defs> 6 + <g stroke="black" fill="none"> 7 + <path d="M10,10 L100,10" /> 8 + <path d="M10,20 L100,20 L100,50" /> 9 + <path d="M40,60 L10,60 L40,42 M60,60 L90,60 L60,42" /> 10 + </g> 11 + </svg>
+21
docs/img/03_pQ.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="700" height="130" viewBox="0 0 700 130"> 4 + <defs> 5 + <path d="M30,75 Q240,30,300,120" stroke="black" fill="none" stroke-width="3" id="pathQ0" /> 6 + </defs> 7 + <use xlink:href="#pathQ0" /> 8 + <use xlink:href="#pathQ0" x="300" y="0" /> 9 + <g stroke="gray" fill="gray"> 10 + <circle cx="330" cy="75" r="3" /> 11 + <circle cx="600" cy="120" r="3" /> 12 + <circle cx="540" cy="30" r="3" /> 13 + <path d="M330,75 L540,30" /> 14 + <path d="M540,30 L600,120" /> 15 + <path d="M330,75 L600,120" stroke-dasharray="5,5" /> 16 + <circle cx="435" cy="52.5" r="3" /> 17 + <circle cx="570" cy="75" r="3" /> 18 + <path d="M435,52.5 L570,75" /> 19 + <circle cx="502.5" cy="63.75" r="4" fill="none" /> 20 + </g> 21 + </svg>
+16
docs/img/03_pS.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="250" height="150" viewBox="0 0 250 150"> 4 + <defs> 5 + </defs> 6 + <path d="M30,100 C50,30,70,50,100,100 S150,40,200,80" stroke="black" fill="none" stroke-width="3" /> 7 + <circle cx="30" cy="100" r="4" /> 8 + <circle cx="50" cy="30" r="2" stroke="gray" fill="gray" /> 9 + <path d="M30,100 L50,30" stroke="gray" /> 10 + <circle cx="100" cy="100" r="4" /> 11 + <circle cx="70" cy="50" r="2" stroke="gray" fill="gray" /> 12 + <path d="M100,100 L70,50" stroke="gray" /> 13 + <circle cx="200" cy="80" r="4" /> 14 + <circle cx="150" cy="40" r="2" stroke="gray" fill="gray" /> 15 + <path d="M200,80 L150,40" stroke="gray" /> 16 + </svg>
+8
docs/img/03_pT.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="400" height="100" viewBox="0 0 400 100"> 4 + <defs> 5 + </defs> 6 + <path d="M30,60 Q80,-10,100,60 Q130,25,200,40" stroke="black" fill="none" stroke-width="3" /> 7 + <path d="M30,60 Q80,-10,100,60 T200,40" stroke="black" fill="none" stroke-width="3" transform="translate(200,0)" /> 8 + </svg>
+8
docs/img/03_pZ.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="90" height="70" viewBox="0 0 90 70"> 4 + <defs> 5 + </defs> 6 + <path d="M10,10 h30 v50 h-30 Z M50,10 h30 v50 Z" stroke="black" fill="none" id="pathZ0" /> 7 + <use xlink:href="#pathZ0" /> 8 + </svg>
+16
docs/img/04_align.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="250" height="120" viewBox="0 0 250 120"> 4 + <defs> 5 + </defs> 6 + <path d="M75,100 L75,0" stroke="gray" /> 7 + <path d="M140,30 L250,30" stroke="gray" /> 8 + <path d="M140,60 L250,60" stroke="gray" /> 9 + <path d="M140,90 L250,90" stroke="gray" /> 10 + <text x="75" y="30" font-size="24" text-anchor="start">Start</text> 11 + <text x="75" y="60" font-size="24" text-anchor="middle">Middle</text> 12 + <text x="75" y="90" font-size="24" text-anchor="end">End</text> 13 + <text x="150" y="30" font-size="24" dominant-baseline="bottom">Auto</text> 14 + <text x="150" y="60" font-size="24" dominant-baseline="middle">Middle</text> 15 + <text x="150" y="90" font-size="24" dominant-baseline="top">Hanging</text> 16 + </svg>
+13
docs/img/04_fill.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="550" height="370" viewBox="0 0 550 370"> 4 + <defs> 5 + </defs> 6 + <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" /> 7 + <text x="20" y="60" font-size="50">Simplest Text</text> 8 + <text x="20" y="120" font-size="50" stroke="black">Outline / Filled</text> 9 + <text x="20" y="180" font-size="50" stroke="black" stroke-width="5">Too big stroke</text> 10 + <text x="20" y="240" font-size="50" stroke="black" stroke-width="0.5" fill="none">Outlined only</text> 11 + <text x="20" y="300" font-size="50" stroke="black" fill="red">Outlined and colored</text> 12 + <text x="20" y="360" font-size="50" fill="blue">Colored fill only</text> 13 + </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
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="400" height="200" viewBox="0 0 400 200"> 4 + <defs> 5 + </defs> 6 + <text x="20" y="30" font-size="20" textLength="250" lengthAdjust="spacing">Two words</text> 7 + <text x="20" y="70" font-size="20" textLength="250" lengthAdjust="spacingAndGlyphs">Two words</text> 8 + <text x="20" y="110" font-size="20">Two words (normal length)</text> 9 + <text x="20" y="150" font-size="20" textLength="80" lengthAdjust="spacing">Two words</text> 10 + <text x="20" y="190" font-size="20" textLength="80" lengthAdjust="spacingAndGlyphs">Two words</text> 11 + <path d="M20,10 L20,195" stroke="gray" /> 12 + <path d="M270,80 L270,10" stroke="gray" /> 13 + <path d="M100,130 L100,195" stroke="gray" /> 14 + </svg>
+8
docs/img/04_multiline_text.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="100" viewBox="0 0 200 100"> 4 + <defs> 5 + </defs> 6 + <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> 7 + <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> 8 + </svg>
+8
docs/img/04_mutiline_text.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="100" viewBox="0 0 200 100"> 4 + <defs> 5 + </defs> 6 + <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> 7 + <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> 8 + </svg>
+31
docs/img/04_path.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="500" height="200" viewBox="0 0 500 200"> 4 + <defs> 5 + <path d="M30,50 C50,20,70,20,120,50 S150,10,200,50" stroke="gray" fill="none" id="textpath0" /> 6 + <path d="M250,30 L300,30 A30,30,0,0,1,330,60 L330,110" stroke="gray" fill="none" id="textpath1" /> 7 + <path d="M30,110 L100,110 L100,160" stroke="gray" fill="none" id="textpath2" /> 8 + <path d="M150,110 A40,30,0,1,0,230,110 M250,110 L270,140" stroke="gray" fill="none" id="textpath3" /> 9 + <path d="M330,130 L330,160 A30,30,0,0,1,300,180 L200,180" stroke="gray" fill="none" id="textpath4" /> 10 + </defs> 11 + <use xlink:href="#textpath0" /> 12 + <use xlink:href="#textpath1" /> 13 + <use xlink:href="#textpath2" /> 14 + <use xlink:href="#textpath3" /> 15 + <use xlink:href="#textpath4" /> 16 + <text font-size="14"><textPath xlink:href="#textpath0"> 17 + <tspan dy="0em">Following a cubic Bézier curve</tspan> 18 + </textPath></text> 19 + <text font-size="14"><textPath xlink:href="#textpath1"> 20 + <tspan dy="0em">Going 'round the bend</tspan> 21 + </textPath></text> 22 + <text font-size="14"><textPath xlink:href="#textpath2"> 23 + <tspan dy="0em">Making a quick turn</tspan> 24 + </textPath></text> 25 + <text font-size="14"><textPath xlink:href="#textpath3"> 26 + <tspan dy="0em">Text along a broken path</tspan> 27 + </textPath></text> 28 + <text font-size="14" offset="50%" text-anchor="middle"><textPath xlink:href="#textpath4" startOffset="50%"> 29 + <tspan dy="0em">centered</tspan> 30 + </textPath></text> 31 + </svg>
+8
docs/img/04_rot.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="100" viewBox="0 0 200 100"> 4 + <defs> 5 + </defs> 6 + <text x="20" y="20" font-size="20" letter-spacing="20" rotate="90">Rotate</text> 7 + <text x="20" y="80" font-size="20" letter-spacing="20" rotate="0 90 180 270">Rotate</text> 8 + </svg>
+7
docs/img/04_rot2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="80" viewBox="0 0 200 80"> 4 + <defs> 5 + </defs> 6 + <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> 7 + </svg>
+7
docs/img/04_tspan.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="600" height="50" viewBox="0 0 600 50"> 4 + <defs> 5 + </defs> 6 + <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> 7 + </svg>
+7
docs/img/04_tspan2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="160" viewBox="0 0 300 160"> 4 + <defs> 5 + </defs> 6 + <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> 7 + </svg>
+7
docs/img/04_tspan3.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="160" viewBox="0 0 300 160"> 4 + <defs> 5 + </defs> 6 + <text x="10" y="30" font-size="24" dx="0,0,21,54" dy="0,5,21,54">Fall</text> 7 + </svg>
+16
docs/img/04_weight.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="600" height="200" viewBox="0 0 600 200"> 4 + <defs> 5 + </defs> 6 + <text x="20" y="35" font-size="30" font-weight="bold">bold</text> 7 + <text x="20" y="75" font-size="30" font-style="italic">italic</text> 8 + <text x="20" y="115" font-size="30" text-decoration="underline">under</text> 9 + <text x="20" y="155" font-size="30" text-decoration="overline">over</text> 10 + <text x="20" y="195" font-size="30" text-decoration="line-through">through</text> 11 + <text x="200" y="35" font-size="30">normal word space</text> 12 + <text x="200" y="75" font-size="30" word-spacing="10">more word space</text> 13 + <text x="200" y="115" font-size="30" word-spacing="-5">less word space</text> 14 + <text x="200" y="155" font-size="30" letter-spacing="8">wide letter space</text> 15 + <text x="200" y="195" font-size="30" letter-spacing="-2">narrow letter space</text> 16 + </svg>
+12
docs/img/05_clip.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="200" viewBox="0 0 200 200"> 4 + <defs> 5 + <clipPath id="clip0"> 6 + <rect x="100" y="100" width="100" height="100" /> 7 + </clipPath> 8 + </defs> 9 + <rect x="100" y="100" width="100" height="100" stroke="gray" fill="none" /> 10 + <circle cx="100" cy="100" r="100" fill="none" stroke="gray" stroke-dasharray="5 5" /> 11 + <circle cx="100" cy="100" r="100" fill="cyan" clip-path="url(#clip0)" /> 12 + </svg>
+12
docs/img/05_clip2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="600" height="200" viewBox="0 0 600 200"> 4 + <defs> 5 + <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" /> 6 + <clipPath id="clip21"> 7 + <circle cx="150" cy="100" r="75" /> 8 + </clipPath> 9 + </defs> 10 + <use xlink:href="#clip20" /> 11 + <use xlink:href="#clip20" x="300" y="0" clip-path="url(#clip21)" /> 12 + </svg>
+29
docs/img/05_clip3.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="300" viewBox="0 0 300 300"> 4 + <defs> 5 + <g id="clip30"> 6 + <rect x="0" y="50" width="90" height="60" fill="#999" /> 7 + <circle cx="25" cy="25" r="25" fill="#666" /> 8 + <path d="M30,0 L80,0 L80,100 Z" fill="#ccc" /> 9 + </g> 10 + <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" /> 11 + <clipPath id="clip32"> 12 + <use xlink:href="#clip31" x="0" y="0" /> 13 + </clipPath> 14 + <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> 15 + <clipPath id="clip34"> 16 + <use xlink:href="#clip33" x="0" y="0" /> 17 + </clipPath> 18 + </defs> 19 + <use xlink:href="#clip30" x="0" y="0" clip-path="url(#clip32)" /> 20 + <g transform="translate(100,0)"> 21 + <use xlink:href="#clip30" /> 22 + <use xlink:href="#clip31" x="0" y="0" /> 23 + </g> 24 + <use xlink:href="#clip30" x="0" y="150" clip-path="url(#clip34)" /> 25 + <g transform="translate(100,150)"> 26 + <use xlink:href="#clip30" /> 27 + <use xlink:href="#clip33" x="0" y="0" /> 28 + </g> 29 + </svg>
+11
docs/img/05_lingrad.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="80" viewBox="0 0 200 80"> 4 + <defs> 5 + <linearGradient x1="150" y1="0" x2="0" y2="0" gradientUnits="userSpaceOnUse" id="grad10"> 6 + <stop offset="0" stop-color="green" /> 7 + <stop offset="1" stop-color="yellow" /> 8 + </linearGradient> 9 + </defs> 10 + <rect x="10" y="10" width="150" height="60" stroke="black" fill="url(#grad10)" /> 11 + </svg>
+15
docs/img/05_mask.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="100" viewBox="0 0 200 100"> 4 + <defs> 5 + <linearGradient x1="0" y1="0" x2="1" y2="0" gradientUnits="objectBoundingBox" id="mask10"> 6 + <stop offset="0" stop-color="white" /> 7 + <stop offset="1" stop-color="black" /> 8 + </linearGradient> 9 + <mask id="mask11"> 10 + <rect x="30" y="0" width="100" height="100" fill="url(#mask10)" /> 11 + </mask> 12 + </defs> 13 + <rect x="0" y="0" width="200" height="100" fill="cyan" stroke="blue" stroke-width="2" /> 14 + <rect x="0" y="0" width="200" height="100" fill="pink" stroke="red" stroke-width="2" mask="url(#mask11)" /> 15 + </svg>
+38
docs/img/05_mask2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="250" height="150" viewBox="0 0 250 150"> 4 + <defs> 5 + <mask maskContentUnits="objectBoundingBox" id="mask20"> 6 + <rect x="0" y="0" width="1" height="1" fill="#f00" /> 7 + </mask> 8 + <mask maskContentUnits="objectBoundingBox" id="mask21"> 9 + <rect x="0" y="0" width="1" height="1" fill="#0f0" /> 10 + </mask> 11 + <mask maskContentUnits="objectBoundingBox" id="mask22"> 12 + <rect x="0" y="0" width="1" height="1" fill="#00f" /> 13 + </mask> 14 + <mask maskContentUnits="objectBoundingBox" id="mask23"> 15 + <rect x="0" y="0" width="1" height="1" fill="#fff" /> 16 + </mask> 17 + </defs> 18 + <rect x="10" y="10" width="50" height="50" fill="#f00" /> 19 + <rect x="70" y="10" width="50" height="50" fill="#0f0" /> 20 + <rect x="130" y="10" width="50" height="50" fill="#00f" /> 21 + <rect x="190" y="10" width="50" height="50" fill="#fff" stroke="black" /> 22 + <g mask="url(#mask20)"> 23 + <circle cx="35" cy="115" r="25" fill="black" /> 24 + <text x="35" y="80" font-size="14" text-anchor="middle">Red</text> 25 + </g> 26 + <g mask="url(#mask21)"> 27 + <circle cx="95" cy="115" r="25" fill="black" /> 28 + <text x="95" y="80" font-size="14" text-anchor="middle">Green</text> 29 + </g> 30 + <g mask="url(#mask22)"> 31 + <circle cx="155" cy="115" r="25" fill="black" /> 32 + <text x="155" y="80" font-size="14" text-anchor="middle">Blue</text> 33 + </g> 34 + <g mask="url(#mask23)"> 35 + <circle cx="215" cy="115" r="25" fill="black" /> 36 + <text x="215" y="80" font-size="14" text-anchor="middle">White</text> 37 + </g> 38 + </svg>
+34
docs/img/05_mask3.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="250" height="100" viewBox="0 0 250 100"> 4 + <defs> 5 + <mask maskContentUnits="objectBoundingBox" id="mask30"> 6 + <rect x="0" y="0" width="1" height="1" fill-opacity="1.0" fill="white" /> 7 + </mask> 8 + <mask maskContentUnits="objectBoundingBox" id="mask31"> 9 + <rect x="0" y="0" width="1" height="1" fill-opacity="0.75" fill="white" /> 10 + </mask> 11 + <mask maskContentUnits="objectBoundingBox" id="mask32"> 12 + <rect x="0" y="0" width="1" height="1" fill-opacity="0.5" fill="white" /> 13 + </mask> 14 + <mask maskContentUnits="objectBoundingBox" id="mask33"> 15 + <rect x="0" y="0" width="1" height="1" fill-opacity="0.25" fill="white" /> 16 + </mask> 17 + </defs> 18 + <g mask="url(#mask30)"> 19 + <circle cx="35" cy="35" r="25" /> 20 + <text x="35" y="80" font-size="14" text-anchor="middle">100%</text> 21 + </g> 22 + <g mask="url(#mask31)"> 23 + <circle cx="95" cy="35" r="25" /> 24 + <text x="95" y="80" font-size="14" text-anchor="middle">50%</text> 25 + </g> 26 + <g mask="url(#mask32)"> 27 + <circle cx="155" cy="35" r="25" /> 28 + <text x="155" y="80" font-size="14" text-anchor="middle">50%</text> 29 + </g> 30 + <g mask="url(#mask33)"> 31 + <circle cx="215" cy="35" r="25" /> 32 + <text x="215" y="80" font-size="14" text-anchor="middle">25%</text> 33 + </g> 34 + </svg>
+11
docs/img/05_radgrad.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="400" height="200" viewBox="0 0 400 200"> 4 + <defs> 5 + <radialGradient cx="200" cy="100" r="100" gradientUnits="userSpaceOnUse" id="grad20"> 6 + <stop offset="0" stop-color="green" stop-opacity="1" /> 7 + <stop offset="1" stop-color="orange" stop-opacity="1" /> 8 + </radialGradient> 9 + </defs> 10 + <rect x="0" y="0" width="100%" height="100%" fill="url(#grad20)" /> 11 + </svg>
+24
docs/img/06_group.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="240" height="120" viewBox="0 0 240 120"> 4 + <defs> 5 + </defs> 6 + <g id="house" fill="none" stroke="black"> 7 + <rect x="6" y="50" width="60" height="60" /> 8 + <path d="M6,50 L36,9 L66,50" /> 9 + <path d="M36,110 L36,80 L50,80 L50,110" /> 10 + </g> 11 + <g id="man" fill="none" stroke="blue"> 12 + <circle cx="85" cy="56" r="10" /> 13 + <path d="M85,66 L85,80" /> 14 + <path d="M76,104 L85,80 L94,104" /> 15 + <path d="M76,70 L85,76 L94,70" /> 16 + </g> 17 + <g id="woman" fill="none" stroke="red"> 18 + <circle cx="110" cy="56" r="10" /> 19 + <path d="M110,66 L110,80 L100,90 L120,90 L110,80" /> 20 + <path d="M104,104 L108,90" /> 21 + <path d="M112,90 L116,104" /> 22 + <path d="M101,70 L110,76 L119,70" /> 23 + </g> 24 + </svg>
+7
docs/img/06_imag.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="200" viewBox="0 0 200 200"> 4 + <defs> 5 + </defs> 6 + <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=" /> 7 + </svg>
+14
docs/img/06_use.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="220" height="170" viewBox="0 0 220 170"> 4 + <defs> 5 + <g id="house" fill="none" stroke="black"> 6 + <rect x="6" y="50" width="60" height="60" /> 7 + <path d="M6,50 L36,9 L66,50" /> 8 + <path d="M36,110 L36,80 L50,80 L50,110" /> 9 + </g> 10 + </defs> 11 + <use xlink:href="#house" /> 12 + <use xlink:href="#house" x="100" y="50" /> 13 + <use xlink:href="#house" x="150" y="20" /> 14 + </svg>
+9
docs/img/07_cart1.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="100" viewBox="0 0 100 100"> 4 + <defs> 5 + </defs> 6 + <path d="M0,100 L0,0 L100,0" fill="none" stroke="green" stroke-width="2" /> 7 + <path d="M40,40 L100,40 L70,70 L40,70" fill="silver" stroke="black" stroke-width="2" /> 8 + <text x="5" y="95" font-size="12">downward y</text> 9 + </svg>
+11
docs/img/07_cart2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="100" viewBox="0 0 100 100"> 4 + <defs> 5 + </defs> 6 + <g transform="translate(0,100) scale(1,-1)"> 7 + <path d="M0,100 L0,0 L100,0" fill="none" stroke="green" stroke-width="2" /> 8 + <path d="M40,40 L100,40 L70,70 L40,70" fill="silver" stroke="black" stroke-width="2" /> 9 + <text x="5" y="95" font-size="12">upward y</text> 10 + </g> 11 + </svg>
+9
docs/img/07_cart3.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="100" height="100" viewBox="0 0 100 100" transform="scale(1,-1)"> 4 + <defs> 5 + </defs> 6 + <path d="M0,100 L0,0 L100,0" fill="none" stroke="green" stroke-width="2" /> 7 + <path d="M40,40 L100,40 L70,70 L40,70" fill="silver" stroke="black" stroke-width="2" /> 8 + <text x="5" y="95" font-size="12">upward y</text> 9 + </svg>
+10
docs/img/07_rota.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="200" viewBox="0 0 200 200"> 4 + <defs> 5 + </defs> 6 + <rect x="0" y="0" width="200" height="200" stroke="gray" fill="none" /> 7 + <rect x="70" y="30" width="40" height="40" fill="silver" /> 8 + <rect x="70" y="30" width="40" height="40" fill="gray" transform="rotate(22.5)" /> 9 + <rect x="70" y="30" width="40" height="40" fill="black" transform="rotate(45)" /> 10 + </svg>
+17
docs/img/07_rota2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="200" viewBox="0 0 300 200"> 4 + <defs> 5 + <g id="arrow"> 6 + <path d="M110,100 L160,100" /> 7 + <path d="M160,100 L155,95 L155,105" /> 8 + </g> 9 + </defs> 10 + <circle cx="100" cy="100" r="3" fill="black" /> 11 + <use xlink:href="#arrow" x="0" y="0" stroke="black" fill="black" /> 12 + <g stroke="red" fill="red"> 13 + <use xlink:href="#arrow" x="0" y="0" transform="rotate (60,100,100)" /> 14 + <use xlink:href="#arrow" x="0" y="0" transform="rotate (-90,100,100)" /> 15 + <use xlink:href="#arrow" x="0" y="0" transform="rotate (-150,100,100)" /> 16 + </g> 17 + </svg>
+12
docs/img/07_scalcent.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="300" height="200" viewBox="0 0 300 200"> 4 + <defs> 5 + <rect x="70" y="80" width="60" height="40" stroke="black" fill="none" id="scalecenter0" /> 6 + </defs> 7 + <circle cx="100" cy="100" r="4" fill="black" /> 8 + <use xlink:href="#scalecenter0" /> 9 + <use xlink:href="#scalecenter0" x="0" y="0" transform="translate(-100,-100) scale(2)" stroke-width="0.5" /> 10 + <use xlink:href="#scalecenter0" x="0" y="0" transform="translate(-150,-150) scale(2.5)" stroke-width="0.4" /> 11 + <use xlink:href="#scalecenter0" x="0" y="0" transform="translate(-200,-200) scale(3)" stroke-width="0.33" /> 12 + </svg>
+9
docs/img/07_scale.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="200" viewBox="0 0 200 200"> 4 + <defs> 5 + <rect x="0" y="0" width="40" height="40" fill="none" stroke-width="2" id="scale10" /> 6 + </defs> 7 + <use xlink:href="#scale10" x="10" y="10" stroke="black" /> 8 + <use xlink:href="#scale10" x="10" y="10" stroke="red" transform="scale(2)" /> 9 + </svg>
+9
docs/img/07_scale2.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="100" viewBox="0 0 200 100"> 4 + <defs> 5 + <rect x="0" y="0" width="40" height="40" fill="none" stroke-width="2" id="scale20" /> 6 + </defs> 7 + <use xlink:href="#scale20" x="10" y="10" stroke="black" /> 8 + <use xlink:href="#scale20" x="10" y="10" stroke="red" transform="scale(3,1.5)" /> 9 + </svg>
+23
docs/img/07_skew.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="100" viewBox="0 0 200 100" id-srefix="skew"> 4 + <defs> 5 + </defs> 6 + <g stroke="gray" stroke-dasharray="4 4"> 7 + <path d="M0,0 L200,0" /> 8 + <path d="M20,0 L20,90" /> 9 + <path d="M120,0 L120,90" /> 10 + </g> 11 + <g transform="translate(20,0)"> 12 + <g transform="skewX(30)"> 13 + <path d="M50,0 L0,0 L0,50" stroke="black" fill="none" stroke-width="2" /> 14 + <text x="0" y="60" font-size="16">skewX</text> 15 + </g> 16 + </g> 17 + <g transform="translate(120,0)"> 18 + <g transform="skewY(30)"> 19 + <path d="M50,0 L0,0 L0,50" stroke="black" fill="none" stroke-width="2" /> 20 + <text x="0" y="60" font-size="16">skewY</text> 21 + </g> 22 + </g> 23 + </svg>
+8
docs/img/07_trans.svg
··· 1 + <?xml version="1.0" encoding="UTF-8"?> 2 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 3 + width="200" height="200" viewBox="0 0 200 200"> 4 + <defs> 5 + </defs> 6 + <rect x="0" y="0" width="40" height="40" /> 7 + <rect x="0" y="0" width="40" height="40" fill="red" transform="translate(50,50)" /> 8 + </svg>
docs/img/example1.png

This is a binary file and will not be displayed.

+1307
docs/index.md
··· 1 + # Drawsvg Quick Reference 2 + 3 + Repository: [https://github.com/cduck/drawsvg](https://github.com/cduck/drawsvg) 4 + 5 + 6 + ```python 7 + import drawsvg as dw 8 + ``` 9 + 10 + 11 + ## Canvas and Document Structure 12 + 13 + ```python 14 + d = dw.Drawing(width, height, origin=(0, 0), 15 + context: drawsvg.types.Context = None, animation_config=None, 16 + id_prefix='d', **svg_args) 17 + ``` 18 + 19 + It is recommended to use a unique `id_prefix` for each svg if you embed multiple on a web page. 20 + 21 + ```python 22 + d = dw.Drawing(400, 300, id_prefix='pic') 23 + ``` 24 + 25 + 26 + ## Basic Shapes 27 + 28 + ### One Line 29 + 30 + ```python 31 + dw.Line(sx, sy, ex, ey, **kwargs) 32 + ``` 33 + 34 + ```python 35 + line = dw.Line(30, 30, 90, 90, stroke='black') 36 + d.append(line) 37 + ``` 38 + 39 + ![svg](img/01_line.svg) 40 + 41 + 42 + ### Multiple Lines 43 + 44 + This is SVG's `polyline` (but drawsvg renders as path with multiple L). 45 + 46 + ```python 47 + dw.Lines(sx, sy, *points, close=False, **kwargs) 48 + ``` 49 + 50 + ```python 51 + lines = dw.Lines(10, 90, 10, 10, 80, 90, 80, 10, 52 + fill='none', stroke='black') 53 + d.append(lines) 54 + ``` 55 + 56 + ![svg](img/01_multilines.svg) 57 + 58 + 59 + ```python 60 + x = [30 + x*10 for x in range(20)] 61 + y = [80, 20]*10 62 + xy = [item for sublist in zip(x, y) for item in sublist] 63 + d.append(dw.Lines(*xy, stroke='black', stroke_width=5, fill='none')) 64 + ``` 65 + 66 + ![svg](img/01_multilines2.svg) 67 + 68 + 69 + ### Polygon 70 + 71 + SVG `Polygon` is drawsvg `Lines` with `close=True`. 72 + 73 + ```python 74 + polygon = dw.Lines(15, 10, 55, 10, 45, 20, 5, 20, 75 + fill='red', stroke='black', close='true') 76 + star = dw.Lines(48, 16, 16, 96, 96, 48, 0, 48, 88, 96, 77 + stroke='black', fill='none', close='true') 78 + d.append(star) 79 + ``` 80 + 81 + ![svg](img/01_polygon.svg) 82 + 83 + 84 + ### Rectangle 85 + 86 + ```python 87 + dw.Rectangle(x, y, width, height, **kwargs) 88 + ``` 89 + 90 + ```python 91 + # Black interior, no outline 92 + d.append(dw.Rectangle(10, 10, 90, 150)) 93 + # No interior, black outline 94 + d.append(dw.Rectangle(120, 10, 60, 120, 95 + fill='none', stroke='black')) 96 + # Blue interior, thick semi-transparent red outline 97 + d.append(dw.Rectangle(210, 10, 75, 90, 98 + fill='#0000ff', stroke='red', 99 + stroke_width=7, stroke_opacity=0.5)) 100 + # Semi-transparent yellow interior, dashed green outline 101 + d.append(dw.Rectangle(300, 10, 105, 60, 102 + fill='yellow', fill_opacity=0.5, 103 + stroke='green', stroke_width=2, 104 + stroke_dasharray='5,2')) 105 + ``` 106 + 107 + ![svg](img/01_rect.svg) 108 + 109 + Rounded corners: 110 + 111 + ```python 112 + # Define both rx and ry 113 + d.append(dw.Rectangle(10, 10, 80, 180, rx='10', ry='10', 114 + stroke='black', fill='none')) 115 + # If only one is given, it applies to both 116 + d.append(dw.Rectangle(110, 10, 80, 180, ry='20', 117 + stroke='black', fill='none')) 118 + d.append(dw.Rectangle(210, 10, 80, 180, rx='40', 119 + stroke='black', fill='none')) 120 + # Rx and ry unequal 121 + d.append(dw.Rectangle(310, 10, 80, 180, rx='30', ry='10', 122 + stroke='black', fill='none')) 123 + d.append(dw.Rectangle(410, 10, 80, 180, rx='10', ry='30', 124 + stroke='black', fill='none')) 125 + ``` 126 + 127 + ![svg](img/01_rectround.svg) 128 + 129 + 130 + ### Circle 131 + 132 + ```python 133 + dw.Circle(cx, cy, r, **kwargs) 134 + ``` 135 + 136 + cx and cy point to circle's center, r refer to its radius 137 + 138 + ```python 139 + d.append(dw.Circle(50, 50, 40)) 140 + d.append(dw.Circle(150, 50, 40, 141 + stroke='black', fill='none')) 142 + d.append(dw.Circle(250, 50, 40, 143 + stroke='black', fill='none', 144 + stroke_width=15)) 145 + ``` 146 + 147 + ![svg](img/01_circ.svg) 148 + 149 + 150 + ### Ellipse 151 + 152 + ```python 153 + dw.Ellipse(cx, cy, rx, ry, **kwarg) 154 + ``` 155 + (cx,cy) points to the center and (rx,ry) tells its radius 156 + 157 + ```python 158 + d.append(dw.Ellipse(50, 50, 50, 30)) 159 + d.append(dw.Ellipse(160, 50, 50, 30, 160 + stroke='black', fill='none')) 161 + d.append(dw.Ellipse(250, 50, 30, 45, 162 + stroke='black',fill='none')) 163 + ``` 164 + 165 + ![svg](img/01_ellip.svg) 166 + 167 + 168 + 169 + ## Color and Painting Properties 170 + 171 + For a full list, see [W3C specifications](https://www.w3.org/TR/SVG11/styling.html). 172 + 173 + 174 + ### fill and stroke\_color 175 + 176 + Some color keyword names are: 177 + aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, white, and yellow. 178 + 179 + Also supported is `#rrggbb`, `#rgb` (hexadecimal), or `rgb(R,G,B)` with 0-255 or with 0-100% for each value. 180 + 181 + ```python 182 + c = ['red', '#9f9', '#9999ff', 'rgb(255,128,64)', 'rgb(60%,20%,60%)'] 183 + for i in range(5): 184 + y = (i + 1)*10 185 + d.append(dw.Line(10, y, 80, y, 186 + stroke=c[i], stroke_width=5)) 187 + ``` 188 + 189 + ![svg](img/02_fsc.svg) 190 + 191 + 192 + ### fill\_opacity and stroke\_opacity 193 + 194 + Value range from 0 = transparent to 1 = solid. 195 + 196 + ```python 197 + for i in range(5): 198 + y = (i + 1)*10 199 + d.append(dw.Line(0, y, 290, y, 200 + stroke='black', stroke_width=5, 201 + stroke_opacity=i/5 + 0.1)) 202 + d.append(dw.Rectangle(i*60, 70, 50, 50, 203 + fill='red', fill_opacity=i/5+0.1)) 204 + ``` 205 + 206 + ![svg](img/02_foso.svg) 207 + 208 + 209 + ### stroke\_dasharray 210 + 211 + ```python 212 + # Nine-pixel dash, five-pixel gap 213 + d.append(dw.Line(10, 10, 100, 10, 214 + stroke='black', stroke_width=2, 215 + stroke_dasharray='9,5')) 216 + # Five-pixel dash, three-pixel gap, nine-pixel dash, two-pixel gap 217 + d.append(dw.Line(10, 20, 100, 20, 218 + stroke='black', stroke_width=2, 219 + stroke_dasharray='5,3,9,2')) 220 + # Odd number of entries alternates dashes and gaps 221 + d.append(dw.Line(10, 30, 100, 30, 222 + stroke='black', stroke_width=2, 223 + stroke_dasharray='9,3,5')) 224 + ``` 225 + 226 + ![svg](img/02_dash.svg) 227 + 228 + 229 + ### stroke\_width 230 + 231 + ```python 232 + for i in range(20): 233 + d.append(dw.Line((i+1)*15, 10, (i+1)*15, 90, 234 + stroke='black', stroke_width=abs(10-i)+1)) 235 + ``` 236 + 237 + ![svg](img/02_strokewdth.svg) 238 + 239 + 240 + ### stroke\_linecap 241 + 242 + `stroke_linecap` can be set to `butt`, `round`, or `square`. 243 + Note that the latter two extend beyond the end coordinates. 244 + 245 + ```python 246 + d.append(dw.Line(10, 15, 50, 15, 247 + stroke='black', stroke_width=15, 248 + stroke_linecap='butt')) 249 + d.append(dw.Line(10, 45, 50, 45, 250 + stroke='black', stroke_width=15, 251 + stroke_linecap='round')) 252 + d.append(dw.Line(10, 75, 50, 75, 253 + stroke='black', stroke_width=15, 254 + stroke_linecap='square')) 255 + # Guide lines 256 + d.append(dw.Lines(10, 0, 10, 100, stroke='#999')) 257 + d.append(dw.Lines(50, 0, 50, 100, stroke='#999')) 258 + ``` 259 + 260 + ![svg](img/02_linecap.svg) 261 + 262 + 263 + ### stroke\_linejoin 264 + 265 + Define the way lines connect at a corner with `stroke-linejoin`: `miter` (pointed), `round`, or `bevel` (flat). 266 + 267 + ```python 268 + d.append(dw.Line(0, 20, 300, 20, stroke='gray')) 269 + g = dw.Group(stroke_width=20, stroke='black', fill='none') 270 + g.append(dw.Lines(10, 80, 50, 20, 90, 80, 271 + stroke_linejoin='miter')) 272 + g.append(dw.Lines(110, 80, 150, 20, 190, 80, 273 + stroke_linejoin='round')) 274 + g.append(dw.Lines(210, 80, 250, 20, 290, 80, 275 + stroke_linejoin='bevel')) 276 + d.append(g) 277 + ``` 278 + 279 + ![svg](img/02_join.svg) 280 + 281 + 282 + ### stroke\_miterlimit 283 + 284 + When two line segments meet at a sharp angle and miter joins have been specified for `stroke-linejoin`, 285 + it is possible for the miter to extend far beyond the thickness of the line stroking the path. 286 + The `stroke-miterlimit` imposes a limit on the ratio of the miter length to the `stroke-width`. 287 + When the limit is exceeded, the join is converted from a miter to a bevel. 288 + (From [W3C doc](https://www.w3.org/TR/SVG11/painting.html#StrokeMiterlimitProperty)) 289 + 290 + ```python 291 + d.append(dw.Line(0, 30, 300, 30, stroke='gray')) 292 + g = dw.Group(stroke_width=20, stroke='black', 293 + fill='none', stroke_linejoin='miter') 294 + g.append(dw.Lines(10, 90, 40, 30, 70, 90)) 295 + g.append(dw.Lines(100, 90, 130, 30, 160, 90, 296 + stroke_miterlimit=2.3)) 297 + g.append(dw.Lines(190, 90, 220, 30, 250, 90, 298 + stroke_miterlimit=1)) 299 + d.append(g) 300 + ``` 301 + 302 + ![svg](img/02_mlimit.svg) 303 + 304 + 305 + ## Path 306 + 307 + ```python 308 + path = dw.Path(**kwargs) 309 + ``` 310 + 311 + The following Path specifiers are also available as lowercase characters. 312 + In that case, their movements are relative to current location. 313 + 314 + 315 + ### M: moveto 316 + 317 + ```python 318 + path.M(x, y) 319 + ``` 320 + 321 + Move to `x, y` (and draw nothing). 322 + 323 + 324 + ### L: lineto 325 + 326 + ```python 327 + path.L(x, y) 328 + ``` 329 + 330 + Draw a straight line to `x, y`. 331 + 332 + ```python 333 + g = dw.Group(stroke='black', fill='none') 334 + 335 + p = dw.Path() 336 + p.M(10, 10).L(100, 10) 337 + g.append(p) 338 + 339 + p = dw.Path() 340 + p.M(10, 20).L(100, 20).L(100, 50) 341 + g.append(p) 342 + 343 + p = dw.Path() 344 + p.M(40, 60).L(10, 60).L(40, 42) 345 + p.M(60, 60).L(90, 60).L(60, 42) 346 + g.append(p) 347 + 348 + d.append(g) 349 + ``` 350 + 351 + ![svg](img/03_pL.svg) 352 + 353 + 354 + ### H: horizontal line 355 + 356 + ```python 357 + path.H(x) 358 + ``` 359 + 360 + Draw a horizontal line to the new `x` location. 361 + 362 + 363 + ### V: vertical line 364 + 365 + ```python 366 + path.V(y) 367 + ``` 368 + 369 + Draw a vertical line to the new `y` location. 370 + 371 + ```python 372 + p = dw.Path(stroke='black', fill='none') 373 + d.append(p.M(10, 10).H(100)) 374 + d.append(p.M(10, 20).H(100).V(50)) 375 + ``` 376 + ![svg](img/03_pHV.svg) 377 + 378 + 379 + ### Q: quadratic Bézier curve (one control point) 380 + 381 + ```python 382 + path.Q(x_ctl, y_ctl, x_end, y_end) 383 + ``` 384 + 385 + Draw a quadratic Bézier curve from current location to `x_end, y_end` by means of `x_ctl, y_ctl`. 386 + 387 + ```python 388 + # Curve only (left) 389 + p = dw.Path(stroke='black', fill='none', stroke_width=3) 390 + d.append(p.M(30, 75).Q(240, 30, 300, 120)) 391 + # With control point and construction lines 392 + d.append(dw.Use(p, 300, 0)) 393 + g = dw.Group(stroke='gray', fill='gray') 394 + g.append(dw.Circle(330, 75, 3)) 395 + g.append(dw.Circle(600, 120, 3)) 396 + g.append(dw.Circle(540, 30, 3)) 397 + g.append(dw.Line(330, 75, 540, 30)) 398 + g.append(dw.Line(540, 30, 600, 120)) 399 + g.append(dw.Line(330, 75, 600, 120, stroke_dasharray='5,5')) 400 + g.append(dw.Circle(435, 52.5, 3)) 401 + g.append(dw.Circle(570, 75, 3)) 402 + g.append(dw.Line(435, 52.5, 570, 75)) 403 + g.append(dw.Circle(502.5, 63.75, 4, fill='none')) 404 + d.append(g) 405 + ``` 406 + 407 + ![svg](img/03_pQ.svg) 408 + 409 + 410 + ### T: smooth quadratic Bézier curve (generated control point) 411 + 412 + ```python 413 + path.T(x, y) 414 + ``` 415 + 416 + Draws a quadratic Bézier curve from the current point to (x, y). 417 + The control point is assumed to be the reflection of the control point on the previous command relative to the current point. 418 + 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. 419 + (From [W3C Doc](https://www.w3.org/TR/SVG11/paths.html#PathDataQuadraticBezierCommands)) 420 + 421 + ```python 422 + # Curve sequence (left) 423 + p = dw.Path(stroke='black', fill='none', stroke_width=3) 424 + d.append(p.M(30, 60).Q(80, -10, 100, 60).Q(130, 25, 200, 40)) 425 + # With smooth continuation (right) 426 + p = dw.Path(stroke='black', fill='none', stroke_width=3, 427 + transform='translate(200,0)') 428 + d.append(p.M(30, 60).Q(80, -10, 100, 60).T(200, 40)) 429 + ``` 430 + 431 + ![svg](img/03_pT.svg) 432 + 433 + 434 + ### C: cubic Bézier curve (two control points) 435 + 436 + ```python 437 + path.C(x_ctl_1, y_ctl_1, x_ctl_2, y_ctl_2, x_end, y_end) 438 + ``` 439 + 440 + Draw a cubic Bézier curve by means of two control points (one for start and one for end). 441 + 442 + ```python 443 + pnt_1 = (40, 50) 444 + pnt_2 = (110, 50) 445 + ctl_1_x = (10, 60, 110, 110, 60, 110) 446 + ctls_2 = ((140, 10), (90, 10), (40, 10), (40, 10), (90, 90), (40, 90)) 447 + 448 + for i in range(6): 449 + trans = f'translate({i*100},0)' 450 + p = dw.Path(stroke='black', fill='none', 451 + stroke_width=3, transform=trans) 452 + ctl_1 = (ctl_1_x[i], 10) 453 + ctl_2 = ctls_2[i] 454 + p.M(*pnt_1) 455 + p.C(*ctl_1, *ctl_2, *pnt_2) 456 + d.append(p) 457 + g = dw.Group(stroke='gray', fill='gray', 458 + stroke_width=1, transform=trans) 459 + g.append(dw.Circle(*ctl_1, 2)) 460 + g.append(dw.Circle(*ctl_2, 2)) 461 + g.append(dw.Line(*pnt_1, *ctl_1)) 462 + g.append(dw.Line(*pnt_2, *ctl_2)) 463 + d.append(g) 464 + ``` 465 + 466 + ![svg](img/03_pC.svg) 467 + 468 + 469 + ### S: smooth cubic Bézier (one control point) 470 + 471 + Similar to `T` in quadratic Bézier curve. The first control point is calculated as reflection of the previous second control point. 472 + 473 + ```python 474 + path.S(x_ctl_2, y_ctl_2, x_end, y_end) 475 + ``` 476 + 477 + ```python 478 + pnt_1 = (30, 100) 479 + pnt_2 = (100, 100) 480 + pnt_3 = (200, 80) 481 + ctl_1 = (50, 30) 482 + ctl_2 = (70, 50) 483 + ctl_3 = (150, 40) 484 + 485 + p = dw.Path(stroke='black', fill='none', stroke_width=3) 486 + p.M(*pnt_1) 487 + p.C(*ctl_1, *ctl_2, *pnt_2) 488 + p.S(*ctl_3, *pnt_3) 489 + d.append(p) 490 + 491 + for pnt, ctl in zip((pnt_1, pnt_2, pnt_3), (ctl_1, ctl_2, ctl_3)): 492 + d.append(dw.Circle(*pnt, 4)) 493 + d.append(dw.Circle(*ctl, 2, stroke='gray', fill='gray')) 494 + d.append(dw.Line(*pnt, *ctl, stroke='gray')) 495 + ``` 496 + 497 + ![svg](img/03_pS.svg) 498 + 499 + 500 + ### A: elliptical Arc 501 + 502 + ```python 503 + path.A(rx, ry, rot, largeArc, sweep, ex, ey) 504 + 505 + rx, ry: radius 506 + rot: x-axis rotation 507 + largeArc: True or False 508 + sweep: True (positive) or False (negative) angle 509 + ex, ey: end point 510 + ``` 511 + 512 + ```python 513 + p = dw.Path(stroke='red') 514 + d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=0, sweep=0, ex=225, ey=125)) 515 + p = dw.Path(stroke='blue') 516 + d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=0, sweep=1, ex=225, ey=125)) 517 + p = dw.Path(stroke='rgb(0 80 255)',stroke_dasharray='5 3') 518 + d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=1, sweep=0, ex=225, ey=125)) 519 + p = dw.Path(stroke='rgb(255 80 0)',stroke_dasharray='5 3') 520 + d.append(p.M(125, 75).A(100, 50, rot=0, large_arc=1, sweep=1, ex=225, ey=125)) 521 + ``` 522 + 523 + ![svg](img/03_pA.svg) 524 + 525 + 526 + ### Z: closepath 527 + 528 + ```python 529 + path.Z() 530 + ``` 531 + 532 + Close the path. 533 + 534 + ```python 535 + p = dw.Path(stroke='black', fill='none') 536 + d.append(p.M(10, 10).h(30).v(50).h(-30).Z()) 537 + d.append(p.M(50, 10).h(30).v(50).Z()) 538 + ``` 539 + 540 + ![svg](img/03_pZ.svg) 541 + 542 + 543 + ## Text 544 + ```python 545 + dw.Text(text, fontSize, x=None, y=None, *, center=False, 546 + line_height=1, line_offset=0, path=None, 547 + start_offset=None, path_args=None, tspan_args=None, 548 + cairo_fix=True, **kwargs) 549 + ``` 550 + 551 + ### Fill and Outline 552 + 553 + Default is black as fill color and no outline. 554 + 555 + ```python 556 + # Reference lines 557 + l = dw.Path(stroke='gray') 558 + l.M(20, 0).V(370) 559 + for i in range(1, 7): 560 + l.M(10, i*60).H(500) 561 + d.append(l) 562 + 563 + d.append(dw.Text('Simplest Text', font_size=50, x=20, y=60)) 564 + d.append(dw.Text('Outline / Filled', font_size=50, x=20, y=120, stroke='black')) 565 + d.append(dw.Text('Too big stroke', font_size=50, x=20, y=180, stroke='black', stroke_width=5)) 566 + d.append(dw.Text('Outlined only', font_size=50, x=20, y=240, stroke='black', stroke_width=0.5, fill='none')) 567 + d.append(dw.Text('Outlined and colored', font_size=50, x=20, y=300, stroke='black', fill='red')) 568 + d.append(dw.Text('Colored fill only', font_size=50, x=20, y=360, fill='blue')) 569 + ``` 570 + 571 + ![svg](img/04_fill.svg) 572 + 573 + 574 + ### Weight, Style, Decoration, Spacing 575 + 576 + ```python 577 + d.append(dw.Text('bold', font_size=30, x=20, y=35, font_weight='bold')) 578 + d.append(dw.Text('italic', font_size=30, x=20, y=75, font_style='italic')) 579 + d.append(dw.Text('under', font_size=30, x=20, y=115, text_decoration='underline')) 580 + d.append(dw.Text('over', font_size=30, x=20, y=155, text_decoration='overline')) 581 + d.append(dw.Text('through', font_size=30, x=20, y=195, text_decoration='line-through')) 582 + d.append(dw.Text('normal word space', font_size=30, x=200, y=35)) 583 + d.append(dw.Text('more word space', font_size=30, x=200, y=75, word_spacing=10)) 584 + d.append(dw.Text('less word space', font_size=30, x=200, y=115, word_spacing=-5)) 585 + d.append(dw.Text('wide letter space', font_size=30, x=200, y=155, letter_spacing=8)) 586 + d.append(dw.Text('narrow letter space', font_size=30, x=200, y=195, letter_spacing=-2)) 587 + ``` 588 + 589 + ![svg](img/04_weight.svg) 590 + 591 + 592 + ### Text Alignment 593 + 594 + Horizontal alignment (`text_anchor`) can be `'start'`, `'middle'` or `'end'`. 595 + 596 + Vertical alignment (`dominant_baseline`) can be `'auto'`, `'middle'` or `'hanging'` 597 + (and more, see [here](https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/dominant-baseline)). 598 + 599 + ```python 600 + d.append(dw.Line(75, 100, 75, 0, stroke='gray')) 601 + d.append(dw.Line(140, 30, 250, 30, stroke='gray')) 602 + d.append(dw.Line(140, 60, 250, 60, stroke='gray')) 603 + d.append(dw.Line(140, 90, 250, 90, stroke='gray')) 604 + d.append(dw.Text('Start', 24, 75, 30, text_anchor='start')) 605 + d.append(dw.Text('Middle', 24, 75, 60, text_anchor='middle')) 606 + d.append(dw.Text('End', 24, 75, 90, text_anchor='end')) 607 + d.append(dw.Text('Auto', 24, 150, 30, dominant_baseline='bottom')) 608 + d.append(dw.Text('Middle', 24, 150, 60, dominant_baseline='middle')) 609 + d.append(dw.Text('Hanging', 24, 150, 90, dominant_baseline='top')) 610 + ``` 611 + 612 + ![svg](img/04_align.svg) 613 + 614 + 615 + ### TSpan 616 + 617 + Continues a `Text` element. 618 + 619 + ```python 620 + txt = dw.Text('Switch among ', 24, 10, 40) 621 + txt.append(dw.TSpan('italic', font_style='italic')) 622 + txt.append(dw.TSpan(', normal, and ')) 623 + txt.append(dw.TSpan('bold', font_weight='bold')) 624 + txt.append(dw.TSpan(' text.')) 625 + d.append(txt) 626 + ``` 627 + 628 + ![svg](img/04_tspan.svg) 629 + 630 + 631 + ```python 632 + txt = dw.Text('F', 24, 10, 30) 633 + txt.append(dw.TSpan('a', dy=5)) 634 + txt.append(dw.TSpan('l', dy=31, dx=21)) 635 + txt.append(dw.TSpan('l', dy=89, dx=54)) 636 + d.append(txt) 637 + ``` 638 + 639 + ![svg](img/04_tspan2.svg) 640 + 641 + The same could be achieved by a list of dx/dy values: 642 + 643 + ```python 644 + d.append(dw.Text('Fall', 24, 10, 30, 645 + dx='0,0,21,54', dy='0,5,21,54')) 646 + ``` 647 + 648 + ![svg](img/04_tspan3.svg) 649 + 650 + 651 + ### Rotate 652 + 653 + Either one angle (degrees), or a list which is applied to all characters. 654 + If the list is smaller than the number of characters, the last angle persists. 655 + 656 + ```python 657 + d.append(dw.Text('Rotate', 20, 20, 20, letter_spacing=20, rotate='90')) 658 + d.append(dw.Text('Rotate', 20, 20, 80, letter_spacing=20, rotate='0 90 180 270')) 659 + ``` 660 + 661 + ![svg](img/04_rot.svg) 662 + 663 + `TSpan` can also be used: 664 + 665 + ```python 666 + import random 667 + random.seed(1) 668 + 669 + txt = dw.Text('', 20, 20, 50, letter_spacing=20) 670 + txt.append(dw.TSpan('R', rotate=random.randrange(360))) 671 + txt.append(dw.TSpan('OT', rotate='50 20')) 672 + rotate = ' '.join([str(random.randrange(360)) for i in range(3)]) 673 + txt.append(dw.TSpan('ATE', rotate=rotate)) 674 + d.append(txt) 675 + ``` 676 + 677 + ![svg](img/04_rot2.svg) 678 + 679 + 680 + ### Setting Text Length 681 + 682 + ```python 683 + s = 'Two words' 684 + d.append(dw.Text(s, 20, 20, 30, textLength=250, lengthAdjust='spacing')) 685 + d.append(dw.Text(s, 20, 20, 70, textLength=250, lengthAdjust='spacingAndGlyphs')) 686 + d.append(dw.Text(s+' (normal length)', 20, 20, 110)) 687 + d.append(dw.Text(s, 20, 20, 150, textLength=80, lengthAdjust='spacing')) 688 + d.append(dw.Text(s, 20, 20, 190, textLength=80, lengthAdjust='spacingAndGlyphs')) 689 + 690 + d.append(dw.Line(20, 10, 20, 195, stroke='gray')) 691 + d.append(dw.Line(270, 80, 270, 10, stroke='gray')) 692 + d.append(dw.Line(100, 130, 100, 195, stroke='gray')) 693 + ``` 694 + 695 + ![svg](img/04_len.svg) 696 + 697 + 698 + ### Text on a Path 699 + 700 + ```python 701 + curve_path = dw.Path(stroke='gray', fill='none') 702 + curve_path.M(30, 50).C(50, 20, 70, 20, 120, 50).S(150, 10, 200, 50) 703 + 704 + round_corner = dw.Path(stroke='gray', fill='none') 705 + round_corner.M(250, 30).L(300, 30).A(30, 30, 0, 0, 1, 330, 60).L(330, 110) 706 + 707 + sharp_corner = dw.Path(stroke='gray', fill='none') 708 + sharp_corner.M(30, 110).L(100, 110).L(100, 160) 709 + 710 + discontinuous = dw.Path(stroke='gray', fill='none') 711 + discontinuous.M(150, 110).A(40, 30, 0, 1, 0, 230, 110).M(250, 110).L(270, 140) 712 + 713 + center_curve = dw.Path(stroke='gray', fill='none') 714 + center_curve.M(330, 130).L(330, 160).A(30, 30, 0, 0, 1, 300, 180).L(200, 180) 715 + 716 + d.append(curve_path) 717 + d.append(round_corner) 718 + d.append(sharp_corner) 719 + d.append(discontinuous) 720 + d.append(center_curve) 721 + 722 + t_cp = dw.Text('Following a cubic Bézier curve', 14, path=curve_path) 723 + t_rc = dw.Text("Going 'round the bend", 14, path=round_corner) 724 + t_sc = dw.Text('Making a quick turn', 14, path=sharp_corner) 725 + t_dc = dw.Text('Text along a broken path', 14, path=discontinuous) 726 + t_ct = dw.Text('centered', 14, path=center_curve, offset='50%', text_anchor='middle') 727 + 728 + d.append(t_cp) 729 + d.append(t_rc) 730 + d.append(t_sc) 731 + d.append(t_dc) 732 + d.append(t_ct) 733 + ``` 734 + 735 + ![svg](img/04_path.svg) 736 + 737 + 738 + ### Multi Line Text 739 + 740 + This is a particular feature of drawsvg: A list of strings as input for Text() 741 + is rendered as multi-line text. 742 + 743 + ```python 744 + tl = ['this is', 'a', 'multiline text', 'given as a', 'list'] 745 + d.append(dw.Text(tl, 14, 50, 20, text_anchor='middle')) 746 + 747 + ts = 'this is\na\nmultiline text\ngiven as a\nstring' 748 + d.append(dw.Text(ts, 14, 150, 20, text_anchor='middle')) 749 + ``` 750 + 751 + ![svg](img/04_multiline_text.svg) 752 + 753 + 754 + ### Fonts 755 + 756 + Specify fonts via `font_family`. 757 + 758 + ```python 759 + d.append(dw.Text('Some text in Times New Roman.', 30, 10, 35, font_family='Times New Roman')) 760 + d.append(dw.Text('Some text in Arial Black.', 30, 10, 75, font_family='Arial Black')) 761 + d.append(dw.Text('Some text in Georgia.', 30, 10, 115, font_family='Georgia')) 762 + ``` 763 + 764 + ![png](img/04_fonts1.png) 765 + 766 + Specify a default font. 767 + 768 + ```python 769 + d = dw.Drawing(600, 120, font_family='Times New Roman') 770 + d.append(dw.Text('Some text in global setting (Times New Roman).', 30, 10, 35)) 771 + d.append(dw.Text('Some text in Arial Black.', 30, 10, 75, font_family='Arial Black')) 772 + d.append(dw.Text('Some text in Georgia.', 30, 10, 115, font_family='Georgia')) 773 + ``` 774 + 775 + ![png](img/04_fonts2.png) 776 + 777 + 778 + 779 + ## Gradient, Clip, Mask 780 + 781 + ### Linear Gradient 782 + 783 + ```python 784 + gradient = dw.LinearGradient(x1, y1, x2, y2, gradientUnits='userSpaceOnUse', **kwargs) 785 + gradient.add_stop(offset, color, opacity=None) 786 + ``` 787 + 788 + ```python 789 + grad = dw.LinearGradient(150, 0, 0, 0) 790 + grad.add_stop(0, 'green') 791 + grad.add_stop(1, 'yellow') 792 + d.append(dw.Rectangle(10, 10, 150, 60, 793 + stroke='black', fill=grad)) 794 + ``` 795 + 796 + ![svg](img/05_lingrad.svg) 797 + 798 + 799 + ### Radial Gradient 800 + 801 + ```python 802 + gradient = dw.RadialGradient(cx, cy, r, **kwargs) 803 + gradient.add_stop(offset, color, opacity=None) 804 + ``` 805 + 806 + ```python 807 + gradient = dw.RadialGradient(200, 100, 100) 808 + gradient.add_stop(0, 'green', 1) 809 + gradient.add_stop(1, 'orange', 1) 810 + bg = dw.Rectangle(x=0, y=0, width='100%', height='100%', fill=gradient) 811 + d.append(bg) 812 + ``` 813 + 814 + ![svg](img/05_radgrad.svg) 815 + 816 + 817 + ### Clip 818 + 819 + ```python 820 + clip_name = dw.ClipPath() 821 + ``` 822 + 823 + To add shape as Clip, use `.append()` method. 824 + To apply Clip, fill `clip_path` argument with `clip_name`. 825 + 826 + ```python 827 + # Show both shapes as they are 828 + d.append(dw.Rectangle(100, 100, 100, 100, 829 + stroke='gray', fill='none')) 830 + d.append(dw.Circle(100, 100, 100, 831 + fill='none', stroke='gray', stroke_dasharray='5 5')) 832 + # Apply rect as clip to circle 833 + clip = dw.ClipPath() 834 + clip.append(dw.Rectangle(100, 100, 100, 100)) 835 + d.append(dw.Circle(100, 100, 100, 836 + fill='cyan', clip_path=clip)) 837 + ``` 838 + 839 + ![svg](img/05_clip.svg) 840 + 841 + Another example: 842 + 843 + ```python 844 + # Draw a random path in the left half of the canvas 845 + p = dw.Path(stroke='black', stroke_width=2, fill='none') 846 + p.M(150, 150) 847 + import random 848 + random.seed(1) 849 + for i in range(40): 850 + p.L(random.randint(0, 300), random.randint(0, 200)) 851 + d.append(p) 852 + 853 + # Circle as clipping shape 854 + circ = dw.Circle(150, 100, 75) 855 + c = dw.ClipPath() 856 + c.append(circ) 857 + 858 + # Repeat lines in the right half and apply clipping 859 + d.append(dw.Use(p, 300, 0, clip_path=c)) 860 + ``` 861 + 862 + ![svg](img/05_clip2.svg) 863 + 864 + Complex clip path: 865 + 866 + ```python 867 + curve1 = dw.Path(stroke='black', stroke_width=1, stroke_dasharray='3 2', fill='none') 868 + curve1.M(5, 55).C(25, 5, 45, -25, 75, 55).C(85, 85, 20, 105, 40, 55).Z() 869 + 870 + curveClip = dw.ClipPath() 871 + curveClip.append(dw.Use(curve1, 0, 0)) 872 + 873 + text1 = dw.Text('CLIP', 48, 20, 20, font_weight='bold', transform='rotate(60)', 874 + stroke='black', stroke_width=1, stroke_dasharray='3 2', fill='none') 875 + textClip = dw.ClipPath() 876 + textClip.append(dw.Use(text1, 0, 0)) 877 + 878 + shapes = dw.Group() 879 + shapes.append(dw.Rectangle(0, 50, 90, 60, fill='#999')) 880 + shapes.append(dw.Circle(25, 25, 25, fill='#666')) 881 + shapes.append(dw.Lines(30, 0, 80, 0, 80, 100, close='true', fill='#ccc')) 882 + 883 + # draw shapes with clip path 884 + d.append(dw.Use(shapes, 0, 0, clip_path=curveClip)) 885 + 886 + # show clip path 887 + g = dw.Group(transform='translate(100,0)') 888 + g.append(shapes) 889 + g.append(dw.Use(curve1, 0, 0)) 890 + d.append(g) 891 + 892 + # draw shapes with text as clip path 893 + d.append(dw.Use(shapes, 0, 150, clip_path=textClip)) 894 + 895 + # show text clip path 896 + g = dw.Group(transform='translate(100,150)') 897 + g.append(shapes) 898 + g.append(dw.Use(text1, 0, 0)) 899 + d.append(g) 900 + ``` 901 + 902 + ![svg](img/05_clip3.svg) 903 + 904 + 905 + ### Mask 906 + 907 + ```python 908 + mask_name = dw.Mask() 909 + ``` 910 + 911 + The transparency of the masking object is transfered to the masked object. 912 + Opaque pixels of the mask produce opaque pixels of the masked object. 913 + Transparent parts of the mask make the corresponding parts of the masked object invisible. 914 + 915 + ```python 916 + gradient = dw.LinearGradient(*[0,0], *[1,0], gradientUnits='objectBoundingBox') 917 + gradient.add_stop(0, 'white') 918 + gradient.add_stop(1, 'black') 919 + 920 + mask = dw.Mask() 921 + box = dw.Rectangle(30, 0, 100, 100, fill=gradient) 922 + mask.append(box) 923 + 924 + # Initial shape 925 + rect = dw.Rectangle(0, 0, 200, 100, 926 + fill='cyan', stroke='blue', stroke_width=2) 927 + d.append(rect) 928 + 929 + # After mask 930 + rect = dw.Rectangle(0, 0, 200, 100, 931 + fill='pink', stroke='red', stroke_width=2, 932 + mask=mask) 933 + d.append(rect) 934 + ``` 935 + 936 + ![svg](img/05_mask.svg) 937 + 938 + Mask using opaque colors: 939 + 940 + ```python 941 + # Define the masks 942 + redmask = dw.Mask(maskContentUnits='objectBoundingBox') 943 + redmask.append(dw.Rectangle(0, 0, 1, 1, fill='#f00')) 944 + greenmask = dw.Mask(maskContentUnits='objectBoundingBox') 945 + greenmask.append(dw.Rectangle(0, 0, 1, 1, fill='#0f0')) 946 + bluemask = dw.Mask(maskContentUnits='objectBoundingBox') 947 + bluemask.append(dw.Rectangle(0, 0, 1, 1, fill='#00f')) 948 + whitemask = dw.Mask(maskContentUnits='objectBoundingBox') 949 + whitemask.append(dw.Rectangle(0, 0, 1, 1, fill='#fff')) 950 + 951 + # Display the colors 952 + d.append(dw.Rectangle(10, 10, 50, 50, fill='#f00')) 953 + d.append(dw.Rectangle(70, 10, 50, 50, fill='#0f0')) 954 + d.append(dw.Rectangle(130, 10, 50, 50, fill='#00f')) 955 + d.append(dw.Rectangle(190, 10, 50, 50, fill='#fff', stroke='black')) 956 + 957 + # Mask 958 + g = dw.Group(mask=redmask) 959 + g.append(dw.Circle(35,115,25,fill='black')) 960 + g.append(dw.Text('Red',14,35,80,text_anchor='middle')) 961 + d.append(g) 962 + g = dw.Group(mask=greenmask) 963 + g.append(dw.Circle(95, 115, 25, fill='black')) 964 + g.append(dw.Text('Green', 14, 95, 80, text_anchor='middle')) 965 + d.append(g) 966 + g = dw.Group(mask=bluemask) 967 + g.append(dw.Circle(155, 115, 25, fill='black')) 968 + g.append(dw.Text('Blue', 14, 155, 80, text_anchor='middle')) 969 + d.append(g) 970 + g = dw.Group(mask=whitemask) 971 + g.append(dw.Circle(215, 115, 25, fill='black')) 972 + g.append(dw.Text('White', 14, 215, 80, text_anchor='middle')) 973 + d.append(g) 974 + ``` 975 + 976 + ![svg](img/05_mask2.svg) 977 + 978 + Mask alpha using opacity only: 979 + 980 + ```python 981 + fullmask = dw.Mask(maskContentUnits='objectBoundingBox') 982 + fullmask.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=1.0, fill='white')) 983 + three_fourths = dw.Mask(maskContentUnits='objectBoundingBox') 984 + three_fourths.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=0.75, fill='white')) 985 + one_half = dw.Mask(maskContentUnits='objectBoundingBox') 986 + one_half.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=0.5, fill='white')) 987 + one_fourth = dw.Mask(maskContentUnits='objectBoundingBox') 988 + one_fourth.append(dw.Rectangle(0, 0, 1, 1, fill_opacity=0.25, fill='white')) 989 + 990 + g = dw.Group(mask=fullmask) 991 + g.append(dw.Circle(35, 35, 25)) 992 + g.append(dw.Text('100%', 14, 35, 80, text_anchor='middle')) 993 + d.append(g) 994 + g = dw.Group(mask=three_fourths) 995 + g.append(dw.Circle(95, 35, 25)) 996 + g.append(dw.Text('50%', 14, 95, 80, text_anchor='middle')) 997 + d.append(g) 998 + g = dw.Group(mask=one_half) 999 + g.append(dw.Circle(155, 35, 25)) 1000 + g.append(dw.Text('50%', 14, 155, 80, text_anchor='middle')) 1001 + d.append(g) 1002 + g = dw.Group(mask=one_fourth) 1003 + g.append(dw.Circle(215, 35, 25)) 1004 + g.append(dw.Text('25%', 14, 215, 80, text_anchor='middle')) 1005 + d.append(g) 1006 + ``` 1007 + 1008 + ![svg](img/05_mask3.svg) 1009 + 1010 + 1011 + ## Group, Use, Defs, Image 1012 + 1013 + ### Group 1014 + 1015 + ```python 1016 + dw.Group(**kwargs) 1017 + ``` 1018 + 1019 + Any style specified in the g tag will apply to all child elements in the group. 1020 + 1021 + ```python 1022 + g_house = dw.Group(id='house', fill='none', stroke='black') 1023 + g_house.append(dw.Rectangle(6, 50, 60, 60)) 1024 + g_house.append(dw.Lines(6, 50, 36, 9, 66, 50)) 1025 + g_house.append(dw.Lines(36, 110, 36, 80, 50, 80, 50, 110)) 1026 + d.append(g_house) 1027 + 1028 + g_man = dw.Group(id='man', fill='none', stroke='blue') 1029 + g_man.append(dw.Circle(85, 56, 10)) 1030 + g_man.append(dw.Line(85, 66, 85, 80)) 1031 + g_man.append(dw.Lines(76, 104, 85, 80, 94, 104)) 1032 + g_man.append(dw.Lines(76, 70, 85, 76, 94, 70)) 1033 + d.append(g_man) 1034 + 1035 + g_woman = dw.Group(id='woman', fill='none', stroke='red') 1036 + g_woman.append(dw.Circle(110, 56, 10)) 1037 + g_woman.append(dw.Lines(110, 66, 110, 80, 100, 90, 120, 90, 110, 80)) 1038 + g_woman.append(dw.Line(104, 104, 108, 90)) 1039 + g_woman.append(dw.Line(112, 90, 116, 104)) 1040 + g_woman.append(dw.Lines(101, 70, 110, 76, 119, 70)) 1041 + d.append(g_woman) 1042 + ``` 1043 + 1044 + ![svg](img/06_group.svg) 1045 + 1046 + 1047 + ### Use 1048 + 1049 + ```python 1050 + dw.Use(other_elem, x, y, **kwargs) 1051 + ``` 1052 + 1053 + ```python 1054 + g_house = dw.Group(id='house', fill='none', stroke='black') 1055 + g_house.append(dw.Rectangle(6, 50, 60, 60)) 1056 + g_house.append(dw.Lines(6, 50, 36, 9, 66, 50)) 1057 + g_house.append(dw.Lines(36, 110, 36, 80, 50, 80, 50, 110)) 1058 + d.append(g_house) 1059 + 1060 + # Use id which is set 1061 + d.append(dw.Use('house', 100, 50)) 1062 + # Or use variable name 1063 + d.append(dw.Use(g_house, 150, 20)) 1064 + ``` 1065 + 1066 + ![svg](img/06_use.svg) 1067 + 1068 + 1069 + ### Defs 1070 + 1071 + Elements that are not appended to the drawing but are referenced by other elements will automatically be included in `<defs></defs>`. 1072 + ([source](https://github.com/cduck/drawsvg/issues/46)) 1073 + 1074 + ```python 1075 + d = dw.Drawing(200, 200, id_prefix='defs') 1076 + 1077 + # Do not append `bond` to the drawing 1078 + bond = dw.Line(0, 0, 10, 10, stroke='black') 1079 + 1080 + # `bond` is automatically added into <defs> 1081 + # A default `id` is generated if one isn't set 1082 + d.append(dw.Use(bond, 20, 50)) 1083 + d.append(dw.Use(bond, 50, 50)) 1084 + d.append(dw.Use(bond, 80, 50)) 1085 + 1086 + print(d.as_svg()) 1087 + ``` 1088 + 1089 + Output: 1090 + 1091 + ```svg 1092 + <?xml version="1.0" encoding="UTF-8"?> 1093 + <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 1094 + width="200" height="200" viewBox="0 0 200 200"> 1095 + <defs> 1096 + <path d="M0,0 L10,10" stroke="black" id="defs0" /> 1097 + </defs> 1098 + <use xlink:href="#defs0" x="20" y="50" /> 1099 + <use xlink:href="#defs0" x="50" y="50" /> 1100 + <use xlink:href="#defs0" x="80" y="50" /> 1101 + </svg> 1102 + ``` 1103 + 1104 + 1105 + ### Image 1106 + 1107 + ```python 1108 + dw.Image(x, y, width, height, path=None, data=None, 1109 + embed=False, mimeType=None, **kwargs) 1110 + ``` 1111 + 1112 + ```python 1113 + d.append(dw.Image(0, 0, 200, 200, 'example1.png', embed=True)) 1114 + ``` 1115 + 1116 + ![svg](img/06_imag.svg) 1117 + 1118 + 1119 + ## Transformations 1120 + 1121 + ### Translate 1122 + 1123 + ```python 1124 + transform = 'translate(x,y)' 1125 + ``` 1126 + 1127 + This attribute can be added to many objects. Simple example: 1128 + 1129 + ```python 1130 + d.append(dw.Rectangle(0, 0, 40, 40)) 1131 + d.append(dw.Rectangle(0, 0, 40, 40, fill='red', transform='translate(50,50)')) 1132 + ``` 1133 + 1134 + ![svg](img/07_trans.svg) 1135 + 1136 + 1137 + ### Scale 1138 + 1139 + ```python 1140 + transform = 'scale(x_mult[, y_mult])' 1141 + ``` 1142 + 1143 + Note that scaling also affects stroke width. 1144 + 1145 + ```python 1146 + square = dw.Rectangle(0, 0, 40, 40, fill='none', stroke_width=2) 1147 + d.append(dw.Use(square, 10, 10, stroke='black')) 1148 + d.append(dw.Use(square, 10, 10, stroke='red', transform='scale(2)')) 1149 + ``` 1150 + 1151 + ![svg](img/07_scale.svg) 1152 + 1153 + It is possible to specify x and y scale separately: 1154 + 1155 + ```python 1156 + square = dw.Rectangle(0, 0, 40, 40, fill='none', stroke_width=2) 1157 + d.append(dw.Use(square, 10, 10, stroke='black')) 1158 + d.append(dw.Use(square, 10, 10, stroke='red', transform='scale(3,1.5)')) 1159 + ``` 1160 + 1161 + ![svg](img/07_scale2.svg) 1162 + 1163 + Scaling around a center point: 1164 + 1165 + ```python 1166 + # Center of scaling: (100, 100) 1167 + d.append(dw.Circle(100, 100, 4, fill='black')) 1168 + # Non-scaled rectangle 1169 + rect = dw.Rectangle(70, 80, 60, 40, stroke='black', fill='none') 1170 + d.append(rect) 1171 + # Scaled rectangles 1172 + d.append(dw.Use(rect, 0, 0, transform='translate(-100,-100) scale(2)', stroke_width=0.5)) 1173 + d.append(dw.Use(rect, 0, 0, transform='translate(-150,-150) scale(2.5)', stroke_width=0.4)) 1174 + d.append(dw.Use(rect, 0, 0, transform='translate(-200,-200) scale(3)', stroke_width=0.33)) 1175 + ``` 1176 + 1177 + ![svg](img/07_scalcent.svg) 1178 + 1179 + 1180 + ### Rotate 1181 + 1182 + ```python 1183 + transform = 'rotate(angle,cx=0,cy=0)' 1184 + ``` 1185 + 1186 + `angle` counts clockwise in degrees. 1187 + `cx`/`cy` are the center of rotation. 1188 + 1189 + ```python 1190 + # Show frame border 1191 + d.append(dw.Rectangle(0, 0, 200, 200, stroke='gray', fill='none')) 1192 + # Rotation is around (0, 0) 1193 + d.append(dw.Rectangle(70, 30, 40, 40, fill='silver')) 1194 + d.append(dw.Rectangle(70, 30, 40, 40, fill='gray', transform='rotate(22.5)')) 1195 + d.append(dw.Rectangle(70, 30, 40, 40, fill='black', transform='rotate(45)')) 1196 + ``` 1197 + 1198 + ![svg](img/07_rota.svg) 1199 + 1200 + ```python 1201 + # Center of rotation 1202 + d.append(dw.Circle(100, 100, 3, fill='black')) 1203 + # Non-rotated arrow 1204 + arrow = dw.Group(id='arrow') 1205 + arrow.append(dw.Line(110, 100, 160, 100)) 1206 + arrow.append(dw.Lines(160, 100, 155, 95, 155, 105)) 1207 + d.append(dw.Use(arrow, 0, 0, stroke='black', fill='black')) 1208 + # Rotated arrows 1209 + g = dw.Group(stroke='red', fill='red') 1210 + g.append(dw.Use(arrow, 0, 0, transform='rotate (60,100,100)')) 1211 + g.append(dw.Use(arrow, 0, 0, transform='rotate (-90,100,100)')) 1212 + g.append(dw.Use(arrow, 0, 0, transform='rotate (-150,100,100)')) 1213 + d.append(g) 1214 + ``` 1215 + 1216 + ![svg](img/07_rota2.svg) 1217 + 1218 + 1219 + ### Skew 1220 + 1221 + ```python 1222 + transform = 'skewX(angle)' 1223 + transform = 'skewY(angle)' 1224 + ``` 1225 + 1226 + ```python 1227 + g = dw.Group(stroke='gray', stroke_dasharray='4 4') 1228 + g.append(dw.Line(0, 0, 200, 0)) 1229 + g.append(dw.Line(20, 0, 20, 90)) 1230 + g.append(dw.Line(120, 0, 120, 90)) 1231 + d.append(g) 1232 + 1233 + h = dw.Group(transform='translate(20,0)') 1234 + h1 = dw.Group(transform='skewX(30)') 1235 + h1.append(dw.Lines(50, 0, 0, 0, 0, 50, 1236 + stroke='black', fill='none', stroke_width=2)) 1237 + h1.append(dw.Text('skewX', 16, 0, 60)) 1238 + h.append(h1) 1239 + d.append(h) 1240 + 1241 + i = dw.Group(transform='translate(120,0)') 1242 + i1 = dw.Group(transform='skewY(30)') 1243 + i1.append(dw.Lines(50, 0, 0, 0, 0, 50, 1244 + stroke='black', fill='none', stroke_width=2)) 1245 + i1.append(dw.Text('skewY', 16, 0, 60)) 1246 + i.append(i1) 1247 + d.append(i) 1248 + ``` 1249 + 1250 + ![svg](img/07_skew.svg) 1251 + 1252 + 1253 + ### Cartesian Coordinates 1254 + 1255 + A drawing which can be translated to Cartesian coordinates 1256 + (where y-coordinates increase upward, not downward) 1257 + by setting the translate-y value to the drawing's height, and also applying `scale(1,-1)`. 1258 + 1259 + Trapezoid with origin to top left (the default): 1260 + 1261 + ```python 1262 + d.append(dw.Lines(0, 100, 0, 0, 100, 0, 1263 + fill='none', stroke='green', stroke_width=2)) 1264 + d.append(dw.Lines(40, 40, 100, 40, 70, 70, 40, 70, 1265 + fill='silver', stroke='black', stroke_width=2)) 1266 + d.append(dw.Text('downward y', 12, 5, 95)) 1267 + ``` 1268 + 1269 + ![svg](img/07_cart1.svg) 1270 + 1271 + Translated origin to bottom left and upward-y: 1272 + 1273 + ```python 1274 + g = dw.Group(transform='translate(0,100) scale(1,-1)') 1275 + g.append(dw.Lines(0, 100, 0, 0, 100, 0, 1276 + fill='none', stroke='green', stroke_width=2)) 1277 + g.append(dw.Lines(40, 40, 100, 40, 70, 70, 40, 70, 1278 + fill='silver', stroke='black', stroke_width=2)) 1279 + g.append(dw.Text('upward y', 12, 5, 95)) 1280 + d.append(g) 1281 + ``` 1282 + 1283 + ![svg](img/07_cart2.svg) 1284 + 1285 + Alternatively, apply `scale(1,-1)` to the whole drawing: 1286 + 1287 + ```python 1288 + d = dw.Drawing(100, 100, id_prefix='cart3', transform='scale(1,-1)') 1289 + d.append(dw.Lines(0, 100, 0, 0, 100, 0, 1290 + fill='none', stroke='green', stroke_width=2)) 1291 + d.append(dw.Lines(40, 40, 100, 40, 70, 70, 40, 70, 1292 + fill='silver', stroke='black', stroke_width=2)) 1293 + d.append(dw.Text('upward y', 12, 5, 95)) 1294 + ``` 1295 + 1296 + ![svg](img/07_cart3.svg) 1297 + 1298 + 1299 + ## Credits 1300 + 1301 + Written by joachim heintz 2023. Edited by Casey Duckering. 1302 + 1303 + Most examples are based on J. David Eisenberg, SVG Essentials, O'Reilly 2002. 1304 + 1305 + 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). 1306 + 1307 + 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
··· 1 + site_name: Drawsvg Quick Reference 2 + nav: 3 + - Home: index.md 4 + theme: readthedocs