From 34b3f09e431687773cdb5f4fec204c79309305d0 Mon Sep 17 00:00:00 2001
From: Ryan Oldenburg <guzba8@gmail.com>
Date: Fri, 19 Feb 2021 12:04:27 -0600
Subject: [PATCH] fill and stroke helpers

---
 README.md                                |  16 ++-
 examples/blur.nim                        |   2 +-
 examples/line.nim                        |   2 +-
 examples/rounded_rectangle.nim           |   2 +-
 examples/shadow.nim                      |   8 +-
 examples/square.nim                      |   2 +-
 src/pixie.nim                            | 165 +++++++++++++++++++----
 tests/images/masks/strokeEllipse.png     | Bin 0 -> 905 bytes
 tests/images/masks/strokePolygon.png     | Bin 0 -> 1486 bytes
 tests/images/masks/strokeRect.png        | Bin 0 -> 345 bytes
 tests/images/masks/strokeRoundedRect.png | Bin 0 -> 831 bytes
 tests/images/strokeEllipse.png           | Bin 0 -> 2607 bytes
 tests/images/strokePolygon.png           | Bin 0 -> 2621 bytes
 tests/images/strokeRect.png              | Bin 0 -> 565 bytes
 tests/images/strokeRoundedRect.png       | Bin 0 -> 1497 bytes
 tests/test_images_draw.nim               |  51 ++++++-
 tests/test_masks.nim                     |  30 ++++-
 17 files changed, 225 insertions(+), 53 deletions(-)
 create mode 100644 tests/images/masks/strokeEllipse.png
 create mode 100644 tests/images/masks/strokePolygon.png
 create mode 100644 tests/images/masks/strokeRect.png
 create mode 100644 tests/images/masks/strokeRoundedRect.png
 create mode 100644 tests/images/strokeEllipse.png
 create mode 100644 tests/images/strokePolygon.png
 create mode 100644 tests/images/strokeRect.png
 create mode 100644 tests/images/strokeRoundedRect.png

diff --git a/README.md b/README.md
index 53be7ab..cd591af 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ let
   pos = vec2(50, 50)
   wh = vec2(100, 100)
 
-image.drawRect(rect(pos, wh), rgba(255, 0, 0, 255))
+image.fillRect(rect(pos, wh), rgba(255, 0, 0, 255))
 ```
 ![example output](examples/square.png)
 
@@ -42,7 +42,7 @@ let
   stop = vec2(175, 175)
   color = parseHtmlColor("#FF5C00").rgba
 
-image.drawSegment(segment(start, stop), color, strokeWidth = 10)
+image.strokeSegment(segment(start, stop), color, strokeWidth = 10)
 ```
 ![example output](examples/line.png)
 
@@ -54,7 +54,7 @@ let
   wh = vec2(100, 100)
   r = 25.0
 
-image.drawRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255))
+image.fillRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255))
 ```
 ![example output](examples/rounded_rectangle.png)
 
@@ -79,19 +79,21 @@ image.fillPath(
 [examples/shadow.nim](examples/shadow.nim)
 ```nim
 let polygonImage = newImage(200, 200)
-polygonImage.drawPolygon(
+polygonImage.fillPolygon(
   vec2(100, 100),
   70,
   sides = 8,
   rgba(255, 255, 255, 255)
 )
 
-image.draw(polygonImage.shadow(
+let shadow = polygonImage.shadow(
   offset = vec2(2, 2),
   spread = 2,
   blur = 10,
   color = rgba(0, 0, 0, 200)
-))
+)
+
+image.draw(shadow)
 image.draw(polygonImage)
 ```
 ![example output](examples/shadow.png)
@@ -100,7 +102,7 @@ image.draw(polygonImage)
 [examples/blur.nim](examples/blur.nim)
 ```nim
 let mask = newMask(200, 200)
-mask.drawPolygon(vec2(100, 100), 70, sides = 6)
+mask.fillPolygon(vec2(100, 100), 70, sides = 6)
 
 blur.blur(20)
 blur.draw(mask, blendMode = bmMask)
diff --git a/examples/blur.nim b/examples/blur.nim
index e9889fd..16d34b5 100644
--- a/examples/blur.nim
+++ b/examples/blur.nim
@@ -8,7 +8,7 @@ let
 image.fill(rgba(255, 255, 255, 255))
 
 let mask = newMask(200, 200)
-mask.drawPolygon(vec2(100, 100), 70, sides = 6)
+mask.fillPolygon(vec2(100, 100), 70, sides = 6)
 
 blur.blur(20)
 blur.draw(mask, blendMode = bmMask)
diff --git a/examples/line.nim b/examples/line.nim
index 3a03e23..24f9b76 100644
--- a/examples/line.nim
+++ b/examples/line.nim
@@ -8,6 +8,6 @@ let
   stop = vec2(175, 175)
   color = parseHtmlColor("#FF5C00").rgba
 
-image.drawSegment(segment(start, stop), color, strokeWidth = 10)
+image.strokeSegment(segment(start, stop), color, strokeWidth = 10)
 
 image.writeFile("examples/line.png")
diff --git a/examples/rounded_rectangle.nim b/examples/rounded_rectangle.nim
index 776fb6d..79bc160 100644
--- a/examples/rounded_rectangle.nim
+++ b/examples/rounded_rectangle.nim
@@ -8,6 +8,6 @@ let
   wh = vec2(100, 100)
   r = 25.0
 
-image.drawRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255))
+image.fillRoundedRect(rect(pos, wh), r, rgba(0, 255, 0, 255))
 
 image.writeFile("examples/rounded_rectangle.png")
diff --git a/examples/shadow.nim b/examples/shadow.nim
index 52c0d33..399ab9b 100644
--- a/examples/shadow.nim
+++ b/examples/shadow.nim
@@ -4,19 +4,21 @@ let image = newImage(200, 200)
 image.fill(rgba(255, 255, 255, 255))
 
 let polygonImage = newImage(200, 200)
-polygonImage.drawPolygon(
+polygonImage.fillPolygon(
   vec2(100, 100),
   70,
   sides = 8,
   rgba(255, 255, 255, 255)
 )
 
-image.draw(polygonImage.shadow(
+let shadow = polygonImage.shadow(
   offset = vec2(2, 2),
   spread = 2,
   blur = 10,
   color = rgba(0, 0, 0, 200)
-))
+)
+
+image.draw(shadow)
 image.draw(polygonImage)
 
 image.writeFile("examples/shadow.png")
diff --git a/examples/square.nim b/examples/square.nim
index 578007c..1942f17 100644
--- a/examples/square.nim
+++ b/examples/square.nim
@@ -7,6 +7,6 @@ let
   pos = vec2(50, 50)
   wh = vec2(100, 100)
 
-image.drawRect(rect(pos, wh), rgba(255, 0, 0, 255))
+image.fillRect(rect(pos, wh), rgba(255, 0, 0, 255))
 
 image.writeFile("examples/square.png")
diff --git a/src/pixie.nim b/src/pixie.nim
index f8b4caf..35d1971 100644
--- a/src/pixie.nim
+++ b/src/pixie.nim
@@ -50,51 +50,95 @@ proc writeFile*(image: Image, filePath: string) =
       raise newException(PixieError, "Unsupported image file extension")
   image.writeFile(filePath, fileformat)
 
-proc drawRect*(
-  image: Image, rect: Rect, color: ColorRGBA, blendMode = bmNormal
-) =
+proc fillRect*(image: Image, rect: Rect, color: ColorRGBA) =
   var path: Path
   path.rect(rect)
-  image.fillPath(path, color, wrNonZero, blendMode)
+  image.fillPath(path, color)
 
-proc drawRect*(mask: Mask, rect: Rect) =
+proc fillRect*(mask: Mask, rect: Rect) =
   var path: Path
   path.rect(rect)
   mask.fillPath(path)
 
-proc drawRoundedRect*(
+proc strokeRect*(
+  image: Image, rect: Rect, color: ColorRGBA, strokeWidth = 1.0
+) =
+  var path: Path
+  path.rect(rect)
+  image.strokePath(path, color, strokeWidth)
+
+proc strokeRect*(mask: Mask, rect: Rect, strokeWidth = 1.0) =
+  var path: Path
+  path.rect(rect)
+  mask.strokePath(path, strokeWidth)
+
+proc fillRoundedRect*(
+  image: Image,
+  rect: Rect,
+  nw, ne, se, sw: float32,
+  color: ColorRGBA
+) =
+  var path: Path
+  path.roundedRect(rect, nw, ne, se, sw)
+  image.fillPath(path, color)
+
+proc fillRoundedRect*(
+  image: Image,
+  rect: Rect,
+  radius: float32,
+  color: ColorRGBA
+) =
+  var path: Path
+  path.roundedRect(rect, radius, radius, radius, radius)
+  image.fillPath(path, color)
+
+proc fillRoundedRect*(mask: Mask, rect: Rect, nw, ne, se, sw: float32) =
+  var path: Path
+  path.roundedRect(rect, nw, ne, se, sw)
+  mask.fillPath(path)
+
+proc fillRoundedRect*(mask: Mask, rect: Rect, radius: float32) =
+  var path: Path
+  path.roundedRect(rect, radius, radius, radius, radius)
+  mask.fillPath(path)
+
+proc strokeRoundedRect*(
   image: Image,
   rect: Rect,
   nw, ne, se, sw: float32,
   color: ColorRGBA,
-  blendMode = bmNormal
+  strokeWidth = 1.0
 ) =
   var path: Path
   path.roundedRect(rect, nw, ne, se, sw)
-  image.fillPath(path, color, wrNonZero, blendMode)
+  image.strokePath(path, color, strokeWidth)
 
-proc drawRoundedRect*(
+proc strokeRoundedRect*(
   image: Image,
   rect: Rect,
   radius: float32,
   color: ColorRGBA,
-  blendMode = bmNormal
+  strokeWidth = 1.0
 ) =
   var path: Path
   path.roundedRect(rect, radius, radius, radius, radius)
-  image.fillPath(path, color, wrNonZero, blendMode)
+  image.strokePath(path, color, strokeWidth)
 
-proc drawRoundedRect*(mask: Mask, rect: Rect, nw, ne, se, sw: float32) =
+proc strokeRoundedRect*(
+  mask: Mask, rect: Rect, nw, ne, se, sw: float32, strokeWidth = 1.0
+) =
   var path: Path
   path.roundedRect(rect, nw, ne, se, sw)
-  mask.fillPath(path)
+  mask.strokePath(path, strokeWidth)
 
-proc drawRoundedRect*(mask: Mask, rect: Rect, radius: float32) =
+proc strokeRoundedRect*(
+  mask: Mask, rect: Rect, radius: float32, strokeWidth = 1.0
+) =
   var path: Path
   path.roundedRect(rect, radius, radius, radius, radius)
-  mask.fillPath(path)
+  mask.strokePath(path, strokeWidth)
 
-proc drawSegment*(
+proc strokeSegment*(
   image: Image,
   segment: Segment,
   color: ColorRGBA,
@@ -106,13 +150,13 @@ proc drawSegment*(
   path.lineTo(segment.to)
   image.strokePath(path, color, strokeWidth, wrNonZero, blendMode)
 
-proc drawSegment*(mask: Mask, segment: Segment, strokeWidth: float32) =
+proc strokeSegment*(mask: Mask, segment: Segment, strokeWidth: float32) =
   var path: Path
   path.moveTo(segment.at)
   path.lineTo(segment.to)
   mask.strokePath(path, strokeWidth)
 
-proc drawEllipse*(
+proc fillEllipse*(
   image: Image,
   center: Vec2,
   rx, ry: float32,
@@ -123,7 +167,7 @@ proc drawEllipse*(
   path.ellipse(center, rx, ry)
   image.fillPath(path, color, wrNonZero, blendMode)
 
-proc drawEllipse*(
+proc fillEllipse*(
   mask: Mask,
   center: Vec2,
   rx, ry: float32
@@ -132,18 +176,38 @@ proc drawEllipse*(
   path.ellipse(center, rx, ry)
   mask.fillPath(path)
 
-proc drawCircle*(
+proc strokeEllipse*(
+  image: Image,
+  center: Vec2,
+  rx, ry: float32,
+  color: ColorRGBA,
+  strokeWidth = 1.0
+) =
+  var path: Path
+  path.ellipse(center, rx, ry)
+  image.strokePath(path, color, strokeWidth)
+
+proc strokeEllipse*(
+  mask: Mask,
+  center: Vec2,
+  rx, ry: float32,
+  strokeWidth = 1.0
+) =
+  var path: Path
+  path.ellipse(center, rx, ry)
+  mask.strokePath(path, strokeWidth)
+
+proc fillCircle*(
   image: Image,
   center: Vec2,
   radius: float32,
-  color: ColorRGBA,
-  blendMode = bmNormal
+  color: ColorRGBA
 ) =
   var path: Path
   path.ellipse(center, radius, radius)
-  image.fillPath(path, color, wrNonZero, blendMode)
+  image.fillPath(path, color)
 
-proc drawCircle*(
+proc fillCircle*(
   mask: Mask,
   center: Vec2,
   radius: float32
@@ -152,19 +216,39 @@ proc drawCircle*(
   path.ellipse(center, radius, radius)
   mask.fillPath(path)
 
-proc drawPolygon*(
+proc strokeCircle*(
+  image: Image,
+  center: Vec2,
+  radius: float32,
+  color: ColorRGBA,
+  strokeWidth = 1.0
+) =
+  var path: Path
+  path.ellipse(center, radius, radius)
+  image.fillPath(path, color)
+
+proc strokeCircle*(
+  mask: Mask,
+  center: Vec2,
+  radius: float32,
+  strokeWidth = 1.0
+) =
+  var path: Path
+  path.ellipse(center, radius, radius)
+  mask.fillPath(path)
+
+proc fillPolygon*(
   image: Image,
   pos: Vec2,
   size: float32,
   sides: int,
-  color: ColorRGBA,
-  blendMode = bmNormal
+  color: ColorRGBA
 ) =
   var path: Path
   path.polygon(pos, size, sides)
-  image.fillPath(path, color, wrNonZero, blendMode)
+  image.fillPath(path, color)
 
-proc drawPolygon*(
+proc fillPolygon*(
   mask: Mask,
   pos: Vec2,
   size: float32,
@@ -173,3 +257,26 @@ proc drawPolygon*(
   var path: Path
   path.polygon(pos, size, sides)
   mask.fillPath(path)
+
+proc strokePolygon*(
+  image: Image,
+  pos: Vec2,
+  size: float32,
+  sides: int,
+  color: ColorRGBA,
+  strokeWidth = 1.0
+) =
+  var path: Path
+  path.polygon(pos, size, sides)
+  image.strokePath(path, color, strokeWidth)
+
+proc strokePolygon*(
+  mask: Mask,
+  pos: Vec2,
+  size: float32,
+  sides: int,
+  strokeWidth = 1.0
+) =
+  var path: Path
+  path.polygon(pos, size, sides)
+  mask.strokePath(path, strokeWidth)
diff --git a/tests/images/masks/strokeEllipse.png b/tests/images/masks/strokeEllipse.png
new file mode 100644
index 0000000000000000000000000000000000000000..872ae6fb6fe1a8519ae23fb0c46c066b166d3752
GIT binary patch
literal 905
zcmV;419tq0P)<h;3K|Lk000e1NJLTq003kF003kN00000Rf)=o0009}Nkl<ZcmeH}
zZAcVd7>18*wBT317z$&Cf*`hmDM%QZB<vQEwWeunNG39rYaa$>gyt?31&T(A$teCX
zN>NF4G3k$n;09r4`PC|Dm^tz)MyUO8*^Jo_XJ+@z**Pmj#JPSf=bYy`&%Mt*bC{z5
ze*hwa1+fbYViy*~E-Z*$SP;9gAa-Fv?81WBg$1z-3t|@*f0<ozN7C~vX#G=z!EmOK
zPKpZ$%W~V1*GWX?ow}Pj>O_hP=L&~YRH8aZUz`-Mw93uBAwxuwS^Gq*^7pLduhQN~
zUAJs{M%?f!qP*Tw5bd@}Ky)?@hHZic7~VwGCS4$GA5Wkr+cLvXVW35nOm!%1mzdDJ
zy|0nYAVq?DGQ{PiNI3j*Ln;OUQY5hd5SJo{D0K@$1=YzjwVe76sF)7N00u(j)IHb+
zDO4XUQXzzhqBlgmYrd<a;URP7uJJ(^)Bo{XXs|e(Tq}8Cq&qoLBrGyssW0yw7-Lx*
z05+B#8|bWg{xu>@kP`B4S}+qKEmD%iCz{XSHm~qg2P@{fzSu~|nBzwe_X|T>q<oJn
z->NT~bB)E!H7y?7s_?5(9OT(b@t}N{b7}oTvvUODy(OJ1!S=tXs$Pf0?Qj`zN?an=
z?s0gAo&DM!0D!dxmR;~c<ebZ{ou`+E?Db$=YEb(5`S}IK9?ebh!LG!u2d_A(nT9`<
zl$Oi96(%1ZJjmt$dE~{j{{OqbUNHqsso>=TMju|`nY{ma6%eMmT9}}sl+=n1C=XDn
z+QP?W8sRYkv)6n$jGMDMfd~K~I6f_lrppY5GMdgxi+4NlApbL$1ckTM1Is>@$C@;4
z_oZV95zwolq&K=TlwoyS5r7i0wkAgjQc=7)zJ>^+M8HNXm4MjG)1>>!Pdq`209&{D
zp!bjbl&%K(iT5G`z)ZvUc=UB;v7%tg^UsSwcLD&gy?r#gTl(VFcZ)Wo+wgLcaI!hk
z+&F3t3vf<(mR?mA*G@<tK_0K2*jXKEuWaiZ{sP!#?lSyop6zL?H<q@K$hr#46yaE&
z95gXZz0qhi)-#N0a8mZA9z$ds$g^vk5D_ehU04viupo9}LF~eU*o6hL3kzZw7Q`+r
fh+SCxJ9hmB;jGh{!ja#D00000NkvXXu0mjfSu~{*

literal 0
HcmV?d00001

diff --git a/tests/images/masks/strokePolygon.png b/tests/images/masks/strokePolygon.png
new file mode 100644
index 0000000000000000000000000000000000000000..96825901fca586d253ecbd058fbda08e8073ca7d
GIT binary patch
literal 1486
zcmV;<1u^=GP)<h;3K|Lk000e1NJLTq003kF003kN00000Rf)=o000G*Nkl<ZcmeI1
zYitx%7>2)@ZK2W|LWu<_u^>%j!M51lQUR+`sYWT3)`o&;p``^h2BV2Tga9QPqN$hS
zC2dK$Sz1~`s}T?*5q~J%QffmrfwaVew$aLEx!BvfGiJMUzPX(_GgAq__W7~<?K$r`
z@0_zc=X`V40e69*i7kTDWsBf+*&;Yywg^s_ErQc!3-jrkRa3u>MM~RsGe<L%$g%@-
z*nK3HMz}}V5)+drPCXOC?f@WU;hOdyrig7a?wc9R))Em5Dt%H&g>CX?KDCjKN&oz)
zD^tKUiES9Kkg{;?z0Ig*npDhZv{W&E@|UX5YFH*|pKwGh3OorF_&5|KAL~<8XkeK%
zl5brUeAM3<|1S_5ZcdG+X9WzCm764;4|tI_5CGAELyYU{l;nDhO(rx)OLCs8c5SD!
zV_F)zyDGhsUWc*CmL(|m<P2b}#=S0#6hsT(lTeGH$&A`i)V_TZLk$DoEG%(;aRXyD
zh9*@hC_KMLz*tM$3o)c9^!~#n)L>+?uv``vo|j`SLeEMpN;-KNV-*G_eA85v9ovQ>
zg)Y}@EKRKzF;-$=QdEK>Z_X8rX|$JOA5;Hmrzs3fqME}|T~Ui6l`HpVVEO#2VT={v
zRj7F9Y5e$i-Vnxg+(mdr;p4ugX{aU-?w5<-U@qc*hHgIZe;dVFcWv}tjoh1p{fYRY
zV?F)5RML?hOFlYg9VDRwn#tlaSy1qs92+5CD8#CS(-$#DC?+9a;r#`T@1v4IPf`-r
zIxF>eF2&^4)!1Sv$AdA8wo=>*Vy?P%O1;VCCS3Di=Mh~4DxR>%usmb;AjT4Ulk!DU
z6+mx+NkWC3c{z&2VUb5kNYI(gt;QV!UTGsTGe-KCqhwxFKgI!cCiOD|6#&pewnhtd
zW=$t5K5-ujCA21)+ocMxL(J=yVk>kOb3O><6_E{^jYVscx<cyF%OChu3N6ta|1j_Z
z$AS0b<z~~BNKC|AxwkC!PG~Kf!11DRd}*C-k<^X^O@xup?3qMvyazyp?h{vuEn;Zm
z4WH7CDl6=A37o+53F{}eXosRTxeu2iNAhtyU%YD<58&Vc92x7(zW7U-@qx?cft$-n
z3bk;D<1m|aS7>UrBZ2l3ycwr=pVO#~dGR%@^DQ&`bwPiu6XoeuR+p8CW?WXFau0SO
zp&JRbl;8pxWt<dh*dlL^o*WAc<lx}5*n{h!wWU737MFT>>l8L8=tlx)^KsJ(nbt^z
zOsbNx`uti;o0iZe?^;Peu%BxKJpNwb-Os8n|En6xNZ_I~0Yxdh%@Ya75lkfD=niZu
zLo<Qa4Okr8cUBe~P*RK)-X)e(qHEEQVzcyWv*d1K6DD`?Q9U+PfS0VIMUfPaKcTA9
z^X`*a)}N<cwnm|w412OiYyG4(vJ>vaJ#rtLPWxNvkOe9_vhmTuF_V@Q%IuTV&7U{W
ze<cPc;;(D5o7ruYUnTO~RtzEkk{l~BFoDYt$w}e7D*gRM2yMbU7aBewr5cP(ptTeq
zOk+IssrIvJmH%~=fu)-K0WmbW5tfOf^ctf_>?wzFHHDpqJE@@wxL+cN1rQefH5#h<
zZ~=b)eZ?3K3%q~jN*(y%k<De)W5~^Ec<cci>CcOPj7I{Ui{tzX03HO9uJZv;_R*hS
z4~S{d8wWU79LNZP<9Yf~l!KQPAmonmD5~#))PS4chD1ux0$}gw$_fpvk$}6z>ha*s
zoG~8{-WH$IT$2%7nX4#sBygr+l2NxRx>x^?BU|4uSrMw<==@nodE`~V9treR@lH7r
zp)*{be}P^@FfoCV@9JjAYdMYPWsPPjpqUB4^+VL-N92&{pAHsG?f~W^xdQ}EY!RF;
oTLh=e7QyMVMR2-oaaX46Kktit5!@d7=Kufz07*qoM6N<$g3r3PlmGw#

literal 0
HcmV?d00001

diff --git a/tests/images/masks/strokeRect.png b/tests/images/masks/strokeRect.png
new file mode 100644
index 0000000000000000000000000000000000000000..c44294a140756a669d05855ef594c69f0a00c3be
GIT binary patch
literal 345
zcmeAS@N?(olHy`uVBq!ia0vp^DIm-NBp5<FPjxUbFe-SuIEGX(zMUSqu0=tFHUIdR
zLw9CmelB~q&8J3oN0+im`$7KVSHV**9dgNe!lu!<!}|Jv^&=(@=KGUBtIWT9V4~S!
zA>ET3k9ZsDG^pHNB((e4@z8>vs!1NVcP9%}?Tt^!n6q?I%GN7WEWATcCTXfveoa5q
z_41bJq!{01l~Y$USgP6|W*%BB7{GKeM&Jx9nD}@irmVbl>qhg;HwlgB-|uR-Hs1Gk
zBh&qg{i$VBCRFHlFYY*!T-axG^2)6zM*A<ae=!xGsP}QYpSr{xRhRGLQoIW$X?Sl+
zp6C*BN!IVv<w*}CRE_3r{~RrJ{f^Ok&sdGd1U-&tO+*kCe(UsY{!dz2uUFs!3Nuev
KKbLh*2~7aN-<G-n

literal 0
HcmV?d00001

diff --git a/tests/images/masks/strokeRoundedRect.png b/tests/images/masks/strokeRoundedRect.png
new file mode 100644
index 0000000000000000000000000000000000000000..73a2437637de8b2b892a1b9d3538e57d1f6bb67b
GIT binary patch
literal 831
zcmeAS@N?(olHy`uVBq!ia0vp^DIm-NBp5<FPjxUbFtd5OIEGX(zMbytBkU;AwtuN;
z)daaEijGb8=AJwUXE-?Z$oNRT^4u}8En^Ma>H>p*F4@^#op(9}cit*c4f9lKV=<9a
z3As>VDCNqja^%P4Z)#c5w`LjrKI`*(+lRMod(ISR?4LO||K7RXck|P8Ht=c)3jIH-
z_kHJwtG|{f`jwY2-sbV^CY#8bBiHQT<!2Y@ns+v?Yuh&O-j~;NUKlp&T>5b&eC~Xu
zjrRXFSA3J1-`TAu>-pr<4Y_IaOE%^o%!@Ay+j4?q;=={8=kGndz}$E@)>tztWXFl6
z0{*2-D%UUgn(kxL@t}lV?tvA9Lib*yw}F?xyUssnw=sOyg@7aXjAl(e7I48;Z_dQY
zJgy7u?DYAS4!Gn5E}xUE!{l4;Yp3V4Wbgd!l>76)w6jfEDBd0;6<2H*e{2Gq@XPGO
zYjT!+cIJ|1Sb2WpuC#TNW(b9A7)(51cc!vjsZ%jIch%-;t_&{&dom0rKG3t(e*Slf
z`<ydQ{CcX!XR197CLZ*%^?W^f&!tZGFAS^L3>O`A$x9AW>zJq@y6S@TROTv&md+N#
z)rT^qE~+aDxhl0?{xCnGqEr|de5dq;T+34PBvU@OU%VCngKOH<E^F7Xf(&!^tXUJK
zrM<kev1Z$p`P&<m_c*MJ(3%h%@oMYg@5ZcL455$rT-m=h<Q4y?>C;x{RjqY6YWV1w
z7eBx5-Yr4P3zF9E%zimr<GXdg>)nWE#=MBCzw3VdaC2JymF>qoJDCsHK9wGr-aXAs
zXy+F8=|OD|P8*4zJ~&Uf;&Nbo-W99Qb=|Xfzc~|`IXlZ^)8qEU|7sV)nLgfs$Lkh9
z`$mF8W&lf)>Ds04j0g74{^?&_AUGq&HtN<!`|C$fHuVWK-gMVp`tG0h`Q%?$m^@h?
zO?3JEYvIO@^#|iFf3J~^WGO0k-uV85x1CX4jD)m>eflRw7cLiughDH$rs!Wb$`dnB
vAOBJBvaRLO)ErK)mX=N3B%veQZhRFFczkGXNKC66C}()O`njxgN@xNAPOOOw

literal 0
HcmV?d00001

diff --git a/tests/images/strokeEllipse.png b/tests/images/strokeEllipse.png
new file mode 100644
index 0000000000000000000000000000000000000000..828dd587db6ee5df53aa6216e09019661918061c
GIT binary patch
literal 2607
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
LTNzawy5s)`@{rbg

literal 0
HcmV?d00001

diff --git a/tests/images/strokePolygon.png b/tests/images/strokePolygon.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4483df04bf0cd0006e065803b563b83c8579c6e
GIT binary patch
literal 2621
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
WR|cr!_w&~+6gcVNj%h>(lm7*D^uSgC

literal 0
HcmV?d00001

diff --git a/tests/images/strokeRect.png b/tests/images/strokeRect.png
new file mode 100644
index 0000000000000000000000000000000000000000..3d8128a172324da11bc2943f2770e5abbd078406
GIT binary patch
literal 565
zcmeAS@N?(olHy`uVBq!ia0vp^DIm<j1|$m}O$}jSVEp6h;uuoF`1bZiua*E2w}-Nq
zie34`B5WfrWV1^Czu?OAio^2w)j3-o_7orfrzdh{;j+wCg)+7h))IaKZJq)VO$UTn
zuBA;_`7UeC^k>JzdA|noZ`c~U{;a}5i$%w)-gB|?PpWeIDXy?md`dm@q$-D*tTT5v
zZhx`)UG|FgR|6eSE<U=}jJxOxuZ=`>088c#F%d_pa!%I?%u&vQDGPVc@;iO9>6^v5
z_py#MwKwN&wZD7id)yhz6G7GIRaH5391}R1ydiFwrm%sf5tmRd+sxl_TI*xJ+nk#{
zduB~*bm^}L37L-9H8#I{UHt7*)1N8p9X73)vpzCSCsD<*PP9iy=Xv&&?Das-IW9M`
z>7VC4oi*Jcs9fP^uTK2T^;^x|ZWWz<UbXjS{GGJ<n?Cv97n^d8_3_$yQT@5MbUYR<
z{L(N{%u$GSsd&#8u1S4vFFBQCSv(z2PChH>p7#BUnn3n+e6A(VPiU%6WL@2}@K|Av
k-BmGR7QBH0*Lcmm`@6rx>4nMCz~sQ->FVdQ&MBb@0GSWnqyPW_

literal 0
HcmV?d00001

diff --git a/tests/images/strokeRoundedRect.png b/tests/images/strokeRoundedRect.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1745c6fb2f2f991dfafcde360a32e0331cc1ce6
GIT binary patch
literal 1497
zcmcIkYcvxI07k`(F^bK4upvg4Z5AoAS=cIhtSir$5vP)kJSr#eN5(aVc|^OeSGu>X
z!epjm$drhRD9kh0@hGgUZuj1E&*|6wchC7=KffQ}`7&Ib9YH`CP)<$`L~<g!eRtYl
z1So#j@QHkioZPmXBqE*?BmYN9=y}Si9r3~_axHK(hkP3ZK*_%Zs{&Jv+rf1qK6X9;
zIATzbj03{VGLz1u3F&THAd9ABM6$tk?F?5yh-=c7Q3dj8VjmHYtlS+DMxZ_xUx^-`
z6OZ>wbJqjM-Ucno##+`F1v4Ti1I_kH`k}~=cyWgLOMe18;BUM@!L?pSK#pZ#OVVNz
z8Bxo&9!<{~s0C=x2j&#+^MI55685a=hq8sdh8(CF#npay1xI{OH3)0-hJ;jljlZb4
zR2gk*@UtWzBU;7e#gqkGFC!tWn|%*UjadabU$1tK_}Cjhh@5&)mxaeKehlcO&&07X
zjw>jSRke~PrmS?j1c!-HDH0KWVwegxa6ywL#$2`xDO{gYjdJg1c#H+7eh$vu>PIM>
z@C!CCL}V)-Xx`q-?%Tl;L2By~KSj={525=lN0d+2<kaq??u`(@OfV81aK)ghK;1s%
zy`JxzT%&JnJGd-F0t%~2*Di03xUbn$0}im#<y}WFR8wpnirEB7L4CowgV^^)EM_(s
z0crPd;3bZPW^Igkkm2h~7SVV2d6p~nYY?{TOm=yDY_XRF(nuym5sZ;JD|#1d*;0`V
zz=&dVzaVTJNG3EZUDpoHxg-~f_KMjIedm5mQKguscF(?ZmadJ?%2J&qH1OrA@)>>2
z5(Q~|&#0WmEdwn~3M`dpc)u4>QINr;g0enN0y?;{+3?V76T1q9Oo1w`q>#OZ?RK)G
zo{DgEgAa<UErrPk)^<LdQ5<TL_whbR*7)SpZ9G5wsI`w;j11nkoiK2t#y|^^)aEY5
z-aVlVgm%_#cJUMDu7+^ab!U5G{1|ymypxwsjYIygglYE^=-z}21#dk04|a1S{H@PO
zK(~swak~#iw98s+aw%PhtI`@8Q=nK5r1%*`!xXEK0#}dbyGSbG-|HhjKm(jQgPH?_
zS3^!e$Ugq6F5`fT24)m(3rWnGyNvs1a6jscU^vG7D$`TvLiY1Em#&Ae#*{o~9oq3-
zZQ*G3J~p>DFKlyaFYbv|J5p+S3B&Tb)7=4L`X4%*@`(#6<aM88(2WEu7a4SmI{WH(
zK@2*$yuOrdxn*RJ^?(EckE?noq}qKwAw1Le%1?!&3G@=}8FC*V!VMFY(`va-JN%`$
zVXfVqP4AnzgDuJ};9+5Z0<Yh)*t%gLO~B^2*hY@)>A!9>31eV@Hi7&q?2&H;;nDpA
zDU7GEC@7**Nr=t%czZeZIQa7}-WojC;0}BI3F;}oyh93+=&@!r6RdJC*~-{Bnrtc%
z)$J9>*PF8<Zj|DEI<7b!W-G#=3k^q{{ExCpNFog7t*}Td%G@P3#0;@A19fc}QY?=^
zh9|c7f9)ZKRZ~#0oKDZ4OZ-h`PkonkJ=YnYq1`Wi5sx%)aXLzUC^xnfQUJUolVD${
z$N`dk1El8uSbtwQD@U4K2*yWYew%hs9I!k1aEg*vpPxB8)X><}`eeTEdLtN5tu~0H
ztZAxAR2q%U^A@;b!LaiLza=K#NZ$;e$aJ+00AzCJ%k~TD&85@2&Qb2jxh0!8-}VV|
z7#(gGy~;H8p6~ML*Iv0sJHr<T4!V&*?r*JAZlBuNlk2!b)^RJqe@TWGRr`Je>#uUa
yLH|2)?7FPc6U#9}=WuS+f3NPx<^6YF*400D#~82%J^KB!<w!@JiN6#46aNIzL9Rpq

literal 0
HcmV?d00001

diff --git a/tests/test_images_draw.nim b/tests/test_images_draw.nim
index a553d84..b4d1c99 100644
--- a/tests/test_images_draw.nim
+++ b/tests/test_images_draw.nim
@@ -53,13 +53,19 @@ block:
 block:
   let image = newImage(100, 100)
   image.fill(rgba(0, 255, 255, 255))
-  image.drawRect(rect(vec2(10, 10), vec2(30, 30)), rgba(255, 255, 0, 255))
+  image.fillRect(rect(vec2(10, 10), vec2(30, 30)), rgba(255, 255, 0, 255))
   image.writeFile("tests/images/drawRect.png")
 
 block:
   let image = newImage(100, 100)
   image.fill(rgba(0, 255, 255, 255))
-  image.drawRoundedRect(
+  image.strokeRect(rect(vec2(10, 10), vec2(30, 30)), rgba(255, 255, 0, 255), 10)
+  image.writeFile("tests/images/strokeRect.png")
+
+block:
+  let image = newImage(100, 100)
+  image.fill(rgba(0, 255, 255, 255))
+  image.fillRoundedRect(
     rect(vec2(10, 10), vec2(30, 30)),
     10,
     rgba(255, 255, 0, 255)
@@ -69,7 +75,18 @@ block:
 block:
   let image = newImage(100, 100)
   image.fill(rgba(0, 255, 255, 255))
-  image.drawSegment(
+  image.strokeRoundedRect(
+    rect(vec2(10, 10), vec2(30, 30)),
+    10,
+    rgba(255, 255, 0, 255),
+    10
+  )
+  image.writeFile("tests/images/strokeRoundedRect.png")
+
+block:
+  let image = newImage(100, 100)
+  image.fill(rgba(0, 255, 255, 255))
+  image.strokeSegment(
     segment(vec2(10, 10), vec2(90, 90)),
     rgba(255, 255, 0, 255),
     strokeWidth = 10
@@ -79,7 +96,7 @@ block:
 block:
   let image = newImage(100, 100)
   image.fill(rgba(0, 255, 255, 255))
-  image.drawEllipse(
+  image.fillEllipse(
     vec2(50, 50),
     25,
     25,
@@ -90,10 +107,34 @@ block:
 block:
   let image = newImage(100, 100)
   image.fill(rgba(0, 255, 255, 255))
-  image.drawPolygon(
+  image.strokeEllipse(
+    vec2(50, 50),
+    25,
+    25,
+    rgba(255, 255, 0, 255),
+    10
+  )
+  image.writeFile("tests/images/strokeEllipse.png")
+
+block:
+  let image = newImage(100, 100)
+  image.fill(rgba(0, 255, 255, 255))
+  image.fillPolygon(
     vec2(50, 50),
     30,
     6,
     rgba(255, 255, 0, 255)
   )
   image.writeFile("tests/images/drawPolygon.png")
+
+block:
+  let image = newImage(100, 100)
+  image.fill(rgba(0, 255, 255, 255))
+  image.strokePolygon(
+    vec2(50, 50),
+    30,
+    6,
+    rgba(255, 255, 0, 255),
+    10
+  )
+  image.writeFile("tests/images/strokePolygon.png")
diff --git a/tests/test_masks.nim b/tests/test_masks.nim
index 5818291..1f79c39 100644
--- a/tests/test_masks.nim
+++ b/tests/test_masks.nim
@@ -105,17 +105,27 @@ block:
 
 block:
   let mask = newMask(100, 100)
-  mask.drawRect(rect(vec2(10, 10), vec2(30, 30)))
+  mask.fillRect(rect(vec2(10, 10), vec2(30, 30)))
   writeFile("tests/images/masks/drawRect.png", mask.encodePng())
 
 block:
   let mask = newMask(100, 100)
-  mask.drawRoundedRect(rect(vec2(10, 10), vec2(30, 30)), 10)
+  mask.strokeRect(rect(vec2(10, 10), vec2(30, 30)), 10)
+  writeFile("tests/images/masks/strokeRect.png", mask.encodePng())
+
+block:
+  let mask = newMask(100, 100)
+  mask.fillRoundedRect(rect(vec2(10, 10), vec2(30, 30)), 10)
   writeFile("tests/images/masks/drawRoundedRect.png", mask.encodePng())
 
 block:
   let mask = newMask(100, 100)
-  mask.drawSegment(
+  mask.strokeRoundedRect(rect(vec2(10, 10), vec2(30, 30)), 10, 10)
+  writeFile("tests/images/masks/strokeRoundedRect.png", mask.encodePng())
+
+block:
+  let mask = newMask(100, 100)
+  mask.strokeSegment(
     segment(vec2(10, 10), vec2(90, 90)),
     strokeWidth = 10
   )
@@ -123,10 +133,20 @@ block:
 
 block:
   let mask = newMask(100, 100)
-  mask.drawEllipse(vec2(50, 50), 20, 10)
+  mask.fillEllipse(vec2(50, 50), 20, 10)
   writeFile("tests/images/masks/drawEllipse.png", mask.encodePng())
 
 block:
   let mask = newMask(100, 100)
-  mask.drawPolygon(vec2(50, 50), 30, 6)
+  mask.strokeEllipse(vec2(50, 50), 20, 10, 10)
+  writeFile("tests/images/masks/strokeEllipse.png", mask.encodePng())
+
+block:
+  let mask = newMask(100, 100)
+  mask.fillPolygon(vec2(50, 50), 30, 6)
   writeFile("tests/images/masks/drawPolygon.png", mask.encodePng())
+
+block:
+  let mask = newMask(100, 100)
+  mask.strokePolygon(vec2(50, 50), 30, 6, 10)
+  writeFile("tests/images/masks/strokePolygon.png", mask.encodePng())