From 1bc41a433b9e112f1dd11b1afa9b25633b967caa Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Sun, 15 Dec 2024 11:13:06 -0500 Subject: [PATCH] Add visual tests for textToPoints, addTextToContours --- src/type/p5.Font.js | 19 +++- test/unit/visual/cases/typography.js | 87 ++++++++++++++++++ .../000.png | Bin 0 -> 1810 bytes .../metadata.json | 3 + .../000.png | Bin 0 -> 1744 bytes .../metadata.json | 3 + .../Fonts can be converted to points/000.png | Bin 0 -> 1540 bytes .../metadata.json | 3 + .../Sampling density can be changed/000.png | Bin 0 -> 1918 bytes .../metadata.json | 3 + 10 files changed, 115 insertions(+), 3 deletions(-) create mode 100644 test/unit/visual/screenshots/Typography/textToContours/Fonts can be converted to points grouped by contour/000.png create mode 100644 test/unit/visual/screenshots/Typography/textToContours/Fonts can be converted to points grouped by contour/metadata.json create mode 100644 test/unit/visual/screenshots/Typography/textToPaths/Fonts can be converted to drawing context commands/000.png create mode 100644 test/unit/visual/screenshots/Typography/textToPaths/Fonts can be converted to drawing context commands/metadata.json create mode 100644 test/unit/visual/screenshots/Typography/textToPoints/Fonts can be converted to points/000.png create mode 100644 test/unit/visual/screenshots/Typography/textToPoints/Fonts can be converted to points/metadata.json create mode 100644 test/unit/visual/screenshots/Typography/textToPoints/Sampling density can be changed/000.png create mode 100644 test/unit/visual/screenshots/Typography/textToPoints/Sampling density can be changed/metadata.json diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index 9b42b4e763..ab6f23d1f5 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -133,10 +133,23 @@ function font(p5, fn) { ({ width, height, options } = this._parseArgs(width, height, options)); // lineate and get the glyphs for each line - let glyphs = this.textToPaths(str, x, y, width, height, options); + let commands = this.textToPaths(str, x, y, width, height, options); // convert glyphs to points array with {sampleFactor, simplifyThreshold} - return pathToPoints(glyphs, options); + return pathToPoints(commands, options); + } + + textToContours(str, x, y, width, height, options) { + const cmds = this.textToPaths(str, x, y, width, height, options); + const cmdContours = []; + for (const cmd of cmds) { + if (cmd[0] === 'M') { + cmdContours.push([]); + } + cmdContours[cmdContours.length - 1].push(cmd); + } + + return cmdContours.map((commands) => pathToPoints(commands, options)); } static async list(log = false) { // tmp @@ -1122,7 +1135,7 @@ function font(p5, fn) { } let opts = parseOpts(options, { - sampleFactor: 0.05, + sampleFactor: 0.25, simplifyThreshold: 0 }); diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index 93014a4ed6..15e33079e2 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -409,4 +409,91 @@ visualSuite("Typography", function () { screenshot(); }); }); + + visualSuite('textToPoints', function() { + visualTest('Fonts can be converted to points', async function(p5, screenshot) { + p5.createCanvas(100, 100); + const font = await p5.loadFont( + '/unit/assets/Inconsolata-Bold.ttf' + ); + p5.background(255); + p5.strokeWeight(2); + p5.textAlign(p5.LEFT, p5.TOP); + p5.textSize(50); + const pts = font.textToPoints('p5*js', 0, 0); + p5.beginShape(p5.POINTS); + for (const { x, y } of pts) p5.vertex(x, y); + p5.endShape(); + screenshot(); + }); + + visualTest('Sampling density can be changed', async function(p5, screenshot) { + p5.createCanvas(100, 100); + const font = await p5.loadFont( + '/unit/assets/Inconsolata-Bold.ttf' + ); + p5.background(255); + p5.strokeWeight(2); + p5.textAlign(p5.LEFT, p5.TOP); + p5.textSize(50); + const pts = font.textToPoints('p5*js', 0, 0, { sampleFactor: 0.5 }); + p5.beginShape(p5.POINTS); + for (const { x, y } of pts) p5.vertex(x, y); + p5.endShape(); + screenshot(); + }); + }); + + visualSuite('textToContours', function() { + visualTest('Fonts can be converted to points grouped by contour', async function(p5, screenshot) { + p5.createCanvas(100, 100); + const font = await p5.loadFont( + '/unit/assets/Inconsolata-Bold.ttf' + ); + p5.background(200); + p5.strokeWeight(2); + p5.textAlign(p5.LEFT, p5.TOP); + p5.textSize(50); + const contours = font.textToContours('p5*js', 0, 0, { samplingDensity: 0.5 }) + p5.beginShape(); + for (const pts of contours) { + p5.beginContour(); + for (const { x, y } of pts) p5.vertex(x, y); + p5.endContour(p5.CLOSE); + } + p5.endShape(); + screenshot(); + }); + }); + + visualSuite('textToPaths', function() { + visualTest('Fonts can be converted to drawing context commands', async function(p5, screenshot) { + p5.createCanvas(100, 100); + const font = await p5.loadFont( + '/unit/assets/Inconsolata-Bold.ttf' + ); + p5.background(200); + p5.strokeWeight(2); + p5.textAlign(p5.LEFT, p5.TOP); + p5.textSize(50); + const cmds = font.textToPaths('p5*js', 0, 0) + p5.drawingContext.beginPath(); + for (const [type, ...args] of cmds) { + if (type === 'M') { + p5.drawingContext.moveTo(...args); + } else if (type === 'L') { + p5.drawingContext.lineTo(...args); + } else if (type === 'C') { + p5.drawingContext.bezierCurveTo(...args); + } else if (type === 'Q') { + p5.drawingContext.quadraticCurveTo(...args); + } else if (type === 'Z') { + p5.drawingContext.closePath(); + } + } + p5.drawingContext.fill(); + p5.drawingContext.stroke(); + screenshot(); + }); + }); }); diff --git a/test/unit/visual/screenshots/Typography/textToContours/Fonts can be converted to points grouped by contour/000.png b/test/unit/visual/screenshots/Typography/textToContours/Fonts can be converted to points grouped by contour/000.png new file mode 100644 index 0000000000000000000000000000000000000000..ab15a8ffbf52070d1dcdb5cac2bed18d6083bf16 GIT binary patch literal 1810 zcmd6o{UZ~I1ICBi&5-523v1(M-tuyhIxn@D$@?NSvSYZe$#CAbL$PMIVj=s=k=L&r zbKYu(c?-=;oR@Lw(2x!hhE?9q_rLi5@I0T-PtUJUx`&&i0{B}n002;M!q{VvNcdks zz@sM3J@z_+R5aER1*jR)Tmk@qgHHCBz2a}K;#}PbHu4|alni4#0(>K7-zil$$jF2sw50wsBqFMx6lqx|TiN5NjD3)a zI5JwtAz@e|k%$%-5t8`dF}0Xza}LW zwllE{!6&0VQTDy@pD9)Yb_!@iMtD>SpMg@kYl{FyKx84VHYKc$^_oZe?5)=w; zf0;h5sHhkgLf`+&L&AcPpgbw$lW~_o%8TRrB)=fZ6rbruwVhav=SQ zYYd3J_7s;PlC~^48L>TgSPH?mn*jVeUlw*sWv5u%_ll#kn8>ZLqqwUji! zMhrT5{|YE9YcBx!D0y~zdOt(2%71tNryz=Q$qHJ2=mDw>nqy^smuCbIH-}l9YN7qK zF{}o8-O9tCI*3Sy{6w^$wDiE!%jx5KMgMpY#ON>~Lr+Aq@p~gQJBFH#(!DWLvn|kN z4FiH8wHtUiks68_+1A>U!ozu)fVrsS>S8MhiwF1o!OTZCNItI>1D zQ{}!g!9qX70Ucc|aQxzCCxEWnAqTcFRWu5h0d1&V3cWV@zF0`@K$_)Bg(g>hqs6JF zLz)~o*3Okv+5!Jvr*C|v;ecN}Rq8lUo&qQ*i!QfC^>sVl+^ z(1@JNF=Q1{+2Ns12#zvnfGT14Xei=ML~~%|ADEddjkugxHPL1ZmwfVInJ|HU7@KDG z8i!TDr&#LgW}kC_HOx4o)2@*%qHx2;q01i4@^?7P&rh`oKX^mnw9;k9D06R-gU(!k zKrRpbv~Yq!m3v$IOTz_Np7*>|uBQ*8KFiV>0i3HFX{eIU(+n4#Pl$NkR#!E^=(3f+ zBlY4t*o18lfV@jr1&S$x2*^2t(%X;l8_g_Q`j0>_lhOXx`~v@+X&f~^Y>MQnX|;Z! z^4PN8@)HWv>rTOkJJHqq61eAE6R)Id35B@}(3a+E3o1bZb-}9y4Xwd)e}1E7_UH9u zxpg+BIesnW!?n2`tlj zOe_9ME^n*o#xGINMx{?Y%zTFIt4d;GZmXlZF=xFyo}XdYf@5@Qs|Bx?p$khGP*KPx zFtPRGMfV?tp;@n)Jfl;-X$;d|c(6(aIUku_qqnRIa%8_Y$1hnTb8m2E*;`!aoF3Yl z23082QGLH;;b$-KBiqQGdk37~iHJjA@Vkjm;cN9J$|xJDj1B%{wMXXC4uPuunoD;S zHeHhQmAk@VHy^8%iPrU^U!^;3T>VI%n?%z-)R%NeYwVcAS|bE;_Lyd3;dW>9a#chV zy(L9%-s}ZEDfD{6cnhNNmGUpAC@zFfgfLuUie>Y3yQ^j&Hj7Rhd*=M3)OBj( z`tyQ59-DaQ{>qH-M&8{vg2w*pKp@o@L{Q>q308?Y2%yjH5Z?t?=S@8}ixGJ^q~RX- zw68ccvQ_Z3(RFwaeDfViJz*?suToYY9jiP_Rk>31p9>roqD(`&XYkhjbFdx=GStnm zOje(E$t?N?%oSsHjFC46zJ+4IJO+Qej#0+S-wRr7L_J{zfmFV)Q2l?H_+aM}dG`%H Sb->{0rj_p|rF#pTYa^$t z>2v2x$+Zooq@zP&;f@ITE)-(*alZCQ?&JQ8&kwKH^Ox7-_2cW6>+j1#7+D!XAP@xG zo59&;)IS1tY`b{s$G~mq#dBD6h~`h5c?e{Ol+Ex6OcCfpJ$xPZ8y9~>?}=*)JGca! zG%enMiK2!92*-eEh2$bD%H^lRh2oLSE}#ac@!AXzH727K@(&74BWm* zNiGE|?^JVPsO+nW(x))OBL=1v*}aA@AJh*T-PwMXg@RSrR1CkYs;av7=KT533qolg z1)e(~m$1xA`}}C_SXj%2{52jJUM9=wnUEtdrK&0AF;{((s^HvHfi?n%s0RSb`G>sd z9q@ z5s;UYGo(bumfC^2HNcXTl-D;LqC#4ta1(G1ADk=3L@@pyzfl+h-N&i+KjTC@K*wvZ zn5!DiyJbG+IGeB3)ru<5=dKUVRd*$R-#_)p5_iW%?biIR@1j|^K9xR0`4>9haP=}%7@LGvAb#7& zn(VPjjsJjcSq&n+t)elqQ5T;H4E#JVM`Ya(T2}QZ$Y!vF>Rt3ne<%~^O5E&2e?M3oh(@`f&FlBR+_m58np>?@L?)BrgrAP>`6`&4Y%*YWrRe)uPL8E{ z|4ubqjd&q+ytnf{ho=+j9Q@Va*lG{j(TS)byp*ve$T@QR00&HybbU!rJC^`aWiFS; zjdhm*vZ4!()!LG_5pl@O9QMY8kMbmAmDrt+qk$=j%)*ICJsUSiF$-3A@wJ9{W)AqK zI?*TiJDsEwIGvwsA8NAiKNay7%^g8r0TGJ?wDfGsGpVdihW=t}3lFB$++*?Y94jsD z9!@R|c8qknZo`RCYHGw{lB{qZtmQn>nx?_#mmWO;#X|j#p2S>c;j0rDmL zzmZlxJ2c*!T6vDBzrs0p*JXX&2tyIFf3I9eUTSo3tF+$zY~k8zWy7av(O-SLdQB^6 z)p+_Ng{4QBQdaMHiSE>^2u<+*=Ln#JdswUSK}Th7d8@B!k^;}*X9sPat4e) zO7=W)kcWK#Fk9^0-a+Mwki;j;Q!k#$T$C6ihI;yxUzsz0<^B2J_A)vx#-V-|)3t6Y zajPuumeK|LcG5ml;}Kl17FT4(iF!k+w|yk9VL@=~iFxw!hG0k2U077{Kx$4R2cz>_ zZ2pN1#h4r@J9RHaTOhvVYNV$(89`szY?1Xp_Fop%%urNIv=+%zE#-p}drz^&ot)3g zy;c@E5)TTq9s?@wkRPdA^b0qU15v>%dGo`wS%`Eg06VspK;Vm_=n>flE6YlQ6- z{X1OrWZdn3k1WK! zU0}e>(hV1JEO3iI#w7pOqc@M~`Z|ShM#mmAmhd8D5<_qaqR*t`+Hu(*ho1OOe0*gg z*)td;_&n3kU}}Ha8Qkdn;g9oG;Y9?Q!edfBLJ2(G&FYZPdI?F?lSUZ3qw7-}{S`5m zz6xGDg6R#GFEy_Ag5%ZD+w1K1+&XyLU8meq;2ki~=Us#>Gu(5eceF2|9AIBQ;u3!p$MkkF zD7YSAM4%Vo6kWv}Z&ZPCX4Kn4x>OMbIJj1r{XbO9S}!L&9I}3xSi5~u5H{17p`nLg F`X7r65e)zU literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textToPaths/Fonts can be converted to drawing context commands/metadata.json b/test/unit/visual/screenshots/Typography/textToPaths/Fonts can be converted to drawing context commands/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/Typography/textToPaths/Fonts can be converted to drawing context commands/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textToPoints/Fonts can be converted to points/000.png b/test/unit/visual/screenshots/Typography/textToPoints/Fonts can be converted to points/000.png new file mode 100644 index 0000000000000000000000000000000000000000..72c80c74638f2c8b8d2a93ad0f0fe8fd6fe7e8bc GIT binary patch literal 1540 zcmd^<>pK$)0LGV;$z@|YZYy?iTdPxU4ci<`w#k$o(%dU-56(%Zv?RBkGppP$4Vh_) z5Sdcsl8S~h$!&>La?Rz5$)Vde*xUS z*^wV}JvX(5NhJ~h)jiM|0AO1S+1bhSLcqN57I*Xk;3zKtqNOZ&wsVz3*)J}`GU&qw z(&xO)`u&R!Ks;K_!;$&(GZI^%Utz{yj~=P?vA?tvAtHSv3JD@IR4QzLV>b~@7<>PI zaW|jO-zSksdVL{EFdxGuxtz6`2Ju4DhAo_KNQlmm&e;ry(IHOJ@yFHHz=UbN*5+n^ zJRZN`a9D-cT>X#LWGdjNLebdN(z0l?qb8ifKUI(1DaN;tWMswgD#G zZ2Pf#R_NyxOf#GEj+y0aF1jGwUHjaSky-SH!CL$Td+BU_R>9!dYn%6CMj4FS<~{kj|IcJOPXW+yCpO6#g||JnsMiyfZi!tTXbG^1Oi<3+mT za`OP4Y_xV&Q^i#va`79gy9+j`ab%vT7Hig1X$fz{3D<$cub<(qB@XSG6l*LDVcc|j z2A9nR7-n{6o`-<*a(c-E(2-GBXbi=B;PdQ720lWaerErlV6id6E=4Rzmt_&p2qHcX zv_IG1`QfCUvI$kScRHAsFjq@86(!8-v0A?E@KO|0`Vm}58_osx300;Ja*Mko_C=Tu zt6JsQEwB^0NUZ=7;@**ldgiIg6?4kC<}jDQ??w-_j(>;EJ9aHhX6z&!v&(NzB!P7N zmtUr8b5GiHBJHlB@;p8|qF_CLt5=Q;r55+ENvW5elT03pi4~wuOxl;6mwMseLS?KH z`|+Ab9go{>80%^z(tej|`DrImp=|Ua=C<6g?aEZ6U9btrImA>c;5TSx{%QGVZ*^_# zo`0oy6rn3xv!vZ)_r2(XWP`-LrN};2dRy(ORom-+fgMmOnk4F4&(JT*VS+yhDO$Kh zbBS2iV5T33K#JBs^YkOeg%Ih)^b4tQu`JZ2!`_3D%Gfq-Q)CddDi>ciaZcGc(7OO7 zUo*qejHIKDZ`MkomW^7sYOF#k_*P#NFD)u(3H)im4#KIA0sp(t@rT`rQ{Ty4_)b~ z=m=q&T~V6^-+vNVm!88eB(IorTMuskIb)@;U#Zaw^5O&x%;21sc1Mbeqc!Do>>F`E ziw>D;^;|MEUCua5A|2sLa)y#;TEg-(gnKxhl(q2NC3qAQ;U5yx8`a@rbPXOu0TRlG z$Jjbs)85&@fF-A5Ayjot)DYX4ePy0PIxsHwha`bf^#@_?35fs6cmuQsT>gFeC1qpt P)&b2OUEm6XDou+FXVvk6bD$ zm(7m3KJG=C?TI-xQpdGsE{h>Vx5x8uJnz@*^LhXF`So+_mve6Fs(Pv*5J=s_9q`#R z;eUaE_nI`v^4*g{qK_L6)G&N#5d>1U^8lQD$@mW;YUfZGXzY1#8PrafWLc4O;<9|> z$kg+z1)(b1tqn#0`P3`i+}OjC`_h9qZ11>lur> z48)TqpL^kyL_x6p0J&9yP1Y|546_7CwFr|VT(esIn#hBROdk5zr?swk4OIS|Oi;Ff z^60@q?v$67)YvW{mw$wNKFw`iF^E7b=AHh5I#U|R_1h$zOwRa*s7;;4+0Ye@y=UX% z9r6lL`ppN{^MFdu6%ND7$n;n1fhCxXvwap)i0q5JQ~W2$7bCYzXwcS$X7PTNZv z7bjEH|E5b9uwpYz!dSC_=a@Cl4%E~rwvMTA$s%LG4ep{*B9dZP-d^z0g)3$*uImEf zlSkXg*Ify~>&nO5C_*D`fkH_N0zxud&&j?kYi6XLy)?HP? zOk|*QoW`CI@rtR<*xbWC4hh)-yNzO!NAwU8gVocw*eQ+uo%i56y-cQcbH9kW4C67E zk!gH2;IbU?Q|1bq%`2Fe!TE>>kQ4x&s~M3C2F6sAP>mC(jA;n4!Me9$;p!avWGGMt ztp~=ZSes|x)W@yE%G(d313BP9&)e&hd}ljNKwN5T^T+QpHz?71JJ3+2im?&~OwF<; zAh|2ewgPy;jlMZ_%%drs9B5x|1e4smNRZ@Rwy-%l(_QwSU?+yXPo5wU*`4vKjU)vvd8 zY$2sU7N*sO;}n_jekW_Y(e=V&8$L00G#Pw86Jx^#n$R=$}GZ6rzlm^X(F zR|h0-`LBG`dk1~Vqm`+Yq{{Y3WHSyKij8H#ZCO=o>cf_XJ_KuCS`80;e_c15L9bk6 zn!tlJoRuHo= z>Mz{-{w+e;gW-1gLgYj%g|2d5wtOa9q7cv7G5`LLua7VGPuSZEyu3Eq&hFZcQ9JNz z-I=;wcr`t+=?m;HD9P_D%*TZtln(g~++LRssWllxJ5Wz3hWa^BeYIkWjc}z34RuDi zx@>EqCj12`K&%P(8z_~~m{FPaOEjk0r5EeY?pA$%oBt2<8EjrzC_Ujf&%HwhdAOVd J8gSuR{{?H