Based on reinder's utility, with a few enhancements:
* differentiated horizontal and vertical scaling
* lowered position for some punctuation signs
* alignement option: left|middle|right
Log in to post a comment.
const turtle = new Turtle() // Text utility function, based on https://turtletoy.net/turtle/1713ddbe99 const print = (() => { const raw = 'br>eoj^jl<jqirjskrjq>brf^fe<n^ne>`ukZdz<qZjz<dgrg<cmqm>`thZhw<lZlw<qao_l^h^e_caccdeefg'+ 'gmiojpkqmqporlshsercp>^vs^as<f^h`hbgdeeceacaab_d^f^h_k`n`q_s^<olmmlolqnspsrrspsnqlol>]wtgtfsereqfph'+ 'nmlpjrhsdsbraq`o`makbjifjekckaj_h^f_eaecffhimporqssstrtq>eoj`i_j^k_kajcid>cqnZl\\j_hcghglhqjulxnz>c'+ 'qfZh\\j_lcmhmllqjuhxfz>brjdjp<egom<ogem>]wjajs<ajsj>fnkrjsirjqkrktiv>]wajsj>fnjqirjskrjq>_usZaz>`ti'+ '^f_dbcgcjdofrisksnrpoqjqgpbn_k^i^>`tfbhak^ks>`tdcdbe`f_h^l^n_o`pbpdofmicsqs>`te^p^jfmfogphqkqmppnrk'+ 'shserdqco>`tm^clrl<m^ms>`to^e^dgefhekenfphqkqmppnrkshserdqco>`tpao_l^j^g_ebdgdlepgrjsksnrppqmqlping'+ 'kfjfggeidl>`tq^gs<c^q^>`th^e_dadceegfkgnhpjqlqopqorlshserdqcocldjfhigmfoepcpao_l^h^>`tpeohmjjkikfjd'+ 'hcecddaf_i^j^m_oapepjoomrjshserdp>fnjjikjlkkjj<jqirjskrjq>fnjjikjlkkjj<krjsirjqkrktiv>^vrabjrs>]wag'+ 'sg<amsm>^vbarjbs>asdcdbe`f_h^l^n_o`pbpdofngjijl<jqirjskrjq>]xofndlcicgdfeehekfmhnknmmnk<icgefhfkgmh'+ 'n<ocnknmpnrntluiugtdsbq`o_l^i^f_d`bbad`g`jambodqfrislsorqqrp<pcokompn>asj^bs<j^rs<elol>_tc^cs<c^l^o'+ '_p`qbqdpfoglh<chlhoipjqlqopqorlscs>`urcqao_m^i^g_eadccfckdnepgrismsorqprn>_tc^cs<c^j^m_oapcqfqkpnop'+ 'mrjscs>`sd^ds<d^q^<dhlh<dsqs>`rd^ds<d^q^<dhlh>`urcqao_m^i^g_eadccfckdnepgrismsorqprnrk<mkrk>_uc^cs<'+ 'q^qs<chqh>fnj^js>brn^nnmqlrjshsfreqdndl>_tc^cs<q^cl<hgqs>`qd^ds<dsps>^vb^bs<b^js<r^js<r^rs>_uc^cs<c'+ '^qs<q^qs>_uh^f_daccbfbkcndpfrhslsnrppqnrkrfqcpan_l^h^>_tc^cs<c^l^o_p`qbqepgohlici>_uh^f_daccbfbkcnd'+ 'pfrhslsnrppqnrkrfqcpan_l^h^<koqu>_tc^cs<c^l^o_p`qbqdpfoglhch<jhqs>`tqao_l^h^e_caccdeefggmiojpkqmqpo'+ 'rlshsercp>brj^js<c^q^>_uc^cmdpfrisksnrppqmq^>asb^js<r^js>^v`^es<j^es<j^os<t^os>`tc^qs<q^cs>asb^jhjs'+ '<r^jh>`tq^cs<c^q^<csqs>cqgZgz<hZhz<gZnZ<gznz>cqc^qv>cqlZlz<mZmz<fZmZ<fzmz>brj\\bj<j\\rj>asazsz>fnkc'+ 'ieigjhkgjfig>atpeps<phnfleiegfehdkdmepgrislsnrpp>`sd^ds<dhffhekemfohpkpmopmrkshsfrdp>asphnfleiegfeh'+ 'dkdmepgrislsnrpp>atp^ps<phnfleiegfehdkdmepgrislsnrpp>asdkpkpiognfleiegfehdkdmepgrislsnrpp>eqo^m^k_j'+ 'bjs<gene>atpepuoxnylzizgy<phnfleiegfehdkdmepgrislsnrpp>ate^es<eihfjemeofpips>fni^j_k^j]i^<jejs>eoj^'+ 'k_l^k]j^<kekvjyhzfz>are^es<oeeo<ikps>fnj^js>[y_e_s<_ibfdegeifjijs<jimfoeretfuius>ateees<eihfjemeofp'+ 'ips>atiegfehdkdmepgrislsnrppqmqkphnfleie>`sdedz<dhffhekemfohpkpmopmrkshsfrdp>atpepz<phnfleiegfehdkd'+ 'mepgrislsnrpp>cpgegs<gkhhjfleoe>bsphofleieffehfjhkmlompopporlsisfrep>eqj^jokrmsos<gene>ateeeofrhsks'+ 'mrpo<peps>brdejs<pejs>_ubefs<jefs<jens<rens>bseeps<pees>brdejs<pejshwfydzcz>bspees<eepe<esps>cqlZj['+ 'i\\h^h`ibjckekgii<j[i]i_jakbldlfkhgjkllnlpkrjsiuiwjy<ikkmkojqirhthvixjylz>fnjZjz>cqhZj[k\\l^l`kbjci'+ 'eigki<j[k]k_jaibhdhfihmjilhnhpirjskukwjy<kkimiojqkrltlvkxjyhz>^vamakbhdgfghhlknlplrksi<akbidhfhhill'+ 'nmpmrlsisg>brb^bscsc^d^dsese^f^fsgsg^h^hsisi^j^jsksk^l^lsmsm^n^nsoso^p^psqsq^r^rs' const decode = (char) => char.charCodeAt(0)-106 const decodePos = ([x, y]) => [decode(x), decode(y)] const decodePath = (str) => str.match(/.{2}/g).map(decodePos) const decodePaths = (str) => str ? str.split('<').map(decodePath) : [] const decodeGlyph = ([lt, rt, ...rest], i) => [decode(lt), decode(rt), decodePaths(rest.join(''))] const font = raw.split('>').map(decodeGlyph) const add = ([x1, y1], [x2, y2]) => [x1 + x2, y1 + y2] const rot = ([x, y], [cos, sin]) => [x*cos - y*sin, y*cos + x*sin] //console.log(font.map((g, i) => [String.fromCharCode(i+32), ...g])) return (t, str, options = {}) => { const defaults = { scale: [1, 1], italic: 0, kerning: 1, align: 'left' } const { scale, italic, kerning, align } = Object.assign(defaults, options) const [sx, sy] = scale ? isNaN(scale) ? scale : [scale, scale] : [1, 1] const strWidth = (str) => [...str].reduce((w, char) => { const code = char.charCodeAt(0)-32 const [lt, rt] = font[code] || [0, 0] return w+(rt-lt) }, 0) const width = Math.max(...str.split('\n').map(strWidth))*sx*kerning let pos = [t.x(), t.y()], o = pos const h = t.h(), [ch, sh] = [Math.cos(h), Math.sin(h)] const printPaths = (paths) => { const pos = [t.x(), t.y()] paths.forEach((path) => { path.forEach(([x, y], i) => { const abs = add(pos, rot([(x-y*italic)*sx, y*sy], [ch, sh])) i == 0 ? t.jump(abs) : t.goto(abs) }) }) } const start = [t.x(), t.y()] str.split('\n').map((line) => { const start = [t.x(), t.y()] const lineWidth = strWidth(line)*sx*kerning const dx = ({ left: 0, middle: lineWidth/2, right: lineWidth })[align] t.up(); t.backward(dx) line.split('').forEach((char) => { const start = [t.x(), t.y()] const code = char.charCodeAt(0)-32 const [lt, rt, paths] = font[code] || [0, 0, []] t.up(); t.backward(lt*sx) t.down(); printPaths(paths) t.up(); t.jump(start); t.forward((rt-lt)*sx*kerning) }) t.jump(start) t.up(); t.right(90); t.forward(38*sy); t.left(90); }) t.jump(start) } })() const fit = .2 const round = (number, n) => { const d = Math.pow(10, n); return Math.round((number + Number.EPSILON) * d) / d; } const roundScale = (scale, n) => { return Array.isArray(scale) ? `[${round(scale[0], n)}, ${round(scale[1], n)}]` : round(scale, n) } const printWithOptions = (options = {}) => { const defaults = { scale: [1, 1], italic: 0, kerning: 1, align: 'left' } const { scale, italic, kerning, align } = Object.assign(defaults, options) const optStr = `scale: ${roundScale(scale, 2)}, italic: ${italic}, kerning: ${kerning}, align: ${align}` const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\n0123456789 &"\'(-_)=+^$%*,?;.:/!~#{[|^@]}<>' print(turtle, `${optStr}\n${str}`, options) } function walk(i) { turtle.jump(0, -90); printWithOptions({ scale: fit, italic: .2, align: 'middle' }) turtle.jump(0, -60); printWithOptions({ scale: fit, kerning: .95, align: 'middle' }) turtle.jump(0, -30); printWithOptions({ scale: [fit*.9, fit], kerning: .95, align: 'middle' }) turtle.jump(0, 0); printWithOptions({ scale: [fit*.8, fit], kerning: .95, align: 'middle' }) turtle.jump(0, 30); printWithOptions({ scale: [fit*.7, fit], kerning: .95, align: 'middle' }) turtle.jump(0, 55); printWithOptions({ scale: [fit*.6, fit*.6], kerning: .95, align: 'left' }) turtle.jump(0, 85); printWithOptions({ scale: [fit*.6, fit*.6], kerning: .95, align: 'right' }) turtle.jump(0, 70); turtle.radians(); turtle.setheading(Math.PI/10) printWithOptions({ scale: fit*.6, kerning: .95, align: 'middle' }) }