From 42bedda0a74209cb0a4e834b3b1ad42e0f8d2de8 Mon Sep 17 00:00:00 2001 From: treeform <starplant@gmail.com> Date: Fri, 18 Mar 2022 19:24:56 -0700 Subject: [PATCH] Fix #372 - Add negative spread. --- src/pixie/masks.nim | 11 +++++++++-- tests/masks/drawPolygon.png | Bin 853 -> 737 bytes tests/masks/negativeSpread.png | Bin 0 -> 180 bytes tests/masks/strokePolygon.png | Bin 1400 -> 1273 bytes tests/test_masks.nim | 11 +++++++++++ 5 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 tests/masks/negativeSpread.png diff --git a/src/pixie/masks.nim b/src/pixie/masks.nim index ea7b718..465dd86 100644 --- a/src/pixie/masks.nim +++ b/src/pixie/masks.nim @@ -234,14 +234,21 @@ proc getValueSmooth*(mask: Mask, x, y: float32): uint8 {.raises: [].} = else: topMix +proc invert(mask: Mask) {.raises: [].} = + ## Makes inverts all values - creates a negative of the mask. + for i in 0 ..< mask.data.len: + mask.data[i] = 255 - mask.data[i] + proc spread*(mask: Mask, spread: float32) {.raises: [PixieError].} = ## Grows the mask by spread. let spread = round(spread).int if spread == 0: return if spread < 0: - raise newException(PixieError, "Cannot apply negative spread") - + mask.invert() + spread(mask, -spread.float32) + mask.invert() + return # Spread in the X direction. Store with dimensions swapped for reading later. let spreadX = newMask(mask.height, mask.width) for y in 0 ..< mask.height: diff --git a/tests/masks/drawPolygon.png b/tests/masks/drawPolygon.png index abd187e6caf02634e38bf9f260ef5d7adab20646..c16c400c321c54864ad69538edd9ebfd4b4e45d3 100644 GIT binary patch delta 714 zcmV;*0yX{B2H^#eBYy&@Nkl<ZcmeI0Ur19?9LIlok%`eLLmD9n3oJ6CWhw@vhYBK) zT_i*c79nd<P(9Q`f%FhW5BX3pxlx!Ai~b;6L{Lyc5H3?QBpGNzqYzet(jsL{W8BTP zyYoBu{Co(B-{<L^d+#})d%hPg{C*nz16V?W<08Rvk>I#UaDQARI4%+^Gp?H6!-LbL za{%=u_A9+xYEG<;&XY8xxK{a|?9~9YCg02liiIL^hkfP7-sR1nvA8i*L0wWEyynR7 z=s33Z{cL_JM^&=AGqj^{r&_;lAXRt?Ls4=h++1qjqI8cpF>1ajL`hQDciJvmZEra+ zG9|iULP6rVaeuSQv}%c}<JIqyOEU~hiS68@Mr?5gmw#a}of$~5lIW3En`Aiv*!H!@ zW0?VtT(T{6p#oo<qoU0{oXAZ?$Rz8!Zfz2+DaPsF&_7pvIR`G$PDR`$xyP(1srUaH zTEw10CHo^s%dkZv$_^eHpA_AY{e@$H{X^8KY`cs+h<~1>6TO47z!C}^7YUAw1jj{! z<08Rvk>I#Ua9kufE)pv=u4r8)=@<ZGUUKO$8Th`NQlQM7@0h^e3NH{A2ZC#Ms+L;m zZqFOE(2__1=AQL!c4BW=z)Ss(q-2yz01|gU)?1gqpF1u}i(d-~KrE1Klo#?pFL^%| z9IF`on}1|UzwKG?%8o_!=+CVh64nxcWaQ~~tho}^yRBO*DiVOH+Y=3<HqqCUXH=R* zY7&6aV7kHF@cMnVeMl5wF_zyXOX~H#jkVda!9zW)*tk=c0L(sq<;ph@Mq0a+TaW|^ zKs@-Z$!MqkIP3pnoJR@OxD18^wp|*euDA3Xb3;XF5}1GSz&Y-@Pit^fB>>Z*5VciL wmn;WjT+4$cBseY-92W_Wiv-6-;{S>34~sR%jC|_ZMgRZ+07*qoM6N<$f_8LH3;+NC delta 831 zcmV-F1Hk;@1=R+SBYy)NNkl<ZcmeI0Ur5tY6vwZcnh6aSj3ku6j7XstIz|P(WDkK> zGsGk#S{nLf5Iq!8Jp>UH5mESuFta~cwDnR{MD&m~1FcLDTtXT`3r2=1vYhdAu-|rn z=bU@*7QJ*oFS>KS=l8wm?8kn;d$ZU-K$|F`$EAcGmlAqhN`L5aDWS)ugdUd?|JArE zKcAuK8xxLBJgy}^2YD4|N0iJnCSlTY(9q#HzW3wF7{X5M5A$M56nEz=nu{Scxv(uJ z#L3Hlf+rUdnUr;AF6t;Y`9f4${GIfa(DeqHCAW+}ID$@gpTJ8^ia(5)9{^~R9KRi? zu~ObPZw;EzCV$6jO(li>*J~<Gnyl>2rD_v!bxkLH;vr40xOq87?utiPN^p0TU(GNi zQfzoUiR-9N?ib;8JQ-y-_>c)<Qr~LI#1xJWp(5O5ncs$1LAcr?P}l%BIaOuk<*`Ly zVq(;!=yo<%gHX{kg=A2Z_KipdO7^M;NDedEdJ!ogD1Uu14rdXQOkV-4CvkQxfO*8k z+XSiw6nq^36|l*2e?F)d;clOUB(TZ3N=PdvKj#@F0!`L*gJB6O?uG#sc(v|zfKrOA z;yZv2G^t+;DCHQHHtBB$y(NfLNslXR+bnTGh|Bk&D7@si-qdd4&|ZaGc<x6vv?3v` zZ$Js$34eQEoyyP3V6)QC%EIs=a7{F|U*J5_2^(Ku3KtOcUP6+X3F|+i`p}x$rToyE zS}NQ#aGdvZfjDR<EO0>WMPi~Zg%^p)x0?7;WN3k(B?fpWY-mTJp^&8SC@v&S*vG^2 zuc^_R6kk&(S3B|5adchh0*O$aut1aS*5T)#lz+Dl(+k@Z7esLSDUqZ*Vej_IZRdgw zX>8}_C+esb#_<lv|AipG6UIii6hl=U&rfmz4uJ_9Y!V+9{Pv`ISP*i!xMf+ncGDV5 zLevQhG>Q&z!k)AbaAs$ACaucK@mJPZGQv*SfQLR*`_%Xs4%MQ;hU9f|><@AQE8<Sr z*f?1d@e!nqN%}~1l0Mo*2|X?)^thDJ<5EJ8O9?$LCG@zI_yb?yt$<oF6wCks002ov JPDHLkV1l;|f7bv2 diff --git a/tests/masks/negativeSpread.png b/tests/masks/negativeSpread.png new file mode 100644 index 0000000000000000000000000000000000000000..0dcc9f36b354a808cc52af568fca2cd7e18f746c GIT binary patch literal 180 zcmeAS@N?(olHy`uVBq!ia0vp^DIm-NBp5<FPjvvPYEKu(kP61P7Zmvp8wj`_^x9cb z^GW3DvN}e!xd&JOy|mkoUBdH;7cThE^m_6Co=dBr?s}fBEdAtG$CeXYqjDrJANzR8 jEzW4tiK)1t%*n5;O-iB;QjsZzAm@0x`njxgN@xNANZU~@ literal 0 HcmV?d00001 diff --git a/tests/masks/strokePolygon.png b/tests/masks/strokePolygon.png index c6475856183e447759a5f80954848c634b1747d8..3ba071255d77bcbbd23487eb73ad8d58e15ea1e2 100644 GIT binary patch delta 1254 zcmV<C1R4AI3i%0;BYy<INkl<ZcmeI1drTZf9LIlqg&v?FFH=%T+7iS{m6mc>N)555 zCK9o7&;<HGq#?%<ZM8<@t7)-njBPZ&FnZTEgo>!GZT4z4)kLgmDusgrRxN2!DyfhX z+JIbo^13s#4|aCg*PKaX%zpl0e=|EX-<==3bMyPnJh%y%B7anv?xMnU7Zs+vsQ7QX zE9$ud-!#=cfO;kyyc^bSxpIL{h0a~spFNYnKz#YyuB$XMG$M&_dzM&&764|kYvGRp z<1)rYBDS;lG5}17L4R$vfzF^&8N(ul-ijzRC=+7P1)>Vee(U2beGH0ZHttCl2IDmV zAi2WcaSa)|7=IFpd%ba~(ny)L@n<KLZV(s{VVuX;sWh9H?;PzSMpQthH%0;LjKPWo zG3$$e9U$uFpeM4(^JdDNPBK!qX8FcsHFMAwxn)=L3bKoTaz0VD%w=t#BI;ylifm!m zN6K0Qz#&Kd?aPsY5qV$b@Oi9Eq9Kxd?8!K?xv%7d@qcml>lLZQjkwan?jfR1LRBQ? zy${o*W;}!2whba{aDRVZEHW_CY8JKmu`-T|i1pbcd3ZC#-}}ma=!)p^fIR{k7&)$B z#|&1MP!@4`%dAoxo}-SVle~qPY-vu*LI#HQflULwSa}vDk-M8;Oq^{X@YBY9qk<_g zdiaNx3x5P#BynTGxnZ#&p(HYJhjgFk`qMT2yoGbwGqffeuK<Ab>etXkj*`f3qH_BE zk~1NBH=a<ZJKAR9ZIRHcq9s9$$FWOZd9t`kbrqaAc_br)>m(8kN95vTbtB>cN{oEc zVN1epgdy_ROI3>R3(h6?Xuk9=(u?db{?5Q}Y=5xzKtir4OD|%(A@<eg#+NUP4d_Mo zh+TCtMF329k;qpN9%)%I-!1~vT_onRVlFGl1#-;qgv9(#Zq|2_+G=d$mHf`X*xcpT zPIl;TAtQGjTZ87!LBF{J>x1R}m$=UA6nQsGTj6j-0FpMZ?$p}WFa3D;?4~}*ged}$ zQGc7%surN!wznZunq!b*49{dI5!YH)*Nk;3g<6)H<M-o%mL<f%w83zWy)#{UI*#av zOL{MJ7S39>ng|&~p_WpEf$8v}9y=NSE~vW4Cl7y@9N0?+zwmqYP6Z9cRT!Yx?a#yB z7>+DgOuH1w-&)s{%~fNJ*H!+46(y9GdVc_zIn$7ogA9y_f~t`op<Ky6MEv6b8XVs! zCnVHF0Q}w)*<^Ahwxp;VC0Fe16J%-y&N@Ew3r{cym6;%h4)(1g(?qGx^!C{LdNN4_ zR~~;#JxQb`0&w0lvx-c3Eq86Vqes9Ays@bhFOz7@1OTSKZ(6tv85r})#2p-Vuz#9~ zI~@^#u`gP3w3CqCWpC-EAaz9m20VY}tEW>(cDVk)rm2j!yLisItv2O$Q}33x@@+Ix z?o2T8?dR#(IylQ$#h<FJoH7iF09<Qsvx&)ik={pNF_x+~Dgw~wzMjt=I|z)uu=S!~ z>SAyv01#~R#IF>O9D<%lPU-(Hi(eQQ0SKI6?^?`tJmok@aS%i$0&unQXL|zlJD;aI z(xMarxZn=7RA{Blm7sAK$Mosbw8xC}BH=(ilW;Ias4(3{h3PIT{y*;e2bD8=?_(F& Q?*IS*07*qoM6N<$f(oB!761SM delta 1382 zcmV-s1)2K!3HS<-BYy=yNkl<ZcmeI0eN0zX7{{N>>u;GLN*kKGkZ>$?_yRvPt=uwQ zE6JY{6Nxe~$lgZF)heAPtGSxh)Ykand?7I>Ovt6J8nd=aKtzISG;|UMTV(F1As{cm zU%QvzdCtA(o^$TK<oxUR`Gfo1bH300-g|!BbDn#`;WiL5aeqW;xEv80E=Poh%MqdB zaztpj9APzFbGmnIw_;08uiVqh<Z!Y)UnMO0GxZ?G!esSZ;#5k~&+YVtgWM#lb}}c2 zC7`62jk1k;<R+VQ^jZ-LOuq4>s8dC1l5i|q)!4v&uur0rn(SUA$utl><qN~P5t&K) zUd1Sukans^+<z-GshTOyV^QYpXPYPzll3K3X3dO_Hlavtaz||}W_i=!;WKR^YTRYR z7&C}Xwyr{{&(n{wk%s47q#@RSnuIJulbMx~sC~N*Lx%q0mDrMT_!`DWgeKm3C~SY$ zk1<Qrlkub}^6qL9GKfr;?xMmCl9|chxgLe7bzK-65Pz72)l5a%sqGkY=y20{dVYC; zqX3afVG*i_Jy$U1(Oir-I`z+Ho<d*}Q#%3GyDKr|awTptwlDJD#8?O3g@Jb;!PCF9 z2QlW;P>6RlA?h2RhHG+f1#Ny!I*F?cUVmIYXk>hTRXZA?SJP3Ef+sD{^M6Y{Em;ZV zG(71D34e9)Ojhimg4|0q77_S;19r_ma}i^NV-j%!-!G{80F@FtQ&X`wqs;u~a!g*z z$BaRb4`Ufk#Sx@C{+|XCB4(2*H8|(N&f_SQ;&VNS{fqYvU>wA3vg?6h7eIIJ5XN%O zJ`+O(u8Ai}NHCeqEe|7o@M05&77X>SLB#@7L4Rp7IXVl~^$wQCww2RKURcT@5(Z&S zJg;N%5XkNhitNy~5fc+znQ5Cbah-?@Ku}%riJglRx)bRF<SrW_%^Hl!=4?d?__bf9 z&-1UQuuEfc6p_Z=_<@8PjLFjF00GcUhW0u$nfNlAK%La2DQ}WLO!I)K_*(5Y?6Sv= z%707w(%~BE$_WqtB#`!%lONu_hvWei{(^oQ%y2>bvP7*N0F=3sqL4+Yo`FrL-^6eX z)&!c1#zqSOreA1P54L#f6_kyxX20%CCcOz6D9`lTomTFw#c2h~4&ViXm`tF)2q(xG zaZ$*yl`f7xkBtd(VBk@_g8PWQsXnn1r+<2Q<2y_zn4bjB<=~<fF|CRSrFhe@yS>2H zqUG<Pt5)jwotQ3W+55CFuY<+}&Xd5!jM=0c=IygCB*KqlAps{#F_pqIfyPbPoX~TQ ziUkyH#E#)rwo9U`vG-$IX1P^yH>n1TJNWo0ChEXjHc+oC3ZuU^beVbYVQlNoc7IT& z-t=W*VtSRl;7&O}Z?xnLrs<&q11(wj=@34PR}@kX(Q@<rCjNhkz$EZ%0bVA#iSu8H zJhlx($oYfDdIToWbssGX7kJI@7a_6+-&{EMA!%h0nLuMPewfDl_(QEylBfRF=zqfT zhv_xfLt3gz=6=y9_FdIDo5D`vN`ESR5@>iDHw#>`U#ealK3al}m)DJBvtanIwRnMr zqHRdJAptM&zZX@+PXcW#=!$C1Pp^tK5)){pMWH4Bwd351>bYmW<;4jHKP3?d*^@v+ zk=^aV>z;9M5B3F?bMA{Jpa5)>&Z5#MfwQ@Gwrmx+kpDlnY)3DzWAEFH0$)(@o4Hws z{7ImFNs>-1;@d5vo-r&;;5;oTg^a9WOGXAOlipJP=A)ic3lB?^TY}Y-+!8`2jtC8x oBSORFh|q93A~al%xGlr=ADUKO`h0S~wEzGB07*qoM6N<$g1n@r5&!@I diff --git a/tests/test_masks.nim b/tests/test_masks.nim index f0ae841..0b9d105 100644 --- a/tests/test_masks.nim +++ b/tests/test_masks.nim @@ -92,6 +92,17 @@ block: a.writeFile("tests/masks/spread.png") +block: + let path = newPath() + path.rect(40, 40, 20, 20) + + let a = newMask(100, 100) + a.fillPath(path) + + a.spread(-5) + + a.writeFile("tests/masks/negativeSpread.png") + block: let mask = newMask(100, 100)