From 2d6c4b0441ab0180dc7e73e5774e99d85284074f Mon Sep 17 00:00:00 2001 From: Daniel Howe Date: Sun, 15 Dec 2024 18:52:38 -0500 Subject: [PATCH 01/27] minor refactors pre-woff --- src/type/p5.Font.js | 20 ++++++++++---------- src/type/text2d.js | 36 ++++++++++++++---------------------- 2 files changed, 24 insertions(+), 32 deletions(-) diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index 7d8008de87..43f30a6930 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -26,20 +26,12 @@ */ /** - * This module defines the p5.Font class and P5 methods for + * This module defines the p5.Font class and p5 methods for * loading fonts from files and urls, and extracting points from their paths. */ import Typr from './lib/Typr.js'; import { createFromCommands } from '@davepagurek/bezier-path'; -function unquote(name) { - // Unquote name from CSS - if ((name.startsWith('"') || name.startsWith("'")) && name.at(0) === name.at(-1)) { - return name.slice(1, -1).replace(/\/(['"])/g, '$1'); - } - return name; -} - function font(p5, fn) { const pathArgCounts = { M: 2, L: 2, C: 6, Q: 4 }; @@ -662,7 +654,6 @@ function font(p5, fn) { simplifyThreshold: 0 }); - const totalPoints = Math.ceil(path.getTotalLength() * opts.sampleFactor); let points = []; @@ -678,6 +669,15 @@ function font(p5, fn) { return points; } + + function unquote(name) { + // Unquote name from CSS + if ((name.startsWith('"') || name.startsWith("'")) && name.at(0) === name.at(-1)) { + return name.slice(1, -1).replace(/\/(['"])/g, '$1'); + } + return name; + } + }; // Convert arrays to named objects diff --git a/src/type/text2d.js b/src/type/text2d.js index f8636916f5..ecac9955fa 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -29,8 +29,6 @@ import { Renderer } from '../core/p5.Renderer'; * - add 'justify' alignment */ -import { Graphics } from '../core/p5.Graphics'; - /** * @module Type * @submodule text2d @@ -73,7 +71,6 @@ function text2d(p5, fn) { 'textStyle', 'textWidth', 'textWrap', - 'textBounds', 'textToPoints', 'textDirection', @@ -94,7 +91,7 @@ function text2d(p5, fn) { } return this._renderer[func](...args); }; - // TODO: is this necessary? + // do the same for p5.Graphics prototype p5.Graphics.prototype[func] = function (...args) { return this._renderer[func](...args); }; @@ -114,7 +111,6 @@ function text2d(p5, fn) { lineHeight: { default: fn.NORMAL, isShorthand: true }, // line-height: { default: normal | number | length | percentage } fontVariant: { default: fn.NORMAL, isShorthand: true }, // font-variant: { default: normal | small-caps } fontStyle: { default: fn.NORMAL, isShorthand: true }, // font-style: { default: normal | italic | oblique } [was 'textStyle' in v1] - direction: { default: 'inherit' }, // direction: { default: inherit | ltr | rtl } }; @@ -160,7 +156,6 @@ function text2d(p5, fn) { * @returns - a bounding box object for the text block: {x,y,w,h} */ Renderer.prototype.textBounds = function (str, x, y, width, height) { - //console.log('TEXT BOUNDS: ', str, x, y, width, height); // delegate to _textBoundsSingle measure function return this._computeBounds(fn._TEXT_BOUNDS, str, x, y, width, height).bounds; }; @@ -187,8 +182,7 @@ function text2d(p5, fn) { Renderer.prototype.textWidth = function (theText) { let lines = this._processLines(theText, null, null); // return the max width of the lines (using tight bounds) - let widths = lines.map(l => this._textWidthSingle(l)); - return Math.max(...widths); + return Math.max(...lines.map(l => this._textWidthSingle(l))); }; /** @@ -199,12 +193,10 @@ function text2d(p5, fn) { Renderer.prototype.fontWidth = function (theText) { // return the max width of the lines (using loose bounds) let lines = this._processLines(theText, null, null); - let widths = lines.map(l => this._fontWidthSingle(l)); - return Math.max(...widths); + return Math.max(...lines.map(l => this._fontWidthSingle(l))); }; /** - * * @param {*} txt - optional text to measure, if provided will be * used to compute the ascent, otherwise the font's ascent will be used * @returns - the ascent of the text @@ -260,10 +252,6 @@ function text2d(p5, fn) { }; }; - Renderer.prototype._currentTextFont = function() { - return this.states.textFont.font || this.states.textFont.family; - } - /** * Set the font and [size] and [options] for rendering text * @param {p5.Font | string} font - the font to use for rendering text @@ -317,17 +305,17 @@ function text2d(p5, fn) { this.textProperties(options); } - this._applyTextProperties(); - //console.log('ctx.font="' + this.textDrawingContext().font + '"'); - return this._pInst; + return this._applyTextProperties(); } Renderer.prototype._directSetFontString = function (font, debug = 0) { if (debug) console.log('_directSetFontString"' + font + '"'); + let defaults = ShorthandFontProps.reduce((props, p) => { props[p] = RendererTextProps[p].default; return props; }, {}); + let el = this._cachedDiv(defaults); el.style.font = font; let style = getComputedStyle(el); @@ -335,8 +323,10 @@ function text2d(p5, fn) { this.states[prop] = style[prop]; if (debug) console.log(' this.states.' + prop + '="' + style[prop] + '"'); }); + if (debug) console.log(' this.states.textFont="' + style.fontFamily + '"'); if (debug) console.log(' this.states.textSize="' + style.fontSize + '"'); + return { family: style.fontFamily, size: style.fontSize }; } @@ -484,6 +474,9 @@ function text2d(p5, fn) { /////////////////////////////// end API //////////////////////////////// + Renderer.prototype._currentTextFont = function () { + return this.states.textFont.font || this.states.textFont.family; + } /* Compute the bounds for a block of text based on the specified @@ -1112,8 +1105,6 @@ function text2d(p5, fn) { if (!states.fillSet) { this._setFill(DefaultFill); } - - //console.log(`fillText(${x},${y},'${text}') font='${this.textDrawingContext().font}'`); this.textDrawingContext().fillText(text, x, y); } @@ -1143,7 +1134,7 @@ function text2d(p5, fn) { case fn.RIGHT: adjustedX = x + adjustedW; break; - case fn.END: // TODO: add fn.END: + case fn.END: throw new Error('textBounds: END not yet supported for textAlign'); } lineData[i] = { text: lines[i], x: adjustedX, y: y + i * textLeading }; @@ -1186,6 +1177,7 @@ function text2d(p5, fn) { return dataArr; } } + if (p5.RendererGL) { p5.RendererGL.prototype.textDrawingContext = function() { if (!this._textDrawingContext) { @@ -1218,7 +1210,7 @@ function text2d(p5, fn) { case fn.RIGHT: adjustedX = x + adjustedW - widths[i]; break; - case fn.END: // TODO: add fn.END: + case fn.END: throw new Error('textBounds: END not yet supported for textAlign'); } lineData[i] = { text: lines[i], x: adjustedX, y: y + i * textLeading }; From 1aec9a2ad204c7c1475bbaa5f5cec201e9d65fc1 Mon Sep 17 00:00:00 2001 From: dhowe Date: Mon, 23 Dec 2024 15:14:02 -0500 Subject: [PATCH 02/27] add updated typr --- src/type/lib/Typr.U.js | 2396 +++++++++++++++++++--------------------- src/type/lib/Typr.js | 1719 +++++++--------------------- 2 files changed, 1523 insertions(+), 2592 deletions(-) diff --git a/src/type/lib/Typr.U.js b/src/type/lib/Typr.U.js index 93c3c0c320..e0496ed450 100644 --- a/src/type/lib/Typr.U.js +++ b/src/type/lib/Typr.U.js @@ -1,1290 +1,1112 @@ -Typr["U"] = { - "shape": function (font, str, ltr) { - - var getGlyphPosition = function (font, gls, i1, ltr) { - var g1 = gls[i1], g2 = gls[i1 + 1], kern = font["kern"]; - if (kern) { - var ind1 = kern.glyph1.indexOf(g1); - if (ind1 != -1) { - var ind2 = kern.rval[ind1].glyph2.indexOf(g2); - if (ind2 != -1) return [0, 0, kern.rval[ind1].vals[ind2], 0]; - } - } - //console.log("no kern"); - return [0, 0, 0, 0]; - } - - - var gls = []; - for (var i = 0; i < str.length; i++) { - var cc = str.codePointAt(i); if (cc > 0xffff) i++; - gls.push(Typr["U"]["codeToGlyph"](font, cc)); - } - var shape = []; - var x = 0, y = 0; - - for (var i = 0; i < gls.length; i++) { - var padj = getGlyphPosition(font, gls, i, ltr); - var gid = gls[i]; - var ax = font["hmtx"].aWidth[gid] + padj[2]; - shape.push({ "g": gid, "cl": i, "dx": 0, "dy": 0, "ax": ax, "ay": 0 }); - x += ax; - } - return shape; - }, - - "shapeToPath": function (font, shape, clr) { - var tpath = { cmds: [], crds: [] }; - var x = 0, y = 0; - - for (var i = 0; i < shape.length; i++) { - var it = shape[i] - var path = Typr["U"]["glyphToPath"](font, it["g"]), crds = path["crds"]; - for (var j = 0; j < crds.length; j += 2) { - tpath.crds.push(crds[j] + x + it["dx"]); - tpath.crds.push(crds[j + 1] + y + it["dy"]); - } - if (clr) tpath.cmds.push(clr); - for (var j = 0; j < path["cmds"].length; j++) tpath.cmds.push(path["cmds"][j]); - var clen = tpath.cmds.length; - if (clr) if (clen != 0 && tpath.cmds[clen - 1] != "X") tpath.cmds.push("X"); // SVG fonts might contain "X". Then, nothing would stroke non-SVG glyphs. - - x += it["ax"]; y += it["ay"]; - } - return { "cmds": tpath.cmds, "crds": tpath.crds }; - }, - - "codeToGlyph": function () { - - // find the greatest index with a value <=v - function arrSearch(arr, k, v) { - var l = 0, r = ~~(arr.length / k); - while (l + 1 != r) { var mid = l + ((r - l) >>> 1); if (arr[mid * k] <= v) l = mid; else r = mid; } - - //var mi = 0; for(var i=0; i= tab.map.length) gid = 0; - else gid = tab.map[code]; - } - /*else if(fmt==2) { - var data=font["_data"], off = cmap.off+tab.off+6, bin=Typr["B"]; - var shKey = bin.readUshort(data,off + 2*(code>>>8)); - var shInd = off + 256*2 + shKey*8; - - var firstCode = bin.readUshort(data,shInd); - var entryCount= bin.readUshort(data,shInd+2); - var idDelta = bin.readShort (data,shInd+4); - var idRangeOffset = bin.readUshort(data,shInd+6); - - if(firstCode<=code && code<=firstCode+entryCount) { - // not completely correct - gid = bin.readUshort(data, shInd+6+idRangeOffset + (code&255)*2); - } - else gid=0; - //if(code>256) console.log(code,(code>>>8),shKey,firstCode,entryCount,idDelta,idRangeOffset); - - //throw "e"; - //console.log(tab, bin.readUshort(data,off)); - //throw "e"; - }*/ - else if (fmt == 4) { - var ec = tab.endCount; gid = 0; - if (code <= ec[ec.length - 1]) { - // smallest index with code <= value - var sind = arrSearch(ec, 1, code); - if (ec[sind] < code) sind++; - - if (code >= tab.startCount[sind]) { - var gli = 0; - if (tab.idRangeOffset[sind] != 0) gli = tab.glyphIdArray[(code - tab.startCount[sind]) + (tab.idRangeOffset[sind] >> 1) - (tab.idRangeOffset.length - sind)]; - else gli = code + tab.idDelta[sind]; - gid = (gli & 0xFFFF); - } - } - } - else if (fmt == 6) { - var off = code - tab.firstCode, arr = tab.glyphIdArray; - if (off < 0 || off >= arr.length) gid = 0; - else gid = arr[off]; - } - else if (fmt == 12) { - var grp = tab.groups; gid = 0; //console.log(grp); throw "e"; - - if (code <= grp[grp.length - 2]) { - var i = arrSearch(grp, 3, code); - if (grp[i] <= code && code <= grp[i + 1]) { gid = grp[i + 2] + (code - grp[i]); } - } - } - else throw "unknown cmap table format " + tab.format; - - //* - var SVG = font["SVG "], loca = font["loca"]; - // if the font claims to have a Glyph for a character, but the glyph is empty, and the character is not "white", it is a lie! - if (gid != 0 && font["CFF "] == null && (SVG == null || SVG.entries[gid] == null) && loca && loca[gid] == loca[gid + 1] // loca not present in CFF or SVG fonts - && whm[code] == null) gid = 0; - //*/ - - return gid; - } - return ctg; - }(), - - "glyphToPath": function (font, gid, noColor) { - var path = { cmds: [], crds: [] }; - - - var SVG = font["SVG "], CFF = font["CFF "], COLR = font["COLR"], CBLC = font["CBLC"], CBDT = font["CBDT"], sbix = font["sbix"], upng = window["UPNG"]; - var U = Typr["U"]; - - var strike = null; - if (CBLC && upng) for (var i = 0; i < CBLC.length; i++) if (CBLC[i][0] <= gid && gid <= CBLC[i][1]) strike = CBLC[i]; - - if (strike || (sbix && sbix[gid])) { - if (strike && strike[2] != 17) throw "not a PNG"; - - if (font["__tmp"] == null) font["__tmp"] = {}; - var cmd = font["__tmp"]["g" + gid]; - if (cmd == null) { - var bmp, len; - if (sbix) { bmp = sbix[gid]; len = bmp.length; } - else { - var boff = strike[3][gid - strike[0]] + 5; // smallGlyphMetrics - len = (CBDT[boff + 1] << 16) | (CBDT[boff + 2] << 8) | CBDT[boff + 3]; boff += 4; - bmp = new Uint8Array(CBDT.buffer, CBDT.byteOffset + boff, len); - } - var str = ""; for (var i = 0; i < len; i++) str += String.fromCharCode(bmp[i]); - cmd = font["__tmp"]["g" + gid] = "data:image/png;base64," + btoa(str); - } - - path.cmds.push(cmd); - var upe = font["head"]["unitsPerEm"] * 1.15; - var gw = Math.round(upe), gh = Math.round(upe), dy = Math.round(-gh * 0.15); - path.crds.push(0, gh + dy, gw, gh + dy, gw, dy, 0, dy); //*/ - } - else if (SVG && SVG.entries[gid]) { - var p = SVG.entries[gid]; - if (p != null) { - if (typeof p == "number") { - var svg = SVG.svgs[p]; - if (typeof svg == "string") { - var prsr = new DOMParser(); - var doc = prsr["parseFromString"](svg, "image/svg+xml"); - svg = SVG.svgs[p] = doc.getElementsByTagName("svg")[0]; - } - p = U["SVG"].toPath(svg, gid); SVG.entries[gid] = p; - } - path = p; - } - } - else if (noColor != true && COLR && COLR[0]["g" + gid] && COLR[0]["g" + gid][1] > 1) { - - function toHex(n) { var o = n.toString(16); return (o.length == 1 ? "0" : "") + o; } - - var CPAL = font["CPAL"], gl = COLR[0]["g" + gid]; - for (var i = 0; i < gl[1]; i++) { - var lid = gl[0] + i; - var cgl = COLR[1][2 * lid], pid = COLR[1][2 * lid + 1] * 4; - var pth = Typr["U"]["glyphToPath"](font, cgl, cgl == gid); - - var col = "#" + toHex(CPAL[pid + 2]) + toHex(CPAL[pid + 1]) + toHex(CPAL[pid + 0]); - path.cmds.push(col); - - path.cmds = path.cmds.concat(pth["cmds"]); - path.crds = path.crds.concat(pth["crds"]); - //console.log(gid, cgl,pid,col); - - path.cmds.push("X"); - } - } - else if (CFF) { - var pdct = CFF["Private"]; - var state = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: pdct ? pdct["defaultWidthX"] : 0, open: false }; - if (CFF["ROS"]) { - var gi = 0; - while (CFF["FDSelect"][gi + 2] <= gid) gi += 2; - pdct = CFF["FDArray"][CFF["FDSelect"][gi + 1]]["Private"]; - } - U["_drawCFF"](CFF["CharStrings"][gid], state, CFF, pdct, path); - } - else if (font["glyf"]) { U["_drawGlyf"](gid, font, path); } - return { "cmds": path.cmds, "crds": path.crds }; - }, - - "_drawGlyf": function (gid, font, path) { - var gl = font["glyf"][gid]; - if (gl == null) gl = font["glyf"][gid] = Typr["T"].glyf._parseGlyf(font, gid); - if (gl != null) { - if (gl.noc > -1) Typr["U"]["_simpleGlyph"](gl, path); - else Typr["U"]["_compoGlyph"](gl, font, path); - } - }, - "_simpleGlyph": function (gl, p) { - var P = Typr["U"]["P"]; - for (var c = 0; c < gl.noc; c++) { - var i0 = (c == 0) ? 0 : (gl.endPts[c - 1] + 1); - var il = gl.endPts[c]; - - for (var i = i0; i <= il; i++) { - var pr = (i == i0) ? il : (i - 1); - var nx = (i == il) ? i0 : (i + 1); - var onCurve = gl.flags[i] & 1; - var prOnCurve = gl.flags[pr] & 1; - var nxOnCurve = gl.flags[nx] & 1; - - var x = gl.xs[i], y = gl.ys[i]; - - if (i == i0) { - if (onCurve) { - if (prOnCurve) P.MoveTo(p, gl.xs[pr], gl.ys[pr]); - else { P.MoveTo(p, x, y); continue; /* will do CurveTo at il */ } - } - else { - if (prOnCurve) P.MoveTo(p, gl.xs[pr], gl.ys[pr]); - else P.MoveTo(p, Math.floor((gl.xs[pr] + x) * 0.5), Math.floor((gl.ys[pr] + y) * 0.5)); - } - } - if (onCurve) { - if (prOnCurve) P.LineTo(p, x, y); - } - else { - if (nxOnCurve) P.qCurveTo(p, x, y, gl.xs[nx], gl.ys[nx]); - else P.qCurveTo(p, x, y, Math.floor((x + gl.xs[nx]) * 0.5), Math.floor((y + gl.ys[nx]) * 0.5)); - } - } - P.ClosePath(p); - } - }, - "_compoGlyph": function (gl, font, p) { - for (var j = 0; j < gl.parts.length; j++) { - var path = { cmds: [], crds: [] }; - var prt = gl.parts[j]; - Typr["U"]["_drawGlyf"](prt.glyphIndex, font, path); - - var m = prt.m; - for (var i = 0; i < path.crds.length; i += 2) { - var x = path.crds[i], y = path.crds[i + 1]; - p.crds.push(x * m.a + y * m.c + m.tx); // not sure, probably right - p.crds.push(x * m.b + y * m.d + m.ty); - } - for (var i = 0; i < path.cmds.length; i++) p.cmds.push(path.cmds[i]); - } - }, - - "pathToSVG": function (path, prec) { - var cmds = path["cmds"], crds = path["crds"]; - if (prec == null) prec = 5; - function num(v) { return parseFloat(v.toFixed(prec)); } - function merge(o) { - var no = [], lstF = false, lstC = ""; - for (var i = 0; i < o.length; i++) { - var it = o[i], isF = (typeof it) == "number"; - if (!isF) { if (it == lstC && it.length == 1 && it != "m") continue; lstC = it; } // move should not be merged (it actually means lineTo) - if (lstF && isF && it >= 0) no.push(" "); - no.push(it); lstF = isF; - } - return no.join(""); - } - - - var out = [], co = 0, lmap = { "M": 2, "L": 2, "Q": 4, "C": 6 }; - var x = 0, y = 0, // perfect coords - //dx=0, dy=0, // relative perfect coords - //rx=0, ry=0, // relative rounded coords - ex = 0, ey = 0, // error between perfect and output coords - mx = 0, my = 0; // perfect coords of the last "Move" - - for (var i = 0; i < cmds.length; i++) { - var cmd = cmds[i], cc = (lmap[cmd] ? lmap[cmd] : 0); - - var o0 = [], dx, dy, rx, ry; // o1=[], cx, cy, ax,ay; - if (cmd == "L") { - dx = crds[co] - x; dy = crds[co + 1] - y; - rx = num(dx + ex); ry = num(dy + ey); - // if this "lineTo" leads to the starting point, and "Z" follows, do not output anything. - if (cmds[i + 1] == "Z" && crds[co] == mx && crds[co + 1] == my) { rx = dx; ry = dy; } - else if (rx == 0 && ry == 0) { } - else if (rx == 0) o0.push("v", ry); - else if (ry == 0) o0.push("h", rx); - else { o0.push("l", rx, ry); } - } - else { - o0.push(cmd.toLowerCase()); - for (var j = 0; j < cc; j += 2) { - dx = crds[co + j] - x; dy = crds[co + j + 1] - y; - rx = num(dx + ex); ry = num(dy + ey); - o0.push(rx, ry); - } - } - if (cc != 0) { ex += dx - rx; ey += dy - ry; } - - /* - if(cmd=="L") { - cx=crds[co]; cy=crds[co+1]; - ax = num(cx); ay=num(cy); - // if this "lineTo" leads to the starting point, and "Z" follows, do not output anything. - if(cmds[i+1]=="Z" && crds[co]==mx && crds[co+1]==my) { ax=cx; ay=cy; } - else if(ax==num(x) && ay==num(y)) {} - else if(ax==num(x)) o1.push("V",ay); - else if(ay==num(y)) o1.push("H",ax); - else { o1.push("L",ax,ay); } - } - else { - o1.push(cmd); - for(var j=0; j> 1, nh = h >> 1; - var nbuf = (hlp && hlp.length == nw * nh * 4) ? hlp : new Uint8Array(nw * nh * 4); - var sb32 = new Uint32Array(buff.buffer), nb32 = new Uint32Array(nbuf.buffer); - for (var y = 0; y < nh; y++) - for (var x = 0; x < nw; x++) { - var ti = (y * nw + x), si = ((y << 1) * w + (x << 1)); - //nbuf[ti ] = buff[si ]; nbuf[ti+1] = buff[si+1]; nbuf[ti+2] = buff[si+2]; nbuf[ti+3] = buff[si+3]; - //* - var c0 = sb32[si], c1 = sb32[si + 1], c2 = sb32[si + w], c3 = sb32[si + w + 1]; - - var a0 = (c0 >>> 24), a1 = (c1 >>> 24), a2 = (c2 >>> 24), a3 = (c3 >>> 24), a = (a0 + a1 + a2 + a3); - - if (a == 1020) { - var r = (((c0 >>> 0) & 255) + ((c1 >>> 0) & 255) + ((c2 >>> 0) & 255) + ((c3 >>> 0) & 255) + 2) >>> 2; - var g = (((c0 >>> 8) & 255) + ((c1 >>> 8) & 255) + ((c2 >>> 8) & 255) + ((c3 >>> 8) & 255) + 2) >>> 2; - var b = (((c0 >>> 16) & 255) + ((c1 >>> 16) & 255) + ((c2 >>> 16) & 255) + ((c3 >>> 16) & 255) + 2) >>> 2; - nb32[ti] = (255 << 24) | (b << 16) | (g << 8) | r; - } - else if (a == 0) nb32[ti] = 0; - else { - var r = ((c0 >>> 0) & 255) * a0 + ((c1 >>> 0) & 255) * a1 + ((c2 >>> 0) & 255) * a2 + ((c3 >>> 0) & 255) * a3; - var g = ((c0 >>> 8) & 255) * a0 + ((c1 >>> 8) & 255) * a1 + ((c2 >>> 8) & 255) * a2 + ((c3 >>> 8) & 255) * a3; - var b = ((c0 >>> 16) & 255) * a0 + ((c1 >>> 16) & 255) * a1 + ((c2 >>> 16) & 255) * a2 + ((c3 >>> 16) & 255) * a3; - - var ia = 1 / a; r = ~~(r * ia + 0.5); g = ~~(g * ia + 0.5); b = ~~(b * ia + 0.5); - nb32[ti] = (((a + 2) >>> 2) << 24) | (b << 16) | (g << 8) | r; - } - } - return { buff: nbuf, w: nw, h: nh }; - } - - return ptc; - }(), - - "P": { - MoveTo: function (p, x, y) { p.cmds.push("M"); p.crds.push(x, y); }, - LineTo: function (p, x, y) { p.cmds.push("L"); p.crds.push(x, y); }, - CurveTo: function (p, a, b, c, d, e, f) { p.cmds.push("C"); p.crds.push(a, b, c, d, e, f); }, - qCurveTo: function (p, a, b, c, d) { p.cmds.push("Q"); p.crds.push(a, b, c, d); }, - ClosePath: function (p) { p.cmds.push("Z"); } - }, - - "_drawCFF": function (cmds, state, font, pdct, p) { - var stack = state.stack; - var nStems = state.nStems, haveWidth = state.haveWidth, width = state.width, open = state.open; - var i = 0; - var x = state.x, y = state.y, c1x = 0, c1y = 0, c2x = 0, c2y = 0, c3x = 0, c3y = 0, c4x = 0, c4y = 0, jpx = 0, jpy = 0; - var CFF = Typr["T"].CFF, P = Typr["U"]["P"]; - - var nominalWidthX = pdct["nominalWidthX"]; - var o = { val: 0, size: 0 }; - //console.log(cmds); - while (i < cmds.length) { - CFF.getCharString(cmds, i, o); - var v = o.val; - i += o.size; - - if (false) { } - else if (v == "o1" || v == "o18") // hstem || hstemhm - { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - } - else if (v == "o3" || v == "o23") // vstem || vstemhm - { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - } - else if (v == "o4") { - if (stack.length > 1 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - if (open) P.ClosePath(p); - - y += stack.pop(); - P.MoveTo(p, x, y); open = true; - } - else if (v == "o5") { - while (stack.length > 0) { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - } - else if (v == "o6" || v == "o7") // hlineto || vlineto - { - var count = stack.length; - var isX = (v == "o6"); - - for (var j = 0; j < count; j++) { - var sval = stack.shift(); - - if (isX) x += sval; else y += sval; - isX = !isX; - P.LineTo(p, x, y); - } - } - else if (v == "o8" || v == "o24") // rrcurveto || rcurveline - { - var count = stack.length; - var index = 0; - while (index + 6 <= count) { - c1x = x + stack.shift(); - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - index += 6; - } - if (v == "o24") { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - } - else if (v == "o11") break; - else if (v == "o1234" || v == "o1235" || v == "o1236" || v == "o1237")//if((v+"").slice(0,3)=="o12") - { - if (v == "o1234") { - c1x = x + stack.shift(); // dx1 - c1y = y; // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y; // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = c2y; // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = y; // dy5 - x = c4x + stack.shift(); // dx6 - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - - } - if (v == "o1235") { - c1x = x + stack.shift(); // dx1 - c1y = y + stack.shift(); // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y + stack.shift(); // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = jpy + stack.shift(); // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = c3y + stack.shift(); // dy5 - x = c4x + stack.shift(); // dx6 - y = c4y + stack.shift(); // dy6 - stack.shift(); // flex depth - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - if (v == "o1236") { - c1x = x + stack.shift(); // dx1 - c1y = y + stack.shift(); // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y; // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = c2y; // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = c3y + stack.shift(); // dy5 - x = c4x + stack.shift(); // dx6 - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - if (v == "o1237") { - c1x = x + stack.shift(); // dx1 - c1y = y + stack.shift(); // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y + stack.shift(); // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = jpy + stack.shift(); // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = c3y + stack.shift(); // dy5 - if (Math.abs(c4x - x) > Math.abs(c4y - y)) { - x = c4x + stack.shift(); - } else { - y = c4y + stack.shift(); - } - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - } - else if (v == "o14") { - if (stack.length > 0 && stack.length != 4 && !haveWidth) { - width = stack.shift() + font["nominalWidthX"]; - haveWidth = true; - } - if (stack.length == 4) // seac = standard encoding accented character - { - - var asb = 0; - var adx = stack.shift(); - var ady = stack.shift(); - var bchar = stack.shift(); - var achar = stack.shift(); - - - var bind = CFF.glyphBySE(font, bchar); - var aind = CFF.glyphBySE(font, achar); - - //console.log(bchar, bind); - //console.log(achar, aind); - //state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; - - Typr["U"]["_drawCFF"](font["CharStrings"][bind], state, font, pdct, p); - state.x = adx; state.y = ady; - Typr["U"]["_drawCFF"](font["CharStrings"][aind], state, font, pdct, p); - - //x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; - } - if (open) { P.ClosePath(p); open = false; } - } - else if (v == "o19" || v == "o20") { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - - i += (nStems + 7) >> 3; - } - - else if (v == "o21") { - if (stack.length > 2 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - - y += stack.pop(); - x += stack.pop(); - - if (open) P.ClosePath(p); - P.MoveTo(p, x, y); open = true; - } - else if (v == "o22") { - if (stack.length > 1 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - - x += stack.pop(); - - if (open) P.ClosePath(p); - P.MoveTo(p, x, y); open = true; - } - else if (v == "o25") { - while (stack.length > 6) { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - - c1x = x + stack.shift(); - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - else if (v == "o26") { - if (stack.length % 2) { - x += stack.shift(); - } - - while (stack.length > 0) { - c1x = x; - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x; - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - - } - else if (v == "o27") { - if (stack.length % 2) { - y += stack.shift(); - } - - while (stack.length > 0) { - c1x = x + stack.shift(); - c1y = y; - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y; - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - } - else if (v == "o10" || v == "o29") // callsubr || callgsubr - { - var obj = (v == "o10" ? pdct : font); - if (stack.length == 0) { console.log("error: empty stack"); } - else { - var ind = stack.pop(); - var subr = obj["Subrs"][ind + obj["Bias"]]; - state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; - Typr["U"]["_drawCFF"](subr, state, font, pdct, p); - x = state.x; y = state.y; nStems = state.nStems; haveWidth = state.haveWidth; width = state.width; open = state.open; - } - } - else if (v == "o30" || v == "o31") // vhcurveto || hvcurveto - { - var count, count1 = stack.length; - var index = 0; - var alternate = v == "o31"; - - count = count1 & ~2; - index += count1 - count; - - while (index < count) { - if (alternate) { - c1x = x + stack.shift(); - c1y = y; - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - y = c2y + stack.shift(); - if (count - index == 5) { x = c2x + stack.shift(); index++; } - else x = c2x; - alternate = false; - } - else { - c1x = x; - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - if (count - index == 5) { y = c2y + stack.shift(); index++; } - else y = c2y; - alternate = true; - } - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - index += 4; - } - } - - else if ((v + "").charAt(0) == "o") { console.log("Unknown operation: " + v, cmds); throw v; } - else stack.push(v); - } - //console.log(cmds); - state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; - }, - - - "SVG": function () { - var M = { - getScale: function (m) { return Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])); }, - translate: function (m, x, y) { M.concat(m, [1, 0, 0, 1, x, y]); }, - rotate: function (m, a) { M.concat(m, [Math.cos(a), -Math.sin(a), Math.sin(a), Math.cos(a), 0, 0]); }, - scale: function (m, x, y) { M.concat(m, [x, 0, 0, y, 0, 0]); }, - concat: function (m, w) { - var a = m[0], b = m[1], c = m[2], d = m[3], tx = m[4], ty = m[5]; - m[0] = (a * w[0]) + (b * w[2]); m[1] = (a * w[1]) + (b * w[3]); - m[2] = (c * w[0]) + (d * w[2]); m[3] = (c * w[1]) + (d * w[3]); - m[4] = (tx * w[0]) + (ty * w[2]) + w[4]; m[5] = (tx * w[1]) + (ty * w[3]) + w[5]; - }, - invert: function (m) { - var a = m[0], b = m[1], c = m[2], d = m[3], tx = m[4], ty = m[5], adbc = a * d - b * c; - m[0] = d / adbc; m[1] = -b / adbc; m[2] = -c / adbc; m[3] = a / adbc; - m[4] = (c * ty - d * tx) / adbc; m[5] = (b * tx - a * ty) / adbc; - }, - multPoint: function (m, p) { var x = p[0], y = p[1]; return [x * m[0] + y * m[2] + m[4], x * m[1] + y * m[3] + m[5]]; }, - multArray: function (m, a) { for (var i = 0; i < a.length; i += 2) { var x = a[i], y = a[i + 1]; a[i] = x * m[0] + y * m[2] + m[4]; a[i + 1] = x * m[1] + y * m[3] + m[5]; } } - } - - function _bracketSplit(str, lbr, rbr) { - var out = [], pos = 0, ci = 0, lvl = 0; - while (true) { //throw "e"; - var li = str.indexOf(lbr, ci); - var ri = str.indexOf(rbr, ci); - if (li == -1 && ri == -1) break; - if (ri == -1 || (li != -1 && li < ri)) { - if (lvl == 0) { out.push(str.slice(pos, li).trim()); pos = li + 1; } - lvl++; ci = li + 1; - } - else if (li == -1 || (ri != -1 && ri < li)) { - lvl--; - if (lvl == 0) { out.push(str.slice(pos, ri).trim()); pos = ri + 1; } - ci = ri + 1; - } - } - return out; - } - //"cssMap": - function cssMap(str) { - var pts = _bracketSplit(str, "{", "}"); - var css = {}; - for (var i = 0; i < pts.length; i += 2) { - var cn = pts[i].split(","); - for (var j = 0; j < cn.length; j++) { - var cnj = cn[j].trim(); if (css[cnj] == null) css[cnj] = ""; - css[cnj] += pts[i + 1]; - } - } - return css; - } - //"readTrnf" - function readTrnf(trna) { - var pts = _bracketSplit(trna, "(", ")"); - var m = [1, 0, 0, 1, 0, 0]; - for (var i = 0; i < pts.length; i += 2) { var om = m; m = _readTrnsAttr(pts[i], pts[i + 1]); M.concat(m, om); } - return m; - } - - function _readTrnsAttr(fnc, vls) { - //console.log(vls); - //vls = vls.replace(/\-/g, " -").trim(); - var m = [1, 0, 0, 1, 0, 0], gotSep = true; - for (var i = 0; i < vls.length; i++) { // matrix(.99915 0 0 .99915.418.552) matrix(1 0 0-.9474-22.535 271.03) - var ch = vls.charAt(i); - if (ch == "," || ch == " ") gotSep = true; - else if (ch == ".") { - if (!gotSep) { vls = vls.slice(0, i) + "," + vls.slice(i); i++; } gotSep = false; - } - else if (ch == "-" && i > 0 && vls[i - 1] != "e") { vls = vls.slice(0, i) + " " + vls.slice(i); i++; gotSep = true; } - } - - vls = vls.split(/\s*[\s,]\s*/).map(parseFloat); - if (false) { } - else if (fnc == "translate") { if (vls.length == 1) M.translate(m, vls[0], 0); else M.translate(m, vls[0], vls[1]); } - else if (fnc == "scale") { if (vls.length == 1) M.scale(m, vls[0], vls[0]); else M.scale(m, vls[0], vls[1]); } - else if (fnc == "rotate") { var tx = 0, ty = 0; if (vls.length != 1) { tx = vls[1]; ty = vls[2]; } M.translate(m, -tx, -ty); M.rotate(m, -Math.PI * vls[0] / 180); M.translate(m, tx, ty); } - else if (fnc == "matrix") m = vls; - else console.log("unknown transform: ", fnc); - return m; - } - - function toPath(svg, gid) { - var pth = { cmds: [], crds: [] }; - - var vb = svg.getAttribute("viewBox"); - if (vb) vb = vb.trim().split(" ").map(parseFloat); else vb = [0, 0, 1000, 1000]; - - var nod = svg; - if (gid != null) { var nd = svg.getElementById("glyph" + gid); if (nd) nod = nd; } - - _toPath(nod.children, pth, null, svg); - for (var i = 0; i < pth.crds.length; i += 2) { - var x = pth.crds[i], y = pth.crds[i + 1]; - x -= vb[0]; - y -= vb[1]; - y = -y; - pth.crds[i] = x; - pth.crds[i + 1] = y; - } - return pth; - } - - var cmap = { - "aliceblue": "#f0f8ff", "antiquewhite": "#faebd7", "aqua": "#00ffff", "aquamarine": "#7fffd4", "azure": "#f0ffff", "beige": "#f5f5dc", "bisque": "#ffe4c4", - "black": "#000000", "blanchedalmond": "#ffebcd", "blue": "#0000ff", "blueviolet": "#8a2be2", "brown": "#a52a2a", "burlywood": "#deb887", "cadetblue": "#5f9ea0", - "chartreuse": "#7fff00", "chocolate": "#d2691e", "coral": "#ff7f50", "cornflowerblue": "#6495ed", "cornsilk": "#fff8dc", "crimson": "#dc143c", "cyan": "#00ffff", - "darkblue": "#00008b", "darkcyan": "#008b8b", "darkgoldenrod": "#b8860b", "darkgray": "#a9a9a9", "darkgreen": "#006400", "darkgrey": "#a9a9a9", "darkkhaki": "#bdb76b", - "darkmagenta": "#8b008b", "darkolivegreen": "#556b2f", "darkorange": "#ff8c00", "darkorchid": "#9932cc", "darkred": "#8b0000", "darksalmon": "#e9967a", "darkseagreen": "#8fbc8f", - "darkslateblue": "#483d8b", "darkslategray": "#2f4f4f", "darkslategrey": "#2f4f4f", "darkturquoise": "#00ced1", "darkviolet": "#9400d3", "deeppink": "#ff1493", - "deepskyblue": "#00bfff", "dimgray": "#696969", "dimgrey": "#696969", "dodgerblue": "#1e90ff", "firebrick": "#b22222", "floralwhite": "#fffaf0", "forestgreen": "#228b22", - "fuchsia": "#ff00ff", "gainsboro": "#dcdcdc", "ghostwhite": "#f8f8ff", "gold": "#ffd700", "goldenrod": "#daa520", "gray": "#808080", "green": "#008000", "greenyellow": "#adff2f", - "grey": "#808080", "honeydew": "#f0fff0", "hotpink": "#ff69b4", "indianred": "#cd5c5c", "indigo": "#4b0082", "ivory": "#fffff0", "khaki": "#f0e68c", "lavender": "#e6e6fa", - "lavenderblush": "#fff0f5", "lawngreen": "#7cfc00", "lemonchiffon": "#fffacd", "lightblue": "#add8e6", "lightcoral": "#f08080", "lightcyan": "#e0ffff", - "lightgoldenrodyellow": "#fafad2", "lightgray": "#d3d3d3", "lightgreen": "#90ee90", "lightgrey": "#d3d3d3", "lightpink": "#ffb6c1", "lightsalmon": "#ffa07a", - "lightseagreen": "#20b2aa", "lightskyblue": "#87cefa", "lightslategray": "#778899", "lightslategrey": "#778899", "lightsteelblue": "#b0c4de", "lightyellow": "#ffffe0", - "lime": "#00ff00", "limegreen": "#32cd32", "linen": "#faf0e6", "magenta": "#ff00ff", "maroon": "#800000", "mediumaquamarine": "#66cdaa", "mediumblue": "#0000cd", - "mediumorchid": "#ba55d3", "mediumpurple": "#9370db", "mediumseagreen": "#3cb371", "mediumslateblue": "#7b68ee", "mediumspringgreen": "#00fa9a", - "mediumturquoise": "#48d1cc", "mediumvioletred": "#c71585", "midnightblue": "#191970", "mintcream": "#f5fffa", "mistyrose": "#ffe4e1", "moccasin": "#ffe4b5", - "navajowhite": "#ffdead", "navy": "#000080", "oldlace": "#fdf5e6", "olive": "#808000", "olivedrab": "#6b8e23", "orange": "#ffa500", "orangered": "#ff4500", - "orchid": "#da70d6", "palegoldenrod": "#eee8aa", "palegreen": "#98fb98", "paleturquoise": "#afeeee", "palevioletred": "#db7093", "papayawhip": "#ffefd5", - "peachpuff": "#ffdab9", "peru": "#cd853f", "pink": "#ffc0cb", "plum": "#dda0dd", "powderblue": "#b0e0e6", "purple": "#800080", "rebeccapurple": "#663399", "red": "#ff0000", - "rosybrown": "#bc8f8f", "royalblue": "#4169e1", "saddlebrown": "#8b4513", "salmon": "#fa8072", "sandybrown": "#f4a460", "seagreen": "#2e8b57", "seashell": "#fff5ee", - "sienna": "#a0522d", "silver": "#c0c0c0", "skyblue": "#87ceeb", "slateblue": "#6a5acd", "slategray": "#708090", "slategrey": "#708090", "snow": "#fffafa", "springgreen": "#00ff7f", - "steelblue": "#4682b4", "tan": "#d2b48c", "teal": "#008080", "thistle": "#d8bfd8", "tomato": "#ff6347", "turquoise": "#40e0d0", "violet": "#ee82ee", "wheat": "#f5deb3", - "white": "#ffffff", "whitesmoke": "#f5f5f5", "yellow": "#ffff00", "yellowgreen": "#9acd32" - }; - - function _toPath(nds, pth, fill, root) { - for (var ni = 0; ni < nds.length; ni++) { - var nd = nds[ni], tn = nd.tagName; - var cfl = nd.getAttribute("fill"); if (cfl == null) cfl = fill; - if (cfl && cfl.startsWith("url")) { - var gid = cfl.slice(5, -1); - var grd = root.getElementById(gid), s0 = grd.children[0]; - if (s0.getAttribute("stop-opacity") != null) continue; - cfl = s0.getAttribute("stop-color"); - } - if (cmap[cfl]) cfl = cmap[cfl]; - if (tn == "g" || tn == "use") { - var tp = { crds: [], cmds: [] }; - if (tn == "g") _toPath(nd.children, tp, cfl, root); - else { - var lnk = nd.getAttribute("xlink:href").slice(1); - var pel = root.getElementById(lnk); - _toPath([pel], tp, cfl, root); - } - var m = [1, 0, 0, 1, 0, 0]; - var x = nd.getAttribute("x"), y = nd.getAttribute("y"); x = x ? parseFloat(x) : 0; y = y ? parseFloat(y) : 0; - M.concat(m, [1, 0, 0, 1, x, y]); - - var trf = nd.getAttribute("transform"); if (trf) M.concat(m, readTrnf(trf)); - - M.multArray(m, tp.crds); - pth.crds = pth.crds.concat(tp.crds); - pth.cmds = pth.cmds.concat(tp.cmds); - } - else if (tn == "path" || tn == "circle" || tn == "ellipse") { - pth.cmds.push(cfl ? cfl : "#000000"); - var d; - if (tn == "path") d = nd.getAttribute("d"); //console.log(d); - if (tn == "circle" || tn == "ellipse") { - var vls = [0, 0, 0, 0], nms = ["cx", "cy", "rx", "ry", "r"]; - for (var i = 0; i < 5; i++) { var V = nd.getAttribute(nms[i]); if (V) { V = parseFloat(V); if (i < 4) vls[i] = V; else vls[2] = vls[3] = V; } } - var cx = vls[0], cy = vls[1], rx = vls[2], ry = vls[3]; - d = ["M", cx - rx, cy, "a", rx, ry, 0, 1, 0, rx * 2, 0, "a", rx, ry, 0, 1, 0, -rx * 2, 0].join(" "); - } - svgToPath(d, pth); pth.cmds.push("X"); - } - else if (tn == "image") { - var w = parseFloat(nd.getAttribute("width")), h = parseFloat(nd.getAttribute("height")); - pth.cmds.push(nd.getAttribute("xlink:href")); - pth.crds.push(0, 0, w, 0, w, h, 0, h); - } - else if (tn == "defs") { } - else console.log(tn); - } - } - - function _tokens(d) { - var ts = [], off = 0, rn = false, cn = "", pc = "", lc = "", nc = 0; // reading number, current number, prev char, lastCommand, number count (after last command - while (off < d.length) { - var cc = d.charCodeAt(off), ch = d.charAt(off); off++; - var isNum = (48 <= cc && cc <= 57) || ch == "." || ch == "-" || ch == "+" || ch == "e" || ch == "E"; - - if (rn) { - if (((ch == "+" || ch == "-") && pc != "e") || (ch == "." && cn.indexOf(".") != -1) || (isNum && (lc == "a" || lc == "A") && ((nc % 7) == 3 || (nc % 7) == 4))) { ts.push(parseFloat(cn)); nc++; cn = ch; } - else if (isNum) cn += ch; - else { ts.push(parseFloat(cn)); nc++; if (ch != "," && ch != " ") { ts.push(ch); lc = ch; nc = 0; } rn = false; } - } - else { - if (isNum) { cn = ch; rn = true; } - else if (ch != "," && ch != " ") { ts.push(ch); lc = ch; nc = 0; } - } - pc = ch; - } - if (rn) ts.push(parseFloat(cn)); - return ts; - } - - function _reps(ts, off, ps) { - var i = off; - while (i < ts.length) { if ((typeof ts[i]) == "string") break; i += ps; } - return (i - off) / ps; - } - - function svgToPath(d, pth) { - var ts = _tokens(d); - var i = 0, x = 0, y = 0, ox = 0, oy = 0, oldo = pth.crds.length; - var pc = { "M": 2, "L": 2, "H": 1, "V": 1, "T": 2, "S": 4, "A": 7, "Q": 4, "C": 6 }; - var cmds = pth.cmds, crds = pth.crds; - - while (i < ts.length) { - var cmd = ts[i]; i++; - var cmu = cmd.toUpperCase(); - - if (cmu == "Z") { cmds.push("Z"); x = ox; y = oy; } - else { - var ps = pc[cmu], reps = _reps(ts, i, ps); - - for (var j = 0; j < reps; j++) { - // If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit lineto commands. - if (j == 1 && cmu == "M") { cmd = (cmd == cmu) ? "L" : "l"; cmu = "L"; } - - var xi = 0, yi = 0; if (cmd != cmu) { xi = x; yi = y; } - - if (false) { } - else if (cmu == "M") { x = xi + ts[i++]; y = yi + ts[i++]; cmds.push("M"); crds.push(x, y); ox = x; oy = y; } - else if (cmu == "L") { x = xi + ts[i++]; y = yi + ts[i++]; cmds.push("L"); crds.push(x, y); } - else if (cmu == "H") { x = xi + ts[i++]; cmds.push("L"); crds.push(x, y); } - else if (cmu == "V") { y = yi + ts[i++]; cmds.push("L"); crds.push(x, y); } - else if (cmu == "Q") { - var x1 = xi + ts[i++], y1 = yi + ts[i++], x2 = xi + ts[i++], y2 = yi + ts[i++]; - cmds.push("Q"); crds.push(x1, y1, x2, y2); x = x2; y = y2; - } - else if (cmu == "T") { - var co = Math.max(crds.length - (cmds[cmds.length - 1] == "Q" ? 4 : 2), oldo); - var x1 = x + x - crds[co], y1 = y + y - crds[co + 1]; - var x2 = xi + ts[i++], y2 = yi + ts[i++]; - cmds.push("Q"); crds.push(x1, y1, x2, y2); x = x2; y = y2; - } - else if (cmu == "C") { - var x1 = xi + ts[i++], y1 = yi + ts[i++], x2 = xi + ts[i++], y2 = yi + ts[i++], x3 = xi + ts[i++], y3 = yi + ts[i++]; - cmds.push("C"); crds.push(x1, y1, x2, y2, x3, y3); x = x3; y = y3; - } - else if (cmu == "S") { - var co = Math.max(crds.length - (cmds[cmds.length - 1] == "C" ? 4 : 2), oldo); - var x1 = x + x - crds[co], y1 = y + y - crds[co + 1]; - var x2 = xi + ts[i++], y2 = yi + ts[i++], x3 = xi + ts[i++], y3 = yi + ts[i++]; - cmds.push("C"); crds.push(x1, y1, x2, y2, x3, y3); x = x3; y = y3; - } - else if (cmu == "A") { // convert SVG Arc to four cubic bézier segments "C" - var x1 = x, y1 = y; - var rx = ts[i++], ry = ts[i++]; - var phi = ts[i++] * (Math.PI / 180), fA = ts[i++], fS = ts[i++]; - var x2 = xi + ts[i++], y2 = yi + ts[i++]; - if (x2 == x && y2 == y && rx == 0 && ry == 0) continue; - - var hdx = (x1 - x2) / 2, hdy = (y1 - y2) / 2; - var cosP = Math.cos(phi), sinP = Math.sin(phi); - var x1A = cosP * hdx + sinP * hdy; - var y1A = -sinP * hdx + cosP * hdy; - - var rxS = rx * rx, ryS = ry * ry; - var x1AS = x1A * x1A, y1AS = y1A * y1A; - var frc = (rxS * ryS - rxS * y1AS - ryS * x1AS) / (rxS * y1AS + ryS * x1AS); - var coef = (fA != fS ? 1 : -1) * Math.sqrt(Math.max(frc, 0)); - var cxA = coef * (rx * y1A) / ry; - var cyA = -coef * (ry * x1A) / rx; - - var cx = cosP * cxA - sinP * cyA + (x1 + x2) / 2; - var cy = sinP * cxA + cosP * cyA + (y1 + y2) / 2; - - var angl = function (ux, uy, vx, vy) { - var lU = Math.sqrt(ux * ux + uy * uy), lV = Math.sqrt(vx * vx + vy * vy); - var num = (ux * vx + uy * vy) / (lU * lV); //console.log(num, Math.acos(num)); - return (ux * vy - uy * vx >= 0 ? 1 : -1) * Math.acos(Math.max(-1, Math.min(1, num))); - } - - var vX = (x1A - cxA) / rx, vY = (y1A - cyA) / ry; - var theta1 = angl(1, 0, vX, vY); - var dtheta = angl(vX, vY, (-x1A - cxA) / rx, (-y1A - cyA) / ry); - dtheta = dtheta % (2 * Math.PI); - - var arc = function (gst, x, y, r, a0, a1, neg) { - var rotate = function (m, a) { - var si = Math.sin(a), co = Math.cos(a); - var a = m[0], b = m[1], c = m[2], d = m[3]; - m[0] = (a * co) + (b * si); m[1] = (-a * si) + (b * co); - m[2] = (c * co) + (d * si); m[3] = (-c * si) + (d * co); - } - var multArr = function (m, a) { - for (var j = 0; j < a.length; j += 2) { - var x = a[j], y = a[j + 1]; - a[j] = m[0] * x + m[2] * y + m[4]; - a[j + 1] = m[1] * x + m[3] * y + m[5]; - } - } - var concatA = function (a, b) { for (var j = 0; j < b.length; j++) a.push(b[j]); } - var concatP = function (p, r) { concatA(p.cmds, r.cmds); concatA(p.crds, r.crds); } - // circle from a0 counter-clock-wise to a1 - if (neg) while (a1 > a0) a1 -= 2 * Math.PI; - else while (a1 < a0) a1 += 2 * Math.PI; - var th = (a1 - a0) / 4; - - var x0 = Math.cos(th / 2), y0 = -Math.sin(th / 2); - var x1 = (4 - x0) / 3, y1 = y0 == 0 ? y0 : (1 - x0) * (3 - x0) / (3 * y0); - var x2 = x1, y2 = -y1; - var x3 = x0, y3 = -y0; - - var ps = [x1, y1, x2, y2, x3, y3]; - - var pth = { cmds: ["C", "C", "C", "C"], crds: ps.slice(0) }; - var rot = [1, 0, 0, 1, 0, 0]; rotate(rot, -th); - for (var j = 0; j < 3; j++) { multArr(rot, ps); concatA(pth.crds, ps); } - - rotate(rot, -a0 + th / 2); rot[0] *= r; rot[1] *= r; rot[2] *= r; rot[3] *= r; rot[4] = x; rot[5] = y; - multArr(rot, pth.crds); - multArr(gst.ctm, pth.crds); - concatP(gst.pth, pth); - } - - var gst = { pth: pth, ctm: [rx * cosP, rx * sinP, -ry * sinP, ry * cosP, cx, cy] }; - arc(gst, 0, 0, 1, theta1, theta1 + dtheta, fS == 0); - x = x2; y = y2; - } - else console.log("Unknown SVG command " + cmd); - } - } - } - }; - return { "cssMap": cssMap, "readTrnf": readTrnf, svgToPath: svgToPath, toPath: toPath }; - }(), - - - - - "initHB": function (hurl, resp) { - var codeLength = function (code) { - var len = 0; - if ((code & (0xffffffff - (1 << 7) + 1)) == 0) { len = 1; } - else if ((code & (0xffffffff - (1 << 11) + 1)) == 0) { len = 2; } - else if ((code & (0xffffffff - (1 << 16) + 1)) == 0) { len = 3; } - else if ((code & (0xffffffff - (1 << 21) + 1)) == 0) { len = 4; } - return len; - } - - fetch(hurl) - .then(function (x) { return x["arrayBuffer"](); }) - .then(function (ab) { return WebAssembly["instantiate"](ab); }) - .then(function (res) { - console.log("HB ready"); - var exp = res["instance"]["exports"], mem = exp["memory"]; - //mem["grow"](30); // each page is 64kb in size - var heapu8, u32, i32; - var __lastFnt, blob, blobPtr, face, font; - - Typr["U"]["shapeHB"] = (function () { - - var toJson = function (ptr) { - var length = exp["hb_buffer_get_length"](ptr); - var result = []; - var iPtr32 = exp["hb_buffer_get_glyph_infos"](ptr, 0) >>> 2; - var pPtr32 = exp["hb_buffer_get_glyph_positions"](ptr, 0) >>> 2; - for (var i = 0; i < length; ++i) { - var a = iPtr32 + i * 5, b = pPtr32 + i * 5; - result.push({ - "g": u32[a + 0], - "cl": u32[a + 2], - "ax": i32[b + 0], - "ay": i32[b + 1], - "dx": i32[b + 2], - "dy": i32[b + 3] - }); - } - //console.log(result); - return result; - } - var te; - - return function (fnt, str, ltr) { - var fdata = fnt["_data"], fn = fnt["name"]["postScriptName"]; - - //var olen = mem.buffer.byteLength, nlen = 2*fdata.length+str.length*16 + 4e6; - //if(olen>>16)+4); //console.log("growing",nlen); - - heapu8 = new Uint8Array(mem.buffer); - u32 = new Uint32Array(mem.buffer); - i32 = new Int32Array(mem.buffer); - - if (__lastFnt != fn) { - if (blob != null) { - exp["hb_blob_destroy"](blob); - exp["free"](blobPtr); - exp["hb_face_destroy"](face); - exp["hb_font_destroy"](font); - } - blobPtr = exp["malloc"](fdata.byteLength); heapu8.set(fdata, blobPtr); - blob = exp["hb_blob_create"](blobPtr, fdata.byteLength, 2, 0, 0); - face = exp["hb_face_create"](blob, 0); - font = exp["hb_font_create"](face) - __lastFnt = fn; - } - if (window["TextEncoder"] == null) { alert("Your browser is too old. Please, update it."); return; } - if (te == null) te = new window["TextEncoder"]("utf8"); - - var buffer = exp["hb_buffer_create"](); - var bytes = te["encode"](str); - var len = bytes.length, strp = exp["malloc"](len); heapu8.set(bytes, strp); - exp["hb_buffer_add_utf8"](buffer, strp, len, 0, len); - exp["free"](strp); - - exp["hb_buffer_set_direction"](buffer, ltr ? 4 : 5); - exp["hb_buffer_guess_segment_properties"](buffer); - exp["hb_shape"](font, buffer, 0, 0); - var json = toJson(buffer)//buffer["json"](); - exp["hb_buffer_destroy"](buffer); - - var arr = json.slice(0); if (!ltr) arr.reverse(); - var ci = 0, bi = 0; // character index, binary index - for (var i = 1; i < arr.length; i++) { - var gl = arr[i], cl = gl["cl"]; - while (true) { - var cpt = str.codePointAt(ci), cln = codeLength(cpt); - if (bi + cln <= cl) { bi += cln; ci += cpt <= 0xffff ? 1 : 2; } - else break; - } - //while(bi+codeLength(str.charCodeAt(ci)) <=cl) { bi+=codeLength(str.charCodeAt(ci)); ci++; } - gl["cl"] = ci; - } - return json; - } - }()); - resp(); - }); - } -} +Typr["U"] = function() { + var P = { + MoveTo : function(p, x, y) { p.cmds.push("M"); p.crds.push(x,y); }, + LineTo : function(p, x, y) { p.cmds.push("L"); p.crds.push(x,y); }, + CurveTo : function(p, a,b,c,d,e,f) { p.cmds.push("C"); p.crds.push(a,b,c,d,e,f); }, + qCurveTo : function(p, a,b,c,d) { p.cmds.push("Q"); p.crds.push(a,b,c,d); }, + ClosePath : function(p) { p.cmds.push("Z"); } + } + + function getGlyphPosition(font, gls,i1,ltr) { + var g1=gls[i1],g2=gls[i1+1], kern=font["kern"]; + if(kern) { + var ind1 = kern.glyph1.indexOf(g1); + if(ind1!=-1) + { + var ind2 = kern.rval[ind1].glyph2.indexOf(g2); + if(ind2!=-1) return [0,0,kern.rval[ind1].vals[ind2],0]; + } + } + //console.log("no kern"); + return [0,0,0,0]; + } + function shape(font,str,prm) { + var ltr = prm["ltr"], fts = prm["fts"], axs=prm["axs"]; + if(font["fvar"] && axs==null) axs = font["fvar"][1][font["_index"]][2]; + + var HVAR = font["HVAR"]; //console.log(HVAR); + if(axs && HVAR) { axs=_normalizeAxis(font,axs); } //console.log(S,axs); + var gls = []; + for(var i=0; i0xffff) i++; + gls.push(codeToGlyph(font, cc)); + } + var shape = []; + var x = 0, y = 0; + + for(var i=0; i>>1); if(arr[mid*k]<=v) l=mid; else r=mid; } + + //var mi = 0; for(var i=0; i=tab.map.length) gid = 0; + else gid = tab.map[code]; + } + /*else if(fmt==2) { + var data=font["_data"], off = cmap.off+tab.off+6, bin=Typr["B"]; + var shKey = bin.readUshort(data,off + 2*(code>>>8)); + var shInd = off + 256*2 + shKey*8; + + var firstCode = bin.readUshort(data,shInd); + var entryCount= bin.readUshort(data,shInd+2); + var idDelta = bin.readShort (data,shInd+4); + var idRangeOffset = bin.readUshort(data,shInd+6); + + if(firstCode<=code && code<=firstCode+entryCount) { + // not completely correct + gid = bin.readUshort(data, shInd+6+idRangeOffset + (code&255)*2); + } + else gid=0; + //if(code>256) console.log(code,(code>>>8),shKey,firstCode,entryCount,idDelta,idRangeOffset); + + //throw "e"; + //console.log(tab, bin.readUshort(data,off)); + //throw "e"; + }*/ + else if(fmt==4) { + var ec = tab.endCount; gid=0; + if(code<=ec[ec.length-1]) { + // smallest index with code <= value + var sind = arrSearch(ec,1,code); + if(ec[sind]=tab.startCount[sind]) { + var gli = 0; + if(tab.idRangeOffset[sind]!=0) gli = tab.glyphIdArray[(code-tab.startCount[sind]) + (tab.idRangeOffset[sind]>>1) - (tab.idRangeOffset.length-sind)]; + else gli = code + tab.idDelta[sind]; + gid = (gli & 0xFFFF); + } + } + } + else if(fmt==6) { + var off = code-tab.firstCode, arr=tab.glyphIdArray; + if(off<0 || off>=arr.length) gid=0; + else gid = arr[off]; + } + else if(fmt==12) { + var grp = tab.groups; gid=0; //console.log(grp); throw "e"; + + if(code<=grp[grp.length-2]) { + var i = arrSearch(grp,3,code); + if(grp[i]<=code && code<=grp[i+1]) { gid = grp[i+2] + (code-grp[i]); } + } + } + else throw "unknown cmap table format "+tab.format; + + //* + var SVG = font["SVG "], loca = font["loca"]; + // if the font claims to have a Glyph for a character, but the glyph is empty, and the character is not "white", it is a lie! + if(gid!=0 && font["CFF "]==null && (SVG==null || SVG.entries[gid]==null) && loca && loca[gid]==loca[gid+1] // loca not present in CFF or SVG fonts + && whm[code]==null ) gid=0; + //*/ + + return gid; + } + function glyphToPath(font, gid, noColor,axs) { + var path = { cmds:[], crds:[] }; + + if(font["fvar"]) { + if(axs==null) axs = font["fvar"][1][font["_index"]][2]; + axs=_normalizeAxis(font,axs); + } + + var SVG = font["SVG "], CFF = font["CFF "], COLR=font["COLR"], CBLC=font["CBLC"], CBDT=font["CBDT"], sbix=font["sbix"], upng=window["UPNG"]; + + var strike = null; + if(CBLC && upng) for(var i=0; i1) { + + function toHex(n){ var o=n.toString(16); return (o.length==1 ? "0":"")+o; } + + var CPAL = font["CPAL"], gl = COLR[0]["g"+gid]; + for(var i=0; i-1) _simpleGlyph(gl, font, gid, path,axs); + else _compoGlyph (gl, font, gid, path,axs); + } + } + function _interpolate(axs,v) { + var acnt = v.length, S = 1; + var s = axs[0]; // start + var p = axs[1]; // peak + var e = axs[2]; // end + + for(var i=0; i p[i] || p[i] > e[i]) AS = 1; + else if (s[i] < 0 && e[i] > 0 && p[i] != 0) AS = 1; + else if (p[i] == 0) AS = 1; + else if (v[i] < s[i] || v[i] > e[i]) AS = 0; + else { + if (v[i] ==p[i]) AS = 1; + else if (v[i] < p[i]) AS = (v[i] - s[i]) / (p[i] - s[i]); + else AS = (e[i] - v[i]) / (e[i] - p[i]); + } + S = S * AS; + } + return S; + } + function _normalizeAxis(font,vv) { + var fvar = font["fvar"], avar = font["avar"]; + var fv = fvar?fvar[0 ]:null; + + var nv = []; + for(var i=0; idef) nv[i]=(v-def)/(max-def); + else nv[i]=0; + + if(avar && nv[i]!=-1) { + var av = avar[i], j=0; + for(; j=nv[i]) break; + var f=(nv[i]-av[j-2])/(av[j]-av[j-2]); + nv[i] = f*av[j+1] + (1-f)*av[j-1]; + } + + } + return nv; + } + function interpolateDeltas(dfs,ind,xs,ys) { + var N=xs.length, ndfs = new Array(N*2+8); ndfs.fill(0); + for(var i=0; i=N) i0--; + for(var j=0; j=0) no.push(" "); + no.push(it); lstF=isF; + } + return no.join(""); + } + + + var out = [], co = 0, lmap = {"M":2,"L":2,"Q":4,"C":6}; + var x =0, y =0, // perfect coords + //dx=0, dy=0, // relative perfect coords + //rx=0, ry=0, // relative rounded coords + ex=0, ey=0, // error between perfect and output coords + mx=0, my=0; // perfect coords of the last "Move" + + for(var i=0; i>1, nh = h>>1; + var nbuf = (hlp && hlp.length==nw*nh*4) ? hlp : new Uint8Array(nw*nh*4); + var sb32 = new Uint32Array(buff.buffer), nb32 = new Uint32Array(nbuf.buffer); + for(var y=0; y>>24), a1 = (c1>>>24), a2 = (c2>>>24), a3 = (c3>>>24), a = (a0+a1+a2+a3); + + if(a==1020) { + var r = (((c0>>> 0)&255) + ((c1>>> 0)&255) + ((c2>>> 0)&255) + ((c3>>> 0)&255)+2)>>>2; + var g = (((c0>>> 8)&255) + ((c1>>> 8)&255) + ((c2>>> 8)&255) + ((c3>>> 8)&255)+2)>>>2; + var b = (((c0>>>16)&255) + ((c1>>>16)&255) + ((c2>>>16)&255) + ((c3>>>16)&255)+2)>>>2; + nb32[ti] = (255<<24) | (b<<16) | (g<<8) | r; + } + else if(a==0) nb32[ti] = 0; + else { + var r = ((c0>>> 0)&255)*a0 + ((c1>>> 0)&255)*a1 + ((c2>>> 0)&255)*a2 + ((c3>>> 0)&255)*a3; + var g = ((c0>>> 8)&255)*a0 + ((c1>>> 8)&255)*a1 + ((c2>>> 8)&255)*a2 + ((c3>>> 8)&255)*a3; + var b = ((c0>>>16)&255)*a0 + ((c1>>>16)&255)*a1 + ((c2>>>16)&255)*a2 + ((c3>>>16)&255)*a3; + + var ia = 1/a; r = ~~(r*ia+0.5); g = ~~(g*ia+0.5); b = ~~(b*ia+0.5); + nb32[ti] = (((a+2)>>>2)<<24) | (b<<16) | (g<<8) | r; + } + } + return { buff:nbuf, w:nw, h:nh }; + } + + var __cnv, __ct; + function pathToContext(path, ctx) { + var c = 0, cmds = path["cmds"], crds = path["crds"]; + + //ctx.translate(3500,500); ctx.rotate(0.25); ctx.scale(1,-1); + + for(var j=0; j> 1; + stack.length = 0; + haveWidth = true; + } + else if(v=="o3" || v=="o23") // vstem || vstemhm + { + var hasWidthArg; + + // The number of stem operators on the stack is always even. + // If the value is uneven, that means a width is specified. + hasWidthArg = stack.length % 2 !== 0; + if (hasWidthArg && !haveWidth) { + width = stack.shift() + nominalWidthX; + } + + nStems += stack.length >> 1; + stack.length = 0; + haveWidth = true; + } + else if(v=="o4") + { + if (stack.length > 1 && !haveWidth) { + width = stack.shift() + nominalWidthX; + haveWidth = true; + } + if(open) P.ClosePath(p); + + y += stack.pop(); + P.MoveTo(p,x,y); open=true; + } + else if(v=="o5") + { + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + P.LineTo(p, x, y); + } + } + else if(v=="o6" || v=="o7") // hlineto || vlineto + { + var count = stack.length; + var isX = (v == "o6"); + + for(var j=0; j Math.abs(c4y - y)) { + x = c4x + stack.shift(); + } else { + y = c4y + stack.shift(); + } + P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); + P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); + } + } + else if(v=="o14") + { + if (stack.length > 0 && stack.length!=4 && !haveWidth) { + width = stack.shift() + font["nominalWidthX"]; + haveWidth = true; + } + if(stack.length==4) // seac = standard encoding accented character + { + + var asb = 0; + var adx = stack.shift(); + var ady = stack.shift(); + var bchar = stack.shift(); + var achar = stack.shift(); + + + var bind = CFF.glyphBySE(font, bchar); + var aind = CFF.glyphBySE(font, achar); + + //console.log(bchar, bind); + //console.log(achar, aind); + //state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; + + _drawCFF(font["CharStrings"][bind], state,font,pdct,p); + state.x = adx; state.y = ady; + _drawCFF(font["CharStrings"][aind], state,font,pdct,p); + + //x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; + } + if(open) { P.ClosePath(p); open=false; } + } + else if(v=="o19" || v=="o20") + { + var hasWidthArg; + + // The number of stem operators on the stack is always even. + // If the value is uneven, that means a width is specified. + hasWidthArg = stack.length % 2 !== 0; + if (hasWidthArg && !haveWidth) { + width = stack.shift() + nominalWidthX; + } + + nStems += stack.length >> 1; + stack.length = 0; + haveWidth = true; + + i += (nStems + 7) >> 3; + } + + else if(v=="o21") { + if (stack.length > 2 && !haveWidth) { + width = stack.shift() + nominalWidthX; + haveWidth = true; + } + + y += stack.pop(); + x += stack.pop(); + + if(open) P.ClosePath(p); + P.MoveTo(p,x,y); open=true; + } + else if(v=="o22") + { + if (stack.length > 1 && !haveWidth) { + width = stack.shift() + nominalWidthX; + haveWidth = true; + } + + x += stack.pop(); + + if(open) P.ClosePath(p); + P.MoveTo(p,x,y); open=true; + } + else if(v=="o25") + { + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + P.LineTo(p, x, y); + } + + c1x = x + stack.shift(); + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + y = c2y + stack.shift(); + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + } + else if(v=="o26") + { + if (stack.length % 2) { + x += stack.shift(); + } + + while (stack.length > 0) { + c1x = x; + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x; + y = c2y + stack.shift(); + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + } + + } + else if(v=="o27") + { + if (stack.length % 2) { + y += stack.shift(); + } + + while (stack.length > 0) { + c1x = x + stack.shift(); + c1y = y; + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + y = c2y; + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + } + } + else if(v=="o10" || v=="o29") // callsubr || callgsubr + { + var obj = (v=="o10" ? pdct : font); + if(stack.length==0) { console.log("error: empty stack"); } + else { + var ind = stack.pop(); + var subr = obj["Subrs"][ ind + obj["Bias"] ]; + state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; + _drawCFF(subr, state,font,pdct,p); + x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; + } + } + else if(v=="o30" || v=="o31") // vhcurveto || hvcurveto + { + var count, count1 = stack.length; + var index = 0; + var alternate = v == "o31"; + + count = count1 & ~2; + index += count1 - count; + + while ( index < count ) + { + if(alternate) + { + c1x = x + stack.shift(); + c1y = y; + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + y = c2y + stack.shift(); + if(count-index == 5) { x = c2x + stack.shift(); index++; } + else x = c2x; + alternate = false; + } + else + { + c1x = x; + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + if(count-index == 5) { y = c2y + stack.shift(); index++; } + else y = c2y; + alternate = true; + } + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + index += 4; + } + } + + else if((v+"").charAt(0)=="o") { console.log("Unknown operation: "+v, cmds); throw v; } + else stack.push(v); + } + //console.log(cmds); + state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; + } + + function initHB(hurl,resp) { + var codeLength = function(code) { + var len=0; + if ((code&(0xffffffff-(1<< 7)+1))==0) { len=1; } + else if((code&(0xffffffff-(1<<11)+1))==0) { len=2; } + else if((code&(0xffffffff-(1<<16)+1))==0) { len=3; } + else if((code&(0xffffffff-(1<<21)+1))==0) { len=4; } + return len; + } + + fetch(hurl) + .then(function (x ) { return x["arrayBuffer"](); }) + .then(function (ab ) { return WebAssembly["instantiate"](ab); }) + .then(function (res) { + console.log("HB ready"); + var exp = res["instance"]["exports"], mem=exp["memory"]; + //mem["grow"](30); // each page is 64kb in size + var heapu8, u32,i32,f32; + var __lastFnt, blob,blobPtr,face,font; + + Typr["U"]["shapeHB"] = (function () { + + var toJson = function (ptr) { + var length = exp["hb_buffer_get_length"](ptr); + var result = []; + var iPtr32 = exp["hb_buffer_get_glyph_infos"](ptr, 0) >>>2; + var pPtr32 = exp["hb_buffer_get_glyph_positions"](ptr, 0) >>>2; + for(var i=0; i>>16)+4); //console.log("growing",nlen); + + heapu8 = new Uint8Array (mem.buffer); + u32 = new Uint32Array(mem.buffer); + i32 = new Int32Array (mem.buffer); + f32 = new Float32Array(mem.buffer); + + if(__lastFnt!=fn) { + if(blob!=null) { + exp["hb_blob_destroy"](blob); + exp["free"](blobPtr); + exp["hb_face_destroy"](face); + exp["hb_font_destroy"](font); + } + blobPtr = exp["malloc"](fdata.byteLength); heapu8.set(fdata, blobPtr); + blob = exp["hb_blob_create"](blobPtr, fdata.byteLength, 2, 0, 0); + face = exp["hb_face_create"](blob, fnt["_index"]); + font = exp["hb_font_create"](face) + __lastFnt = fn; + } + if(window["TextEncoder"]==null) { alert("Your browser is too old. Please, update it."); return; } + if(te==null) te = new window["TextEncoder"]("utf8"); + + var buffer = exp["hb_buffer_create"](); + var bytes = te["encode"](str); + var len=bytes.length, strp = exp["malloc"](len); heapu8.set(bytes, strp); + exp["hb_buffer_add_utf8"](buffer, strp, len, 0, len); + exp["free"](strp); + + var bin = Typr["B"]; + + var feat=0; + if(fts) { + feat = exp["malloc"](16*fts.length); + for(var i=0; i>>2; + bin.writeASCII (heapu8, off , fe[0].split("").reverse().join("")); + u32[qo+1]=fe[1]; + u32[qo+2]=fe[2]; + u32[qo+3]=fe[3]; + } + //console.log(fts); + } + var vdat = 0; + if(axs) { + var axes=fnt["fvar"][0]; //console.log(axes, axs); + vdat = exp["malloc"](8*axs.length); + for(var i=0; i>>2; + bin.writeASCII (heapu8, off , axes[i][0].split("").reverse().join("")); + f32[qo+1]=axs[i]; + } + } + //*/ + + if(axs) exp["hb_font_set_variations"](font,vdat,axs.length); + exp["hb_buffer_set_direction"](buffer,ltr?4:5); + exp["hb_buffer_guess_segment_properties"](buffer); + exp["hb_shape"](font, buffer, feat,fts?fts.length:0); + var json = toJson(buffer)//buffer["json"](); + exp["hb_buffer_destroy"](buffer); + if(fts) exp["free"](feat); + if(axs) exp["free"](vdat); + + var arr = json.slice(0); if(!ltr) arr.reverse(); + var ci=0, bi=0; // character index, binary index + for(var i=1; i>>1); //offset += segCount*2; + obj.glyphIdArray = rUs(data, offset, ((offset0+length)-offset)>>1); //offset += segCount*2; return obj; }, @@ -1185,8 +1239,6 @@ Typr["T"].maxp = { return obj; } }; - - Typr["T"].name = { parseTab : function(data, offset, length) { @@ -1196,6 +1248,7 @@ Typr["T"].name = { var count = bin.readUshort(data, offset); offset += 2; var stringOffset = bin.readUshort(data, offset); offset += 2; + var ooo = offset-6 + stringOffset; //console.log(format,count); var names = [ @@ -1226,7 +1279,6 @@ Typr["T"].name = { "darkPalette" ]; - var offset0 = offset; var rU = bin.readUshort; for(var i=0; i 0xffff) i++; - gls.push(Typr["U"]["codeToGlyph"](font, cc)); - } - var shape = []; - var x = 0, y = 0; - - for (var i = 0; i < gls.length; i++) { - var padj = getGlyphPosition(font, gls, i, ltr); - var gid = gls[i]; - var ax = font["hmtx"].aWidth[gid] + padj[2]; - shape.push({ "g": gid, "cl": i, "dx": 0, "dy": 0, "ax": ax, "ay": 0 }); - x += ax; - } - return shape; - }, - - "shapeToPath": function (font, shape, clr) { - var tpath = { cmds: [], crds: [] }; - var x = 0, y = 0; - - for (var i = 0; i < shape.length; i++) { - var it = shape[i] - var path = Typr["U"]["glyphToPath"](font, it["g"]), crds = path["crds"]; - for (var j = 0; j < crds.length; j += 2) { - tpath.crds.push(crds[j] + x + it["dx"]); - tpath.crds.push(crds[j + 1] + y + it["dy"]); - } - if (clr) tpath.cmds.push(clr); - for (var j = 0; j < path["cmds"].length; j++) tpath.cmds.push(path["cmds"][j]); - var clen = tpath.cmds.length; - if (clr) if (clen != 0 && tpath.cmds[clen - 1] != "X") tpath.cmds.push("X"); // SVG fonts might contain "X". Then, nothing would stroke non-SVG glyphs. - - x += it["ax"]; y += it["ay"]; - } - return { "cmds": tpath.cmds, "crds": tpath.crds }; - }, - - "codeToGlyph": function () { - - // find the greatest index with a value <=v - function arrSearch(arr, k, v) { - var l = 0, r = ~~(arr.length / k); - while (l + 1 != r) { var mid = l + ((r - l) >>> 1); if (arr[mid * k] <= v) l = mid; else r = mid; } - - //var mi = 0; for(var i=0; i= tab.map.length) gid = 0; - else gid = tab.map[code]; - } - /*else if(fmt==2) { - var data=font["_data"], off = cmap.off+tab.off+6, bin=Typr["B"]; - var shKey = bin.readUshort(data,off + 2*(code>>>8)); - var shInd = off + 256*2 + shKey*8; - - var firstCode = bin.readUshort(data,shInd); - var entryCount= bin.readUshort(data,shInd+2); - var idDelta = bin.readShort (data,shInd+4); - var idRangeOffset = bin.readUshort(data,shInd+6); - - if(firstCode<=code && code<=firstCode+entryCount) { - // not completely correct - gid = bin.readUshort(data, shInd+6+idRangeOffset + (code&255)*2); - } - else gid=0; - //if(code>256) console.log(code,(code>>>8),shKey,firstCode,entryCount,idDelta,idRangeOffset); - - //throw "e"; - //console.log(tab, bin.readUshort(data,off)); - //throw "e"; - }*/ - else if (fmt == 4) { - var ec = tab.endCount; gid = 0; - if (code <= ec[ec.length - 1]) { - // smallest index with code <= value - var sind = arrSearch(ec, 1, code); - if (ec[sind] < code) sind++; - - if (code >= tab.startCount[sind]) { - var gli = 0; - if (tab.idRangeOffset[sind] != 0) gli = tab.glyphIdArray[(code - tab.startCount[sind]) + (tab.idRangeOffset[sind] >> 1) - (tab.idRangeOffset.length - sind)]; - else gli = code + tab.idDelta[sind]; - gid = (gli & 0xFFFF); - } - } - } - else if (fmt == 6) { - var off = code - tab.firstCode, arr = tab.glyphIdArray; - if (off < 0 || off >= arr.length) gid = 0; - else gid = arr[off]; - } - else if (fmt == 12) { - var grp = tab.groups; gid = 0; //console.log(grp); throw "e"; - - if (code <= grp[grp.length - 2]) { - var i = arrSearch(grp, 3, code); - if (grp[i] <= code && code <= grp[i + 1]) { gid = grp[i + 2] + (code - grp[i]); } - } - } - else throw "unknown cmap table format " + tab.format; - - //* - var SVG = font["SVG "], loca = font["loca"]; - // if the font claims to have a Glyph for a character, but the glyph is empty, and the character is not "white", it is a lie! - if (gid != 0 && font["CFF "] == null && (SVG == null || SVG.entries[gid] == null) && loca && loca[gid] == loca[gid + 1] // loca not present in CFF or SVG fonts - && whm[code] == null) gid = 0; - //*/ - - return gid; - } - return ctg; - }(), - - "glyphToPath": function (font, gid, noColor) { - var path = { cmds: [], crds: [] }; - - - var SVG = font["SVG "], CFF = font["CFF "], COLR = font["COLR"], CBLC = font["CBLC"], CBDT = font["CBDT"], sbix = font["sbix"], upng = window["UPNG"]; - var U = Typr["U"]; - - var strike = null; - if (CBLC && upng) for (var i = 0; i < CBLC.length; i++) if (CBLC[i][0] <= gid && gid <= CBLC[i][1]) strike = CBLC[i]; - - if (strike || (sbix && sbix[gid])) { - if (strike && strike[2] != 17) throw "not a PNG"; - - if (font["__tmp"] == null) font["__tmp"] = {}; - var cmd = font["__tmp"]["g" + gid]; - if (cmd == null) { - var bmp, len; - if (sbix) { bmp = sbix[gid]; len = bmp.length; } - else { - var boff = strike[3][gid - strike[0]] + 5; // smallGlyphMetrics - len = (CBDT[boff + 1] << 16) | (CBDT[boff + 2] << 8) | CBDT[boff + 3]; boff += 4; - bmp = new Uint8Array(CBDT.buffer, CBDT.byteOffset + boff, len); - } - var str = ""; for (var i = 0; i < len; i++) str += String.fromCharCode(bmp[i]); - cmd = font["__tmp"]["g" + gid] = "data:image/png;base64," + btoa(str); - } - - path.cmds.push(cmd); - var upe = font["head"]["unitsPerEm"] * 1.15; - var gw = Math.round(upe), gh = Math.round(upe), dy = Math.round(-gh * 0.15); - path.crds.push(0, gh + dy, gw, gh + dy, gw, dy, 0, dy); //*/ - } - else if (SVG && SVG.entries[gid]) { - var p = SVG.entries[gid]; - if (p != null) { - if (typeof p == "number") { - var svg = SVG.svgs[p]; - if (typeof svg == "string") { - var prsr = new DOMParser(); - var doc = prsr["parseFromString"](svg, "image/svg+xml"); - svg = SVG.svgs[p] = doc.getElementsByTagName("svg")[0]; - } - p = U["SVG"].toPath(svg, gid); SVG.entries[gid] = p; - } - path = p; - } - } - else if (noColor != true && COLR && COLR[0]["g" + gid] && COLR[0]["g" + gid][1] > 1) { - - function toHex(n) { var o = n.toString(16); return (o.length == 1 ? "0" : "") + o; } - - var CPAL = font["CPAL"], gl = COLR[0]["g" + gid]; - for (var i = 0; i < gl[1]; i++) { - var lid = gl[0] + i; - var cgl = COLR[1][2 * lid], pid = COLR[1][2 * lid + 1] * 4; - var pth = Typr["U"]["glyphToPath"](font, cgl, cgl == gid); - - var col = "#" + toHex(CPAL[pid + 2]) + toHex(CPAL[pid + 1]) + toHex(CPAL[pid + 0]); - path.cmds.push(col); - - path.cmds = path.cmds.concat(pth["cmds"]); - path.crds = path.crds.concat(pth["crds"]); - //console.log(gid, cgl,pid,col); - - path.cmds.push("X"); - } - } - else if (CFF) { - var pdct = CFF["Private"]; - var state = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: pdct ? pdct["defaultWidthX"] : 0, open: false }; - if (CFF["ROS"]) { - var gi = 0; - while (CFF["FDSelect"][gi + 2] <= gid) gi += 2; - pdct = CFF["FDArray"][CFF["FDSelect"][gi + 1]]["Private"]; - } - U["_drawCFF"](CFF["CharStrings"][gid], state, CFF, pdct, path); - } - else if (font["glyf"]) { U["_drawGlyf"](gid, font, path); } - return { "cmds": path.cmds, "crds": path.crds }; - }, - - "_drawGlyf": function (gid, font, path) { - var gl = font["glyf"][gid]; - if (gl == null) gl = font["glyf"][gid] = Typr["T"].glyf._parseGlyf(font, gid); - if (gl != null) { - if (gl.noc > -1) Typr["U"]["_simpleGlyph"](gl, path); - else Typr["U"]["_compoGlyph"](gl, font, path); - } - }, - "_simpleGlyph": function (gl, p) { - var P = Typr["U"]["P"]; - for (var c = 0; c < gl.noc; c++) { - var i0 = (c == 0) ? 0 : (gl.endPts[c - 1] + 1); - var il = gl.endPts[c]; - - for (var i = i0; i <= il; i++) { - var pr = (i == i0) ? il : (i - 1); - var nx = (i == il) ? i0 : (i + 1); - var onCurve = gl.flags[i] & 1; - var prOnCurve = gl.flags[pr] & 1; - var nxOnCurve = gl.flags[nx] & 1; - - var x = gl.xs[i], y = gl.ys[i]; - - if (i == i0) { - if (onCurve) { - if (prOnCurve) P.MoveTo(p, gl.xs[pr], gl.ys[pr]); - else { P.MoveTo(p, x, y); continue; /* will do CurveTo at il */ } - } - else { - if (prOnCurve) P.MoveTo(p, gl.xs[pr], gl.ys[pr]); - else P.MoveTo(p, Math.floor((gl.xs[pr] + x) * 0.5), Math.floor((gl.ys[pr] + y) * 0.5)); - } - } - if (onCurve) { - if (prOnCurve) P.LineTo(p, x, y); - } - else { - if (nxOnCurve) P.qCurveTo(p, x, y, gl.xs[nx], gl.ys[nx]); - else P.qCurveTo(p, x, y, Math.floor((x + gl.xs[nx]) * 0.5), Math.floor((y + gl.ys[nx]) * 0.5)); - } - } - P.ClosePath(p); - } - }, - "_compoGlyph": function (gl, font, p) { - for (var j = 0; j < gl.parts.length; j++) { - var path = { cmds: [], crds: [] }; - var prt = gl.parts[j]; - Typr["U"]["_drawGlyf"](prt.glyphIndex, font, path); - - var m = prt.m; - for (var i = 0; i < path.crds.length; i += 2) { - var x = path.crds[i], y = path.crds[i + 1]; - p.crds.push(x * m.a + y * m.c + m.tx); // not sure, probably right - p.crds.push(x * m.b + y * m.d + m.ty); - } - for (var i = 0; i < path.cmds.length; i++) p.cmds.push(path.cmds[i]); - } - }, - - "pathToSVG": function (path, prec) { - var cmds = path["cmds"], crds = path["crds"]; - if (prec == null) prec = 5; - function num(v) { return parseFloat(v.toFixed(prec)); } - function merge(o) { - var no = [], lstF = false, lstC = ""; - for (var i = 0; i < o.length; i++) { - var it = o[i], isF = (typeof it) == "number"; - if (!isF) { if (it == lstC && it.length == 1 && it != "m") continue; lstC = it; } // move should not be merged (it actually means lineTo) - if (lstF && isF && it >= 0) no.push(" "); - no.push(it); lstF = isF; - } - return no.join(""); - } - - - var out = [], co = 0, lmap = { "M": 2, "L": 2, "Q": 4, "C": 6 }; - var x = 0, y = 0, // perfect coords - //dx=0, dy=0, // relative perfect coords - //rx=0, ry=0, // relative rounded coords - ex = 0, ey = 0, // error between perfect and output coords - mx = 0, my = 0; // perfect coords of the last "Move" - - for (var i = 0; i < cmds.length; i++) { - var cmd = cmds[i], cc = (lmap[cmd] ? lmap[cmd] : 0); - - var o0 = [], dx, dy, rx, ry; // o1=[], cx, cy, ax,ay; - if (cmd == "L") { - dx = crds[co] - x; dy = crds[co + 1] - y; - rx = num(dx + ex); ry = num(dy + ey); - // if this "lineTo" leads to the starting point, and "Z" follows, do not output anything. - if (cmds[i + 1] == "Z" && crds[co] == mx && crds[co + 1] == my) { rx = dx; ry = dy; } - else if (rx == 0 && ry == 0) { } - else if (rx == 0) o0.push("v", ry); - else if (ry == 0) o0.push("h", rx); - else { o0.push("l", rx, ry); } - } - else { - o0.push(cmd.toLowerCase()); - for (var j = 0; j < cc; j += 2) { - dx = crds[co + j] - x; dy = crds[co + j + 1] - y; - rx = num(dx + ex); ry = num(dy + ey); - o0.push(rx, ry); - } - } - if (cc != 0) { ex += dx - rx; ey += dy - ry; } - - /* - if(cmd=="L") { - cx=crds[co]; cy=crds[co+1]; - ax = num(cx); ay=num(cy); - // if this "lineTo" leads to the starting point, and "Z" follows, do not output anything. - if(cmds[i+1]=="Z" && crds[co]==mx && crds[co+1]==my) { ax=cx; ay=cy; } - else if(ax==num(x) && ay==num(y)) {} - else if(ax==num(x)) o1.push("V",ay); - else if(ay==num(y)) o1.push("H",ax); - else { o1.push("L",ax,ay); } - } - else { - o1.push(cmd); - for(var j=0; j> 1, nh = h >> 1; - var nbuf = (hlp && hlp.length == nw * nh * 4) ? hlp : new Uint8Array(nw * nh * 4); - var sb32 = new Uint32Array(buff.buffer), nb32 = new Uint32Array(nbuf.buffer); - for (var y = 0; y < nh; y++) - for (var x = 0; x < nw; x++) { - var ti = (y * nw + x), si = ((y << 1) * w + (x << 1)); - //nbuf[ti ] = buff[si ]; nbuf[ti+1] = buff[si+1]; nbuf[ti+2] = buff[si+2]; nbuf[ti+3] = buff[si+3]; - //* - var c0 = sb32[si], c1 = sb32[si + 1], c2 = sb32[si + w], c3 = sb32[si + w + 1]; - - var a0 = (c0 >>> 24), a1 = (c1 >>> 24), a2 = (c2 >>> 24), a3 = (c3 >>> 24), a = (a0 + a1 + a2 + a3); - - if (a == 1020) { - var r = (((c0 >>> 0) & 255) + ((c1 >>> 0) & 255) + ((c2 >>> 0) & 255) + ((c3 >>> 0) & 255) + 2) >>> 2; - var g = (((c0 >>> 8) & 255) + ((c1 >>> 8) & 255) + ((c2 >>> 8) & 255) + ((c3 >>> 8) & 255) + 2) >>> 2; - var b = (((c0 >>> 16) & 255) + ((c1 >>> 16) & 255) + ((c2 >>> 16) & 255) + ((c3 >>> 16) & 255) + 2) >>> 2; - nb32[ti] = (255 << 24) | (b << 16) | (g << 8) | r; - } - else if (a == 0) nb32[ti] = 0; - else { - var r = ((c0 >>> 0) & 255) * a0 + ((c1 >>> 0) & 255) * a1 + ((c2 >>> 0) & 255) * a2 + ((c3 >>> 0) & 255) * a3; - var g = ((c0 >>> 8) & 255) * a0 + ((c1 >>> 8) & 255) * a1 + ((c2 >>> 8) & 255) * a2 + ((c3 >>> 8) & 255) * a3; - var b = ((c0 >>> 16) & 255) * a0 + ((c1 >>> 16) & 255) * a1 + ((c2 >>> 16) & 255) * a2 + ((c3 >>> 16) & 255) * a3; - - var ia = 1 / a; r = ~~(r * ia + 0.5); g = ~~(g * ia + 0.5); b = ~~(b * ia + 0.5); - nb32[ti] = (((a + 2) >>> 2) << 24) | (b << 16) | (g << 8) | r; - } - } - return { buff: nbuf, w: nw, h: nh }; - } - - return ptc; - }(), - - "P": { - MoveTo: function (p, x, y) { p.cmds.push("M"); p.crds.push(x, y); }, - LineTo: function (p, x, y) { p.cmds.push("L"); p.crds.push(x, y); }, - CurveTo: function (p, a, b, c, d, e, f) { p.cmds.push("C"); p.crds.push(a, b, c, d, e, f); }, - qCurveTo: function (p, a, b, c, d) { p.cmds.push("Q"); p.crds.push(a, b, c, d); }, - ClosePath: function (p) { p.cmds.push("Z"); } - }, - - "_drawCFF": function (cmds, state, font, pdct, p) { - var stack = state.stack; - var nStems = state.nStems, haveWidth = state.haveWidth, width = state.width, open = state.open; - var i = 0; - var x = state.x, y = state.y, c1x = 0, c1y = 0, c2x = 0, c2y = 0, c3x = 0, c3y = 0, c4x = 0, c4y = 0, jpx = 0, jpy = 0; - var CFF = Typr["T"].CFF, P = Typr["U"]["P"]; - - var nominalWidthX = pdct["nominalWidthX"]; - var o = { val: 0, size: 0 }; - //console.log(cmds); - while (i < cmds.length) { - CFF.getCharString(cmds, i, o); - var v = o.val; - i += o.size; - - if (false) { } - else if (v == "o1" || v == "o18") // hstem || hstemhm - { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - } - else if (v == "o3" || v == "o23") // vstem || vstemhm - { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - } - else if (v == "o4") { - if (stack.length > 1 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - if (open) P.ClosePath(p); - - y += stack.pop(); - P.MoveTo(p, x, y); open = true; - } - else if (v == "o5") { - while (stack.length > 0) { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - } - else if (v == "o6" || v == "o7") // hlineto || vlineto - { - var count = stack.length; - var isX = (v == "o6"); - - for (var j = 0; j < count; j++) { - var sval = stack.shift(); - - if (isX) x += sval; else y += sval; - isX = !isX; - P.LineTo(p, x, y); - } - } - else if (v == "o8" || v == "o24") // rrcurveto || rcurveline - { - var count = stack.length; - var index = 0; - while (index + 6 <= count) { - c1x = x + stack.shift(); - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - index += 6; - } - if (v == "o24") { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - } - else if (v == "o11") break; - else if (v == "o1234" || v == "o1235" || v == "o1236" || v == "o1237")//if((v+"").slice(0,3)=="o12") - { - if (v == "o1234") { - c1x = x + stack.shift(); // dx1 - c1y = y; // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y; // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = c2y; // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = y; // dy5 - x = c4x + stack.shift(); // dx6 - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - - } - if (v == "o1235") { - c1x = x + stack.shift(); // dx1 - c1y = y + stack.shift(); // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y + stack.shift(); // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = jpy + stack.shift(); // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = c3y + stack.shift(); // dy5 - x = c4x + stack.shift(); // dx6 - y = c4y + stack.shift(); // dy6 - stack.shift(); // flex depth - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - if (v == "o1236") { - c1x = x + stack.shift(); // dx1 - c1y = y + stack.shift(); // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y; // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = c2y; // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = c3y + stack.shift(); // dy5 - x = c4x + stack.shift(); // dx6 - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - if (v == "o1237") { - c1x = x + stack.shift(); // dx1 - c1y = y + stack.shift(); // dy1 - c2x = c1x + stack.shift(); // dx2 - c2y = c1y + stack.shift(); // dy2 - jpx = c2x + stack.shift(); // dx3 - jpy = c2y + stack.shift(); // dy3 - c3x = jpx + stack.shift(); // dx4 - c3y = jpy + stack.shift(); // dy4 - c4x = c3x + stack.shift(); // dx5 - c4y = c3y + stack.shift(); // dy5 - if (Math.abs(c4x - x) > Math.abs(c4y - y)) { - x = c4x + stack.shift(); - } else { - y = c4y + stack.shift(); - } - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - } - else if (v == "o14") { - if (stack.length > 0 && stack.length != 4 && !haveWidth) { - width = stack.shift() + font["nominalWidthX"]; - haveWidth = true; - } - if (stack.length == 4) // seac = standard encoding accented character - { - - var asb = 0; - var adx = stack.shift(); - var ady = stack.shift(); - var bchar = stack.shift(); - var achar = stack.shift(); - - - var bind = CFF.glyphBySE(font, bchar); - var aind = CFF.glyphBySE(font, achar); - - //console.log(bchar, bind); - //console.log(achar, aind); - //state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; - - Typr["U"]["_drawCFF"](font["CharStrings"][bind], state, font, pdct, p); - state.x = adx; state.y = ady; - Typr["U"]["_drawCFF"](font["CharStrings"][aind], state, font, pdct, p); - - //x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; - } - if (open) { P.ClosePath(p); open = false; } - } - else if (v == "o19" || v == "o20") { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - - i += (nStems + 7) >> 3; - } - - else if (v == "o21") { - if (stack.length > 2 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - - y += stack.pop(); - x += stack.pop(); - - if (open) P.ClosePath(p); - P.MoveTo(p, x, y); open = true; - } - else if (v == "o22") { - if (stack.length > 1 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - - x += stack.pop(); - - if (open) P.ClosePath(p); - P.MoveTo(p, x, y); open = true; - } - else if (v == "o25") { - while (stack.length > 6) { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - - c1x = x + stack.shift(); - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - else if (v == "o26") { - if (stack.length % 2) { - x += stack.shift(); - } - - while (stack.length > 0) { - c1x = x; - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x; - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - - } - else if (v == "o27") { - if (stack.length % 2) { - y += stack.shift(); - } - - while (stack.length > 0) { - c1x = x + stack.shift(); - c1y = y; - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y; - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - } - else if (v == "o10" || v == "o29") // callsubr || callgsubr - { - var obj = (v == "o10" ? pdct : font); - if (stack.length == 0) { console.log("error: empty stack"); } - else { - var ind = stack.pop(); - var subr = obj["Subrs"][ind + obj["Bias"]]; - state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; - Typr["U"]["_drawCFF"](subr, state, font, pdct, p); - x = state.x; y = state.y; nStems = state.nStems; haveWidth = state.haveWidth; width = state.width; open = state.open; - } - } - else if (v == "o30" || v == "o31") // vhcurveto || hvcurveto - { - var count, count1 = stack.length; - var index = 0; - var alternate = v == "o31"; - - count = count1 & ~2; - index += count1 - count; - - while (index < count) { - if (alternate) { - c1x = x + stack.shift(); - c1y = y; - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - y = c2y + stack.shift(); - if (count - index == 5) { x = c2x + stack.shift(); index++; } - else x = c2x; - alternate = false; - } - else { - c1x = x; - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - if (count - index == 5) { y = c2y + stack.shift(); index++; } - else y = c2y; - alternate = true; - } - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - index += 4; - } - } - - else if ((v + "").charAt(0) == "o") { console.log("Unknown operation: " + v, cmds); throw v; } - else stack.push(v); - } - //console.log(cmds); - state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; - }, - - - "SVG": function () { - var M = { - getScale: function (m) { return Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])); }, - translate: function (m, x, y) { M.concat(m, [1, 0, 0, 1, x, y]); }, - rotate: function (m, a) { M.concat(m, [Math.cos(a), -Math.sin(a), Math.sin(a), Math.cos(a), 0, 0]); }, - scale: function (m, x, y) { M.concat(m, [x, 0, 0, y, 0, 0]); }, - concat: function (m, w) { - var a = m[0], b = m[1], c = m[2], d = m[3], tx = m[4], ty = m[5]; - m[0] = (a * w[0]) + (b * w[2]); m[1] = (a * w[1]) + (b * w[3]); - m[2] = (c * w[0]) + (d * w[2]); m[3] = (c * w[1]) + (d * w[3]); - m[4] = (tx * w[0]) + (ty * w[2]) + w[4]; m[5] = (tx * w[1]) + (ty * w[3]) + w[5]; - }, - invert: function (m) { - var a = m[0], b = m[1], c = m[2], d = m[3], tx = m[4], ty = m[5], adbc = a * d - b * c; - m[0] = d / adbc; m[1] = -b / adbc; m[2] = -c / adbc; m[3] = a / adbc; - m[4] = (c * ty - d * tx) / adbc; m[5] = (b * tx - a * ty) / adbc; - }, - multPoint: function (m, p) { var x = p[0], y = p[1]; return [x * m[0] + y * m[2] + m[4], x * m[1] + y * m[3] + m[5]]; }, - multArray: function (m, a) { for (var i = 0; i < a.length; i += 2) { var x = a[i], y = a[i + 1]; a[i] = x * m[0] + y * m[2] + m[4]; a[i + 1] = x * m[1] + y * m[3] + m[5]; } } - } - - function _bracketSplit(str, lbr, rbr) { - var out = [], pos = 0, ci = 0, lvl = 0; - while (true) { //throw "e"; - var li = str.indexOf(lbr, ci); - var ri = str.indexOf(rbr, ci); - if (li == -1 && ri == -1) break; - if (ri == -1 || (li != -1 && li < ri)) { - if (lvl == 0) { out.push(str.slice(pos, li).trim()); pos = li + 1; } - lvl++; ci = li + 1; - } - else if (li == -1 || (ri != -1 && ri < li)) { - lvl--; - if (lvl == 0) { out.push(str.slice(pos, ri).trim()); pos = ri + 1; } - ci = ri + 1; - } - } - return out; - } - //"cssMap": - function cssMap(str) { - var pts = _bracketSplit(str, "{", "}"); - var css = {}; - for (var i = 0; i < pts.length; i += 2) { - var cn = pts[i].split(","); - for (var j = 0; j < cn.length; j++) { - var cnj = cn[j].trim(); if (css[cnj] == null) css[cnj] = ""; - css[cnj] += pts[i + 1]; - } - } - return css; - } - //"readTrnf" - function readTrnf(trna) { - var pts = _bracketSplit(trna, "(", ")"); - var m = [1, 0, 0, 1, 0, 0]; - for (var i = 0; i < pts.length; i += 2) { var om = m; m = _readTrnsAttr(pts[i], pts[i + 1]); M.concat(m, om); } - return m; - } - - function _readTrnsAttr(fnc, vls) { - //console.log(vls); - //vls = vls.replace(/\-/g, " -").trim(); - var m = [1, 0, 0, 1, 0, 0], gotSep = true; - for (var i = 0; i < vls.length; i++) { // matrix(.99915 0 0 .99915.418.552) matrix(1 0 0-.9474-22.535 271.03) - var ch = vls.charAt(i); - if (ch == "," || ch == " ") gotSep = true; - else if (ch == ".") { - if (!gotSep) { vls = vls.slice(0, i) + "," + vls.slice(i); i++; } gotSep = false; - } - else if (ch == "-" && i > 0 && vls[i - 1] != "e") { vls = vls.slice(0, i) + " " + vls.slice(i); i++; gotSep = true; } - } - - vls = vls.split(/\s*[\s,]\s*/).map(parseFloat); - if (false) { } - else if (fnc == "translate") { if (vls.length == 1) M.translate(m, vls[0], 0); else M.translate(m, vls[0], vls[1]); } - else if (fnc == "scale") { if (vls.length == 1) M.scale(m, vls[0], vls[0]); else M.scale(m, vls[0], vls[1]); } - else if (fnc == "rotate") { var tx = 0, ty = 0; if (vls.length != 1) { tx = vls[1]; ty = vls[2]; } M.translate(m, -tx, -ty); M.rotate(m, -Math.PI * vls[0] / 180); M.translate(m, tx, ty); } - else if (fnc == "matrix") m = vls; - else console.log("unknown transform: ", fnc); - return m; - } - - function toPath(svg, gid) { - var pth = { cmds: [], crds: [] }; - - var vb = svg.getAttribute("viewBox"); - if (vb) vb = vb.trim().split(" ").map(parseFloat); else vb = [0, 0, 1000, 1000]; - - var nod = svg; - if (gid != null) { var nd = svg.getElementById("glyph" + gid); if (nd) nod = nd; } - - _toPath(nod.children, pth, null, svg); - for (var i = 0; i < pth.crds.length; i += 2) { - var x = pth.crds[i], y = pth.crds[i + 1]; - x -= vb[0]; - y -= vb[1]; - y = -y; - pth.crds[i] = x; - pth.crds[i + 1] = y; - } - return pth; - } - - var cmap = { - "aliceblue": "#f0f8ff", "antiquewhite": "#faebd7", "aqua": "#00ffff", "aquamarine": "#7fffd4", "azure": "#f0ffff", "beige": "#f5f5dc", "bisque": "#ffe4c4", - "black": "#000000", "blanchedalmond": "#ffebcd", "blue": "#0000ff", "blueviolet": "#8a2be2", "brown": "#a52a2a", "burlywood": "#deb887", "cadetblue": "#5f9ea0", - "chartreuse": "#7fff00", "chocolate": "#d2691e", "coral": "#ff7f50", "cornflowerblue": "#6495ed", "cornsilk": "#fff8dc", "crimson": "#dc143c", "cyan": "#00ffff", - "darkblue": "#00008b", "darkcyan": "#008b8b", "darkgoldenrod": "#b8860b", "darkgray": "#a9a9a9", "darkgreen": "#006400", "darkgrey": "#a9a9a9", "darkkhaki": "#bdb76b", - "darkmagenta": "#8b008b", "darkolivegreen": "#556b2f", "darkorange": "#ff8c00", "darkorchid": "#9932cc", "darkred": "#8b0000", "darksalmon": "#e9967a", "darkseagreen": "#8fbc8f", - "darkslateblue": "#483d8b", "darkslategray": "#2f4f4f", "darkslategrey": "#2f4f4f", "darkturquoise": "#00ced1", "darkviolet": "#9400d3", "deeppink": "#ff1493", - "deepskyblue": "#00bfff", "dimgray": "#696969", "dimgrey": "#696969", "dodgerblue": "#1e90ff", "firebrick": "#b22222", "floralwhite": "#fffaf0", "forestgreen": "#228b22", - "fuchsia": "#ff00ff", "gainsboro": "#dcdcdc", "ghostwhite": "#f8f8ff", "gold": "#ffd700", "goldenrod": "#daa520", "gray": "#808080", "green": "#008000", "greenyellow": "#adff2f", - "grey": "#808080", "honeydew": "#f0fff0", "hotpink": "#ff69b4", "indianred": "#cd5c5c", "indigo": "#4b0082", "ivory": "#fffff0", "khaki": "#f0e68c", "lavender": "#e6e6fa", - "lavenderblush": "#fff0f5", "lawngreen": "#7cfc00", "lemonchiffon": "#fffacd", "lightblue": "#add8e6", "lightcoral": "#f08080", "lightcyan": "#e0ffff", - "lightgoldenrodyellow": "#fafad2", "lightgray": "#d3d3d3", "lightgreen": "#90ee90", "lightgrey": "#d3d3d3", "lightpink": "#ffb6c1", "lightsalmon": "#ffa07a", - "lightseagreen": "#20b2aa", "lightskyblue": "#87cefa", "lightslategray": "#778899", "lightslategrey": "#778899", "lightsteelblue": "#b0c4de", "lightyellow": "#ffffe0", - "lime": "#00ff00", "limegreen": "#32cd32", "linen": "#faf0e6", "magenta": "#ff00ff", "maroon": "#800000", "mediumaquamarine": "#66cdaa", "mediumblue": "#0000cd", - "mediumorchid": "#ba55d3", "mediumpurple": "#9370db", "mediumseagreen": "#3cb371", "mediumslateblue": "#7b68ee", "mediumspringgreen": "#00fa9a", - "mediumturquoise": "#48d1cc", "mediumvioletred": "#c71585", "midnightblue": "#191970", "mintcream": "#f5fffa", "mistyrose": "#ffe4e1", "moccasin": "#ffe4b5", - "navajowhite": "#ffdead", "navy": "#000080", "oldlace": "#fdf5e6", "olive": "#808000", "olivedrab": "#6b8e23", "orange": "#ffa500", "orangered": "#ff4500", - "orchid": "#da70d6", "palegoldenrod": "#eee8aa", "palegreen": "#98fb98", "paleturquoise": "#afeeee", "palevioletred": "#db7093", "papayawhip": "#ffefd5", - "peachpuff": "#ffdab9", "peru": "#cd853f", "pink": "#ffc0cb", "plum": "#dda0dd", "powderblue": "#b0e0e6", "purple": "#800080", "rebeccapurple": "#663399", "red": "#ff0000", - "rosybrown": "#bc8f8f", "royalblue": "#4169e1", "saddlebrown": "#8b4513", "salmon": "#fa8072", "sandybrown": "#f4a460", "seagreen": "#2e8b57", "seashell": "#fff5ee", - "sienna": "#a0522d", "silver": "#c0c0c0", "skyblue": "#87ceeb", "slateblue": "#6a5acd", "slategray": "#708090", "slategrey": "#708090", "snow": "#fffafa", "springgreen": "#00ff7f", - "steelblue": "#4682b4", "tan": "#d2b48c", "teal": "#008080", "thistle": "#d8bfd8", "tomato": "#ff6347", "turquoise": "#40e0d0", "violet": "#ee82ee", "wheat": "#f5deb3", - "white": "#ffffff", "whitesmoke": "#f5f5f5", "yellow": "#ffff00", "yellowgreen": "#9acd32" - }; - - function _toPath(nds, pth, fill, root) { - for (var ni = 0; ni < nds.length; ni++) { - var nd = nds[ni], tn = nd.tagName; - var cfl = nd.getAttribute("fill"); if (cfl == null) cfl = fill; - if (cfl && cfl.startsWith("url")) { - var gid = cfl.slice(5, -1); - var grd = root.getElementById(gid), s0 = grd.children[0]; - if (s0.getAttribute("stop-opacity") != null) continue; - cfl = s0.getAttribute("stop-color"); - } - if (cmap[cfl]) cfl = cmap[cfl]; - if (tn == "g" || tn == "use") { - var tp = { crds: [], cmds: [] }; - if (tn == "g") _toPath(nd.children, tp, cfl, root); - else { - var lnk = nd.getAttribute("xlink:href").slice(1); - var pel = root.getElementById(lnk); - _toPath([pel], tp, cfl, root); - } - var m = [1, 0, 0, 1, 0, 0]; - var x = nd.getAttribute("x"), y = nd.getAttribute("y"); x = x ? parseFloat(x) : 0; y = y ? parseFloat(y) : 0; - M.concat(m, [1, 0, 0, 1, x, y]); - - var trf = nd.getAttribute("transform"); if (trf) M.concat(m, readTrnf(trf)); - - M.multArray(m, tp.crds); - pth.crds = pth.crds.concat(tp.crds); - pth.cmds = pth.cmds.concat(tp.cmds); - } - else if (tn == "path" || tn == "circle" || tn == "ellipse") { - pth.cmds.push(cfl ? cfl : "#000000"); - var d; - if (tn == "path") d = nd.getAttribute("d"); //console.log(d); - if (tn == "circle" || tn == "ellipse") { - var vls = [0, 0, 0, 0], nms = ["cx", "cy", "rx", "ry", "r"]; - for (var i = 0; i < 5; i++) { var V = nd.getAttribute(nms[i]); if (V) { V = parseFloat(V); if (i < 4) vls[i] = V; else vls[2] = vls[3] = V; } } - var cx = vls[0], cy = vls[1], rx = vls[2], ry = vls[3]; - d = ["M", cx - rx, cy, "a", rx, ry, 0, 1, 0, rx * 2, 0, "a", rx, ry, 0, 1, 0, -rx * 2, 0].join(" "); - } - svgToPath(d, pth); pth.cmds.push("X"); - } - else if (tn == "image") { - var w = parseFloat(nd.getAttribute("width")), h = parseFloat(nd.getAttribute("height")); - pth.cmds.push(nd.getAttribute("xlink:href")); - pth.crds.push(0, 0, w, 0, w, h, 0, h); - } - else if (tn == "defs") { } - else console.log(tn); - } - } - - function _tokens(d) { - var ts = [], off = 0, rn = false, cn = "", pc = "", lc = "", nc = 0; // reading number, current number, prev char, lastCommand, number count (after last command - while (off < d.length) { - var cc = d.charCodeAt(off), ch = d.charAt(off); off++; - var isNum = (48 <= cc && cc <= 57) || ch == "." || ch == "-" || ch == "+" || ch == "e" || ch == "E"; - - if (rn) { - if (((ch == "+" || ch == "-") && pc != "e") || (ch == "." && cn.indexOf(".") != -1) || (isNum && (lc == "a" || lc == "A") && ((nc % 7) == 3 || (nc % 7) == 4))) { ts.push(parseFloat(cn)); nc++; cn = ch; } - else if (isNum) cn += ch; - else { ts.push(parseFloat(cn)); nc++; if (ch != "," && ch != " ") { ts.push(ch); lc = ch; nc = 0; } rn = false; } - } - else { - if (isNum) { cn = ch; rn = true; } - else if (ch != "," && ch != " ") { ts.push(ch); lc = ch; nc = 0; } - } - pc = ch; - } - if (rn) ts.push(parseFloat(cn)); - return ts; - } - - function _reps(ts, off, ps) { - var i = off; - while (i < ts.length) { if ((typeof ts[i]) == "string") break; i += ps; } - return (i - off) / ps; - } - - function svgToPath(d, pth) { - var ts = _tokens(d); - var i = 0, x = 0, y = 0, ox = 0, oy = 0, oldo = pth.crds.length; - var pc = { "M": 2, "L": 2, "H": 1, "V": 1, "T": 2, "S": 4, "A": 7, "Q": 4, "C": 6 }; - var cmds = pth.cmds, crds = pth.crds; - - while (i < ts.length) { - var cmd = ts[i]; i++; - var cmu = cmd.toUpperCase(); - - if (cmu == "Z") { cmds.push("Z"); x = ox; y = oy; } - else { - var ps = pc[cmu], reps = _reps(ts, i, ps); - - for (var j = 0; j < reps; j++) { - // If a moveto is followed by multiple pairs of coordinates, the subsequent pairs are treated as implicit lineto commands. - if (j == 1 && cmu == "M") { cmd = (cmd == cmu) ? "L" : "l"; cmu = "L"; } - - var xi = 0, yi = 0; if (cmd != cmu) { xi = x; yi = y; } - - if (false) { } - else if (cmu == "M") { x = xi + ts[i++]; y = yi + ts[i++]; cmds.push("M"); crds.push(x, y); ox = x; oy = y; } - else if (cmu == "L") { x = xi + ts[i++]; y = yi + ts[i++]; cmds.push("L"); crds.push(x, y); } - else if (cmu == "H") { x = xi + ts[i++]; cmds.push("L"); crds.push(x, y); } - else if (cmu == "V") { y = yi + ts[i++]; cmds.push("L"); crds.push(x, y); } - else if (cmu == "Q") { - var x1 = xi + ts[i++], y1 = yi + ts[i++], x2 = xi + ts[i++], y2 = yi + ts[i++]; - cmds.push("Q"); crds.push(x1, y1, x2, y2); x = x2; y = y2; - } - else if (cmu == "T") { - var co = Math.max(crds.length - (cmds[cmds.length - 1] == "Q" ? 4 : 2), oldo); - var x1 = x + x - crds[co], y1 = y + y - crds[co + 1]; - var x2 = xi + ts[i++], y2 = yi + ts[i++]; - cmds.push("Q"); crds.push(x1, y1, x2, y2); x = x2; y = y2; - } - else if (cmu == "C") { - var x1 = xi + ts[i++], y1 = yi + ts[i++], x2 = xi + ts[i++], y2 = yi + ts[i++], x3 = xi + ts[i++], y3 = yi + ts[i++]; - cmds.push("C"); crds.push(x1, y1, x2, y2, x3, y3); x = x3; y = y3; - } - else if (cmu == "S") { - var co = Math.max(crds.length - (cmds[cmds.length - 1] == "C" ? 4 : 2), oldo); - var x1 = x + x - crds[co], y1 = y + y - crds[co + 1]; - var x2 = xi + ts[i++], y2 = yi + ts[i++], x3 = xi + ts[i++], y3 = yi + ts[i++]; - cmds.push("C"); crds.push(x1, y1, x2, y2, x3, y3); x = x3; y = y3; - } - else if (cmu == "A") { // convert SVG Arc to four cubic bézier segments "C" - var x1 = x, y1 = y; - var rx = ts[i++], ry = ts[i++]; - var phi = ts[i++] * (Math.PI / 180), fA = ts[i++], fS = ts[i++]; - var x2 = xi + ts[i++], y2 = yi + ts[i++]; - if (x2 == x && y2 == y && rx == 0 && ry == 0) continue; - - var hdx = (x1 - x2) / 2, hdy = (y1 - y2) / 2; - var cosP = Math.cos(phi), sinP = Math.sin(phi); - var x1A = cosP * hdx + sinP * hdy; - var y1A = -sinP * hdx + cosP * hdy; - - var rxS = rx * rx, ryS = ry * ry; - var x1AS = x1A * x1A, y1AS = y1A * y1A; - var frc = (rxS * ryS - rxS * y1AS - ryS * x1AS) / (rxS * y1AS + ryS * x1AS); - var coef = (fA != fS ? 1 : -1) * Math.sqrt(Math.max(frc, 0)); - var cxA = coef * (rx * y1A) / ry; - var cyA = -coef * (ry * x1A) / rx; - - var cx = cosP * cxA - sinP * cyA + (x1 + x2) / 2; - var cy = sinP * cxA + cosP * cyA + (y1 + y2) / 2; - - var angl = function (ux, uy, vx, vy) { - var lU = Math.sqrt(ux * ux + uy * uy), lV = Math.sqrt(vx * vx + vy * vy); - var num = (ux * vx + uy * vy) / (lU * lV); //console.log(num, Math.acos(num)); - return (ux * vy - uy * vx >= 0 ? 1 : -1) * Math.acos(Math.max(-1, Math.min(1, num))); - } - - var vX = (x1A - cxA) / rx, vY = (y1A - cyA) / ry; - var theta1 = angl(1, 0, vX, vY); - var dtheta = angl(vX, vY, (-x1A - cxA) / rx, (-y1A - cyA) / ry); - dtheta = dtheta % (2 * Math.PI); - - var arc = function (gst, x, y, r, a0, a1, neg) { - var rotate = function (m, a) { - var si = Math.sin(a), co = Math.cos(a); - var a = m[0], b = m[1], c = m[2], d = m[3]; - m[0] = (a * co) + (b * si); m[1] = (-a * si) + (b * co); - m[2] = (c * co) + (d * si); m[3] = (-c * si) + (d * co); - } - var multArr = function (m, a) { - for (var j = 0; j < a.length; j += 2) { - var x = a[j], y = a[j + 1]; - a[j] = m[0] * x + m[2] * y + m[4]; - a[j + 1] = m[1] * x + m[3] * y + m[5]; - } - } - var concatA = function (a, b) { for (var j = 0; j < b.length; j++) a.push(b[j]); } - var concatP = function (p, r) { concatA(p.cmds, r.cmds); concatA(p.crds, r.crds); } - // circle from a0 counter-clock-wise to a1 - if (neg) while (a1 > a0) a1 -= 2 * Math.PI; - else while (a1 < a0) a1 += 2 * Math.PI; - var th = (a1 - a0) / 4; - - var x0 = Math.cos(th / 2), y0 = -Math.sin(th / 2); - var x1 = (4 - x0) / 3, y1 = y0 == 0 ? y0 : (1 - x0) * (3 - x0) / (3 * y0); - var x2 = x1, y2 = -y1; - var x3 = x0, y3 = -y0; - - var ps = [x1, y1, x2, y2, x3, y3]; - - var pth = { cmds: ["C", "C", "C", "C"], crds: ps.slice(0) }; - var rot = [1, 0, 0, 1, 0, 0]; rotate(rot, -th); - for (var j = 0; j < 3; j++) { multArr(rot, ps); concatA(pth.crds, ps); } - - rotate(rot, -a0 + th / 2); rot[0] *= r; rot[1] *= r; rot[2] *= r; rot[3] *= r; rot[4] = x; rot[5] = y; - multArr(rot, pth.crds); - multArr(gst.ctm, pth.crds); - concatP(gst.pth, pth); - } - - var gst = { pth: pth, ctm: [rx * cosP, rx * sinP, -ry * sinP, ry * cosP, cx, cy] }; - arc(gst, 0, 0, 1, theta1, theta1 + dtheta, fS == 0); - x = x2; y = y2; - } - else console.log("Unknown SVG command " + cmd); - } - } - } - }; - return { "cssMap": cssMap, "readTrnf": readTrnf, svgToPath: svgToPath, toPath: toPath }; - }(), - - - - - "initHB": function (hurl, resp) { - var codeLength = function (code) { - var len = 0; - if ((code & (0xffffffff - (1 << 7) + 1)) == 0) { len = 1; } - else if ((code & (0xffffffff - (1 << 11) + 1)) == 0) { len = 2; } - else if ((code & (0xffffffff - (1 << 16) + 1)) == 0) { len = 3; } - else if ((code & (0xffffffff - (1 << 21) + 1)) == 0) { len = 4; } - return len; - } - - fetch(hurl) - .then(function (x) { return x["arrayBuffer"](); }) - .then(function (ab) { return WebAssembly["instantiate"](ab); }) - .then(function (res) { - console.log("HB ready"); - var exp = res["instance"]["exports"], mem = exp["memory"]; - //mem["grow"](30); // each page is 64kb in size - var heapu8, u32, i32; - var __lastFnt, blob, blobPtr, face, font; - - Typr["U"]["shapeHB"] = (function () { - - var toJson = function (ptr) { - var length = exp["hb_buffer_get_length"](ptr); - var result = []; - var iPtr32 = exp["hb_buffer_get_glyph_infos"](ptr, 0) >>> 2; - var pPtr32 = exp["hb_buffer_get_glyph_positions"](ptr, 0) >>> 2; - for (var i = 0; i < length; ++i) { - var a = iPtr32 + i * 5, b = pPtr32 + i * 5; - result.push({ - "g": u32[a + 0], - "cl": u32[a + 2], - "ax": i32[b + 0], - "ay": i32[b + 1], - "dx": i32[b + 2], - "dy": i32[b + 3] - }); - } - //console.log(result); - return result; - } - var te; - - return function (fnt, str, ltr) { - var fdata = fnt["_data"], fn = fnt["name"]["postScriptName"]; - - //var olen = mem.buffer.byteLength, nlen = 2*fdata.length+str.length*16 + 4e6; - //if(olen>>16)+4); //console.log("growing",nlen); - - heapu8 = new Uint8Array(mem.buffer); - u32 = new Uint32Array(mem.buffer); - i32 = new Int32Array(mem.buffer); - - if (__lastFnt != fn) { - if (blob != null) { - exp["hb_blob_destroy"](blob); - exp["free"](blobPtr); - exp["hb_face_destroy"](face); - exp["hb_font_destroy"](font); - } - blobPtr = exp["malloc"](fdata.byteLength); heapu8.set(fdata, blobPtr); - blob = exp["hb_blob_create"](blobPtr, fdata.byteLength, 2, 0, 0); - face = exp["hb_face_create"](blob, 0); - font = exp["hb_font_create"](face) - __lastFnt = fn; - } - if (window["TextEncoder"] == null) { alert("Your browser is too old. Please, update it."); return; } - if (te == null) te = new window["TextEncoder"]("utf8"); - - var buffer = exp["hb_buffer_create"](); - var bytes = te["encode"](str); - var len = bytes.length, strp = exp["malloc"](len); heapu8.set(bytes, strp); - exp["hb_buffer_add_utf8"](buffer, strp, len, 0, len); - exp["free"](strp); - - exp["hb_buffer_set_direction"](buffer, ltr ? 4 : 5); - exp["hb_buffer_guess_segment_properties"](buffer); - exp["hb_shape"](font, buffer, 0, 0); - var json = toJson(buffer)//buffer["json"](); - exp["hb_buffer_destroy"](buffer); - - var arr = json.slice(0); if (!ltr) arr.reverse(); - var ci = 0, bi = 0; // character index, binary index - for (var i = 1; i < arr.length; i++) { - var gl = arr[i], cl = gl["cl"]; - while (true) { - var cpt = str.codePointAt(ci), cln = codeLength(cpt); - if (bi + cln <= cl) { bi += cln; ci += cpt <= 0xffff ? 1 : 2; } - else break; - } - //while(bi+codeLength(str.charCodeAt(ci)) <=cl) { bi+=codeLength(str.charCodeAt(ci)); ci++; } - gl["cl"] = ci; - } - return json; - } - }()); - resp(); - }); - } -} +Typr["T"].fvar = { + parseTab : function(data, offset, length, obj) + { + var name = obj["name"]; + var off = offset; + var bin = Typr["B"]; + var axes = [], inst=[]; + + off+=8; + var acnt = bin.readUshort(data,off); off+=2; + off+=2; + var icnt = bin.readUshort(data,off); off+=2; + var isiz = bin.readUshort(data,off); off+=2; + + for(var i=0; i>>12)!=0) throw "e"; + + var snum = vcnt&SHARED_POINT_NUMBERS; vcnt&=0xfff; + // offset to the serialized data + var soff = bin.readUshort(data,off); off+=2; + + var hdr = readTupleVarHeader(data,off,vcnt,acnt, offset+goff+offs[i+1]); + + var tab = []; tabs.push(tab); + // Serialized Data + off=offset + goff + offs[i] + soff; + + var sind = null; + if(snum) { + var oo = readPointNumbers(data,off,i); + sind=oo[0]; off=oo[1]; + } + + for(var j=0; j> 4) + 1; //if(entrySize!=1) throw entrySize; + + //console.log(fmt, entryFormat, mapCount, entrySize); + + var dfs=[]; + for(var i=0; i> ((entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1); + var innerIndex = entry & ((1 << ((entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1)) - 1); + //map.push(outerIndex,innerIndex); + dfs.push(varStore[outerIndex][innerIndex]); + //console.log(outerIndex,innerIndex); + //console.log(i,varStore[outerIndex][innerIndex]); + } + + return [regs,dfs]; + } +}; \ No newline at end of file From a30722c7ea4146049db0f4d1d461d4d7f62d0e8a Mon Sep 17 00:00:00 2001 From: dhowe Date: Mon, 23 Dec 2024 15:16:56 -0500 Subject: [PATCH 03/27] add pako to support woff font decompression --- package-lock.json | 18 +++++++++++++----- package.json | 3 ++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index 361236241e..9a0cbede14 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,8 @@ "gifenc": "^1.0.3", "libtess": "^1.2.2", "omggif": "^1.0.10", - "opentype.js": "^1.3.1" + "opentype.js": "^1.3.1", + "pako": "^2.1.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", @@ -6298,6 +6299,13 @@ "setimmediate": "^1.0.5" } }, + "node_modules/jszip/node_modules/pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", + "dev": true, + "license": "(MIT AND Zlib)" + }, "node_modules/jszip/node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -8246,10 +8254,10 @@ "dev": true }, "node_modules/pako": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", - "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==", - "dev": true + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz", + "integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==", + "license": "(MIT AND Zlib)" }, "node_modules/parent-module": { "version": "1.0.1", diff --git a/package.json b/package.json index 9bb4916f0c..5461c57510 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,8 @@ "gifenc": "^1.0.3", "libtess": "^1.2.2", "omggif": "^1.0.10", - "opentype.js": "^1.3.1" + "opentype.js": "^1.3.1", + "pako": "^2.1.0" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", From 679b7f17a6535c5ccfe3f60154e10360e4aa7c92 Mon Sep 17 00:00:00 2001 From: dhowe Date: Mon, 23 Dec 2024 19:06:52 -0500 Subject: [PATCH 04/27] add default export for Typr --- src/type/lib/Typr.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/type/lib/Typr.js b/src/type/lib/Typr.js index cfabeb9b5b..ad5fd739c7 100644 --- a/src/type/lib/Typr.js +++ b/src/type/lib/Typr.js @@ -1934,4 +1934,6 @@ Typr["T"].HVAR = { return [regs,dfs]; } -}; \ No newline at end of file +}; + +export default Typr; From cf69c7f732dcb00843d41db5f15b0638ce9a5979 Mon Sep 17 00:00:00 2001 From: dhowe Date: Wed, 25 Dec 2024 12:14:52 -0500 Subject: [PATCH 05/27] integrating updated Typr --- src/type/p5.Font.js | 15 ++++++++++----- test/unit/visual/cases/typography.js | 13 +++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index 044166e6e7..34ef0a6661 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -29,16 +29,18 @@ * This module defines the p5.Font class and p5 methods for * loading fonts from files and urls, and extracting points from their paths. */ + +// import Typr import Typr from './lib/Typr.js'; import { createFromCommands } from '@davepagurek/bezier-path'; function font(p5, fn) { const pathArgCounts = { M: 2, L: 2, C: 6, Q: 4 }; - const validFontTypes = ['ttf', 'otf', 'woff', 'woff2']; + const validFontTypes = ['ttf', 'otf', 'woff'];//, 'woff2']; const validFontTypesRe = new RegExp(`\\.(${validFontTypes.join('|')})`, 'i'); const extractFontNameRe = new RegExp(`([^/]+)(\\.(?:${validFontTypes.join('|')}))`, 'i'); - const invalidFontError = 'Sorry, only TTF, OTF, WOFF and WOFF2 files are supported.'; + const invalidFontError = 'Sorry, only TTF, OTF and WOFF files are supported.'; // and WOFF2 const fontFaceVariations = ['weight', 'stretch', 'style']; p5.Font = class Font { @@ -214,7 +216,7 @@ function font(p5, fn) { } /////////////////////////////// HELPERS //////////////////////////////// - + _verticalAlign(size) { const { sCapHeight } = this.data?.['OS/2'] || {}; const { unitsPerEm = 1000 } = this.data?.head || {}; @@ -569,6 +571,8 @@ function font(p5, fn) { try { // load the raw font bytes let result = await fn.loadBytes(path); + console.log('result:', result); + if (!result) { throw Error('Failed to load font data'); } @@ -579,7 +583,7 @@ function font(p5, fn) { // TODO: generate descriptors from font in the future if (fonts.length !== 1 || fonts[0].cmap === undefined) { - throw Error(23); + throw Error('Unable to parse font data'); } // make sure we have a valid name @@ -598,7 +602,8 @@ function font(p5, fn) { console.warn('Failed to parse font data:', err); try { // create a FontFace object and pass it to p5.Font - console.log(`Retrying '${name}' without font-data: '${path}'`); + let ident = name || path.substring(path.lastIndexOf('/') + 1); + console.log(`Retrying '${ident}' without font-data: '${path}'`); pfont = await create(this, name, path, descriptors); } catch (err) { diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index e8984da241..83a242861b 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -43,6 +43,19 @@ visualSuite("Typography", function () { screenshot(); }); + visualTest('with a woff font file', async function (p5, screenshot) { + p5.createCanvas(100, 100); + const font = await p5.loadFont( + '/unit/assets/Lato-Regular.woff' + ); + p5.textFont(font); + p5.textAlign(p5.LEFT, p5.TOP); + p5.textSize(35); + p5.text('p5*js', 0, 10, p5.width); + screenshot(); + }); + + visualTest('with a font file in WebGL', async function(p5, screenshot) { p5.createCanvas(100, 100, p5.WEBGL); const font = await p5.loadFont( From 4c25a62208b5440c30b621b0aedd19d409ef4a4d Mon Sep 17 00:00:00 2001 From: dhowe Date: Wed, 25 Dec 2024 12:37:43 -0500 Subject: [PATCH 06/27] fix ^ bug in direct set with font strings --- src/type/p5.Font.js | 20 +++++++------------- src/type/text2d.js | 7 ++++++- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index 34ef0a6661..245cb440ac 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -571,7 +571,7 @@ function font(p5, fn) { try { // load the raw font bytes let result = await fn.loadBytes(path); - console.log('result:', result); + //console.log('result:', result); if (!result) { throw Error('Failed to load font data'); @@ -583,15 +583,13 @@ function font(p5, fn) { // TODO: generate descriptors from font in the future if (fonts.length !== 1 || fonts[0].cmap === undefined) { - throw Error('Unable to parse font data'); + throw Error('parsing font data'); } // make sure we have a valid name if (!name) { name = extractFontName(fonts[0], path); - if (name.includes(' ')) { - name = name.replace(/ /g, '_'); - } + if (name.includes(' ')) name = name.replace(/ /g, '_'); } // create a FontFace object and pass it to the p5.Font constructor @@ -599,23 +597,19 @@ function font(p5, fn) { } catch (err) { // failed to parse the font, load it as a simple FontFace - console.warn('Failed to parse font data:', err); + let ident = name || path.substring(path.lastIndexOf('/') + 1); + console.warn(`WARNING: No font data for '${ident}'`); try { // create a FontFace object and pass it to p5.Font - let ident = name || path.substring(path.lastIndexOf('/') + 1); console.log(`Retrying '${ident}' without font-data: '${path}'`); pfont = await create(this, name, path, descriptors); } catch (err) { - if (error) { - error(err); - } + if (error) error(err); throw err; } } - if (success) { - success(pfont); - } + if (success) success(pfont); return pfont; } diff --git a/src/type/text2d.js b/src/type/text2d.js index a363deea74..f0e088f58b 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -291,7 +291,12 @@ function text2d(p5, fn) { } // check for font-string with size in first arg - if (typeof size === 'undefined' && /^[.0-9]+(%|em|p[xt])/.test(family)) { + console.log('family: ', family, 'size: ', size); + + // removed ^ from regex to allow direct set of font strings including size + if (typeof size === 'undefined' && /[.0-9]+(%|em|p[xt])/.test(family)) { + console.log('direct font string: ', family); + ({ family, size } = this._directSetFontString(family)); } From 4c4dac07ff0959cdfec0035d2044d9f4648b5ca8 Mon Sep 17 00:00:00 2001 From: dhowe Date: Fri, 27 Dec 2024 16:12:29 -0500 Subject: [PATCH 07/27] update Typr, fix bug in fontWidth, textWidth --- src/type/lib/Typr.U.js | 1112 ----- src/type/lib/Typr.js | 4683 +++++++++++++-------- src/type/p5.Font.js | 9 +- src/type/text2d.js | 33 +- test/manual-test-examples/type/index.html | 45 - 5 files changed, 2870 insertions(+), 3012 deletions(-) delete mode 100644 src/type/lib/Typr.U.js diff --git a/src/type/lib/Typr.U.js b/src/type/lib/Typr.U.js deleted file mode 100644 index e0496ed450..0000000000 --- a/src/type/lib/Typr.U.js +++ /dev/null @@ -1,1112 +0,0 @@ - - -Typr["U"] = function() { - var P = { - MoveTo : function(p, x, y) { p.cmds.push("M"); p.crds.push(x,y); }, - LineTo : function(p, x, y) { p.cmds.push("L"); p.crds.push(x,y); }, - CurveTo : function(p, a,b,c,d,e,f) { p.cmds.push("C"); p.crds.push(a,b,c,d,e,f); }, - qCurveTo : function(p, a,b,c,d) { p.cmds.push("Q"); p.crds.push(a,b,c,d); }, - ClosePath : function(p) { p.cmds.push("Z"); } - } - - function getGlyphPosition(font, gls,i1,ltr) { - var g1=gls[i1],g2=gls[i1+1], kern=font["kern"]; - if(kern) { - var ind1 = kern.glyph1.indexOf(g1); - if(ind1!=-1) - { - var ind2 = kern.rval[ind1].glyph2.indexOf(g2); - if(ind2!=-1) return [0,0,kern.rval[ind1].vals[ind2],0]; - } - } - //console.log("no kern"); - return [0,0,0,0]; - } - function shape(font,str,prm) { - var ltr = prm["ltr"], fts = prm["fts"], axs=prm["axs"]; - if(font["fvar"] && axs==null) axs = font["fvar"][1][font["_index"]][2]; - - var HVAR = font["HVAR"]; //console.log(HVAR); - if(axs && HVAR) { axs=_normalizeAxis(font,axs); } //console.log(S,axs); - var gls = []; - for(var i=0; i0xffff) i++; - gls.push(codeToGlyph(font, cc)); - } - var shape = []; - var x = 0, y = 0; - - for(var i=0; i>>1); if(arr[mid*k]<=v) l=mid; else r=mid; } - - //var mi = 0; for(var i=0; i=tab.map.length) gid = 0; - else gid = tab.map[code]; - } - /*else if(fmt==2) { - var data=font["_data"], off = cmap.off+tab.off+6, bin=Typr["B"]; - var shKey = bin.readUshort(data,off + 2*(code>>>8)); - var shInd = off + 256*2 + shKey*8; - - var firstCode = bin.readUshort(data,shInd); - var entryCount= bin.readUshort(data,shInd+2); - var idDelta = bin.readShort (data,shInd+4); - var idRangeOffset = bin.readUshort(data,shInd+6); - - if(firstCode<=code && code<=firstCode+entryCount) { - // not completely correct - gid = bin.readUshort(data, shInd+6+idRangeOffset + (code&255)*2); - } - else gid=0; - //if(code>256) console.log(code,(code>>>8),shKey,firstCode,entryCount,idDelta,idRangeOffset); - - //throw "e"; - //console.log(tab, bin.readUshort(data,off)); - //throw "e"; - }*/ - else if(fmt==4) { - var ec = tab.endCount; gid=0; - if(code<=ec[ec.length-1]) { - // smallest index with code <= value - var sind = arrSearch(ec,1,code); - if(ec[sind]=tab.startCount[sind]) { - var gli = 0; - if(tab.idRangeOffset[sind]!=0) gli = tab.glyphIdArray[(code-tab.startCount[sind]) + (tab.idRangeOffset[sind]>>1) - (tab.idRangeOffset.length-sind)]; - else gli = code + tab.idDelta[sind]; - gid = (gli & 0xFFFF); - } - } - } - else if(fmt==6) { - var off = code-tab.firstCode, arr=tab.glyphIdArray; - if(off<0 || off>=arr.length) gid=0; - else gid = arr[off]; - } - else if(fmt==12) { - var grp = tab.groups; gid=0; //console.log(grp); throw "e"; - - if(code<=grp[grp.length-2]) { - var i = arrSearch(grp,3,code); - if(grp[i]<=code && code<=grp[i+1]) { gid = grp[i+2] + (code-grp[i]); } - } - } - else throw "unknown cmap table format "+tab.format; - - //* - var SVG = font["SVG "], loca = font["loca"]; - // if the font claims to have a Glyph for a character, but the glyph is empty, and the character is not "white", it is a lie! - if(gid!=0 && font["CFF "]==null && (SVG==null || SVG.entries[gid]==null) && loca && loca[gid]==loca[gid+1] // loca not present in CFF or SVG fonts - && whm[code]==null ) gid=0; - //*/ - - return gid; - } - function glyphToPath(font, gid, noColor,axs) { - var path = { cmds:[], crds:[] }; - - if(font["fvar"]) { - if(axs==null) axs = font["fvar"][1][font["_index"]][2]; - axs=_normalizeAxis(font,axs); - } - - var SVG = font["SVG "], CFF = font["CFF "], COLR=font["COLR"], CBLC=font["CBLC"], CBDT=font["CBDT"], sbix=font["sbix"], upng=window["UPNG"]; - - var strike = null; - if(CBLC && upng) for(var i=0; i1) { - - function toHex(n){ var o=n.toString(16); return (o.length==1 ? "0":"")+o; } - - var CPAL = font["CPAL"], gl = COLR[0]["g"+gid]; - for(var i=0; i-1) _simpleGlyph(gl, font, gid, path,axs); - else _compoGlyph (gl, font, gid, path,axs); - } - } - function _interpolate(axs,v) { - var acnt = v.length, S = 1; - var s = axs[0]; // start - var p = axs[1]; // peak - var e = axs[2]; // end - - for(var i=0; i p[i] || p[i] > e[i]) AS = 1; - else if (s[i] < 0 && e[i] > 0 && p[i] != 0) AS = 1; - else if (p[i] == 0) AS = 1; - else if (v[i] < s[i] || v[i] > e[i]) AS = 0; - else { - if (v[i] ==p[i]) AS = 1; - else if (v[i] < p[i]) AS = (v[i] - s[i]) / (p[i] - s[i]); - else AS = (e[i] - v[i]) / (e[i] - p[i]); - } - S = S * AS; - } - return S; - } - function _normalizeAxis(font,vv) { - var fvar = font["fvar"], avar = font["avar"]; - var fv = fvar?fvar[0 ]:null; - - var nv = []; - for(var i=0; idef) nv[i]=(v-def)/(max-def); - else nv[i]=0; - - if(avar && nv[i]!=-1) { - var av = avar[i], j=0; - for(; j=nv[i]) break; - var f=(nv[i]-av[j-2])/(av[j]-av[j-2]); - nv[i] = f*av[j+1] + (1-f)*av[j-1]; - } - - } - return nv; - } - function interpolateDeltas(dfs,ind,xs,ys) { - var N=xs.length, ndfs = new Array(N*2+8); ndfs.fill(0); - for(var i=0; i=N) i0--; - for(var j=0; j=0) no.push(" "); - no.push(it); lstF=isF; - } - return no.join(""); - } - - - var out = [], co = 0, lmap = {"M":2,"L":2,"Q":4,"C":6}; - var x =0, y =0, // perfect coords - //dx=0, dy=0, // relative perfect coords - //rx=0, ry=0, // relative rounded coords - ex=0, ey=0, // error between perfect and output coords - mx=0, my=0; // perfect coords of the last "Move" - - for(var i=0; i>1, nh = h>>1; - var nbuf = (hlp && hlp.length==nw*nh*4) ? hlp : new Uint8Array(nw*nh*4); - var sb32 = new Uint32Array(buff.buffer), nb32 = new Uint32Array(nbuf.buffer); - for(var y=0; y>>24), a1 = (c1>>>24), a2 = (c2>>>24), a3 = (c3>>>24), a = (a0+a1+a2+a3); - - if(a==1020) { - var r = (((c0>>> 0)&255) + ((c1>>> 0)&255) + ((c2>>> 0)&255) + ((c3>>> 0)&255)+2)>>>2; - var g = (((c0>>> 8)&255) + ((c1>>> 8)&255) + ((c2>>> 8)&255) + ((c3>>> 8)&255)+2)>>>2; - var b = (((c0>>>16)&255) + ((c1>>>16)&255) + ((c2>>>16)&255) + ((c3>>>16)&255)+2)>>>2; - nb32[ti] = (255<<24) | (b<<16) | (g<<8) | r; - } - else if(a==0) nb32[ti] = 0; - else { - var r = ((c0>>> 0)&255)*a0 + ((c1>>> 0)&255)*a1 + ((c2>>> 0)&255)*a2 + ((c3>>> 0)&255)*a3; - var g = ((c0>>> 8)&255)*a0 + ((c1>>> 8)&255)*a1 + ((c2>>> 8)&255)*a2 + ((c3>>> 8)&255)*a3; - var b = ((c0>>>16)&255)*a0 + ((c1>>>16)&255)*a1 + ((c2>>>16)&255)*a2 + ((c3>>>16)&255)*a3; - - var ia = 1/a; r = ~~(r*ia+0.5); g = ~~(g*ia+0.5); b = ~~(b*ia+0.5); - nb32[ti] = (((a+2)>>>2)<<24) | (b<<16) | (g<<8) | r; - } - } - return { buff:nbuf, w:nw, h:nh }; - } - - var __cnv, __ct; - function pathToContext(path, ctx) { - var c = 0, cmds = path["cmds"], crds = path["crds"]; - - //ctx.translate(3500,500); ctx.rotate(0.25); ctx.scale(1,-1); - - for(var j=0; j> 1; - stack.length = 0; - haveWidth = true; - } - else if(v=="o3" || v=="o23") // vstem || vstemhm - { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - } - else if(v=="o4") - { - if (stack.length > 1 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - if(open) P.ClosePath(p); - - y += stack.pop(); - P.MoveTo(p,x,y); open=true; - } - else if(v=="o5") - { - while (stack.length > 0) { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - } - else if(v=="o6" || v=="o7") // hlineto || vlineto - { - var count = stack.length; - var isX = (v == "o6"); - - for(var j=0; j Math.abs(c4y - y)) { - x = c4x + stack.shift(); - } else { - y = c4y + stack.shift(); - } - P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); - P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); - } - } - else if(v=="o14") - { - if (stack.length > 0 && stack.length!=4 && !haveWidth) { - width = stack.shift() + font["nominalWidthX"]; - haveWidth = true; - } - if(stack.length==4) // seac = standard encoding accented character - { - - var asb = 0; - var adx = stack.shift(); - var ady = stack.shift(); - var bchar = stack.shift(); - var achar = stack.shift(); - - - var bind = CFF.glyphBySE(font, bchar); - var aind = CFF.glyphBySE(font, achar); - - //console.log(bchar, bind); - //console.log(achar, aind); - //state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; - - _drawCFF(font["CharStrings"][bind], state,font,pdct,p); - state.x = adx; state.y = ady; - _drawCFF(font["CharStrings"][aind], state,font,pdct,p); - - //x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; - } - if(open) { P.ClosePath(p); open=false; } - } - else if(v=="o19" || v=="o20") - { - var hasWidthArg; - - // The number of stem operators on the stack is always even. - // If the value is uneven, that means a width is specified. - hasWidthArg = stack.length % 2 !== 0; - if (hasWidthArg && !haveWidth) { - width = stack.shift() + nominalWidthX; - } - - nStems += stack.length >> 1; - stack.length = 0; - haveWidth = true; - - i += (nStems + 7) >> 3; - } - - else if(v=="o21") { - if (stack.length > 2 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - - y += stack.pop(); - x += stack.pop(); - - if(open) P.ClosePath(p); - P.MoveTo(p,x,y); open=true; - } - else if(v=="o22") - { - if (stack.length > 1 && !haveWidth) { - width = stack.shift() + nominalWidthX; - haveWidth = true; - } - - x += stack.pop(); - - if(open) P.ClosePath(p); - P.MoveTo(p,x,y); open=true; - } - else if(v=="o25") - { - while (stack.length > 6) { - x += stack.shift(); - y += stack.shift(); - P.LineTo(p, x, y); - } - - c1x = x + stack.shift(); - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - else if(v=="o26") - { - if (stack.length % 2) { - x += stack.shift(); - } - - while (stack.length > 0) { - c1x = x; - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x; - y = c2y + stack.shift(); - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - - } - else if(v=="o27") - { - if (stack.length % 2) { - y += stack.shift(); - } - - while (stack.length > 0) { - c1x = x + stack.shift(); - c1y = y; - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - y = c2y; - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - } - } - else if(v=="o10" || v=="o29") // callsubr || callgsubr - { - var obj = (v=="o10" ? pdct : font); - if(stack.length==0) { console.log("error: empty stack"); } - else { - var ind = stack.pop(); - var subr = obj["Subrs"][ ind + obj["Bias"] ]; - state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; - _drawCFF(subr, state,font,pdct,p); - x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; - } - } - else if(v=="o30" || v=="o31") // vhcurveto || hvcurveto - { - var count, count1 = stack.length; - var index = 0; - var alternate = v == "o31"; - - count = count1 & ~2; - index += count1 - count; - - while ( index < count ) - { - if(alternate) - { - c1x = x + stack.shift(); - c1y = y; - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - y = c2y + stack.shift(); - if(count-index == 5) { x = c2x + stack.shift(); index++; } - else x = c2x; - alternate = false; - } - else - { - c1x = x; - c1y = y + stack.shift(); - c2x = c1x + stack.shift(); - c2y = c1y + stack.shift(); - x = c2x + stack.shift(); - if(count-index == 5) { y = c2y + stack.shift(); index++; } - else y = c2y; - alternate = true; - } - P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); - index += 4; - } - } - - else if((v+"").charAt(0)=="o") { console.log("Unknown operation: "+v, cmds); throw v; } - else stack.push(v); - } - //console.log(cmds); - state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; - } - - function initHB(hurl,resp) { - var codeLength = function(code) { - var len=0; - if ((code&(0xffffffff-(1<< 7)+1))==0) { len=1; } - else if((code&(0xffffffff-(1<<11)+1))==0) { len=2; } - else if((code&(0xffffffff-(1<<16)+1))==0) { len=3; } - else if((code&(0xffffffff-(1<<21)+1))==0) { len=4; } - return len; - } - - fetch(hurl) - .then(function (x ) { return x["arrayBuffer"](); }) - .then(function (ab ) { return WebAssembly["instantiate"](ab); }) - .then(function (res) { - console.log("HB ready"); - var exp = res["instance"]["exports"], mem=exp["memory"]; - //mem["grow"](30); // each page is 64kb in size - var heapu8, u32,i32,f32; - var __lastFnt, blob,blobPtr,face,font; - - Typr["U"]["shapeHB"] = (function () { - - var toJson = function (ptr) { - var length = exp["hb_buffer_get_length"](ptr); - var result = []; - var iPtr32 = exp["hb_buffer_get_glyph_infos"](ptr, 0) >>>2; - var pPtr32 = exp["hb_buffer_get_glyph_positions"](ptr, 0) >>>2; - for(var i=0; i>>16)+4); //console.log("growing",nlen); - - heapu8 = new Uint8Array (mem.buffer); - u32 = new Uint32Array(mem.buffer); - i32 = new Int32Array (mem.buffer); - f32 = new Float32Array(mem.buffer); - - if(__lastFnt!=fn) { - if(blob!=null) { - exp["hb_blob_destroy"](blob); - exp["free"](blobPtr); - exp["hb_face_destroy"](face); - exp["hb_font_destroy"](font); - } - blobPtr = exp["malloc"](fdata.byteLength); heapu8.set(fdata, blobPtr); - blob = exp["hb_blob_create"](blobPtr, fdata.byteLength, 2, 0, 0); - face = exp["hb_face_create"](blob, fnt["_index"]); - font = exp["hb_font_create"](face) - __lastFnt = fn; - } - if(window["TextEncoder"]==null) { alert("Your browser is too old. Please, update it."); return; } - if(te==null) te = new window["TextEncoder"]("utf8"); - - var buffer = exp["hb_buffer_create"](); - var bytes = te["encode"](str); - var len=bytes.length, strp = exp["malloc"](len); heapu8.set(bytes, strp); - exp["hb_buffer_add_utf8"](buffer, strp, len, 0, len); - exp["free"](strp); - - var bin = Typr["B"]; - - var feat=0; - if(fts) { - feat = exp["malloc"](16*fts.length); - for(var i=0; i>>2; - bin.writeASCII (heapu8, off , fe[0].split("").reverse().join("")); - u32[qo+1]=fe[1]; - u32[qo+2]=fe[2]; - u32[qo+3]=fe[3]; - } - //console.log(fts); - } - var vdat = 0; - if(axs) { - var axes=fnt["fvar"][0]; //console.log(axes, axs); - vdat = exp["malloc"](8*axs.length); - for(var i=0; i>>2; - bin.writeASCII (heapu8, off , axes[i][0].split("").reverse().join("")); - f32[qo+1]=axs[i]; - } - } - //*/ - - if(axs) exp["hb_font_set_variations"](font,vdat,axs.length); - exp["hb_buffer_set_direction"](buffer,ltr?4:5); - exp["hb_buffer_guess_segment_properties"](buffer); - exp["hb_shape"](font, buffer, feat,fts?fts.length:0); - var json = toJson(buffer)//buffer["json"](); - exp["hb_buffer_destroy"](buffer); - if(fts) exp["free"](feat); - if(axs) exp["free"](vdat); - - var arr = json.slice(0); if(!ltr) arr.reverse(); - var ci=0, bi=0; // character index, binary index - for(var i=1; i=buff.length) throw "error"; - var a = Typr["B"].t.uint8; - a[0] = buff[p+3]; - a[1] = buff[p+2]; - a[2] = buff[p+1]; - a[3] = buff[p]; - return Typr["B"].t.int32[0]; - }, - - readInt8 : function(buff, p) - { - //if(p>=buff.length) throw "error"; - var a = Typr["B"].t.uint8; - a[0] = buff[p]; - return Typr["B"].t.int8[0]; - }, - readShort : function(buff, p) - { - //if(p>=buff.length) throw "error"; - var a = Typr["B"].t.uint16; - a[0] = (buff[p]<<8) | buff[p+1]; - return Typr["B"].t.int16[0]; - }, - readUshort : function(buff, p) - { - //if(p>=buff.length) throw "error"; - return (buff[p]<<8) | buff[p+1]; - }, - writeUshort : function(buff, p, n) - { - buff[p] = (n>>8)&255; buff[p+1] = n&255; - }, - readUshorts : function(buff, p, len) - { - var arr = []; - for(var i=0; i=buff.length) throw "error"; - var a = Typr["B"].t.uint8; - a[3] = buff[p]; a[2] = buff[p+1]; a[1] = buff[p+2]; a[0] = buff[p+3]; - return Typr["B"].t.uint32[0]; - }, - writeUint: function(buff, p, n) - { - buff[p] = (n>>24)&255; buff[p+1] = (n>>16)&255; buff[p+2] = (n>>8)&255; buff[p+3] = (n>>0)&255; - }, - readUint64 : function(buff, p) - { - //if(p>=buff.length) throw "error"; - return (Typr["B"].readUint(buff, p)*(0xffffffff+1)) + Typr["B"].readUint(buff, p+4); - }, - readASCII : function(buff, p, l) // l : length in Characters (not Bytes) - { - //if(p>=buff.length) throw "error"; - var s = ""; - for(var i = 0; i < l; i++) s += String.fromCharCode(buff[p+i]); - return s; - }, - writeASCII : function(buff, p, s) // l : length in Characters (not Bytes) - { - for(var i = 0; i < s.length; i++) - buff[p+i] = s.charCodeAt(i); - }, - readUnicode : function(buff, p, l) - { - //if(p>=buff.length) throw "error"; - var s = ""; - for(var i = 0; i < l; i++) - { - var c = (buff[p++]<<8) | buff[p++]; - s += String.fromCharCode(c); - } - return s; - }, - _tdec : window["TextDecoder"] ? new window["TextDecoder"]() : null, - readUTF8 : function(buff, p, l) { - var tdec = Typr["B"]._tdec; - if(tdec && p==0 && l==buff.length) return tdec["decode"](buff); - return Typr["B"].readASCII(buff,p,l); - }, - readBytes : function(buff, p, l) - { - //if(p>=buff.length) throw "error"; - var arr = []; - for(var i=0; i=buff.length) throw "error"; - var s = []; - for(var i = 0; i < l; i++) - s.push(String.fromCharCode(buff[p+i])); - return s; - }, - t : function() { - var ab = new ArrayBuffer(8); - return { - buff : ab, - int8 : new Int8Array (ab), - uint8 : new Uint8Array (ab), - int16 : new Int16Array (ab), - uint16 : new Uint16Array(ab), - int32 : new Int32Array (ab), - uint32 : new Uint32Array(ab) - } - }() + readFixed: function (data, o) { + return ((data[o] << 8) | data[o + 1]) + (((data[o + 2] << 8) | data[o + 3]) / (256 * 256 + 4)); + }, + readF2dot14: function (data, o) { + var num = Typr["B"].readShort(data, o); + return num / 16384; + }, + readInt: function (buff, p) { + //if(p>=buff.length) throw "error"; + var a = Typr["B"].t.uint8; + a[0] = buff[p + 3]; + a[1] = buff[p + 2]; + a[2] = buff[p + 1]; + a[3] = buff[p]; + return Typr["B"].t.int32[0]; + }, + + readInt8: function (buff, p) { + //if(p>=buff.length) throw "error"; + var a = Typr["B"].t.uint8; + a[0] = buff[p]; + return Typr["B"].t.int8[0]; + }, + readShort: function (buff, p) { + //if(p>=buff.length) throw "error"; + var a = Typr["B"].t.uint16; + a[0] = (buff[p] << 8) | buff[p + 1]; + return Typr["B"].t.int16[0]; + }, + readUshort: function (buff, p) { + //if(p>=buff.length) throw "error"; + return (buff[p] << 8) | buff[p + 1]; + }, + writeUshort: function (buff, p, n) { + buff[p] = (n >> 8) & 255; buff[p + 1] = n & 255; + }, + readUshorts: function (buff, p, len) { + var arr = []; + for (var i = 0; i < len; i++) { + var v = Typr["B"].readUshort(buff, p + i * 2); //if(v==932) console.log(p+i*2); + arr.push(v); + } + return arr; + }, + readUint: function (buff, p) { + //if(p>=buff.length) throw "error"; + var a = Typr["B"].t.uint8; + a[3] = buff[p]; a[2] = buff[p + 1]; a[1] = buff[p + 2]; a[0] = buff[p + 3]; + return Typr["B"].t.uint32[0]; + }, + writeUint: function (buff, p, n) { + buff[p] = (n >> 24) & 255; buff[p + 1] = (n >> 16) & 255; buff[p + 2] = (n >> 8) & 255; buff[p + 3] = (n >> 0) & 255; + }, + readUint64: function (buff, p) { + //if(p>=buff.length) throw "error"; + return (Typr["B"].readUint(buff, p) * (0xffffffff + 1)) + Typr["B"].readUint(buff, p + 4); + }, + readASCII: function (buff, p, l) // l : length in Characters (not Bytes) + { + //if(p>=buff.length) throw "error"; + var s = ""; + for (var i = 0; i < l; i++) s += String.fromCharCode(buff[p + i]); + return s; + }, + writeASCII: function (buff, p, s) // l : length in Characters (not Bytes) + { + for (var i = 0; i < s.length; i++) + buff[p + i] = s.charCodeAt(i); + }, + readUnicode: function (buff, p, l) { + //if(p>=buff.length) throw "error"; + var s = ""; + for (var i = 0; i < l; i++) { + var c = (buff[p++] << 8) | buff[p++]; + s += String.fromCharCode(c); + } + return s; + }, + _tdec: window["TextDecoder"] ? new window["TextDecoder"]() : null, + readUTF8: function (buff, p, l) { + var tdec = Typr["B"]._tdec; + if (tdec && p == 0 && l == buff.length) return tdec["decode"](buff); + return Typr["B"].readASCII(buff, p, l); + }, + readBytes: function (buff, p, l) { + //if(p>=buff.length) throw "error"; + var arr = []; + for (var i = 0; i < l; i++) arr.push(buff[p + i]); + return arr; + }, + readASCIIArray: function (buff, p, l) // l : length in Characters (not Bytes) + { + //if(p>=buff.length) throw "error"; + var s = []; + for (var i = 0; i < l; i++) + s.push(String.fromCharCode(buff[p + i])); + return s; + }, + t: function () { + var ab = new ArrayBuffer(8); + return { + buff: ab, + int8: new Int8Array(ab), + uint8: new Uint8Array(ab), + int16: new Int16Array(ab), + uint16: new Uint16Array(ab), + int32: new Int32Array(ab), + uint32: new Uint32Array(ab) + } + }() }; @@ -371,1569 +354,2609 @@ Typr["B"] = { - Typr["T"].CFF = { - parseTab : function(data, offset, length) - { - var bin = Typr["B"]; - var CFF = Typr["T"].CFF; - - data = new Uint8Array(data.buffer, offset, length); - offset = 0; - - // Header - var major = data[offset]; offset++; - var minor = data[offset]; offset++; - var hdrSize = data[offset]; offset++; - var offsize = data[offset]; offset++; - //console.log(major, minor, hdrSize, offsize); - - // Name INDEX - var ninds = []; - offset = CFF.readIndex(data, offset, ninds); - var names = []; - - for(var i=0; i 255 ) return -1; - return Typr["T"].CFF.glyphByUnicode(cff, Typr["T"].CFF.tableSE[charcode]); - }, - - /*readEncoding : function(data, offset, num) - { - var bin = Typr["B"]; - - var array = ['.notdef']; - var format = data[offset]; offset++; - //console.log("Encoding"); - //console.log(format); - - if(format==0) - { - var nCodes = data[offset]; offset++; - for(var i=0; i>4, nib1 = b&0xf; - if(nib0 != 0xf) nibs.push(nib0); if(nib1!=0xf) nibs.push(nib1); - if(nib1==0xf) break; - } - var s = ""; - var chars = [0,1,2,3,4,5,6,7,8,9,".","e","e-","reserved","-","endOfNumber"]; - for(var i=0; i 255) return -1; + return Typr["T"].CFF.glyphByUnicode(cff, Typr["T"].CFF.tableSE[charcode]); + }, + + /*readEncoding : function(data, offset, num) + { + var bin = Typr["B"]; + + var array = ['.notdef']; + var format = data[offset]; offset++; + //console.log("Encoding"); + //console.log(format); + + if(format==0) + { + var nCodes = data[offset]; offset++; + for(var i=0; i> 4, nib1 = b & 0xf; + if (nib0 != 0xf) nibs.push(nib0); if (nib1 != 0xf) nibs.push(nib1); + if (nib1 == 0xf) break; + } + var s = ""; + var chars = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, ".", "e", "e-", "reserved", "-", "endOfNumber"]; + for (var i = 0; i < nibs.length; i++) s += chars[nibs[i]]; + //console.log(nibs); + val = parseFloat(s); + } + + if (b0 <= 21) // operator + { + var keys = ["version", "Notice", "FullName", "FamilyName", "Weight", "FontBBox", "BlueValues", "OtherBlues", "FamilyBlues", "FamilyOtherBlues", + "StdHW", "StdVW", "escape", "UniqueID", "XUID", "charset", "Encoding", "CharStrings", "Private", "Subrs", + "defaultWidthX", "nominalWidthX"]; + + key = keys[b0]; vs = 1; + if (b0 == 12) { + var keys = ["Copyright", "isFixedPitch", "ItalicAngle", "UnderlinePosition", "UnderlineThickness", "PaintType", "CharstringType", "FontMatrix", "StrokeWidth", "BlueScale", + "BlueShift", "BlueFuzz", "StemSnapH", "StemSnapV", "ForceBold", "", "", "LanguageGroup", "ExpansionFactor", "initialRandomSeed", + "SyntheticBase", "PostScript", "BaseFontName", "BaseFontBlend", "", "", "", "", "", "", + "ROS", "CIDFontVersion", "CIDFontRevision", "CIDFontType", "CIDCount", "UIDBase", "FDArray", "FDSelect", "FontName"]; + key = keys[b1]; vs = 2; + } + } + + if (key != null) { dict[key] = carr.length == 1 ? carr[0] : carr; carr = []; } + else carr.push(val); + + offset += vs; + } + return dict; + } +}; Typr["T"].cmap = { - parseTab : function(data, offset, length) - { - var obj = {tables:[],ids:{},off:offset}; - data = new Uint8Array(data.buffer, offset, length); - offset = 0; - - var offset0 = offset; - var bin = Typr["B"], rU = bin.readUshort, cmap = Typr["T"].cmap; - var version = rU(data, offset); offset += 2; - var numTables = rU(data, offset); offset += 2; - - //console.log(version, numTables); - - var offs = []; - - - for(var i=0; i>>1; - obj.searchRange = rU(data, offset); offset+=2; - obj.entrySelector = rU(data, offset); offset+=2; - obj.rangeShift = rU(data, offset); offset+=2; - obj.endCount = rUs(data, offset, segCount); offset += segCount*2; - offset+=2; - obj.startCount = rUs(data, offset, segCount); offset += segCount*2; - obj.idDelta = []; - for(var i=0; i>1); //offset += segCount*2; - return obj; - }, - - parse6 : function(data, offset, obj) - { - var bin = Typr["B"]; - var offset0 = offset; - offset+=2; - var length = bin.readUshort(data, offset); offset+=2; - var language = bin.readUshort(data, offset); offset+=2; - obj.firstCode = bin.readUshort(data, offset); offset+=2; - var entryCount = bin.readUshort(data, offset); offset+=2; - obj.glyphIdArray = []; - for(var i=0; i>> 1; + obj.searchRange = rU(data, offset); offset += 2; + obj.entrySelector = rU(data, offset); offset += 2; + obj.rangeShift = rU(data, offset); offset += 2; + obj.endCount = rUs(data, offset, segCount); offset += segCount * 2; + offset += 2; + obj.startCount = rUs(data, offset, segCount); offset += segCount * 2; + obj.idDelta = []; + for (var i = 0; i < segCount; i++) { obj.idDelta.push(bin.readShort(data, offset)); offset += 2; } + obj.idRangeOffset = rUs(data, offset, segCount); offset += segCount * 2; + obj.glyphIdArray = rUs(data, offset, ((offset0 + length) - offset) >> 1); //offset += segCount*2; + return obj; + }, + + parse6: function (data, offset, obj) { + var bin = Typr["B"]; + var offset0 = offset; + offset += 2; + var length = bin.readUshort(data, offset); offset += 2; + var language = bin.readUshort(data, offset); offset += 2; + obj.firstCode = bin.readUshort(data, offset); offset += 2; + var entryCount = bin.readUshort(data, offset); offset += 2; + obj.glyphIdArray = []; + for (var i = 0; i < entryCount; i++) { obj.glyphIdArray.push(bin.readUshort(data, offset)); offset += 2; } + + return obj; + }, + + parse12: function (data, offset, obj) { + var bin = Typr["B"], rU = bin.readUint; + var offset0 = offset; + offset += 4; + var length = rU(data, offset); offset += 4; + var lang = rU(data, offset); offset += 4; + var nGroups = rU(data, offset) * 3; offset += 4; + + var gps = obj.groups = new Uint32Array(nGroups);//new Uint32Array(data.slice(offset, offset+nGroups*12).buffer); + + for (var i = 0; i < nGroups; i += 3) { + gps[i] = rU(data, offset + (i << 2)); + gps[i + 1] = rU(data, offset + (i << 2) + 4); + gps[i + 2] = rU(data, offset + (i << 2) + 8); + } + return obj; + } }; Typr["T"].CBLC = { - parseTab : function(data, offset, length) - { - var bin = Typr["B"], ooff=offset; - - var maj = bin.readUshort(data,offset); offset+=2; - var min = bin.readUshort(data,offset); offset+=2; - - var numSizes = bin.readUint (data,offset); offset+=4; - - var out = []; - for(var i=0; i=gl.xMax || gl.yMin>=gl.yMax) return null; - - if(gl.noc>0) - { - gl.endPts = []; - for(var i=0; i= gl.xMax || gl.yMin >= gl.yMax) return null; + + if (gl.noc > 0) { + gl.endPts = []; + for (var i = 0; i < gl.noc; i++) { gl.endPts.push(bin.readUshort(data, offset)); offset += 2; } + + var instructionLength = bin.readUshort(data, offset); offset += 2; + if ((data.length - offset) < instructionLength) return null; + gl.instructions = bin.readBytes(data, offset, instructionLength); offset += instructionLength; + + var crdnum = gl.endPts[gl.noc - 1] + 1; + gl.flags = []; + for (var i = 0; i < crdnum; i++) { + var flag = data[offset]; offset++; + gl.flags.push(flag); + if ((flag & 8) != 0) { + var rep = data[offset]; offset++; + for (var j = 0; j < rep; j++) { gl.flags.push(flag); i++; } + } + } + gl.xs = []; + for (var i = 0; i < crdnum; i++) { + var i8 = ((gl.flags[i] & 2) != 0), same = ((gl.flags[i] & 16) != 0); + if (i8) { gl.xs.push(same ? data[offset] : -data[offset]); offset++; } + else { + if (same) gl.xs.push(0); + else { gl.xs.push(bin.readShort(data, offset)); offset += 2; } + } + } + gl.ys = []; + for (var i = 0; i < crdnum; i++) { + var i8 = ((gl.flags[i] & 4) != 0), same = ((gl.flags[i] & 32) != 0); + if (i8) { gl.ys.push(same ? data[offset] : -data[offset]); offset++; } + else { + if (same) gl.ys.push(0); + else { gl.ys.push(bin.readShort(data, offset)); offset += 2; } + } + } + var x = 0, y = 0; + for (var i = 0; i < crdnum; i++) { x += gl.xs[i]; y += gl.ys[i]; gl.xs[i] = x; gl.ys[i] = y; } + //console.log(endPtsOfContours, instructionLength, instructions, flags, xCoordinates, yCoordinates); + } + else { + var ARG_1_AND_2_ARE_WORDS = 1 << 0; + var ARGS_ARE_XY_VALUES = 1 << 1; + var ROUND_XY_TO_GRID = 1 << 2; + var WE_HAVE_A_SCALE = 1 << 3; + var RESERVED = 1 << 4; + var MORE_COMPONENTS = 1 << 5; + var WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6; + var WE_HAVE_A_TWO_BY_TWO = 1 << 7; + var WE_HAVE_INSTRUCTIONS = 1 << 8; + var USE_MY_METRICS = 1 << 9; + var OVERLAP_COMPOUND = 1 << 10; + var SCALED_COMPONENT_OFFSET = 1 << 11; + var UNSCALED_COMPONENT_OFFSET = 1 << 12; + + gl.parts = []; + var flags; + do { + flags = bin.readUshort(data, offset); offset += 2; + var part = { m: { a: 1, b: 0, c: 0, d: 1, tx: 0, ty: 0 }, p1: -1, p2: -1 }; gl.parts.push(part); + part.glyphIndex = bin.readUshort(data, offset); offset += 2; + if (flags & ARG_1_AND_2_ARE_WORDS) { + var arg1 = bin.readShort(data, offset); offset += 2; + var arg2 = bin.readShort(data, offset); offset += 2; + } else { + var arg1 = bin.readInt8(data, offset); offset++; + var arg2 = bin.readInt8(data, offset); offset++; + } + + if (flags & ARGS_ARE_XY_VALUES) { part.m.tx = arg1; part.m.ty = arg2; } + else { part.p1 = arg1; part.p2 = arg2; } + //part.m.tx = arg1; part.m.ty = arg2; + //else { throw "params are not XY values"; } + + if (flags & WE_HAVE_A_SCALE) { + part.m.a = part.m.d = bin.readF2dot14(data, offset); offset += 2; + } else if (flags & WE_HAVE_AN_X_AND_Y_SCALE) { + part.m.a = bin.readF2dot14(data, offset); offset += 2; + part.m.d = bin.readF2dot14(data, offset); offset += 2; + } else if (flags & WE_HAVE_A_TWO_BY_TWO) { + part.m.a = bin.readF2dot14(data, offset); offset += 2; + part.m.b = bin.readF2dot14(data, offset); offset += 2; + part.m.c = bin.readF2dot14(data, offset); offset += 2; + part.m.d = bin.readF2dot14(data, offset); offset += 2; + } + } while (flags & MORE_COMPONENTS) + if (flags & WE_HAVE_INSTRUCTIONS) { + var numInstr = bin.readUshort(data, offset); offset += 2; + gl.instr = []; + for (var i = 0; i < numInstr; i++) { gl.instr.push(data[offset]); offset++; } + } + } + return gl; + } }; Typr["T"].head = { - parseTab : function(data, offset, length) - { - var bin = Typr["B"]; - var obj = {}; - var tableVersion = bin.readFixed(data, offset); offset += 4; - - obj["fontRevision"] = bin.readFixed(data, offset); offset += 4; - var checkSumAdjustment = bin.readUint(data, offset); offset += 4; - var magicNumber = bin.readUint(data, offset); offset += 4; - obj["flags"] = bin.readUshort(data, offset); offset += 2; - obj["unitsPerEm"] = bin.readUshort(data, offset); offset += 2; - obj["created"] = bin.readUint64(data, offset); offset += 8; - obj["modified"] = bin.readUint64(data, offset); offset += 8; - obj["xMin"] = bin.readShort(data, offset); offset += 2; - obj["yMin"] = bin.readShort(data, offset); offset += 2; - obj["xMax"] = bin.readShort(data, offset); offset += 2; - obj["yMax"] = bin.readShort(data, offset); offset += 2; - obj["macStyle"] = bin.readUshort(data, offset); offset += 2; - obj["lowestRecPPEM"] = bin.readUshort(data, offset); offset += 2; - obj["fontDirectionHint"] = bin.readShort(data, offset); offset += 2; - obj["indexToLocFormat"] = bin.readShort(data, offset); offset += 2; - obj["glyphDataFormat"] = bin.readShort(data, offset); offset += 2; - return obj; - } + parseTab: function (data, offset, length) { + var bin = Typr["B"]; + var obj = {}; + var tableVersion = bin.readFixed(data, offset); offset += 4; + + obj["fontRevision"] = bin.readFixed(data, offset); offset += 4; + var checkSumAdjustment = bin.readUint(data, offset); offset += 4; + var magicNumber = bin.readUint(data, offset); offset += 4; + obj["flags"] = bin.readUshort(data, offset); offset += 2; + obj["unitsPerEm"] = bin.readUshort(data, offset); offset += 2; + obj["created"] = bin.readUint64(data, offset); offset += 8; + obj["modified"] = bin.readUint64(data, offset); offset += 8; + obj["xMin"] = bin.readShort(data, offset); offset += 2; + obj["yMin"] = bin.readShort(data, offset); offset += 2; + obj["xMax"] = bin.readShort(data, offset); offset += 2; + obj["yMax"] = bin.readShort(data, offset); offset += 2; + obj["macStyle"] = bin.readUshort(data, offset); offset += 2; + obj["lowestRecPPEM"] = bin.readUshort(data, offset); offset += 2; + obj["fontDirectionHint"] = bin.readShort(data, offset); offset += 2; + obj["indexToLocFormat"] = bin.readShort(data, offset); offset += 2; + obj["glyphDataFormat"] = bin.readShort(data, offset); offset += 2; + return obj; + } }; Typr["T"].hhea = { - parseTab : function(data, offset, length) - { - var bin = Typr["B"]; - var obj = {}; - var tableVersion = bin.readFixed(data, offset); offset += 4; - - var keys = ["ascender","descender","lineGap", - "advanceWidthMax","minLeftSideBearing","minRightSideBearing","xMaxExtent", - "caretSlopeRise","caretSlopeRun","caretOffset", - "res0","res1","res2","res3", - "metricDataFormat","numberOfHMetrics" ]; - - for(var i=0; i< keys.length; i++) { - var key = keys[i]; - var func = (key=="advanceWidthMax" || key=="numberOfHMetrics")?bin.readUshort:bin.readShort; - obj[key]=func(data,offset+i*2); - } - return obj; - } + parseTab: function (data, offset, length) { + var bin = Typr["B"]; + var obj = {}; + var tableVersion = bin.readFixed(data, offset); offset += 4; + + var keys = ["ascender", "descender", "lineGap", + "advanceWidthMax", "minLeftSideBearing", "minRightSideBearing", "xMaxExtent", + "caretSlopeRise", "caretSlopeRun", "caretOffset", + "res0", "res1", "res2", "res3", + "metricDataFormat", "numberOfHMetrics"]; + + for (var i = 0; i < keys.length; i++) { + var key = keys[i]; + var func = (key == "advanceWidthMax" || key == "numberOfHMetrics") ? bin.readUshort : bin.readShort; + obj[key] = func(data, offset + i * 2); + } + return obj; + } }; Typr["T"].hmtx = { - parseTab : function(data, offset, length, font) - { - var bin = Typr["B"]; - var aWidth = []; - var lsBearing = []; - - var nG = font["maxp"]["numGlyphs"], nH = font["hhea"]["numberOfHMetrics"]; - var aw = 0, lsb = 0, i=0; - while(i>>8; + parseTab: function (data, offset, length, font) { + var bin = Typr["B"], kern = Typr["T"].kern; + + var version = bin.readUshort(data, offset); + if (version == 1) return kern.parseV1(data, offset, length, font); + var nTables = bin.readUshort(data, offset + 2); offset += 4; + + var map = { glyph1: [], rval: [] }; + for (var i = 0; i < nTables; i++) { + offset += 2; // skip version + var length = bin.readUshort(data, offset); offset += 2; + var coverage = bin.readUshort(data, offset); offset += 2; + var format = coverage >>> 8; /* I have seen format 128 once, that's why I do */ format &= 0xf; - if(format==0) offset = kern.readFormat0(data, offset, map); - //else throw "unknown kern table format: "+format; - } - return map; - }, - - parseV1 : function(data, offset, length, font) - { - var bin = Typr["B"], kern=Typr["T"].kern; - - var version = bin.readFixed(data, offset); // 0x00010000 - var nTables = bin.readUint (data, offset+4); offset+=8; - - var map = {glyph1: [], rval:[]}; - for(var i=0; i>>12)!=0) throw "e"; - - var snum = vcnt&SHARED_POINT_NUMBERS; vcnt&=0xfff; - // offset to the serialized data - var soff = bin.readUshort(data,off); off+=2; - - var hdr = readTupleVarHeader(data,off,vcnt,acnt, offset+goff+offs[i+1]); - - var tab = []; tabs.push(tab); - // Serialized Data - off=offset + goff + offs[i] + soff; - - var sind = null; - if(snum) { - var oo = readPointNumbers(data,off,i); - sind=oo[0]; off=oo[1]; - } - - for(var j=0; j>>12)!=0) throw "e"; + + var snum = vcnt & SHARED_POINT_NUMBERS; vcnt &= 0xfff; + // offset to the serialized data + var soff = bin.readUshort(data, off); off += 2; + + var hdr = readTupleVarHeader(data, off, vcnt, acnt, offset + goff + offs[i + 1]); + + var tab = []; tabs.push(tab); + // Serialized Data + off = offset + goff + offs[i] + soff; + + var sind = null; + if (snum) { + var oo = readPointNumbers(data, off, i); + sind = oo[0]; off = oo[1]; + } + + for (var j = 0; j < vcnt; j++) { + var vr = hdr[j], end = off + vr[0]; //console.log(vr); console.log(data.slice(off,off+vr[0])); + + var ind = sind; + if (vr[2] & PRIVATE_POINT_NUMBERS) { + var oo = readPointNumbers(data, off, i); + ind = oo[0]; off = oo[1]; + } + // read packed deltas (delta runs) + var ds = []; + while (off < end) { + var cb = data[off++]; // control byte; + var cnt = (cb & 0x3f) + 1; + if (cb & DELTAS_ARE_ZERO) { for (var k = 0; k < cnt; k++) ds.push(0); } + else if (cb & DELTAS_ARE_WORDS) { for (var k = 0; k < cnt; k++) ds.push(bin.readShort(data, off + k * 2)); off += cnt * 2; } + else { for (var k = 0; k < cnt; k++) ds.push(i8[off + k]); off += cnt; } + } + //if(ind) console.log(ind, ds); + var ti = vr[1]; + + tab.push([[ + vr[3] ? vr[3] : mins[ti], + vr[4] ? vr[4] : tups[ti], + vr[5] ? vr[5] : maxs[ti] + ], ds, ind.length == 0 ? null : ind]); + + if (ind.length != 0 && ind.length * 2 != ds.length) throw "e"; + //if(i==116) console.log(ind, ds); + } + } + return tabs; + } + + return { parseTab: parseTab }; })(); Typr["T"].avar = { - parseTab : function(data, offset, length, obj) - { - var off = offset; - var bin = Typr["B"], out = []; - - off+=6; - var acnt = bin.readUshort(data,off); off+=2; - - for(var ai=0; ai> 4) + 1; //if(entrySize!=1) throw entrySize; - - //console.log(fmt, entryFormat, mapCount, entrySize); - - var dfs=[]; - for(var i=0; i> ((entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1); - var innerIndex = entry & ((1 << ((entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1)) - 1); - //map.push(outerIndex,innerIndex); - dfs.push(varStore[outerIndex][innerIndex]); - //console.log(outerIndex,innerIndex); - //console.log(i,varStore[outerIndex][innerIndex]); - } - - return [regs,dfs]; - } + parseTab: function (data, offset, length, obj) { + var off = offset, oo = offset; + var bin = Typr["B"], out = []; + + //console.log(data.slice(off)); + off += 4; + + var varO = bin.readUint(data, off); off += 4; + var advO = bin.readUint(data, off); off += 4; + var lsbO = bin.readUint(data, off); off += 4; + var rsbO = bin.readUint(data, off); off += 4; + if (lsbO != 0 || rsbO != 0) throw lsbO; + + //console.log(varO,advO,lsbO,rsbO); + + off = oo + varO; // item variation store + + // ItemVariationStore + var ioff = off; + + var fmt = bin.readUshort(data, off); off += 2; if (fmt != 1) throw "e"; + var vregO = bin.readUint(data, off); off += 4; + // itemVariationDataCount + var vcnt = bin.readUshort(data, off); off += 2; + + var offs = []; for (var i = 0; i < vcnt; i++) offs.push(bin.readUint(data, off + i * 4)); off += vcnt * 4; //if(offs.length!=1) throw "e"; + //console.log(vregO,vcnt,offs); + + off = ioff + vregO; + var acnt = bin.readUshort(data, off); off += 2; + var rcnt = bin.readUshort(data, off); off += 2; + + var regs = []; + for (var i = 0; i < rcnt; i++) { + var crd = [[], [], []]; regs.push(crd); + for (var j = 0; j < acnt; j++) { + crd[0].push(bin.readF2dot14(data, off + 0)); + crd[1].push(bin.readF2dot14(data, off + 2)); + crd[2].push(bin.readF2dot14(data, off + 4)); + off += 6; + } + } + //console.log(acnt, rcnt, regs); + + + var i8 = new Int8Array(data.buffer); + var varStore = []; + for (var i = 0; i < offs.length; i++) { + // ItemVariationData + off = oo + varO + offs[i]; var vdata = []; varStore.push(vdata); + var icnt = bin.readUshort(data, off); off += 2; // itemCount + var dcnt = bin.readUshort(data, off); off += 2; if (dcnt & 0x8000) throw "e"; + var rcnt = bin.readUshort(data, off); off += 2; + var ixs = []; for (var j = 0; j < rcnt; j++) ixs.push(bin.readUshort(data, off + j * 2)); off += rcnt * 2; + //console.log(icnt,dcnt,rcnt,ixs); + //console.log(data.slice(off)); + + for (var k = 0; k < icnt; k++) { // deltaSets + var deltaData = []; //vdata.push(deltaData); + for (var ri = 0; ri < rcnt; ri++) { + deltaData.push(ri < dcnt ? bin.readShort(data, off) : i8[off]); + off += ri < dcnt ? 2 : 1; + + } + var dd = new Array(regs.length); dd.fill(0); vdata.push(dd); + for (var j = 0; j < ixs.length; j++) dd[ixs[j]] = deltaData[j]; + } + } + + //console.log(varStore); + + // VariationRegionList + + + + off = oo + advO; // advance widths + + // DeltaSetIndexMap + + var fmt = data[off++]; if (fmt != 0) throw "e"; + var entryFormat = data[off++]; + + var mapCount = bin.readUshort(data, off); off += 2; + + var INNER_INDEX_BIT_COUNT_MASK = 0x0f; + var MAP_ENTRY_SIZE_MASK = 0x30; + var entrySize = ((entryFormat & MAP_ENTRY_SIZE_MASK) >> 4) + 1; //if(entrySize!=1) throw entrySize; + + //console.log(fmt, entryFormat, mapCount, entrySize); + + var dfs = []; + for (var i = 0; i < mapCount; i++) { + var entry = 0; + if (entrySize == 1) entry = data[off++]; + else { entry = bin.readUshort(data, off); off += 2; } + var outerIndex = entry >> ((entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1); + var innerIndex = entry & ((1 << ((entryFormat & INNER_INDEX_BIT_COUNT_MASK) + 1)) - 1); + //map.push(outerIndex,innerIndex); + dfs.push(varStore[outerIndex][innerIndex]); + //console.log(outerIndex,innerIndex); + //console.log(i,varStore[outerIndex][innerIndex]); + } + + return [regs, dfs]; + } }; -export default Typr; +Typr["U"] = function () { + var P = { + MoveTo: function (p, x, y) { p.cmds.push("M"); p.crds.push(x, y); }, + LineTo: function (p, x, y) { p.cmds.push("L"); p.crds.push(x, y); }, + CurveTo: function (p, a, b, c, d, e, f) { p.cmds.push("C"); p.crds.push(a, b, c, d, e, f); }, + qCurveTo: function (p, a, b, c, d) { p.cmds.push("Q"); p.crds.push(a, b, c, d); }, + ClosePath: function (p) { p.cmds.push("Z"); } + } + + function getGlyphPosition(font, gls, i1, ltr) { + var g1 = gls[i1], g2 = gls[i1 + 1], kern = font["kern"]; + if (kern) { + var ind1 = kern.glyph1.indexOf(g1); + if (ind1 != -1) { + var ind2 = kern.rval[ind1].glyph2.indexOf(g2); + if (ind2 != -1) return [0, 0, kern.rval[ind1].vals[ind2], 0]; + } + } + //console.log("no kern"); + return [0, 0, 0, 0]; + } + function shape(font, str, prm) { + if (prm == null) prm = {}; + var ltr = prm["ltr"], fts = prm["fts"], axs = prm["axs"]; + if (font["fvar"] && axs == null) axs = font["fvar"][1][font["_index"]][2]; + + var HVAR = font["HVAR"]; //console.log(HVAR); + if (axs && HVAR) { axs = _normalizeAxis(font, axs); } //console.log(S,axs); + var gls = []; + for (var i = 0; i < str.length; i++) { + var cc = str.codePointAt(i); if (cc > 0xffff) i++; + gls.push(codeToGlyph(font, cc)); + } + var shape = []; + var x = 0, y = 0; + + for (var i = 0; i < gls.length; i++) { + var padj = getGlyphPosition(font, gls, i, ltr); + var gid = gls[i]; //console.log(gid); + var ax = font["hmtx"].aWidth[gid] + padj[2]; + if (HVAR && HVAR[1][gid]) { //ax+=S*HVAR[1][gid][0]; + var difs = HVAR[1][gid]; //console.log(difs); + for (var j = 0; j < HVAR[0].length; j++) { + ax += _interpolate(HVAR[0][j], axs) * difs[j]; + } + } + shape.push({ "g": gid, "cl": i, "dx": 0, "dy": 0, "ax": ax, "ay": 0 }); + x += ax; + } + return shape; + } + + function shapeToPath(font, shape, prm) { + var tpath = { cmds: [], crds: [] }; + var x = 0, y = 0, clr, axs; + if (prm) { clr = prm["clr"]; axs = prm["axs"]; } + + for (var i = 0; i < shape.length; i++) { + var it = shape[i] + var path = glyphToPath(font, it["g"], false, axs), crds = path["crds"]; + for (var j = 0; j < crds.length; j += 2) { + tpath.crds.push(crds[j] + x + it["dx"]); + tpath.crds.push(crds[j + 1] + y + it["dy"]); + } + if (clr) tpath.cmds.push(clr); + for (var j = 0; j < path["cmds"].length; j++) tpath.cmds.push(path["cmds"][j]); + var clen = tpath.cmds.length; + if (clr) if (clen != 0 && tpath.cmds[clen - 1] != "X") tpath.cmds.push("X"); // SVG fonts might contain "X". Then, nothing would stroke non-SVG glyphs. + + x += it["ax"]; y += it["ay"]; + } + return { "cmds": tpath.cmds, "crds": tpath.crds }; + } + + + // find the greatest index with a value <=v + function arrSearch(arr, k, v) { + var l = 0, r = ~~(arr.length / k); + while (l + 1 != r) { var mid = l + ((r - l) >>> 1); if (arr[mid * k] <= v) l = mid; else r = mid; } + + //var mi = 0; for(var i=0; i= tab.map.length) gid = 0; + else gid = tab.map[code]; + } + /*else if(fmt==2) { + var data=font["_data"], off = cmap.off+tab.off+6, bin=Typr["B"]; + var shKey = bin.readUshort(data,off + 2*(code>>>8)); + var shInd = off + 256*2 + shKey*8; + + var firstCode = bin.readUshort(data,shInd); + var entryCount= bin.readUshort(data,shInd+2); + var idDelta = bin.readShort (data,shInd+4); + var idRangeOffset = bin.readUshort(data,shInd+6); + + if(firstCode<=code && code<=firstCode+entryCount) { + // not completely correct + gid = bin.readUshort(data, shInd+6+idRangeOffset + (code&255)*2); + } + else gid=0; + //if(code>256) console.log(code,(code>>>8),shKey,firstCode,entryCount,idDelta,idRangeOffset); + + //throw "e"; + //console.log(tab, bin.readUshort(data,off)); + //throw "e"; + }*/ + else if (fmt == 4) { + var ec = tab.endCount; gid = 0; + if (code <= ec[ec.length - 1]) { + // smallest index with code <= value + var sind = arrSearch(ec, 1, code); + if (ec[sind] < code) sind++; + + if (code >= tab.startCount[sind]) { + var gli = 0; + if (tab.idRangeOffset[sind] != 0) gli = tab.glyphIdArray[(code - tab.startCount[sind]) + (tab.idRangeOffset[sind] >> 1) - (tab.idRangeOffset.length - sind)]; + else gli = code + tab.idDelta[sind]; + gid = (gli & 0xFFFF); + } + } + } + else if (fmt == 6) { + var off = code - tab.firstCode, arr = tab.glyphIdArray; + if (off < 0 || off >= arr.length) gid = 0; + else gid = arr[off]; + } + else if (fmt == 12) { + var grp = tab.groups; gid = 0; //console.log(grp); throw "e"; + + if (code <= grp[grp.length - 2]) { + var i = arrSearch(grp, 3, code); + if (grp[i] <= code && code <= grp[i + 1]) { gid = grp[i + 2] + (code - grp[i]); } + } + } + else throw "unknown cmap table format " + tab.format; + + //* + var SVG = font["SVG "], loca = font["loca"]; + // if the font claims to have a Glyph for a character, but the glyph is empty, and the character is not "white", it is a lie! + if (gid != 0 && font["CFF "] == null && (SVG == null || SVG.entries[gid] == null) && loca && loca[gid] == loca[gid + 1] // loca not present in CFF or SVG fonts + && whm[code] == null) gid = 0; + //*/ + + return gid; + } + function glyphToPath(font, gid, noColor, axs) { + var path = { cmds: [], crds: [] }; + + if (font["fvar"]) { + if (axs == null) axs = font["fvar"][1][font["_index"]][2]; + axs = _normalizeAxis(font, axs); + } + + var SVG = font["SVG "], CFF = font["CFF "], COLR = font["COLR"], CBLC = font["CBLC"], CBDT = font["CBDT"], sbix = font["sbix"], upng = window["UPNG"]; + + var strike = null; + if (CBLC && upng) for (var i = 0; i < CBLC.length; i++) if (CBLC[i][0] <= gid && gid <= CBLC[i][1]) strike = CBLC[i]; + + if (strike || (sbix && sbix[gid])) { + if (strike && strike[2] != 17) throw "not a PNG"; + + if (font["__tmp"] == null) font["__tmp"] = {}; + var cmd = font["__tmp"]["g" + gid]; + if (cmd == null) { + var bmp, len; + if (sbix) { bmp = sbix[gid]; len = bmp.length; } + else { + var boff = strike[3][gid - strike[0]] + 5; // smallGlyphMetrics + len = (CBDT[boff + 1] << 16) | (CBDT[boff + 2] << 8) | CBDT[boff + 3]; boff += 4; + bmp = new Uint8Array(CBDT.buffer, CBDT.byteOffset + boff, len); + } + var str = ""; for (var i = 0; i < len; i++) str += String.fromCharCode(bmp[i]); + cmd = font["__tmp"]["g" + gid] = "data:image/png;base64," + btoa(str); + } + + path.cmds.push(cmd); + var upe = font["head"]["unitsPerEm"] * 1.15; + var gw = Math.round(upe), gh = Math.round(upe), dy = Math.round(-gh * 0.15); + path.crds.push(0, gh + dy, gw, gh + dy, gw, dy, 0, dy); //*/ + } + else if (SVG && SVG.entries[gid]) { + var p = SVG.entries[gid]; + if (p != null) { + if (typeof p == "number") { + var svg = SVG.svgs[p]; + if (typeof svg == "string") { + var prsr = new DOMParser(); + var doc = prsr["parseFromString"](svg, "image/svg+xml"); + svg = SVG.svgs[p] = doc.getElementsByTagName("svg")[0]; + } + p = Typr["U"]["SVG"].toPath(svg, gid); SVG.entries[gid] = p; + } + path = p; + } + } + else if (noColor != true && COLR && COLR[0]["g" + gid] && COLR[0]["g" + gid][1] > 1) { + + function toHex(n) { var o = n.toString(16); return (o.length == 1 ? "0" : "") + o; } + + var CPAL = font["CPAL"], gl = COLR[0]["g" + gid]; + for (var i = 0; i < gl[1]; i++) { + var lid = gl[0] + i; + var cgl = COLR[1][2 * lid], pid = COLR[1][2 * lid + 1] * 4; + var pth = glyphToPath(font, cgl, cgl == gid); + + var col = "#" + toHex(CPAL[pid + 2]) + toHex(CPAL[pid + 1]) + toHex(CPAL[pid + 0]); + path.cmds.push(col); + + path.cmds = path.cmds.concat(pth["cmds"]); + path.crds = path.crds.concat(pth["crds"]); + //console.log(gid, cgl,pid,col); + + path.cmds.push("X"); + } + } + else if (CFF) { + var pdct = CFF["Private"]; + var state = { x: 0, y: 0, stack: [], nStems: 0, haveWidth: false, width: pdct ? pdct["defaultWidthX"] : 0, open: false }; + if (CFF["ROS"]) { + var gi = 0; + while (CFF["FDSelect"][gi + 2] <= gid) gi += 2; + pdct = CFF["FDArray"][CFF["FDSelect"][gi + 1]]["Private"]; + } + _drawCFF(CFF["CharStrings"][gid], state, CFF, pdct, path); + } + else if (font["glyf"]) { _drawGlyf(gid, font, path, axs); } + return { "cmds": path.cmds, "crds": path.crds }; + } + + function _drawGlyf(gid, font, path, axs) { + var gl = font["glyf"][gid]; + + if (gl == null) gl = font["glyf"][gid] = Typr["T"].glyf._parseGlyf(font, gid); + if (gl != null) { + if (gl.noc > -1) _simpleGlyph(gl, font, gid, path, axs); + else _compoGlyph(gl, font, gid, path, axs); + } + } + function _interpolate(axs, v) { + var acnt = v.length, S = 1; + var s = axs[0]; // start + var p = axs[1]; // peak + var e = axs[2]; // end + + for (var i = 0; i < v.length; i++) { + var AS = 1; + if (s[i] > p[i] || p[i] > e[i]) AS = 1; + else if (s[i] < 0 && e[i] > 0 && p[i] != 0) AS = 1; + else if (p[i] == 0) AS = 1; + else if (v[i] < s[i] || v[i] > e[i]) AS = 0; + else { + if (v[i] == p[i]) AS = 1; + else if (v[i] < p[i]) AS = (v[i] - s[i]) / (p[i] - s[i]); + else AS = (e[i] - v[i]) / (e[i] - p[i]); + } + S = S * AS; + } + return S; + } + function _normalizeAxis(font, vv) { + var fvar = font["fvar"], avar = font["avar"]; + var fv = fvar ? fvar[0] : null; + + var nv = []; + for (var i = 0; i < fv.length; i++) { + var min = fv[i][1], def = fv[i][2], max = fv[i][3], v = Math.max(min, Math.min(max, vv[i])); + if (v < def) nv[i] = (def - v) / (min - def); + else if (v > def) nv[i] = (v - def) / (max - def); + else nv[i] = 0; + + if (avar && nv[i] != -1) { + var av = avar[i], j = 0; + for (; j < av.length; j += 2) if (av[j] >= nv[i]) break; + var f = (nv[i] - av[j - 2]) / (av[j] - av[j - 2]); + nv[i] = f * av[j + 1] + (1 - f) * av[j - 1]; + } + + } + return nv; + } + function interpolateDeltas(dfs, ind, xs, ys, endPts) { + var N = xs.length, ndfs = new Array(N * 2 + 8); ndfs.fill(0); + for (var i = 0; i < N; i++) { + var dx = 0, dy = 0, ii = ind.indexOf(i); + if (ii != -1) { dx = dfs[ii]; dy = dfs[ind.length + ii]; } + else { + var cmp = 0; while (endPts[cmp] < i) cmp++; + var cmp0 = cmp == 0 ? 0 : endPts[cmp - 1] + 1; + var cmp1 = endPts[cmp]; + + var i0 = -1, i1 = -1; + + for (var j = 0; j < ind.length; j++) { var v = ind[j]; if (v < cmp0 || v > cmp1 || v >= N) continue; i0 = j; if (i1 == -1) i1 = j; } + for (var j = 0; j < ind.length; j++) { var v = ind[j]; if (v < cmp0 || v > cmp1 || v >= N) continue; if (v < i) i0 = j; if (i < v) { i1 = j; break; } } + + //var i0 = ind.length-1, i1=0; if(ind[i0]>=N) i0--; + //for(var j=0; j= 0) no.push(" "); + no.push(it); lstF = isF; + } + return no.join(""); + } + + + var out = [], co = 0, lmap = { "M": 2, "L": 2, "Q": 4, "C": 6 }; + var x = 0, y = 0, // perfect coords + //dx=0, dy=0, // relative perfect coords + //rx=0, ry=0, // relative rounded coords + ex = 0, ey = 0, // error between perfect and output coords + mx = 0, my = 0; // perfect coords of the last "Move" + + for (var i = 0; i < cmds.length; i++) { + var cmd = cmds[i], cc = (lmap[cmd] ? lmap[cmd] : 0); + + var o0 = [], dx, dy, rx, ry; // o1=[], cx, cy, ax,ay; + if (cmd == "L") { + dx = crds[co] - x; dy = crds[co + 1] - y; + rx = num(dx + ex); ry = num(dy + ey); + // if this "lineTo" leads to the starting point, and "Z" follows, do not output anything. + if (cmds[i + 1] == "Z" && crds[co] == mx && crds[co + 1] == my) { rx = dx; ry = dy; } + else if (rx == 0 && ry == 0) { } + else if (rx == 0) o0.push("v", ry); + else if (ry == 0) o0.push("h", rx); + else { o0.push("l", rx, ry); } + } + else { + o0.push(cmd.toLowerCase()); + for (var j = 0; j < cc; j += 2) { + dx = crds[co + j] - x; dy = crds[co + j + 1] - y; + rx = num(dx + ex); ry = num(dy + ey); + o0.push(rx, ry); + } + } + if (cc != 0) { ex += dx - rx; ey += dy - ry; } + + var ou = o0; + for (var j = 0; j < ou.length; j++) out.push(ou[j]); + + if (cc != 0) { co += cc; x = crds[co - 2]; y = crds[co - 1]; } + if (cmd == "M") { mx = x; my = y; } + if (cmd == "Z") { x = mx; y = my; } + } + + return merge(out); + } + function SVGToPath(d) { + var pth = { cmds: [], crds: [] }; + Typr["U"]["SVG"].svgToPath(d, pth); + return { "cmds": pth.cmds, "crds": pth.crds }; + } + + function mipmapB(buff, w, h, hlp) { + var nw = w >> 1, nh = h >> 1; + var nbuf = (hlp && hlp.length == nw * nh * 4) ? hlp : new Uint8Array(nw * nh * 4); + var sb32 = new Uint32Array(buff.buffer), nb32 = new Uint32Array(nbuf.buffer); + for (var y = 0; y < nh; y++) + for (var x = 0; x < nw; x++) { + var ti = (y * nw + x), si = ((y << 1) * w + (x << 1)); + //nbuf[ti ] = buff[si ]; nbuf[ti+1] = buff[si+1]; nbuf[ti+2] = buff[si+2]; nbuf[ti+3] = buff[si+3]; + //* + var c0 = sb32[si], c1 = sb32[si + 1], c2 = sb32[si + w], c3 = sb32[si + w + 1]; + + var a0 = (c0 >>> 24), a1 = (c1 >>> 24), a2 = (c2 >>> 24), a3 = (c3 >>> 24), a = (a0 + a1 + a2 + a3); + + if (a == 1020) { + var r = (((c0 >>> 0) & 255) + ((c1 >>> 0) & 255) + ((c2 >>> 0) & 255) + ((c3 >>> 0) & 255) + 2) >>> 2; + var g = (((c0 >>> 8) & 255) + ((c1 >>> 8) & 255) + ((c2 >>> 8) & 255) + ((c3 >>> 8) & 255) + 2) >>> 2; + var b = (((c0 >>> 16) & 255) + ((c1 >>> 16) & 255) + ((c2 >>> 16) & 255) + ((c3 >>> 16) & 255) + 2) >>> 2; + nb32[ti] = (255 << 24) | (b << 16) | (g << 8) | r; + } + else if (a == 0) nb32[ti] = 0; + else { + var r = ((c0 >>> 0) & 255) * a0 + ((c1 >>> 0) & 255) * a1 + ((c2 >>> 0) & 255) * a2 + ((c3 >>> 0) & 255) * a3; + var g = ((c0 >>> 8) & 255) * a0 + ((c1 >>> 8) & 255) * a1 + ((c2 >>> 8) & 255) * a2 + ((c3 >>> 8) & 255) * a3; + var b = ((c0 >>> 16) & 255) * a0 + ((c1 >>> 16) & 255) * a1 + ((c2 >>> 16) & 255) * a2 + ((c3 >>> 16) & 255) * a3; + + var ia = 1 / a; r = ~~(r * ia + 0.5); g = ~~(g * ia + 0.5); b = ~~(b * ia + 0.5); + nb32[ti] = (((a + 2) >>> 2) << 24) | (b << 16) | (g << 8) | r; + } + } + return { buff: nbuf, w: nw, h: nh }; + } + + var __cnv, __ct; + function pathToContext(path, ctx) { + var c = 0, cmds = path["cmds"], crds = path["crds"]; + + //ctx.translate(3500,500); ctx.rotate(0.25); ctx.scale(1,-1); + + for (var j = 0; j < cmds.length; j++) { + var cmd = cmds[j]; + if (cmd == "M") { + ctx.moveTo(crds[c], crds[c + 1]); + c += 2; + } + else if (cmd == "L") { + ctx.lineTo(crds[c], crds[c + 1]); + c += 2; + } + else if (cmd == "C") { + ctx.bezierCurveTo(crds[c], crds[c + 1], crds[c + 2], crds[c + 3], crds[c + 4], crds[c + 5]); + c += 6; + } + else if (cmd == "Q") { + ctx.quadraticCurveTo(crds[c], crds[c + 1], crds[c + 2], crds[c + 3]); + c += 4; + } + else if (cmd[0] == "d") { + var upng = window["UPNG"]; + var x0 = crds[c], y0 = crds[c + 1], x1 = crds[c + 2], y1 = crds[c + 3], x2 = crds[c + 4], y2 = crds[c + 5], x3 = crds[c + 6], y3 = crds[c + 7]; c += 8; + //y0+=400; y1+=400; y1+=600; + if (upng == null) { + ctx.moveTo(x0, y0); ctx.lineTo(x1, y1); ctx.lineTo(x2, y2); ctx.lineTo(x3, y3); ctx.closePath(); + continue; + } + var dx0 = (x1 - x0), dy0 = (y1 - y0), dx1 = (x3 - x0), dy1 = (y3 - y0); + var sbmp = atob(cmd.slice(22)); + var bmp = new Uint8Array(sbmp.length); + for (var i = 0; i < sbmp.length; i++) bmp[i] = sbmp.charCodeAt(i); + + var img = upng["decode"](bmp.buffer), w = img["width"], h = img["height"]; //console.log(img); + + var nbmp = new Uint8Array(upng["toRGBA8"](img)[0]); + var tr = ctx["getTransform"](); + var scl = Math.sqrt(Math.abs(tr["a"] * tr["d"] - tr["b"] * tr["c"])) * Math.sqrt(dx1 * dx1 + dy1 * dy1) / h; + while (scl < 0.5) { + var nd = mipmapB(nbmp, w, h); + nbmp = nd.buff; w = nd.w; h = nd.h; scl *= 2; + } + + if (__cnv == null) { __cnv = document.createElement("canvas"); __ct = __cnv.getContext("2d"); } + if (__cnv.width != w || __cnv.height != h) { __cnv.width = w; __cnv.height = h; } + + __ct.putImageData(new ImageData(new Uint8ClampedArray(nbmp.buffer), w, h), 0, 0); + ctx.save(); + ctx.transform(dx0, dy0, dx1, dy1, x0, y0); + ctx.scale(1 / w, 1 / h); + ctx.drawImage(__cnv, 0, 0); //*/ + ctx.restore(); + } + else if (cmd.charAt(0) == "#" || cmd.charAt(0) == "r") { + ctx.beginPath(); + ctx.fillStyle = cmd; + } + else if (cmd.charAt(0) == "O" && cmd != "OX") { + ctx.beginPath(); + var pts = cmd.split("-"); + ctx.lineWidth = parseFloat(pts[2]); + ctx.lineCap = ["butt", "round", "square"][parseFloat(pts[3])]; + ctx.lineJoin = ["miter", "round", "bevel"][parseFloat(pts[4])]; + ctx.miterLimit = parseFloat(pts[5]); + ctx.lineDashOffset = parseFloat(pts[6]); + ctx.setLineDash(pts[7].split(",").map(parseFloat)); + ctx.strokeStyle = pts[1]; + } + else if (cmd == "Z") { + ctx.closePath(); + } + else if (cmd == "X") { + ctx.fill(); + } + else if (cmd == "OX") { + ctx.stroke(); + } + } + } + + + function _drawCFF(cmds, state, font, pdct, p) { + var stack = state.stack; + var nStems = state.nStems, haveWidth = state.haveWidth, width = state.width, open = state.open; + var i = 0; + var x = state.x, y = state.y, c1x = 0, c1y = 0, c2x = 0, c2y = 0, c3x = 0, c3y = 0, c4x = 0, c4y = 0, jpx = 0, jpy = 0; + var CFF = Typr["T"].CFF; + + var nominalWidthX = pdct["nominalWidthX"]; + var o = { val: 0, size: 0 }; + //console.log(cmds); + while (i < cmds.length) { + CFF.getCharString(cmds, i, o); + var v = o.val; + i += o.size; + + if (false) { } + else if (v == "o1" || v == "o18") // hstem || hstemhm + { + var hasWidthArg; + + // The number of stem operators on the stack is always even. + // If the value is uneven, that means a width is specified. + hasWidthArg = stack.length % 2 !== 0; + if (hasWidthArg && !haveWidth) { + width = stack.shift() + nominalWidthX; + } + + nStems += stack.length >> 1; + stack.length = 0; + haveWidth = true; + } + else if (v == "o3" || v == "o23") // vstem || vstemhm + { + var hasWidthArg; + + // The number of stem operators on the stack is always even. + // If the value is uneven, that means a width is specified. + hasWidthArg = stack.length % 2 !== 0; + if (hasWidthArg && !haveWidth) { + width = stack.shift() + nominalWidthX; + } + + nStems += stack.length >> 1; + stack.length = 0; + haveWidth = true; + } + else if (v == "o4") { + if (stack.length > 1 && !haveWidth) { + width = stack.shift() + nominalWidthX; + haveWidth = true; + } + if (open) P.ClosePath(p); + + y += stack.pop(); + P.MoveTo(p, x, y); open = true; + } + else if (v == "o5") { + while (stack.length > 0) { + x += stack.shift(); + y += stack.shift(); + P.LineTo(p, x, y); + } + } + else if (v == "o6" || v == "o7") // hlineto || vlineto + { + var count = stack.length; + var isX = (v == "o6"); + + for (var j = 0; j < count; j++) { + var sval = stack.shift(); + + if (isX) x += sval; else y += sval; + isX = !isX; + P.LineTo(p, x, y); + } + } + else if (v == "o8" || v == "o24") // rrcurveto || rcurveline + { + var count = stack.length; + var index = 0; + while (index + 6 <= count) { + c1x = x + stack.shift(); + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + y = c2y + stack.shift(); + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + index += 6; + } + if (v == "o24") { + x += stack.shift(); + y += stack.shift(); + P.LineTo(p, x, y); + } + } + else if (v == "o11") break; + else if (v == "o1234" || v == "o1235" || v == "o1236" || v == "o1237")//if((v+"").slice(0,3)=="o12") + { + if (v == "o1234") { + c1x = x + stack.shift(); // dx1 + c1y = y; // dy1 + c2x = c1x + stack.shift(); // dx2 + c2y = c1y + stack.shift(); // dy2 + jpx = c2x + stack.shift(); // dx3 + jpy = c2y; // dy3 + c3x = jpx + stack.shift(); // dx4 + c3y = c2y; // dy4 + c4x = c3x + stack.shift(); // dx5 + c4y = y; // dy5 + x = c4x + stack.shift(); // dx6 + P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); + P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); + + } + if (v == "o1235") { + c1x = x + stack.shift(); // dx1 + c1y = y + stack.shift(); // dy1 + c2x = c1x + stack.shift(); // dx2 + c2y = c1y + stack.shift(); // dy2 + jpx = c2x + stack.shift(); // dx3 + jpy = c2y + stack.shift(); // dy3 + c3x = jpx + stack.shift(); // dx4 + c3y = jpy + stack.shift(); // dy4 + c4x = c3x + stack.shift(); // dx5 + c4y = c3y + stack.shift(); // dy5 + x = c4x + stack.shift(); // dx6 + y = c4y + stack.shift(); // dy6 + stack.shift(); // flex depth + P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); + P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); + } + if (v == "o1236") { + c1x = x + stack.shift(); // dx1 + c1y = y + stack.shift(); // dy1 + c2x = c1x + stack.shift(); // dx2 + c2y = c1y + stack.shift(); // dy2 + jpx = c2x + stack.shift(); // dx3 + jpy = c2y; // dy3 + c3x = jpx + stack.shift(); // dx4 + c3y = c2y; // dy4 + c4x = c3x + stack.shift(); // dx5 + c4y = c3y + stack.shift(); // dy5 + x = c4x + stack.shift(); // dx6 + P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); + P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); + } + if (v == "o1237") { + c1x = x + stack.shift(); // dx1 + c1y = y + stack.shift(); // dy1 + c2x = c1x + stack.shift(); // dx2 + c2y = c1y + stack.shift(); // dy2 + jpx = c2x + stack.shift(); // dx3 + jpy = c2y + stack.shift(); // dy3 + c3x = jpx + stack.shift(); // dx4 + c3y = jpy + stack.shift(); // dy4 + c4x = c3x + stack.shift(); // dx5 + c4y = c3y + stack.shift(); // dy5 + if (Math.abs(c4x - x) > Math.abs(c4y - y)) { + x = c4x + stack.shift(); + } else { + y = c4y + stack.shift(); + } + P.CurveTo(p, c1x, c1y, c2x, c2y, jpx, jpy); + P.CurveTo(p, c3x, c3y, c4x, c4y, x, y); + } + } + else if (v == "o14") { + if (stack.length > 0 && stack.length != 4 && !haveWidth) { + width = stack.shift() + font["nominalWidthX"]; + haveWidth = true; + } + if (stack.length == 4) // seac = standard encoding accented character + { + + var asb = 0; + var adx = stack.shift(); + var ady = stack.shift(); + var bchar = stack.shift(); + var achar = stack.shift(); + + + var bind = CFF.glyphBySE(font, bchar); + var aind = CFF.glyphBySE(font, achar); + + //console.log(bchar, bind); + //console.log(achar, aind); + //state.x=x; state.y=y; state.nStems=nStems; state.haveWidth=haveWidth; state.width=width; state.open=open; + + _drawCFF(font["CharStrings"][bind], state, font, pdct, p); + state.x = adx; state.y = ady; + _drawCFF(font["CharStrings"][aind], state, font, pdct, p); + + //x=state.x; y=state.y; nStems=state.nStems; haveWidth=state.haveWidth; width=state.width; open=state.open; + } + if (open) { P.ClosePath(p); open = false; } + } + else if (v == "o19" || v == "o20") { + var hasWidthArg; + + // The number of stem operators on the stack is always even. + // If the value is uneven, that means a width is specified. + hasWidthArg = stack.length % 2 !== 0; + if (hasWidthArg && !haveWidth) { + width = stack.shift() + nominalWidthX; + } + + nStems += stack.length >> 1; + stack.length = 0; + haveWidth = true; + + i += (nStems + 7) >> 3; + } + + else if (v == "o21") { + if (stack.length > 2 && !haveWidth) { + width = stack.shift() + nominalWidthX; + haveWidth = true; + } + + y += stack.pop(); + x += stack.pop(); + + if (open) P.ClosePath(p); + P.MoveTo(p, x, y); open = true; + } + else if (v == "o22") { + if (stack.length > 1 && !haveWidth) { + width = stack.shift() + nominalWidthX; + haveWidth = true; + } + + x += stack.pop(); + + if (open) P.ClosePath(p); + P.MoveTo(p, x, y); open = true; + } + else if (v == "o25") { + while (stack.length > 6) { + x += stack.shift(); + y += stack.shift(); + P.LineTo(p, x, y); + } + + c1x = x + stack.shift(); + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + y = c2y + stack.shift(); + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + } + else if (v == "o26") { + if (stack.length % 2) { + x += stack.shift(); + } + + while (stack.length > 0) { + c1x = x; + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x; + y = c2y + stack.shift(); + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + } + + } + else if (v == "o27") { + if (stack.length % 2) { + y += stack.shift(); + } + + while (stack.length > 0) { + c1x = x + stack.shift(); + c1y = y; + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + y = c2y; + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + } + } + else if (v == "o10" || v == "o29") // callsubr || callgsubr + { + var obj = (v == "o10" ? pdct : font); + if (stack.length == 0) { console.log("error: empty stack"); } + else { + var ind = stack.pop(); + var subr = obj["Subrs"][ind + obj["Bias"]]; + state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; + _drawCFF(subr, state, font, pdct, p); + x = state.x; y = state.y; nStems = state.nStems; haveWidth = state.haveWidth; width = state.width; open = state.open; + } + } + else if (v == "o30" || v == "o31") // vhcurveto || hvcurveto + { + var count, count1 = stack.length; + var index = 0; + var alternate = v == "o31"; + + count = count1 & ~2; + index += count1 - count; + + while (index < count) { + if (alternate) { + c1x = x + stack.shift(); + c1y = y; + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + y = c2y + stack.shift(); + if (count - index == 5) { x = c2x + stack.shift(); index++; } + else x = c2x; + alternate = false; + } + else { + c1x = x; + c1y = y + stack.shift(); + c2x = c1x + stack.shift(); + c2y = c1y + stack.shift(); + x = c2x + stack.shift(); + if (count - index == 5) { y = c2y + stack.shift(); index++; } + else y = c2y; + alternate = true; + } + P.CurveTo(p, c1x, c1y, c2x, c2y, x, y); + index += 4; + } + } + + else if ((v + "").charAt(0) == "o") { console.log("Unknown operation: " + v, cmds); throw v; } + else stack.push(v); + } + //console.log(cmds); + state.x = x; state.y = y; state.nStems = nStems; state.haveWidth = haveWidth; state.width = width; state.open = open; + } + + function initHB(hurl, resp) { + var codeLength = function (code) { + var len = 0; + if ((code & (0xffffffff - (1 << 7) + 1)) == 0) { len = 1; } + else if ((code & (0xffffffff - (1 << 11) + 1)) == 0) { len = 2; } + else if ((code & (0xffffffff - (1 << 16) + 1)) == 0) { len = 3; } + else if ((code & (0xffffffff - (1 << 21) + 1)) == 0) { len = 4; } + return len; + } + + fetch(hurl) + .then(function (x) { return x["arrayBuffer"](); }) + .then(function (ab) { return WebAssembly["instantiate"](ab); }) + .then(function (res) { + console.log("HB ready"); + var exp = res["instance"]["exports"], mem = exp["memory"]; + //mem["grow"](30); // each page is 64kb in size + var heapu8, u32, i32, f32; + var __lastFnt, blob, blobPtr, face, font; + + Typr["U"]["shapeHB"] = (function () { + + var toJson = function (ptr) { + var length = exp["hb_buffer_get_length"](ptr); + var result = []; + var iPtr32 = exp["hb_buffer_get_glyph_infos"](ptr, 0) >>> 2; + var pPtr32 = exp["hb_buffer_get_glyph_positions"](ptr, 0) >>> 2; + for (var i = 0; i < length; ++i) { + var a = iPtr32 + i * 5, b = pPtr32 + i * 5; + result.push({ + "g": u32[a + 0], + "cl": u32[a + 2], + "ax": i32[b + 0], + "ay": i32[b + 1], + "dx": i32[b + 2], + "dy": i32[b + 3] + }); + } + //console.log(result); + return result; + } + var te; + + return function (fnt, str, prm) { + var fdata = fnt["_data"], fn = fnt["name"]["postScriptName"]; + var ltr = prm["ltr"], fts = prm["fts"], axs = prm["axs"]; + if (fnt["fvar"] && axs == null) axs = fnt["fvar"][1][fnt["_index"]][2]; + + //var olen = mem.buffer.byteLength, nlen = 2*fdata.length+str.length*16 + 4e6; + //if(olen>>16)+4); //console.log("growing",nlen); + + heapu8 = new Uint8Array(mem.buffer); + u32 = new Uint32Array(mem.buffer); + i32 = new Int32Array(mem.buffer); + f32 = new Float32Array(mem.buffer); + + if (__lastFnt != fn) { + if (blob != null) { + exp["hb_blob_destroy"](blob); + exp["free"](blobPtr); + exp["hb_face_destroy"](face); + exp["hb_font_destroy"](font); + } + blobPtr = exp["malloc"](fdata.byteLength); heapu8.set(fdata, blobPtr); + blob = exp["hb_blob_create"](blobPtr, fdata.byteLength, 2, 0, 0); + face = exp["hb_face_create"](blob, fnt["_index"]); + font = exp["hb_font_create"](face) + __lastFnt = fn; + } + if (window["TextEncoder"] == null) { alert("Your browser is too old. Please, update it."); return; } + if (te == null) te = new window["TextEncoder"]("utf8"); + + var buffer = exp["hb_buffer_create"](); + var bytes = te["encode"](str); + var len = bytes.length, strp = exp["malloc"](len); heapu8.set(bytes, strp); + exp["hb_buffer_add_utf8"](buffer, strp, len, 0, len); + exp["free"](strp); + + var bin = Typr["B"]; + + var feat = 0; + if (fts) { + feat = exp["malloc"](16 * fts.length); + for (var i = 0; i < fts.length; i++) { + var fe = fts[i]; + var off = feat + i * 16, qo = off >>> 2; + bin.writeASCII(heapu8, off, fe[0].split("").reverse().join("")); + u32[qo + 1] = fe[1]; + u32[qo + 2] = fe[2]; + u32[qo + 3] = fe[3]; + } + //console.log(fts); + } + var vdat = 0; + if (axs && fnt["fvar"]) { + var axes = fnt["fvar"][0]; //console.log(axes, axs); + vdat = exp["malloc"](8 * axs.length); + for (var i = 0; i < axs.length; i++) { + var off = vdat + i * 8, qo = off >>> 2; + bin.writeASCII(heapu8, off, axes[i][0].split("").reverse().join("")); + f32[qo + 1] = axs[i]; + } + } + //*/ + + if (axs) exp["hb_font_set_variations"](font, vdat, axs.length); + exp["hb_buffer_set_direction"](buffer, ltr ? 4 : 5); + exp["hb_buffer_guess_segment_properties"](buffer); + exp["hb_shape"](font, buffer, feat, fts ? fts.length : 0); + var json = toJson(buffer)//buffer["json"](); + exp["hb_buffer_destroy"](buffer); + if (fts) exp["free"](feat); + if (axs) exp["free"](vdat); + + var arr = json.slice(0); if (!ltr) arr.reverse(); + var ci = 0, bi = 0; // character index, binary index + for (var i = 1; i < arr.length; i++) { + var gl = arr[i], cl = gl["cl"]; + while (true) { + var cpt = str.codePointAt(ci), cln = codeLength(cpt); + if (bi + cln <= cl) { bi += cln; ci += cpt <= 0xffff ? 1 : 2; } + else break; + } + //while(bi+codeLength(str.charCodeAt(ci)) <=cl) { bi+=codeLength(str.charCodeAt(ci)); ci++; } + gl["cl"] = ci; + } + return json; + } + }()); + resp(); + }); + } + + return { "shape": shape, "shapeToPath": shapeToPath, "codeToGlyph": codeToGlyph, "glyphToPath": glyphToPath, "pathToSVG": pathToSVG, "SVGToPath": SVGToPath, "pathToContext": pathToContext, "initHB": initHB }; +}(); + + +export default Typr; \ No newline at end of file diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index 245cb440ac..f5f5b0bb16 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -30,8 +30,8 @@ * loading fonts from files and urls, and extracting points from their paths. */ -// import Typr import Typr from './lib/Typr.js'; + import { createFromCommands } from '@davepagurek/bezier-path'; function font(p5, fn) { @@ -598,10 +598,9 @@ function font(p5, fn) { } catch (err) { // failed to parse the font, load it as a simple FontFace let ident = name || path.substring(path.lastIndexOf('/') + 1); - console.warn(`WARNING: No font data for '${ident}'`); + console.warn(`WARN: No glyph data for '${ident}', retrying as FontFace`); try { // create a FontFace object and pass it to p5.Font - console.log(`Retrying '${ident}' without font-data: '${path}'`); pfont = await create(this, name, path, descriptors); } catch (err) { @@ -619,9 +618,7 @@ function font(p5, fn) { let face = createFontFace(name, path, descriptors, rawFont); // load if we need to - if (face.status !== 'loaded') { - await face.load(); - } + if (face.status !== 'loaded') await face.load(); // add it to the document document.fonts.add(face); diff --git a/src/type/text2d.js b/src/type/text2d.js index f0e088f58b..a4c9e55d4e 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -179,7 +179,7 @@ function text2d(p5, fn) { * @returns - the width of the text in pixels */ Renderer.prototype.textWidth = function (theText) { - let lines = this._processLines(theText, null, null); + let lines = this._processLines(theText); // return the max width of the lines (using tight bounds) return Math.max(...lines.map(l => this._textWidthSingle(l))); }; @@ -191,7 +191,7 @@ function text2d(p5, fn) { */ Renderer.prototype.fontWidth = function (theText) { // return the max width of the lines (using loose bounds) - let lines = this._processLines(theText, null, null); + let lines = this._processLines(theText); return Math.max(...lines.map(l => this._fontWidthSingle(l))); }; @@ -279,27 +279,22 @@ function text2d(p5, fn) { family += '-' + font.name.fontSubfamily; } } - - if (typeof family !== 'string') { - throw Error('null font passed to textFont', font); + else if (typeof font === 'string') { + // direct set the font-string if it contains size + if (typeof size === 'undefined' && /[.0-9]+(%|em|p[xt])/.test(family)) { + //console.log('direct set font-string: ', family); + ({ family, size } = this._directSetFontString(family)); + } } + if (typeof family !== 'string') throw Error('null font in textFont()'); + // handle two-arg case: textFont(font, options) if (arguments.length === 2 && typeof size === 'object') { options = size; size = undefined; } - // check for font-string with size in first arg - console.log('family: ', family, 'size: ', size); - - // removed ^ from regex to allow direct set of font strings including size - if (typeof size === 'undefined' && /[.0-9]+(%|em|p[xt])/.test(family)) { - console.log('direct font string: ', family); - - ({ family, size } = this._directSetFontString(family)); - } - // update font properties in this.states this.states.textFont = { font, family, size }; @@ -313,7 +308,7 @@ function text2d(p5, fn) { this.textProperties(options); } - return this._applyTextProperties(); + return this._applyTextProperties(); } Renderer.prototype._directSetFontString = function (font, debug = 0) { @@ -323,7 +318,7 @@ function text2d(p5, fn) { props[p] = RendererTextProps[p].default; return props; }, {}); - + let el = this._cachedDiv(defaults); el.style.font = font; let style = getComputedStyle(el); @@ -331,10 +326,10 @@ function text2d(p5, fn) { this.states[prop] = style[prop]; if (debug) console.log(' this.states.' + prop + '="' + style[prop] + '"'); }); - + if (debug) console.log(' this.states.textFont="' + style.fontFamily + '"'); if (debug) console.log(' this.states.textSize="' + style.fontSize + '"'); - + return { family: style.fontFamily, size: style.fontSize }; } diff --git a/test/manual-test-examples/type/index.html b/test/manual-test-examples/type/index.html index e2f605bbe2..3beba27d44 100755 --- a/test/manual-test-examples/type/index.html +++ b/test/manual-test-examples/type/index.html @@ -545,45 +545,6 @@ }; - let manualLineBreaksLeft = function (p) { - let x = 10, y = 120, s, showBB = 0, h = 54.5; - p.setup = function () { - p.createCanvas(900, 400); - p.textSize(30); - p.textLeading(26); - p.stroke(0) && p.strokeWeight(1) && p.line(0, y, p.width, y); //h-line - - //1 - s = 'LEFT TOP\nalignment\nis easy.'; - p.fill(0) && p.noStroke() && p.textAlign(p.LEFT, p.TOP) && p.text(s, x, y); - //p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - if (showBB) p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - p.stroke(0) && p.strokeWeight(1) && p.line(x, 0, x, p.height); // v-line - - //2 - x += 165, s = 'LEFT BASELINE\nalignment\nis easy.'; - p.fill(0) && p.noStroke() && p.textAlign(p.LEFT, p.BASELINE) && p.text(s, x, y); - //p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - if (showBB) p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - p.stroke(0) && p.strokeWeight(1) && p.line(x, 0, x, p.height); // v-line - - //3 - x += 250, s = 'LEFT CENTER\nalignment\nis easy.'; - p.fill(0) && p.noStroke() && p.textAlign(p.LEFT, p.CENTER) && p.text(s, x, y); - if (showBB) p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - p.stroke(0) && p.strokeWeight(1) && p.line(x, 0, x, p.height); // v-line - - //4 - x += 225, s = 'LEFT BOTTOM\nalignment\nis easy.'; - p.fill(0) && p.noStroke() && p.textAlign(p.LEFT, p.BOTTOM) && p.text(s, x, y); - //p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - if (showBB) p.noFill() && p.stroke(0) && p.rect(...Object.values(p.textBounds(s, x, y))); - p.stroke(0) && p.strokeWeight(1) && p.line(x, 0, x, p.height); // v-line - - p.loadImage('img/p5v2.jpg').then((img) => p.image(img, p.width - 20, 0)); - } - } - let manualLineBreaks = function (p) { let x, y, s, showBB = 0; @@ -2487,7 +2448,6 @@ new p5(customBoundsMulti_RectModeRadius, 'customBoundsMulti_RectModeRadius'); new p5(loadedBoundsWithPoints, 'loadedBoundsWithPoints'); - new p5(manualLineBreaksLeft, 'manualLineBreaksLeft'); new p5(manualLineBreaks, 'manualLineBreaks'); new p5(singleWordBounds, 'singleWordBounds'); new p5(textVerticalAlign, 'textVerticalAlign'); @@ -2619,11 +2579,6 @@

singleWordBounds

-
-

manualLineBreaksLeft

- -
-

manualLineBreaks

From 450be6db860e1fcccf62c2ec6ae69f176774e1f8 Mon Sep 17 00:00:00 2001 From: dhowe Date: Fri, 27 Dec 2024 16:37:55 -0500 Subject: [PATCH 08/27] add tests for pr --- .../type/font/Lato-Regular.woff | Bin 0 -> 31700 bytes test/unit/assets/Lato-Regular.woff | Bin 0 -> 31700 bytes test/unit/visual/cases/typography.js | 1 - .../textFont/with a woff font file/000.png | Bin 0 -> 2048 bytes .../with a woff font file/metadata.json | 3 +++ .../000.png | Bin 2766 -> 0 bytes .../001.png | Bin 2766 -> 0 bytes .../002.png | Bin 2739 -> 0 bytes .../003.png | Bin 2694 -> 0 bytes .../004.png | Bin 2670 -> 0 bytes 10 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 test/manual-test-examples/type/font/Lato-Regular.woff create mode 100644 test/unit/assets/Lato-Regular.woff create mode 100644 test/unit/visual/screenshots/Typography/textFont/with a woff font file/000.png create mode 100644 test/unit/visual/screenshots/Typography/textFont/with a woff font file/metadata.json delete mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/000.png delete mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/001.png delete mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/002.png delete mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/003.png delete mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/004.png diff --git a/test/manual-test-examples/type/font/Lato-Regular.woff b/test/manual-test-examples/type/font/Lato-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..c3321de244b825216143de62750bcf45cebd0e17 GIT binary patch literal 31700 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 BY#aap literal 0 HcmV?d00001 diff --git a/test/unit/assets/Lato-Regular.woff b/test/unit/assets/Lato-Regular.woff new file mode 100644 index 0000000000000000000000000000000000000000..c3321de244b825216143de62750bcf45cebd0e17 GIT binary patch literal 31700 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 BY#aap literal 0 HcmV?d00001 diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index 83a242861b..73aff5a8be 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -92,7 +92,6 @@ visualSuite("Typography", function () { const font = await p5.loadFont( 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap' ); - for (let weight = 400; weight <= 800; weight += 100) { p5.background(255); p5.textFont(font); diff --git a/test/unit/visual/screenshots/Typography/textFont/with a woff font file/000.png b/test/unit/visual/screenshots/Typography/textFont/with a woff font file/000.png new file mode 100644 index 0000000000000000000000000000000000000000..525c649b2dd800c2e2df42a70ec7bf14d7a8f6f2 GIT binary patch literal 2048 zcmds&`#%#31IA~|{kByrM6NN+G`HhgSz8<7Fq@{_Vv{9oV>oguj#W%Gn#)PbEp62+ zx1!al@IiYM(j&f=F?$j*;I6Yn9UTe)Xd8T5p-^<~ z@M!1^nN}ofp|v`MZ3mP)yMUl$K@BfKrx7nQM&8V%O+=jdDfsbZ*UNz>M-Ruxqp&bP zY82PnNk_%1Lu^SyT?fY)>{aQu>rhA5D#g$~{V(VW(R{yKtlz4Z{;D*<%>fx5y zq;vC72|sTM3%adz8gzuvJgn*pZ+0_k6(|)$lH9lEWL~pA{!qo%W1FiD^_k6Hdz#&> z6=$mhvR-x8bN1w5n!041d=HZ~v`eD@y0+bt>?^r&-qu~M)nw9f_blCH(M|%0`r3oq z2SRL-0V4p#msS+Ou#&!KP}-4$e&+8o#W`^0Cwl*p-6||vSN7DtUSz#qRx|99Rip2_ z!Y*CUTCH|rgBV#2YxnIeMk;kFikLrijwLW8YLeD$k^Ey|Y_t)nb@)!;wJu{bzb* zUV5d_1sP5et_nSbX-w{WY*{I|b7H=w zaIq05J03Oe2Ppw+?(kb8(M<6n1%0LC>XGREe(u8Vq0sKybHFX-O87W~r2ylBVl1GX z*Z>P8Av0T5#Z^%#NW-y1*TYUd&636%$BM6LB{t}cyh~7lRN*H4CFk=Bpzq}s2*x(E z@1j?c-$ImPwSB5&zuQkgZ8Y+TTd~ZoWL%}R9q66>#aHF+dyB0@b(NUKQ9*mxo$JwH zQz~}(1jNa)o<3jwsRJk+6{S&n8tZHzq3+X3i8R=ZL0Iv{pl1$zGqexS;h(VP8+XsW z%=)vj-*PH!-x{wb*o{;8rVlt`_uMd)TZ@Vg4!S&d zYLGwh$zK*HZFH*hwbwX#Bi_L$GT||}@!+8k{t&QHX2MRoznaJQ&jc=E;PnLpqzX{k zWA*^403@o8$U(SrqyXF)5)w-Mbd#;{B0P;VrxH^|*^R%I(cj+A13wV8%e|9(vWcvK z!^;Us?dc&F7!&dXV?H4w@8ZPgs9DW?q})sS>7K*8GT@G3oz}tWyglUB7nlUw>|jiz zH)pWgZ5*2+6cOXtBb=KCc9kQ@`I2lMU$RPk&KLy(G!96eDs=O!yXB~hiYDd;=Y@rG z0U^9TubEI%D4z~oxN3Qg*?ltJ6fTJZ#lieXxf->6bNn$b1KMaS}*G z+6O%3n$$(KBwtGPx3e(9551%>h;N+?S5E_*ez?^ez@!|tu!@k_sKXB<4OZBiQs>1dgmX8UT*{;wW!nJ{myl-P;S1PN zF52eAve!x~UdFhryRo6+>YT$_X+fVMomna5ovNHM!#;idtF<{=bZ=hg^M2)4XL^zQ zuZSymByB~JK?}L`1rqTA+?m_<05-1TEB$+ZK_>hQBFII#Rq^ue3K!*-a%f)9QJw@* zJJt3=%?GsYQ3OkIlU#<`vz~DEu4=gH&0%O@=!OG|tJkUAkz#0_<|vuVRE@8qlTq}4dvt3@ak zgcQ#%m|rv-|74&$CV*8;YQ1)A2^R8?^>4o&(JOy4$QpiiE0KFEJ}{Kc_`_xB&-qS4 z>f7~f*>-+H7qyyWgOVay{?2aD5avg|JSi^C7{lft#_ht8UcKyDfwRjeU$@_&3S;^2lCl^w*|CE?nnJ>>Z4VbQ`XX zU)IIl31!8lU@y|UgR!}j8yRe8m%JN!wZ)ZR0^HD%Y4C$@Uere-bhOh&!aGf0UxEo0 zgzO)w=_bEe);rxu4zs9f*a~OTQ1FHVbZA$_`u@+YEWNQ|bvi1aD%3M<0b6yHs^mYX fYyLlgn4C3DQh7{@RhQS;=A{FCFahW~R8;oA!?dn3 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textFont/with a woff font file/metadata.json b/test/unit/visual/screenshots/Typography/textFont/with a woff font file/metadata.json new file mode 100644 index 0000000000..2d4bfe30da --- /dev/null +++ b/test/unit/visual/screenshots/Typography/textFont/with a woff font file/metadata.json @@ -0,0 +1,3 @@ +{ + "numScreenshots": 1 +} \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/000.png b/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/000.png deleted file mode 100644 index a0a4df342877a72b1bf18e925028eedcbe19bdfa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2766 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 AumAu6 diff --git a/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/003.png b/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/003.png deleted file mode 100644 index 5e8e4be2f211c643cdf6c5c7f40dae2b9ba9a651..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2694 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 L-wJn z*csZF`V`GD%>LFl;7oNR!rz&gIAx3xFmwoZ%fYRh-vNxBu|?D5X&<+@?>98?JDAaI z%@AkKN6jwGE-bhNOREKu``?NB=g!?3&C?9T3}Ss-IyALAFiY6?qe%(L$;p?YUMiq6 zj@v!)OywMuz9&*~7e(_y<^XlzwVvnr1gW?@_S~*tQGV1nMhrBY{F{W|{{ppR&-6uEs;b%I?FZ zi|ygzDSzl+&-SHWa(F*d=hRw#tI3m@!ZlOznlDqy%_MAp!{*~`is9a9iJr&jeAUTU z80AD>N%n}-<2-7Anh)k+hth*?_QKG;`cp4u>qSMHWJv)}PEQ<;Z7B910wdg#xwrh7BjH#@@*Qj2xM4Nv~r zmn=N?n5ZN~87$W=HxFmZJ869g+!W|b5mJ{)E-MyRgQKfvop;#9Eopn-Cv+w@r)y0u zN_1cBej5!h-rxFrMyV1(;0vJka?o{RwNBe3j)GwNLC68kI>=FHIzl+bSM+Y3i zd}4sPW^W<$;_GuP4}a0-vekXCa7$sW02%MOMr3XaMk|PB^yn;4Rc$P<5mabe3dIsExs|F{IV-SiEiZM-@7#o!rzANdv+h?o_XTA@F5Vpx!4+PVK4Yg zCy16ia}e@`+LtsjkRf>`^ydmQ<)^AKNa=PrTYWOS6!tX^#%rYRvqqdk5gI$WQEb@x414Ax}T(_Jt_I3j=@a5 zvju~WX0xs7TA|N*%Kf{vi7Jb|^>Il`&N3ev>{*2>;!7ksV%A2AOr2VT_QSRxgKTQ4 zYwfqqBmUX*Q=Xi<-~hLrvaNHRo07ON`62M$twvYEo$Cp4t=G6v-`B^VdweCOP!-7e z7|U1tKbD*ezc8@yt#6Z!#i$by)z-LmUopXXzlw(^3d zH)Ja~7t3SYWUNiJVQY^HMV0)h2;T5vrF+wIVY_Q7&yLb(gmfQjFp3!Y8S?w*Dpr-1 zeBN=j(QQZ$AHKf`q=f!;qP>1HdFlfs)*MI~!1?LX1pAjkESOW(XQ~_KPmtF1Z z?}je-mO*b%f{8e9F-(KYnWnqr@Z)dM%&Z6~PM}SN)WQpnHP2V!HRz1`Bku|71-%iw z``l&pnL^1-X0_FW)j>$HHg9=inf>mU7pB3>IIm9k}88os%)K39{&Fv2)CgddKnqaadL0zotQw77stz zwjpI4{8+lm>bo`HP$?YUr07jd#~RLlu}0;zCp- zk3%fnLskZO$GecY$H@NVixW!yg!ICrBHmvIrHJU7f+g_pC^-}x-f zyXz8l`BBo1%0>+?ee1({%Ghh$eY{N`u<_+Zl14z86e$O!Y4OY%EX^lrn>%SrkIy8|RmGPMC2kW!3mQ@o1vG9{ali*9JXXotd1p5St(N3u{EgnrMI6iEOD^g2`UEsX$&AUH40%s z$u^a;CF^=orwJdEmbv@XJSPVPo)1#X^FhiQ0cqngvz<|$Mi*9^GeW(@E&;TWhnHQ) zN?}-aZ~OI+F|6nsYe>CnM$NJsPmLl=z2o6r-{p#?b*@iS?=+>(JeW_`L~$fbK81xFmo8@ z#BmBe)dB-w^o$bOYC{7eZ*LoCUbaewLC4Ds&YC=x<)=)Fr>HIk=1S)!_296R1Q2@p zBZP~ZKu$AA!Gk;3=q(xC$b*?2P)i{r=aqsG*;O%%Cs&o(YT2Tc1VYVQnA=vQ7A{ZKt|O z01d;udd0KvU9CFdT^UCJe;u%rberQYT#=5J2)8a0Nmp|l1QVS*JD~RiqM5@Ewik4d zY-f2+1@%r8wMeKz-=hcyrlX^VPbKd3ZOM@3B8|#EKvhQLlMJ&I!7=1xk>;az*rWaGTY6=-_r*3j z;7r(#)&%~mITl$wu5YRfCI39&vyCZvULKL96}V9yN1ee&o;(<@e|nMIu Date: Sat, 28 Dec 2024 17:47:02 -0500 Subject: [PATCH 09/27] re-add missing screenshots, add direct-set test, remove opentype.js --- package-lock.json | 26 -------------- package.json | 1 - test/unit/visual/cases/typography.js | 33 ++++++++++-------- .../With the default font/000.png | Bin 829 -> 0 bytes .../With the default monospace font/000.png | Bin 830 -> 0 bytes .../metadata.json | 3 -- .../with a directly set font string/000.png | Bin 0 -> 2510 bytes .../metadata.json | 0 .../000.png | Bin 0 -> 2766 bytes .../001.png | Bin 0 -> 2766 bytes .../002.png | Bin 0 -> 2739 bytes .../003.png | Bin 0 -> 2694 bytes .../004.png | Bin 0 -> 2670 bytes 13 files changed, 19 insertions(+), 44 deletions(-) delete mode 100644 test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default font/000.png delete mode 100644 test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default monospace font/000.png delete mode 100644 test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default monospace font/metadata.json create mode 100644 test/unit/visual/screenshots/Typography/textFont/with a directly set font string/000.png rename test/unit/visual/screenshots/Typography/{textFont() with default fonts/With the default font => textFont/with a directly set font string}/metadata.json (100%) create mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/000.png create mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/001.png create mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/002.png create mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/003.png create mode 100644 test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/004.png diff --git a/package-lock.json b/package-lock.json index 9a0cbede14..26bc055005 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,6 @@ "gifenc": "^1.0.3", "libtess": "^1.2.2", "omggif": "^1.0.10", - "opentype.js": "^1.3.1", "pako": "^2.1.0" }, "devDependencies": { @@ -8129,21 +8128,6 @@ "opencollective-postinstall": "index.js" } }, - "node_modules/opentype.js": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/opentype.js/-/opentype.js-1.3.4.tgz", - "integrity": "sha512-d2JE9RP/6uagpQAVtJoF0pJJA/fgai89Cc50Yp0EJHk+eLp6QQ7gBoblsnubRULNY132I0J1QKMJ+JTbMqz4sw==", - "dependencies": { - "string.prototype.codepointat": "^0.2.1", - "tiny-inflate": "^1.0.3" - }, - "bin": { - "ot": "bin/ot" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -10051,11 +10035,6 @@ "node": ">=8" } }, - "node_modules/string.prototype.codepointat": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz", - "integrity": "sha512-2cBVCj6I4IOvEnjgO/hWqXjqBGsY+zwPmHl12Srk9IXSZ56Jwwmy+66XO5Iut/oQVR7t5ihYdLB0GMa4alEUcg==" - }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -10219,11 +10198,6 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==" - }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", diff --git a/package.json b/package.json index 5461c57510..b0abf95b81 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,6 @@ "gifenc": "^1.0.3", "libtess": "^1.2.2", "omggif": "^1.0.10", - "opentype.js": "^1.3.1", "pako": "^2.1.0" }, "devDependencies": { diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index 73aff5a8be..7246bb6413 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -19,7 +19,7 @@ visualSuite("Typography", function () { screenshot(); }); - visualTest('with a Google Font URL', async function(p5, screenshot) { + visualTest('with a Google Font URL', async function (p5, screenshot) { p5.createCanvas(100, 100); const font = await p5.loadFont( 'https://fonts.googleapis.com/css2?family=Bricolage+Grotesque:opsz,wght@12..96,200..800&display=swap' @@ -31,7 +31,7 @@ visualSuite("Typography", function () { screenshot(); }); - visualTest('with a font file', async function(p5, screenshot) { + visualTest('with a font file', async function (p5, screenshot) { p5.createCanvas(100, 100); const font = await p5.loadFont( '/unit/assets/Inconsolata-Bold.ttf' @@ -55,8 +55,14 @@ visualSuite("Typography", function () { screenshot(); }); + visualTest('with a directly set font string', async function (p5, screenshot) { + p5.createCanvas(100, 100); + p5.textFont("italic bold 32px Georgia"); + p5.text('p5*js', 0, 10, p5.width); + screenshot(); + }); - visualTest('with a font file in WebGL', async function(p5, screenshot) { + visualTest('with a font file in WebGL', async function (p5, screenshot) { p5.createCanvas(100, 100, p5.WEBGL); const font = await p5.loadFont( '/unit/assets/Inconsolata-Bold.ttf' @@ -64,12 +70,12 @@ visualSuite("Typography", function () { p5.textFont(font); p5.textAlign(p5.LEFT, p5.TOP); p5.textSize(35); - p5.text('p5*js', -p5.width/2, -p5.height/2 + 10, p5.width); + p5.text('p5*js', -p5.width / 2, -p5.height / 2 + 10, p5.width); screenshot(); }); }); - visualSuite('textWeight', function() { + visualSuite('textWeight', function () { visualTest('can control non-variable fonts', async function (p5, screenshot) { p5.createCanvas(100, 100); const font = await p5.loadFont( @@ -109,7 +115,6 @@ visualSuite("Typography", function () { '/unit/assets/BricolageGrotesque-Variable.ttf', { weight: '200 800' } ); - for (let weight = 400; weight <= 800; weight += 100) { p5.background(255); p5.textFont(font); @@ -422,8 +427,8 @@ visualSuite("Typography", function () { }); }); - visualSuite('textToPoints', function() { - visualTest('Fonts can be converted to points', async function(p5, 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' @@ -438,7 +443,7 @@ visualSuite("Typography", function () { screenshot(); }); - visualTest('Sampling density can be changed', async function(p5, 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' @@ -454,7 +459,7 @@ visualSuite("Typography", function () { }); for (const mode of ['RADIANS', 'DEGREES']) { - visualTest(`Fonts point angles work in ${mode} mode`, async function(p5, screenshot) { + visualTest(`Fonts point angles work in ${mode} mode`, async function (p5, screenshot) { p5.createCanvas(100, 100); const font = await p5.loadFont( '/unit/assets/Inconsolata-Bold.ttf' @@ -481,8 +486,8 @@ visualSuite("Typography", function () { } }); - visualSuite('textToContours', function() { - visualTest('Fonts can be converted to points grouped by contour', async function(p5, 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' @@ -502,8 +507,8 @@ visualSuite("Typography", function () { }); }); - visualSuite('textToPaths', function() { - visualTest('Fonts can be converted to drawing context commands', async function(p5, 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' diff --git a/test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default font/000.png b/test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default font/000.png deleted file mode 100644 index 9412be344069b600d55c68b79ad7ebc049b63ed3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 829 zcmeAS@N?(olHy`uVBq!ia0vp^Mj*_=1|;R|J2nC-#^NA%Cx&(BWL`2bFn#xQaSX|D zemgC4MPHyu+k9bH&eoU-(ld=qj9P=HaB~(a9%Y@VQlzwqM=?etr7y*=DA6NE(MWVI zU#HK+DM2ZG;y3cw#>U6ruYdJr{pb0=ZvTGw``f+uaj$Eyhd57NGfV4Z^NSM}304J? zJ1(6$r^~>`xVu3-F5lJtRfFt-s)WVj6`XUr52Pg66x@Bic2!Zz_Kn626?`TP+6~)} zg~caia_pSwaJ%4}T7lS(X~~;q6;eeP?QOh%fH|Q#v6S%}lW^m=1G(I5cgn5un3(P` zUuH(q4?_di9RZIPK0Q!&J3Do!>A`*T8Enry$Y)$E_G7Z5x>MHr=IP3ZG*3-DcWl*- zXdamj?CPm=q^0JpWk1HSy`g;CiTRD!rj_s7&2}T_yY@Wg*E%}y+Oy1*j^7GPm@2u8 zX9n*a20I2@=Zt?FKHqI(|v8{r69G zCqA4nwWi2(=i;fn=ex9vq-JowVVw3PLM}tp_v%X<1Kt<%S1!s3-#|zNy%D z-<#cYV|~4fr}fx!<`}WRV>-Mx@YKrv2RB5D6$Lq0+pqOs!IS-#xx~NL<*H9_7;j12 z+v8o!|5&A8U9V{-KCid0W3BPE($WHt7Z>^uC0su#(eLIWz&kDIu`gSxUBQY6qNZ0W z#li%mmqz?t{?w@Pxns(XV*;Tw>LnNNN|zIxyeh+W_2QLFYJMdBU3{fwwcKa!A0gXh z;&Lh^g7n(D*F2SaSZHtg=-?uCx1b}Fefifc>0s}kC*djRZ)Uq;l9HTGRg#LU&CM?d vyt*njyy%=L@-gKyv$iJD8Ujtb{;+c_m}RW^>d{qTeqiu)^>bP0l+XkKjQ?(; diff --git a/test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default monospace font/000.png b/test/unit/visual/screenshots/Typography/textFont() with default fonts/With the default monospace font/000.png deleted file mode 100644 index a88804ae7178954bfcbab941518e7fe701dfa3ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 830 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 AumAu6 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/003.png b/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/003.png new file mode 100644 index 0000000000000000000000000000000000000000..5e8e4be2f211c643cdf6c5c7f40dae2b9ba9a651 GIT binary patch literal 2694 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 L-wJn z*csZF`V`GD%>LFl;7oNR!rz&gIAx3xFmwoZ%fYRh-vNxBu|?D5X&<+@?>98?JDAaI z%@AkKN6jwGE-bhNOREKu``?NB=g!?3&C?9T3}Ss-IyALAFiY6?qe%(L$;p?YUMiq6 zj@v!)OywMuz9&*~7e(_y<^XlzwVvnr1gW?@_S~*tQGV1nMhrBY{F{W|{{ppR&-6uEs;b%I?FZ zi|ygzDSzl+&-SHWa(F*d=hRw#tI3m@!ZlOznlDqy%_MAp!{*~`is9a9iJr&jeAUTU z80AD>N%n}-<2-7Anh)k+hth*?_QKG;`cp4u>qSMHWJv)}PEQ<;Z7B910wdg#xwrh7BjH#@@*Qj2xM4Nv~r zmn=N?n5ZN~87$W=HxFmZJ869g+!W|b5mJ{)E-MyRgQKfvop;#9Eopn-Cv+w@r)y0u zN_1cBej5!h-rxFrMyV1(;0vJka?o{RwNBe3j)GwNLC68kI>=FHIzl+bSM+Y3i zd}4sPW^W<$;_GuP4}a0-vekXCa7$sW02%MOMr3XaMk|PB^yn;4Rc$P<5mabe3dIsExs|F{IV-SiEiZM-@7#o!rzANdv+h?o_XTA@F5Vpx!4+PVK4Yg zCy16ia}e@`+LtsjkRf>`^ydmQ<)^AKNa=PrTYWOS6!tX^#%rYRvqqdk5gI$WQEb@x414Ax}T(_Jt_I3j=@a5 zvju~WX0xs7TA|N*%Kf{vi7Jb|^>Il`&N3ev>{*2>;!7ksV%A2AOr2VT_QSRxgKTQ4 zYwfqqBmUX*Q=Xi<-~hLrvaNHRo07ON`62M$twvYEo$Cp4t=G6v-`B^VdweCOP!-7e z7|U1tKbD*ezc8@yt#6Z!#i$by)z-LmUopXXzlw(^3d zH)Ja~7t3SYWUNiJVQY^HMV0)h2;T5vrF+wIVY_Q7&yLb(gmfQjFp3!Y8S?w*Dpr-1 zeBN=j(QQZ$AHKf`q=f!;qP>1HdFlfs)*MI~!1?LX1pAjkESOW(XQ~_KPmtF1Z z?}je-mO*b%f{8e9F-(KYnWnqr@Z)dM%&Z6~PM}SN)WQpnHP2V!HRz1`Bku|71-%iw z``l&pnL^1-X0_FW)j>$HHg9=inf>mU7pB3>IIm9k}88os%)K39{&Fv2)CgddKnqaadL0zotQw77stz zwjpI4{8+lm>bo`HP$?YUr07jd#~RLlu}0;zCp- zk3%fnLskZO$GecY$H@NVixW!yg!ICrBHmvIrHJU7f+g_pC^-}x-f zyXz8l`BBo1%0>+?ee1({%Ghh$eY{N`u<_+Zl14z86e$O!Y4OY%EX^lrn>%SrkIy8|RmGPMC2kW!3mQ@o1vG9{ali*9JXXotd1p5St(N3u{EgnrMI6iEOD^g2`UEsX$&AUH40%s z$u^a;CF^=orwJdEmbv@XJSPVPo)1#X^FhiQ0cqngvz<|$Mi*9^GeW(@E&;TWhnHQ) zN?}-aZ~OI+F|6nsYe>CnM$NJsPmLl=z2o6r-{p#?b*@iS?=+>(JeW_`L~$fbK81xFmo8@ z#BmBe)dB-w^o$bOYC{7eZ*LoCUbaewLC4Ds&YC=x<)=)Fr>HIk=1S)!_296R1Q2@p zBZP~ZKu$AA!Gk;3=q(xC$b*?2P)i{r=aqsG*;O%%Cs&o(YT2Tc1VYVQnA=vQ7A{ZKt|O z01d;udd0KvU9CFdT^UCJe;u%rberQYT#=5J2)8a0Nmp|l1QVS*JD~RiqM5@Ewik4d zY-f2+1@%r8wMeKz-=hcyrlX^VPbKd3ZOM@3B8|#EKvhQLlMJ&I!7=1xk>;az*rWaGTY6=-_r*3j z;7r(#)&%~mITl$wu5YRfCI39&vyCZvULKL96}V9yN1ee&o;(<@e|nMIu Date: Sat, 28 Dec 2024 18:13:38 -0500 Subject: [PATCH 10/27] regenerating missing/failing screenshots --- src/type/text2d.js | 17 +++++++++-------- test/unit/visual/cases/typography.js | 10 ++++++---- .../000.png | Bin 16023 -> 15259 bytes .../000.png | Bin 34629 -> 34185 bytes .../000.png | Bin 32266 -> 32362 bytes .../all alignments with single line/000.png | Bin 0 -> 12800 bytes .../all alignments with single word/000.png | Bin 3787 -> 12800 bytes .../000.png | Bin 2766 -> 2466 bytes 8 files changed, 15 insertions(+), 12 deletions(-) create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/000.png diff --git a/src/type/text2d.js b/src/type/text2d.js index a4c9e55d4e..8d055357d4 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -1057,14 +1057,15 @@ function text2d(p5, fn) { this._applyFontString(); // set these after the font so they're not overridden - this.textDrawingContext().direction = this.states.direction; - this.textDrawingContext().textAlign = this.states.textAlign; - this.textDrawingContext().textBaseline = this.states.textBaseline; + let context = this.textDrawingContext(); + context.direction = this.states.direction; + context.textAlign = this.states.textAlign; + context.textBaseline = this.states.textBaseline; // set manually as (still) not fully supported as part of font-string let stretch = this.states.fontStretch; - if (FontStretchKeys.includes(stretch) && this.textDrawingContext().fontStretch !== stretch) { - this.textDrawingContext().fontStretch = stretch; + if (FontStretchKeys.includes(stretch) && context.fontStretch !== stretch) { + context.fontStretch = stretch; } // apply each property in queue after the font so they're not overridden @@ -1072,12 +1073,12 @@ function text2d(p5, fn) { let [prop, val] = contextQueue.shift(); if (debug) console.log('apply context property "' + prop + '" = "' + val + '"'); - this.textDrawingContext()[prop] = val; + context[prop] = val; // check if the value was set successfully - if (this.textDrawingContext()[prop] !== val) { + if (context[prop] !== val) { console.warn(`Unable to set '${prop}' property on context2d. It may not be supported.`); // FES? - console.log('Expected "' + val + '" but got: "' + this.textDrawingContext()[prop] + '"'); + console.log('Expected "' + val + '" but got: "' + context[prop] + '"'); } } diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index 7246bb6413..e112dd3161 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -118,6 +118,8 @@ visualSuite("Typography", function () { for (let weight = 400; weight <= 800; weight += 100) { p5.background(255); p5.textFont(font); + console.log(p5.textProperties()); + p5.textAlign(p5.LEFT, p5.TOP); p5.textSize(35); p5.textWeight(weight); @@ -127,8 +129,8 @@ visualSuite("Typography", function () { }); }); - visualSuite("textAlign", function () { // TEMPORARY SKIP - /*visualTest.skip("all alignments with single word", function (p5, screenshot) { + visualSuite("textAlign", function () { + visualTest("all alignments with single word", function (p5, screenshot) { const alignments = [ { alignX: p5.LEFT, alignY: p5.TOP }, { alignX: p5.CENTER, alignY: p5.TOP }, @@ -154,7 +156,7 @@ visualSuite("Typography", function () { screenshot(); }); - visualTest.skip("all alignments with single line", function (p5, screenshot) { + visualTest("all alignments with single line", function (p5, screenshot) { const alignments = [ { alignX: p5.LEFT, alignY: p5.TOP }, { alignX: p5.CENTER, alignY: p5.TOP }, @@ -178,7 +180,7 @@ visualSuite("Typography", function () { p5.rect(bb.x, bb.y, bb.w, bb.h); }); screenshot(); - });*/ + }); visualTest("all alignments with multi-lines and wrap word", function (p5, screenshot) { diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/000.png index 7687835897d839d6c21a9758b773d19989ef6fdc..276354a49f010542ef7cc2035b3e19bce9758fd7 100644 GIT binary patch literal 15259 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 literal 16023 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

W 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 P%@Jg!6eNpZKm-0aqgOK? diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/000.png index 6c7d403104e4814e1235a73e74f631940e6a427d..073b087cd7494a2d78ec5438fcd82ae8cb2d63f7 100644 GIT binary patch literal 34185 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 Q=sa|_)3Y-J z;Euf+gW+Kn(9zIjc9wO#yv`&vq@<;#Z;6VI-@1R_6}K-BVB8mjmNKV{B~PY-*K2j_u;I zzYN){$H>Tt9WqG-8XB6z^5Pq`7$`S}*DyZ7#OCBCqIF2>4r_W8c(Dc6vi zdm^VgTO~wzb`c@@SRZPEW;Co3?=_u|vv2UZ)V~_xH!bX{kB^PLwcPvbKaL9!?26ie zg_wR%gnkPbD3IL)E7|2=b533Wzc52vhAV#jNQ#X^iEUP4CMdBHd>!9c97NRl^EZKAqf;2*Hs68`XogeAaek;^tiB)5EmqM<7FV8 zK_g(^Ay~m)33(x_&Zt`NwY-ocZa9F5UqHJSrT?=Rpt^d3X zOBsz7)0{B0#Wk<<{FRzkeO=wu*Sb0%I>zWcSj?|vaD9Q z-?Cr7 zWlpBDdms2}`gvx;d90TrsTCUL+4tNv`!BFXMcp&rwKSXZOLavvhTn02saf~>@{C4# zqb24BB|p6r6J@1wh=*Z|YRHA(-x_s=mlaT7EczF3!(GQf|6u%ZM{Yr{;#`lx_bS2u zjA0uslLZ$SHyOZ_PGW5As?_VFjd$Pl8mb){_ICD5941Dm71)bPZrK6b?Q&bbPvp=2%sn14%HSQsA#MdTXG?Q?ccj(x+c zJ}Q>51|@<7WIb-KJ`-9nl+3T{Dk>6Zj|J}D^@MYV;a1wR?`8(=MZ| zY|}4xmBds>00LLj=M%nPDa(>_Nh#&puW*AgZ|Im)JY?r7Z9boPqm7HtLZJcQnEkZi z!F)+&@c7i&dBVu$;G6%2(p{JVC6wE>A_+)lEfV;Kw#V73fxFI$n!Pix(;TQM3*T_s z)5#yQ7o}swG)MfqAg1R3aKQskQcBv$CvT&pd;QLj?gRnbn@qv|q|$G71xrrDPZRFm z9=*3cBn~$j;L{1l+`<7dp{9RiBQQLvxX>D7wR};fup{63)8bijR;{k30fI&d&!|ezC}U-EDJr9#d+llrA6^ zIzZj;l56X1^=!)VCXbUgdb>_g+XAP!n3$I@8(uPfaJl#CUKX%MsoL7wML--mrr$9- z9~B_?Q=jssFnip4Au$oAwCcr)ZFZ^rA0zpFaZxA8<8+tf&Ye5L1X%09cQRZi?#&F$ zgwyl@$(laky~%a!7LL!^!EJ0HcsAj=L&+&9I^*8I&w;{T9z+73SVgvv-(_d3V}a$s z0ve#^iLS0$6N4fI&tIsmULayF$UFCaTNods_F*cL-cFuS1WxKz?&{ZH8TZ~ z5!ZKriEsh{wTXhfe1Yk=vD|1jO3Xddz*1mEDS(XAfAaKcm%k^Ie(u|IorAE!)%0y|?Y*F3+t__M+9`pS=A66Bw+xw%VQAOOZXc4*ky*myOz zwJmeq#iZHw5gd-x0$uxSY3bg{_5hrv31Vgv93}84e22;b6LL}(kPj6qi9AYx@xFs3 zC5i12GF5InihuKFW+nh;m7WY0U9INNI(6ElW~ik=uxX2X9juf`FY{elIMZjvzSZ#9F$CrXqtse|}}|;b}I@=nRV86(~GY0EFxxX7x`1 zYwywMikzIBdU3llM|28p&=c!9Uq|TM5(CsUU+(XUc|C0;82Z$KxV9`si`#n!_h>f z{i-M@XW04T&C1V%&;=lvPf zaG1b7o$(n}Fa89!3pcby_U-rUmAJ%2p|pGYSUGEHaX5ugv-<*<|H9dMk2c0?_GdWR z^;e^siY-uu4D0IZlKj_y2SomAZB0Xzns@k>a{7E}fC6w4v~=YbnC$3#HR9j@sS<6j zbIrV4UwJ8=m|j7VuPG%}&p+?X!^`_sgo{f#74$GV5mX?-Fr2G%HH8dKj zC@5|Mw8jP@;Hk9tiBmWb0$YX*6EpL#gzw$6d+F+`J5%}c`9j{%VgJ?D)zZbqg%8L( zznG<;0k5V?s{Sj$U4H|{4tumnUr_8l>!m{4R)fKIJOtniq!@GI{dUCS!ovG6FsGQL zzx^#dppdmtP*9i}$64pTOmoTI*yGF+V3AQad&&c2~a1!><8C1ApVspFb%~z4wq> zZd#m!$m10h7}!|19xR8gK{it5vfK=T!bpam(s~=@P4H|ab21kJ2KWHWY5C*FkL|NW zf>xJsWTP{;goFeilxLFcD-7nFG>nWy{QUeU_$!{%wVuyG%@6|qM^DBXHy?LhZ#@kT z<3Tzo7c0-(qLTM_cD&oWyN6l2Z6cdY%^~3Kf!CxG_+$8y2WETG>h~6rsM)vRkS%iG z^F(8P{i@r{%qSSoNCk5Ii6+O#JuiS~kdl6Y;4`V00C8Xi)4Zyxs_yx-XI_$Io=`0b z0ru%ZefJ$eZy&O}yzU4HuwH#vASIpDBbC zoDNlLT3Rv4A6QUg$*A@8igFbe7XE+`Lxt`)PfRj0l3ZHzP#MwP)D&*F+(WbH?k)&U zpgJWrwI`g(-N@X$JS%xQxqR;uVtgLlIj72|rS23~@I=eC!zcn*IpZW^6@G_}c0K1uk!&Z4?qfF~e@o{WyEKJ}Y1``ug%mQ(4cJ@6yt-Juj z}f2}GHuAzZJEmZev?KWxe-PpFd(d z*gl9jK@0cLL?jye!jggl9r8!{jSAtZ$;p9NuCB#!?m3~JAOZk&4*B)d(rZfuNUfer zOH02RSA7@TV~4=rHAhG%REvv`KbZ9XeIdq69T@K?V5mZy9GYR%$|x6ILXHq!U0SN3 z8fuxCI8Ow}kzhL-Ax>|5d;Z*PQ_%0MtSrayV9bFupkRWEZj~{1-@LyErcf$+A}S%n z?DKb2L}q^7T>|&-}NIli#>4f`L|J25X{|rI`I{epXW^hEZ@q{udTh{ zZ~q4VLeT#f@kcf!i8a ziyiMZ4J+(kg47`TIV;PBz&o#~NCFIDI-J01313DXsdvb_0`c}47SIzaXz@&ds4N>n z|8lm-CC}We=7OT4$;j4c*vFd_Ne8gw0PJoG@be>;_4JZt&`b&@wmEoqdh&n#(*5TrZ#P~U z(Na^dsP@XJg?r_ZH=}t34nGEWpDq;@Rm|v(3d?R<5?jUn*(UT~qb1jVCEZDh!Ged! zAd8BDS{vX$ID2jGe*KZ`{IxG9qi_9ruk9= z5rV~iC@k)LQj!`YZ8hb82{Wkyo+%D3B2HvR+d2r@Y2;jOK$ z!9{)lNI@9%dAg$eGX~jgZ=folfZRp9llJ}lK@9*_buzN|+Hfwq-~i9TlAUh6O8@wA z@BZDpqF8I1Po7w!g|~vZ9`?rpGpw>@iO7Z2zuprNl!z>lpKc)|A z4tiQ!6Et;n;y1RpONiEBS83D&Y5l%CMfey!{R!Y8SuL%&vAljpHo3=&usG?tDii~a zn##lC>^CSIaSkHDt6=grDk{+zw8on*rx&ODobd1}Ng(1+_V+h^jE`UJY;2sB9^`SW zxaw(d|1dE*x$)rR6vH2yCo+wX=EA}ljs*k`fN@1Y6l@2pi*S&?03e$JSaV&_20=7_ zRswdr!-jYv+>ITGh+FoKjtXFfl?UAflm*@$@us;Q2H>K_C;t3l8yg#&1sLQC5N8<* zrcclKKe#fl^Ad$-1+~mMN?DNk;>%#vC;(Jz%+T{*GgqIf^>j%K4OOTvD;u-~&PrKP zaYYQIm&%*-F0;38(|FTAPIPm37bhej*xB9L8QR;~iC=IM5tU%<4QrVzfGUE?{`j#5j78)un6uEC-YPuH0=)!4Sq^s86}-H6mi=aBO)<9l@t_NE1L;vgy$!D zJ~}x`j}fJ#d3a?nc9xuX>kTqYiU%yq2S8um1g+^qCD0diBqQiOWco%jD;SdBGO6hYu++8pBcE(BAVRj^SlxT|jR&RCKiUZ!$&C z7HC`UwQ9Du9@9J|!W=M3K>h02Uo4wNmodV3etG_s`)C{6f$Y3w1noqO1m`1FZtmJH zF(YEi=Oo6*i^k<)i&|u6rs>we0LR!6`JDOhUT0PAjV4d$2VU)LbQZ1hZ!ELjE8`R3bLJMO3 z3h46>QOj$kb@?>P>1=#t?hqHa#r@7Cr4-f3AxYMtV;^#mH z$~Ofvg=F&oYT~H6RM2XyquY2cq9iIK7G)A1m_M-h*XYb5`LJYnKVt-YXs;cW2l%l7 zt~c$$e^4?L6>jo(kK4!;6X*YpMMrR%#iHxt#p0HuKDZP8!1QC;u)hJ5MkgyaQm2^( zyMUa9%mzK!fbmV^J*z_0a;c0&1tQZg!HcM^9f08Jju}pQ;V^N&ioA+Mg4RB&kjf*CxV_L=l8`+jEvgixi(wbJ4(D5S8SK? z08gLD$vR)N1?4i2`RVJz?;a>48dM(+QE5U?&5i=}*Az)>Z4Sw6-}sOMO*OU-Ymo-F zTxfo5Xuwyp4y)PUqX?)9hwhxE-0A%C-2WGU0=8Cy&GZzF3q*d$ zoxMlH&-@itV3L31Qq(iX?Ynd=(wFGUMEfH=8rJg6VWPBBgZWLKe3T0#tR26*1MvU%YY1&QK}{a$enhSzkBD@A8esZk3TC!PQAJfQ!q48sBQvmK zQh#5OnLqru=$E)+%vN-n|FJXr-Tu$6KTLJ^)z#fsj??^npqb%`a;YSo8sSJ3%4Qw= zlWN!pq68T`9TrgQHq7K;mr6bjl4s5QU+0#O#W2TDi+?egou2V)N8iMG41!MrEx>wt z$@q{lG$j;dn0b#2!KM28QGN-=>-Vmq^)SUu%X4$K!A*%RX8acdAPGIQwnn}WwQ`;L zi6Jg5>C@1-KB_(ksZ9FJSppqhGJenUOPez_L9Pr@vq7Cz^i7rL3)}<8Q7@gHg>RA+ zn!=f;yR$hv@4n4=MIbNzcJoJk3hp(oni{WG+8`M7w+zj@Pr3+%4z%|yOWH$e?^Oq= z2Imk3HGTZogYpJR{rWX#c;ut3enlv|2O!3}?W94eLkNbgI^b3auaKHCUrhh2rzR~f zPD{iC6D#O$PF7YS9svPQ2UtvP%*=Khr>Bhx-#j?HvZeq8`UXt!UmyN=PmKUsA}2jo zC&o4~WR}Y6>J83IT{K2J!q5(24cVCpjL(KZ0MBFPte$|~);20Kay4!Z`gp`B{!x)~ zZGz){z3nNF8fu`yh*uOBpC~9CPv7W%)PFr9l+V8*o?2Ngb3gNxU?grc<@W{> zmIplF4F5>l50AHi?ppAVMPmA0aFewvy=+R7=N6Xdl(qy<>l);Iy!`*mUe8o z_lInP=+7V!G^qTix`I6ZqdPlDkaqv-`_Dl|5(?Bt8y6qnH48t#hNha@*TdHb=PzPr zfx-#I!T6k@BMb!LJILtGP9nA71L>(YNBevKat|#kHJ*Uvd|NS=H=yWgJ?{9 zN(y!W!1;jyOC3=;Jg7I4x{00mAVx zgOoSoQY8eN906u}uKyA9_JPAdx%q&}-ywt)M`vr$0XMv7o>z!&t+iz}vaHFo^vo7&uBn zIQ<3nDK}`8!#7AsPGXXiR~c{IFav$~yXDozDHF`(Jf0N`XWe{)(ui+MfdJxdy zNUPv~8XX?C2jby=Pe+F+9Vuz41qTfrGxxOA)bDUW!~x=C0$(EterC;CeIg>F<}e|C z{zif;Bcy4QhmOur6S#6!o<4ngUSG;4VQ+0s4I-XUFLW99^!LZg)XG%BRjQ#-9sSkT zb_1LdRY0cXg1`MC^h8k;2z`X|%xi7v_UuM*08#Jn-(n-9qitAM#$e=9^zf*>&Bn%0t4mk6~1O7D@T7Zy( z4_-=9s9_umzkEr^FDN(*K>gj{e|H857DZ@)^AKV{r-OK+v;(K13e>f4Fo}0b)9>)| zO5GC^`?J2jPIm}pa^UrQ@Tu8>KYOPOTy-IE#V9-+9J#;-AojY!4A;yk?W^iRIfig_ z@sB(l$ZqQaiWpBkvJDqiDS1T_;= zG&vdB>whbzEib<$^y1v|W|1w_xylMr^h&HF(Md_}D^P3}{VWA4$O4|e2E0sTwRLq7 zc=-72KU-U00+D}ja95o5_W0}Bzn#_90|PZ0>q+s*Tae>`6S1**0+8Rx59|T{!11#F zW0#?QbaST0y#yac^wzCgPr)_zSEW-}s~OD#_M<#lJEeB^_7b0c8xsO)P*{ctl#1

`#)v1ez8wuwL`2+`5dq=AYe2^FUe1cOAG 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 WIALH!;5ZJCr#Px>q*I_}OZ*@49T~F# literal 32266 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 Si(h}~0H`WzDb&e9!u}t+huaST literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/000.png index 2c1e6d3bcab84a19aec9bda08cf7165b398d7b4f..47c7462e4cf08735c53a29623204142f3946acf2 100644 GIT binary patch literal 12800 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 Si(h}~0H`WzDb&e9!u}t+huaST literal 3787 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 Date: Sat, 28 Dec 2024 23:24:02 -0500 Subject: [PATCH 11/27] fix two minor bugs: font-name discovery, textProps circular ref --- src/type/p5.Font.js | 8 +++++--- src/type/text2d.js | 23 ++++++++++++++++------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index f5f5b0bb16..e6143c3d16 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -572,7 +572,7 @@ function font(p5, fn) { // load the raw font bytes let result = await fn.loadBytes(path); //console.log('result:', result); - + if (!result) { throw Error('Failed to load font data'); } @@ -597,11 +597,13 @@ function font(p5, fn) { } catch (err) { // failed to parse the font, load it as a simple FontFace - let ident = name || path.substring(path.lastIndexOf('/') + 1); + let ident = name || path + .substring(path.lastIndexOf('/') + 1) + .replace(/\.[^/.]+$/, ""); console.warn(`WARN: No glyph data for '${ident}', retrying as FontFace`); try { // create a FontFace object and pass it to p5.Font - pfont = await create(this, name, path, descriptors); + pfont = await create(this, ident, path, descriptors); } catch (err) { if (error) error(err); diff --git a/src/type/text2d.js b/src/type/text2d.js index 8d055357d4..a7862ca7c1 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -103,8 +103,6 @@ function text2d(p5, fn) { textLeading: { default: 15 }, textSize: { default: 12 }, textWrap: { default: fn.WORD }, - - // added v2.0 fontStretch: { default: fn.NORMAL, isShorthand: true }, // font-stretch: { default: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded } fontWeight: { default: fn.NORMAL, isShorthand: true }, // font-stretch: { default: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded } lineHeight: { default: fn.NORMAL, isShorthand: true }, // line-height: { default: normal | number | length | percentage } @@ -456,17 +454,28 @@ function text2d(p5, fn) { return this._pInst; } - // getter: get props from this.textDrawingContext() + // getter: get props from drawingContext + let context = this.textDrawingContext(); properties = ContextTextProps.reduce((props, p) => { - props[p] = this.textDrawingContext()[p]; + props[p] = context[p]; return props; }, {}); - // add renderer.states props + // add renderer props Object.keys(RendererTextProps).forEach(p => { - properties[p] = this.states[p]; if (RendererTextProps[p]?.type === 'Context2d') { - properties[p] = this.textDrawingContext()[p]; + properties[p] = context[p]; + } + else { // a renderer.states property + if (p === 'textFont') { + // avoid circular ref. inside textFont + properties[p] = Object.assign({}, this._currentTextFont()); + delete properties[p]._pInst; + console.log('textFont: ', properties[p]); + } + else { + properties[p] = this.states[p]; + } } }); From 9ba2d64c8f8cc9661e27966d665e5b21a39e41eb Mon Sep 17 00:00:00 2001 From: dhowe Date: Sun, 29 Dec 2024 10:50:52 -0500 Subject: [PATCH 12/27] revert merge with parameter validation issues --- docs/parameterData.json | 2 +- src/accessibility/describe.js | 4 +- src/accessibility/outputs.js | 4 +- src/app.js | 14 +- src/color/creating_reading.js | 20 +- src/color/p5.Color.js | 4 +- src/color/setting.js | 4 +- src/core/constants.js | 6 +- src/core/environment.js | 6 +- src/core/friendly_errors/fes_core.js | 1991 +++++++++---------- src/core/friendly_errors/file_errors.js | 12 +- src/core/friendly_errors/index.js | 8 +- src/core/friendly_errors/param_validator.js | 41 +- src/core/friendly_errors/stacktrace.js | 17 +- src/core/init.js | 8 +- src/core/rendering.js | 8 +- src/core/transform.js | 16 +- src/data/p5.TypedDict.js | 4 +- src/dom/dom.js | 26 +- src/dom/p5.MediaElement.js | 6 +- src/events/acceleration.js | 4 +- src/events/keyboard.js | 2 +- src/image/image.js | 6 +- src/image/loading_displaying.js | 8 +- src/image/pixels.js | 12 +- src/io/files.js | 14 +- src/math/calculation.js | 14 +- src/math/random.js | 2 +- src/math/trigonometry.js | 2 +- src/shape/2d_primitives.js | 19 +- src/shape/attributes.js | 10 +- src/shape/curves.js | 16 +- src/shape/vertex.js | 10 +- src/type/p5.Font.js | 8 +- src/type/text2d.js | 23 +- src/utilities/string_functions.js | 20 +- src/webgl/3d_primitives.js | 14 +- src/webgl/interaction.js | 4 +- src/webgl/light.js | 14 +- src/webgl/loading.js | 4 +- src/webgl/material.js | 32 +- src/webgl/p5.Camera.js | 10 +- 42 files changed, 1199 insertions(+), 1250 deletions(-) diff --git a/docs/parameterData.json b/docs/parameterData.json index b9fbd6670e..545de2f5a7 100644 --- a/docs/parameterData.json +++ b/docs/parameterData.json @@ -374,7 +374,7 @@ [ "Number?", "Number?", - "String?", + "P2D|WEBGL?", "HTMLCanvasElement?" ], [ diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index de28a74f01..5173a101de 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -118,7 +118,7 @@ function describe(p5, fn){ */ fn.describe = function(text, display) { - // p5._validateParameters('describe', arguments); + p5._validateParameters('describe', arguments); if (typeof text !== 'string') { return; } @@ -244,7 +244,7 @@ function describe(p5, fn){ */ fn.describeElement = function(name, text, display) { - // p5._validateParameters('describeElement', arguments); + p5._validateParameters('describeElement', arguments); if (typeof text !== 'string' || typeof name !== 'string') { return; } diff --git a/src/accessibility/outputs.js b/src/accessibility/outputs.js index 68ab322a5a..97b38712f4 100644 --- a/src/accessibility/outputs.js +++ b/src/accessibility/outputs.js @@ -122,7 +122,7 @@ function outputs(p5, fn){ */ fn.textOutput = function(display) { - // p5._validateParameters('textOutput', arguments); + p5._validateParameters('textOutput', arguments); //if textOutput is already true if (this._accessibleOutputs.text) { return; @@ -257,7 +257,7 @@ function outputs(p5, fn){ */ fn.gridOutput = function(display) { - // p5._validateParameters('gridOutput', arguments); + p5._validateParameters('gridOutput', arguments); //if gridOutput is already true if (this._accessibleOutputs.grid) { return; diff --git a/src/app.js b/src/app.js index 8b5579f252..9de84f07f2 100644 --- a/src/app.js +++ b/src/app.js @@ -1,10 +1,10 @@ // core import p5 from './core/main'; -// import './core/friendly_errors/stacktrace'; -// import './core/friendly_errors/validate_params'; -// import './core/friendly_errors/file_errors'; -// import './core/friendly_errors/fes_core'; -// import './core/friendly_errors/sketch_reader'; +import './core/friendly_errors/stacktrace'; +import './core/friendly_errors/validate_params'; +import './core/friendly_errors/file_errors'; +import './core/friendly_errors/fes_core'; +import './core/friendly_errors/sketch_reader'; import shape from './shape'; shape(p5); @@ -61,8 +61,6 @@ webgl(p5); import type from './type' type(p5); -import { waitForDocumentReady, waitingForTranslator, _globalInit } from './core/init'; -Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); +import './core/init'; export default p5; - diff --git a/src/color/creating_reading.js b/src/color/creating_reading.js index 9396c0f0a9..976aba3176 100644 --- a/src/color/creating_reading.js +++ b/src/color/creating_reading.js @@ -349,7 +349,7 @@ function creatingReading(p5, fn){ * @return {p5.Color} */ fn.color = function(...args) { - // p5._validateParameters('color', args); + p5._validateParameters('color', args); if (args[0] instanceof Color) { // TODO: perhaps change color mode to match instance mode? return args[0]; // Do nothing if argument is already a color object. @@ -495,7 +495,7 @@ function creatingReading(p5, fn){ *

*/ fn.red = function(c) { - // p5._validateParameters('red', arguments); + p5._validateParameters('red', arguments); // Get current red max return this.color(c)._getRed(); }; @@ -632,7 +632,7 @@ function creatingReading(p5, fn){ * */ fn.green = function(c) { - // p5._validateParameters('green', arguments); + p5._validateParameters('green', arguments); // Get current green max return this.color(c)._getGreen(); }; @@ -769,7 +769,7 @@ function creatingReading(p5, fn){ * */ fn.blue = function(c) { - // p5._validateParameters('blue', arguments); + p5._validateParameters('blue', arguments); // Get current blue max return this.color(c)._getBlue(); }; @@ -871,7 +871,7 @@ function creatingReading(p5, fn){ * */ fn.alpha = function(c) { - // p5._validateParameters('alpha', arguments); + p5._validateParameters('alpha', arguments); // Get current alpha max return this.color(c)._getAlpha(); }; @@ -993,7 +993,7 @@ function creatingReading(p5, fn){ * */ fn.hue = function(c) { - // p5._validateParameters('hue', arguments); + p5._validateParameters('hue', arguments); return this.color(c)._getHue(); }; @@ -1170,7 +1170,7 @@ function creatingReading(p5, fn){ * */ fn.saturation = function(c) { - // p5._validateParameters('saturation', arguments); + p5._validateParameters('saturation', arguments); return this.color(c)._getSaturation(); }; @@ -1315,7 +1315,7 @@ function creatingReading(p5, fn){ * */ fn.brightness = function(c) { - // p5._validateParameters('brightness', arguments); + p5._validateParameters('brightness', arguments); return this.color(c)._getBrightness(); }; @@ -1460,7 +1460,7 @@ function creatingReading(p5, fn){ * */ fn.lightness = function(c) { - // p5._validateParameters('lightness', arguments); + p5._validateParameters('lightness', arguments); return this.color(c)._getLightness(); }; @@ -1524,7 +1524,7 @@ function creatingReading(p5, fn){ * */ fn.lerpColor = function(c1, c2, amt) { - // p5._validateParameters('lerpColor', arguments); + p5._validateParameters('lerpColor', arguments); return c1.lerp(c2, amt, this._renderer.states.colorMode); }; } diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index b3f0fe13d9..0df96a4abd 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -89,7 +89,7 @@ class Color { this._color = to(this._color, this._color.spaceId); }catch(err){ // TODO: Invalid color string - throw new Error('Invalid color string'); + console.error('Invalid color string'); } }else{ @@ -107,8 +107,6 @@ class Color { }else if(vals.length === 1){ mappedVals = Color.mapColorRange([vals[0], vals[0], vals[0]], this.mode, colorMaxes); mappedVals.push(1); - }else{ - throw new Error('Invalid color'); } }else{ mappedVals = vals; diff --git a/src/color/setting.js b/src/color/setting.js index 77c31cf25f..05f8f684ba 100644 --- a/src/color/setting.js +++ b/src/color/setting.js @@ -949,7 +949,7 @@ function setting(p5, fn){ * @return {String} The current color mode. */ fn.colorMode = function(mode, max1, max2, max3, maxA) { - // p5._validateParameters('colorMode', arguments); + p5._validateParameters('colorMode', arguments); if ( [ RGB, @@ -2184,7 +2184,7 @@ function setting(p5, fn){ * */ fn.blendMode = function (mode) { - // p5._validateParameters('blendMode', arguments); + p5._validateParameters('blendMode', arguments); if (mode === constants.NORMAL) { // Warning added 3/26/19, can be deleted in future (1.0 release?) console.warn( diff --git a/src/core/constants.js b/src/core/constants.js index 0885ab3e48..ff9c873433 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -20,7 +20,7 @@ export const VERSION = 'VERSION_WILL_BE_REPLACED_BY_BUILD'; * @property {P2D} P2D * @final */ -export const P2D = 'p2d'; +export const P2D = Symbol('p2d'); export const P2DHDR = 'p2d-hdr'; @@ -45,7 +45,7 @@ export const P2DHDR = 'p2d-hdr'; * @property {WEBGL} WEBGL * @final */ -export const WEBGL = 'webgl'; +export const WEBGL = Symbol('webgl'); /** * One of the two possible values of a WebGL canvas (either WEBGL or WEBGL2), * which can be used to determine what capabilities the rendering environment @@ -54,7 +54,7 @@ export const WEBGL = 'webgl'; * @property {WEBGL2} WEBGL2 * @final */ -export const WEBGL2 = 'webgl2'; +export const WEBGL2 = Symbol('webgl2'); // ENVIRONMENT /** diff --git a/src/core/environment.js b/src/core/environment.js index 1cdb735644..fa35c8f7de 100644 --- a/src/core/environment.js +++ b/src/core/environment.js @@ -407,7 +407,7 @@ function environment(p5, fn){ * @return {Number} current frame rate. */ fn.frameRate = function(fps) { - // p5._validateParameters('frameRate', arguments); + p5._validateParameters('frameRate', arguments); if (typeof fps !== 'number' || fps < 0) { return this._frameRate; } else { @@ -992,7 +992,7 @@ function environment(p5, fn){ * */ fn.fullscreen = function(val) { - // p5._validateParameters('fullscreen', arguments); + p5._validateParameters('fullscreen', arguments); // no arguments, return fullscreen or not if (typeof val === 'undefined') { return ( @@ -1070,7 +1070,7 @@ function environment(p5, fn){ * @returns {Number} current pixel density of the sketch. */ fn.pixelDensity = function(val) { - // p5._validateParameters('pixelDensity', arguments); + p5._validateParameters('pixelDensity', arguments); let returnValue; if (typeof val === 'number') { if (val !== this._renderer._pixelDensity) { diff --git a/src/core/friendly_errors/fes_core.js b/src/core/friendly_errors/fes_core.js index 00ffa5ed66..25df52d5f3 100644 --- a/src/core/friendly_errors/fes_core.js +++ b/src/core/friendly_errors/fes_core.js @@ -22,1088 +22,1083 @@ * sequence of each function, please look at the FES Reference + Dev Notes: * https://github.com/processing/p5.js/blob/main/contributor_docs/fes_reference_dev_notes.md */ +import p5 from '../main'; import { translator } from '../internationalization'; import errorTable from './browser_errors'; import * as contants from '../constants'; -function fesCore(p5, fn){ - // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta - // See testColors below for all the color codes and names - const typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; - let misusedAtTopLevelCode = null; - let defineMisusedAtTopLevelCode = null; - - // the threshold for the maximum allowed levenshtein distance - // used in misspelling detection - const EDIT_DIST_THRESHOLD = 2; - - // to enable or disable styling (color, font-size, etc. ) for fes messages - const ENABLE_FES_STYLING = false; - - if (typeof IS_MINIFIED !== 'undefined') { - p5._friendlyError = - p5._checkForUserDefinedFunctions = - p5._fesErrorMonitor = - () => {}; - } else { - let doFriendlyWelcome = false; // TEMP until we get it all working LM - - // const errorTable = require('./browser_errors').default; - - // -- Borrowed from jQuery 1.11.3 -- - const class2type = {}; - const toString = class2type.toString; - const names = [ - 'Boolean', - 'Number', - 'String', - 'Function', - 'Array', - 'Date', - 'RegExp', - 'Object', - 'Error' - ]; - for (let n = 0; n < names.length; n++) { - class2type[`[object ${names[n]}]`] = names[n].toLowerCase(); +// p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta +// See testColors below for all the color codes and names +const typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; +let misusedAtTopLevelCode = null; +let defineMisusedAtTopLevelCode = null; + +// the threshold for the maximum allowed levenshtein distance +// used in misspelling detection +const EDIT_DIST_THRESHOLD = 2; + +// to enable or disable styling (color, font-size, etc. ) for fes messages +const ENABLE_FES_STYLING = false; + +if (typeof IS_MINIFIED !== 'undefined') { + p5._friendlyError = + p5._checkForUserDefinedFunctions = + p5._fesErrorMonitor = + () => {}; +} else { + let doFriendlyWelcome = false; // TEMP until we get it all working LM + + // const errorTable = require('./browser_errors').default; + + // -- Borrowed from jQuery 1.11.3 -- + const class2type = {}; + const toString = class2type.toString; + const names = [ + 'Boolean', + 'Number', + 'String', + 'Function', + 'Array', + 'Date', + 'RegExp', + 'Object', + 'Error' + ]; + for (let n = 0; n < names.length; n++) { + class2type[`[object ${names[n]}]`] = names[n].toLowerCase(); + } + const getType = obj => { + if (obj == null) { + return `${obj}`; } - const getType = obj => { - if (obj == null) { - return `${obj}`; - } - return typeof obj === 'object' || typeof obj === 'function' - ? class2type[toString.call(obj)] || 'object' - : typeof obj; - }; - - // -- End borrow -- - - // entry points into user-defined code - const entryPoints = [ - 'setup', - 'draw', - 'preload', - 'deviceMoved', - 'deviceTurned', - 'deviceShaken', - 'doubleClicked', - 'mousePressed', - 'mouseReleased', - 'mouseMoved', - 'mouseDragged', - 'mouseClicked', - 'mouseWheel', - 'touchStarted', - 'touchMoved', - 'touchEnded', - 'keyPressed', - 'keyReleased', - 'keyTyped', - 'windowResized' - ]; - - const friendlyWelcome = () => { - // p5.js brand - magenta: #ED225D - //const astrixBgColor = 'transparent'; - //const astrixTxtColor = '#ED225D'; - //const welcomeBgColor = '#ED225D'; - //const welcomeTextColor = 'white'; - const welcomeMessage = translator('fes.pre', { - message: translator('fes.welcome') - }); - console.log( - ' _ \n' + - ' /\\| |/\\ \n' + - " \\ ` ' / \n" + - ' / , . \\ \n' + - ' \\/|_|\\/ ' + - '\n\n' + - welcomeMessage - ); - }; - - /** - * Takes a message and a p5 function func, and adds a link pointing to - * the reference documentation of func at the end of the message - * - * @method mapToReference - * @private - * @param {String} message the words to be said - * @param {String} [func] the name of function - * - * @returns {String} - */ - const mapToReference = (message, func) => { - let msgWithReference = ''; - if (func == null || func.substring(0, 4) === 'load') { - msgWithReference = message; - } else { - const methodParts = func.split('.'); - const referenceSection = - methodParts.length > 1 ? `${methodParts[0]}.${methodParts[1]}` : 'p5'; + return typeof obj === 'object' || typeof obj === 'function' + ? class2type[toString.call(obj)] || 'object' + : typeof obj; + }; - const funcName = - methodParts.length === 1 ? func : methodParts.slice(2).join('/'); + // -- End borrow -- + + // entry points into user-defined code + const entryPoints = [ + 'setup', + 'draw', + 'preload', + 'deviceMoved', + 'deviceTurned', + 'deviceShaken', + 'doubleClicked', + 'mousePressed', + 'mouseReleased', + 'mouseMoved', + 'mouseDragged', + 'mouseClicked', + 'mouseWheel', + 'touchStarted', + 'touchMoved', + 'touchEnded', + 'keyPressed', + 'keyReleased', + 'keyTyped', + 'windowResized' + ]; + + const friendlyWelcome = () => { + // p5.js brand - magenta: #ED225D + //const astrixBgColor = 'transparent'; + //const astrixTxtColor = '#ED225D'; + //const welcomeBgColor = '#ED225D'; + //const welcomeTextColor = 'white'; + const welcomeMessage = translator('fes.pre', { + message: translator('fes.welcome') + }); + console.log( + ' _ \n' + + ' /\\| |/\\ \n' + + " \\ ` ' / \n" + + ' / , . \\ \n' + + ' \\/|_|\\/ ' + + '\n\n' + + welcomeMessage + ); + }; - //Whenever func having p5.[Class] is encountered, we need to have the error link as mentioned below else different link - funcName.startsWith('p5.') ? - msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}.${funcName})` : - msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}/${funcName})`; - } - return msgWithReference; - }; - - /** - * Prints out a fancy, colorful message to the console log - * Attaches Friendly Errors prefix [fes.pre] to the message. - * - * @method _report - * @private - * @param {String} message Message to be printed - * @param {String} [func] Name of function - * @param {Number|String} [color] CSS color code - * - * @return console logs - */ - p5._report = (message, func, color) => { - // if p5._fesLogger is set ( i.e we are running tests ), use that - // instead of console.log - const log = - p5._fesLogger == null ? console.log.bind(console) : p5._fesLogger; - - if (doFriendlyWelcome) { - friendlyWelcome(); - doFriendlyWelcome = false; - } - if ('undefined' === getType(color)) { - color = '#B40033'; // dark magenta - } else if (getType(color) === 'number') { - // Type to color - color = typeColors[color]; - } + /** + * Takes a message and a p5 function func, and adds a link pointing to + * the reference documentation of func at the end of the message + * + * @method mapToReference + * @private + * @param {String} message the words to be said + * @param {String} [func] the name of function + * + * @returns {String} + */ + const mapToReference = (message, func) => { + let msgWithReference = ''; + if (func == null || func.substring(0, 4) === 'load') { + msgWithReference = message; + } else { + const methodParts = func.split('.'); + const referenceSection = + methodParts.length > 1 ? `${methodParts[0]}.${methodParts[1]}` : 'p5'; + + const funcName = + methodParts.length === 1 ? func : methodParts.slice(2).join('/'); + + //Whenever func having p5.[Class] is encountered, we need to have the error link as mentioned below else different link + funcName.startsWith('p5.') ? + msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}.${funcName})` : + msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}/${funcName})`; + } + return msgWithReference; + }; - // Add a link to the reference docs of func at the end of the message - message = mapToReference(message, func); - let style = [`color: ${color}`, 'font-family: Arial', 'font-size: larger']; - const prefixedMsg = translator('fes.pre', { message }); + /** + * Prints out a fancy, colorful message to the console log + * Attaches Friendly Errors prefix [fes.pre] to the message. + * + * @method _report + * @private + * @param {String} message Message to be printed + * @param {String} [func] Name of function + * @param {Number|String} [color] CSS color code + * + * @return console logs + */ + p5._report = (message, func, color) => { + // if p5._fesLogger is set ( i.e we are running tests ), use that + // instead of console.log + const log = + p5._fesLogger == null ? console.log.bind(console) : p5._fesLogger; + + if (doFriendlyWelcome) { + friendlyWelcome(); + doFriendlyWelcome = false; + } + if ('undefined' === getType(color)) { + color = '#B40033'; // dark magenta + } else if (getType(color) === 'number') { + // Type to color + color = typeColors[color]; + } - if (ENABLE_FES_STYLING) { - log('%c' + prefixedMsg, style.join(';')); - } else { - log(prefixedMsg); - } - }; - /** - * This is a generic method that can be called from anywhere in the p5 - * library to alert users to a common error. - * - * @method _friendlyError - * @private - * @param {String} message Message to be printed - * @param {String} [func] Name of the function linked to error - * @param {Number|String} [color] CSS color code - */ - p5._friendlyError = function(message, func, color) { - p5._report(message, func, color); - }; - - /** - * This is called internally if there is an error with autoplay. Generates - * and prints a friendly error message [fes.autoplay]. - * - * @method _friendlyAutoplayError - * @private - */ - p5._friendlyAutoplayError = function(src) { - const message = translator('fes.autoplay', { - src, - url: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' - }); - console.log(translator('fes.pre', { message })); - }; - - /** - * Measures dissimilarity between two strings by calculating - * the Levenshtein distance. - * - * If the "distance" between them is small enough, it is - * reasonable to think that one is the misspelled version of the other. - * - * Specifically, this uses the Wagner–Fischer algorithm. - * @method computeEditDistance - * @private - * @param {String} w1 the first word - * @param {String} w2 the second word - * - * @returns {Number} the "distance" between the two words, a smaller value - * indicates that the words are similar - */ - const computeEditDistance = (w1, w2) => { - const l1 = w1.length, - l2 = w2.length; - if (l1 === 0) return w2; - if (l2 === 0) return w1; - - let prev = []; - let cur = []; + // Add a link to the reference docs of func at the end of the message + message = mapToReference(message, func); + let style = [`color: ${color}`, 'font-family: Arial', 'font-size: larger']; + const prefixedMsg = translator('fes.pre', { message }); - for (let j = 0; j < l2 + 1; j++) { - cur[j] = j; - } + if (ENABLE_FES_STYLING) { + log('%c' + prefixedMsg, style.join(';')); + } else { + log(prefixedMsg); + } + }; + /** + * This is a generic method that can be called from anywhere in the p5 + * library to alert users to a common error. + * + * @method _friendlyError + * @private + * @param {String} message Message to be printed + * @param {String} [func] Name of the function linked to error + * @param {Number|String} [color] CSS color code + */ + p5._friendlyError = function(message, func, color) { + p5._report(message, func, color); + }; - prev = cur; + /** + * This is called internally if there is an error with autoplay. Generates + * and prints a friendly error message [fes.autoplay]. + * + * @method _friendlyAutoplayError + * @private + */ + p5._friendlyAutoplayError = function(src) { + const message = translator('fes.autoplay', { + src, + url: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' + }); + console.log(translator('fes.pre', { message })); + }; - for (let i = 1; i < l1 + 1; i++) { - cur = []; - for (let j = 0; j < l2 + 1; j++) { - if (j === 0) { - cur[j] = i; - } else { - let a1 = w1[i - 1], - a2 = w2[j - 1]; - let temp = 999999; - let cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; - temp = temp > cost + prev[j - 1] ? cost + prev[j - 1] : temp; - temp = temp > 1 + cur[j - 1] ? 1 + cur[j - 1] : temp; - temp = temp > 1 + prev[j] ? 1 + prev[j] : temp; - cur[j] = temp; - } - } - prev = cur; - } + /** + * Measures dissimilarity between two strings by calculating + * the Levenshtein distance. + * + * If the "distance" between them is small enough, it is + * reasonable to think that one is the misspelled version of the other. + * + * Specifically, this uses the Wagner–Fischer algorithm. + * @method computeEditDistance + * @private + * @param {String} w1 the first word + * @param {String} w2 the second word + * + * @returns {Number} the "distance" between the two words, a smaller value + * indicates that the words are similar + */ + const computeEditDistance = (w1, w2) => { + const l1 = w1.length, + l2 = w2.length; + if (l1 === 0) return w2; + if (l2 === 0) return w1; - return cur[l2]; - }; - - /** - * Checks capitalization for user defined functions. - * - * Generates and prints a friendly error message using key: - * "fes.checkUserDefinedFns". - * - * @method checkForUserDefinedFunctions - * @private - * @param {*} context Current default context. Set to window in - * "global mode" and to a p5 instance in "instance mode" - */ - const checkForUserDefinedFunctions = context => { - if (p5.disableFriendlyErrors) return; - - // if using instance mode, this function would be called with the current - // instance as context - const instanceMode = context instanceof p5; - context = instanceMode ? context : window; - const fnNames = entryPoints; - - const fxns = {}; - // lowercasename -> actualName mapping - fnNames.forEach(symbol => { - fxns[symbol.toLowerCase()] = symbol; - }); + let prev = []; + let cur = []; - for (const prop of Object.keys(context)) { - const lowercase = prop.toLowerCase(); - - // check if the lowercase property name has an entry in fxns, if the - // actual name with correct capitalization doesnt exist in context, - // and if the user-defined symbol is of the type function - if ( - fxns[lowercase] && - !context[fxns[lowercase]] && - typeof context[prop] === 'function' - ) { - const msg = translator('fes.checkUserDefinedFns', { - name: prop, - actualName: fxns[lowercase] - }); - - p5._friendlyError(msg, fxns[lowercase]); - } - } - }; - - /** - * Compares the symbol caught in the ReferenceError to everything in - * misusedAtTopLevel ( all public p5 properties ). - * - * Generates and prints a friendly error message using key: "fes.misspelling". - * - * @method handleMisspelling - * @private - * @param {String} errSym Symbol to whose spelling to check - * @param {Error} error ReferenceError object - * - * @returns {Boolean} tell whether error was likely due to typo - */ - const handleMisspelling = (errSym, error) => { - if (!misusedAtTopLevelCode) { - defineMisusedAtTopLevelCode(); - } + for (let j = 0; j < l2 + 1; j++) { + cur[j] = j; + } - const distanceMap = {}; - let min = 999999; - // compute the levenshtein distance for the symbol against all known - // public p5 properties. Find the property with the minimum distance - misusedAtTopLevelCode.forEach(symbol => { - let dist = computeEditDistance(errSym, symbol.name); - if (distanceMap[dist]) distanceMap[dist].push(symbol); - else distanceMap[dist] = [symbol]; + prev = cur; - if (dist < min) min = dist; - }); + for (let i = 1; i < l1 + 1; i++) { + cur = []; + for (let j = 0; j < l2 + 1; j++) { + if (j === 0) { + cur[j] = i; + } else { + let a1 = w1[i - 1], + a2 = w2[j - 1]; + let temp = 999999; + let cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; + temp = temp > cost + prev[j - 1] ? cost + prev[j - 1] : temp; + temp = temp > 1 + cur[j - 1] ? 1 + cur[j - 1] : temp; + temp = temp > 1 + prev[j] ? 1 + prev[j] : temp; + cur[j] = temp; + } + } + prev = cur; + } - // if the closest match has more "distance" than the max allowed threshold - if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; + return cur[l2]; + }; - // Show a message only if the caught symbol and the matched property name - // differ in their name ( either letter difference or difference of case ) - const matchedSymbols = distanceMap[min].filter( - symbol => symbol.name !== errSym - ); - if (matchedSymbols.length !== 0) { - const parsed = p5._getErrorStackParser().parse(error); - let locationObj; - if ( - parsed && - parsed[0] && - parsed[0].fileName && - parsed[0].lineNumber && - parsed[0].columnNumber - ) { - locationObj = { - location: `${parsed[0].fileName}:${parsed[0].lineNumber}:${ - parsed[0].columnNumber - }`, - file: parsed[0].fileName.split('/').slice(-1), - line: parsed[0].lineNumber - }; - } + /** + * Checks capitalization for user defined functions. + * + * Generates and prints a friendly error message using key: + * "fes.checkUserDefinedFns". + * + * @method checkForUserDefinedFunctions + * @private + * @param {*} context Current default context. Set to window in + * "global mode" and to a p5 instance in "instance mode" + */ + const checkForUserDefinedFunctions = context => { + if (p5.disableFriendlyErrors) return; + + // if using instance mode, this function would be called with the current + // instance as context + const instanceMode = context instanceof p5; + context = instanceMode ? context : window; + const fnNames = entryPoints; + + const fxns = {}; + // lowercasename -> actualName mapping + fnNames.forEach(symbol => { + fxns[symbol.toLowerCase()] = symbol; + }); - let msg; - if (matchedSymbols.length === 1) { - // To be used when there is only one closest match. The count parameter - // allows i18n to pick between the keys "fes.misspelling" and - // "fes.misspelling_plural" - msg = translator('fes.misspelling', { - name: errSym, - actualName: matchedSymbols[0].name, - type: matchedSymbols[0].type, - location: locationObj ? translator('fes.location', locationObj) : '', - count: matchedSymbols.length - }); - } else { - // To be used when there are multiple closest matches. Gives each - // suggestion on its own line, the function name followed by a link to - // reference documentation - const suggestions = matchedSymbols - .map(symbol => { - const message = - '▶️ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); - return mapToReference(message, symbol.name); - }) - .join('\n'); - - msg = translator('fes.misspelling', { - name: errSym, - suggestions, - location: locationObj ? translator('fes.location', locationObj) : '', - count: matchedSymbols.length - }); - } + for (const prop of Object.keys(context)) { + const lowercase = prop.toLowerCase(); - // If there is only one closest match, tell _friendlyError to also add - // a link to the reference documentation. In case of multiple matches, - // this is already done in the suggestions variable, one link for each - // suggestion. - p5._friendlyError( - msg, - matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined - ); - return true; - } - return false; - }; - - /** - * Prints a friendly stacktrace for user-written functions for "global" errors - * - * Generates and prints a friendly error message using key: - * "fes.globalErrors.stackTop", "fes.globalErrors.stackSubseq". - * - * @method printFriendlyStack - * @private - * @param {Array} friendlyStack - */ - const printFriendlyStack = friendlyStack => { - const log = - p5._fesLogger && typeof p5._fesLogger === 'function' - ? p5._fesLogger - : console.log.bind(console); - if (friendlyStack.length > 1) { - let stacktraceMsg = ''; - friendlyStack.forEach((frame, idx) => { - const location = `${frame.fileName}:${frame.lineNumber}:${ - frame.columnNumber - }`; - let frameMsg, - translationObj = { - func: frame.functionName, - line: frame.lineNumber, - location, - file: frame.fileName.split('/').slice(-1) - }; - if (idx === 0) { - frameMsg = translator('fes.globalErrors.stackTop', translationObj); - } else { - frameMsg = translator('fes.globalErrors.stackSubseq', translationObj); - } - stacktraceMsg += frameMsg; + // check if the lowercase property name has an entry in fxns, if the + // actual name with correct capitalization doesnt exist in context, + // and if the user-defined symbol is of the type function + if ( + fxns[lowercase] && + !context[fxns[lowercase]] && + typeof context[prop] === 'function' + ) { + const msg = translator('fes.checkUserDefinedFns', { + name: prop, + actualName: fxns[lowercase] }); - log(stacktraceMsg); - } - }; - - /** - * Takes a stacktrace array and filters out all frames that show internal p5 - * details. - * - * Generates and prints a friendly error message using key: - * "fes.wrongPreload", "fes.libraryError". - * - * The processed stack is used to find whether the error happened internally - * within the library, and if the error was due to a non-loadX() method - * being used in preload. - * - * "Internally" here means that the exact location of the error (the top of - * the stack) is a piece of code written in the p5.js library (which may or - * may not have been called from the user's sketch). - * - * @method processStack - * @private - * @param {Error} error - * @param {Array} stacktrace - * - * @returns {Array} An array with two elements, [isInternal, friendlyStack] - * isInternal: a boolean value indicating whether the error - * happened internally - * friendlyStack: the filtered (simplified) stacktrace - */ - const processStack = (error, stacktrace) => { - // cannot process a stacktrace that doesn't exist - if (!stacktrace) return [false, null]; - - stacktrace.forEach(frame => { - frame.functionName = frame.functionName || ''; - }); - // isInternal - Did this error happen inside the library - let isInternal = false; - let p5FileName, friendlyStack, currentEntryPoint; - - // Intentionally throw an error that we catch so that we can check the name - // of the current file. Any errors we see from this file, we treat as - // internal errors. - try { - throw new Error(); - } catch (testError) { - const testStacktrace = p5._getErrorStackParser().parse(testError); - p5FileName = testStacktrace[0].fileName; + p5._friendlyError(msg, fxns[lowercase]); } + } + }; - for (let i = stacktrace.length - 1; i >= 0; i--) { - let splitted = stacktrace[i].functionName.split('.'); - if (entryPoints.includes(splitted[splitted.length - 1])) { - // remove everything below an entry point function (setup, draw, etc). - // (it's usually the internal initialization calls) - friendlyStack = stacktrace.slice(0, i + 1); - currentEntryPoint = splitted[splitted.length - 1]; - // We call the error "internal" if the source of the error was a - // function from within the p5.js library file, but called from the - // user's code directly. We only need to check the topmost frame in - // the stack trace since any function internal to p5 should pass this - // check, not just public p5 functions. - if (stacktrace[0].fileName === p5FileName) { - isInternal = true; - break; - } - break; - } + /** + * Compares the symbol caught in the ReferenceError to everything in + * misusedAtTopLevel ( all public p5 properties ). + * + * Generates and prints a friendly error message using key: "fes.misspelling". + * + * @method handleMisspelling + * @private + * @param {String} errSym Symbol to whose spelling to check + * @param {Error} error ReferenceError object + * + * @returns {Boolean} tell whether error was likely due to typo + */ + const handleMisspelling = (errSym, error) => { + if (!misusedAtTopLevelCode) { + defineMisusedAtTopLevelCode(); + } + + const distanceMap = {}; + let min = 999999; + // compute the levenshtein distance for the symbol against all known + // public p5 properties. Find the property with the minimum distance + misusedAtTopLevelCode.forEach(symbol => { + let dist = computeEditDistance(errSym, symbol.name); + if (distanceMap[dist]) distanceMap[dist].push(symbol); + else distanceMap[dist] = [symbol]; + + if (dist < min) min = dist; + }); + + // if the closest match has more "distance" than the max allowed threshold + if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; + + // Show a message only if the caught symbol and the matched property name + // differ in their name ( either letter difference or difference of case ) + const matchedSymbols = distanceMap[min].filter( + symbol => symbol.name !== errSym + ); + if (matchedSymbols.length !== 0) { + const parsed = p5._getErrorStackParser().parse(error); + let locationObj; + if ( + parsed && + parsed[0] && + parsed[0].fileName && + parsed[0].lineNumber && + parsed[0].columnNumber + ) { + locationObj = { + location: `${parsed[0].fileName}:${parsed[0].lineNumber}:${ + parsed[0].columnNumber + }`, + file: parsed[0].fileName.split('/').slice(-1), + line: parsed[0].lineNumber + }; } - // in some cases ( errors in promises, callbacks, etc), no entry-point - // function may be found in the stacktrace. In that case just use the - // entire stacktrace for friendlyStack - if (!friendlyStack) friendlyStack = stacktrace; - - if (isInternal) { - // the frameIndex property is added before the filter, so frameIndex - // corresponds to the index of a frame in the original stacktrace. - // Then we filter out all frames which belong to the file that contains - // the p5 library - friendlyStack = friendlyStack - .map((frame, index) => { - frame.frameIndex = index; - return frame; + let msg; + if (matchedSymbols.length === 1) { + // To be used when there is only one closest match. The count parameter + // allows i18n to pick between the keys "fes.misspelling" and + // "fes.misspelling_plural" + msg = translator('fes.misspelling', { + name: errSym, + actualName: matchedSymbols[0].name, + type: matchedSymbols[0].type, + location: locationObj ? translator('fes.location', locationObj) : '', + count: matchedSymbols.length + }); + } else { + // To be used when there are multiple closest matches. Gives each + // suggestion on its own line, the function name followed by a link to + // reference documentation + const suggestions = matchedSymbols + .map(symbol => { + const message = + '▶️ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); + return mapToReference(message, symbol.name); }) - .filter(frame => frame.fileName !== p5FileName); - - // a weird case, if for some reason we can't identify the function called - // from user's code - if (friendlyStack.length === 0) return [true, null]; - - // get the function just above the topmost frame in the friendlyStack. - // i.e the name of the library function called from user's code - const func = stacktrace[friendlyStack[0].frameIndex - 2].functionName - .split('.') - .slice(-1)[0]; - - // Try and get the location (line no.) from the top element of the stack - let locationObj; - if ( - friendlyStack[0].fileName && - friendlyStack[0].lineNumber && - friendlyStack[0].columnNumber - ) { - locationObj = { - location: `${friendlyStack[0].fileName}:${ - friendlyStack[0].lineNumber - }:${friendlyStack[0].columnNumber}`, - file: friendlyStack[0].fileName.split('/').slice(-1), - line: friendlyStack[0].lineNumber - }; + .join('\n'); - // if already handled by another part of the FES, don't handle again - if (p5._fesLogCache[locationObj.location]) return [true, null]; - } + msg = translator('fes.misspelling', { + name: errSym, + suggestions, + location: locationObj ? translator('fes.location', locationObj) : '', + count: matchedSymbols.length + }); + } - // Check if the error is due to a non loadX method being used incorrectly - // in preload - if ( - currentEntryPoint === 'preload' && - fn._preloadMethods[func] == null - ) { - p5._friendlyError( - translator('fes.wrongPreload', { - func, - location: locationObj - ? translator('fes.location', locationObj) - : '', - error: error.message - }), - 'preload' - ); + // If there is only one closest match, tell _friendlyError to also add + // a link to the reference documentation. In case of multiple matches, + // this is already done in the suggestions variable, one link for each + // suggestion. + p5._friendlyError( + msg, + matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined + ); + return true; + } + return false; + }; + + /** + * Prints a friendly stacktrace for user-written functions for "global" errors + * + * Generates and prints a friendly error message using key: + * "fes.globalErrors.stackTop", "fes.globalErrors.stackSubseq". + * + * @method printFriendlyStack + * @private + * @param {Array} friendlyStack + */ + const printFriendlyStack = friendlyStack => { + const log = + p5._fesLogger && typeof p5._fesLogger === 'function' + ? p5._fesLogger + : console.log.bind(console); + if (friendlyStack.length > 1) { + let stacktraceMsg = ''; + friendlyStack.forEach((frame, idx) => { + const location = `${frame.fileName}:${frame.lineNumber}:${ + frame.columnNumber + }`; + let frameMsg, + translationObj = { + func: frame.functionName, + line: frame.lineNumber, + location, + file: frame.fileName.split('/').slice(-1) + }; + if (idx === 0) { + frameMsg = translator('fes.globalErrors.stackTop', translationObj); } else { - // Library error - p5._friendlyError( - translator('fes.libraryError', { - func, - location: locationObj - ? translator('fes.location', locationObj) - : '', - error: error.message - }), - func - ); + frameMsg = translator('fes.globalErrors.stackSubseq', translationObj); } + stacktraceMsg += frameMsg; + }); + log(stacktraceMsg); + } + }; - // Finally, if it's an internal error, print the friendlyStack - // ( fesErrorMonitor won't handle this error ) - if (friendlyStack && friendlyStack.length) { - printFriendlyStack(friendlyStack); - } - } - return [isInternal, friendlyStack]; - }; - - /** - * Handles "global" errors that the browser catches. - * - * Called when an error event happens and detects the type of error. - * - * Generates and prints a friendly error message using key: - * "fes.globalErrors.syntax.[*]", "fes.globalErrors.reference.[*]", - * "fes.globalErrors.type.[*]". - * - * @method fesErrorMonitor - * @private - * @param {*} e Event object to extract error details from - */ - const fesErrorMonitor = e => { - if (p5.disableFriendlyErrors) return; - // Try to get the error object from e - let error; - if (e instanceof Error) { - error = e; - } else if (e instanceof ErrorEvent) { - error = e.error; - } else if (e instanceof PromiseRejectionEvent) { - error = e.reason; - if (!(error instanceof Error)) return; - } - if (!error) return; + /** + * Takes a stacktrace array and filters out all frames that show internal p5 + * details. + * + * Generates and prints a friendly error message using key: + * "fes.wrongPreload", "fes.libraryError". + * + * The processed stack is used to find whether the error happened internally + * within the library, and if the error was due to a non-loadX() method + * being used in preload. + * + * "Internally" here means that the exact location of the error (the top of + * the stack) is a piece of code written in the p5.js library (which may or + * may not have been called from the user's sketch). + * + * @method processStack + * @private + * @param {Error} error + * @param {Array} stacktrace + * + * @returns {Array} An array with two elements, [isInternal, friendlyStack] + * isInternal: a boolean value indicating whether the error + * happened internally + * friendlyStack: the filtered (simplified) stacktrace + */ + const processStack = (error, stacktrace) => { + // cannot process a stacktrace that doesn't exist + if (!stacktrace) return [false, null]; - let stacktrace = p5._getErrorStackParser().parse(error); - // process the stacktrace from the browser and simplify it to give - // friendlyStack. - let [isInternal, friendlyStack] = processStack(error, stacktrace); + stacktrace.forEach(frame => { + frame.functionName = frame.functionName || ''; + }); - // if this is an internal library error, the type of the error is not relevant, - // only the user code that lead to it is. - if (isInternal) { - return; - } + // isInternal - Did this error happen inside the library + let isInternal = false; + let p5FileName, friendlyStack, currentEntryPoint; + + // Intentionally throw an error that we catch so that we can check the name + // of the current file. Any errors we see from this file, we treat as + // internal errors. + try { + throw new Error(); + } catch (testError) { + const testStacktrace = p5._getErrorStackParser().parse(testError); + p5FileName = testStacktrace[0].fileName; + } - const errList = errorTable[error.name]; - if (!errList) return; // this type of error can't be handled yet - let matchedError; - for (const obj of errList) { - let string = obj.msg; - // capture the primary symbol mentioned in the error - string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); - string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); - string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); - let matched = error.message.match(string); - - if (matched) { - matchedError = Object.assign({}, obj); - matchedError.match = matched; + for (let i = stacktrace.length - 1; i >= 0; i--) { + let splitted = stacktrace[i].functionName.split('.'); + if (entryPoints.includes(splitted[splitted.length - 1])) { + // remove everything below an entry point function (setup, draw, etc). + // (it's usually the internal initialization calls) + friendlyStack = stacktrace.slice(0, i + 1); + currentEntryPoint = splitted[splitted.length - 1]; + // We call the error "internal" if the source of the error was a + // function from within the p5.js library file, but called from the + // user's code directly. We only need to check the topmost frame in + // the stack trace since any function internal to p5 should pass this + // check, not just public p5 functions. + if (stacktrace[0].fileName === p5FileName) { + isInternal = true; break; } + break; } + } + + // in some cases ( errors in promises, callbacks, etc), no entry-point + // function may be found in the stacktrace. In that case just use the + // entire stacktrace for friendlyStack + if (!friendlyStack) friendlyStack = stacktrace; + + if (isInternal) { + // the frameIndex property is added before the filter, so frameIndex + // corresponds to the index of a frame in the original stacktrace. + // Then we filter out all frames which belong to the file that contains + // the p5 library + friendlyStack = friendlyStack + .map((frame, index) => { + frame.frameIndex = index; + return frame; + }) + .filter(frame => frame.fileName !== p5FileName); + + // a weird case, if for some reason we can't identify the function called + // from user's code + if (friendlyStack.length === 0) return [true, null]; - if (!matchedError) return; + // get the function just above the topmost frame in the friendlyStack. + // i.e the name of the library function called from user's code + const func = stacktrace[friendlyStack[0].frameIndex - 1].functionName + .split('.') + .slice(-1)[0]; - // Try and get the location from the top element of the stack + // Try and get the location (line no.) from the top element of the stack let locationObj; if ( - stacktrace && - stacktrace[0].fileName && - stacktrace[0].lineNumber && - stacktrace[0].columnNumber + friendlyStack[0].fileName && + friendlyStack[0].lineNumber && + friendlyStack[0].columnNumber ) { locationObj = { - location: `${stacktrace[0].fileName}:${stacktrace[0].lineNumber}:${ - stacktrace[0].columnNumber - }`, - file: stacktrace[0].fileName.split('/').slice(-1), + location: `${friendlyStack[0].fileName}:${ + friendlyStack[0].lineNumber + }:${friendlyStack[0].columnNumber}`, + file: friendlyStack[0].fileName.split('/').slice(-1), line: friendlyStack[0].lineNumber }; + + // if already handled by another part of the FES, don't handle again + if (p5._fesLogCache[locationObj.location]) return [true, null]; } - switch (error.name) { - case 'SyntaxError': { - // We can't really do much with syntax errors other than try to use - // a simpler framing of the error message. The stack isn't available - // for syntax errors - switch (matchedError.type) { - case 'INVALIDTOKEN': { - //Error if there is an invalid or unexpected token that doesn't belong at this position in the code - //let x = “not a string”; -> string not in proper quotes - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.invalidToken', { - url - }) - ); - break; - } - case 'UNEXPECTEDTOKEN': { - //Error if a specific language construct(, { ; etc) was expected, but something else was provided - //for (let i = 0; i < 5,; ++i) -> a comma after i<5 instead of a semicolon - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.unexpectedToken', { - url - }) - ); - break; - } - case 'REDECLAREDVARIABLE': { - //Error if a variable is redeclared by the user. Example=> - //let a = 10; - //let a = 100; - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Redeclared_parameter#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.redeclaredVariable', { - symbol: errSym, - url - }) - ); - break; - } - case 'MISSINGINITIALIZER': { - //Error if a const variable is not initialized during declaration - //Example => const a; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_initializer_in_const#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.missingInitializer', { - url - }) - ); - break; - } - case 'BADRETURNORYIELD': { - //Error when a return statement is misplaced(usually outside of a function) - // const a = function(){ - // ..... - // } - // return; -> misplaced return statement - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.badReturnOrYield', { - url - }) - ); - break; - } + // Check if the error is due to a non loadX method being used incorrectly + // in preload + if ( + currentEntryPoint === 'preload' && + p5.prototype._preloadMethods[func] == null + ) { + p5._friendlyError( + translator('fes.wrongPreload', { + func, + location: locationObj + ? translator('fes.location', locationObj) + : '', + error: error.message + }), + 'preload' + ); + } else { + // Library error + p5._friendlyError( + translator('fes.libraryError', { + func, + location: locationObj + ? translator('fes.location', locationObj) + : '', + error: error.message + }), + func + ); + } + + // Finally, if it's an internal error, print the friendlyStack + // ( fesErrorMonitor won't handle this error ) + if (friendlyStack && friendlyStack.length) { + printFriendlyStack(friendlyStack); + } + } + return [isInternal, friendlyStack]; + }; + + /** + * Handles "global" errors that the browser catches. + * + * Called when an error event happens and detects the type of error. + * + * Generates and prints a friendly error message using key: + * "fes.globalErrors.syntax.[*]", "fes.globalErrors.reference.[*]", + * "fes.globalErrors.type.[*]". + * + * @method fesErrorMonitor + * @private + * @param {*} e Event object to extract error details from + */ + const fesErrorMonitor = e => { + if (p5.disableFriendlyErrors) return; + // Try to get the error object from e + let error; + if (e instanceof Error) { + error = e; + } else if (e instanceof ErrorEvent) { + error = e.error; + } else if (e instanceof PromiseRejectionEvent) { + error = e.reason; + if (!(error instanceof Error)) return; + } + if (!error) return; + + let stacktrace = p5._getErrorStackParser().parse(error); + // process the stacktrace from the browser and simplify it to give + // friendlyStack. + let [isInternal, friendlyStack] = processStack(error, stacktrace); + + // if this is an internal library error, the type of the error is not relevant, + // only the user code that lead to it is. + if (isInternal) { + return; + } + + const errList = errorTable[error.name]; + if (!errList) return; // this type of error can't be handled yet + let matchedError; + for (const obj of errList) { + let string = obj.msg; + // capture the primary symbol mentioned in the error + string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); + string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); + string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); + let matched = error.message.match(string); + + if (matched) { + matchedError = Object.assign({}, obj); + matchedError.match = matched; + break; + } + } + + if (!matchedError) return; + + // Try and get the location from the top element of the stack + let locationObj; + if ( + stacktrace && + stacktrace[0].fileName && + stacktrace[0].lineNumber && + stacktrace[0].columnNumber + ) { + locationObj = { + location: `${stacktrace[0].fileName}:${stacktrace[0].lineNumber}:${ + stacktrace[0].columnNumber + }`, + file: stacktrace[0].fileName.split('/').slice(-1), + line: friendlyStack[0].lineNumber + }; + } + + switch (error.name) { + case 'SyntaxError': { + // We can't really do much with syntax errors other than try to use + // a simpler framing of the error message. The stack isn't available + // for syntax errors + switch (matchedError.type) { + case 'INVALIDTOKEN': { + //Error if there is an invalid or unexpected token that doesn't belong at this position in the code + //let x = “not a string”; -> string not in proper quotes + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.invalidToken', { + url + }) + ); + break; + } + case 'UNEXPECTEDTOKEN': { + //Error if a specific language construct(, { ; etc) was expected, but something else was provided + //for (let i = 0; i < 5,; ++i) -> a comma after i<5 instead of a semicolon + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.unexpectedToken', { + url + }) + ); + break; + } + case 'REDECLAREDVARIABLE': { + //Error if a variable is redeclared by the user. Example=> + //let a = 10; + //let a = 100; + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Redeclared_parameter#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.redeclaredVariable', { + symbol: errSym, + url + }) + ); + break; + } + case 'MISSINGINITIALIZER': { + //Error if a const variable is not initialized during declaration + //Example => const a; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_initializer_in_const#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.missingInitializer', { + url + }) + ); + break; + } + case 'BADRETURNORYIELD': { + //Error when a return statement is misplaced(usually outside of a function) + // const a = function(){ + // ..... + // } + // return; -> misplaced return statement + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.badReturnOrYield', { + url + }) + ); + break; } - break; } - case 'ReferenceError': { - switch (matchedError.type) { - case 'NOTDEFINED': { - //Error if there is a non-existent variable referenced somewhere - //let a = 10; - //console.log(x); - let errSym = matchedError.match[1]; - - if (errSym && handleMisspelling(errSym, error)) { - break; - } - - // if the flow gets this far, this is likely not a misspelling - // of a p5 property/function - let url = 'https://p5js.org/examples/data-variable-scope.html'; - p5._friendlyError( - translator('fes.globalErrors.reference.notDefined', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); - - if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'ReferenceError': { + switch (matchedError.type) { + case 'NOTDEFINED': { + //Error if there is a non-existent variable referenced somewhere + //let a = 10; + //console.log(x); + let errSym = matchedError.match[1]; + + if (errSym && handleMisspelling(errSym, error)) { break; } - case 'CANNOTACCESS': { - //Error if a lexical variable was accessed before it was initialized - //console.log(a); -> variable accessed before it was initialized - //let a=100; - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.reference.cannotAccess', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - } - break; - } + // if the flow gets this far, this is likely not a misspelling + // of a p5 property/function + let url = 'https://p5js.org/examples/data-variable-scope.html'; + p5._friendlyError( + translator('fes.globalErrors.reference.notDefined', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - case 'TypeError': { - switch (matchedError.type) { - case 'NOTFUNC': { - //Error when some code expects you to provide a function, but that didn't happen - //let a = document.getElementByID('foo'); -> getElementById instead of getElementByID - let errSym = matchedError.match[1]; - let splitSym = errSym.split('.'); - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; - - // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb - let translationObj = { + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'CANNOTACCESS': { + //Error if a lexical variable was accessed before it was initialized + //console.log(a); -> variable accessed before it was initialized + //let a=100; + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.reference.cannotAccess', { url, - symbol: splitSym[splitSym.length - 1], - obj: splitSym.slice(0, splitSym.length - 1).join('.'), + symbol: errSym, location: locationObj ? translator('fes.location', locationObj) : '' - }; - - // There are two cases to handle here. When the function is called - // as a property of an object and when it's called independently. - // Both have different explanations. - if (splitSym.length > 1) { - p5._friendlyError( - translator('fes.globalErrors.type.notfuncObj', translationObj) - ); - } else { - p5._friendlyError( - translator('fes.globalErrors.type.notfunc', translationObj) - ); - } - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - case 'READNULL': { - //Error if a property of null is accessed - //let a = null; - //console.log(a.property); -> a is null - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; - /*let url2 = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null';*/ - p5._friendlyError( - translator('fes.globalErrors.type.readFromNull', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); + }) + ); - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - case 'READUDEFINED': { - //Error if a property of undefined is accessed - //let a; -> default value of a is undefined - //console.log(a.property); -> a is undefined - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; - /*let url2 = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#description';*/ + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + } + break; + } + + case 'TypeError': { + switch (matchedError.type) { + case 'NOTFUNC': { + //Error when some code expects you to provide a function, but that didn't happen + //let a = document.getElementByID('foo'); -> getElementById instead of getElementByID + let errSym = matchedError.match[1]; + let splitSym = errSym.split('.'); + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; + + // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb + let translationObj = { + url, + symbol: splitSym[splitSym.length - 1], + obj: splitSym.slice(0, splitSym.length - 1).join('.'), + location: locationObj + ? translator('fes.location', locationObj) + : '' + }; + + // There are two cases to handle here. When the function is called + // as a property of an object and when it's called independently. + // Both have different explanations. + if (splitSym.length > 1) { p5._friendlyError( - translator('fes.globalErrors.type.readFromUndefined', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) + translator('fes.globalErrors.type.notfuncObj', translationObj) ); - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - case 'CONSTASSIGN': { - //Error when a const variable is reassigned a value - //const a = 100; - //a=10; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_const_assignment#what_went_wrong'; + } else { p5._friendlyError( - translator('fes.globalErrors.type.constAssign', { - url, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) + translator('fes.globalErrors.type.notfunc', translationObj) ); - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; } - } - } - } - }; - - p5._fesErrorMonitor = fesErrorMonitor; - p5._checkForUserDefinedFunctions = checkForUserDefinedFunctions; - - // logger for testing purposes. - p5._fesLogger = null; - p5._fesLogCache = {}; - - window.addEventListener('load', checkForUserDefinedFunctions, false); - window.addEventListener('error', p5._fesErrorMonitor, false); - window.addEventListener('unhandledrejection', p5._fesErrorMonitor, false); - - /** - * Prints out all the colors in the color pallete with white text. - * For color blindness testing. - */ - /* function testColors() { - const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; - p5._friendlyError(str, 'print', '#ED225D'); // p5.js magenta - p5._friendlyError(str, 'print', '#2D7BB6'); // p5.js blue - p5._friendlyError(str, 'print', '#EE9900'); // p5.js orange - p5._friendlyError(str, 'print', '#A67F59'); // p5.js light brown - p5._friendlyError(str, 'print', '#704F21'); // p5.js gold - p5._friendlyError(str, 'print', '#1CC581'); // auto cyan - p5._friendlyError(str, 'print', '#FF6625'); // auto orange - p5._friendlyError(str, 'print', '#79EB22'); // auto green - p5._friendlyError(str, 'print', '#B40033'); // p5.js darkened magenta - p5._friendlyError(str, 'print', '#084B7F'); // p5.js darkened blue - p5._friendlyError(str, 'print', '#945F00'); // p5.js darkened orange - p5._friendlyError(str, 'print', '#6B441D'); // p5.js darkened brown - p5._friendlyError(str, 'print', '#2E1B00'); // p5.js darkened gold - p5._friendlyError(str, 'print', '#008851'); // auto dark cyan - p5._friendlyError(str, 'print', '#C83C00'); // auto dark orange - p5._friendlyError(str, 'print', '#4DB200'); // auto dark green - } */ - } - - // This is a lazily-defined list of p5 symbols that may be - // misused by beginners at top-level code, outside of setup/draw. We'd like - // to detect these errors and help the user by suggesting they move them - // into setup/draw. - // - // For more details, see https://github.com/processing/p5.js/issues/1121. - misusedAtTopLevelCode = null; - const FAQ_URL = - 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; - /** - * A helper function for populating misusedAtTopLevel list. - * - * @method defineMisusedAtTopLevelCode - * @private - */ - defineMisusedAtTopLevelCode = () => { - const uniqueNamesFound = {}; - - const getSymbols = obj => - Object.getOwnPropertyNames(obj) - .filter(name => { - if (name[0] === '_') { - return false; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; } - if (name in uniqueNamesFound) { - return false; + case 'READNULL': { + //Error if a property of null is accessed + //let a = null; + //console.log(a.property); -> a is null + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; + /*let url2 = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null';*/ + p5._friendlyError( + translator('fes.globalErrors.type.readFromNull', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; } + case 'READUDEFINED': { + //Error if a property of undefined is accessed + //let a; -> default value of a is undefined + //console.log(a.property); -> a is undefined + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; + /*let url2 = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#description';*/ + p5._friendlyError( + translator('fes.globalErrors.type.readFromUndefined', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - uniqueNamesFound[name] = true; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'CONSTASSIGN': { + //Error when a const variable is reassigned a value + //const a = 100; + //a=10; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_const_assignment#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.type.constAssign', { + url, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - return true; - }) - .map(name => { - let type; - - if (typeof obj[name] === 'function') { - type = 'function'; - } else if (name === name.toUpperCase()) { - type = 'constant'; - } else { - type = 'variable'; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; } + } + } + } + }; - return { name, type }; - }); + p5._fesErrorMonitor = fesErrorMonitor; + p5._checkForUserDefinedFunctions = checkForUserDefinedFunctions; - misusedAtTopLevelCode = [].concat( - getSymbols(fn), - // At present, p5 only adds its constants to fn during - // construction, which may not have happened at the time a - // ReferenceError is thrown, so we'll manually add them to our list. - getSymbols(contants) - ); + // logger for testing purposes. + p5._fesLogger = null; + p5._fesLogCache = {}; - // This will ultimately ensure that we report the most specific error - // possible to the user, e.g. advising them about HALF_PI instead of PI - // when their code misuses the former. - misusedAtTopLevelCode.sort((a, b) => b.name.length - a.name.length); - }; + window.addEventListener('load', checkForUserDefinedFunctions, false); + window.addEventListener('error', p5._fesErrorMonitor, false); + window.addEventListener('unhandledrejection', p5._fesErrorMonitor, false); /** - * Detects browser level error event for p5 constants/functions used outside - * of setup() and draw(). - * - * Generates and prints a friendly error message using key: - * "fes.misusedTopLevel". - * - * @method helpForMisusedAtTopLevelCode - * @private - * @param {Event} e Error event - * @param {Boolean} log false - * - * @returns {Boolean} true + * Prints out all the colors in the color pallete with white text. + * For color blindness testing. */ - const helpForMisusedAtTopLevelCode = (e, log) => { - if (!log) { - log = console.log.bind(console); - } + /* function testColors() { + const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; + p5._friendlyError(str, 'print', '#ED225D'); // p5.js magenta + p5._friendlyError(str, 'print', '#2D7BB6'); // p5.js blue + p5._friendlyError(str, 'print', '#EE9900'); // p5.js orange + p5._friendlyError(str, 'print', '#A67F59'); // p5.js light brown + p5._friendlyError(str, 'print', '#704F21'); // p5.js gold + p5._friendlyError(str, 'print', '#1CC581'); // auto cyan + p5._friendlyError(str, 'print', '#FF6625'); // auto orange + p5._friendlyError(str, 'print', '#79EB22'); // auto green + p5._friendlyError(str, 'print', '#B40033'); // p5.js darkened magenta + p5._friendlyError(str, 'print', '#084B7F'); // p5.js darkened blue + p5._friendlyError(str, 'print', '#945F00'); // p5.js darkened orange + p5._friendlyError(str, 'print', '#6B441D'); // p5.js darkened brown + p5._friendlyError(str, 'print', '#2E1B00'); // p5.js darkened gold + p5._friendlyError(str, 'print', '#008851'); // auto dark cyan + p5._friendlyError(str, 'print', '#C83C00'); // auto dark orange + p5._friendlyError(str, 'print', '#4DB200'); // auto dark green + } */ +} - if (!misusedAtTopLevelCode) { - defineMisusedAtTopLevelCode(); - } +// This is a lazily-defined list of p5 symbols that may be +// misused by beginners at top-level code, outside of setup/draw. We'd like +// to detect these errors and help the user by suggesting they move them +// into setup/draw. +// +// For more details, see https://github.com/processing/p5.js/issues/1121. +misusedAtTopLevelCode = null; +const FAQ_URL = + 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; - // If we find that we're logging lots of false positives, we can - // uncomment the following code to avoid displaying anything if the - // user's code isn't likely to be using p5's global mode. (Note that - // setup/draw are more likely to be defined due to JS function hoisting.) - // - //if (!('setup' in window || 'draw' in window)) { - // return; - //} - - misusedAtTopLevelCode.some(symbol => { - // Note that while just checking for the occurrence of the - // symbol name in the error message could result in false positives, - // a more rigorous test is difficult because different browsers - // log different messages, and the format of those messages may - // change over time. - // - // For example, if the user uses 'PI' in their code, it may result - // in any one of the following messages: - // - // * 'PI' is undefined (Microsoft Edge) - // * ReferenceError: PI is undefined (Firefox) - // * Uncaught ReferenceError: PI is not defined (Chrome) - - if (e.message && e.message.match(`\\W?${symbol.name}\\W`) !== null) { - const symbolName = - symbol.type === 'function' ? `${symbol.name}()` : symbol.name; - if (typeof IS_MINIFIED !== 'undefined') { - log( - `Did you just try to use p5.js's ${symbolName} ${ - symbol.type - }? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: ${FAQ_URL}` - ); - } else { - log( - translator('fes.misusedTopLevel', { - symbolName, - symbolType: symbol.type, - url: FAQ_URL - }) - ); +/** + * A helper function for populating misusedAtTopLevel list. + * + * @method defineMisusedAtTopLevelCode + * @private + */ +defineMisusedAtTopLevelCode = () => { + const uniqueNamesFound = {}; + + const getSymbols = obj => + Object.getOwnPropertyNames(obj) + .filter(name => { + if (name[0] === '_') { + return false; } + if (name in uniqueNamesFound) { + return false; + } + + uniqueNamesFound[name] = true; + return true; - } - }); - }; + }) + .map(name => { + let type; + + if (typeof obj[name] === 'function') { + type = 'function'; + } else if (name === name.toUpperCase()) { + type = 'constant'; + } else { + type = 'variable'; + } - // Exposing this primarily for unit testing. - fn._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; + return { name, type }; + }); - if (document.readyState !== 'complete') { - window.addEventListener('error', helpForMisusedAtTopLevelCode, false); + misusedAtTopLevelCode = [].concat( + getSymbols(p5.prototype), + // At present, p5 only adds its constants to p5.prototype during + // construction, which may not have happened at the time a + // ReferenceError is thrown, so we'll manually add them to our list. + getSymbols(contants) + ); - // Our job is only to catch ReferenceErrors that are thrown when - // global (non-instance mode) p5 APIs are used at the top-level - // scope of a file, so we'll unbind our error listener now to make - // sure we don't log false positives later. - window.addEventListener('load', () => { - window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); - }); + // This will ultimately ensure that we report the most specific error + // possible to the user, e.g. advising them about HALF_PI instead of PI + // when their code misuses the former. + misusedAtTopLevelCode.sort((a, b) => b.name.length - a.name.length); +}; + +/** + * Detects browser level error event for p5 constants/functions used outside + * of setup() and draw(). + * + * Generates and prints a friendly error message using key: + * "fes.misusedTopLevel". + * + * @method helpForMisusedAtTopLevelCode + * @private + * @param {Event} e Error event + * @param {Boolean} log false + * + * @returns {Boolean} true + */ +const helpForMisusedAtTopLevelCode = (e, log) => { + if (!log) { + log = console.log.bind(console); } -} -export default fesCore; + if (!misusedAtTopLevelCode) { + defineMisusedAtTopLevelCode(); + } -if (typeof p5 !== 'undefined') { - fesCore(p5, p5.prototype); + // If we find that we're logging lots of false positives, we can + // uncomment the following code to avoid displaying anything if the + // user's code isn't likely to be using p5's global mode. (Note that + // setup/draw are more likely to be defined due to JS function hoisting.) + // + //if (!('setup' in window || 'draw' in window)) { + // return; + //} + + misusedAtTopLevelCode.some(symbol => { + // Note that while just checking for the occurrence of the + // symbol name in the error message could result in false positives, + // a more rigorous test is difficult because different browsers + // log different messages, and the format of those messages may + // change over time. + // + // For example, if the user uses 'PI' in their code, it may result + // in any one of the following messages: + // + // * 'PI' is undefined (Microsoft Edge) + // * ReferenceError: PI is undefined (Firefox) + // * Uncaught ReferenceError: PI is not defined (Chrome) + + if (e.message && e.message.match(`\\W?${symbol.name}\\W`) !== null) { + const symbolName = + symbol.type === 'function' ? `${symbol.name}()` : symbol.name; + if (typeof IS_MINIFIED !== 'undefined') { + log( + `Did you just try to use p5.js's ${symbolName} ${ + symbol.type + }? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: ${FAQ_URL}` + ); + } else { + log( + translator('fes.misusedTopLevel', { + symbolName, + symbolType: symbol.type, + url: FAQ_URL + }) + ); + } + return true; + } + }); +}; + +// Exposing this primarily for unit testing. +p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; + +if (document.readyState !== 'complete') { + window.addEventListener('error', helpForMisusedAtTopLevelCode, false); + + // Our job is only to catch ReferenceErrors that are thrown when + // global (non-instance mode) p5 APIs are used at the top-level + // scope of a file, so we'll unbind our error listener now to make + // sure we don't log false positives later. + window.addEventListener('load', () => { + window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); + }); } + +export default p5; diff --git a/src/core/friendly_errors/file_errors.js b/src/core/friendly_errors/file_errors.js index 8f212c8355..677d7a61b9 100644 --- a/src/core/friendly_errors/file_errors.js +++ b/src/core/friendly_errors/file_errors.js @@ -2,9 +2,12 @@ * @for p5 * @requires core */ +import p5 from '../main'; import { translator } from '../internationalization'; -function fileErrors(p5, fn){ +if (typeof IS_MINIFIED !== 'undefined') { + p5._friendlyFileLoadError = () => {}; +} else { // mapping used by `_friendlyFileLoadError` const fileLoadErrorCases = (num, filePath) => { const suggestion = translator('fes.fileLoadError.suggestion', { @@ -73,7 +76,6 @@ function fileErrors(p5, fn){ }; } }; - /** * Called internally if there is an error during file loading. * @@ -91,8 +93,4 @@ function fileErrors(p5, fn){ }; } -export default fileErrors; - -if (typeof p5 !== 'undefined') { - fileErrors(p5, p5.prototype); -} +export default p5; diff --git a/src/core/friendly_errors/index.js b/src/core/friendly_errors/index.js index d69a3c604e..8f1b0e56e0 100644 --- a/src/core/friendly_errors/index.js +++ b/src/core/friendly_errors/index.js @@ -1,13 +1,7 @@ -import fesCore from './fes_core'; -import stacktrace from './stacktrace'; import validateParams from './param_validator.js'; import sketchVerifier from './sketch_verifier.js'; -import fileErrors from './file_errors'; export default function (p5) { - p5.registerAddon(fesCore); - p5.registerAddon(stacktrace); p5.registerAddon(validateParams); p5.registerAddon(sketchVerifier); - p5.registerAddon(fileErrors); -} +} \ No newline at end of file diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index 975c5eab95..27a5420695 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -2,11 +2,12 @@ * @for p5 * @requires core */ +import p5 from '../main.js'; import * as constants from '../constants.js'; -import * as z from 'zod'; +import { z } from 'zod'; import dataDoc from '../../../docs/parameterData.json'; -function validateParams(p5, fn, lifecycles) { +function validateParams(p5, fn) { // Cache for Zod schemas let schemaRegistry = new Map(); @@ -18,7 +19,7 @@ function validateParams(p5, fn, lifecycles) { // and so on. const p5Constructors = {}; - function loadP5Constructors() { + fn.loadP5Constructors = function () { // Make a list of all p5 classes to be used for argument validation // This must be done only when everything has loaded otherwise we get // an empty array @@ -131,8 +132,6 @@ function validateParams(p5, fn, lifecycles) { const { funcName, funcClass } = extractFuncNameAndClass(func); let funcInfo = dataDoc[funcClass][funcName]; - if(!funcInfo) return; - let overloads = []; if (funcInfo.hasOwnProperty('overloads')) { overloads = funcInfo.overloads; @@ -331,7 +330,7 @@ function validateParams(p5, fn, lifecycles) { * @returns {String} The friendly error message. */ fn.friendlyParamError = function (zodErrorObj, func) { - let message = '🌸 p5.js says: '; + let message; // The `zodErrorObj` might contain multiple errors of equal importance // (after scoring the schema closeness in `findClosestSchema`). Here, we // always print the first error so that user can work through the errors @@ -392,16 +391,16 @@ function validateParams(p5, fn, lifecycles) { } case 'too_small': { const minArgs = currentError.minimum; - message += `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`; + message = `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`; break; } case 'invalid_type': { - message += buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); + message = buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); break; } case 'too_big': { const maxArgs = currentError.maximum; - message += `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`; + message = `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`; break; } default: { @@ -448,10 +447,6 @@ function validateParams(p5, fn, lifecycles) { return; // skip FES } - if (!Array.isArray(args)) { - args = Array.from(args); - } - // An edge case: even when all arguments are optional and therefore, // theoretically allowed to stay undefined and valid, it is likely that the // user intended to call the function with non-undefined arguments. Skip @@ -468,7 +463,6 @@ function validateParams(p5, fn, lifecycles) { let funcSchemas = schemaRegistry.get(func); if (!funcSchemas) { funcSchemas = fn.generateZodSchemasForFunc(func); - if (!funcSchemas) return; schemaRegistry.set(func, funcSchemas); } @@ -488,26 +482,11 @@ function validateParams(p5, fn, lifecycles) { }; } }; - - lifecycles.presetup = function(){ - loadP5Constructors(); - - const excludes = ['validate']; - for(const f in this){ - if(!excludes.includes(f) && !f.startsWith('_') && typeof this[f] === 'function'){ - const copy = this[f]; - - this[f] = function(...args) { - this.validate(f, args); - return copy.call(this, ...args); - }; - } - } - }; } export default validateParams; if (typeof p5 !== 'undefined') { validateParams(p5, p5.prototype); -} + p5.prototype.loadP5Constructors(); +} \ No newline at end of file diff --git a/src/core/friendly_errors/stacktrace.js b/src/core/friendly_errors/stacktrace.js index 1777abac41..fe6a1b5722 100644 --- a/src/core/friendly_errors/stacktrace.js +++ b/src/core/friendly_errors/stacktrace.js @@ -2,6 +2,8 @@ * @for p5 * @requires core */ +import p5 from '../main'; + // Borrow from stacktracejs https://github.com/stacktracejs/stacktrace.js with // minor modifications. The license for the same and the code is included below @@ -239,14 +241,7 @@ function ErrorStackParser() { // End borrow // wrapper exposing ErrorStackParser -function stacktrace(p5, fn){ - p5._getErrorStackParser = function getErrorStackParser() { - return new ErrorStackParser(); - }; -} - -export default stacktrace; - -if (typeof p5 !== 'undefined') { - stacktrace(p5, p5.prototype); -} +p5._getErrorStackParser = function getErrorStackParser() { + return new ErrorStackParser(); +}; +export default p5; diff --git a/src/core/init.js b/src/core/init.js index d6ac049bb2..88922bbd71 100644 --- a/src/core/init.js +++ b/src/core/init.js @@ -12,7 +12,7 @@ import { initialize as initTranslator } from './internationalization'; * @private * @return {Undefined} */ -export const _globalInit = () => { +const _globalInit = () => { // Could have been any property defined within the p5 constructor. // If that property is already a part of the global object, // this code has already run before, likely due to a duplicate import @@ -37,7 +37,7 @@ export const _globalInit = () => { }; // make a promise that resolves when the document is ready -export const waitForDocumentReady = () => +const waitForDocumentReady = () => new Promise((resolve, reject) => { // if the page is ready, initialize p5 immediately if (document.readyState === 'complete') { @@ -50,6 +50,8 @@ export const waitForDocumentReady = () => }); // only load translations if we're using the full, un-minified library -export const waitingForTranslator = +const waitingForTranslator = typeof IS_MINIFIED === 'undefined' ? initTranslator() : Promise.resolve(); + +Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); diff --git a/src/core/rendering.js b/src/core/rendering.js index 810ce3bc32..29a779d7ea 100644 --- a/src/core/rendering.js +++ b/src/core/rendering.js @@ -9,6 +9,8 @@ import { Framebuffer } from '../webgl/p5.Framebuffer'; let renderers; function rendering(p5, fn){ + let defaultId = 'defaultCanvas0'; // this gets set again in createCanvas + const defaultClass = 'p5Canvas'; // Extend additional renderers object to p5 class, new renderer can be similarly attached renderers = p5.renderers = {}; @@ -124,7 +126,7 @@ function rendering(p5, fn){ * @return {p5.Renderer} */ p5.prototype.createCanvas = function (w, h, renderer, ...args) { - // p5._validateParameters('createCanvas', arguments); + p5._validateParameters('createCanvas', arguments); //optional: renderer, otherwise defaults to p2d let selectedRenderer = constants.P2D @@ -240,7 +242,7 @@ function rendering(p5, fn){ * */ p5.prototype.resizeCanvas = function (w, h, noRedraw) { - // p5._validateParameters('resizeCanvas', arguments); + p5._validateParameters('resizeCanvas', arguments); if (this._renderer) { // Make sure width and height are updated before the renderer resizes so // that framebuffers updated from the resize read the correct size @@ -401,7 +403,7 @@ function rendering(p5, fn){ args[1] = args[0]; args[0] = constants.P2D; } - // p5._validateParameters('createGraphics', arguments); + p5._validateParameters('createGraphics', arguments); return new p5.Graphics(w, h, args[0], this, args[1]); }; diff --git a/src/core/transform.js b/src/core/transform.js index 5ba580999c..e6e33c47e9 100644 --- a/src/core/transform.js +++ b/src/core/transform.js @@ -461,7 +461,7 @@ function transform(p5, fn){ * */ fn.rotate = function(angle, axis) { - // p5._validateParameters('rotate', arguments); + p5._validateParameters('rotate', arguments); this._renderer.rotate(this._toRadians(angle), axis); return this; }; @@ -597,7 +597,7 @@ function transform(p5, fn){ */ fn.rotateX = function(angle) { this._assert3d('rotateX'); - // p5._validateParameters('rotateX', arguments); + p5._validateParameters('rotateX', arguments); this._renderer.rotateX(this._toRadians(angle)); return this; }; @@ -733,7 +733,7 @@ function transform(p5, fn){ */ fn.rotateY = function(angle) { this._assert3d('rotateY'); - // p5._validateParameters('rotateY', arguments); + p5._validateParameters('rotateY', arguments); this._renderer.rotateY(this._toRadians(angle)); return this; }; @@ -869,7 +869,7 @@ function transform(p5, fn){ */ fn.rotateZ = function(angle) { this._assert3d('rotateZ'); - // p5._validateParameters('rotateZ', arguments); + p5._validateParameters('rotateZ', arguments); this._renderer.rotateZ(this._toRadians(angle)); return this; }; @@ -1041,7 +1041,7 @@ function transform(p5, fn){ * @chainable */ fn.scale = function(x, y, z) { - // p5._validateParameters('scale', arguments); + p5._validateParameters('scale', arguments); // Only check for Vector argument type if Vector is available if (x instanceof p5.Vector) { const v = x; @@ -1136,7 +1136,7 @@ function transform(p5, fn){ * */ fn.shearX = function(angle) { - // p5._validateParameters('shearX', arguments); + p5._validateParameters('shearX', arguments); const rad = this._toRadians(angle); this._renderer.applyMatrix(1, 0, Math.tan(rad), 1, 0, 0); return this; @@ -1213,7 +1213,7 @@ function transform(p5, fn){ * */ fn.shearY = function(angle) { - // p5._validateParameters('shearY', arguments); + p5._validateParameters('shearY', arguments); const rad = this._toRadians(angle); this._renderer.applyMatrix(1, Math.tan(rad), 0, 1, 0, 0); return this; @@ -1396,7 +1396,7 @@ function transform(p5, fn){ * @chainable */ fn.translate = function(x, y, z) { - // p5._validateParameters('translate', arguments); + p5._validateParameters('translate', arguments); if (this._renderer.isP3D) { this._renderer.translate(x, y, z); } else { diff --git a/src/data/p5.TypedDict.js b/src/data/p5.TypedDict.js index 51fcda7d5b..d816769c0c 100644 --- a/src/data/p5.TypedDict.js +++ b/src/data/p5.TypedDict.js @@ -40,7 +40,7 @@ function typedDict(p5, fn){ */ fn.createStringDict = function (key, value) { - // p5._validateParameters('createStringDict', arguments); + p5._validateParameters('createStringDict', arguments); return new p5.StringDict(key, value); }; @@ -74,7 +74,7 @@ function typedDict(p5, fn){ */ fn.createNumberDict = function (key, value) { - // p5._validateParameters('createNumberDict', arguments); + p5._validateParameters('createNumberDict', arguments); return new p5.NumberDict(key, value); }; diff --git a/src/dom/dom.js b/src/dom/dom.js index ae40b40ace..50713d327b 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -99,7 +99,7 @@ function dom(p5, fn){ * */ fn.select = function (e, p) { - // p5._validateParameters('select', arguments); + p5._validateParameters('select', arguments); const container = this._getContainer(p); const res = container.querySelector(e); if (res) { @@ -193,7 +193,7 @@ function dom(p5, fn){ * */ fn.selectAll = function (e, p) { - // p5._validateParameters('selectAll', arguments); + p5._validateParameters('selectAll', arguments); const arr = []; const container = this._getContainer(p); const res = container.querySelectorAll(e); @@ -306,7 +306,7 @@ function dom(p5, fn){ * */ fn.createElement = function (tag, content) { - // p5._validateParameters('createElement', arguments); + p5._validateParameters('createElement', arguments); const elt = document.createElement(tag); if (typeof content !== 'undefined') { elt.innerHTML = content; @@ -381,7 +381,7 @@ function dom(p5, fn){ * */ fn.removeElements = function (e) { - // p5._validateParameters('removeElements', arguments); + p5._validateParameters('removeElements', arguments); // el.remove splices from this._elements, so don't mix iteration with it const isNotCanvasElement = el => !(el.elt instanceof HTMLCanvasElement); const removeableElements = this._elements.filter(isNotCanvasElement); @@ -613,7 +613,7 @@ function dom(p5, fn){ * @return {p5.Element} new p5.Element object. */ fn.createImg = function () { - // p5._validateParameters('createImg', arguments); + p5._validateParameters('createImg', arguments); const elt = document.createElement('img'); const args = arguments; let self; @@ -689,7 +689,7 @@ function dom(p5, fn){ * */ fn.createA = function (href, html, target) { - // p5._validateParameters('createA', arguments); + p5._validateParameters('createA', arguments); const elt = document.createElement('a'); elt.href = href; elt.innerHTML = html; @@ -819,7 +819,7 @@ function dom(p5, fn){ * */ fn.createSlider = function (min, max, value, step) { - // p5._validateParameters('createSlider', arguments); + p5._validateParameters('createSlider', arguments); const elt = document.createElement('input'); elt.type = 'range'; elt.min = min; @@ -910,7 +910,7 @@ function dom(p5, fn){ * */ fn.createButton = function (label, value) { - // p5._validateParameters('createButton', arguments); + p5._validateParameters('createButton', arguments); const elt = document.createElement('button'); elt.innerHTML = label; if (value) elt.value = value; @@ -1014,7 +1014,7 @@ function dom(p5, fn){ * */ fn.createCheckbox = function (...args) { - // p5._validateParameters('createCheckbox', args); + p5._validateParameters('createCheckbox', args); // Create a container element const elt = document.createElement('div'); @@ -1241,7 +1241,7 @@ function dom(p5, fn){ */ fn.createSelect = function (...args) { - // p5._validateParameters('createSelect', args); + p5._validateParameters('createSelect', args); let self; let arg = args[0]; if (arg instanceof Element && arg.elt instanceof HTMLSelectElement) { @@ -1715,7 +1715,7 @@ function dom(p5, fn){ * */ fn.createColorPicker = function (value) { - // p5._validateParameters('createColorPicker', arguments); + p5._validateParameters('createColorPicker', arguments); // TODO: This implementation needs to be rechecked or reimplemented // The way it worked with color is a bit too complex const elt = document.createElement('input'); @@ -1826,7 +1826,7 @@ function dom(p5, fn){ * @return {p5.Element} */ fn.createInput = function (value = '', type = 'text') { - // p5._validateParameters('createInput', arguments); + p5._validateParameters('createInput', arguments); let elt = document.createElement('input'); elt.setAttribute('value', value); elt.setAttribute('type', type); @@ -1936,7 +1936,7 @@ function dom(p5, fn){ * */ fn.createFileInput = function (callback, multiple = false) { - // p5._validateParameters('createFileInput', arguments); + p5._validateParameters('createFileInput', arguments); const handleFileSelect = function (event) { for (const file of event.target.files) { diff --git a/src/dom/p5.MediaElement.js b/src/dom/p5.MediaElement.js index fa68e50cee..d263617046 100644 --- a/src/dom/p5.MediaElement.js +++ b/src/dom/p5.MediaElement.js @@ -1459,7 +1459,7 @@ function media(p5, fn){ * */ fn.createVideo = function (src, callback) { - // p5._validateParameters('createVideo', arguments); + p5._validateParameters('createVideo', arguments); return createMedia(this, 'video', src, callback); }; @@ -1507,7 +1507,7 @@ function media(p5, fn){ * */ fn.createAudio = function (src, callback) { - // p5._validateParameters('createAudio', arguments); + p5._validateParameters('createAudio', arguments); return createMedia(this, 'audio', src, callback); }; @@ -1668,7 +1668,7 @@ function media(p5, fn){ * */ fn.createCapture = function (...args) { - // p5._validateParameters('createCapture', args); + p5._validateParameters('createCapture', args); // return if getUserMedia is not supported by the browser if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) { diff --git a/src/events/acceleration.js b/src/events/acceleration.js index 37e657dc12..8a6d1b86b5 100644 --- a/src/events/acceleration.js +++ b/src/events/acceleration.js @@ -451,7 +451,7 @@ function acceleration(p5, fn){ */ fn.setMoveThreshold = function (val) { - // p5._validateParameters('setMoveThreshold', arguments); + p5._validateParameters('setMoveThreshold', arguments); move_threshold = val; }; @@ -493,7 +493,7 @@ function acceleration(p5, fn){ */ fn.setShakeThreshold = function (val) { - // p5._validateParameters('setShakeThreshold', arguments); + p5._validateParameters('setShakeThreshold', arguments); shake_threshold = val; }; diff --git a/src/events/keyboard.js b/src/events/keyboard.js index 5b0de949ed..fbc03ffad4 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -903,7 +903,7 @@ function keyboard(p5, fn){ * */ fn.keyIsDown = function(code) { - // p5._validateParameters('keyIsDown', arguments); + p5._validateParameters('keyIsDown', arguments); return this._downKeys[code] || false; }; diff --git a/src/image/image.js b/src/image/image.js index af08c052dc..7db4af9ab4 100644 --- a/src/image/image.js +++ b/src/image/image.js @@ -148,7 +148,7 @@ function image(p5, fn){ * */ fn.createImage = function(width, height) { - // p5._validateParameters('createImage', arguments); + p5._validateParameters('createImage', arguments); return new p5.Image(width, height); }; @@ -272,7 +272,7 @@ function image(p5, fn){ * @param {String} [extension] */ fn.saveCanvas = function(...args) { - // p5._validateParameters('saveCanvas', args); + p5._validateParameters('saveCanvas', args); // copy arguments to array let htmlCanvas, filename, extension, temporaryGraphics; @@ -658,7 +658,7 @@ function image(p5, fn){ * */ fn.saveFrames = function(fName, ext, _duration, _fps, callback) { - // p5._validateParameters('saveFrames', arguments); + p5._validateParameters('saveFrames', arguments); let duration = _duration || 3; duration = Math.max(Math.min(duration, 15), 0); duration = duration * 1000; diff --git a/src/image/loading_displaying.js b/src/image/loading_displaying.js index a95efdcf0c..b8fa13db81 100644 --- a/src/image/loading_displaying.js +++ b/src/image/loading_displaying.js @@ -107,7 +107,7 @@ function loadingDisplaying(p5, fn){ successCallback, failureCallback ) { - // p5._validateParameters('loadImage', arguments); + p5._validateParameters('loadImage', arguments); try{ let pImg = new p5.Image(1, 1, this); @@ -1063,7 +1063,7 @@ function loadingDisplaying(p5, fn){ ) { // set defaults per spec: https://goo.gl/3ykfOq - // p5._validateParameters('image', arguments); + p5._validateParameters('image', arguments); let defW = img.width; let defH = img.height; @@ -1291,7 +1291,7 @@ function loadingDisplaying(p5, fn){ * @param {p5.Color} color the tint color */ fn.tint = function(...args) { - // p5._validateParameters('tint', args); + p5._validateParameters('tint', args); const c = this.color(...args); this._renderer.states.tint = c._getRGBA([255, 255, 255, 255]); }; @@ -1445,7 +1445,7 @@ function loadingDisplaying(p5, fn){ * */ fn.imageMode = function(m) { - // p5._validateParameters('imageMode', arguments); + p5._validateParameters('imageMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || diff --git a/src/image/pixels.js b/src/image/pixels.js index 770cfede47..c2e2e10c6b 100644 --- a/src/image/pixels.js +++ b/src/image/pixels.js @@ -275,7 +275,7 @@ function pixels(p5, fn){ * @param {(BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL)} blendMode */ fn.blend = function(...args) { - // p5._validateParameters('blend', args); + p5._validateParameters('blend', args); if (this._renderer) { this._renderer.blend(...args); } else { @@ -352,7 +352,7 @@ function pixels(p5, fn){ * @param {Integer} dh */ fn.copy = function(...args) { - // p5._validateParameters('copy', args); + p5._validateParameters('copy', args); let srcImage, sx, sy, sw, sh, dx, dy, dw, dh; if (args.length === 9) { @@ -721,7 +721,7 @@ function pixels(p5, fn){ * frag shader using a `tex0` uniform. */ fn.filter = function(...args) { - // p5._validateParameters('filter', args); + p5._validateParameters('filter', args); let { shader, operation, value, useWebGL } = parseFilterArgs(...args); @@ -916,7 +916,7 @@ function pixels(p5, fn){ * @return {Number[]} color of the pixel at (x, y) in array format `[R, G, B, A]`. */ fn.get = function(x, y, w, h) { - // p5._validateParameters('get', arguments); + p5._validateParameters('get', arguments); return this._renderer.get(...arguments); }; @@ -967,7 +967,7 @@ function pixels(p5, fn){ * */ fn.loadPixels = function(...args) { - // p5._validateParameters('loadPixels', args); + p5._validateParameters('loadPixels', args); this._renderer.loadPixels(); }; @@ -1147,7 +1147,7 @@ function pixels(p5, fn){ * */ fn.updatePixels = function(x, y, w, h) { - // p5._validateParameters('updatePixels', arguments); + p5._validateParameters('updatePixels', arguments); // graceful fail - if loadPixels() or set() has not been called, pixel // array will be empty, ignore call to updatePixels() if (this.pixels.length === 0) { diff --git a/src/io/files.js b/src/io/files.js index a73a169daf..3834dbf6bc 100644 --- a/src/io/files.js +++ b/src/io/files.js @@ -291,7 +291,7 @@ function files(p5, fn){ * */ fn.loadJSON = async function (path, successCallback, errorCallback) { - // p5._validateParameters('loadJSON', arguments); + p5._validateParameters('loadJSON', arguments); try{ const { data } = await request(path, 'json'); @@ -438,7 +438,7 @@ function files(p5, fn){ * */ fn.loadStrings = async function (path, successCallback, errorCallback) { - // p5._validateParameters('loadStrings', arguments); + p5._validateParameters('loadStrings', arguments); try{ let { data } = await request(path, 'text'); @@ -853,7 +853,7 @@ function files(p5, fn){ * @return {Promise} */ fn.httpGet = async function (path, datatype='text', successCallback, errorCallback) { - // p5._validateParameters('httpGet', arguments); + p5._validateParameters('httpGet', arguments); if (typeof datatype === 'function') { errorCallback = successCallback; @@ -950,7 +950,7 @@ function files(p5, fn){ * @return {Promise} */ fn.httpPost = async function (path, data, datatype='text', successCallback, errorCallback) { - // p5._validateParameters('httpPost', arguments); + p5._validateParameters('httpPost', arguments); // This behave similarly to httpGet and additional options should be passed // as a `Request`` to path. Both method and body will be overridden. @@ -1812,7 +1812,7 @@ function files(p5, fn){ * */ fn.saveJSON = function (json, filename, optimize) { - // p5._validateParameters('saveJSON', arguments); + p5._validateParameters('saveJSON', arguments); let stringify; if (optimize) { stringify = JSON.stringify(json); @@ -1956,7 +1956,7 @@ function files(p5, fn){ * */ fn.saveStrings = function (list, filename, extension, isCRLF) { - // p5._validateParameters('saveStrings', arguments); + p5._validateParameters('saveStrings', arguments); const ext = extension || 'txt'; const pWriter = new p5.PrintWriter(filename, ext); for (let item of list) { @@ -2018,7 +2018,7 @@ function files(p5, fn){ * */ fn.saveTable = function (table, filename, options) { - // p5._validateParameters('saveTable', arguments); + p5._validateParameters('saveTable', arguments); let ext; if (options === undefined) { ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length); diff --git a/src/math/calculation.js b/src/math/calculation.js index 5075b8c8ad..56bc535d74 100644 --- a/src/math/calculation.js +++ b/src/math/calculation.js @@ -147,7 +147,7 @@ function calculation(p5, fn){ * */ fn.constrain = function(n, low, high) { - // p5._validateParameters('constrain', arguments); + p5._validateParameters('constrain', arguments); return Math.max(Math.min(n, high), low); }; @@ -216,7 +216,7 @@ function calculation(p5, fn){ * @return {Number} distance between the two points. */ fn.dist = function(...args) { - // p5._validateParameters('dist', args); + p5._validateParameters('dist', args); if (args.length === 4) { //2D return Math.hypot(args[2] - args[0], args[3] - args[1]); @@ -417,7 +417,7 @@ function calculation(p5, fn){ * */ fn.lerp = function(start, stop, amt) { - // p5._validateParameters('lerp', arguments); + p5._validateParameters('lerp', arguments); return amt * (stop - start) + start; }; @@ -528,7 +528,7 @@ function calculation(p5, fn){ * */ fn.mag = function(x, y) { - // p5._validateParameters('mag', arguments); + p5._validateParameters('mag', arguments); return Math.hypot(x, y); }; @@ -604,7 +604,7 @@ function calculation(p5, fn){ * */ fn.map = function(n, start1, stop1, start2, stop2, withinBounds) { - // p5._validateParameters('map', arguments); + p5._validateParameters('map', arguments); const newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2; if (!withinBounds) { return newval; @@ -821,7 +821,7 @@ function calculation(p5, fn){ * */ fn.norm = function(n, start, stop) { - // p5._validateParameters('norm', arguments); + p5._validateParameters('norm', arguments); return this.map(n, start, stop, 0, 1); }; @@ -1094,7 +1094,7 @@ function calculation(p5, fn){ * */ fn.fract = function(toConvert) { - // p5._validateParameters('fract', arguments); + p5._validateParameters('fract', arguments); let sign = 0; let num = Number(toConvert); if (isNaN(num) || Math.abs(num) === Infinity) { diff --git a/src/math/random.js b/src/math/random.js index 7e272c7e02..dca10fad7a 100644 --- a/src/math/random.js +++ b/src/math/random.js @@ -261,7 +261,7 @@ function random(p5, fn){ * @return {*} random element from the array. */ fn.random = function(min, max) { - // p5._validateParameters('random', arguments); + p5._validateParameters('random', arguments); let rand; if (this[randomStateProp] != null) { diff --git a/src/math/trigonometry.js b/src/math/trigonometry.js index 89335ca771..8fe2f5f169 100644 --- a/src/math/trigonometry.js +++ b/src/math/trigonometry.js @@ -741,7 +741,7 @@ function trigonometry(p5, fn){ * @return {(RADIANS|DEGREES)} mode either RADIANS or DEGREES */ fn.angleMode = function(mode) { - // p5._validateParameters('angleMode', arguments); + p5._validateParameters('angleMode', arguments); if (typeof mode === 'undefined') { return this._angleMode; } else if (mode === DEGREES || mode === RADIANS) { diff --git a/src/shape/2d_primitives.js b/src/shape/2d_primitives.js index a060ef07bd..3f1e0a3506 100644 --- a/src/shape/2d_primitives.js +++ b/src/shape/2d_primitives.js @@ -309,8 +309,7 @@ function primitives(p5, fn){ * */ fn.arc = function(x, y, w, h, start, stop, mode, detail) { - // this.validate("p5.arc", arguments); - // p5._validateParameters('arc', arguments); + p5._validateParameters('arc', arguments); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately @@ -481,7 +480,7 @@ function primitives(p5, fn){ * draw a stroke for a detail of more than 50. */ fn.ellipse = function(x, y, w, h, detailX) { - // p5._validateParameters('ellipse', arguments); + p5._validateParameters('ellipse', arguments); return this._renderEllipse(...arguments); }; @@ -531,7 +530,7 @@ function primitives(p5, fn){ * */ fn.circle = function(...args) { - // p5._validateParameters('circle', args); + p5._validateParameters('circle', args); const argss = args.slice( 0, 2); argss.push(args[2], args[2]); return this._renderEllipse(...argss); @@ -711,7 +710,7 @@ function primitives(p5, fn){ * @chainable */ fn.line = function(...args) { - // p5._validateParameters('line', args); + p5._validateParameters('line', args); if (this._renderer.states.strokeColor) { this._renderer.line(...args); @@ -895,7 +894,7 @@ function primitives(p5, fn){ * @chainable */ fn.point = function(...args) { - // p5._validateParameters('point', args); + p5._validateParameters('point', args); if (this._renderer.states.strokeColor) { if (args.length === 1 && args[0] instanceof p5.Vector) { @@ -1056,7 +1055,7 @@ function primitives(p5, fn){ * @chainable */ fn.quad = function(...args) { - // p5._validateParameters('quad', args); + p5._validateParameters('quad', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { if (this._renderer.isP3D && args.length < 12) { @@ -1214,7 +1213,7 @@ function primitives(p5, fn){ * @chainable */ fn.rect = function(...args) { - // p5._validateParameters('rect', args); + p5._validateParameters('rect', args); return this._renderRect(...args); }; @@ -1328,7 +1327,7 @@ function primitives(p5, fn){ * */ fn.square = function(x, y, s, tl, tr, br, bl) { - // p5._validateParameters('square', arguments); + p5._validateParameters('square', arguments); // duplicate width for height in case of square return this._renderRect.call(this, x, y, s, s, tl, tr, br, bl); }; @@ -1432,7 +1431,7 @@ function primitives(p5, fn){ * */ fn.triangle = function(...args) { - // p5._validateParameters('triangle', args); + p5._validateParameters('triangle', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { this._renderer.triangle(args); diff --git a/src/shape/attributes.js b/src/shape/attributes.js index 10e6f720cd..bf787d1df7 100644 --- a/src/shape/attributes.js +++ b/src/shape/attributes.js @@ -85,7 +85,7 @@ function attributes(p5, fn){ * */ fn.ellipseMode = function(m) { - // p5._validateParameters('ellipseMode', arguments); + p5._validateParameters('ellipseMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || @@ -288,7 +288,7 @@ function attributes(p5, fn){ * */ fn.rectMode = function(m) { - // p5._validateParameters('rectMode', arguments); + p5._validateParameters('rectMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || @@ -427,7 +427,7 @@ function attributes(p5, fn){ * */ fn.strokeCap = function(cap) { - // p5._validateParameters('strokeCap', arguments); + p5._validateParameters('strokeCap', arguments); if ( cap === constants.ROUND || cap === constants.SQUARE || @@ -526,7 +526,7 @@ function attributes(p5, fn){ * */ fn.strokeJoin = function(join) { - // p5._validateParameters('strokeJoin', arguments); + p5._validateParameters('strokeJoin', arguments); if ( join === constants.ROUND || join === constants.BEVEL || @@ -593,7 +593,7 @@ function attributes(p5, fn){ * */ fn.strokeWeight = function(w) { - // p5._validateParameters('strokeWeight', arguments); + p5._validateParameters('strokeWeight', arguments); this._renderer.strokeWeight(w); return this; }; diff --git a/src/shape/curves.js b/src/shape/curves.js index 93a19c1d38..30f7287d9d 100644 --- a/src/shape/curves.js +++ b/src/shape/curves.js @@ -201,7 +201,7 @@ function curves(p5, fn){ * @chainable */ fn.bezier = function(...args) { - // p5._validateParameters('bezier', args); + p5._validateParameters('bezier', args); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately @@ -312,7 +312,7 @@ function curves(p5, fn){ * */ fn.bezierDetail = function(d) { - // p5._validateParameters('bezierDetail', arguments); + p5._validateParameters('bezierDetail', arguments); this._bezierDetail = d; return this; }; @@ -432,7 +432,7 @@ function curves(p5, fn){ * */ fn.bezierPoint = function(a, b, c, d, t) { - // p5._validateParameters('bezierPoint', arguments); + p5._validateParameters('bezierPoint', arguments); const adjustedT = 1 - t; return ( @@ -550,7 +550,7 @@ function curves(p5, fn){ * */ fn.bezierTangent = function(a, b, c, d, t) { - // p5._validateParameters('bezierTangent', arguments); + p5._validateParameters('bezierTangent', arguments); const adjustedT = 1 - t; return ( @@ -756,7 +756,7 @@ function curves(p5, fn){ * @chainable */ fn.curve = function(...args) { - // p5._validateParameters('curve', args); + p5._validateParameters('curve', args); if (this._renderer.states.strokeColor) { this._renderer.curve(...args); @@ -815,7 +815,7 @@ function curves(p5, fn){ * */ fn.curveTightness = function(t) { - // p5._validateParameters('curveTightness', arguments); + p5._validateParameters('curveTightness', arguments); this._renderer._curveTightness = t; return this; }; @@ -933,7 +933,7 @@ function curves(p5, fn){ * */ fn.curvePoint = function(a, b, c, d, t) { - // p5._validateParameters('curvePoint', arguments); + p5._validateParameters('curvePoint', arguments); const s = this._renderer._curveTightness, t3 = t * t * t, t2 = t * t, @@ -1049,7 +1049,7 @@ function curves(p5, fn){ * */ fn.curveTangent = function(a, b, c, d, t) { - // p5._validateParameters('curveTangent', arguments); + p5._validateParameters('curveTangent', arguments); const s = this._renderer._curveTightness, tt3 = t * t * 3, diff --git a/src/shape/vertex.js b/src/shape/vertex.js index 71ba437bb3..34f452f45f 100644 --- a/src/shape/vertex.js +++ b/src/shape/vertex.js @@ -398,7 +398,7 @@ function vertex(p5, fn){ * */ fn.beginShape = function(kind) { - // p5._validateParameters('beginShape', arguments); + p5._validateParameters('beginShape', arguments); this._renderer.beginShape(...arguments); }; @@ -1061,7 +1061,7 @@ function vertex(p5, fn){ * */ fn.curveVertex = function(...args) { - // p5._validateParameters('curveVertex', args); + p5._validateParameters('curveVertex', args); this._renderer.splineVertex(...args); return this; }; @@ -1230,7 +1230,7 @@ function vertex(p5, fn){ * */ fn.endShape = function(mode, count = 1) { - // p5._validateParameters('endShape', arguments); + p5._validateParameters('endShape', arguments); if (count < 1) { console.log('🌸 p5.js says: You can not have less than one instance'); count = 1; @@ -1487,7 +1487,7 @@ function vertex(p5, fn){ } else { [x1, y1, z1, x2, y2, z2] = args; } - // p5._validateParameters('quadraticVertex', args); + p5._validateParameters('quadraticVertex', args); const prevOrder = this.bezierOrder(); this.bezierOrder(2); this.bezierVertex(x1, y1, z1); @@ -1680,7 +1680,7 @@ function vertex(p5, fn){ */ fn.normal = function(x, y, z) { this._assert3d('normal'); - // p5._validateParameters('normal', arguments); + p5._validateParameters('normal', arguments); this._renderer.normal(...arguments); return this; diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index e6143c3d16..f5f5b0bb16 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -572,7 +572,7 @@ function font(p5, fn) { // load the raw font bytes let result = await fn.loadBytes(path); //console.log('result:', result); - + if (!result) { throw Error('Failed to load font data'); } @@ -597,13 +597,11 @@ function font(p5, fn) { } catch (err) { // failed to parse the font, load it as a simple FontFace - let ident = name || path - .substring(path.lastIndexOf('/') + 1) - .replace(/\.[^/.]+$/, ""); + let ident = name || path.substring(path.lastIndexOf('/') + 1); console.warn(`WARN: No glyph data for '${ident}', retrying as FontFace`); try { // create a FontFace object and pass it to p5.Font - pfont = await create(this, ident, path, descriptors); + pfont = await create(this, name, path, descriptors); } catch (err) { if (error) error(err); diff --git a/src/type/text2d.js b/src/type/text2d.js index a7862ca7c1..8d055357d4 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -103,6 +103,8 @@ function text2d(p5, fn) { textLeading: { default: 15 }, textSize: { default: 12 }, textWrap: { default: fn.WORD }, + + // added v2.0 fontStretch: { default: fn.NORMAL, isShorthand: true }, // font-stretch: { default: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded } fontWeight: { default: fn.NORMAL, isShorthand: true }, // font-stretch: { default: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded } lineHeight: { default: fn.NORMAL, isShorthand: true }, // line-height: { default: normal | number | length | percentage } @@ -454,28 +456,17 @@ function text2d(p5, fn) { return this._pInst; } - // getter: get props from drawingContext - let context = this.textDrawingContext(); + // getter: get props from this.textDrawingContext() properties = ContextTextProps.reduce((props, p) => { - props[p] = context[p]; + props[p] = this.textDrawingContext()[p]; return props; }, {}); - // add renderer props + // add renderer.states props Object.keys(RendererTextProps).forEach(p => { + properties[p] = this.states[p]; if (RendererTextProps[p]?.type === 'Context2d') { - properties[p] = context[p]; - } - else { // a renderer.states property - if (p === 'textFont') { - // avoid circular ref. inside textFont - properties[p] = Object.assign({}, this._currentTextFont()); - delete properties[p]._pInst; - console.log('textFont: ', properties[p]); - } - else { - properties[p] = this.states[p]; - } + properties[p] = this.textDrawingContext()[p]; } }); diff --git a/src/utilities/string_functions.js b/src/utilities/string_functions.js index 94e4cfdf9f..07bb5dc073 100644 --- a/src/utilities/string_functions.js +++ b/src/utilities/string_functions.js @@ -47,7 +47,7 @@ function stringFunctions(p5, fn){ * */ fn.join = function(list, separator) { - // p5._validateParameters('join', arguments); + p5._validateParameters('join', arguments); return list.join(separator); }; @@ -106,7 +106,7 @@ function stringFunctions(p5, fn){ * */ fn.match = function(str, reg) { - // p5._validateParameters('match', arguments); + p5._validateParameters('match', arguments); return str.match(reg); }; @@ -176,7 +176,7 @@ function stringFunctions(p5, fn){ * */ fn.matchAll = function(str, reg) { - // p5._validateParameters('matchAll', arguments); + p5._validateParameters('matchAll', arguments); const re = new RegExp(reg, 'g'); let match = re.exec(str); const matches = []; @@ -269,7 +269,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nf = function(nums, left, right) { - // p5._validateParameters('nf', arguments); + p5._validateParameters('nf', arguments); if (nums instanceof Array) { return nums.map(x => doNf(x, left, right)); } else { @@ -402,7 +402,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfc = function(num, right) { - // p5._validateParameters('nfc', arguments); + p5._validateParameters('nfc', arguments); if (num instanceof Array) { return num.map(x => doNfc(x, right)); } else { @@ -544,7 +544,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfp = function(...args) { - // p5._validateParameters('nfp', args); + p5._validateParameters('nfp', args); const nfRes = fn.nf.apply(this, args); if (nfRes instanceof Array) { return nfRes.map(addNfp); @@ -661,7 +661,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfs = function(...args) { - // p5._validateParameters('nfs', args); + p5._validateParameters('nfs', args); const nfRes = fn.nf.apply(this, args); if (nfRes instanceof Array) { return nfRes.map(addNfs); @@ -731,7 +731,7 @@ function stringFunctions(p5, fn){ * */ fn.split = function(str, delim) { - // p5._validateParameters('split', arguments); + p5._validateParameters('split', arguments); return str.split(delim); }; @@ -874,7 +874,7 @@ function stringFunctions(p5, fn){ * */ fn.splitTokens = function(value, delims) { - // p5._validateParameters('splitTokens', arguments); + p5._validateParameters('splitTokens', arguments); let d; if (typeof delims !== 'undefined') { let str = delims; @@ -974,7 +974,7 @@ function stringFunctions(p5, fn){ * @return {String[]} trimmed strings. */ fn.trim = function(str) { - // p5._validateParameters('trim', arguments); + p5._validateParameters('trim', arguments); if (str instanceof Array) { return str.map(this.trim); } else { diff --git a/src/webgl/3d_primitives.js b/src/webgl/3d_primitives.js index 1c880d87d0..a2af7f3476 100644 --- a/src/webgl/3d_primitives.js +++ b/src/webgl/3d_primitives.js @@ -554,7 +554,7 @@ function primitives3D(p5, fn){ detailY = 1 ) { this._assert3d('plane'); - // p5._validateParameters('plane', arguments); + p5._validateParameters('plane', arguments); this._renderer.plane(width, height, detailX, detailY); return this; @@ -691,7 +691,7 @@ function primitives3D(p5, fn){ */ fn.box = function(width, height, depth, detailX, detailY) { this._assert3d('box'); - // p5._validateParameters('box', arguments); + p5._validateParameters('box', arguments); this._renderer.box(width, height, depth, detailX, detailY); @@ -823,7 +823,7 @@ function primitives3D(p5, fn){ */ fn.sphere = function(radius = 50, detailX = 24, detailY = 16) { this._assert3d('sphere'); - // p5._validateParameters('sphere', arguments); + p5._validateParameters('sphere', arguments); this._renderer.sphere(radius, detailX, detailY); @@ -1051,7 +1051,7 @@ function primitives3D(p5, fn){ topCap = true ) { this._assert3d('cylinder'); - // p5._validateParameters('cylinder', arguments); + p5._validateParameters('cylinder', arguments); this._renderer.cylinder(radius, height, detailX, detailY, bottomCap, topCap); @@ -1271,7 +1271,7 @@ function primitives3D(p5, fn){ cap = true ) { this._assert3d('cone'); - // p5._validateParameters('cone', arguments); + p5._validateParameters('cone', arguments); this._renderer.cone(radius, height, detailX, detailY, cap); @@ -1454,7 +1454,7 @@ function primitives3D(p5, fn){ detailY = 16 ) { this._assert3d('ellipsoid'); - // p5._validateParameters('ellipsoid', arguments); + p5._validateParameters('ellipsoid', arguments); this._renderer.ellipsoid(radiusX, radiusY, radiusZ, detailX, detailY); @@ -1613,7 +1613,7 @@ function primitives3D(p5, fn){ */ fn.torus = function(radius, tubeRadius, detailX, detailY) { this._assert3d('torus'); - // p5._validateParameters('torus', arguments); + p5._validateParameters('torus', arguments); this._renderer.torus(radius, tubeRadius, detailX, detailY); diff --git a/src/webgl/interaction.js b/src/webgl/interaction.js index 1b257ce6fd..71f6cf8c62 100644 --- a/src/webgl/interaction.js +++ b/src/webgl/interaction.js @@ -169,7 +169,7 @@ function interaction(p5, fn){ options ) { this._assert3d('orbitControl'); - // p5._validateParameters('orbitControl', arguments); + p5._validateParameters('orbitControl', arguments); const cam = this._renderer.states.curCamera; @@ -687,7 +687,7 @@ function interaction(p5, fn){ fn.debugMode = function(...args) { this._assert3d('debugMode'); - // p5._validateParameters('debugMode', args); + p5._validateParameters('debugMode', args); // start by removing existing 'post' registered debug methods for (let i = this._registeredMethods.post.length - 1; i >= 0; i--) { diff --git a/src/webgl/light.js b/src/webgl/light.js index 2d66d79ad0..bfeca289e8 100644 --- a/src/webgl/light.js +++ b/src/webgl/light.js @@ -191,7 +191,7 @@ function light(p5, fn){ */ fn.ambientLight = function (v1, v2, v3, a) { this._assert3d('ambientLight'); - // p5._validateParameters('ambientLight', arguments); + p5._validateParameters('ambientLight', arguments); this._renderer.ambientLight(...arguments); @@ -442,7 +442,7 @@ function light(p5, fn){ */ fn.specularColor = function (v1, v2, v3) { this._assert3d('specularColor'); - // p5._validateParameters('specularColor', arguments); + p5._validateParameters('specularColor', arguments); this._renderer.specularColor(...arguments); @@ -629,7 +629,7 @@ function light(p5, fn){ */ fn.directionalLight = function (v1, v2, v3, x, y, z) { this._assert3d('directionalLight'); - // p5._validateParameters('directionalLight', arguments); + p5._validateParameters('directionalLight', arguments); //@TODO: check parameters number this._renderer.directionalLight(...arguments); @@ -872,7 +872,7 @@ function light(p5, fn){ */ fn.pointLight = function (v1, v2, v3, x, y, z) { this._assert3d('pointLight'); - // p5._validateParameters('pointLight', arguments); + p5._validateParameters('pointLight', arguments); //@TODO: check parameters number this._renderer.pointLight(...arguments); @@ -1151,7 +1151,7 @@ function light(p5, fn){ quadraticAttenuation ) { this._assert3d('lightFalloff'); - // p5._validateParameters('lightFalloff', arguments); + p5._validateParameters('lightFalloff', arguments); this._renderer.lightFalloff( constantAttenuation, @@ -1378,7 +1378,7 @@ function light(p5, fn){ concentration ) { this._assert3d('spotLight'); - // p5._validateParameters('spotLight', arguments); + p5._validateParameters('spotLight', arguments); this._renderer.spotLight(...arguments); @@ -1445,7 +1445,7 @@ function light(p5, fn){ */ fn.noLights = function (...args) { this._assert3d('noLights'); - // p5._validateParameters('noLights', args); + p5._validateParameters('noLights', args); this._renderer.noLights(); diff --git a/src/webgl/loading.js b/src/webgl/loading.js index 3ada682900..4cf2f46b1d 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -335,7 +335,7 @@ function loading(p5, fn){ * @return {Promise} new p5.Geometry object. */ fn.loadModel = async function (path, fileType, normalize, successCallback, failureCallback) { - // p5._validateParameters('loadModel', arguments); + p5._validateParameters('loadModel', arguments); let flipU = false; let flipV = false; @@ -1086,7 +1086,7 @@ function loading(p5, fn){ */ fn.model = function (model, count = 1) { this._assert3d('model'); - // p5._validateParameters('model', arguments); + p5._validateParameters('model', arguments); if (model.vertices.length > 0) { if (!this._renderer.geometryInHash(model.gid)) { diff --git a/src/webgl/material.js b/src/webgl/material.js index 9b1593f5b2..5e455d50ba 100644 --- a/src/webgl/material.js +++ b/src/webgl/material.js @@ -125,7 +125,7 @@ function material(p5, fn){ successCallback, failureCallback ) { - // p5._validateParameters('loadShader', arguments); + p5._validateParameters('loadShader', arguments); const loadedShader = new Shader(); @@ -510,7 +510,7 @@ function material(p5, fn){ * */ fn.createShader = function (vertSrc, fragSrc, options) { - // p5._validateParameters('createShader', arguments); + p5._validateParameters('createShader', arguments); return new Shader(this._renderer, vertSrc, fragSrc, options); }; /** @@ -549,7 +549,7 @@ function material(p5, fn){ * @alt * A rectangle with a shader applied to it. */ - fn.loadFilterShader = async function (fragFilename, successCallback, failureCallback) { + fn.loadFilterShader = async function (fragFilename, successCallback, failureCallback) { p5._validateParameters('loadFilterShader', arguments); try { // Load the fragment shader @@ -558,7 +558,7 @@ function material(p5, fn){ // Create the shader using createFilterShader const loadedShader = this.createFilterShader(fragString, true); - + if (successCallback) { successCallback(loadedShader); } @@ -568,7 +568,7 @@ function material(p5, fn){ if (failureCallback) { failureCallback(err); } else { - console.error(err); + console.error(err); } } }; @@ -663,8 +663,8 @@ function material(p5, fn){ * * */ - fn.createFilterShader = function (fragSrc) { - // p5._validateParameters('createFilterShader', arguments); + fn.createFilterShader = function (fragSrc, skipContextCheck = false) { + p5._validateParameters('createFilterShader', arguments); let defaultVertV1 = ` uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; @@ -899,7 +899,7 @@ function material(p5, fn){ */ fn.shader = function (s) { this._assert3d('shader'); - // p5._validateParameters('shader', arguments); + p5._validateParameters('shader', arguments); this._renderer.shader(s); @@ -1072,7 +1072,7 @@ function material(p5, fn){ */ fn.strokeShader = function (s) { this._assert3d('strokeShader'); - // p5._validateParameters('strokeShader', arguments); + p5._validateParameters('strokeShader', arguments); this._renderer.strokeShader(s); @@ -1229,7 +1229,7 @@ function material(p5, fn){ */ fn.imageShader = function (s) { this._assert3d('imageShader'); - // p5._validateParameters('imageShader', arguments); + p5._validateParameters('imageShader', arguments); this._renderer.imageShader(s); @@ -2334,7 +2334,7 @@ function material(p5, fn){ */ fn.texture = function (tex) { this._assert3d('texture'); - // p5._validateParameters('texture', arguments); + p5._validateParameters('texture', arguments); // NOTE: make generic or remove need for if (tex.gifProperties) { @@ -2848,7 +2848,7 @@ function material(p5, fn){ */ fn.normalMaterial = function (...args) { this._assert3d('normalMaterial'); - // p5._validateParameters('normalMaterial', args); + p5._validateParameters('normalMaterial', args); this._renderer.normalMaterial(...args); @@ -3075,7 +3075,7 @@ function material(p5, fn){ */ fn.ambientMaterial = function (v1, v2, v3) { this._assert3d('ambientMaterial'); - // p5._validateParameters('ambientMaterial', arguments); + p5._validateParameters('ambientMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states._hasSetAmbient = true; @@ -3171,7 +3171,7 @@ function material(p5, fn){ */ fn.emissiveMaterial = function (v1, v2, v3, a) { this._assert3d('emissiveMaterial'); - // p5._validateParameters('emissiveMaterial', arguments); + p5._validateParameters('emissiveMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states.curEmissiveColor = color._array; @@ -3426,7 +3426,7 @@ function material(p5, fn){ */ fn.specularMaterial = function (v1, v2, v3, alpha) { this._assert3d('specularMaterial'); - // p5._validateParameters('specularMaterial', arguments); + p5._validateParameters('specularMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states.curSpecularColor = color._array; @@ -3499,7 +3499,7 @@ function material(p5, fn){ */ fn.shininess = function (shine) { this._assert3d('shininess'); - // p5._validateParameters('shininess', arguments); + p5._validateParameters('shininess', arguments); this._renderer.shininess(shine); diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js index f87628b253..c85d14f335 100644 --- a/src/webgl/p5.Camera.js +++ b/src/webgl/p5.Camera.js @@ -3182,7 +3182,7 @@ function camera(p5, fn){ */ fn.camera = function (...args) { this._assert3d('camera'); - // p5._validateParameters('camera', args); + p5._validateParameters('camera', args); this._renderer.camera(...args); return this; }; @@ -3313,7 +3313,7 @@ function camera(p5, fn){ */ fn.perspective = function (...args) { this._assert3d('perspective'); - // p5._validateParameters('perspective', args); + p5._validateParameters('perspective', args); this._renderer.perspective(...args); return this; }; @@ -3437,7 +3437,7 @@ function camera(p5, fn){ */ fn.linePerspective = function (enable) { - // p5._validateParameters('linePerspective', arguments); + p5._validateParameters('linePerspective', arguments); if (!(this._renderer instanceof RendererGL)) { throw new Error('linePerspective() must be called in WebGL mode.'); } @@ -3550,7 +3550,7 @@ function camera(p5, fn){ */ fn.ortho = function (...args) { this._assert3d('ortho'); - // p5._validateParameters('ortho', args); + p5._validateParameters('ortho', args); this._renderer.ortho(...args); return this; }; @@ -3662,7 +3662,7 @@ function camera(p5, fn){ */ fn.frustum = function (...args) { this._assert3d('frustum'); - // p5._validateParameters('frustum', args); + p5._validateParameters('frustum', args); this._renderer.frustum(...args); return this; }; From 8aadc26dc7da7646ee57fecddfb2e25985103b79 Mon Sep 17 00:00:00 2001 From: dhowe Date: Sun, 29 Dec 2024 12:00:27 -0500 Subject: [PATCH 13/27] refix to font name extraction, regenerate one screenshot --- src/type/p5.Font.js | 11 ++++++++--- test/unit/visual/cases/typography.js | 2 -- .../000.png | Bin 2466 -> 2766 bytes 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/type/p5.Font.js b/src/type/p5.Font.js index f5f5b0bb16..ffd984b829 100644 --- a/src/type/p5.Font.js +++ b/src/type/p5.Font.js @@ -526,6 +526,7 @@ function font(p5, fn) { * @param {...any} args - path, name, onSuccess, onError, descriptors * @returns a Promise that resolves with a p5.Font instance */ + p5.prototype.loadFont = async function (...args/*path, name, onSuccess, onError, descriptors*/) { let { path, name, success, error, descriptors } = parseCreateArgs(...args); @@ -572,7 +573,7 @@ function font(p5, fn) { // load the raw font bytes let result = await fn.loadBytes(path); //console.log('result:', result); - + if (!result) { throw Error('Failed to load font data'); } @@ -597,11 +598,15 @@ function font(p5, fn) { } catch (err) { // failed to parse the font, load it as a simple FontFace - let ident = name || path.substring(path.lastIndexOf('/') + 1); + let ident = name || path + .substring(path.lastIndexOf('/') + 1) + .replace(/\.[^/.]+$/, ""); + console.warn(`WARN: No glyph data for '${ident}', retrying as FontFace`); + try { // create a FontFace object and pass it to p5.Font - pfont = await create(this, name, path, descriptors); + pfont = await create(this, ident, path, descriptors); } catch (err) { if (error) error(err); diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index e112dd3161..0398c16c25 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -118,8 +118,6 @@ visualSuite("Typography", function () { for (let weight = 400; weight <= 800; weight += 100) { p5.background(255); p5.textFont(font); - console.log(p5.textProperties()); - p5.textAlign(p5.LEFT, p5.TOP); p5.textSize(35); p5.textWeight(weight); diff --git a/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/000.png b/test/unit/visual/screenshots/Typography/textWeight/can control variable fonts from files/000.png index cc1cea177c68869986b5b08e8cb40967ecab7861..a0a4df342877a72b1bf18e925028eedcbe19bdfa 100644 GIT binary patch literal 2766 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 Uwsqkyt8@XdhUS Date: Sun, 29 Dec 2024 12:03:19 -0500 Subject: [PATCH 14/27] refix to circular ref in textProperties --- src/type/text2d.js | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/type/text2d.js b/src/type/text2d.js index 8d055357d4..c94032e2b6 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -442,6 +442,10 @@ function text2d(p5, fn) { return modified ? this._applyTextProperties() : this._pInst; }; + /** + * Batch set/get text properties for the renderer. + * The properties can be either on `states` or `drawingContext` + */ /** * Batch set/get text properties for the renderer. * The properties can be either on `states` or `drawingContext` @@ -456,17 +460,27 @@ function text2d(p5, fn) { return this._pInst; } - // getter: get props from this.textDrawingContext() + // getter: get props from drawingContext + let context = this.textDrawingContext(); properties = ContextTextProps.reduce((props, p) => { - props[p] = this.textDrawingContext()[p]; + props[p] = context[p]; return props; }, {}); - // add renderer.states props + // add renderer props Object.keys(RendererTextProps).forEach(p => { - properties[p] = this.states[p]; if (RendererTextProps[p]?.type === 'Context2d') { - properties[p] = this.textDrawingContext()[p]; + properties[p] = context[p]; + } + else { // a renderer.states property + if (p === 'textFont') { + // avoid circular ref. inside textFont + properties[p] = Object.assign({}, this._currentTextFont()); + delete properties[p]._pInst; + } + else { + properties[p] = this.states[p]; + } } }); From d49cab829f66843e088c5b78748b199cc1075aaa Mon Sep 17 00:00:00 2001 From: dhowe Date: Sun, 29 Dec 2024 13:10:18 -0500 Subject: [PATCH 15/27] handle non-object fonts in textProperties --- src/type/text2d.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/type/text2d.js b/src/type/text2d.js index c94032e2b6..d2847d78a9 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -475,8 +475,12 @@ function text2d(p5, fn) { else { // a renderer.states property if (p === 'textFont') { // avoid circular ref. inside textFont - properties[p] = Object.assign({}, this._currentTextFont()); - delete properties[p]._pInst; + let current = this._currentTextFont(); + if (typeof current === 'object' && '_pInst' in current) { + current = Object.assign({}, current); + delete current._pInst; + } + properties[p] = current; } else { properties[p] = this.states[p]; From 2680f800213c872d5b9585ae7d77381d677c6652 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 9 Jan 2025 16:10:10 -0500 Subject: [PATCH 16/27] Revert "revert merge with parameter validation issues" This reverts commit 9ba2d64c8f8cc9661e27966d665e5b21a39e41eb. --- docs/parameterData.json | 2 +- src/accessibility/describe.js | 4 +- src/accessibility/outputs.js | 4 +- src/app.js | 14 +- src/color/creating_reading.js | 20 +- src/color/p5.Color.js | 4 +- src/color/setting.js | 4 +- src/core/constants.js | 6 +- src/core/environment.js | 6 +- src/core/friendly_errors/fes_core.js | 1991 ++++++++++--------- src/core/friendly_errors/file_errors.js | 12 +- src/core/friendly_errors/index.js | 8 +- src/core/friendly_errors/param_validator.js | 41 +- src/core/friendly_errors/stacktrace.js | 17 +- src/core/init.js | 8 +- src/core/rendering.js | 8 +- src/core/transform.js | 16 +- src/data/p5.TypedDict.js | 4 +- src/dom/dom.js | 26 +- src/dom/p5.MediaElement.js | 6 +- src/events/acceleration.js | 4 +- src/events/keyboard.js | 2 +- src/image/image.js | 6 +- src/image/loading_displaying.js | 8 +- src/image/pixels.js | 12 +- src/io/files.js | 14 +- src/math/calculation.js | 14 +- src/math/random.js | 2 +- src/math/trigonometry.js | 2 +- src/shape/2d_primitives.js | 19 +- src/shape/attributes.js | 10 +- src/shape/curves.js | 16 +- src/shape/vertex.js | 10 +- src/type/text2d.js | 2 - src/utilities/string_functions.js | 20 +- src/webgl/3d_primitives.js | 14 +- src/webgl/interaction.js | 4 +- src/webgl/light.js | 14 +- src/webgl/loading.js | 4 +- src/webgl/material.js | 32 +- src/webgl/p5.Camera.js | 10 +- 41 files changed, 1229 insertions(+), 1191 deletions(-) diff --git a/docs/parameterData.json b/docs/parameterData.json index 545de2f5a7..b9fbd6670e 100644 --- a/docs/parameterData.json +++ b/docs/parameterData.json @@ -374,7 +374,7 @@ [ "Number?", "Number?", - "P2D|WEBGL?", + "String?", "HTMLCanvasElement?" ], [ diff --git a/src/accessibility/describe.js b/src/accessibility/describe.js index 5173a101de..de28a74f01 100644 --- a/src/accessibility/describe.js +++ b/src/accessibility/describe.js @@ -118,7 +118,7 @@ function describe(p5, fn){ */ fn.describe = function(text, display) { - p5._validateParameters('describe', arguments); + // p5._validateParameters('describe', arguments); if (typeof text !== 'string') { return; } @@ -244,7 +244,7 @@ function describe(p5, fn){ */ fn.describeElement = function(name, text, display) { - p5._validateParameters('describeElement', arguments); + // p5._validateParameters('describeElement', arguments); if (typeof text !== 'string' || typeof name !== 'string') { return; } diff --git a/src/accessibility/outputs.js b/src/accessibility/outputs.js index 97b38712f4..68ab322a5a 100644 --- a/src/accessibility/outputs.js +++ b/src/accessibility/outputs.js @@ -122,7 +122,7 @@ function outputs(p5, fn){ */ fn.textOutput = function(display) { - p5._validateParameters('textOutput', arguments); + // p5._validateParameters('textOutput', arguments); //if textOutput is already true if (this._accessibleOutputs.text) { return; @@ -257,7 +257,7 @@ function outputs(p5, fn){ */ fn.gridOutput = function(display) { - p5._validateParameters('gridOutput', arguments); + // p5._validateParameters('gridOutput', arguments); //if gridOutput is already true if (this._accessibleOutputs.grid) { return; diff --git a/src/app.js b/src/app.js index 9de84f07f2..8b5579f252 100644 --- a/src/app.js +++ b/src/app.js @@ -1,10 +1,10 @@ // core import p5 from './core/main'; -import './core/friendly_errors/stacktrace'; -import './core/friendly_errors/validate_params'; -import './core/friendly_errors/file_errors'; -import './core/friendly_errors/fes_core'; -import './core/friendly_errors/sketch_reader'; +// import './core/friendly_errors/stacktrace'; +// import './core/friendly_errors/validate_params'; +// import './core/friendly_errors/file_errors'; +// import './core/friendly_errors/fes_core'; +// import './core/friendly_errors/sketch_reader'; import shape from './shape'; shape(p5); @@ -61,6 +61,8 @@ webgl(p5); import type from './type' type(p5); -import './core/init'; +import { waitForDocumentReady, waitingForTranslator, _globalInit } from './core/init'; +Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); export default p5; + diff --git a/src/color/creating_reading.js b/src/color/creating_reading.js index 976aba3176..9396c0f0a9 100644 --- a/src/color/creating_reading.js +++ b/src/color/creating_reading.js @@ -349,7 +349,7 @@ function creatingReading(p5, fn){ * @return {p5.Color} */ fn.color = function(...args) { - p5._validateParameters('color', args); + // p5._validateParameters('color', args); if (args[0] instanceof Color) { // TODO: perhaps change color mode to match instance mode? return args[0]; // Do nothing if argument is already a color object. @@ -495,7 +495,7 @@ function creatingReading(p5, fn){ * */ fn.red = function(c) { - p5._validateParameters('red', arguments); + // p5._validateParameters('red', arguments); // Get current red max return this.color(c)._getRed(); }; @@ -632,7 +632,7 @@ function creatingReading(p5, fn){ * */ fn.green = function(c) { - p5._validateParameters('green', arguments); + // p5._validateParameters('green', arguments); // Get current green max return this.color(c)._getGreen(); }; @@ -769,7 +769,7 @@ function creatingReading(p5, fn){ * */ fn.blue = function(c) { - p5._validateParameters('blue', arguments); + // p5._validateParameters('blue', arguments); // Get current blue max return this.color(c)._getBlue(); }; @@ -871,7 +871,7 @@ function creatingReading(p5, fn){ * */ fn.alpha = function(c) { - p5._validateParameters('alpha', arguments); + // p5._validateParameters('alpha', arguments); // Get current alpha max return this.color(c)._getAlpha(); }; @@ -993,7 +993,7 @@ function creatingReading(p5, fn){ * */ fn.hue = function(c) { - p5._validateParameters('hue', arguments); + // p5._validateParameters('hue', arguments); return this.color(c)._getHue(); }; @@ -1170,7 +1170,7 @@ function creatingReading(p5, fn){ * */ fn.saturation = function(c) { - p5._validateParameters('saturation', arguments); + // p5._validateParameters('saturation', arguments); return this.color(c)._getSaturation(); }; @@ -1315,7 +1315,7 @@ function creatingReading(p5, fn){ * */ fn.brightness = function(c) { - p5._validateParameters('brightness', arguments); + // p5._validateParameters('brightness', arguments); return this.color(c)._getBrightness(); }; @@ -1460,7 +1460,7 @@ function creatingReading(p5, fn){ * */ fn.lightness = function(c) { - p5._validateParameters('lightness', arguments); + // p5._validateParameters('lightness', arguments); return this.color(c)._getLightness(); }; @@ -1524,7 +1524,7 @@ function creatingReading(p5, fn){ * */ fn.lerpColor = function(c1, c2, amt) { - p5._validateParameters('lerpColor', arguments); + // p5._validateParameters('lerpColor', arguments); return c1.lerp(c2, amt, this._renderer.states.colorMode); }; } diff --git a/src/color/p5.Color.js b/src/color/p5.Color.js index 0df96a4abd..b3f0fe13d9 100644 --- a/src/color/p5.Color.js +++ b/src/color/p5.Color.js @@ -89,7 +89,7 @@ class Color { this._color = to(this._color, this._color.spaceId); }catch(err){ // TODO: Invalid color string - console.error('Invalid color string'); + throw new Error('Invalid color string'); } }else{ @@ -107,6 +107,8 @@ class Color { }else if(vals.length === 1){ mappedVals = Color.mapColorRange([vals[0], vals[0], vals[0]], this.mode, colorMaxes); mappedVals.push(1); + }else{ + throw new Error('Invalid color'); } }else{ mappedVals = vals; diff --git a/src/color/setting.js b/src/color/setting.js index 05f8f684ba..77c31cf25f 100644 --- a/src/color/setting.js +++ b/src/color/setting.js @@ -949,7 +949,7 @@ function setting(p5, fn){ * @return {String} The current color mode. */ fn.colorMode = function(mode, max1, max2, max3, maxA) { - p5._validateParameters('colorMode', arguments); + // p5._validateParameters('colorMode', arguments); if ( [ RGB, @@ -2184,7 +2184,7 @@ function setting(p5, fn){ * */ fn.blendMode = function (mode) { - p5._validateParameters('blendMode', arguments); + // p5._validateParameters('blendMode', arguments); if (mode === constants.NORMAL) { // Warning added 3/26/19, can be deleted in future (1.0 release?) console.warn( diff --git a/src/core/constants.js b/src/core/constants.js index ff9c873433..0885ab3e48 100644 --- a/src/core/constants.js +++ b/src/core/constants.js @@ -20,7 +20,7 @@ export const VERSION = 'VERSION_WILL_BE_REPLACED_BY_BUILD'; * @property {P2D} P2D * @final */ -export const P2D = Symbol('p2d'); +export const P2D = 'p2d'; export const P2DHDR = 'p2d-hdr'; @@ -45,7 +45,7 @@ export const P2DHDR = 'p2d-hdr'; * @property {WEBGL} WEBGL * @final */ -export const WEBGL = Symbol('webgl'); +export const WEBGL = 'webgl'; /** * One of the two possible values of a WebGL canvas (either WEBGL or WEBGL2), * which can be used to determine what capabilities the rendering environment @@ -54,7 +54,7 @@ export const WEBGL = Symbol('webgl'); * @property {WEBGL2} WEBGL2 * @final */ -export const WEBGL2 = Symbol('webgl2'); +export const WEBGL2 = 'webgl2'; // ENVIRONMENT /** diff --git a/src/core/environment.js b/src/core/environment.js index fa35c8f7de..1cdb735644 100644 --- a/src/core/environment.js +++ b/src/core/environment.js @@ -407,7 +407,7 @@ function environment(p5, fn){ * @return {Number} current frame rate. */ fn.frameRate = function(fps) { - p5._validateParameters('frameRate', arguments); + // p5._validateParameters('frameRate', arguments); if (typeof fps !== 'number' || fps < 0) { return this._frameRate; } else { @@ -992,7 +992,7 @@ function environment(p5, fn){ * */ fn.fullscreen = function(val) { - p5._validateParameters('fullscreen', arguments); + // p5._validateParameters('fullscreen', arguments); // no arguments, return fullscreen or not if (typeof val === 'undefined') { return ( @@ -1070,7 +1070,7 @@ function environment(p5, fn){ * @returns {Number} current pixel density of the sketch. */ fn.pixelDensity = function(val) { - p5._validateParameters('pixelDensity', arguments); + // p5._validateParameters('pixelDensity', arguments); let returnValue; if (typeof val === 'number') { if (val !== this._renderer._pixelDensity) { diff --git a/src/core/friendly_errors/fes_core.js b/src/core/friendly_errors/fes_core.js index 25df52d5f3..00ffa5ed66 100644 --- a/src/core/friendly_errors/fes_core.js +++ b/src/core/friendly_errors/fes_core.js @@ -22,1083 +22,1088 @@ * sequence of each function, please look at the FES Reference + Dev Notes: * https://github.com/processing/p5.js/blob/main/contributor_docs/fes_reference_dev_notes.md */ -import p5 from '../main'; import { translator } from '../internationalization'; import errorTable from './browser_errors'; import * as contants from '../constants'; -// p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta -// See testColors below for all the color codes and names -const typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; -let misusedAtTopLevelCode = null; -let defineMisusedAtTopLevelCode = null; - -// the threshold for the maximum allowed levenshtein distance -// used in misspelling detection -const EDIT_DIST_THRESHOLD = 2; - -// to enable or disable styling (color, font-size, etc. ) for fes messages -const ENABLE_FES_STYLING = false; - -if (typeof IS_MINIFIED !== 'undefined') { - p5._friendlyError = - p5._checkForUserDefinedFunctions = - p5._fesErrorMonitor = - () => {}; -} else { - let doFriendlyWelcome = false; // TEMP until we get it all working LM - - // const errorTable = require('./browser_errors').default; - - // -- Borrowed from jQuery 1.11.3 -- - const class2type = {}; - const toString = class2type.toString; - const names = [ - 'Boolean', - 'Number', - 'String', - 'Function', - 'Array', - 'Date', - 'RegExp', - 'Object', - 'Error' - ]; - for (let n = 0; n < names.length; n++) { - class2type[`[object ${names[n]}]`] = names[n].toLowerCase(); - } - const getType = obj => { - if (obj == null) { - return `${obj}`; - } - return typeof obj === 'object' || typeof obj === 'function' - ? class2type[toString.call(obj)] || 'object' - : typeof obj; - }; - - // -- End borrow -- - - // entry points into user-defined code - const entryPoints = [ - 'setup', - 'draw', - 'preload', - 'deviceMoved', - 'deviceTurned', - 'deviceShaken', - 'doubleClicked', - 'mousePressed', - 'mouseReleased', - 'mouseMoved', - 'mouseDragged', - 'mouseClicked', - 'mouseWheel', - 'touchStarted', - 'touchMoved', - 'touchEnded', - 'keyPressed', - 'keyReleased', - 'keyTyped', - 'windowResized' - ]; - - const friendlyWelcome = () => { - // p5.js brand - magenta: #ED225D - //const astrixBgColor = 'transparent'; - //const astrixTxtColor = '#ED225D'; - //const welcomeBgColor = '#ED225D'; - //const welcomeTextColor = 'white'; - const welcomeMessage = translator('fes.pre', { - message: translator('fes.welcome') - }); - console.log( - ' _ \n' + - ' /\\| |/\\ \n' + - " \\ ` ' / \n" + - ' / , . \\ \n' + - ' \\/|_|\\/ ' + - '\n\n' + - welcomeMessage - ); - }; - - /** - * Takes a message and a p5 function func, and adds a link pointing to - * the reference documentation of func at the end of the message - * - * @method mapToReference - * @private - * @param {String} message the words to be said - * @param {String} [func] the name of function - * - * @returns {String} - */ - const mapToReference = (message, func) => { - let msgWithReference = ''; - if (func == null || func.substring(0, 4) === 'load') { - msgWithReference = message; - } else { - const methodParts = func.split('.'); - const referenceSection = - methodParts.length > 1 ? `${methodParts[0]}.${methodParts[1]}` : 'p5'; - - const funcName = - methodParts.length === 1 ? func : methodParts.slice(2).join('/'); - - //Whenever func having p5.[Class] is encountered, we need to have the error link as mentioned below else different link - funcName.startsWith('p5.') ? - msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}.${funcName})` : - msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}/${funcName})`; - } - return msgWithReference; - }; - - /** - * Prints out a fancy, colorful message to the console log - * Attaches Friendly Errors prefix [fes.pre] to the message. - * - * @method _report - * @private - * @param {String} message Message to be printed - * @param {String} [func] Name of function - * @param {Number|String} [color] CSS color code - * - * @return console logs - */ - p5._report = (message, func, color) => { - // if p5._fesLogger is set ( i.e we are running tests ), use that - // instead of console.log - const log = - p5._fesLogger == null ? console.log.bind(console) : p5._fesLogger; - - if (doFriendlyWelcome) { - friendlyWelcome(); - doFriendlyWelcome = false; - } - if ('undefined' === getType(color)) { - color = '#B40033'; // dark magenta - } else if (getType(color) === 'number') { - // Type to color - color = typeColors[color]; +function fesCore(p5, fn){ + // p5.js blue, p5.js orange, auto dark green; fallback p5.js darkened magenta + // See testColors below for all the color codes and names + const typeColors = ['#2D7BB6', '#EE9900', '#4DB200', '#C83C00']; + let misusedAtTopLevelCode = null; + let defineMisusedAtTopLevelCode = null; + + // the threshold for the maximum allowed levenshtein distance + // used in misspelling detection + const EDIT_DIST_THRESHOLD = 2; + + // to enable or disable styling (color, font-size, etc. ) for fes messages + const ENABLE_FES_STYLING = false; + + if (typeof IS_MINIFIED !== 'undefined') { + p5._friendlyError = + p5._checkForUserDefinedFunctions = + p5._fesErrorMonitor = + () => {}; + } else { + let doFriendlyWelcome = false; // TEMP until we get it all working LM + + // const errorTable = require('./browser_errors').default; + + // -- Borrowed from jQuery 1.11.3 -- + const class2type = {}; + const toString = class2type.toString; + const names = [ + 'Boolean', + 'Number', + 'String', + 'Function', + 'Array', + 'Date', + 'RegExp', + 'Object', + 'Error' + ]; + for (let n = 0; n < names.length; n++) { + class2type[`[object ${names[n]}]`] = names[n].toLowerCase(); } + const getType = obj => { + if (obj == null) { + return `${obj}`; + } + return typeof obj === 'object' || typeof obj === 'function' + ? class2type[toString.call(obj)] || 'object' + : typeof obj; + }; + + // -- End borrow -- + + // entry points into user-defined code + const entryPoints = [ + 'setup', + 'draw', + 'preload', + 'deviceMoved', + 'deviceTurned', + 'deviceShaken', + 'doubleClicked', + 'mousePressed', + 'mouseReleased', + 'mouseMoved', + 'mouseDragged', + 'mouseClicked', + 'mouseWheel', + 'touchStarted', + 'touchMoved', + 'touchEnded', + 'keyPressed', + 'keyReleased', + 'keyTyped', + 'windowResized' + ]; + + const friendlyWelcome = () => { + // p5.js brand - magenta: #ED225D + //const astrixBgColor = 'transparent'; + //const astrixTxtColor = '#ED225D'; + //const welcomeBgColor = '#ED225D'; + //const welcomeTextColor = 'white'; + const welcomeMessage = translator('fes.pre', { + message: translator('fes.welcome') + }); + console.log( + ' _ \n' + + ' /\\| |/\\ \n' + + " \\ ` ' / \n" + + ' / , . \\ \n' + + ' \\/|_|\\/ ' + + '\n\n' + + welcomeMessage + ); + }; + + /** + * Takes a message and a p5 function func, and adds a link pointing to + * the reference documentation of func at the end of the message + * + * @method mapToReference + * @private + * @param {String} message the words to be said + * @param {String} [func] the name of function + * + * @returns {String} + */ + const mapToReference = (message, func) => { + let msgWithReference = ''; + if (func == null || func.substring(0, 4) === 'load') { + msgWithReference = message; + } else { + const methodParts = func.split('.'); + const referenceSection = + methodParts.length > 1 ? `${methodParts[0]}.${methodParts[1]}` : 'p5'; - // Add a link to the reference docs of func at the end of the message - message = mapToReference(message, func); - let style = [`color: ${color}`, 'font-family: Arial', 'font-size: larger']; - const prefixedMsg = translator('fes.pre', { message }); - - if (ENABLE_FES_STYLING) { - log('%c' + prefixedMsg, style.join(';')); - } else { - log(prefixedMsg); - } - }; - /** - * This is a generic method that can be called from anywhere in the p5 - * library to alert users to a common error. - * - * @method _friendlyError - * @private - * @param {String} message Message to be printed - * @param {String} [func] Name of the function linked to error - * @param {Number|String} [color] CSS color code - */ - p5._friendlyError = function(message, func, color) { - p5._report(message, func, color); - }; - - /** - * This is called internally if there is an error with autoplay. Generates - * and prints a friendly error message [fes.autoplay]. - * - * @method _friendlyAutoplayError - * @private - */ - p5._friendlyAutoplayError = function(src) { - const message = translator('fes.autoplay', { - src, - url: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' - }); - console.log(translator('fes.pre', { message })); - }; + const funcName = + methodParts.length === 1 ? func : methodParts.slice(2).join('/'); - /** - * Measures dissimilarity between two strings by calculating - * the Levenshtein distance. - * - * If the "distance" between them is small enough, it is - * reasonable to think that one is the misspelled version of the other. - * - * Specifically, this uses the Wagner–Fischer algorithm. - * @method computeEditDistance - * @private - * @param {String} w1 the first word - * @param {String} w2 the second word - * - * @returns {Number} the "distance" between the two words, a smaller value - * indicates that the words are similar - */ - const computeEditDistance = (w1, w2) => { - const l1 = w1.length, - l2 = w2.length; - if (l1 === 0) return w2; - if (l2 === 0) return w1; - - let prev = []; - let cur = []; + //Whenever func having p5.[Class] is encountered, we need to have the error link as mentioned below else different link + funcName.startsWith('p5.') ? + msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}.${funcName})` : + msgWithReference = `${message} (http://p5js.org/reference/#/${referenceSection}/${funcName})`; + } + return msgWithReference; + }; + + /** + * Prints out a fancy, colorful message to the console log + * Attaches Friendly Errors prefix [fes.pre] to the message. + * + * @method _report + * @private + * @param {String} message Message to be printed + * @param {String} [func] Name of function + * @param {Number|String} [color] CSS color code + * + * @return console logs + */ + p5._report = (message, func, color) => { + // if p5._fesLogger is set ( i.e we are running tests ), use that + // instead of console.log + const log = + p5._fesLogger == null ? console.log.bind(console) : p5._fesLogger; + + if (doFriendlyWelcome) { + friendlyWelcome(); + doFriendlyWelcome = false; + } + if ('undefined' === getType(color)) { + color = '#B40033'; // dark magenta + } else if (getType(color) === 'number') { + // Type to color + color = typeColors[color]; + } - for (let j = 0; j < l2 + 1; j++) { - cur[j] = j; - } + // Add a link to the reference docs of func at the end of the message + message = mapToReference(message, func); + let style = [`color: ${color}`, 'font-family: Arial', 'font-size: larger']; + const prefixedMsg = translator('fes.pre', { message }); - prev = cur; + if (ENABLE_FES_STYLING) { + log('%c' + prefixedMsg, style.join(';')); + } else { + log(prefixedMsg); + } + }; + /** + * This is a generic method that can be called from anywhere in the p5 + * library to alert users to a common error. + * + * @method _friendlyError + * @private + * @param {String} message Message to be printed + * @param {String} [func] Name of the function linked to error + * @param {Number|String} [color] CSS color code + */ + p5._friendlyError = function(message, func, color) { + p5._report(message, func, color); + }; + + /** + * This is called internally if there is an error with autoplay. Generates + * and prints a friendly error message [fes.autoplay]. + * + * @method _friendlyAutoplayError + * @private + */ + p5._friendlyAutoplayError = function(src) { + const message = translator('fes.autoplay', { + src, + url: 'https://developer.mozilla.org/docs/Web/Media/Autoplay_guide' + }); + console.log(translator('fes.pre', { message })); + }; + + /** + * Measures dissimilarity between two strings by calculating + * the Levenshtein distance. + * + * If the "distance" between them is small enough, it is + * reasonable to think that one is the misspelled version of the other. + * + * Specifically, this uses the Wagner–Fischer algorithm. + * @method computeEditDistance + * @private + * @param {String} w1 the first word + * @param {String} w2 the second word + * + * @returns {Number} the "distance" between the two words, a smaller value + * indicates that the words are similar + */ + const computeEditDistance = (w1, w2) => { + const l1 = w1.length, + l2 = w2.length; + if (l1 === 0) return w2; + if (l2 === 0) return w1; + + let prev = []; + let cur = []; - for (let i = 1; i < l1 + 1; i++) { - cur = []; for (let j = 0; j < l2 + 1; j++) { - if (j === 0) { - cur[j] = i; - } else { - let a1 = w1[i - 1], - a2 = w2[j - 1]; - let temp = 999999; - let cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; - temp = temp > cost + prev[j - 1] ? cost + prev[j - 1] : temp; - temp = temp > 1 + cur[j - 1] ? 1 + cur[j - 1] : temp; - temp = temp > 1 + prev[j] ? 1 + prev[j] : temp; - cur[j] = temp; - } + cur[j] = j; } - prev = cur; - } - return cur[l2]; - }; - - /** - * Checks capitalization for user defined functions. - * - * Generates and prints a friendly error message using key: - * "fes.checkUserDefinedFns". - * - * @method checkForUserDefinedFunctions - * @private - * @param {*} context Current default context. Set to window in - * "global mode" and to a p5 instance in "instance mode" - */ - const checkForUserDefinedFunctions = context => { - if (p5.disableFriendlyErrors) return; - - // if using instance mode, this function would be called with the current - // instance as context - const instanceMode = context instanceof p5; - context = instanceMode ? context : window; - const fnNames = entryPoints; - - const fxns = {}; - // lowercasename -> actualName mapping - fnNames.forEach(symbol => { - fxns[symbol.toLowerCase()] = symbol; - }); + prev = cur; - for (const prop of Object.keys(context)) { - const lowercase = prop.toLowerCase(); + for (let i = 1; i < l1 + 1; i++) { + cur = []; + for (let j = 0; j < l2 + 1; j++) { + if (j === 0) { + cur[j] = i; + } else { + let a1 = w1[i - 1], + a2 = w2[j - 1]; + let temp = 999999; + let cost = a1.toLowerCase() === a2.toLowerCase() ? 0 : 1; + temp = temp > cost + prev[j - 1] ? cost + prev[j - 1] : temp; + temp = temp > 1 + cur[j - 1] ? 1 + cur[j - 1] : temp; + temp = temp > 1 + prev[j] ? 1 + prev[j] : temp; + cur[j] = temp; + } + } + prev = cur; + } - // check if the lowercase property name has an entry in fxns, if the - // actual name with correct capitalization doesnt exist in context, - // and if the user-defined symbol is of the type function - if ( - fxns[lowercase] && - !context[fxns[lowercase]] && - typeof context[prop] === 'function' - ) { - const msg = translator('fes.checkUserDefinedFns', { - name: prop, - actualName: fxns[lowercase] - }); + return cur[l2]; + }; + + /** + * Checks capitalization for user defined functions. + * + * Generates and prints a friendly error message using key: + * "fes.checkUserDefinedFns". + * + * @method checkForUserDefinedFunctions + * @private + * @param {*} context Current default context. Set to window in + * "global mode" and to a p5 instance in "instance mode" + */ + const checkForUserDefinedFunctions = context => { + if (p5.disableFriendlyErrors) return; + + // if using instance mode, this function would be called with the current + // instance as context + const instanceMode = context instanceof p5; + context = instanceMode ? context : window; + const fnNames = entryPoints; + + const fxns = {}; + // lowercasename -> actualName mapping + fnNames.forEach(symbol => { + fxns[symbol.toLowerCase()] = symbol; + }); - p5._friendlyError(msg, fxns[lowercase]); + for (const prop of Object.keys(context)) { + const lowercase = prop.toLowerCase(); + + // check if the lowercase property name has an entry in fxns, if the + // actual name with correct capitalization doesnt exist in context, + // and if the user-defined symbol is of the type function + if ( + fxns[lowercase] && + !context[fxns[lowercase]] && + typeof context[prop] === 'function' + ) { + const msg = translator('fes.checkUserDefinedFns', { + name: prop, + actualName: fxns[lowercase] + }); + + p5._friendlyError(msg, fxns[lowercase]); + } + } + }; + + /** + * Compares the symbol caught in the ReferenceError to everything in + * misusedAtTopLevel ( all public p5 properties ). + * + * Generates and prints a friendly error message using key: "fes.misspelling". + * + * @method handleMisspelling + * @private + * @param {String} errSym Symbol to whose spelling to check + * @param {Error} error ReferenceError object + * + * @returns {Boolean} tell whether error was likely due to typo + */ + const handleMisspelling = (errSym, error) => { + if (!misusedAtTopLevelCode) { + defineMisusedAtTopLevelCode(); } - } - }; - /** - * Compares the symbol caught in the ReferenceError to everything in - * misusedAtTopLevel ( all public p5 properties ). - * - * Generates and prints a friendly error message using key: "fes.misspelling". - * - * @method handleMisspelling - * @private - * @param {String} errSym Symbol to whose spelling to check - * @param {Error} error ReferenceError object - * - * @returns {Boolean} tell whether error was likely due to typo - */ - const handleMisspelling = (errSym, error) => { - if (!misusedAtTopLevelCode) { - defineMisusedAtTopLevelCode(); - } + const distanceMap = {}; + let min = 999999; + // compute the levenshtein distance for the symbol against all known + // public p5 properties. Find the property with the minimum distance + misusedAtTopLevelCode.forEach(symbol => { + let dist = computeEditDistance(errSym, symbol.name); + if (distanceMap[dist]) distanceMap[dist].push(symbol); + else distanceMap[dist] = [symbol]; - const distanceMap = {}; - let min = 999999; - // compute the levenshtein distance for the symbol against all known - // public p5 properties. Find the property with the minimum distance - misusedAtTopLevelCode.forEach(symbol => { - let dist = computeEditDistance(errSym, symbol.name); - if (distanceMap[dist]) distanceMap[dist].push(symbol); - else distanceMap[dist] = [symbol]; + if (dist < min) min = dist; + }); - if (dist < min) min = dist; - }); + // if the closest match has more "distance" than the max allowed threshold + if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; - // if the closest match has more "distance" than the max allowed threshold - if (min > Math.min(EDIT_DIST_THRESHOLD, errSym.length)) return false; + // Show a message only if the caught symbol and the matched property name + // differ in their name ( either letter difference or difference of case ) + const matchedSymbols = distanceMap[min].filter( + symbol => symbol.name !== errSym + ); + if (matchedSymbols.length !== 0) { + const parsed = p5._getErrorStackParser().parse(error); + let locationObj; + if ( + parsed && + parsed[0] && + parsed[0].fileName && + parsed[0].lineNumber && + parsed[0].columnNumber + ) { + locationObj = { + location: `${parsed[0].fileName}:${parsed[0].lineNumber}:${ + parsed[0].columnNumber + }`, + file: parsed[0].fileName.split('/').slice(-1), + line: parsed[0].lineNumber + }; + } - // Show a message only if the caught symbol and the matched property name - // differ in their name ( either letter difference or difference of case ) - const matchedSymbols = distanceMap[min].filter( - symbol => symbol.name !== errSym - ); - if (matchedSymbols.length !== 0) { - const parsed = p5._getErrorStackParser().parse(error); - let locationObj; - if ( - parsed && - parsed[0] && - parsed[0].fileName && - parsed[0].lineNumber && - parsed[0].columnNumber - ) { - locationObj = { - location: `${parsed[0].fileName}:${parsed[0].lineNumber}:${ - parsed[0].columnNumber - }`, - file: parsed[0].fileName.split('/').slice(-1), - line: parsed[0].lineNumber - }; - } + let msg; + if (matchedSymbols.length === 1) { + // To be used when there is only one closest match. The count parameter + // allows i18n to pick between the keys "fes.misspelling" and + // "fes.misspelling_plural" + msg = translator('fes.misspelling', { + name: errSym, + actualName: matchedSymbols[0].name, + type: matchedSymbols[0].type, + location: locationObj ? translator('fes.location', locationObj) : '', + count: matchedSymbols.length + }); + } else { + // To be used when there are multiple closest matches. Gives each + // suggestion on its own line, the function name followed by a link to + // reference documentation + const suggestions = matchedSymbols + .map(symbol => { + const message = + '▶️ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); + return mapToReference(message, symbol.name); + }) + .join('\n'); + + msg = translator('fes.misspelling', { + name: errSym, + suggestions, + location: locationObj ? translator('fes.location', locationObj) : '', + count: matchedSymbols.length + }); + } - let msg; - if (matchedSymbols.length === 1) { - // To be used when there is only one closest match. The count parameter - // allows i18n to pick between the keys "fes.misspelling" and - // "fes.misspelling_plural" - msg = translator('fes.misspelling', { - name: errSym, - actualName: matchedSymbols[0].name, - type: matchedSymbols[0].type, - location: locationObj ? translator('fes.location', locationObj) : '', - count: matchedSymbols.length + // If there is only one closest match, tell _friendlyError to also add + // a link to the reference documentation. In case of multiple matches, + // this is already done in the suggestions variable, one link for each + // suggestion. + p5._friendlyError( + msg, + matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined + ); + return true; + } + return false; + }; + + /** + * Prints a friendly stacktrace for user-written functions for "global" errors + * + * Generates and prints a friendly error message using key: + * "fes.globalErrors.stackTop", "fes.globalErrors.stackSubseq". + * + * @method printFriendlyStack + * @private + * @param {Array} friendlyStack + */ + const printFriendlyStack = friendlyStack => { + const log = + p5._fesLogger && typeof p5._fesLogger === 'function' + ? p5._fesLogger + : console.log.bind(console); + if (friendlyStack.length > 1) { + let stacktraceMsg = ''; + friendlyStack.forEach((frame, idx) => { + const location = `${frame.fileName}:${frame.lineNumber}:${ + frame.columnNumber + }`; + let frameMsg, + translationObj = { + func: frame.functionName, + line: frame.lineNumber, + location, + file: frame.fileName.split('/').slice(-1) + }; + if (idx === 0) { + frameMsg = translator('fes.globalErrors.stackTop', translationObj); + } else { + frameMsg = translator('fes.globalErrors.stackSubseq', translationObj); + } + stacktraceMsg += frameMsg; }); - } else { - // To be used when there are multiple closest matches. Gives each - // suggestion on its own line, the function name followed by a link to - // reference documentation - const suggestions = matchedSymbols - .map(symbol => { - const message = - '▶️ ' + symbol.name + (symbol.type === 'function' ? '()' : ''); - return mapToReference(message, symbol.name); - }) - .join('\n'); + log(stacktraceMsg); + } + }; + + /** + * Takes a stacktrace array and filters out all frames that show internal p5 + * details. + * + * Generates and prints a friendly error message using key: + * "fes.wrongPreload", "fes.libraryError". + * + * The processed stack is used to find whether the error happened internally + * within the library, and if the error was due to a non-loadX() method + * being used in preload. + * + * "Internally" here means that the exact location of the error (the top of + * the stack) is a piece of code written in the p5.js library (which may or + * may not have been called from the user's sketch). + * + * @method processStack + * @private + * @param {Error} error + * @param {Array} stacktrace + * + * @returns {Array} An array with two elements, [isInternal, friendlyStack] + * isInternal: a boolean value indicating whether the error + * happened internally + * friendlyStack: the filtered (simplified) stacktrace + */ + const processStack = (error, stacktrace) => { + // cannot process a stacktrace that doesn't exist + if (!stacktrace) return [false, null]; + + stacktrace.forEach(frame => { + frame.functionName = frame.functionName || ''; + }); - msg = translator('fes.misspelling', { - name: errSym, - suggestions, - location: locationObj ? translator('fes.location', locationObj) : '', - count: matchedSymbols.length - }); + // isInternal - Did this error happen inside the library + let isInternal = false; + let p5FileName, friendlyStack, currentEntryPoint; + + // Intentionally throw an error that we catch so that we can check the name + // of the current file. Any errors we see from this file, we treat as + // internal errors. + try { + throw new Error(); + } catch (testError) { + const testStacktrace = p5._getErrorStackParser().parse(testError); + p5FileName = testStacktrace[0].fileName; } - // If there is only one closest match, tell _friendlyError to also add - // a link to the reference documentation. In case of multiple matches, - // this is already done in the suggestions variable, one link for each - // suggestion. - p5._friendlyError( - msg, - matchedSymbols.length === 1 ? matchedSymbols[0].name : undefined - ); - return true; - } - return false; - }; + for (let i = stacktrace.length - 1; i >= 0; i--) { + let splitted = stacktrace[i].functionName.split('.'); + if (entryPoints.includes(splitted[splitted.length - 1])) { + // remove everything below an entry point function (setup, draw, etc). + // (it's usually the internal initialization calls) + friendlyStack = stacktrace.slice(0, i + 1); + currentEntryPoint = splitted[splitted.length - 1]; + // We call the error "internal" if the source of the error was a + // function from within the p5.js library file, but called from the + // user's code directly. We only need to check the topmost frame in + // the stack trace since any function internal to p5 should pass this + // check, not just public p5 functions. + if (stacktrace[0].fileName === p5FileName) { + isInternal = true; + break; + } + break; + } + } - /** - * Prints a friendly stacktrace for user-written functions for "global" errors - * - * Generates and prints a friendly error message using key: - * "fes.globalErrors.stackTop", "fes.globalErrors.stackSubseq". - * - * @method printFriendlyStack - * @private - * @param {Array} friendlyStack - */ - const printFriendlyStack = friendlyStack => { - const log = - p5._fesLogger && typeof p5._fesLogger === 'function' - ? p5._fesLogger - : console.log.bind(console); - if (friendlyStack.length > 1) { - let stacktraceMsg = ''; - friendlyStack.forEach((frame, idx) => { - const location = `${frame.fileName}:${frame.lineNumber}:${ - frame.columnNumber - }`; - let frameMsg, - translationObj = { - func: frame.functionName, - line: frame.lineNumber, - location, - file: frame.fileName.split('/').slice(-1) + // in some cases ( errors in promises, callbacks, etc), no entry-point + // function may be found in the stacktrace. In that case just use the + // entire stacktrace for friendlyStack + if (!friendlyStack) friendlyStack = stacktrace; + + if (isInternal) { + // the frameIndex property is added before the filter, so frameIndex + // corresponds to the index of a frame in the original stacktrace. + // Then we filter out all frames which belong to the file that contains + // the p5 library + friendlyStack = friendlyStack + .map((frame, index) => { + frame.frameIndex = index; + return frame; + }) + .filter(frame => frame.fileName !== p5FileName); + + // a weird case, if for some reason we can't identify the function called + // from user's code + if (friendlyStack.length === 0) return [true, null]; + + // get the function just above the topmost frame in the friendlyStack. + // i.e the name of the library function called from user's code + const func = stacktrace[friendlyStack[0].frameIndex - 2].functionName + .split('.') + .slice(-1)[0]; + + // Try and get the location (line no.) from the top element of the stack + let locationObj; + if ( + friendlyStack[0].fileName && + friendlyStack[0].lineNumber && + friendlyStack[0].columnNumber + ) { + locationObj = { + location: `${friendlyStack[0].fileName}:${ + friendlyStack[0].lineNumber + }:${friendlyStack[0].columnNumber}`, + file: friendlyStack[0].fileName.split('/').slice(-1), + line: friendlyStack[0].lineNumber }; - if (idx === 0) { - frameMsg = translator('fes.globalErrors.stackTop', translationObj); + + // if already handled by another part of the FES, don't handle again + if (p5._fesLogCache[locationObj.location]) return [true, null]; + } + + // Check if the error is due to a non loadX method being used incorrectly + // in preload + if ( + currentEntryPoint === 'preload' && + fn._preloadMethods[func] == null + ) { + p5._friendlyError( + translator('fes.wrongPreload', { + func, + location: locationObj + ? translator('fes.location', locationObj) + : '', + error: error.message + }), + 'preload' + ); } else { - frameMsg = translator('fes.globalErrors.stackSubseq', translationObj); + // Library error + p5._friendlyError( + translator('fes.libraryError', { + func, + location: locationObj + ? translator('fes.location', locationObj) + : '', + error: error.message + }), + func + ); } - stacktraceMsg += frameMsg; - }); - log(stacktraceMsg); - } - }; - /** - * Takes a stacktrace array and filters out all frames that show internal p5 - * details. - * - * Generates and prints a friendly error message using key: - * "fes.wrongPreload", "fes.libraryError". - * - * The processed stack is used to find whether the error happened internally - * within the library, and if the error was due to a non-loadX() method - * being used in preload. - * - * "Internally" here means that the exact location of the error (the top of - * the stack) is a piece of code written in the p5.js library (which may or - * may not have been called from the user's sketch). - * - * @method processStack - * @private - * @param {Error} error - * @param {Array} stacktrace - * - * @returns {Array} An array with two elements, [isInternal, friendlyStack] - * isInternal: a boolean value indicating whether the error - * happened internally - * friendlyStack: the filtered (simplified) stacktrace - */ - const processStack = (error, stacktrace) => { - // cannot process a stacktrace that doesn't exist - if (!stacktrace) return [false, null]; + // Finally, if it's an internal error, print the friendlyStack + // ( fesErrorMonitor won't handle this error ) + if (friendlyStack && friendlyStack.length) { + printFriendlyStack(friendlyStack); + } + } + return [isInternal, friendlyStack]; + }; + + /** + * Handles "global" errors that the browser catches. + * + * Called when an error event happens and detects the type of error. + * + * Generates and prints a friendly error message using key: + * "fes.globalErrors.syntax.[*]", "fes.globalErrors.reference.[*]", + * "fes.globalErrors.type.[*]". + * + * @method fesErrorMonitor + * @private + * @param {*} e Event object to extract error details from + */ + const fesErrorMonitor = e => { + if (p5.disableFriendlyErrors) return; + // Try to get the error object from e + let error; + if (e instanceof Error) { + error = e; + } else if (e instanceof ErrorEvent) { + error = e.error; + } else if (e instanceof PromiseRejectionEvent) { + error = e.reason; + if (!(error instanceof Error)) return; + } + if (!error) return; - stacktrace.forEach(frame => { - frame.functionName = frame.functionName || ''; - }); + let stacktrace = p5._getErrorStackParser().parse(error); + // process the stacktrace from the browser and simplify it to give + // friendlyStack. + let [isInternal, friendlyStack] = processStack(error, stacktrace); - // isInternal - Did this error happen inside the library - let isInternal = false; - let p5FileName, friendlyStack, currentEntryPoint; - - // Intentionally throw an error that we catch so that we can check the name - // of the current file. Any errors we see from this file, we treat as - // internal errors. - try { - throw new Error(); - } catch (testError) { - const testStacktrace = p5._getErrorStackParser().parse(testError); - p5FileName = testStacktrace[0].fileName; - } + // if this is an internal library error, the type of the error is not relevant, + // only the user code that lead to it is. + if (isInternal) { + return; + } - for (let i = stacktrace.length - 1; i >= 0; i--) { - let splitted = stacktrace[i].functionName.split('.'); - if (entryPoints.includes(splitted[splitted.length - 1])) { - // remove everything below an entry point function (setup, draw, etc). - // (it's usually the internal initialization calls) - friendlyStack = stacktrace.slice(0, i + 1); - currentEntryPoint = splitted[splitted.length - 1]; - // We call the error "internal" if the source of the error was a - // function from within the p5.js library file, but called from the - // user's code directly. We only need to check the topmost frame in - // the stack trace since any function internal to p5 should pass this - // check, not just public p5 functions. - if (stacktrace[0].fileName === p5FileName) { - isInternal = true; + const errList = errorTable[error.name]; + if (!errList) return; // this type of error can't be handled yet + let matchedError; + for (const obj of errList) { + let string = obj.msg; + // capture the primary symbol mentioned in the error + string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); + string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); + string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); + let matched = error.message.match(string); + + if (matched) { + matchedError = Object.assign({}, obj); + matchedError.match = matched; break; } - break; } - } - - // in some cases ( errors in promises, callbacks, etc), no entry-point - // function may be found in the stacktrace. In that case just use the - // entire stacktrace for friendlyStack - if (!friendlyStack) friendlyStack = stacktrace; - - if (isInternal) { - // the frameIndex property is added before the filter, so frameIndex - // corresponds to the index of a frame in the original stacktrace. - // Then we filter out all frames which belong to the file that contains - // the p5 library - friendlyStack = friendlyStack - .map((frame, index) => { - frame.frameIndex = index; - return frame; - }) - .filter(frame => frame.fileName !== p5FileName); - - // a weird case, if for some reason we can't identify the function called - // from user's code - if (friendlyStack.length === 0) return [true, null]; - // get the function just above the topmost frame in the friendlyStack. - // i.e the name of the library function called from user's code - const func = stacktrace[friendlyStack[0].frameIndex - 1].functionName - .split('.') - .slice(-1)[0]; + if (!matchedError) return; - // Try and get the location (line no.) from the top element of the stack + // Try and get the location from the top element of the stack let locationObj; if ( - friendlyStack[0].fileName && - friendlyStack[0].lineNumber && - friendlyStack[0].columnNumber + stacktrace && + stacktrace[0].fileName && + stacktrace[0].lineNumber && + stacktrace[0].columnNumber ) { locationObj = { - location: `${friendlyStack[0].fileName}:${ - friendlyStack[0].lineNumber - }:${friendlyStack[0].columnNumber}`, - file: friendlyStack[0].fileName.split('/').slice(-1), + location: `${stacktrace[0].fileName}:${stacktrace[0].lineNumber}:${ + stacktrace[0].columnNumber + }`, + file: stacktrace[0].fileName.split('/').slice(-1), line: friendlyStack[0].lineNumber }; - - // if already handled by another part of the FES, don't handle again - if (p5._fesLogCache[locationObj.location]) return [true, null]; } - // Check if the error is due to a non loadX method being used incorrectly - // in preload - if ( - currentEntryPoint === 'preload' && - p5.prototype._preloadMethods[func] == null - ) { - p5._friendlyError( - translator('fes.wrongPreload', { - func, - location: locationObj - ? translator('fes.location', locationObj) - : '', - error: error.message - }), - 'preload' - ); - } else { - // Library error - p5._friendlyError( - translator('fes.libraryError', { - func, - location: locationObj - ? translator('fes.location', locationObj) - : '', - error: error.message - }), - func - ); - } - - // Finally, if it's an internal error, print the friendlyStack - // ( fesErrorMonitor won't handle this error ) - if (friendlyStack && friendlyStack.length) { - printFriendlyStack(friendlyStack); - } - } - return [isInternal, friendlyStack]; - }; - - /** - * Handles "global" errors that the browser catches. - * - * Called when an error event happens and detects the type of error. - * - * Generates and prints a friendly error message using key: - * "fes.globalErrors.syntax.[*]", "fes.globalErrors.reference.[*]", - * "fes.globalErrors.type.[*]". - * - * @method fesErrorMonitor - * @private - * @param {*} e Event object to extract error details from - */ - const fesErrorMonitor = e => { - if (p5.disableFriendlyErrors) return; - // Try to get the error object from e - let error; - if (e instanceof Error) { - error = e; - } else if (e instanceof ErrorEvent) { - error = e.error; - } else if (e instanceof PromiseRejectionEvent) { - error = e.reason; - if (!(error instanceof Error)) return; - } - if (!error) return; - - let stacktrace = p5._getErrorStackParser().parse(error); - // process the stacktrace from the browser and simplify it to give - // friendlyStack. - let [isInternal, friendlyStack] = processStack(error, stacktrace); - - // if this is an internal library error, the type of the error is not relevant, - // only the user code that lead to it is. - if (isInternal) { - return; - } - - const errList = errorTable[error.name]; - if (!errList) return; // this type of error can't be handled yet - let matchedError; - for (const obj of errList) { - let string = obj.msg; - // capture the primary symbol mentioned in the error - string = string.replace(new RegExp('{{}}', 'g'), '([a-zA-Z0-9_]+)'); - string = string.replace(new RegExp('{{.}}', 'g'), '(.+)'); - string = string.replace(new RegExp('{}', 'g'), '(?:[a-zA-Z0-9_]+)'); - let matched = error.message.match(string); - - if (matched) { - matchedError = Object.assign({}, obj); - matchedError.match = matched; - break; - } - } - - if (!matchedError) return; - - // Try and get the location from the top element of the stack - let locationObj; - if ( - stacktrace && - stacktrace[0].fileName && - stacktrace[0].lineNumber && - stacktrace[0].columnNumber - ) { - locationObj = { - location: `${stacktrace[0].fileName}:${stacktrace[0].lineNumber}:${ - stacktrace[0].columnNumber - }`, - file: stacktrace[0].fileName.split('/').slice(-1), - line: friendlyStack[0].lineNumber - }; - } - - switch (error.name) { - case 'SyntaxError': { - // We can't really do much with syntax errors other than try to use - // a simpler framing of the error message. The stack isn't available - // for syntax errors - switch (matchedError.type) { - case 'INVALIDTOKEN': { - //Error if there is an invalid or unexpected token that doesn't belong at this position in the code - //let x = “not a string”; -> string not in proper quotes - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.invalidToken', { - url - }) - ); - break; - } - case 'UNEXPECTEDTOKEN': { - //Error if a specific language construct(, { ; etc) was expected, but something else was provided - //for (let i = 0; i < 5,; ++i) -> a comma after i<5 instead of a semicolon - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.unexpectedToken', { - url - }) - ); - break; - } - case 'REDECLAREDVARIABLE': { - //Error if a variable is redeclared by the user. Example=> - //let a = 10; - //let a = 100; - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Redeclared_parameter#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.redeclaredVariable', { - symbol: errSym, - url - }) - ); - break; - } - case 'MISSINGINITIALIZER': { - //Error if a const variable is not initialized during declaration - //Example => const a; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_initializer_in_const#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.missingInitializer', { - url - }) - ); - break; - } - case 'BADRETURNORYIELD': { - //Error when a return statement is misplaced(usually outside of a function) - // const a = function(){ - // ..... - // } - // return; -> misplaced return statement - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.syntax.badReturnOrYield', { - url - }) - ); - break; + switch (error.name) { + case 'SyntaxError': { + // We can't really do much with syntax errors other than try to use + // a simpler framing of the error message. The stack isn't available + // for syntax errors + switch (matchedError.type) { + case 'INVALIDTOKEN': { + //Error if there is an invalid or unexpected token that doesn't belong at this position in the code + //let x = “not a string”; -> string not in proper quotes + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Illegal_character#What_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.invalidToken', { + url + }) + ); + break; + } + case 'UNEXPECTEDTOKEN': { + //Error if a specific language construct(, { ; etc) was expected, but something else was provided + //for (let i = 0; i < 5,; ++i) -> a comma after i<5 instead of a semicolon + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Unexpected_token#What_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.unexpectedToken', { + url + }) + ); + break; + } + case 'REDECLAREDVARIABLE': { + //Error if a variable is redeclared by the user. Example=> + //let a = 10; + //let a = 100; + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Redeclared_parameter#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.redeclaredVariable', { + symbol: errSym, + url + }) + ); + break; + } + case 'MISSINGINITIALIZER': { + //Error if a const variable is not initialized during declaration + //Example => const a; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Missing_initializer_in_const#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.missingInitializer', { + url + }) + ); + break; + } + case 'BADRETURNORYIELD': { + //Error when a return statement is misplaced(usually outside of a function) + // const a = function(){ + // ..... + // } + // return; -> misplaced return statement + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Bad_return_or_yield#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.syntax.badReturnOrYield', { + url + }) + ); + break; + } } + break; } - break; - } - case 'ReferenceError': { - switch (matchedError.type) { - case 'NOTDEFINED': { - //Error if there is a non-existent variable referenced somewhere - //let a = 10; - //console.log(x); - let errSym = matchedError.match[1]; - - if (errSym && handleMisspelling(errSym, error)) { + case 'ReferenceError': { + switch (matchedError.type) { + case 'NOTDEFINED': { + //Error if there is a non-existent variable referenced somewhere + //let a = 10; + //console.log(x); + let errSym = matchedError.match[1]; + + if (errSym && handleMisspelling(errSym, error)) { + break; + } + + // if the flow gets this far, this is likely not a misspelling + // of a p5 property/function + let url = 'https://p5js.org/examples/data-variable-scope.html'; + p5._friendlyError( + translator('fes.globalErrors.reference.notDefined', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); + + if (friendlyStack) printFriendlyStack(friendlyStack); break; } + case 'CANNOTACCESS': { + //Error if a lexical variable was accessed before it was initialized + //console.log(a); -> variable accessed before it was initialized + //let a=100; + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.reference.cannotAccess', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - // if the flow gets this far, this is likely not a misspelling - // of a p5 property/function - let url = 'https://p5js.org/examples/data-variable-scope.html'; - p5._friendlyError( - translator('fes.globalErrors.reference.notDefined', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } } - case 'CANNOTACCESS': { - //Error if a lexical variable was accessed before it was initialized - //console.log(a); -> variable accessed before it was initialized - //let a=100; - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_lexical_declaration_before_init#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.reference.cannotAccess', { + break; + } + + case 'TypeError': { + switch (matchedError.type) { + case 'NOTFUNC': { + //Error when some code expects you to provide a function, but that didn't happen + //let a = document.getElementByID('foo'); -> getElementById instead of getElementByID + let errSym = matchedError.match[1]; + let splitSym = errSym.split('.'); + let url = + 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; + + // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb + let translationObj = { url, - symbol: errSym, + symbol: splitSym[splitSym.length - 1], + obj: splitSym.slice(0, splitSym.length - 1).join('.'), location: locationObj ? translator('fes.location', locationObj) : '' - }) - ); - - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - } - break; - } - - case 'TypeError': { - switch (matchedError.type) { - case 'NOTFUNC': { - //Error when some code expects you to provide a function, but that didn't happen - //let a = document.getElementByID('foo'); -> getElementById instead of getElementByID - let errSym = matchedError.match[1]; - let splitSym = errSym.split('.'); - let url = - 'https://developer.mozilla.org/docs/Web/JavaScript/Reference/Errors/Not_a_function#What_went_wrong'; - - // if errSym is aa.bb.cc , symbol would be cc and obj would aa.bb - let translationObj = { - url, - symbol: splitSym[splitSym.length - 1], - obj: splitSym.slice(0, splitSym.length - 1).join('.'), - location: locationObj - ? translator('fes.location', locationObj) - : '' - }; - - // There are two cases to handle here. When the function is called - // as a property of an object and when it's called independently. - // Both have different explanations. - if (splitSym.length > 1) { + }; + + // There are two cases to handle here. When the function is called + // as a property of an object and when it's called independently. + // Both have different explanations. + if (splitSym.length > 1) { + p5._friendlyError( + translator('fes.globalErrors.type.notfuncObj', translationObj) + ); + } else { + p5._friendlyError( + translator('fes.globalErrors.type.notfunc', translationObj) + ); + } + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'READNULL': { + //Error if a property of null is accessed + //let a = null; + //console.log(a.property); -> a is null + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; + /*let url2 = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null';*/ p5._friendlyError( - translator('fes.globalErrors.type.notfuncObj', translationObj) + translator('fes.globalErrors.type.readFromNull', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) ); - } else { + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } + case 'READUDEFINED': { + //Error if a property of undefined is accessed + //let a; -> default value of a is undefined + //console.log(a.property); -> a is undefined + let errSym = matchedError.match[1]; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; + /*let url2 = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#description';*/ p5._friendlyError( - translator('fes.globalErrors.type.notfunc', translationObj) + translator('fes.globalErrors.type.readFromUndefined', { + url, + symbol: errSym, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) ); + + if (friendlyStack) printFriendlyStack(friendlyStack); + break; } + case 'CONSTASSIGN': { + //Error when a const variable is reassigned a value + //const a = 100; + //a=10; + let url = + 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_const_assignment#what_went_wrong'; + p5._friendlyError( + translator('fes.globalErrors.type.constAssign', { + url, + location: locationObj + ? translator('fes.location', locationObj) + : '' + }) + ); - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + if (friendlyStack) printFriendlyStack(friendlyStack); + break; + } } - case 'READNULL': { - //Error if a property of null is accessed - //let a = null; - //console.log(a.property); -> a is null - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; - /*let url2 = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null';*/ - p5._friendlyError( - translator('fes.globalErrors.type.readFromNull', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); + } + } + }; + + p5._fesErrorMonitor = fesErrorMonitor; + p5._checkForUserDefinedFunctions = checkForUserDefinedFunctions; + + // logger for testing purposes. + p5._fesLogger = null; + p5._fesLogCache = {}; + + window.addEventListener('load', checkForUserDefinedFunctions, false); + window.addEventListener('error', p5._fesErrorMonitor, false); + window.addEventListener('unhandledrejection', p5._fesErrorMonitor, false); + + /** + * Prints out all the colors in the color pallete with white text. + * For color blindness testing. + */ + /* function testColors() { + const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; + p5._friendlyError(str, 'print', '#ED225D'); // p5.js magenta + p5._friendlyError(str, 'print', '#2D7BB6'); // p5.js blue + p5._friendlyError(str, 'print', '#EE9900'); // p5.js orange + p5._friendlyError(str, 'print', '#A67F59'); // p5.js light brown + p5._friendlyError(str, 'print', '#704F21'); // p5.js gold + p5._friendlyError(str, 'print', '#1CC581'); // auto cyan + p5._friendlyError(str, 'print', '#FF6625'); // auto orange + p5._friendlyError(str, 'print', '#79EB22'); // auto green + p5._friendlyError(str, 'print', '#B40033'); // p5.js darkened magenta + p5._friendlyError(str, 'print', '#084B7F'); // p5.js darkened blue + p5._friendlyError(str, 'print', '#945F00'); // p5.js darkened orange + p5._friendlyError(str, 'print', '#6B441D'); // p5.js darkened brown + p5._friendlyError(str, 'print', '#2E1B00'); // p5.js darkened gold + p5._friendlyError(str, 'print', '#008851'); // auto dark cyan + p5._friendlyError(str, 'print', '#C83C00'); // auto dark orange + p5._friendlyError(str, 'print', '#4DB200'); // auto dark green + } */ + } - if (friendlyStack) printFriendlyStack(friendlyStack); - break; - } - case 'READUDEFINED': { - //Error if a property of undefined is accessed - //let a; -> default value of a is undefined - //console.log(a.property); -> a is undefined - let errSym = matchedError.match[1]; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cant_access_property#what_went_wrong'; - /*let url2 = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined#description';*/ - p5._friendlyError( - translator('fes.globalErrors.type.readFromUndefined', { - url, - symbol: errSym, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); + // This is a lazily-defined list of p5 symbols that may be + // misused by beginners at top-level code, outside of setup/draw. We'd like + // to detect these errors and help the user by suggesting they move them + // into setup/draw. + // + // For more details, see https://github.com/processing/p5.js/issues/1121. + misusedAtTopLevelCode = null; + const FAQ_URL = + 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + /** + * A helper function for populating misusedAtTopLevel list. + * + * @method defineMisusedAtTopLevelCode + * @private + */ + defineMisusedAtTopLevelCode = () => { + const uniqueNamesFound = {}; + + const getSymbols = obj => + Object.getOwnPropertyNames(obj) + .filter(name => { + if (name[0] === '_') { + return false; + } + if (name in uniqueNamesFound) { + return false; } - case 'CONSTASSIGN': { - //Error when a const variable is reassigned a value - //const a = 100; - //a=10; - let url = - 'https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Invalid_const_assignment#what_went_wrong'; - p5._friendlyError( - translator('fes.globalErrors.type.constAssign', { - url, - location: locationObj - ? translator('fes.location', locationObj) - : '' - }) - ); - if (friendlyStack) printFriendlyStack(friendlyStack); - break; + uniqueNamesFound[name] = true; + + return true; + }) + .map(name => { + let type; + + if (typeof obj[name] === 'function') { + type = 'function'; + } else if (name === name.toUpperCase()) { + type = 'constant'; + } else { + type = 'variable'; } - } - } - } - }; - p5._fesErrorMonitor = fesErrorMonitor; - p5._checkForUserDefinedFunctions = checkForUserDefinedFunctions; + return { name, type }; + }); - // logger for testing purposes. - p5._fesLogger = null; - p5._fesLogCache = {}; + misusedAtTopLevelCode = [].concat( + getSymbols(fn), + // At present, p5 only adds its constants to fn during + // construction, which may not have happened at the time a + // ReferenceError is thrown, so we'll manually add them to our list. + getSymbols(contants) + ); - window.addEventListener('load', checkForUserDefinedFunctions, false); - window.addEventListener('error', p5._fesErrorMonitor, false); - window.addEventListener('unhandledrejection', p5._fesErrorMonitor, false); + // This will ultimately ensure that we report the most specific error + // possible to the user, e.g. advising them about HALF_PI instead of PI + // when their code misuses the former. + misusedAtTopLevelCode.sort((a, b) => b.name.length - a.name.length); + }; /** - * Prints out all the colors in the color pallete with white text. - * For color blindness testing. + * Detects browser level error event for p5 constants/functions used outside + * of setup() and draw(). + * + * Generates and prints a friendly error message using key: + * "fes.misusedTopLevel". + * + * @method helpForMisusedAtTopLevelCode + * @private + * @param {Event} e Error event + * @param {Boolean} log false + * + * @returns {Boolean} true */ - /* function testColors() { - const str = 'A box of biscuits, a box of mixed biscuits and a biscuit mixer'; - p5._friendlyError(str, 'print', '#ED225D'); // p5.js magenta - p5._friendlyError(str, 'print', '#2D7BB6'); // p5.js blue - p5._friendlyError(str, 'print', '#EE9900'); // p5.js orange - p5._friendlyError(str, 'print', '#A67F59'); // p5.js light brown - p5._friendlyError(str, 'print', '#704F21'); // p5.js gold - p5._friendlyError(str, 'print', '#1CC581'); // auto cyan - p5._friendlyError(str, 'print', '#FF6625'); // auto orange - p5._friendlyError(str, 'print', '#79EB22'); // auto green - p5._friendlyError(str, 'print', '#B40033'); // p5.js darkened magenta - p5._friendlyError(str, 'print', '#084B7F'); // p5.js darkened blue - p5._friendlyError(str, 'print', '#945F00'); // p5.js darkened orange - p5._friendlyError(str, 'print', '#6B441D'); // p5.js darkened brown - p5._friendlyError(str, 'print', '#2E1B00'); // p5.js darkened gold - p5._friendlyError(str, 'print', '#008851'); // auto dark cyan - p5._friendlyError(str, 'print', '#C83C00'); // auto dark orange - p5._friendlyError(str, 'print', '#4DB200'); // auto dark green - } */ -} - -// This is a lazily-defined list of p5 symbols that may be -// misused by beginners at top-level code, outside of setup/draw. We'd like -// to detect these errors and help the user by suggesting they move them -// into setup/draw. -// -// For more details, see https://github.com/processing/p5.js/issues/1121. -misusedAtTopLevelCode = null; -const FAQ_URL = - 'https://github.com/processing/p5.js/wiki/p5.js-overview#why-cant-i-assign-variables-using-p5-functions-and-variables-before-setup'; - -/** - * A helper function for populating misusedAtTopLevel list. - * - * @method defineMisusedAtTopLevelCode - * @private - */ -defineMisusedAtTopLevelCode = () => { - const uniqueNamesFound = {}; - - const getSymbols = obj => - Object.getOwnPropertyNames(obj) - .filter(name => { - if (name[0] === '_') { - return false; - } - if (name in uniqueNamesFound) { - return false; - } + const helpForMisusedAtTopLevelCode = (e, log) => { + if (!log) { + log = console.log.bind(console); + } - uniqueNamesFound[name] = true; + if (!misusedAtTopLevelCode) { + defineMisusedAtTopLevelCode(); + } - return true; - }) - .map(name => { - let type; - - if (typeof obj[name] === 'function') { - type = 'function'; - } else if (name === name.toUpperCase()) { - type = 'constant'; + // If we find that we're logging lots of false positives, we can + // uncomment the following code to avoid displaying anything if the + // user's code isn't likely to be using p5's global mode. (Note that + // setup/draw are more likely to be defined due to JS function hoisting.) + // + //if (!('setup' in window || 'draw' in window)) { + // return; + //} + + misusedAtTopLevelCode.some(symbol => { + // Note that while just checking for the occurrence of the + // symbol name in the error message could result in false positives, + // a more rigorous test is difficult because different browsers + // log different messages, and the format of those messages may + // change over time. + // + // For example, if the user uses 'PI' in their code, it may result + // in any one of the following messages: + // + // * 'PI' is undefined (Microsoft Edge) + // * ReferenceError: PI is undefined (Firefox) + // * Uncaught ReferenceError: PI is not defined (Chrome) + + if (e.message && e.message.match(`\\W?${symbol.name}\\W`) !== null) { + const symbolName = + symbol.type === 'function' ? `${symbol.name}()` : symbol.name; + if (typeof IS_MINIFIED !== 'undefined') { + log( + `Did you just try to use p5.js's ${symbolName} ${ + symbol.type + }? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: ${FAQ_URL}` + ); } else { - type = 'variable'; + log( + translator('fes.misusedTopLevel', { + symbolName, + symbolType: symbol.type, + url: FAQ_URL + }) + ); } + return true; + } + }); + }; - return { name, type }; - }); - - misusedAtTopLevelCode = [].concat( - getSymbols(p5.prototype), - // At present, p5 only adds its constants to p5.prototype during - // construction, which may not have happened at the time a - // ReferenceError is thrown, so we'll manually add them to our list. - getSymbols(contants) - ); + // Exposing this primarily for unit testing. + fn._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; - // This will ultimately ensure that we report the most specific error - // possible to the user, e.g. advising them about HALF_PI instead of PI - // when their code misuses the former. - misusedAtTopLevelCode.sort((a, b) => b.name.length - a.name.length); -}; + if (document.readyState !== 'complete') { + window.addEventListener('error', helpForMisusedAtTopLevelCode, false); -/** - * Detects browser level error event for p5 constants/functions used outside - * of setup() and draw(). - * - * Generates and prints a friendly error message using key: - * "fes.misusedTopLevel". - * - * @method helpForMisusedAtTopLevelCode - * @private - * @param {Event} e Error event - * @param {Boolean} log false - * - * @returns {Boolean} true - */ -const helpForMisusedAtTopLevelCode = (e, log) => { - if (!log) { - log = console.log.bind(console); + // Our job is only to catch ReferenceErrors that are thrown when + // global (non-instance mode) p5 APIs are used at the top-level + // scope of a file, so we'll unbind our error listener now to make + // sure we don't log false positives later. + window.addEventListener('load', () => { + window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); + }); } +} - if (!misusedAtTopLevelCode) { - defineMisusedAtTopLevelCode(); - } +export default fesCore; - // If we find that we're logging lots of false positives, we can - // uncomment the following code to avoid displaying anything if the - // user's code isn't likely to be using p5's global mode. (Note that - // setup/draw are more likely to be defined due to JS function hoisting.) - // - //if (!('setup' in window || 'draw' in window)) { - // return; - //} - - misusedAtTopLevelCode.some(symbol => { - // Note that while just checking for the occurrence of the - // symbol name in the error message could result in false positives, - // a more rigorous test is difficult because different browsers - // log different messages, and the format of those messages may - // change over time. - // - // For example, if the user uses 'PI' in their code, it may result - // in any one of the following messages: - // - // * 'PI' is undefined (Microsoft Edge) - // * ReferenceError: PI is undefined (Firefox) - // * Uncaught ReferenceError: PI is not defined (Chrome) - - if (e.message && e.message.match(`\\W?${symbol.name}\\W`) !== null) { - const symbolName = - symbol.type === 'function' ? `${symbol.name}()` : symbol.name; - if (typeof IS_MINIFIED !== 'undefined') { - log( - `Did you just try to use p5.js's ${symbolName} ${ - symbol.type - }? If so, you may want to move it into your sketch's setup() function.\n\nFor more details, see: ${FAQ_URL}` - ); - } else { - log( - translator('fes.misusedTopLevel', { - symbolName, - symbolType: symbol.type, - url: FAQ_URL - }) - ); - } - return true; - } - }); -}; - -// Exposing this primarily for unit testing. -p5.prototype._helpForMisusedAtTopLevelCode = helpForMisusedAtTopLevelCode; - -if (document.readyState !== 'complete') { - window.addEventListener('error', helpForMisusedAtTopLevelCode, false); - - // Our job is only to catch ReferenceErrors that are thrown when - // global (non-instance mode) p5 APIs are used at the top-level - // scope of a file, so we'll unbind our error listener now to make - // sure we don't log false positives later. - window.addEventListener('load', () => { - window.removeEventListener('error', helpForMisusedAtTopLevelCode, false); - }); +if (typeof p5 !== 'undefined') { + fesCore(p5, p5.prototype); } - -export default p5; diff --git a/src/core/friendly_errors/file_errors.js b/src/core/friendly_errors/file_errors.js index 677d7a61b9..8f212c8355 100644 --- a/src/core/friendly_errors/file_errors.js +++ b/src/core/friendly_errors/file_errors.js @@ -2,12 +2,9 @@ * @for p5 * @requires core */ -import p5 from '../main'; import { translator } from '../internationalization'; -if (typeof IS_MINIFIED !== 'undefined') { - p5._friendlyFileLoadError = () => {}; -} else { +function fileErrors(p5, fn){ // mapping used by `_friendlyFileLoadError` const fileLoadErrorCases = (num, filePath) => { const suggestion = translator('fes.fileLoadError.suggestion', { @@ -76,6 +73,7 @@ if (typeof IS_MINIFIED !== 'undefined') { }; } }; + /** * Called internally if there is an error during file loading. * @@ -93,4 +91,8 @@ if (typeof IS_MINIFIED !== 'undefined') { }; } -export default p5; +export default fileErrors; + +if (typeof p5 !== 'undefined') { + fileErrors(p5, p5.prototype); +} diff --git a/src/core/friendly_errors/index.js b/src/core/friendly_errors/index.js index 8f1b0e56e0..d69a3c604e 100644 --- a/src/core/friendly_errors/index.js +++ b/src/core/friendly_errors/index.js @@ -1,7 +1,13 @@ +import fesCore from './fes_core'; +import stacktrace from './stacktrace'; import validateParams from './param_validator.js'; import sketchVerifier from './sketch_verifier.js'; +import fileErrors from './file_errors'; export default function (p5) { + p5.registerAddon(fesCore); + p5.registerAddon(stacktrace); p5.registerAddon(validateParams); p5.registerAddon(sketchVerifier); -} \ No newline at end of file + p5.registerAddon(fileErrors); +} diff --git a/src/core/friendly_errors/param_validator.js b/src/core/friendly_errors/param_validator.js index 27a5420695..975c5eab95 100644 --- a/src/core/friendly_errors/param_validator.js +++ b/src/core/friendly_errors/param_validator.js @@ -2,12 +2,11 @@ * @for p5 * @requires core */ -import p5 from '../main.js'; import * as constants from '../constants.js'; -import { z } from 'zod'; +import * as z from 'zod'; import dataDoc from '../../../docs/parameterData.json'; -function validateParams(p5, fn) { +function validateParams(p5, fn, lifecycles) { // Cache for Zod schemas let schemaRegistry = new Map(); @@ -19,7 +18,7 @@ function validateParams(p5, fn) { // and so on. const p5Constructors = {}; - fn.loadP5Constructors = function () { + function loadP5Constructors() { // Make a list of all p5 classes to be used for argument validation // This must be done only when everything has loaded otherwise we get // an empty array @@ -132,6 +131,8 @@ function validateParams(p5, fn) { const { funcName, funcClass } = extractFuncNameAndClass(func); let funcInfo = dataDoc[funcClass][funcName]; + if(!funcInfo) return; + let overloads = []; if (funcInfo.hasOwnProperty('overloads')) { overloads = funcInfo.overloads; @@ -330,7 +331,7 @@ function validateParams(p5, fn) { * @returns {String} The friendly error message. */ fn.friendlyParamError = function (zodErrorObj, func) { - let message; + let message = '🌸 p5.js says: '; // The `zodErrorObj` might contain multiple errors of equal importance // (after scoring the schema closeness in `findClosestSchema`). Here, we // always print the first error so that user can work through the errors @@ -391,16 +392,16 @@ function validateParams(p5, fn) { } case 'too_small': { const minArgs = currentError.minimum; - message = `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`; + message += `Expected at least ${minArgs} argument${minArgs > 1 ? 's' : ''}, but received fewer`; break; } case 'invalid_type': { - message = buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); + message += buildTypeMismatchMessage(currentError.received, currentError.expected, currentError.path.join('.')); break; } case 'too_big': { const maxArgs = currentError.maximum; - message = `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`; + message += `Expected at most ${maxArgs} argument${maxArgs > 1 ? 's' : ''}, but received more`; break; } default: { @@ -447,6 +448,10 @@ function validateParams(p5, fn) { return; // skip FES } + if (!Array.isArray(args)) { + args = Array.from(args); + } + // An edge case: even when all arguments are optional and therefore, // theoretically allowed to stay undefined and valid, it is likely that the // user intended to call the function with non-undefined arguments. Skip @@ -463,6 +468,7 @@ function validateParams(p5, fn) { let funcSchemas = schemaRegistry.get(func); if (!funcSchemas) { funcSchemas = fn.generateZodSchemasForFunc(func); + if (!funcSchemas) return; schemaRegistry.set(func, funcSchemas); } @@ -482,11 +488,26 @@ function validateParams(p5, fn) { }; } }; + + lifecycles.presetup = function(){ + loadP5Constructors(); + + const excludes = ['validate']; + for(const f in this){ + if(!excludes.includes(f) && !f.startsWith('_') && typeof this[f] === 'function'){ + const copy = this[f]; + + this[f] = function(...args) { + this.validate(f, args); + return copy.call(this, ...args); + }; + } + } + }; } export default validateParams; if (typeof p5 !== 'undefined') { validateParams(p5, p5.prototype); - p5.prototype.loadP5Constructors(); -} \ No newline at end of file +} diff --git a/src/core/friendly_errors/stacktrace.js b/src/core/friendly_errors/stacktrace.js index fe6a1b5722..1777abac41 100644 --- a/src/core/friendly_errors/stacktrace.js +++ b/src/core/friendly_errors/stacktrace.js @@ -2,8 +2,6 @@ * @for p5 * @requires core */ -import p5 from '../main'; - // Borrow from stacktracejs https://github.com/stacktracejs/stacktrace.js with // minor modifications. The license for the same and the code is included below @@ -241,7 +239,14 @@ function ErrorStackParser() { // End borrow // wrapper exposing ErrorStackParser -p5._getErrorStackParser = function getErrorStackParser() { - return new ErrorStackParser(); -}; -export default p5; +function stacktrace(p5, fn){ + p5._getErrorStackParser = function getErrorStackParser() { + return new ErrorStackParser(); + }; +} + +export default stacktrace; + +if (typeof p5 !== 'undefined') { + stacktrace(p5, p5.prototype); +} diff --git a/src/core/init.js b/src/core/init.js index 88922bbd71..d6ac049bb2 100644 --- a/src/core/init.js +++ b/src/core/init.js @@ -12,7 +12,7 @@ import { initialize as initTranslator } from './internationalization'; * @private * @return {Undefined} */ -const _globalInit = () => { +export const _globalInit = () => { // Could have been any property defined within the p5 constructor. // If that property is already a part of the global object, // this code has already run before, likely due to a duplicate import @@ -37,7 +37,7 @@ const _globalInit = () => { }; // make a promise that resolves when the document is ready -const waitForDocumentReady = () => +export const waitForDocumentReady = () => new Promise((resolve, reject) => { // if the page is ready, initialize p5 immediately if (document.readyState === 'complete') { @@ -50,8 +50,6 @@ const waitForDocumentReady = () => }); // only load translations if we're using the full, un-minified library -const waitingForTranslator = +export const waitingForTranslator = typeof IS_MINIFIED === 'undefined' ? initTranslator() : Promise.resolve(); - -Promise.all([waitForDocumentReady(), waitingForTranslator]).then(_globalInit); diff --git a/src/core/rendering.js b/src/core/rendering.js index 29a779d7ea..810ce3bc32 100644 --- a/src/core/rendering.js +++ b/src/core/rendering.js @@ -9,8 +9,6 @@ import { Framebuffer } from '../webgl/p5.Framebuffer'; let renderers; function rendering(p5, fn){ - let defaultId = 'defaultCanvas0'; // this gets set again in createCanvas - const defaultClass = 'p5Canvas'; // Extend additional renderers object to p5 class, new renderer can be similarly attached renderers = p5.renderers = {}; @@ -126,7 +124,7 @@ function rendering(p5, fn){ * @return {p5.Renderer} */ p5.prototype.createCanvas = function (w, h, renderer, ...args) { - p5._validateParameters('createCanvas', arguments); + // p5._validateParameters('createCanvas', arguments); //optional: renderer, otherwise defaults to p2d let selectedRenderer = constants.P2D @@ -242,7 +240,7 @@ function rendering(p5, fn){ * */ p5.prototype.resizeCanvas = function (w, h, noRedraw) { - p5._validateParameters('resizeCanvas', arguments); + // p5._validateParameters('resizeCanvas', arguments); if (this._renderer) { // Make sure width and height are updated before the renderer resizes so // that framebuffers updated from the resize read the correct size @@ -403,7 +401,7 @@ function rendering(p5, fn){ args[1] = args[0]; args[0] = constants.P2D; } - p5._validateParameters('createGraphics', arguments); + // p5._validateParameters('createGraphics', arguments); return new p5.Graphics(w, h, args[0], this, args[1]); }; diff --git a/src/core/transform.js b/src/core/transform.js index e6e33c47e9..5ba580999c 100644 --- a/src/core/transform.js +++ b/src/core/transform.js @@ -461,7 +461,7 @@ function transform(p5, fn){ * */ fn.rotate = function(angle, axis) { - p5._validateParameters('rotate', arguments); + // p5._validateParameters('rotate', arguments); this._renderer.rotate(this._toRadians(angle), axis); return this; }; @@ -597,7 +597,7 @@ function transform(p5, fn){ */ fn.rotateX = function(angle) { this._assert3d('rotateX'); - p5._validateParameters('rotateX', arguments); + // p5._validateParameters('rotateX', arguments); this._renderer.rotateX(this._toRadians(angle)); return this; }; @@ -733,7 +733,7 @@ function transform(p5, fn){ */ fn.rotateY = function(angle) { this._assert3d('rotateY'); - p5._validateParameters('rotateY', arguments); + // p5._validateParameters('rotateY', arguments); this._renderer.rotateY(this._toRadians(angle)); return this; }; @@ -869,7 +869,7 @@ function transform(p5, fn){ */ fn.rotateZ = function(angle) { this._assert3d('rotateZ'); - p5._validateParameters('rotateZ', arguments); + // p5._validateParameters('rotateZ', arguments); this._renderer.rotateZ(this._toRadians(angle)); return this; }; @@ -1041,7 +1041,7 @@ function transform(p5, fn){ * @chainable */ fn.scale = function(x, y, z) { - p5._validateParameters('scale', arguments); + // p5._validateParameters('scale', arguments); // Only check for Vector argument type if Vector is available if (x instanceof p5.Vector) { const v = x; @@ -1136,7 +1136,7 @@ function transform(p5, fn){ * */ fn.shearX = function(angle) { - p5._validateParameters('shearX', arguments); + // p5._validateParameters('shearX', arguments); const rad = this._toRadians(angle); this._renderer.applyMatrix(1, 0, Math.tan(rad), 1, 0, 0); return this; @@ -1213,7 +1213,7 @@ function transform(p5, fn){ * */ fn.shearY = function(angle) { - p5._validateParameters('shearY', arguments); + // p5._validateParameters('shearY', arguments); const rad = this._toRadians(angle); this._renderer.applyMatrix(1, Math.tan(rad), 0, 1, 0, 0); return this; @@ -1396,7 +1396,7 @@ function transform(p5, fn){ * @chainable */ fn.translate = function(x, y, z) { - p5._validateParameters('translate', arguments); + // p5._validateParameters('translate', arguments); if (this._renderer.isP3D) { this._renderer.translate(x, y, z); } else { diff --git a/src/data/p5.TypedDict.js b/src/data/p5.TypedDict.js index d816769c0c..51fcda7d5b 100644 --- a/src/data/p5.TypedDict.js +++ b/src/data/p5.TypedDict.js @@ -40,7 +40,7 @@ function typedDict(p5, fn){ */ fn.createStringDict = function (key, value) { - p5._validateParameters('createStringDict', arguments); + // p5._validateParameters('createStringDict', arguments); return new p5.StringDict(key, value); }; @@ -74,7 +74,7 @@ function typedDict(p5, fn){ */ fn.createNumberDict = function (key, value) { - p5._validateParameters('createNumberDict', arguments); + // p5._validateParameters('createNumberDict', arguments); return new p5.NumberDict(key, value); }; diff --git a/src/dom/dom.js b/src/dom/dom.js index 50713d327b..ae40b40ace 100644 --- a/src/dom/dom.js +++ b/src/dom/dom.js @@ -99,7 +99,7 @@ function dom(p5, fn){ * */ fn.select = function (e, p) { - p5._validateParameters('select', arguments); + // p5._validateParameters('select', arguments); const container = this._getContainer(p); const res = container.querySelector(e); if (res) { @@ -193,7 +193,7 @@ function dom(p5, fn){ * */ fn.selectAll = function (e, p) { - p5._validateParameters('selectAll', arguments); + // p5._validateParameters('selectAll', arguments); const arr = []; const container = this._getContainer(p); const res = container.querySelectorAll(e); @@ -306,7 +306,7 @@ function dom(p5, fn){ * */ fn.createElement = function (tag, content) { - p5._validateParameters('createElement', arguments); + // p5._validateParameters('createElement', arguments); const elt = document.createElement(tag); if (typeof content !== 'undefined') { elt.innerHTML = content; @@ -381,7 +381,7 @@ function dom(p5, fn){ * */ fn.removeElements = function (e) { - p5._validateParameters('removeElements', arguments); + // p5._validateParameters('removeElements', arguments); // el.remove splices from this._elements, so don't mix iteration with it const isNotCanvasElement = el => !(el.elt instanceof HTMLCanvasElement); const removeableElements = this._elements.filter(isNotCanvasElement); @@ -613,7 +613,7 @@ function dom(p5, fn){ * @return {p5.Element} new p5.Element object. */ fn.createImg = function () { - p5._validateParameters('createImg', arguments); + // p5._validateParameters('createImg', arguments); const elt = document.createElement('img'); const args = arguments; let self; @@ -689,7 +689,7 @@ function dom(p5, fn){ * */ fn.createA = function (href, html, target) { - p5._validateParameters('createA', arguments); + // p5._validateParameters('createA', arguments); const elt = document.createElement('a'); elt.href = href; elt.innerHTML = html; @@ -819,7 +819,7 @@ function dom(p5, fn){ * */ fn.createSlider = function (min, max, value, step) { - p5._validateParameters('createSlider', arguments); + // p5._validateParameters('createSlider', arguments); const elt = document.createElement('input'); elt.type = 'range'; elt.min = min; @@ -910,7 +910,7 @@ function dom(p5, fn){ * */ fn.createButton = function (label, value) { - p5._validateParameters('createButton', arguments); + // p5._validateParameters('createButton', arguments); const elt = document.createElement('button'); elt.innerHTML = label; if (value) elt.value = value; @@ -1014,7 +1014,7 @@ function dom(p5, fn){ * */ fn.createCheckbox = function (...args) { - p5._validateParameters('createCheckbox', args); + // p5._validateParameters('createCheckbox', args); // Create a container element const elt = document.createElement('div'); @@ -1241,7 +1241,7 @@ function dom(p5, fn){ */ fn.createSelect = function (...args) { - p5._validateParameters('createSelect', args); + // p5._validateParameters('createSelect', args); let self; let arg = args[0]; if (arg instanceof Element && arg.elt instanceof HTMLSelectElement) { @@ -1715,7 +1715,7 @@ function dom(p5, fn){ * */ fn.createColorPicker = function (value) { - p5._validateParameters('createColorPicker', arguments); + // p5._validateParameters('createColorPicker', arguments); // TODO: This implementation needs to be rechecked or reimplemented // The way it worked with color is a bit too complex const elt = document.createElement('input'); @@ -1826,7 +1826,7 @@ function dom(p5, fn){ * @return {p5.Element} */ fn.createInput = function (value = '', type = 'text') { - p5._validateParameters('createInput', arguments); + // p5._validateParameters('createInput', arguments); let elt = document.createElement('input'); elt.setAttribute('value', value); elt.setAttribute('type', type); @@ -1936,7 +1936,7 @@ function dom(p5, fn){ * */ fn.createFileInput = function (callback, multiple = false) { - p5._validateParameters('createFileInput', arguments); + // p5._validateParameters('createFileInput', arguments); const handleFileSelect = function (event) { for (const file of event.target.files) { diff --git a/src/dom/p5.MediaElement.js b/src/dom/p5.MediaElement.js index d263617046..fa68e50cee 100644 --- a/src/dom/p5.MediaElement.js +++ b/src/dom/p5.MediaElement.js @@ -1459,7 +1459,7 @@ function media(p5, fn){ * */ fn.createVideo = function (src, callback) { - p5._validateParameters('createVideo', arguments); + // p5._validateParameters('createVideo', arguments); return createMedia(this, 'video', src, callback); }; @@ -1507,7 +1507,7 @@ function media(p5, fn){ * */ fn.createAudio = function (src, callback) { - p5._validateParameters('createAudio', arguments); + // p5._validateParameters('createAudio', arguments); return createMedia(this, 'audio', src, callback); }; @@ -1668,7 +1668,7 @@ function media(p5, fn){ * */ fn.createCapture = function (...args) { - p5._validateParameters('createCapture', args); + // p5._validateParameters('createCapture', args); // return if getUserMedia is not supported by the browser if (!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia)) { diff --git a/src/events/acceleration.js b/src/events/acceleration.js index 8a6d1b86b5..37e657dc12 100644 --- a/src/events/acceleration.js +++ b/src/events/acceleration.js @@ -451,7 +451,7 @@ function acceleration(p5, fn){ */ fn.setMoveThreshold = function (val) { - p5._validateParameters('setMoveThreshold', arguments); + // p5._validateParameters('setMoveThreshold', arguments); move_threshold = val; }; @@ -493,7 +493,7 @@ function acceleration(p5, fn){ */ fn.setShakeThreshold = function (val) { - p5._validateParameters('setShakeThreshold', arguments); + // p5._validateParameters('setShakeThreshold', arguments); shake_threshold = val; }; diff --git a/src/events/keyboard.js b/src/events/keyboard.js index fbc03ffad4..5b0de949ed 100644 --- a/src/events/keyboard.js +++ b/src/events/keyboard.js @@ -903,7 +903,7 @@ function keyboard(p5, fn){ * */ fn.keyIsDown = function(code) { - p5._validateParameters('keyIsDown', arguments); + // p5._validateParameters('keyIsDown', arguments); return this._downKeys[code] || false; }; diff --git a/src/image/image.js b/src/image/image.js index 7db4af9ab4..af08c052dc 100644 --- a/src/image/image.js +++ b/src/image/image.js @@ -148,7 +148,7 @@ function image(p5, fn){ * */ fn.createImage = function(width, height) { - p5._validateParameters('createImage', arguments); + // p5._validateParameters('createImage', arguments); return new p5.Image(width, height); }; @@ -272,7 +272,7 @@ function image(p5, fn){ * @param {String} [extension] */ fn.saveCanvas = function(...args) { - p5._validateParameters('saveCanvas', args); + // p5._validateParameters('saveCanvas', args); // copy arguments to array let htmlCanvas, filename, extension, temporaryGraphics; @@ -658,7 +658,7 @@ function image(p5, fn){ * */ fn.saveFrames = function(fName, ext, _duration, _fps, callback) { - p5._validateParameters('saveFrames', arguments); + // p5._validateParameters('saveFrames', arguments); let duration = _duration || 3; duration = Math.max(Math.min(duration, 15), 0); duration = duration * 1000; diff --git a/src/image/loading_displaying.js b/src/image/loading_displaying.js index b8fa13db81..a95efdcf0c 100644 --- a/src/image/loading_displaying.js +++ b/src/image/loading_displaying.js @@ -107,7 +107,7 @@ function loadingDisplaying(p5, fn){ successCallback, failureCallback ) { - p5._validateParameters('loadImage', arguments); + // p5._validateParameters('loadImage', arguments); try{ let pImg = new p5.Image(1, 1, this); @@ -1063,7 +1063,7 @@ function loadingDisplaying(p5, fn){ ) { // set defaults per spec: https://goo.gl/3ykfOq - p5._validateParameters('image', arguments); + // p5._validateParameters('image', arguments); let defW = img.width; let defH = img.height; @@ -1291,7 +1291,7 @@ function loadingDisplaying(p5, fn){ * @param {p5.Color} color the tint color */ fn.tint = function(...args) { - p5._validateParameters('tint', args); + // p5._validateParameters('tint', args); const c = this.color(...args); this._renderer.states.tint = c._getRGBA([255, 255, 255, 255]); }; @@ -1445,7 +1445,7 @@ function loadingDisplaying(p5, fn){ * */ fn.imageMode = function(m) { - p5._validateParameters('imageMode', arguments); + // p5._validateParameters('imageMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || diff --git a/src/image/pixels.js b/src/image/pixels.js index c2e2e10c6b..770cfede47 100644 --- a/src/image/pixels.js +++ b/src/image/pixels.js @@ -275,7 +275,7 @@ function pixels(p5, fn){ * @param {(BLEND|DARKEST|LIGHTEST|DIFFERENCE|MULTIPLY|EXCLUSION|SCREEN|REPLACE|OVERLAY|HARD_LIGHT|SOFT_LIGHT|DODGE|BURN|ADD|NORMAL)} blendMode */ fn.blend = function(...args) { - p5._validateParameters('blend', args); + // p5._validateParameters('blend', args); if (this._renderer) { this._renderer.blend(...args); } else { @@ -352,7 +352,7 @@ function pixels(p5, fn){ * @param {Integer} dh */ fn.copy = function(...args) { - p5._validateParameters('copy', args); + // p5._validateParameters('copy', args); let srcImage, sx, sy, sw, sh, dx, dy, dw, dh; if (args.length === 9) { @@ -721,7 +721,7 @@ function pixels(p5, fn){ * frag shader using a `tex0` uniform. */ fn.filter = function(...args) { - p5._validateParameters('filter', args); + // p5._validateParameters('filter', args); let { shader, operation, value, useWebGL } = parseFilterArgs(...args); @@ -916,7 +916,7 @@ function pixels(p5, fn){ * @return {Number[]} color of the pixel at (x, y) in array format `[R, G, B, A]`. */ fn.get = function(x, y, w, h) { - p5._validateParameters('get', arguments); + // p5._validateParameters('get', arguments); return this._renderer.get(...arguments); }; @@ -967,7 +967,7 @@ function pixels(p5, fn){ * */ fn.loadPixels = function(...args) { - p5._validateParameters('loadPixels', args); + // p5._validateParameters('loadPixels', args); this._renderer.loadPixels(); }; @@ -1147,7 +1147,7 @@ function pixels(p5, fn){ * */ fn.updatePixels = function(x, y, w, h) { - p5._validateParameters('updatePixels', arguments); + // p5._validateParameters('updatePixels', arguments); // graceful fail - if loadPixels() or set() has not been called, pixel // array will be empty, ignore call to updatePixels() if (this.pixels.length === 0) { diff --git a/src/io/files.js b/src/io/files.js index 3834dbf6bc..a73a169daf 100644 --- a/src/io/files.js +++ b/src/io/files.js @@ -291,7 +291,7 @@ function files(p5, fn){ * */ fn.loadJSON = async function (path, successCallback, errorCallback) { - p5._validateParameters('loadJSON', arguments); + // p5._validateParameters('loadJSON', arguments); try{ const { data } = await request(path, 'json'); @@ -438,7 +438,7 @@ function files(p5, fn){ * */ fn.loadStrings = async function (path, successCallback, errorCallback) { - p5._validateParameters('loadStrings', arguments); + // p5._validateParameters('loadStrings', arguments); try{ let { data } = await request(path, 'text'); @@ -853,7 +853,7 @@ function files(p5, fn){ * @return {Promise} */ fn.httpGet = async function (path, datatype='text', successCallback, errorCallback) { - p5._validateParameters('httpGet', arguments); + // p5._validateParameters('httpGet', arguments); if (typeof datatype === 'function') { errorCallback = successCallback; @@ -950,7 +950,7 @@ function files(p5, fn){ * @return {Promise} */ fn.httpPost = async function (path, data, datatype='text', successCallback, errorCallback) { - p5._validateParameters('httpPost', arguments); + // p5._validateParameters('httpPost', arguments); // This behave similarly to httpGet and additional options should be passed // as a `Request`` to path. Both method and body will be overridden. @@ -1812,7 +1812,7 @@ function files(p5, fn){ * */ fn.saveJSON = function (json, filename, optimize) { - p5._validateParameters('saveJSON', arguments); + // p5._validateParameters('saveJSON', arguments); let stringify; if (optimize) { stringify = JSON.stringify(json); @@ -1956,7 +1956,7 @@ function files(p5, fn){ * */ fn.saveStrings = function (list, filename, extension, isCRLF) { - p5._validateParameters('saveStrings', arguments); + // p5._validateParameters('saveStrings', arguments); const ext = extension || 'txt'; const pWriter = new p5.PrintWriter(filename, ext); for (let item of list) { @@ -2018,7 +2018,7 @@ function files(p5, fn){ * */ fn.saveTable = function (table, filename, options) { - p5._validateParameters('saveTable', arguments); + // p5._validateParameters('saveTable', arguments); let ext; if (options === undefined) { ext = filename.substring(filename.lastIndexOf('.') + 1, filename.length); diff --git a/src/math/calculation.js b/src/math/calculation.js index 56bc535d74..5075b8c8ad 100644 --- a/src/math/calculation.js +++ b/src/math/calculation.js @@ -147,7 +147,7 @@ function calculation(p5, fn){ * */ fn.constrain = function(n, low, high) { - p5._validateParameters('constrain', arguments); + // p5._validateParameters('constrain', arguments); return Math.max(Math.min(n, high), low); }; @@ -216,7 +216,7 @@ function calculation(p5, fn){ * @return {Number} distance between the two points. */ fn.dist = function(...args) { - p5._validateParameters('dist', args); + // p5._validateParameters('dist', args); if (args.length === 4) { //2D return Math.hypot(args[2] - args[0], args[3] - args[1]); @@ -417,7 +417,7 @@ function calculation(p5, fn){ * */ fn.lerp = function(start, stop, amt) { - p5._validateParameters('lerp', arguments); + // p5._validateParameters('lerp', arguments); return amt * (stop - start) + start; }; @@ -528,7 +528,7 @@ function calculation(p5, fn){ * */ fn.mag = function(x, y) { - p5._validateParameters('mag', arguments); + // p5._validateParameters('mag', arguments); return Math.hypot(x, y); }; @@ -604,7 +604,7 @@ function calculation(p5, fn){ * */ fn.map = function(n, start1, stop1, start2, stop2, withinBounds) { - p5._validateParameters('map', arguments); + // p5._validateParameters('map', arguments); const newval = (n - start1) / (stop1 - start1) * (stop2 - start2) + start2; if (!withinBounds) { return newval; @@ -821,7 +821,7 @@ function calculation(p5, fn){ * */ fn.norm = function(n, start, stop) { - p5._validateParameters('norm', arguments); + // p5._validateParameters('norm', arguments); return this.map(n, start, stop, 0, 1); }; @@ -1094,7 +1094,7 @@ function calculation(p5, fn){ * */ fn.fract = function(toConvert) { - p5._validateParameters('fract', arguments); + // p5._validateParameters('fract', arguments); let sign = 0; let num = Number(toConvert); if (isNaN(num) || Math.abs(num) === Infinity) { diff --git a/src/math/random.js b/src/math/random.js index dca10fad7a..7e272c7e02 100644 --- a/src/math/random.js +++ b/src/math/random.js @@ -261,7 +261,7 @@ function random(p5, fn){ * @return {*} random element from the array. */ fn.random = function(min, max) { - p5._validateParameters('random', arguments); + // p5._validateParameters('random', arguments); let rand; if (this[randomStateProp] != null) { diff --git a/src/math/trigonometry.js b/src/math/trigonometry.js index 8fe2f5f169..89335ca771 100644 --- a/src/math/trigonometry.js +++ b/src/math/trigonometry.js @@ -741,7 +741,7 @@ function trigonometry(p5, fn){ * @return {(RADIANS|DEGREES)} mode either RADIANS or DEGREES */ fn.angleMode = function(mode) { - p5._validateParameters('angleMode', arguments); + // p5._validateParameters('angleMode', arguments); if (typeof mode === 'undefined') { return this._angleMode; } else if (mode === DEGREES || mode === RADIANS) { diff --git a/src/shape/2d_primitives.js b/src/shape/2d_primitives.js index 3f1e0a3506..a060ef07bd 100644 --- a/src/shape/2d_primitives.js +++ b/src/shape/2d_primitives.js @@ -309,7 +309,8 @@ function primitives(p5, fn){ * */ fn.arc = function(x, y, w, h, start, stop, mode, detail) { - p5._validateParameters('arc', arguments); + // this.validate("p5.arc", arguments); + // p5._validateParameters('arc', arguments); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately @@ -480,7 +481,7 @@ function primitives(p5, fn){ * draw a stroke for a detail of more than 50. */ fn.ellipse = function(x, y, w, h, detailX) { - p5._validateParameters('ellipse', arguments); + // p5._validateParameters('ellipse', arguments); return this._renderEllipse(...arguments); }; @@ -530,7 +531,7 @@ function primitives(p5, fn){ * */ fn.circle = function(...args) { - p5._validateParameters('circle', args); + // p5._validateParameters('circle', args); const argss = args.slice( 0, 2); argss.push(args[2], args[2]); return this._renderEllipse(...argss); @@ -710,7 +711,7 @@ function primitives(p5, fn){ * @chainable */ fn.line = function(...args) { - p5._validateParameters('line', args); + // p5._validateParameters('line', args); if (this._renderer.states.strokeColor) { this._renderer.line(...args); @@ -894,7 +895,7 @@ function primitives(p5, fn){ * @chainable */ fn.point = function(...args) { - p5._validateParameters('point', args); + // p5._validateParameters('point', args); if (this._renderer.states.strokeColor) { if (args.length === 1 && args[0] instanceof p5.Vector) { @@ -1055,7 +1056,7 @@ function primitives(p5, fn){ * @chainable */ fn.quad = function(...args) { - p5._validateParameters('quad', args); + // p5._validateParameters('quad', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { if (this._renderer.isP3D && args.length < 12) { @@ -1213,7 +1214,7 @@ function primitives(p5, fn){ * @chainable */ fn.rect = function(...args) { - p5._validateParameters('rect', args); + // p5._validateParameters('rect', args); return this._renderRect(...args); }; @@ -1327,7 +1328,7 @@ function primitives(p5, fn){ * */ fn.square = function(x, y, s, tl, tr, br, bl) { - p5._validateParameters('square', arguments); + // p5._validateParameters('square', arguments); // duplicate width for height in case of square return this._renderRect.call(this, x, y, s, s, tl, tr, br, bl); }; @@ -1431,7 +1432,7 @@ function primitives(p5, fn){ * */ fn.triangle = function(...args) { - p5._validateParameters('triangle', args); + // p5._validateParameters('triangle', args); if (this._renderer.states.strokeColor || this._renderer.states.fillColor) { this._renderer.triangle(args); diff --git a/src/shape/attributes.js b/src/shape/attributes.js index bf787d1df7..10e6f720cd 100644 --- a/src/shape/attributes.js +++ b/src/shape/attributes.js @@ -85,7 +85,7 @@ function attributes(p5, fn){ * */ fn.ellipseMode = function(m) { - p5._validateParameters('ellipseMode', arguments); + // p5._validateParameters('ellipseMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || @@ -288,7 +288,7 @@ function attributes(p5, fn){ * */ fn.rectMode = function(m) { - p5._validateParameters('rectMode', arguments); + // p5._validateParameters('rectMode', arguments); if ( m === constants.CORNER || m === constants.CORNERS || @@ -427,7 +427,7 @@ function attributes(p5, fn){ * */ fn.strokeCap = function(cap) { - p5._validateParameters('strokeCap', arguments); + // p5._validateParameters('strokeCap', arguments); if ( cap === constants.ROUND || cap === constants.SQUARE || @@ -526,7 +526,7 @@ function attributes(p5, fn){ * */ fn.strokeJoin = function(join) { - p5._validateParameters('strokeJoin', arguments); + // p5._validateParameters('strokeJoin', arguments); if ( join === constants.ROUND || join === constants.BEVEL || @@ -593,7 +593,7 @@ function attributes(p5, fn){ * */ fn.strokeWeight = function(w) { - p5._validateParameters('strokeWeight', arguments); + // p5._validateParameters('strokeWeight', arguments); this._renderer.strokeWeight(w); return this; }; diff --git a/src/shape/curves.js b/src/shape/curves.js index 30f7287d9d..93a19c1d38 100644 --- a/src/shape/curves.js +++ b/src/shape/curves.js @@ -201,7 +201,7 @@ function curves(p5, fn){ * @chainable */ fn.bezier = function(...args) { - p5._validateParameters('bezier', args); + // p5._validateParameters('bezier', args); // if the current stroke and fill settings wouldn't result in something // visible, exit immediately @@ -312,7 +312,7 @@ function curves(p5, fn){ * */ fn.bezierDetail = function(d) { - p5._validateParameters('bezierDetail', arguments); + // p5._validateParameters('bezierDetail', arguments); this._bezierDetail = d; return this; }; @@ -432,7 +432,7 @@ function curves(p5, fn){ * */ fn.bezierPoint = function(a, b, c, d, t) { - p5._validateParameters('bezierPoint', arguments); + // p5._validateParameters('bezierPoint', arguments); const adjustedT = 1 - t; return ( @@ -550,7 +550,7 @@ function curves(p5, fn){ * */ fn.bezierTangent = function(a, b, c, d, t) { - p5._validateParameters('bezierTangent', arguments); + // p5._validateParameters('bezierTangent', arguments); const adjustedT = 1 - t; return ( @@ -756,7 +756,7 @@ function curves(p5, fn){ * @chainable */ fn.curve = function(...args) { - p5._validateParameters('curve', args); + // p5._validateParameters('curve', args); if (this._renderer.states.strokeColor) { this._renderer.curve(...args); @@ -815,7 +815,7 @@ function curves(p5, fn){ * */ fn.curveTightness = function(t) { - p5._validateParameters('curveTightness', arguments); + // p5._validateParameters('curveTightness', arguments); this._renderer._curveTightness = t; return this; }; @@ -933,7 +933,7 @@ function curves(p5, fn){ * */ fn.curvePoint = function(a, b, c, d, t) { - p5._validateParameters('curvePoint', arguments); + // p5._validateParameters('curvePoint', arguments); const s = this._renderer._curveTightness, t3 = t * t * t, t2 = t * t, @@ -1049,7 +1049,7 @@ function curves(p5, fn){ * */ fn.curveTangent = function(a, b, c, d, t) { - p5._validateParameters('curveTangent', arguments); + // p5._validateParameters('curveTangent', arguments); const s = this._renderer._curveTightness, tt3 = t * t * 3, diff --git a/src/shape/vertex.js b/src/shape/vertex.js index 34f452f45f..71ba437bb3 100644 --- a/src/shape/vertex.js +++ b/src/shape/vertex.js @@ -398,7 +398,7 @@ function vertex(p5, fn){ * */ fn.beginShape = function(kind) { - p5._validateParameters('beginShape', arguments); + // p5._validateParameters('beginShape', arguments); this._renderer.beginShape(...arguments); }; @@ -1061,7 +1061,7 @@ function vertex(p5, fn){ * */ fn.curveVertex = function(...args) { - p5._validateParameters('curveVertex', args); + // p5._validateParameters('curveVertex', args); this._renderer.splineVertex(...args); return this; }; @@ -1230,7 +1230,7 @@ function vertex(p5, fn){ * */ fn.endShape = function(mode, count = 1) { - p5._validateParameters('endShape', arguments); + // p5._validateParameters('endShape', arguments); if (count < 1) { console.log('🌸 p5.js says: You can not have less than one instance'); count = 1; @@ -1487,7 +1487,7 @@ function vertex(p5, fn){ } else { [x1, y1, z1, x2, y2, z2] = args; } - p5._validateParameters('quadraticVertex', args); + // p5._validateParameters('quadraticVertex', args); const prevOrder = this.bezierOrder(); this.bezierOrder(2); this.bezierVertex(x1, y1, z1); @@ -1680,7 +1680,7 @@ function vertex(p5, fn){ */ fn.normal = function(x, y, z) { this._assert3d('normal'); - p5._validateParameters('normal', arguments); + // p5._validateParameters('normal', arguments); this._renderer.normal(...arguments); return this; diff --git a/src/type/text2d.js b/src/type/text2d.js index d2847d78a9..5283aec65f 100644 --- a/src/type/text2d.js +++ b/src/type/text2d.js @@ -103,8 +103,6 @@ function text2d(p5, fn) { textLeading: { default: 15 }, textSize: { default: 12 }, textWrap: { default: fn.WORD }, - - // added v2.0 fontStretch: { default: fn.NORMAL, isShorthand: true }, // font-stretch: { default: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded } fontWeight: { default: fn.NORMAL, isShorthand: true }, // font-stretch: { default: normal | ultra-condensed | extra-condensed | condensed | semi-condensed | semi-expanded | expanded | extra-expanded | ultra-expanded } lineHeight: { default: fn.NORMAL, isShorthand: true }, // line-height: { default: normal | number | length | percentage } diff --git a/src/utilities/string_functions.js b/src/utilities/string_functions.js index 07bb5dc073..94e4cfdf9f 100644 --- a/src/utilities/string_functions.js +++ b/src/utilities/string_functions.js @@ -47,7 +47,7 @@ function stringFunctions(p5, fn){ * */ fn.join = function(list, separator) { - p5._validateParameters('join', arguments); + // p5._validateParameters('join', arguments); return list.join(separator); }; @@ -106,7 +106,7 @@ function stringFunctions(p5, fn){ * */ fn.match = function(str, reg) { - p5._validateParameters('match', arguments); + // p5._validateParameters('match', arguments); return str.match(reg); }; @@ -176,7 +176,7 @@ function stringFunctions(p5, fn){ * */ fn.matchAll = function(str, reg) { - p5._validateParameters('matchAll', arguments); + // p5._validateParameters('matchAll', arguments); const re = new RegExp(reg, 'g'); let match = re.exec(str); const matches = []; @@ -269,7 +269,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nf = function(nums, left, right) { - p5._validateParameters('nf', arguments); + // p5._validateParameters('nf', arguments); if (nums instanceof Array) { return nums.map(x => doNf(x, left, right)); } else { @@ -402,7 +402,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfc = function(num, right) { - p5._validateParameters('nfc', arguments); + // p5._validateParameters('nfc', arguments); if (num instanceof Array) { return num.map(x => doNfc(x, right)); } else { @@ -544,7 +544,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfp = function(...args) { - p5._validateParameters('nfp', args); + // p5._validateParameters('nfp', args); const nfRes = fn.nf.apply(this, args); if (nfRes instanceof Array) { return nfRes.map(addNfp); @@ -661,7 +661,7 @@ function stringFunctions(p5, fn){ * @return {String[]} formatted strings. */ fn.nfs = function(...args) { - p5._validateParameters('nfs', args); + // p5._validateParameters('nfs', args); const nfRes = fn.nf.apply(this, args); if (nfRes instanceof Array) { return nfRes.map(addNfs); @@ -731,7 +731,7 @@ function stringFunctions(p5, fn){ * */ fn.split = function(str, delim) { - p5._validateParameters('split', arguments); + // p5._validateParameters('split', arguments); return str.split(delim); }; @@ -874,7 +874,7 @@ function stringFunctions(p5, fn){ * */ fn.splitTokens = function(value, delims) { - p5._validateParameters('splitTokens', arguments); + // p5._validateParameters('splitTokens', arguments); let d; if (typeof delims !== 'undefined') { let str = delims; @@ -974,7 +974,7 @@ function stringFunctions(p5, fn){ * @return {String[]} trimmed strings. */ fn.trim = function(str) { - p5._validateParameters('trim', arguments); + // p5._validateParameters('trim', arguments); if (str instanceof Array) { return str.map(this.trim); } else { diff --git a/src/webgl/3d_primitives.js b/src/webgl/3d_primitives.js index a2af7f3476..1c880d87d0 100644 --- a/src/webgl/3d_primitives.js +++ b/src/webgl/3d_primitives.js @@ -554,7 +554,7 @@ function primitives3D(p5, fn){ detailY = 1 ) { this._assert3d('plane'); - p5._validateParameters('plane', arguments); + // p5._validateParameters('plane', arguments); this._renderer.plane(width, height, detailX, detailY); return this; @@ -691,7 +691,7 @@ function primitives3D(p5, fn){ */ fn.box = function(width, height, depth, detailX, detailY) { this._assert3d('box'); - p5._validateParameters('box', arguments); + // p5._validateParameters('box', arguments); this._renderer.box(width, height, depth, detailX, detailY); @@ -823,7 +823,7 @@ function primitives3D(p5, fn){ */ fn.sphere = function(radius = 50, detailX = 24, detailY = 16) { this._assert3d('sphere'); - p5._validateParameters('sphere', arguments); + // p5._validateParameters('sphere', arguments); this._renderer.sphere(radius, detailX, detailY); @@ -1051,7 +1051,7 @@ function primitives3D(p5, fn){ topCap = true ) { this._assert3d('cylinder'); - p5._validateParameters('cylinder', arguments); + // p5._validateParameters('cylinder', arguments); this._renderer.cylinder(radius, height, detailX, detailY, bottomCap, topCap); @@ -1271,7 +1271,7 @@ function primitives3D(p5, fn){ cap = true ) { this._assert3d('cone'); - p5._validateParameters('cone', arguments); + // p5._validateParameters('cone', arguments); this._renderer.cone(radius, height, detailX, detailY, cap); @@ -1454,7 +1454,7 @@ function primitives3D(p5, fn){ detailY = 16 ) { this._assert3d('ellipsoid'); - p5._validateParameters('ellipsoid', arguments); + // p5._validateParameters('ellipsoid', arguments); this._renderer.ellipsoid(radiusX, radiusY, radiusZ, detailX, detailY); @@ -1613,7 +1613,7 @@ function primitives3D(p5, fn){ */ fn.torus = function(radius, tubeRadius, detailX, detailY) { this._assert3d('torus'); - p5._validateParameters('torus', arguments); + // p5._validateParameters('torus', arguments); this._renderer.torus(radius, tubeRadius, detailX, detailY); diff --git a/src/webgl/interaction.js b/src/webgl/interaction.js index 71f6cf8c62..1b257ce6fd 100644 --- a/src/webgl/interaction.js +++ b/src/webgl/interaction.js @@ -169,7 +169,7 @@ function interaction(p5, fn){ options ) { this._assert3d('orbitControl'); - p5._validateParameters('orbitControl', arguments); + // p5._validateParameters('orbitControl', arguments); const cam = this._renderer.states.curCamera; @@ -687,7 +687,7 @@ function interaction(p5, fn){ fn.debugMode = function(...args) { this._assert3d('debugMode'); - p5._validateParameters('debugMode', args); + // p5._validateParameters('debugMode', args); // start by removing existing 'post' registered debug methods for (let i = this._registeredMethods.post.length - 1; i >= 0; i--) { diff --git a/src/webgl/light.js b/src/webgl/light.js index bfeca289e8..2d66d79ad0 100644 --- a/src/webgl/light.js +++ b/src/webgl/light.js @@ -191,7 +191,7 @@ function light(p5, fn){ */ fn.ambientLight = function (v1, v2, v3, a) { this._assert3d('ambientLight'); - p5._validateParameters('ambientLight', arguments); + // p5._validateParameters('ambientLight', arguments); this._renderer.ambientLight(...arguments); @@ -442,7 +442,7 @@ function light(p5, fn){ */ fn.specularColor = function (v1, v2, v3) { this._assert3d('specularColor'); - p5._validateParameters('specularColor', arguments); + // p5._validateParameters('specularColor', arguments); this._renderer.specularColor(...arguments); @@ -629,7 +629,7 @@ function light(p5, fn){ */ fn.directionalLight = function (v1, v2, v3, x, y, z) { this._assert3d('directionalLight'); - p5._validateParameters('directionalLight', arguments); + // p5._validateParameters('directionalLight', arguments); //@TODO: check parameters number this._renderer.directionalLight(...arguments); @@ -872,7 +872,7 @@ function light(p5, fn){ */ fn.pointLight = function (v1, v2, v3, x, y, z) { this._assert3d('pointLight'); - p5._validateParameters('pointLight', arguments); + // p5._validateParameters('pointLight', arguments); //@TODO: check parameters number this._renderer.pointLight(...arguments); @@ -1151,7 +1151,7 @@ function light(p5, fn){ quadraticAttenuation ) { this._assert3d('lightFalloff'); - p5._validateParameters('lightFalloff', arguments); + // p5._validateParameters('lightFalloff', arguments); this._renderer.lightFalloff( constantAttenuation, @@ -1378,7 +1378,7 @@ function light(p5, fn){ concentration ) { this._assert3d('spotLight'); - p5._validateParameters('spotLight', arguments); + // p5._validateParameters('spotLight', arguments); this._renderer.spotLight(...arguments); @@ -1445,7 +1445,7 @@ function light(p5, fn){ */ fn.noLights = function (...args) { this._assert3d('noLights'); - p5._validateParameters('noLights', args); + // p5._validateParameters('noLights', args); this._renderer.noLights(); diff --git a/src/webgl/loading.js b/src/webgl/loading.js index 4cf2f46b1d..3ada682900 100755 --- a/src/webgl/loading.js +++ b/src/webgl/loading.js @@ -335,7 +335,7 @@ function loading(p5, fn){ * @return {Promise} new p5.Geometry object. */ fn.loadModel = async function (path, fileType, normalize, successCallback, failureCallback) { - p5._validateParameters('loadModel', arguments); + // p5._validateParameters('loadModel', arguments); let flipU = false; let flipV = false; @@ -1086,7 +1086,7 @@ function loading(p5, fn){ */ fn.model = function (model, count = 1) { this._assert3d('model'); - p5._validateParameters('model', arguments); + // p5._validateParameters('model', arguments); if (model.vertices.length > 0) { if (!this._renderer.geometryInHash(model.gid)) { diff --git a/src/webgl/material.js b/src/webgl/material.js index 5e455d50ba..9b1593f5b2 100644 --- a/src/webgl/material.js +++ b/src/webgl/material.js @@ -125,7 +125,7 @@ function material(p5, fn){ successCallback, failureCallback ) { - p5._validateParameters('loadShader', arguments); + // p5._validateParameters('loadShader', arguments); const loadedShader = new Shader(); @@ -510,7 +510,7 @@ function material(p5, fn){ * */ fn.createShader = function (vertSrc, fragSrc, options) { - p5._validateParameters('createShader', arguments); + // p5._validateParameters('createShader', arguments); return new Shader(this._renderer, vertSrc, fragSrc, options); }; /** @@ -549,7 +549,7 @@ function material(p5, fn){ * @alt * A rectangle with a shader applied to it. */ - fn.loadFilterShader = async function (fragFilename, successCallback, failureCallback) { + fn.loadFilterShader = async function (fragFilename, successCallback, failureCallback) { p5._validateParameters('loadFilterShader', arguments); try { // Load the fragment shader @@ -558,7 +558,7 @@ function material(p5, fn){ // Create the shader using createFilterShader const loadedShader = this.createFilterShader(fragString, true); - + if (successCallback) { successCallback(loadedShader); } @@ -568,7 +568,7 @@ function material(p5, fn){ if (failureCallback) { failureCallback(err); } else { - console.error(err); + console.error(err); } } }; @@ -663,8 +663,8 @@ function material(p5, fn){ * * */ - fn.createFilterShader = function (fragSrc, skipContextCheck = false) { - p5._validateParameters('createFilterShader', arguments); + fn.createFilterShader = function (fragSrc) { + // p5._validateParameters('createFilterShader', arguments); let defaultVertV1 = ` uniform mat4 uModelViewMatrix; uniform mat4 uProjectionMatrix; @@ -899,7 +899,7 @@ function material(p5, fn){ */ fn.shader = function (s) { this._assert3d('shader'); - p5._validateParameters('shader', arguments); + // p5._validateParameters('shader', arguments); this._renderer.shader(s); @@ -1072,7 +1072,7 @@ function material(p5, fn){ */ fn.strokeShader = function (s) { this._assert3d('strokeShader'); - p5._validateParameters('strokeShader', arguments); + // p5._validateParameters('strokeShader', arguments); this._renderer.strokeShader(s); @@ -1229,7 +1229,7 @@ function material(p5, fn){ */ fn.imageShader = function (s) { this._assert3d('imageShader'); - p5._validateParameters('imageShader', arguments); + // p5._validateParameters('imageShader', arguments); this._renderer.imageShader(s); @@ -2334,7 +2334,7 @@ function material(p5, fn){ */ fn.texture = function (tex) { this._assert3d('texture'); - p5._validateParameters('texture', arguments); + // p5._validateParameters('texture', arguments); // NOTE: make generic or remove need for if (tex.gifProperties) { @@ -2848,7 +2848,7 @@ function material(p5, fn){ */ fn.normalMaterial = function (...args) { this._assert3d('normalMaterial'); - p5._validateParameters('normalMaterial', args); + // p5._validateParameters('normalMaterial', args); this._renderer.normalMaterial(...args); @@ -3075,7 +3075,7 @@ function material(p5, fn){ */ fn.ambientMaterial = function (v1, v2, v3) { this._assert3d('ambientMaterial'); - p5._validateParameters('ambientMaterial', arguments); + // p5._validateParameters('ambientMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states._hasSetAmbient = true; @@ -3171,7 +3171,7 @@ function material(p5, fn){ */ fn.emissiveMaterial = function (v1, v2, v3, a) { this._assert3d('emissiveMaterial'); - p5._validateParameters('emissiveMaterial', arguments); + // p5._validateParameters('emissiveMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states.curEmissiveColor = color._array; @@ -3426,7 +3426,7 @@ function material(p5, fn){ */ fn.specularMaterial = function (v1, v2, v3, alpha) { this._assert3d('specularMaterial'); - p5._validateParameters('specularMaterial', arguments); + // p5._validateParameters('specularMaterial', arguments); const color = fn.color.apply(this, arguments); this._renderer.states.curSpecularColor = color._array; @@ -3499,7 +3499,7 @@ function material(p5, fn){ */ fn.shininess = function (shine) { this._assert3d('shininess'); - p5._validateParameters('shininess', arguments); + // p5._validateParameters('shininess', arguments); this._renderer.shininess(shine); diff --git a/src/webgl/p5.Camera.js b/src/webgl/p5.Camera.js index c85d14f335..f87628b253 100644 --- a/src/webgl/p5.Camera.js +++ b/src/webgl/p5.Camera.js @@ -3182,7 +3182,7 @@ function camera(p5, fn){ */ fn.camera = function (...args) { this._assert3d('camera'); - p5._validateParameters('camera', args); + // p5._validateParameters('camera', args); this._renderer.camera(...args); return this; }; @@ -3313,7 +3313,7 @@ function camera(p5, fn){ */ fn.perspective = function (...args) { this._assert3d('perspective'); - p5._validateParameters('perspective', args); + // p5._validateParameters('perspective', args); this._renderer.perspective(...args); return this; }; @@ -3437,7 +3437,7 @@ function camera(p5, fn){ */ fn.linePerspective = function (enable) { - p5._validateParameters('linePerspective', arguments); + // p5._validateParameters('linePerspective', arguments); if (!(this._renderer instanceof RendererGL)) { throw new Error('linePerspective() must be called in WebGL mode.'); } @@ -3550,7 +3550,7 @@ function camera(p5, fn){ */ fn.ortho = function (...args) { this._assert3d('ortho'); - p5._validateParameters('ortho', args); + // p5._validateParameters('ortho', args); this._renderer.ortho(...args); return this; }; @@ -3662,7 +3662,7 @@ function camera(p5, fn){ */ fn.frustum = function (...args) { this._assert3d('frustum'); - p5._validateParameters('frustum', args); + // p5._validateParameters('frustum', args); this._renderer.frustum(...args); return this; }; From 6f86e8a6f20ac211704b04c42c3b1f8b879b9936 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 9 Jan 2025 16:29:32 -0500 Subject: [PATCH 17/27] Use a google font for the directly set font string test --- test/unit/visual/cases/typography.js | 19 ++++++++++++++---- .../with a directly set font string/000.png | Bin 2510 -> 2247 bytes 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index 0398c16c25..7c444190ff 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -56,10 +56,21 @@ visualSuite("Typography", function () { }); visualTest('with a directly set font string', async function (p5, screenshot) { - p5.createCanvas(100, 100); - p5.textFont("italic bold 32px Georgia"); - p5.text('p5*js', 0, 10, p5.width); - screenshot(); + const link = document.createElement('link'); + link.id = 'font'; + link.href = 'https://fonts.googleapis.com/css2?family=EB+Garamond:ital,wght@0,400..800;1,400..800&display=swap'; + link.rel = 'stylesheet'; + document.head.appendChild(link); + try { + await document.fonts.ready; + + p5.createCanvas(100, 100); + p5.textFont(`italic bold 32px "EB Garamond"`); + p5.text('p5*js', 0, 10, p5.width); + screenshot(); + } finally { + document.head.removeChild(link); + } }); visualTest('with a font file in WebGL', async function (p5, screenshot) { diff --git a/test/unit/visual/screenshots/Typography/textFont/with a directly set font string/000.png b/test/unit/visual/screenshots/Typography/textFont/with a directly set font string/000.png index 2a4a498c69f05c34f7817a2b650532733f73c619..93d9d23ac90e36a8621894a5162c1cc2bc92a8b6 100644 GIT binary patch literal 2247 zcmdUx=|9ws0>!7YjAb;*HYmn6Wob22)Fgw4A6XjvRvKep3gh7s6K061EW;pO%e7?e zOo^zFZ65pm$u>3hm@JL46jE_<-M9C?xUcVvbI#|Sf8cvk?QG0p;)>!B2m}ULnBw=7 z_-{c)_Wcfz;jkYEBJk!oNZqh99|D0U0H($c(KnX!g_&qanWS7UErHAB61-5_1bISK zF(Jx}vfsJfR2r8{D_EZ~XuuA?zWwoTRIK}y5}CX*n2HT5C|H1%!kwX#pDmx*{bro< z%mhvqLJq_4JhgGLfb%2|_$^YC{$u#3imuQxzpRbIvihymPu+BK&W4%M0&My#M$Et* z)Q^juE}%;-p7V_ceptF`JVF5AY1pWu6WBy|0=$1@lKd%um|Q8-!_8-HL{sYD8-rq= zy|t=*-*vJ$u!?bs0)Qyl&%KEFB=l5Ovk6CSHWpCA*hN|bt9fA&fSU&xLcfvoytvF9 z+;-L+(g+9y1e%0X*&FUdSE{un8tb((H*Os&NG4e*QNPZtUievssv0wDM>IE--3M1! z@gF*{KJYMibyRVm#pmeFJ3}|rwQ$J82F+^ZED=N4uM7+nskNjNFel|Tm##In>jm%V zTlFEEOs$<%{e_f@lFB|Y7f!4 zUJT^VPfvN;piOo?nkh@pJXLR-FO#bkdc zLojt3+v0)edR!`uguJL}u?6IE`wAHzDjJ>)$X#Rbr*ETyM&k`RT~d?&$CZ~hj8ivr zjt4ux!(0w(%E&p+Bp(U9q^+FJ6YO8l#o#Itj%s%Fuex1;m&6N$iB|80Ux>yDnV<3FltE zp^YbxN(H+BY$dVLSBjAbP=@k1o1L59p7X8N(ROZjx?h`W(&uoBP|m}CyC3D0a)9XC ztzffLLSL~xbj5llwP>)5Uc`sLYi1HU0(@t}>&G-hLOanCgQdmgww7piN=! z%kfdO23E*-YgC1(i)75Wj}L{~I!&^&sMIx{!iWkEqV#Bj?J4p0kv|8<(Or$_@I0G? z2{qf-#o3#7qPyZqbl8S%tFS}lVXDyJ#8Uq7XpxTG_>G?uyE z1zWE@w1~Y9@8*Orp3RG@ORhY8qM>G^Z!n~Y7SksexZ~8?CA4Cs%hv3WiIb`OWW~Fh zah9W&!%1GSmU5{l?M@m#&d{^h{F|tqs29gIjk)%nJGA;hv$lwA-!s-6Q#(-Ejz(|g zfxSLQTsieUlbKC(mom>*zuS4z|2kBaU!pH1IH{ENVl)J{5h~$_>n}-r(Ni9vR-1B| zX7-f6@%vg^OR};>r94xq23{QTAZZ>M;KM!E>jh!9!3WG#1mVKh4C7)Qvse5vYHch% z8L5c}l=r;`xK zOL@@zsy6?`x-u_dj%e)1(MZt~Y0Q%VBS;k^RVnW;Fi^)<3&y zfal*c8a@-697D;&Jw#%{*=unY>Z2TGA*4_Kk`l*5te$1sV+M=+3N7XX$9hbA)1N-n%DTC<$v|g|pX; zm&S=(i14oW$3SuZB6yOEAxUy0yN<;q2K7`x39N04?YSd?Y8NFfvvF6 z#PzG4iE#W|JhLVOi5_iwpWnA*WTx_18X;R5IepAOXmw(8Suhgs=B$eOi8{E?&7(*D kCpZ5Kr2p5$MfKU!-X;O0)d`W-{bvFJ%xp~Sa9)Z30(dehTL1t6 literal 2510 zcmd^>*;~?y0*1i?!6j*2IN4}WVA+IbD!Bv-=_Hm*xFm>6na6RfOg*KJ8 z&W8Gf7yla=^haNj<+}a=IGlQl3@Y#XSq=ihZ&GYXuGhV1^WY2By&7*tPg+gv58K)} zxRPzF@(>?}^iKM-?5kkBAU)iH(-#f({@Sl@+v01Z{K|uF6!^kH|D|a+9%tXN%oA1% zz1F@ueMK+xe;aAp?jVi)30 zg}fOKCr_y)n)4m=|3^U+BQdjw0#zwoyNy497|!a9)+RiP1q@+Eyg+Rgo?Ot}8+Q5Q z#_db{9}6mb)@hxrnS=5i_IFgEGNsyX&_x1gm)nakeL`(uDVIa)hiH=HTnptEMWiuW zbbBRTz!|~D+Dd#d1Oq}$5nyaNCLM~})pl-F`+He5cqach}mB?l>Ji zG>O86FOkQ(rZPzcDfrvD*p(Zsq`BcdGPbhx<>`g z585VoGbcB(TSi+AE=wO~dZ>S%II=JjnB4$hRBhD$1-K79q*a|sP;Uf}2e9ul>f=j* z%XZOUvW&_O!^u~|YF_rcPmsREU}D4G0Cu~i2C1cG7>g3$anGbWOIJy+AM#vgO4c=% zxRqsNl@~ki8Oj#~g;M7?p&aX=jHr8n)0sP03^lzd5;Z7S;HEU8NU^9LFdKE;j&H!= zJC8*1fbgea-(?}oX`?kY1kv?&QM#-eq@ztGmx1)DkM-zvkI4!O$=>~E3=0rxjqB$2?L<2{)NymXcBCrFjSrS+;K$It z#`t+7_TBg9s+&&35o##l+f;{Ti$>kOGkTks6Ch)pvH1_Uq7bv1=FuX>1hYp3ut)WA zV#IwQpy*>%3RhgUSDIsoJg_Z}kzE1@+(ww0>l>X;z#}mtKDH@B)D_on5ilFnA5$ zfenasM2vuCPx(Epi2_Dk0#rxe2S?!MlEmXr018~}bSbU$i6ehc$EFx_uKTK~ZW_^A z@>V;!&tcVd{i)^wdN_(7Q_<_@{~C)HAk300$F{8`*Bz_eK2G}YPEq=@&4}uH6L3^^dk%r4?aQcJxqME}++#5Z` zsYh;hDxUv4pJOc97QQb0-Zr}=Aqt7blKRFVsecSn^y)^o*B90Uwg!Kwh4%7fZKO%) z19q0XG$V|zDzLMcYv!zb@6UYKg0fkh^U2lG;@5#z$)5&fZ|Z@M;NOPEsi*IIl166_ zvRm5`!`c+_`2u)vY7-E}WeF}Q%)%uD^!DGaL4X1q#v6G{Fm^f}=TVYO4x$C7fCh zzV8P3aI-?aH4bZ7y4pxIxpR&vhq}C2Wuv0gH$%@oOqR= ztX3YZG1$M79OUElqS@nCQ$@0EeB`G)FH7i>;I_J&gcZ`Xt~OJcR`4+~?Qct(8LnpB zqC24`lzL#2i%n!Ndo0)>R04lz(Wi5wn(3XRGwPubmXwnP~&hX31xLd|pPZ~Pg zb0f~8rbo4=#UcsVYi%*qeq>)rXTYEs>FV#>p){;>hQO{IVtUN&MX@-977raWii(t1 z`^b;fq!;OmV{HBOUgTXrc3XCf!CV+fH3&Sx63i*SuYkH42zJfoGp~AsUdNt*$a=m+ z&g&{#iPd&5Q6@Zx9}42M1ej7zdkl;RQHa$YRGjo`8c6+{>77+hfX{r5tZiQ(^)J}l zWHj33pN$I}8B&))dPSbUn*5uotiyL|EnQ?J87%v(;CxApXFoj_W=2t`o5Jc+>M*ef zFLgE?sq!)CA{6$)p=kG=1*=Jj0PC_TCgK-n*9PgPaiM!S>82(rU<=i}$GJp^YQ9xi z5r>eeJnm&6F4(@OS;4}fJwXPr7yCbz?qiwl2r@;oJa$L)sgd)+m3hkKQkcbOMRZpJ g{T<~0Z+@Hj&FXf Date: Thu, 9 Jan 2025 16:32:33 -0500 Subject: [PATCH 18/27] Try using a larger image for weird aspect ratios --- test/unit/visual/visualTest.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/unit/visual/visualTest.js b/test/unit/visual/visualTest.js index cd4726c47a..55a7bdd036 100644 --- a/test/unit/visual/visualTest.js +++ b/test/unit/visual/visualTest.js @@ -81,7 +81,15 @@ export function visualSuite( } export async function checkMatch(actual, expected, p5) { - const scale = Math.min(MAX_SIDE/expected.width, MAX_SIDE/expected.height); + let scale = Math.min(MAX_SIDE/expected.width, MAX_SIDE/expected.height); + + // Long screenshots end up super tiny when fit to a small square, so we + // can double the max side length for these + const ratio = expected.width / expected.height; + const narrow = ratio < 0.5 || ratio > 2; + if (narrow) { + scale *= 2; + } for (const img of [actual, expected]) { img.resize( From b43b6520d90a0352d94b86d783314a9730210684 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 9 Jan 2025 16:45:11 -0500 Subject: [PATCH 19/27] Break big screenshots into multiple small screenshots --- test/unit/visual/cases/typography.js | 45 ++++++------------ .../000.png | Bin 15259 -> 3399 bytes .../001.png | Bin 0 -> 5222 bytes .../002.png | Bin 0 -> 6738 bytes .../003.png | Bin 0 -> 8660 bytes .../004.png | Bin 0 -> 9547 bytes .../005.png | Bin 0 -> 10389 bytes .../006.png | Bin 0 -> 11422 bytes .../007.png | Bin 0 -> 11556 bytes .../008.png | Bin 0 -> 11492 bytes .../metadata.json | 2 +- .../000.png | Bin 34185 -> 7750 bytes .../001.png | Bin 0 -> 8731 bytes .../002.png | Bin 0 -> 9141 bytes .../003.png | Bin 0 -> 13219 bytes .../004.png | Bin 0 -> 13209 bytes .../005.png | Bin 0 -> 12361 bytes .../006.png | Bin 0 -> 15061 bytes .../007.png | Bin 0 -> 14708 bytes .../008.png | Bin 0 -> 12961 bytes .../metadata.json | 2 +- .../000.png | Bin 32362 -> 4430 bytes .../001.png | Bin 0 -> 4378 bytes .../002.png | Bin 0 -> 4454 bytes .../003.png | Bin 0 -> 4370 bytes .../004.png | Bin 0 -> 4285 bytes .../005.png | Bin 0 -> 4356 bytes .../006.png | Bin 0 -> 4321 bytes .../007.png | Bin 0 -> 4294 bytes .../008.png | Bin 0 -> 4330 bytes .../metadata.json | 2 +- .../all alignments with single line/000.png | Bin 12800 -> 5381 bytes .../all alignments with single line/001.png | Bin 0 -> 3910 bytes .../all alignments with single line/002.png | Bin 0 -> 686 bytes .../all alignments with single line/003.png | Bin 0 -> 4423 bytes .../all alignments with single line/004.png | Bin 0 -> 2435 bytes .../all alignments with single line/005.png | Bin 0 -> 686 bytes .../all alignments with single line/006.png | Bin 0 -> 982 bytes .../all alignments with single line/007.png | Bin 0 -> 837 bytes .../all alignments with single line/008.png | Bin 0 -> 686 bytes .../metadata.json | 2 +- .../all alignments with single word/000.png | Bin 12800 -> 5381 bytes .../all alignments with single word/001.png | Bin 0 -> 3910 bytes .../all alignments with single word/002.png | Bin 0 -> 686 bytes .../all alignments with single word/003.png | Bin 0 -> 4423 bytes .../all alignments with single word/004.png | Bin 0 -> 2435 bytes .../all alignments with single word/005.png | Bin 0 -> 686 bytes .../all alignments with single word/006.png | Bin 0 -> 982 bytes .../all alignments with single word/007.png | Bin 0 -> 837 bytes .../all alignments with single word/008.png | Bin 0 -> 686 bytes .../metadata.json | 2 +- .../textStyle/all text styles/000.png | Bin 6856 -> 7288 bytes .../verify width of a string/000.png | Bin 2592 -> 2134 bytes test/unit/visual/visualTest.js | 2 +- 54 files changed, 21 insertions(+), 36 deletions(-) create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/001.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/002.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/003.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/004.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/005.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/006.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/007.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/008.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/001.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/002.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/003.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/004.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/005.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/006.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/007.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/008.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/001.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/002.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/003.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/004.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/005.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/006.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/007.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/008.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/001.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/002.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/003.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/004.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/005.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/006.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/007.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/008.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/001.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/002.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/003.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/004.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/005.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/006.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/007.png create mode 100644 test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/008.png diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index 7c444190ff..e079b33aae 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -155,14 +155,15 @@ visualSuite("Typography", function () { p5.createCanvas(300, 80); p5.textSize(60); alignments.forEach((alignment) => { + p5.background(255); p5.textAlign(alignment.alignX, alignment.alignY); p5.text("Single Line", 0, 0); const bb = p5.textBounds("Single Line", 0, 0); p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + screenshot(); }) - screenshot(); }); visualTest("all alignments with single line", function (p5, screenshot) { @@ -181,14 +182,15 @@ visualSuite("Typography", function () { p5.createCanvas(300, 80); p5.textSize(60); alignments.forEach((alignment) => { + p5.background(255); p5.textAlign(alignment.alignX, alignment.alignY); p5.text("Single Line", 0, 0); const bb = p5.textBounds("Single Line", 0, 0); p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + screenshot(); }); - screenshot(); }); visualTest("all alignments with multi-lines and wrap word", @@ -205,7 +207,7 @@ visualSuite("Typography", function () { { alignX: p5.RIGHT, alignY: p5.BOTTOM }, ]; - p5.createCanvas(300, 200); + p5.createCanvas(150, 100); p5.textSize(20); p5.textWrap(p5.WORD); @@ -215,11 +217,7 @@ visualSuite("Typography", function () { const boxHeight = 60; alignments.forEach((alignment, i) => { - if (i % 3 === 0 && i !== 0) { - yPos += 70; - xPos = 20; - } - + p5.background(255); p5.textAlign(alignment.alignX, alignment.alignY); p5.noFill(); @@ -245,9 +243,8 @@ visualSuite("Typography", function () { p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); - xPos += 120; + screenshot(); }); - screenshot(); } ); @@ -266,7 +263,7 @@ visualSuite("Typography", function () { { alignX: p5.RIGHT, alignY: p5.BOTTOM }, ]; - p5.createCanvas(300, 200); + p5.createCanvas(150, 100); p5.textSize(20); p5.textWrap(p5.CHAR); @@ -276,11 +273,6 @@ visualSuite("Typography", function () { const boxHeight = 60; alignments.forEach((alignment, i) => { - if (i % 3 === 0 && i !== 0) { - yPos += 70; - xPos = 20; - } - p5.textAlign(alignment.alignX, alignment.alignY); p5.noFill(); @@ -306,9 +298,8 @@ visualSuite("Typography", function () { p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); - xPos += 120; + screenshot(); }); - screenshot(); } ); @@ -327,7 +318,7 @@ visualSuite("Typography", function () { { alignX: p5.RIGHT, alignY: p5.BOTTOM }, ]; - p5.createCanvas(300, 200); + p5.createCanvas(150, 100); p5.textSize(20); let xPos = 20; @@ -336,11 +327,6 @@ visualSuite("Typography", function () { const boxHeight = 60; alignments.forEach((alignment, i) => { - if (i % 3 === 0 && i !== 0) { - yPos += 70; - xPos = 20; - } - p5.textAlign(alignment.alignX, alignment.alignY); p5.noFill(); @@ -360,16 +346,15 @@ visualSuite("Typography", function () { p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); - xPos += 120; + screenshot(); }); - screenshot(); } ); }); visualSuite("textStyle", function () { visualTest("all text styles", function (p5, screenshot) { - p5.createCanvas(300, 100); + p5.createCanvas(150, 150); p5.textSize(20); p5.textAlign(p5.LEFT, p5.TOP); @@ -426,14 +411,14 @@ visualSuite("Typography", function () { visualSuite("textWidth", function () { visualTest("verify width of a string", function (p5, screenshot) { - p5.createCanvas(300, 100); + p5.createCanvas(100, 100); p5.textSize(20); const text = "Width Test"; const width = p5.textWidth(text); - p5.text(text, 0, 50); + p5.text(text, 0, 30); p5.noFill(); p5.stroke("red"); - p5.rect(0, 50 - 20, width, 20); + p5.rect(0, 30 - 20, width, 20); screenshot(); }); }); diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/000.png index 276354a49f010542ef7cc2035b3e19bce9758fd7..06d53c4a5a4156dcac1293eb109a87e2cc8bc81b 100644 GIT binary patch literal 3399 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 literal 15259 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 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/001.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/001.png new file mode 100644 index 0000000000000000000000000000000000000000..dd671cd3eb6322619d72de6ece236d7d84a486a5 GIT binary patch literal 5222 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 CaSWaS literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/002.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/002.png new file mode 100644 index 0000000000000000000000000000000000000000..070e4fe43091e7954d832425af88da863dd03600 GIT binary patch literal 6738 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/003.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/003.png new file mode 100644 index 0000000000000000000000000000000000000000..28a0d29a3ed6d699a671af3c54b0053bd2172bb6 GIT binary patch literal 8660 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 R(cp9xL`6YUzFZa-`agfrjNkwO literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/005.png new file mode 100644 index 0000000000000000000000000000000000000000..07d8191aaf6504baed71523caa26a95db7da695f GIT binary patch literal 10389 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

FWMm{^czF0zt@=d<1cEO2-?IQI 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/006.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/006.png new file mode 100644 index 0000000000000000000000000000000000000000..2bc19e4804c598dace603ec90b2cc05f81966c1c GIT binary patch literal 11422 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 I(y-9~0ZBG_J^%m! literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/008.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/008.png new file mode 100644 index 0000000000000000000000000000000000000000..ca7f62d287fdbbb2572c7aec25010aa659bc22a8 GIT binary patch literal 11492 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/metadata.json b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/metadata.json index 2d4bfe30da..5147b8612d 100644 --- a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/metadata.json +++ b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/metadata.json @@ -1,3 +1,3 @@ { - "numScreenshots": 1 + "numScreenshots": 9 } \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/000.png index 073b087cd7494a2d78ec5438fcd82ae8cb2d63f7..0469fddbf42f44b01759d29ff710e540a5af87a9 100644 GIT binary patch literal 7750 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 literal 34185 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 a*8;o*GH$#<;=*5hAXF3{J@_Vv_WvK2Lc4bW literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/002.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/002.png new file mode 100644 index 0000000000000000000000000000000000000000..9da1618b8c3db47e5bd9ba59f7ef0699c09d44af GIT binary patch literal 9141 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 O5P2CD>2fJp;Qs*pmbG>O literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/003.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/003.png new file mode 100644 index 0000000000000000000000000000000000000000..7b47aac4157fffd58d21a8fd0b75f1bd6dab4d8d GIT binary patch literal 13219 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/005.png new file mode 100644 index 0000000000000000000000000000000000000000..0c1ca0e6566497e02c46c5d8887660cf1b797902 GIT binary patch literal 12361 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 MjfzaIlyS)a0JG|=L;wH) literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/006.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/006.png new file mode 100644 index 0000000000000000000000000000000000000000..a574fbb80f87ef8f15f4399c0bf80b3d01312f94 GIT binary patch literal 15061 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 Z%7Q@6**)i)7LHLO$V)3dFOxJ1{y$Eg^{@Z{ literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/008.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/008.png new file mode 100644 index 0000000000000000000000000000000000000000..8813e569189e9a34c99df1c8acd58cedbc6db1aa GIT binary patch literal 12961 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 T%{utb2|__mRkl*vH1z)fa~wJ! literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/metadata.json b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/metadata.json index 2d4bfe30da..5147b8612d 100644 --- a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/metadata.json +++ b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/metadata.json @@ -1,3 +1,3 @@ { - "numScreenshots": 1 + "numScreenshots": 9 } \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/000.png index 97fd71d9a2a876d5308c5df15e600463e52505b4..8f90d81969d23c4b1a43a17c92f1a120e443de9a 100644 GIT binary patch literal 4430 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 WIALH!;5ZJCr#Px>q*I_}OZ*@49T~F# diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/001.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/001.png new file mode 100644 index 0000000000000000000000000000000000000000..13c5eee1fa5386b3da3480aa1f17be77fc247c22 GIT binary patch literal 4378 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 LxeV~+}ZUN2Hj)urX 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/005.png new file mode 100644 index 0000000000000000000000000000000000000000..3be11ce3be863f5991dbaedc3d0e65554c300c7f GIT binary patch literal 4356 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/008.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/008.png new file mode 100644 index 0000000000000000000000000000000000000000..07eed26a1ddbaf842fffef5e43f0a5217bae2cd2 GIT binary patch literal 4330 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/metadata.json b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/metadata.json index 2d4bfe30da..5147b8612d 100644 --- a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/metadata.json +++ b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap word/metadata.json @@ -1,3 +1,3 @@ { - "numScreenshots": 1 + "numScreenshots": 9 } \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/000.png index 47c7462e4cf08735c53a29623204142f3946acf2..58d9573821742afd972720565f4f21530a3bae81 100644 GIT binary patch literal 5381 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 literal 12800 zcmc(mWkVcI)2J7B2oN;5Cb+x1JIk`zk_2}T?ht}QaM$2$aAy~8LV)1zkf4jZ!{K@V z#Q8Ea^`-0TshY0p>Y5lGEoD4xN^AfCfTyaWpa%dTalAh3V4}ZXOAspluQwzQJ!LsS z-5AwA06+&&Rgg9KVt$l|wPOA0Zm>6z;u9-HUs7OIa*?kr^mTUO$BDiO_XZ%27S8~@k|0b}&hqB%ySn7geM|4+e z*Yw8g<@n&7Wfy|L>kBQE#MKxtzoH)(_7JKV zY8CQ=B7`!A!G-ax6P|%{uk~DsA3Jz3UJGx`dgiW#>w9JXoE%hwIlvfTi4LdrVjKiD z$fgG2^NmmQMd&ryamYc&;V-{zMhP78A1lzuTfeXtG}5@r-XDA2>ina|2WVBmC4crB zhjNDIgxLHGw!nHMUO>KelE+tn^ZCXGVzDtDKQ4vZ){M^G@+F!OR<8SegF=hm1NgJJ zw@b3ILD@yR-HR@p&@=9v=Q~hjCx0Z=$B;X)hV_ zGf9Co|Eb}I(gwHHdh&zMpu6411mz>|@Wju1R34%>KI&@x2M2%S88k1w?ryOXoc>U} z5F5%*Pn}ER?sm&I7Tguly!zUYJ%fLJ#Dx%jIS6gMwc~PpvhGjRq_N`$^)Gqzo0JmY z*T{BPSzzn$+&lQww5fCDqY00V2p*<~FCj({Wk^{U%?#qS?3O9*&IfjcrVVUg|2mw5 z?U{Z%=_4c-T(#wt=g8JxcsBHF-Du!BmZbuP^|Xt*Z9sKb<{AA9zRphr+x34a@y~UM zeQHSO^KKK3^?#XMr$n)wV*?)^BtlY`rNCIrySK-}3eYoi)>bti-V@wI4P8>?1)Q_q zv@$@q)+0^Ye=ohlVPhCbtPdTi8xP7|!f0V{B~S~r2TqK3f*CZ<69;`na{x0z2iR_K zov3*wb$T=o674rVf*##BBHmi3y-3;$MSh9@T!ODZT`UuzJ12}E z8n_+pGH*zqp+A@sfke1+jZY7o#)0#TFSZcxjT;IxofBYUgO9Ar_Efyh&Vwt*tesbX zTAunOPHd0 z*BfZ=iKHgX-KwdUgfl{m_E=_|OqRp219)>E+9+7l<2A_sra zQo#Tgp3$&&uotU26?pvTfBq!8@VrynP+&mu7+jEgt$V#DrHu36jVf!>II*KCy*_kg zxGznw-L~B~ah+~MO!sY1;WnEKaoZDD=x=GZrk4|czxw%y)*HWq`G=hKZT?3gBPpce z;2ib~s$OAsg5aC>=h{Pk<6DiBi+4w?PC=m4u^p?6 zc6~|mz1zS(NTb&+;b;AR3?^8MDr*F&Sv78Nuhibk3^ za4|u)ff);bX-Lt<$~VEP0smqH3`5BnVAu^-@Pi5AhAmIFNrL^ zo-RG)p??nqzc6=1fIqS$Cn_6t530rV*5g%#%>SrUrcSqS^Keiyz65Cf3T&?;{Z*`? zgn+Ncr(K^?K2|U?zdupO*(HV4Z;_42GpYgJHej#{3s z6Q2H}IvqAW9gZ7){F+9Bn zCt0rPxpe&#-cC0KumG987mdGipuwYzMXkJKaWk}R6T!K;lZIl+Zc)VTv|hDDaes4XYgOWG*YEAbyB63b}}`d2Lf(Ynmo4h8TptqCHD>qdLN1Ac$t$+XnW^uc{}3~Kw7WY%XK zjL~U^%$Of{e8E#ui_SO*6O2VaDc8rZ)~Du5F|!cifNN5F2Q->ChjN5N+)Xqk^vTfG z|EW@ey2`jPvf^hSx8gbr-JJyqS!i+Aztx$NtwpD5N2`jXHcaoC6YR|P ze@;gQ$_xsd-)AeKURVxwA3%QiTgGj+tp3FnQfQ+#?cffmB+%_k__OZ^5X7>AtI`bb z{PVHbIChx}tN!sgTpSUW;apqVeVo8m6j8r^BsW1^%SLP;qy8T70r^2>>SRm-D}f0nIW#$N~9ugBv_p@#BmBiFK25oimA`%99Tx& zQ6v+1B%k3*6xT~N)+QFc74!!kI(qv?kVXJsUHHMZEr=+91B>vN;YgY@n5omR(ZzP+zb zL%oW6=jDhI!kp~%7O1W^q6|yP^+w|@_Hh%hD@TP=#nvmUBOcB}+MCeR4j(nZ;nok? zt?=~qD6A*~aR7&AQ2%1N%t{)T&AW)xoPZmqDMKWn&GcV0Y!LNzyvuR zRwnvbjlLHw&fI4c?ld3nVOk!4W1TaS^iubXiB@Fym?8%_rS1@26LnLd;9w9>P^1FAJiW<@&~$sdNux2hvi>Sp zHlii(@+@q)&rcZ=*aY?4mz_~38*rPVZcZv$+?|sn&|qF_F4ESc@8+zzMRr&1U}wmo zN)0-=$|m+#N^wxz0gj^eoBg=rPtQw{w@&N9Wfej4NUp(nw{<*u;tt~jw}St0y7OhP zGeF9?wnmQ_YJ73nwOljH{DLv7{^mvCaU+}D}?20#QkMBPZ`XdNFY}P&~v|}A_}5v z$*Po&xrEpw!FLEtYLgP?KDL6 znne>SQw)UACN@(^R8k-8&n2#!C5<7ZYAmi|>;x?K zQrug`{66a7e(FZ9K|%s1(rndudznby+F8{874n0icN5BqZt21J<7G z=a^?HiiPa(D0=MZCR>lA=WW6*X2g~g=ws^qSy@v!>Qm^rmb1Pu^*$lZnSa>gG<#!~ zeDWFTKtKe6zhEUv-oxE>M)2jKpQnG!b!ZIwbg9?s_urP4=gg198M8=wpP5pM5F zQ_Vx+ko2(HD=wsPW@07)otr$fWE^f~+-iRrX5Xk#wk+0-5ICGihw44|p~`a#=a?h} z^x(wi=E@Rz?6P>L^cxW@m#(0*z>gR*c2p>Qzo!U*cqUM1if02l=vEV>)wLpKp9zNo z(e6aadq@u3nR7+ElaJj3^du*e+Bu28^FPT*@}$(5`#4%PPoiAl8#(L}WuHAu%CE;i z@vif6{1`8qd!frl4*PQmh3C@`D%TAK1}{ofd9!b{l19jPs2P(FirbmhHFX%|1Ysj{s3YJsEVxCVB5OLjJ=rDWtgXHLfPbCQQAQdRc~qjH{C!gjBA^zn_w4o_Zbz#dPab${i|dZ`c=nq{*EMj75ax&ulZhJ{A7? zgGNj~3{XePiYm$}Gbx+&w!nHh`BsO@GVn5N)y(sGAA*-}^XfdME8zTBNtBywuxSrFJTS;_>G-GT zMSJO^L4g%;2l|oCrUfcxAIQe(C_|gt-d72 zB3eB9yr^q9{5j5od|O*nct>Wfb$aY|9JR8kR}Ze+kFq~H76m?!E@=xT`uJX4G@)~N z$p)qfk8%m|Nw{b3Xyk87I9S;YG-Z1GL6AdCtxuYw{6Nj4Kin9%Cf~uYEkZ|`q&_S1 zC*2*O50*w(_%k+dV{?nv=P*WZM{g1T_KaQ$IQ&nK@MHypMna0raH8(gVKXR8{vCs|-2u1M*n!<3+Qxr}5P2l%0$|EKPY5O^Zv?{K%)sAYm4@%O2*DG82KU^mYFl#y;kAe0+z=Hv8AkJ z{hclJ(}#6XC3wM1;~pnfM!vZ&&sk#T$4|;I$_yJ;Pw;w{v;u3>H~Oz8evsyVsv@zO zs@yjN2c3J45At48KccTnvWwk5G=Fe=*Sos=+YGC#%p?T;8-o=oumkQcej8xUjd81C zRjTN22Y%XE#Ra+5pblYG(tNJr9$ZvZ|0M4UB)hN0;64V|po_#mIF$XQ|_|mi+3Qxck*g70iE_IvSo(Wp|R= z7yq2f)Bw>%1+Bj4o_6r6!k9R4``LjDnhO0G0ZfbyFI=de(UJs(fg`lsL*-<2qL6#? zbI-LoQyM?YRX<4kBLPuq^gsMzoKESw|Gek*@~x-seqK}0rY;*NtKdkcvM3asRa@Yi|BS(ArJdqUCZU*83#W;RkTx3S?8v4 zE2u#;d{(7WTz<>(+7FNA1${1?5ZI2i!uwX;vaLLSc)&xa(_7s6YKkP7e&CORWAeY={{wnSSWOBrwNafAm)| zw!@~f!nq~!B5F6|02P0&cHEwSEh{~hK0KHUL9u=BV9=NHZ4?B^a zEU073FPCdUTV`L+gG!wTQpEdl$YAQ+f-Y@WhBbY5?Qb~=TVa=n%w2@uzSwh(jIvt# zGUOK6K{pg4Rkjxwfv1(y@Mpf`eIhP+FaAmgL#``I*NMi02UDETirug`wiXv7LmVWd zxXF3uHp<0Ei-)XEgla686%x0=wf`Q{e!h|tW3-2`V|nQ0GdNOjz$hr)RUPm2aUCm+|OeVANu0w}!FhEDZ}CsHhPX46TnMTusS zd?p-cYo(xBxV<^w*^l1d9r4U0Wn(C-BmTgWx$7q4OA0bty|sSSA8u1_(DX$-zmSx# zAz3^*ZP5QvC5DcLU}^U;rQ%)etRz4W7IbP$O*HY@Cu3^VzwoUDkkw>nmS-UXabP{- zXw}_hkUWBaG?6&lG}DSk1`BVw7BPGDaH{_5WV$Z4RO$o8CbshGWuljnfd9oVX+kxC z1Y7u~XJDsap3P1_FpfAl$iTZ*T~pdO(bP))eMB6`w}#MTdSj%u09p<5ci2l5WghC; zx+ETUT^t|ss7jRT`n2>&%=Kp9v^j?Yqg0E0wW>3c4lLg&xca^uU0m{o4m3iWBVM!I zwKjn1PY;!jlY!7je5n9Ys(%qa7s2DJahWn@$aiazs~~O z?vsg}T4CY-eWMS3sFUM2n%=?~)3z@q{ZfN8-7&ggqpOoAWT_JfPRMnc;U(#c6c?|U zKlZ{9qy5I6m}b=}QO%<&=q?EKi$oE?*J)&RWoCe?$;+DlzAo&3jjfWl-nY_%$U;j> z!x*oLLvvXbfwm0KWZfL@;<{a?1EjCAh$Rn2=GbYx(NDcPx*f$ad3?_Vxz0Wj@6RTH zYbLn0aN;VPBBd4_x<9JoroH()Szigd6JAz`wfMJbWdQ#oHlnGE+1 zvATPk-Ob631(LXC>ujV$?v`tU3SK zA^tc(^Jd}Z8VAnAS{?&VzBp&C<&!^D9Nn`BVlSPy!#?=?y(RyRWp1nTGP4csA8^qz%!esKQjPRT^>>rTwY^P4i811SmE)z4Q$*0Ma~@v~j>3jg!*^CI z%^J;b8sDJ=CeVY3TTN%xgfKfc*Jiq88CUq%%UBPKjb}R4I$Ft<6w9!;bM$NeR3EqE zw@#g`xJZhvz$HI^@1zu%^8-_cPODLTrD;OpXa!dsAg1wbVEW2%t-9wszjhWAM_iX& z0@fE%kO0?n_*6L(q}k8qY%A2Nu!XdSL8Kg@j|>_!!z%-Z2%ZUn>`}-wO7jN;P-;a) z(MEwrQW%?9U(S%eJko=AS(3EL2HDDD z=BGQ(u?VM)sCqO99Z6UHM)Xn&g6BJBR1OsWU~+WzY78z)mcMt85$a!TT4FTa&AEW! zp)iHik7Sr@RLz0tipkmH)b=5>z-Y$)O|kj9t3B5o9Ae3@5;oQ9549LafRX>yD~a1H z^~+_BoZEDy*GseVkDe!wChBz`Oj(|ZCHT8ZIl0UZ>zJRO5&`PCNy6%_aUADtj!@DS ze`V+w;SWe07-Q`(GE(y_K#|+tT}Vl{<)cBS;f8`@R@NXN-UrR@q##ldiAz522^%EXly5CiW z+zf>Ghm9e5$QctOc<*V90HBUxe`>sfJlyJ7^lXV8jNkihgm>|8mW18-w~?p`e(L&| z`8?Es3p=@}&<`ryc7#-N%bYWFBZ@j5AQzRcZUF@ChST)UUx8C%j2r02p2_MsLrm?z znj=ZI0;09oF^Gji;=f&P;D32m`x0P&3(lz(Ma~d4a<@{{T-`U+DjokeeIHeX3yKuW zC5}e#ko_xwoSOkG?&nmnJ%@IHXH3Ptj-~~A8=RLAvXXB{52>JA>e2A+>OOMTsC3{r z2|Gj^BW-OBkd48o)PgHy-&z1kuKL{%dWapi35z^gc_j&z9PfOM>rDpaCsp)zpml0+ z5ddoKhv~hBtL3`Sr@#iaO(UPWBQ$-{*x>Ld9Oo@r$&9Ayh)Lt;K(PrX?KvFCmQs>L zmE|VVIS$i&dB;{{uW*N%8jw0%$lu>V8-6g&JIXYj*74aLQV`xLjm-XbACBegx{uap^Xpb_J0zb!FjLFoLP&zt}DKqKTY4ezCB(Dif6^nrvuz;s~q7 z@`Y&FA<#^xF`<{=w#u2qwAZR8;?AU-!#h`m4$3SMi7H#bqenSLBMIH4aR+;WN=pPTS zFF=XT3QxlsYDVU`@bAe^rw{}XUTq|-TE?G51J0B6?3;bY+8lp$mh=4<+RDkTFdcz3 z7h!@pz1kF#tTv{71-AOBbLqo zxTlmUCEkCD-?DLQTVJtxSNiT-$gI(U8X-l=2ey>VJ=YlA*M;Y{mV5ur-7?OVOwf&e zo7axatWa~lXAEgbnd~;haWRK)^>JM{n`0MxjgMFyLJ!HgTcbO>^mT%K8-^XxwU|(? z==LB2Zc;#c{gG(mK0MXvS9b)KZsk^UPTr#RO3&RG*2H4BpS2Kqv!L3pezI_@!2WqLMKdqO&4gQAB_q4(&B@bsT85PAuoBFw(BpIJ`89+X~_Bb_nB<@aj8UIhYl z9#HqC46NhrakhBrf0q={M?kpF4uvna2iQ*$@%f^EvnpJUrE~dBZU)%$$tkKk^@wsB z02O$<)vInYG&J6*5n}WJ0Ac(AD67g*9AAXqI~c*sUQ3iAoF+q+qKpYqvC43z6vD;5 zRW|4-HC*i{gTlvwQdUGRTEPNg0*A~VA8e|EPn%m6^-wnqVi;>lif%ygHu{0j%R$`9 z?%CqmZ@+Epwn^4j9uK;NaCNxidThpozS3_b{Er^^fAnvT&FCDj^Im+6)7F z|6O)!$}=_5=o9&k1HK6k@uwxE3Q*HBeW8#Xc0qQ&aykdsb-ZMwhiqeU&;3W~2)jS# zSuo*OhubmOsT~7u67iSyI5ciHu_kbAMi7 zD%cK>Wk4c=gMnH#2J2pUhSntqWzpyo*o~&BwC(Sto;2QtoHFAs7o=~|vlt>BuK!ll zllsEo$b)vByqU_O>cDSvywBWP(9ggc-94=7MALR;6ME?~+eE|ketUk3sxm7fvKlQv zAmZ|u3{f_B+D?R2C-dQpW64yNWBXn*4MrnxZnN^9e(cP5A$_tfXWU==RzH}^pX>_T z-@Lyl<(jjC&IO(d_PZOmc(97tnJ)B~f7SDwH1xPGfLCQippKQdFqwLRG=xTDo$E+4Yf$t1rj!z+_V{*7gtA;8M@-sXQq zL;l1~{^0|&A0}Aqv261hO}=+nm+m}qV=Ld1`^|OlCaJuFBs)FzblAeu5{EZSxL38F8ZMb9?}rkj&xY`(0uETL7ZDxqRk(Tj+ZN@wQ#wC z=JBJ)GbyrZ9;hxzHAGz0^~l^nJ*Sh?t5eNEU$=km_G5 zZBJd+>?&_O9TM6uxRw06=}UcO7w8uhhdqVPN{RJR=))k$+v)m!cA8Y5+p{D69?0}hVi0VgMBhv^VHh#_COEn zNdx@|4*##)_{_d}Y$uWTDXgGKQVFAfRcBY_-5Ijpv;lq9Dy3R9 zFhGqoSM9n?4(i5)D)klV6SwkVVV8}@{KJ-NE?~{yW6xmDHNKK@|MDI%_p5(%3K=%# zlxpB;*Padn#nu86nQT(FTa;?Cm)B_Qk+MaW^v7!ON1l*doJ%FBbdvs>T3Z?ukDLpr z@<-T30GY`#3dGqsJ|aR>PYZud{@p?ITGAl8Hpp<)FYqfX^jxyUm^UN^UOaLV852g& zmSVK${E6hM+FORZGG$y&g`+?wOZs%LYHx^wXwtjHY|i%79Z_G}-*C}PQaO9Kc8h{& zjAjeIwnTuzR>CiC1vSy%!(UB>gBLxB4H$88?j)#2h2onc;d3L`vY4vcX; z;5j#Ph0Q^=kv2i-ApG8a3XfY_Yb13LdCw?QP8CLZ))DxitEH{%?5MTE*u6H6ZO@bF zyO|LZ@C8tEDOr#bv~iiF!h z4Y9baX%?3U`s1tvf?g~4ip48Mr)NJ`;V5Lthf*7%kUMufyr5QIe4noGq+Ra;90bQ% zQyvJ1vA%CP1*;;p^qzq`0ezd&Q7%*j(b-W+{t)&uep*k*DvV#P(^CSmurPhtXlr_; z8@HwIu)^dmn4`HuC-=_B8I`sM_&?f_P9n+o6yz7ojRP^_)V*?&3vZ5JtVANanj^hf z9z7pi8(gNQ3=It$H8yiB`=7NDn=q`znx3kH4|w@Askza>i4}(PMLVeA;I4M81V>`S z^VqIsFEZ@>!sIw_1bOb7Kd|1M5O-w8E+MiD&gij%l^23gaEBFP z{5hvT+gB0_=^Ap+fc?Yi_ioJSj9}};DoQWnb|@=cH8QYw3uK4!vGR1r^u9|ZiMa4T zU5nT4Ga#*%V61lwU~R!<@+!r+f{DHTA^6|7^s!*!kzqv%FHR~i?l|665tEMpL|Qn0 zVs6_d{VcCvR?pqj61X#U`_E6~7|xGvt%zFtQ!5*LJ1e(r+e!(>B#f}DDsz&(UE|!; zh%`Tv0iE~hgjH3JVi~QWI1{Snutt%i@^_@CPYlt>C6{AfHg{1lHf|2@WD=GH%dqJFSBTU z+tG00S8RLN(^B-Wopxf2SxNIKk^USK?uI%z7Skayh|Mf$PgM@wgu1{P5%IPk()wE0 z0*#L;uda=Tl*NIMbk2NyjobeO9msZm>S?%8w(p;!F&e`==+0bRtiK*Hy&!-i~VEP!v?P<`-5}fzG~kvU~c&I zPs3?w09ZbqxH?*~-<^{*Cds8~OIt3kb7p9*b9B?>v@f8LBv*)xR#pKq)feiQh&=CN z6G8IY4k4ZattVbjYJ<$hl&#J8T+ADVTqP*nHwdz_4=ND+l@pja`@ObafCSEWa0K6IsMn4Kc_1P^nX+GRo3;Qm_w{ww-Sst z|Cc3P6#huc-^Y#LMG#3pS$?@+`^(@@9a%0MhNj$iRk9&(EJ+T4h+d}$JNuBD3t#?` zVuMkNKo-LXl)2*lV>)?-H2o$lU~1-{KY@G%Om9X0uv<(PFwUv>{Lb*?&QmVE>4Ozv zgMLB^wm)uN3@3CV2#t{-?O$^RXs$<3nB#=)6a`5PW36&ppBNw4cX-D9S^`BP81`Fe z_)J@ZD9p{N<{oXLa`ssvS)UQU(AAxIux24Pv;zfnT})jfY&|zE1Ll_8b?2@ z1Z(`BawF%V&z+h552$$!9y;sWiw$Y!lz8B6bHHl*oF@VwkFI~D?AiMu)GjZBt$mV~Ax7|P z9F5g(7;#`6&Z30Px%<&Lqda{+e2>M?G4r2wnTqOM;uRs33P*dMO9EU=j7A9)6vMK^ z8$j}$KC4xX7E`fvw3rBwWEfFf|2}I#i+RK9;uPk_O?`ZO&=)D`H!=92c2!6n&HNLg zkmf2Ztm?|+t8M9T9riHKM|c_`(^?b9&6bz^vUlj;sX8}tzy6O_bS(jUZctu9@{JOW zHCRCQzwUT~&ncXv!u*}`y^_mJ&@}aW$0MpMy#@}K!kY}gqbnWUi9eo3N~zxlBnAg}D=~)QE<6K; zX*9QZdY0@jctIUxUA|T#@yyi(h@?Oh@8wdRw5Ivc=IM{F)i$_Qs6>)qbLiu?Z4WO^ z2$qn5dgkT4stGa7@he)kaEbBX?2@`H7k66L9_6_!&%9!#S@k2rNq;ZH**57X+F4i0 zobrz=8kCyyQB_7J?0;M3e6lqyW0d@TR?vZs2xq@-qMM3_>EI7(@3qogE;3W4{C(#~ zTc(^LE!jTX?jFt(>Z98nC7UWc>vqGWg9N!0G;iE+7m^BTh#n-TeZSOy`2fqPL8C?i_p zb5l#wU`yW(zOY@(>g8YEfmRm!nZbgbQm>6jcJ$jfWBhEeY^h)1sX%v(`eJp~B4@3c zFwSA$&z%i`aB=i!*4kIln1$#=d3IQKP}JP{N6ClBj!W>|BwO{$Qkinoarx^&3_CY} z`2A+1}U;7GJ-b?7Co%6sHt4A&7Ya%Rc z@}~ZfZb|EYZ%L2@;-&fBP}%Z|Q#ym^xuWn7R!95K-kL4jKDG4KbeP#`Pb1`s)iUh` z_S!Y37||yrE&(N9X+zR@KD=zDt)I$sW*_wLltywG?IRj;^9pc@wGq3!Z-qq7TSf#2 zlo6ipXq^5!9lQ3_VztoiR$>mVQ`y-0rS)P?qVNr0^Kf{&N{bE4fT)6L!s+z|&N{^a zpA26m9$TUcfWw4>iI=HrVTw#E^Q$YgGJ~&-UL{zeY9VrsEV0w98*``{@@o34l~&Vj zXD$9Gy*dy!6kW5)a4-#(4a?Ky)ibt|4#}ZrHL`hEJ8%0 Si(h}~0H`WzDb&e9!u}t+huaST diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/001.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/001.png new file mode 100644 index 0000000000000000000000000000000000000000..6e93fb8f0614daf76ce161f2f01f0bce6e48bef2 GIT binary patch literal 3910 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/003.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/003.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8c5b8f11f43ae0649006eca8c411235a58d9cf GIT binary patch literal 4423 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 ZKgP9t@X;$RmPk4pj1A18RS?(2{{hDzB$EID literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/004.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/004.png new file mode 100644 index 0000000000000000000000000000000000000000..e08ba483b2216eda94e8ab2f1f4e7c624e3a43c8 GIT binary patch literal 2435 zcmeHJ=|9v97avQEwXr6$=b2>bCS?g@U&}t4u?$jIxJI&cnJn2RCR-xeCKs0&{7TuE zXGDq{N_Q8y-!(5s>{SVK}=gm3i#o52-oX<&hw6_xCm*xk7KteXw=FT7xhdNt! z1oNsnX83Unij*o zvrx29dvTDwX6CeamH#QAv{ooTCdtftqG5?E$OB8Kxg+mbSQfg9nX! zX6s9oKZ@RRA`I>?*4zEE6}19eHCTP=S8Ifc^eUdFc-#4Xv~HTyq_u_UGO_aIy|{`2 z&72H_w=So9pweMJO$Kr~%k56*G|oA-(c()`8|aP-!i^IX3W`1y08oz-=`&BA!V(6$*ya?*yvA6G}h#NA8n|W5O<`~ z{swv@E91H*rI%lJEGS{0Y)Af%wOcK6DfXGl4e8Q|*+~sQS|*oZBu(WafW`T}(FzQm zPst|HIGKCl)PRd}CP0FD>;F95xoHk?jw&gu3rwsGKC2uY{o4k!>D1{RNgD~hKOI2c zobr{n{bd!npR2aG0*=j^sDFX(MCxz%{4(tqQ+KdwLg#ies~^Gigz3#@(eoVC6q)`l zyqw~&xdICKmYUOH&n+MBc;qNT&?T-1+1_*7-kZ@=cbIGFi9w>;{y|ea|LLyE;Cal? z*W@QGo0 z;)Q1)b~>5~L=|!Sc>fA1*0FM}2lV8iP&@RtUqut)zotOHk_}82yd_aIeS#{NX+fd@4eYHGh!RhFQNTy9L9l$e35JZVh&5+MMqSku?wC++@&%^^k$`Oq9Qr#a$P$ zgOFT|Yr*BR))9E6NS=HKm+%Fhhb!30D0yf`gDN_$Ch27m?8G&iu1Ed5uv_O9a#trg z)9^pCVNbOqsTztN`{a_%tM63O*e3&b8r+SiTia{;e{#~QnIhp=`*x#7Q1Ff=(SXg#+gBY)Q+gq5RIgp^KqG}O zY%68jU_2;dj^u!zgycsr50C!z%M9*v&esu!5dIqZxSh>LOT}*ex}0l0C)0QDT65vG z2HK^hmdBmC}PmX_|s;jQk2@AlUQ79-Bn_O9NTCE!t zEIz&KN@$5%-Y(CH{OPVR6ob_Ege^aE*+t=ErV1-zTjKvPH%g@r$8ROhNA)4P#BVQx zi2Y_Iezpq0?tzx3U_@yt!;!J3fVpqi4Dkv-%OOx&`DC_utgLy(O`DypW*B;_U{nt~ z-o_vm=URY>7jfrL!WH6uM3hdT@jm-_MZ+bfc%S9&9+P19`QiQq5-|pNz~K(wJjC?? zM&#(AB4TDK-8I+*aNhTP5UGs#+(Hl#vIJU(RXYMi6UGZ;WhdKA0iHYt>o5>J!J0g( zn9)ywOWW!PI)I2urc5?nhnYoxV#n@JPEEWJq`=eq*toVcGWc5@d`@V>&+H*2{|Z*< zxb=gWVTeVokuPV$_%2#5Ugl2U2uJ)Em3&cAE=atw7B_@&$1}MU5)VqS5HtpHeufwW z&q5_qOhKGr$;%)P@Od*3(e@);ik}0lfan2nD`W|BaI2lY<$HnqSHb^x@;~g!<2VlQ Xk(Zubl=3R}R|T@Mus5$W^-1^_XbNbr literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/005.png new file mode 100644 index 0000000000000000000000000000000000000000..56e366297cd5708a7acf2a668e68e2bdc2983442 GIT binary patch literal 686 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!131`#33*wa66EY zx=LsY17q`3b`F6P91?4MLYssX5;pu{U}TbHY@WK(D}afGXPUf%gMxCx2BT0;uZD($ zpO{%VQdoGxmT5V13K&Gx0Zr~{ICv^VRfCac^{A6TeF=ArV o4xYMzg+oHee$>*T9=s12ckQ!RuqfkR3`~Fwp00i_>zopr0EMT`Q~&?~ literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/006.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/006.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d39748d91160774b0f8058f5ca2f1cf760e251 GIT binary patch literal 982 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!131`#r z)HQy7K}k>doquZl=v&#dySrzuUOjX1;+cQ{o-MGgxBL9&=9zEb)b9WNd*=ChV|lwX zHGeFM3k-@YcI-T-_(6pA-oCk!Zm;{Bx9Z#~n)tb%RZc$r-Mh4XH8=04?ox%vr82iCY4G6Gb)3ptDnm{r-UW|$z+9r literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/007.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/007.png new file mode 100644 index 0000000000000000000000000000000000000000..7b86de4c494bb50f37e01b43eb8740128c8583cd GIT binary patch literal 837 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!131`#=!GM4Rb(Z7kbs?JM^G)anxdRveU;fB$8A!D5bZ z0fh@pY^!@!I0PgF4I-3XEt(k`#S9{HRU8`*bTk~4(mW)|!m*{{V3sl`6N?)Q&ovLh za|#X%Sb4&vJp~jDloB?$brrBNGU+C4xaHBr&?v~*Y#P*J%ps7$*nHJZh=rqvLt@QD zr8$lb4%`xJ%qA%~B)A+%=oNX$!^9GGAYto77DgszCbsM)9O33*wa66EY zx=LsY17q`3b`F6P91?4MLYssX5;pu{U}TbHY@WK(D}afGXPUf%gMxCx2BT0;uZD($ zpO{%VQdoGxmT5V13K&Gx0Zr~{ICv^VRfCac^{A6TeF=ArV o4xYMzg+oHee$>*T9=s12ckQ!RuqfkR3`~Fwp00i_>zopr0EMT`Q~&?~ literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/metadata.json b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/metadata.json index 2d4bfe30da..5147b8612d 100644 --- a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/metadata.json +++ b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single line/metadata.json @@ -1,3 +1,3 @@ { - "numScreenshots": 1 + "numScreenshots": 9 } \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/000.png index 47c7462e4cf08735c53a29623204142f3946acf2..58d9573821742afd972720565f4f21530a3bae81 100644 GIT binary patch literal 5381 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 literal 12800 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 Si(h}~0H`WzDb&e9!u}t+huaST diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/001.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/001.png new file mode 100644 index 0000000000000000000000000000000000000000..6e93fb8f0614daf76ce161f2f01f0bce6e48bef2 GIT binary patch literal 3910 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 literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/003.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/003.png new file mode 100644 index 0000000000000000000000000000000000000000..dd8c5b8f11f43ae0649006eca8c411235a58d9cf GIT binary patch literal 4423 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 ZKgP9t@X;$RmPk4pj1A18RS?(2{{hDzB$EID literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/004.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/004.png new file mode 100644 index 0000000000000000000000000000000000000000..e08ba483b2216eda94e8ab2f1f4e7c624e3a43c8 GIT binary patch literal 2435 zcmeHJ=|9v97avQEwXr6$=b2>bCS?g@U&}t4u?$jIxJI&cnJn2RCR-xeCKs0&{7TuE zXGDq{N_Q8y-!(5s>{SVK}=gm3i#o52-oX<&hw6_xCm*xk7KteXw=FT7xhdNt! z1oNsnX83Unij*o zvrx29dvTDwX6CeamH#QAv{ooTCdtftqG5?E$OB8Kxg+mbSQfg9nX! zX6s9oKZ@RRA`I>?*4zEE6}19eHCTP=S8Ifc^eUdFc-#4Xv~HTyq_u_UGO_aIy|{`2 z&72H_w=So9pweMJO$Kr~%k56*G|oA-(c()`8|aP-!i^IX3W`1y08oz-=`&BA!V(6$*ya?*yvA6G}h#NA8n|W5O<`~ z{swv@E91H*rI%lJEGS{0Y)Af%wOcK6DfXGl4e8Q|*+~sQS|*oZBu(WafW`T}(FzQm zPst|HIGKCl)PRd}CP0FD>;F95xoHk?jw&gu3rwsGKC2uY{o4k!>D1{RNgD~hKOI2c zobr{n{bd!npR2aG0*=j^sDFX(MCxz%{4(tqQ+KdwLg#ies~^Gigz3#@(eoVC6q)`l zyqw~&xdICKmYUOH&n+MBc;qNT&?T-1+1_*7-kZ@=cbIGFi9w>;{y|ea|LLyE;Cal? z*W@QGo0 z;)Q1)b~>5~L=|!Sc>fA1*0FM}2lV8iP&@RtUqut)zotOHk_}82yd_aIeS#{NX+fd@4eYHGh!RhFQNTy9L9l$e35JZVh&5+MMqSku?wC++@&%^^k$`Oq9Qr#a$P$ zgOFT|Yr*BR))9E6NS=HKm+%Fhhb!30D0yf`gDN_$Ch27m?8G&iu1Ed5uv_O9a#trg z)9^pCVNbOqsTztN`{a_%tM63O*e3&b8r+SiTia{;e{#~QnIhp=`*x#7Q1Ff=(SXg#+gBY)Q+gq5RIgp^KqG}O zY%68jU_2;dj^u!zgycsr50C!z%M9*v&esu!5dIqZxSh>LOT}*ex}0l0C)0QDT65vG z2HK^hmdBmC}PmX_|s;jQk2@AlUQ79-Bn_O9NTCE!t zEIz&KN@$5%-Y(CH{OPVR6ob_Ege^aE*+t=ErV1-zTjKvPH%g@r$8ROhNA)4P#BVQx zi2Y_Iezpq0?tzx3U_@yt!;!J3fVpqi4Dkv-%OOx&`DC_utgLy(O`DypW*B;_U{nt~ z-o_vm=URY>7jfrL!WH6uM3hdT@jm-_MZ+bfc%S9&9+P19`QiQq5-|pNz~K(wJjC?? zM&#(AB4TDK-8I+*aNhTP5UGs#+(Hl#vIJU(RXYMi6UGZ;WhdKA0iHYt>o5>J!J0g( zn9)ywOWW!PI)I2urc5?nhnYoxV#n@JPEEWJq`=eq*toVcGWc5@d`@V>&+H*2{|Z*< zxb=gWVTeVokuPV$_%2#5Ugl2U2uJ)Em3&cAE=atw7B_@&$1}MU5)VqS5HtpHeufwW z&q5_qOhKGr$;%)P@Od*3(e@);ik}0lfan2nD`W|BaI2lY<$HnqSHb^x@;~g!<2VlQ Xk(Zubl=3R}R|T@Mus5$W^-1^_XbNbr literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/005.png new file mode 100644 index 0000000000000000000000000000000000000000..56e366297cd5708a7acf2a668e68e2bdc2983442 GIT binary patch literal 686 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!131`#33*wa66EY zx=LsY17q`3b`F6P91?4MLYssX5;pu{U}TbHY@WK(D}afGXPUf%gMxCx2BT0;uZD($ zpO{%VQdoGxmT5V13K&Gx0Zr~{ICv^VRfCac^{A6TeF=ArV o4xYMzg+oHee$>*T9=s12ckQ!RuqfkR3`~Fwp00i_>zopr0EMT`Q~&?~ literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/006.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/006.png new file mode 100644 index 0000000000000000000000000000000000000000..a6d39748d91160774b0f8058f5ca2f1cf760e251 GIT binary patch literal 982 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!131`#r z)HQy7K}k>doquZl=v&#dySrzuUOjX1;+cQ{o-MGgxBL9&=9zEb)b9WNd*=ChV|lwX zHGeFM3k-@YcI-T-_(6pA-oCk!Zm;{Bx9Z#~n)tb%RZc$r-Mh4XH8=04?ox%vr82iCY4G6Gb)3ptDnm{r-UW|$z+9r literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/007.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/007.png new file mode 100644 index 0000000000000000000000000000000000000000..7b86de4c494bb50f37e01b43eb8740128c8583cd GIT binary patch literal 837 zcmeAS@N?(olHy`uVBq!ia0y~yVAKJ!131`#=!GM4Rb(Z7kbs?JM^G)anxdRveU;fB$8A!D5bZ z0fh@pY^!@!I0PgF4I-3XEt(k`#S9{HRU8`*bTk~4(mW)|!m*{{V3sl`6N?)Q&ovLh za|#X%Sb4&vJp~jDloB?$brrBNGU+C4xaHBr&?v~*Y#P*J%ps7$*nHJZh=rqvLt@QD zr8$lb4%`xJ%qA%~B)A+%=oNX$!^9GGAYto77DgszCbsM)9O33*wa66EY zx=LsY17q`3b`F6P91?4MLYssX5;pu{U}TbHY@WK(D}afGXPUf%gMxCx2BT0;uZD($ zpO{%VQdoGxmT5V13K&Gx0Zr~{ICv^VRfCac^{A6TeF=ArV o4xYMzg+oHee$>*T9=s12ckQ!RuqfkR3`~Fwp00i_>zopr0EMT`Q~&?~ literal 0 HcmV?d00001 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/metadata.json b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/metadata.json index 2d4bfe30da..5147b8612d 100644 --- a/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/metadata.json +++ b/test/unit/visual/screenshots/Typography/textAlign/all alignments with single word/metadata.json @@ -1,3 +1,3 @@ { - "numScreenshots": 1 + "numScreenshots": 9 } \ No newline at end of file diff --git a/test/unit/visual/screenshots/Typography/textStyle/all text styles/000.png b/test/unit/visual/screenshots/Typography/textStyle/all text styles/000.png index e8d25e8f75d75dfa2fdb3550ec61fe0462d4b8c8..e732fffd0db08c2150b5b59b927babcd324ccf05 100644 GIT binary patch literal 7288 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 literal 6856 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 2; if (narrow) { - scale *= 2; + scale *= Math.max(ratio, 1/ratio); } for (const img of [actual, expected]) { From 96c616ace1337f731cac6537c6e568b74926b159 Mon Sep 17 00:00:00 2001 From: Dave Pagurek Date: Thu, 9 Jan 2025 16:58:36 -0500 Subject: [PATCH 20/27] Fix backgrounds not getting cleared, image sizes, alignment --- test/unit/visual/cases/typography.js | 27 +++++++++++++----- .../000.png | Bin 3399 -> 2722 bytes .../001.png | Bin 5222 -> 2681 bytes .../002.png | Bin 6738 -> 2597 bytes .../003.png | Bin 8660 -> 2508 bytes .../004.png | Bin 9547 -> 2482 bytes .../005.png | Bin 10389 -> 2411 bytes .../006.png | Bin 11422 -> 2535 bytes .../007.png | Bin 11556 -> 2491 bytes .../008.png | Bin 11492 -> 2451 bytes .../000.png | Bin 7750 -> 4897 bytes .../001.png | Bin 8731 -> 4733 bytes .../002.png | Bin 9141 -> 4654 bytes .../003.png | Bin 13219 -> 4849 bytes .../004.png | Bin 13209 -> 4638 bytes .../005.png | Bin 12361 -> 4588 bytes .../006.png | Bin 15061 -> 4811 bytes .../007.png | Bin 14708 -> 4615 bytes .../008.png | Bin 12961 -> 4565 bytes .../all alignments with single line/000.png | Bin 5381 -> 6168 bytes .../all alignments with single line/001.png | Bin 3910 -> 6858 bytes .../all alignments with single line/002.png | Bin 686 -> 5708 bytes .../all alignments with single line/003.png | Bin 4423 -> 6011 bytes .../all alignments with single line/004.png | Bin 2435 -> 7107 bytes .../all alignments with single line/005.png | Bin 686 -> 5779 bytes .../all alignments with single line/006.png | Bin 982 -> 6227 bytes .../all alignments with single line/007.png | Bin 837 -> 6862 bytes .../all alignments with single line/008.png | Bin 686 -> 5765 bytes .../all alignments with single word/000.png | Bin 5381 -> 6772 bytes .../all alignments with single word/001.png | Bin 3910 -> 7527 bytes .../all alignments with single word/002.png | Bin 686 -> 5100 bytes .../all alignments with single word/003.png | Bin 4423 -> 6816 bytes .../all alignments with single word/004.png | Bin 2435 -> 7527 bytes .../all alignments with single word/005.png | Bin 686 -> 5100 bytes .../all alignments with single word/006.png | Bin 982 -> 6860 bytes .../all alignments with single word/007.png | Bin 837 -> 7527 bytes .../all alignments with single word/008.png | Bin 686 -> 5100 bytes .../with a directly set font string/000.png | Bin 2247 -> 2220 bytes test/unit/visual/visualTest.js | 2 +- 39 files changed, 21 insertions(+), 8 deletions(-) diff --git a/test/unit/visual/cases/typography.js b/test/unit/visual/cases/typography.js index e079b33aae..32dab5ebe9 100644 --- a/test/unit/visual/cases/typography.js +++ b/test/unit/visual/cases/typography.js @@ -63,6 +63,7 @@ visualSuite("Typography", function () { document.head.appendChild(link); try { await document.fonts.ready; + await new Promise((res) => setTimeout(res, 500)) p5.createCanvas(100, 100); p5.textFont(`italic bold 32px "EB Garamond"`); @@ -152,16 +153,18 @@ visualSuite("Typography", function () { { alignX: p5.RIGHT, alignY: p5.BOTTOM }, ]; - p5.createCanvas(300, 80); + p5.createCanvas(300, 300); p5.textSize(60); alignments.forEach((alignment) => { p5.background(255); p5.textAlign(alignment.alignX, alignment.alignY); - p5.text("Single Line", 0, 0); - const bb = p5.textBounds("Single Line", 0, 0); + p5.text("Single Line", p5.width / 2, p5.height / 2); + const bb = p5.textBounds("Single Line", p5.width / 2, p5.height / 2); + p5.push(); p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + p5.pop(); screenshot(); }) }); @@ -179,16 +182,18 @@ visualSuite("Typography", function () { { alignX: p5.RIGHT, alignY: p5.BOTTOM }, ]; - p5.createCanvas(300, 80); - p5.textSize(60); + p5.createCanvas(300, 300); + p5.textSize(45); alignments.forEach((alignment) => { p5.background(255); p5.textAlign(alignment.alignX, alignment.alignY); - p5.text("Single Line", 0, 0); - const bb = p5.textBounds("Single Line", 0, 0); + p5.text("Single Line", p5.width / 2, p5.height / 2); + const bb = p5.textBounds("Single Line", p5.width / 2, p5.height / 2); + p5.push(); p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + p5.pop(); screenshot(); }); }); @@ -218,6 +223,7 @@ visualSuite("Typography", function () { alignments.forEach((alignment, i) => { p5.background(255); + p5.push(); p5.textAlign(alignment.alignX, alignment.alignY); p5.noFill(); @@ -242,6 +248,7 @@ visualSuite("Typography", function () { p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + p5.pop(); screenshot(); }); @@ -273,6 +280,8 @@ visualSuite("Typography", function () { const boxHeight = 60; alignments.forEach((alignment, i) => { + p5.background(255); + p5.push(); p5.textAlign(alignment.alignX, alignment.alignY); p5.noFill(); @@ -297,6 +306,7 @@ visualSuite("Typography", function () { p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + p5.pop(); screenshot(); }); @@ -327,6 +337,8 @@ visualSuite("Typography", function () { const boxHeight = 60; alignments.forEach((alignment, i) => { + p5.background(255); + p5.push(); p5.textAlign(alignment.alignX, alignment.alignY); p5.noFill(); @@ -345,6 +357,7 @@ visualSuite("Typography", function () { p5.noFill(); p5.stroke("red"); p5.rect(bb.x, bb.y, bb.w, bb.h); + p5.pop(); screenshot(); }); diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/000.png index 06d53c4a5a4156dcac1293eb109a87e2cc8bc81b..7dddf410d4606f16b8b745a142172b04f2fe7f41 100644 GIT binary patch literal 2722 zcmcgu`8(7B6JNz%AdrBCInthEGdOaC z7yM7Vw5@OqSCGA#G3aIYi3Jdd&(#8Hgbs0E%EtRzj~)LwR4EvDT7w>PGUu4IBzdKr zR#|Mio0L$3KYzrc%UED@R6QsDlypcG)R_>^`xgp7>zyD(*zbL>t3F>E=lF4QXL-oQ zFX(oUR%l9f5AFWx(us(zt6`NrZec%bw@2@h$Yk=-nVFAj3_AOGT2n<7oa+|0( zW5f#_{YeZDFn=E?+B4p{-VU57u8cg$pCOH#Ly052nuP?Efw&T~geUbW*Z%;>lLzp4 z{Ko2xnF;qC>fPmo0umQqppsz`lg!!>ODF1`pdd&9r7zX_TQmKUwqIYvy&qB&X5$RF zoLv481hS!i@kyi)JFemGg0bYi?{$lS9ah@Y%d@Zea&E~@B)7)xiLBPCUsIMPyDduB zntC%Y-sYX$U?oeWGvzMdIBSO{l~(ygXf=I1PY0FP)jcH;qUB=a8{!_aqaO0-Yv<%B z-dn59dvJeo*yxq}+X9PpS-Sx9){7>%fdawJ4ojuEdl(R@$FH^(mf`Fo@JW zsUQB7Q6&$o=sr=pRwQ^*JN~y=3y4Oe9f0#c0!$^f@5ZxIPRgSLzILDF6A%zHV5T$H zttqOeyMlS836&~9?TgY+GeteL&v*o4^O2N+V%!B1fpFlNR!|Xi)bW+O_2FZPy#9W) zbG4TMr-L>jh3z6+L$9u}v$TTVR|9iAU@$yR6*fD@wVjB z=lb-}jc?NP=w%Pgb5wFchJuSKP(~|>Fzq13<_GNk*(8xjNCt!9;hFF_rW!-8!!p5K zvc|CC96R_Tjiml!KgfjfO#5CLP%8cF>RSu|M<7I{!A?_PnMbuDs~#$;KPTV4^M`u$ST9sr;x^+M6jD|#4( zt5wLDLtpBtlkwY0;%cZE2}RdBLkfj5O&;Dp7>+x=%AXM$K*GTUGjzCw^bCTRPY6Jj zANWr;S#y|tEVBvNw9eJfMkPU|W#`G~esXrDpr%G$1%C*5z*BC3YY6q7w*7k*S4H3qt1tD8nPy5MGNt8fLv$?klhS|wL)zK!Nq)sbjtvbt@w^uHZz*rwT5OBgz1-23;r^hR}dtr}ld%aH29` ztLpaQ>!o($(S<0hMVk7pe^J#f0EcE_O8bPv5M9n5RQ2*Cy$l#xg@b=DX;qy8MRdX0 zxMhLR0QX7ih;xYc;4YQ_@Rv8~@3KT{9H&2*oy$6{yyZconI zMV8n`M_O0nI;@QPC&n>evg-38=B>>mp`Dun@PX>x10vyZ>`JFs?uA(oKz}s!vfp@k zT;ehP(Gi8Cc6P?FMwFVPAv*S50ZAkEA%>1Z^YN{s?W^0xk2mhFr6dpFT(1030~GBS zu}7b)4VKou8XDZkfVy!V&WHX^6+Li_pP>Q88*XBAtP=ZOz{%qU@z zw$!Z7a^nGDVb^JK^Nr}NnV0d5JFlxg;V{zni-Jn3*%~VGm_qA8lT(x5in-(y820V* zNa9;bO0W56L&wKz4pKTiyaqM5C-+@2PtN>&mS^ng^Uzp^y3rcL3g-(%)Wi~~Oe&U% zq}!5PFl{^;iIZ?(K{gJ!(wAE`Lfr=oao9r zBCzyL&cP$zI>!afonU=m^9l{MUom+7Ip6_$?{zyh-*%yKyv#wKHr)~qb~2tm@TmLU z9_pN$>idWz=9+F45>kI|TOX6jbI&GAQ+giR8o+WG0j?Gm7dlkTX1ST|JXMl@J29|8 zR6YIY+I@PRphc@8^yW7&)KsWB)kFKCmAch%S3fCGuXZBB}Hk-I0%Ey_-%G zhJX0ke%s^XYH8+-{}Tq)k*#u~|3f3_ zs`ZD1RYgT>?)jlFH*(+1jC<|Ma0^82`;?91Qa)hXm|)V^8EMa2yUTLK%+1Y}{!y!6E17Ic)AYl#ervj2eq3;- z?oCpnF08qh3%4&xpAi1Rmod>27&bV-d8FLNEEKe&Woq#i@+bb!-situzbNNip-vqd QoTn3HVQPbXX^bKK7nPSU!vFvP literal 3399 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 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/001.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/001.png index dd671cd3eb6322619d72de6ece236d7d84a486a5..0b6c23cbf6a51cf2dda35908b8fc8a47e01acf4e 100644 GIT binary patch literal 2681 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 CaSWaS diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/002.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/002.png index 070e4fe43091e7954d832425af88da863dd03600..6d7b7c1288bc0290e1519c1147e36a67b67ac985 100644 GIT binary patch literal 2597 zcmcJR_ct317sth@qNo~e2{mdqI%8DPme`vhMTlBKgW9VE5f7?6Hf{7l6G2j{cI{|u z#E3nr^%gN=6s`H>eSdrZfaiz%z4x5Yx%Y>AzW1D)YHex6&nwQ$#>U2PVhpimkib^g50N`MesBR#f?KHw4?8_%o>sLLoY5LA7~K;NkdxM||*<4ODUF>t}J1d}4HyEOk}sMaYx+0V~! zv8y*vni>kO*?JF#+m`_=Ot6G2lm-;M8` zVCjpPST=`nb$cHlKA5V|M|q|fIqncQxXUc~+oxUN+i)}@t z(S{$7x0fCFHvhx-!FLE7`{+@Dx?qjXS!qKZi`FTTDRlfoUqR?XpQOs=%QbLW1mWW6 z)*3~`y%-V(!|6BMtg{O{Iyw@$aKXyU%c~kSsjd}&q%A5ULfcyC_Z=g)GBmm-jB^%XlC$FaRuHz*#pJ~fMxCz z%X951;Lt^DEMT3D#3QV5Rk}SzuylWyso^(0@Ycw8X|Q;HVZrFa?YMdTuWzkMv675G z>vKt~Ob_alfySt<-xDRg-zrEX&u1GED3q#2o_faeX)>6Luh-PlvPATf!@Avgeb{oO z0H?KOfmWx!Ty(WTy4W>qZUNw%ckh(2DC!f*SA~Ur$H$8UatwNzV-+-dcTJLCN;`Yq zS_YwJcAe=mzhu2gq^6~(zlAr1Z;(@DmIsT?z&?GzwYh-l`pzv?^NPUP=HB+1nWh+2 z2$(Z#U~9T5CQCq43&JvC#DxF&B{@V?ity9&b36_X4r0B9I(Y!SCbZ}9JDVxKrpS#% z#a}uxJM%G9wGZVofHw!jKV`39xEYMu+}uR==Bic4>;|mOO^E`&7U-q9YMdb*9K_~= zea~1m+c1;31tVv?3ZA-KVn5e4Bt{Oi_L(OdD@vXs5EjGaT2)k3iZ*^wZ*i3s6(#EF z>(>?MX#|$6O*d$aGXNYXtRWE0FPJsAf3ni;`4>;P0k)1IAV-9|Qb!Osa-B0Jb)RTo z_Tb^=Q!lf>$*HS7+6z5u6)tU%)yce-EYh?#<{|SFdR!$Cn!m(UK38BnREx2byW_w)q-ltzGF1YHo z#yFKSl|Zix@rjcK-UDwHXDK40?1Ox|I6?Z;(h`THU|tw|CZ6{stfX66Clf7?$SFdj zz0yd79y~0d{6C=b|KRZDk^SLhU}MOQ{e{=cYHB!^Sy#c8BO0MyQX z%6TaWV{Cb}a*1Wh#zrubCf%m@(ajwXndv<}^-`-mhi2@Fv}_~(hy#i8l)<{YMshnk zAkhcEH#B-XzweB68~YiXJjd8u-MPBwWEJs@*oWz254W@wa98B48Am8`hC3r}3509D zS^4Wp$=GHv;42cQP3RXUTURp7k$d(8& zhV2#bhKW8*OY~jpLi#a`bJ=c`(NS~S&m4E0{DGuCg@%pRc4zx``YrguEkrUr$;;a+<>y}1p34cyjxSWfsBj{Fzj~3 z8n8G2X4OD_iJOfOT~X1_-XT+4l&H62^aaxuEbs#UJnrcrt6RZK!p+ghx3zWnS>7dp zEggYdnYB9hJge0t+T-;MmL@L>tiVcfgox++Bxj2W*h&bA8EOWO>varl#E-+%L&O;m zE!*AV2WG0ldkv%&31`h$sBH#)_^|YKtpGI78{cD(WXheMZDyLU^a`W(L2wC`=QlsF#p1TPN z^UL!qHp{W6YiJ>LD(KDIc)X{H$#cB5j%)OE!WWNX&vNT4na#c#=weEUy}CtL=rzO%!ZG|G zIJXRr)v4quAP7)5k4g5-u0H#5Fu<&MPkeHO7ZlsX9d2T3Q;DXZRcZd&PdkJmPuhMe zu9o6jZ_-uKUBo8Rqvv1UvMEQSizhg8C(e?=VI+n(4~(euhVTerW=ACkWd6J8@N7ac W&c!y;*_HM8v6&cHLMrqSiT?mAm+{8{ literal 6738 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 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/003.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/003.png index 28a0d29a3ed6d699a671af3c54b0053bd2172bb6..8a87de67d1e057573fbbc95fafc6871c8f0ee8d9 100644 GIT binary patch literal 2508 zcmcImX;c#E8U~6|TpAU{aVr~3MQp*fQFF;O6?Z{!#mJP*(b5dsT*9SM)H2AuDMCd_ zz)7?+_p-EHa?3Q=93?e@+{*3Jk9*GjckiG3<6X~t&U>EoJn#9wTOMwXau78L005A4 zI%V%AiFApbk=pgs`@a!N0x-tQ(GF1AsUZLWq*I*iZGA{V3q{29uCA(W+co9YP*ydy zJ}}78PUjS90cyB^z zy?2gUEL_owSrno6_lzDh3ft=9biE~?EshBcZn&`t(SMkbr5r7dJ&y6o_l8JeK}m)Z z&wmZ4La@yV|DSvf%J$_1O)Sq1@<+;y{fxowG=o&}bO&r<@^rwoH}~Sji#D|=*+;5s z<||$`hULDTt>L!W7_K=;X~*}4cCbzA#tE~~JwO8hK>v#&1bY(gR%ze^1iAotCxO5Y z6&%wO=%UK~cRrIyD_XFu;1iXi2^XQ*`_}Oeu_)OsYKBkZ`?NHv+JH(BwfWiQ#nG3k zd-ndKtejjG+M#AP+LpCfWNHS}e(*p~Sq&l_&C&vAY5+m9ha3}^1--hht*?^w`*YGE4{@Fz|dxq3eve z7g$|2JrrD@!6+2h!+$Fpb|NiSK^Kb8a};dmnQkIf&;y!h=K?0~0=kNs;f)*SyD zdDx)=LbUB@XXn&Cj*TfES5?{IC*jJ%4WA0=j{Q-9I7)J=1m{3=s3-HYk0T;APV z>aL)qbki(q^mBzS9&C<%S76pgGw|(Gt3X#^K0Lc*;N|6YmnZ#}!whA@)mH%uJO?qSIgmh0VCP5U;3o|`R8q?+i6zi_F3e)0mEs5IW@-lI7#>yD*5G9 zd(GjXDets?6S^+fymFVE8h)rMG%Y>dySHz=>1Kbld(rR7C9VbKe+Mt2!a56W?;Q%{ zl0>I{SY9W|m5DocPxdez+m$+tEC%O{+vB8h+gqEwur4iN2MgcxtiOkGhq3zWw4FmkLupxAzT2g`j2U(0nY168w!O!GJBU}#DY3k# z9!wyMv4;NqR>__lt$YcnR8NKjixs)G@jcg=sE9-&xzQ7LeQcaJnOP^ZqU&CaAE~`? zuIyTSdS>Q|s(Z|wHhvR`zce=>XAw7VBY4m344C2b$W{-J+NOfGNxlqB968KKyBcl1d}%d^lQlyXntK|GEn;UA0-whv z4#7wNOqh1n-t3A5r`Jpn3CFaxf$J*^-bbKdHnF#aB?MRv{#c$vTfexvikV1}2xzMH zmXdSwiBx(0wb=b45dFCM=(&&b^ip;F(#D!-DtxTosxt6-%GU%!Yp+X$TG<31H+x;QegU1}u=P94Mx%5)@6r^YHo9tolOW+y_E)=KzqjrnEl zS4#hczW$fBBkotOv{#1o742Tm1vFV%AG9S|7=@B4`LH7&I~ko4-Fx{8g?OejZEMU1 z#x+K7;NHz>8FVXRo)+Du(UKK@b0~W^SH~o@Wny`!!HN!Mu@DdFJ)YH#6IidE9mrt*&?9q>KlzSX!!TXt43) zVU`rq)&}{^Nr%bBcLknE{Wp4g7>jL2)6ePOey60$#GTzKdcsvgaqM!-~! z8@J$*jPsb1Q-+TS-Os@Th(xhZ8C7{>^^;tKQ3y@2e$8>`*tbTzs5i-$T^}UMQ?@Mx zO}~s#;fe{|I%fP)rH?S_3d`WG&vKU?OfExIZr(AC?eP zd|D$tl6PdjyE?*`)_0pDh1~-Gq(gj*BY804eMiXRGbYNdM&x`uLA0?y0<&`rA zupm115%#=aW0hX6&!D$W+cRNi&2{6!Iux;e+xu(l6A*|_lreu25A1l5Vq%2=c02)Vd~8UV_Gro1q9=rY z1j#Q1H(o3Yaoyw6h>QfLt{lc6>*JQB9>C}E6HctdxEklMy)BAdlz-!cO&P4b30n{% zjV&=8@7@9Zph$|9s|FMp}4LFO~bd`g-KqcQZfYV7g`${`} G(!T%_Mzoj! literal 8660 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 G68{6IM4m4I literal 9547 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 R(cp9xL`6YUzFZa-`agfrjNkwO diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/005.png index 07d8191aaf6504baed71523caa26a95db7da695f..e20620541604a93acc85a318c6ca60a0a3aa9c9d 100644 GIT binary patch literal 2411 zcmbtWYd8}O8@Ae*iHs&X%nUIb-d0np38@@1hca`XMhtC|LnLX@hRT~`ByV~1lFizt zBxkBmD0xlJ=a+KGD9xHf-t~R&pYPvyUEh!AdH&qjb>Gi(J=cBRDb9qG%8(rpIXO9H zJ6ju9+02nu09gKK_i9~~4Zua$lh$(Fj$Jcya*FzPHdbdY`Oe>`+GcxbwrC5@23v#q z2(RFsX?)Z2r=HX+Zy2Qyke;d$$csg1Z>ojlYammp53ex7^fBQBVM7+*bW{hZ509VS z?^$OYQv7lw??vw6k98}vmqnqu8vvK;h1G(KKNc1&KGnWAe~)@35C~jJrHSt#NvfE8 zuwrw!L^2ep3sJ@B3c3uNkeg3zLy%4c6uU5v%ilD#6B=S?f;r2}KR9 zUy9_Kut@YRH4K()17HN&5O?U40vcJHfbA^KetX`VL?{TH1NES0k?#O>A$<^{on1WA$s_tBE9{Xw?qVHC!3Si zCBULg(U~8|$GfU7P;d{?I-feAn0CfMyez$%==qE&WQ0WIGb1cXPfALPKfRe- zcXgxw+x(!r=hI*vr{65Hm*)ouyECfuP-t|fN5#3;{)(Wfu3`r)ZRj91>mFJkg#xl^ z83Pw{8DgQ6U`{d`3eu=`v$s#(PapA)77fi9l3*}c#FvTVDe39%drkc6F_f0u`lRIt zE=SSCMr%h+$d~I39U=bPrRNiKy-&VMmx8EWk5W|f>LIf?j4z$+d)(nbtlKVWWYb1! zJ!nH!Iv^0J&;d+bC-KBIG9^1Q`|fwf%y!$|tBMncXdMiHQ1asL;=*WypP-^5ur)(paDLEC9FBuA+%m0I zuFwof=H}+uh)LV~@h?R(j>wUz+p+%E>8-JjfgJ_r0{W;$!!^(6$})KVzu{7;6dTs} z%Wq`Z_U-M7fXz=!=6cFARdydbGdNdTYN#C9MM+_0rWK0)vCd?F!&l)7!He?Dl+}sX zY4{5!TQcvC>6+pEn}O?1JA)jP;p{!hyH;wANZ^CZvNI0!j9JzEby_t3?(opqdkO#p zw1P%AepRvt26YttIjJtkj60bQFYolJ3b#5-p{&chn{PV=JawL34$(;b;#Nr?<s**Y9B05{M$XS2hPnDdx70kO z+wfND<;xhGcl@^*xw$1{()?OV(~e^!AK31JGhM~i59WQ&brd}Q!l4aUe+Y?Hkkluv zd;UfGev7qscQ2)is7byNPjvs$Zp!f4q~F?_aBmwN&Rv4PDv)y;tUMo8#ptyhDhq7S zVd%L?@<&%C3pnT5dJUys!zvAcG9P9qo6?O%-es*=t$WtIFW*d?OzkVX7Z zVb>2_U359$Xj90+!}rLbGvR*OP>h%M=9pirr}Rj`cH&P5G@s#vHJY&hu}i#06O#0g zx3(Z<5Y{GNMRp%KM%1FMZ*1&X9XT_x?+LH8)V7D?@%xP5PP4F5aeiUSvhK@IQ|-AC zb3MjBpy?0nTrwWJ-!vWIs?PA@OYwU+XX~Jc5jm!QCR?>F*8F1l@-KAEh(gW2N*#u09I+5RTH!lxG;{A&T#*ip3yK46ERBs7T7QSj}so7*OI_i&wAX2Kd}^W#yRU@NEg~jaA9b54 z_gBUhQ0q%hD#--EIRg?wk7Iq{ZB5S;zb8Q_rzi0y1hup@^Vk@OQFo{T=^BBQoZHsc zmf^-G#uDx~d3X$}t3B$cH$XXL0NPoR{T+*Nu8Ekkchov&bq;!CJShoC^>Id+z-vG1 z5trjQmiindQ=OTDNY-ARf*Sff4Zg$GoJQe>@;_tFL~l*TO~D54@KPV8zqt5m_A&0D zsko0%QBzl6+K7y2d{}G@nO0<*`qusm$HxVCufIxB$I2X<-h(@~v^3=qQkE4Euvp%S zdR1SN(|#4D&Oszp5u%Mt8=Lv8gP^;wV?jgjkytEt z>=qwqS+?QEX@@Nmc-Etku_I>;>ZdCiuN6*#hGfA(@V~@>|0`dtD|D_$cqa-)db0E+ NXLp=n!?h+e{sz_XY{>us literal 10389 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

FWMm{^czF0zt@=d<1cEO2-?IQI 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 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/006.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/006.png index 2bc19e4804c598dace603ec90b2cc05f81966c1c..1556d8c47fb78ad646b451af5fb747992dd90e30 100644 GIT binary patch literal 2535 zcmbtWX*3&(5>7&@C@mFxxmxOx*xHM>_9d||MKnc;wZvL#ZD=eNM7X$7OHr<+#FF4y zizv6QsHL@4?NW`U_M%$L%RBG9AMgEp=lz(ObH155vz(bZlWc8i#KR@Z1pokeOpFa} zSTdVM9_P>flRNfrvji~2#z-GfJ0!je0B{zY80y(YIByh$dm~K*-gXJu!tN%kO0}Cf zU53D|^(Im3waIihFm)2uUF%()f60lD`Vw_YA*3X&=*XwIZp4+Ktl7e5(cN<;IQ;2_pdtz3Rmb^DYo*26+Gfr1h_&Lj_Qgk&#I$X<>!Pvs1C} z8_mJvN=C7y{CvVnj&KVgRagb&J6Q`iHa1Q^7rDO%`PAqW&jJ?z%DBeDbai!cDvTX7 zs@tDj?{ZYwDl02+`&QAYq(GWJ%y{>E<>jiUbli40QNNw&(f}FRLxJ;xug?>luCk^=@>(X0J1CQMCqDiOpNyCY&-r>f)L~Q zXbtM)#Fvp=NS-JO_hCYais1RoK{4R>dFNLZKMe98{T# zt8C4*{(-n-$#{`@@yZ=(+r{Qb%hMrqM}ltQM5HL{>%F}%gH-HM@EG}?m4$6jB9HB? zR_L0*5`%%P5-}=ocsN}0@fN;(oPg~?4-}{`~3BK@#kE( z<~l&xw%tpAg>25;{uMK3TvIpK^)$V-R2mGa=qonByA2m=2`i&3 z@s~RGd(ggmoR^G@1?>kSk83snOGJK38t;sLBCZ)>ZQ&1-)W*_2Qr*YLnt~Sf%?s{8 zR##V1joy5szk0t!l)d3TsIV$>Tk1_-bM9P*!{KteS`gqm2Y~!=xbS0Zh%BomrBOe3 z7)Gg*IuiM6{x)cfykAXXo80?&>o87jk2#(4IZ@7KyHns84Y&QxS+VKnz{B$spZl|@ zj~IwX%(!VyrD;g*!RjbS==ubNf=whIrqC5oFSwp7K1ey*V_v&{9no?BgUq5L*37BN zFBg=hNL(8yKS3Il>(}w$@6?5&WtO;+s(w$3M)o$^5v@j9{fe<_v(lxFl>DxqTNOVRi*{# zVD_a;8Zn0o9-aIM_3-e(1;%05#Z)l@QTuCUf?u8qZ86>wd%g_jk1rLV`2;&p-kWu@ zR97viF_u}Zph}^2_1_!#s$qSpB)dru1d3(Rg zYl^t|^ovfw-UuzB96=Oy5zn9D_v^?9bem^s^ls(>yXY)oU;nacyulai8j+ru`- zPV5o#hw=5B%;6%aY+#0(bX&KYmo^8%>eA7u6)x+P>;p8T)z{!iV(c)eJfszYfI%}k zQTBHH6hE>wdMexe-#{kcK$9sb+rQtVxBhA_&J!*pLj5n34;pT*m+g&YWXapEh^XxB z2L^Q-Z2LKYZY`bbdJ%-&`dI^l`pEQ1~c&0uAh7sgrI^Hp_*+-h8 zmcwkkysjhCC2G{_xS!WPXm?wtlaj=4BKYn7OUfXyr&cJ>p{2om^=?0j>*O2yC9DZ* zd3x5FQvA^8Ln)_X;xj2_tp_)X{b`;8uu)F(%wsQJ#<$f`B;}W$h#YKp*G*ge-AdT~ zM~}|CH1h(B+`If%e81WB70#kPdvD}Y=&BNoFCw79ze~h(u(7d0E*z)oB?&1y>3SKm z$4u3O^^%hjderIf7kRS#6Of53mn0NF=JNG=+a3LdYHIG)8%1wX)P_M8;?2Uj8h0?MZaWQtsUg;Ffp(+H6~_PQhkS==%aEsA|Hq z0K9}&)T`38t8m(`66ILSl@y4L{&|3`O=Mlr%F2lmEuV*!+=`Yb)NNC)?T82;X$ z`?Aa9qFU-lzQjY*9Z7HtHDHObX-hdavW(;(Wj!V33JW6#U>II>;&C%OY*aAF`zI*d zfXBDZ5tQx2eXB7VI8dCZI;#L2XatLY>clNu_vCG6<2*lsc>P^y!LM8`!p&$m{DJr; zCG_nvN_o2sI=2aDFfBw8$Dl@M`6=d(wBikJ6t8OaY5?bdggXUyCqSH}bY=2bpBumg LZfRJnkB<8XzUadZ literal 11422 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 I(y-9~0ZBG_J^%m! diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/008.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-line manual text/008.png index ca7f62d287fdbbb2572c7aec25010aa659bc22a8..169c050835a524dcda399a356393e9470dfa23bf 100644 GIT binary patch literal 2451 zcmbW3dpr{g8^^cI^$=n!B{7M1(~-GVBt}Lug&E6SI>(IUQn@6o#nc&E z!~^7H{)t{)3lafFxZ0lpaC$YT008+@4z|{3qt1QJBcIH0-1Tx_Lk|RQL_h?V4o$qx z4A${t*INcypLJ11%0=rg+jXL`-^0goe)Ul_gee z-?(>X#MRUDxwV;F2?lx5tgQ9E`R?wG?xSa1+}zwU4&i_~U^yt>1dffs0;w34dV}NK z`d8Ru5JNE#mp~$?W!T9>G=xO}UOyC`x&vWUfB{lVG48wd@Bzme+dz&CwlS9bDgh!b z$Aoy2(@AMSq=E_pS=VpCgGv$9wef_2QXCZ{Q*S_m zbmy9%>CHQ$@4@j-tMz}0y?B9>UQ(ihU=ZGB6BAcA=Ibb*dt(w;XT^sd930YwLKktZ ze=?2>gTp76CIvh8?W-|<8naq?OXF}7NsOhlUa%8rP`*Ggr0hCScB(Y&;|nx)bMa&H z)vZlpwlNvX5&1cpA6yNL^k1$wL){m5y-nKA3xF zr>=W=cwM%_?|$f@!IMlB5k{lY>U`T}%r8x+fBO6HN^+e~%Qd68ACXz6q4~xXQ8)2d zU7eA6*u;%o%Q(W^Xw!pWjJ>_1pI?!phEWHcw5yauY&xKJz^PnEme+4hXPHz}-QrTE zxk<|VIDo15EiLa_;#=%aZPzr@j`-Z0ap#W8`qCsL8~c4$T)YIV>|@;MqtVE*Q*0CT#=7}WB$7<}{Tulx0@Djq+_PO?C z<)KEwHTixJ^N{x&PF3w>|7Dw=|;B777ye!O$$E-f#gf5Y{?M0NA_Mo7shx*&;7 zm#ga~=O}W&GCxK%w=nlhp?5v6VEG!kkbGesk+OjcGRd@!A`Ii*HI&mm{D*c^^tGQ+ ztJh7PeNuFphBU>vb9)hHnz7$zJt-l=*Ql*@O3ZSkY1E!t03^5I;t|q@G>ZE0&%Vkg z6hM=onv#MO5*s5O{QUi&TX+z``|(Mwi*CV}xBw?2dE`;ZbWcyjXn-_ZRP9w|+E!?j zTnSx>?Vzjj4KMv%3zHritT;0%EVNl|_NI~6r+sZ$93&E zJwwCOi5|lfd-sU$FL8WYP>xIlZqM6%@{3yQClr)1#JAVCiETg?=jQV&*j zX%~w@@B-?v+b&*R!=5N%pPoJsihl(A2SZ(|43aA1e>4p5fZ`>r{4XyxYvmxk{-W0S zFq#~`6WFxe^6LPZOzwXg@!8^|0^{b*fYs?C*iXu@AFHcl0|U5t+qGxW%XV{P&#Nv2 zV^*j2-rQE~5)@xQoBY8&c=IN(>P={eJpH_Y*>z9<^yaYltTpF$Y6c%o*~JZ#1~n}c zj@>?QK>}~w%F4>3Dp7KiT9eQwonb-S_PjosGx1Tcwwz89D>1;a?yXef0I-Vwg_p%S z{Acg05{G-A7RK9yer&8Q7H4ON)$7~Y_S)Lm9Zpys4_huV4+&5?$_el z3VRfxa*u96F4?}jYtU_NyLb<*U@%)M^?B=%iXQ<; zJ>Mv+NwDOF2foa{0O1*pN^M87Napqar%V~7tT|vZ^E6lUZEaZ&hU@e_!A78u-~JUp z&;!Mn#kLkssv(juv#0)0MGPGKAY77X+8hx@K9pllXd-~PNY-unl> z1pq27y2@m6hZ)z%>c{n4=>9_gk<36kOn3G!$hZ zJ7|Hys{62=9ly5{l{X|LNn~pXwy@$v zs&Clr63C%>$TuBiNj6(3TL@9HfhI+85|yEO?{B4VJ2uSzXJ0i|3Y5=!yJAWr=nhjE zz`m0g2%uI<$jHd}O)UPvMM>XGQcAkyyyGQdU!ihsyHu<{hTa$gG|IAuq>9?)rCkN z+(}souXlNgshH4j$z6XNO?u**A;BTPd*OF-qV*OB+s5Ym%G69~!}OG0%6pA-@=6#2 zd{l8ZZ%%2h96KhY(oh~rX=;YIM?@3~7lsfhN(Om5j4*RR%ExHH$*Mv9lezwta*_T` zKmL9}Ko1cf9y=XQ?f1onaGQw(^q|2@?%Y8%!a_s5c)q2c@cpIoL6(`S>)S5;|C!nQ_39 zzoS81GUuTHDOX@Kl-{Le}((=7NE(#1tOiL5}K5Q9#aCqp$z{nWt z$LelrnU8}NR&#ZIEm?KEH>qrnhSZ0UR9N@{ymi_$JW)_??e4+7`1K_R9x-u6fkqLY zrQH?3|mMRjSiprD~)5_juz^?wOF-{ z!8O^!++3eh($7a!MC4OeV4!q!X{nvNs%o^lvojAXJ^k;MlA`{ZFA=z7R@_c4lu`ZW zyhU33ca@cu_*+|BW~(h;!Md872#k!34BFb-#agV1sAg=;%r^@1@(kb~)GF)h%8J1) z`v(TTt7~Wksiq6#?l7>TO-xQopHSM~UmZdF&Cjv-&dx-m*jTwm5+Xj>*zmG*a73Az znqDZ=<9Ux}h(k|3eG)1v9PMOfgFBuc@A;0Ge$nY_Xz*qg7o(|bY02fQrgp^`=;;mi zARks?U}E~_IFnXG&Uu&_FB5&z~vH%5v^nT6!2LeOHr$aJf{O%*xK*QfoCz zdEa(@`l||zkHumi5s;x9HZ|iGZ+-X`^SlF-9Qudm*wv4gnjrx+p0L;Wh zW5Hm!^z?K*4h{~Xt(_gJj~*V+fhu`uo!$|0v%k^8EZu=l!W7!uk36!9fIg0wFD}fO%C$#2Exz+XHlW zcXy$|!NDF?HMPa7!}-5lG&J#DgS5s0E&&HKOB zgQ$Jtq@@jNcRQHT_&cR#P5Ixh2iDiSmz9(pc+RceA06#M>uSsSi%NFr85oY3+1MsS zI`9YxHgogy{lfbG8vP4EG6Uf{Q>NFz+1T9dy}#ZawiDOCS@myw*w)U*2Ct&H7*E(~ zO{xyS2|41_G?l+x!NP)roxMF_yWeBeBv=Du*Jw_5wjhUL%gu4$N1+=7l297(mTao3 zstz9R?r1Td#;FhphSf-^3nSij?7)D{ZiSv>ZQYMwqAYuJ2Mvz$KV~apQ`NE%<%^0a zFd`!-=WgZ#6!^m^}Z zdOFkTJfo~^nMYn8bhXtRr5X-0FqsdB71i^}P(3g*B9hnc^oGdi)hlMm&us55#Ip`k#Fak9`!HI{#vlTW0xn23W=r?Z?YdM(anq5*ccc!YNzCTuN0p3rB719n*X>o zmV=&tir?#;y=X$i=Qf4Mm^`q9rmog_*;RxR>rIfS7(Uz@!jBGIA_ZG@fY|s>rJSdZgSeQgDoqlm z^uXqCRRs$ewnUHyPyJ)QLB>E&_RGIx{S@=ZkBu^ZGFCdym8_|8^=NJqgpse_#RMiw zN=gzYHQJ}lkAapCZWasS0gKj+4dQ*7l&|z^7+(JTDO-)VT_xAT?KJ8NJ>gdco zfke+JDk_q0X>A>Jb#ogwH8m~oBu5{?;nHuclv7kJK$J-N@k9LA(b6x|_(EnAUt|Pf zQPBnouk&010Q4IERYG=i9cn4IHa2T-l|X_TY;JG6GttnP6t}keZevS6RI0vtQ}IF~ zEg`{-^KcD^_-jJ&=~oZ)R+>2tKd{a3E8dzIf%S<4T zki=#5BsxU+`0((sJ(_s}^0qhN7fx9BOJg%L7Y#$h3=Sryuvf2M$mD9YQDwYV z+l|dLto@)~mzK8p5LigI;&@Do=08_wn=F~Cs?gHXl2KS#xSOg6ny)VG+Y@>%yi%NADhFh$xtas1W#uk>A<-#8~|6sBvitHC; z`Za;=Y`7kke10Ijf{7Wo`rMws*sS8lNN~8kP$k-fn*k+rm4_r+go=vFO<7s_y`9~m z9f5oaO>Bq>%*@-nc@VIQ>o&hfG7bFx$jHcMz-vgcyxA!$=j_~>Hmk}FTlcG)YPG(r zGWw?wo_}IjQyVVmkEK-h=pXb>Txs)7>oKis@jRnFKAf+)JEipZe+JY!qXiH)(aOFJ zxRRV4+1mVkOaBiacCRKTG{z@1j_*5L!QltXD=5%{GLqGfh+MvX26Gkp;d`>uS`rfz zv;Y13_gJuZ%?T(^D{FTov7kz7=Vxb|a!&;Ih&gZk9wiASyzo6RJ_+jkI}AvqPiaxn z3$M}aWN>_Cxo??c@$m5IK^5jkLJB!7EMy+0q>QT3l|`72jFHE9B12mQe>)#de`!_< zNQAE8ZY-5#uQatZrR_-i%eld1uJQbQ#y`33>4Ns(%|3ki;A&z*V`E_6!I$b(|A$9Vu=n|PCsUY)hGy;nkp}gAsIPBl zC{4(*1C-+Z?(XiF3=9m_2xqWn_ajpUMMZofPW?ZH-gn&)my-`Tie23%kW4FjXa0+bIUBO`1V zgcP%~=!gif&AmMq8aB45&QWj4xwO8ZZe;}pWUG}Hug1+y^V6#%z2h?OldQ?TpJ9C) zU%#%bth@p2$zQ^GL(bgCN9@1aKUZTlD)IX`wvQGE6#~CAYvli^H-CQ$qZSajgvSai zX{fFi!5l2f&JIdUPJX7d|LE?HtXpA-G(0>^4VZQ47%*>3)smC)@s0=DN71p;#&!ha(Iy&`i?Ck6* zD5d{)Mw7ud*vi}4+2x0Yq3BK`{rmQKf6a7p3Y*!2gZn5(X?wXp4f&{5ne2IWNXjiJ zhi5)%4xPY=r;0dwPU=L-uR(WHD*78VRbx1j+_YHF>Ysg;h3wM$;lPER|- z)tU8u5z*6IG#2?$?sGWDQxhGH@ii-p=7Xan3gF%WUhnzepreqrI~(rV@#p^JQ|mX;P-a8OVZ2?@z&_m$Vh?)bNn ze><<_pWm}>j-XldzxS1r>bOu&V05#et6Z1%@DNH4m%%|y zbZQw=qFXTnSVqGw$m`XPdlwg%WK{cAKQ4Zz9oh5OwDFYyz-Sg07KYo22_q7wr!w+~ z)0G) zH&iW6P+K1zL+ioo#PHbj6+NDO!q=~=|IW`9xb*5vFFFDdq9g>^9#EH^iq-TMo#o&U zR>v?O&tOLx8F^jm>Oo>n>j1&*ss2{2jlu6BgJTdH7#N6>958z+(i>)O+aOh z)V$xS(%09g9{VM`o+TS5(Qk$+Cxn3%dx_h$-i}^6ng?AF6Px&iP{I`((!CA~3JQA5 z*$qG$4+|YV!P?I5v#V@=OUpy7)kyjaDEsnQTHkrjTcvlFmiF4k#abkKK%Gv^&U)Bk zFFPT}_7(VGEmzu1vpR4hd6iCPWSF&%WRwL+9UmWCo*|Zi#Ud*UJ$M8nrCzh?mZ#t1 zH3jyW-QM4qaJ{R}O;e(;PfkpX+32?%8XEczKtm8~gs7~ntRyip(c|;y&vIBv4%B!N zFiT6u>W^Ck9u)(FJyEQzbIa^R`9($jpo*CH{Qez&HHImKi^%dw-edyA9!ZFdG$7m1 z!H*wvy{c15`7CRhSy%*Srlz7lNq&zkOK=4kPM ze$p3~4VE>;UhYWz3E~VyNy){#$3g2A7|o|JE1x$?v6=roY$>^bxEXJ^w2`#(LPGzH2P1jCbIO7UI+6-Bih`t92{2sxJS zFoKRz)B5gsjwLpg1U)GU34|=BHxG(MB{3x8x{HIB@LVGKg!+AROSHMEDVzWeiHd?E zreleNhGu=!8*NKCh?+|Kn<+`?;K+!Cfd7+^m6FiKMwNnKW!tyDphWMT5sK#*_>704 zHY&WSc4vKo2-m8V;xa!e2YY*w*Umhh?yu|}VtKu<>z<(G(nCXpyE_xg=9B;(*bx4+Au23f%S(a*htYkC8pN#_L)HU?G8ICg z+txs0pN)-;WQM2*rx-1*%%{nGHEmJ%!<2%OlEG;-D@#iUzZ&2Bx~^>6NhsvhpVegUpqT9QpTQ`^QO{ra&iI?fH!BKDK~&Z{KEj2SP zh`=}xtcfQ8W-IV9#2^ae$9U+82S(w7_0hdqL9g+RbDjg21A5p94i(UWzPWVnmZQrjYPSNl#8@ z`jL{tyh?@rB1~48UB=j;(TPU))vLjg>K<>yao9)1EFWJy2Ye7k%}q#|M}*yD$l`-I^O zF(}s^J!)D@bK^mY;N0I1B00BfByyn z1U8_dqoeP0r0tdUvATM2rBYIHA$qeD6DR9}*Um9)@l+3HO7nX5;d!7;@c<&)234T*9!@irH>cusbfIBj;Cs6_S?~1(Q6)7@QcX>K&8_`UZDnO@lC-p4%d4wYM{qjSSYhaO)zxUnWqm>7Iw~rW zuG-qunO9d=#oXhWlKv7N(uTmrD{%ml$6h&mvPXfCXaiKhkdoqJ{d&jMHsT2eV2mOR zSb9+s2t^y4pYJEc{X!}JeIGd3BVVYVsi{lZp)xdd1)|=C*qU+um+wtVDc+jd2GG_UZ z>eSOyr%_-`9r>Sagct*+baIlqvkY`)!+%1-#?DUl^7NE@okfWhBh+>8mkX(lv$Gt+ zUEd>8obk7$B+Iyd^V;le_^;{hw$|1^#C-2uOfcqqw)Z8_}b2n{b{p5fugRiuIudVOkd6K#1%c%m85kvycNqzOP9lL54Fgu!5kwzjsiv6SK}qP};vf4ms+?Z_kcLr;zle{!7y z>%hhTo@7}n>+MKagPyjwfR2{d6u=Xj`s!*8O$CMgwC?pyIXSsq8Kk|rDzo|7x;pi( zFl=WDcXugi>8y|EoBi#w2-rVf3jw;Gu9!29I`#-J|A`)NPashx@o;yyqkGP*H~OWv zh6di7JdGXz(yIgn1pMaa=7q8n${-Y$%()@5FcSK57#!fWtm*`1DypjKbii}v4(^8I zauP0uZmIm@W??B>0J8EWf&5FC?IGvhzh{mU6BF>FqN3__bU7P~4USQS#Kdnt`w$=k zHsY05UHy^7^*asf#Kh8)*v$C2GuP(EcDpY+?OOtTLc)*)_$EM68v+9Z*~nGy5wx)# zEo@Cp)}N1;o7I6PkN_-Cnw`j&CWsoI`^tNC(@+x2${gOdGA+pG3%-c!l5pkuFf_n) zE>1KH8uD4nN)aVsNghaF6X3;5mK(KaY@eKPp(+dSPMoca)V2-1INIDKX!p7O2yKjb zk*d0~eSGZqQcy674V&-*gNa{%1n_4R-Lm&cOo)dl*pzcaseDZ7Lgrul&H2#Lqr&lr zhiU1m`|cV#f*fs)m@Yg$JbDr0_A8~09`C>LPUx<4IreX^lPc9ak&Bl zZ0KiDZIlusKOLRQ-gr(j^54&)XcHjzEx1WAVsaE?2l5IE(1CHS3w%ryq=bGS00t@k z8^2$$q>On??ghv&E;iKHM`HB8zzk&I;*tc>FytrsH`hfteHXBC-L5;@g#H{_VD$nG zn52(rY<>lcBIbYx1_K3D$bp|C+~Lo_z=9v}^3j28^<-mXJHObQECbt2jJk*X=YFZl zZO}kky0g_v*$TOPoX11Qna3m~;>9=GSsGLg*VDC5hDr^fbq?E}pS%nC*9Zs+U+nDc zSoQYyjs(0o0y+<4HV|=`l6$w`$IxPkjBTybJpU#fu@rrkpJuH8XOa&b_vXu79~Z+ z9cv$-7D$N9+4c2xL*`2t#^IqM_STY;SJ=mLK*GRdQVrdFMuhL+CO>rkV_rQD)?^C6 z@VCd&0%1F_N9w5bCIY)nfunZ=H1i%1sHu}5_y;#PH_zT=h{3I!^^RRI(90>9pFcTb zlsvL1Az@K*YOA~)rga6%4%#B?in3*B%A8LZZr1F%gvqo*fp$n_=+Gm?q85=cTW^3&^kI# z!!0IOR(&t^3=C-J7DUYC;B5;Db8jB+UlC4DASym5n$+*t*opv8%JJm z=&>fEmky^11p{vDLR`DP;p}BbC)~Rp@QAoJng zzkg57#f2^9A<(itl!`FH$1Ab;VpKeUQQ9L}s8>G0vfXKZ0%AjVf#xyT}-h|)*0-nu!X)|5q9k{|D6RWjlLR=|IDR{}`+#)Ba4_U|Cy0LG`a+RgLQIyR6g z3EkY@xx2f%VyH;povzD{@9*z7V^fL+h~5NlY?vaCS_4Lcf%FAYIE|u8oG2H{IM^Tf zWk~g{X4i7Wu46LT;>X=zF2Blocxv<(7XpsHGMo@ecvcEI4G?6S5pzZp;SnHK6}(X# z74>_d1yNZ%U-ycuz4Wm5y)@iLVHxH{Z7rm%3OBvoIT-3OcsT!)mo2KfATcWtE~Uv5 zlPDoRP^!r!IL{*aozBb=#qjVI?)AyvseH9=yzSBU<%i9PuFG%V=J^Ee;gNfKetuR! z5c-zbso~=C_HOfqRwcX%-ivPnAi*dosK0f?*_M^T4UXZ+_4Ogp20}*W=EQJWxGK1R zdAV4-`HELIRP9}Tu>Pgu;9!`lp~WwK-h2|EYfhh%mxnYoH4UdG1=$qy!_dYx{t}NH z{zet?pZ5&ImH>Z8_l!>I#@4If7K?%df%n%2%G1;Si=Jhg@4PNB<>h1J8XJpHu~6jt zz98YDp#@NLU@GA=21Fm)LH3X(Nl7bJ?$)}QqsZwbhadi|x?+#-H)_QGQulmSTnmU8!XwUgieD^{NXLKst za}aWUWL>+}?d|tRAxck7ftSBrWltWf?iM|dTrf*o_d)@0g1q^+lI&2J&JD*_UHPF{ zOT&h=)WogQ6=CPmY1{4UFm4jl$sL+sj>TGTNa5uz%6#WIyG^IoVI3kww%&h9Ir!-fVFFe)SE zckljZ5BUSkSIFxetgNyROX;hX=ROYw&BF?a8Op%6`40(k6WY`msQvN$@59Ss%28uhMTRdcTS`4N#wYI);Gm5S>`?7OwJ_)eCl4RO zLC9yw1YKA!D&ku{Gh|_>eF6{Swt>roKqYII6a&rfM~ZPaoq)WvGf1DYQ&B|UNvz^{ zcr+rtv~=aj0$GcL{nmH>wXKWCYpLccT*z_18>CX1-s$METEoVK#)+Q?ZiRs%V6KL# zM{@Uj2KF2+?b;hzS*M@HXar*ZBac%vOXN4M9tfQ?Gx0Adg0e=UKx+s~M{gu4JdsOXa#SQCzv;m|K-9YkfD4+EN zy(Kub)e+QvZ2nB%Qkl-oxVW(a;3*hJMnuF1@c>020^A=mpj^nU$e=Z%+S<<~MXue% zqFMJf{+GxzZ%K9f&8znT|Ij27^I_Ir`pfoT_hWr+jk~_Q+<~9JbR?Dk#U24(HgEXv zkxnulFiJHN86B-pNJZuUZ=uc>9tQ>*YzClNkeZZ~gx=UaO-!bp;2jz{QO>0v_voZb_n;n2;9cc zvjUDQEw3<;gKzRewb4Sd*ETo5rDtSta&d4h1ByeKUs&h~+PWv*jKy?h|4{=j1ATog zYS4tSPw>9-O0EKa!r=+**BiLOo}N4@1B2H2<>epuSJwiipwk~V>9p0~EP76B$vO4$??)Pf+M0(yFy z3yX_x-CbR;kr5G5rHp~X5T!-c7>B~Px3^J%7A+&@)F&}_aCp7@GU!WUQj$A-Sa+-2 z$B!ZzNlA=7e5Kp>Hyv5(PTZl|b9!KKsgzGZ05hoXkC&(C1F+|P$c|lBy_FLGT};ty zYa5WnixWL$QSp_w8Qn@g`4u|f;Td24-tPE!Ct(2tgJ75ww&Y-ld4As6_{F;y;go}!3<7g~>ucM&Qd%N81v3M!6h%*BJ&dbXy{Td6} z0$TPS-MAlMKk{-WRdU9WEnp%0Ydhkh)A;rE^_*k7dpkQGz#w@X1MMvT6MNWEtA}h`m|~lP-Qg~X*P80;v4H^< z@@R3}8TOO^T5@ZoI!8xG$y=M7dn$6d7Wf%XBD?= zmPu$qK-a{>wYDZCM4rd91wLjbw7#LC>i6&8^D;7BsAnwgU^fx(GJOm6K=K#mZ^;&aX^oWmxO z=-sS-^jE8OEV6pxU0Imdy0stup9ws}|C>csTs>RAIi`7(;Y}U#g+3EYnhUe;=*8Z) z+r^r|%`~h~)0I6uM-lt}zZutFapMSoUyA=f;`;1n9ZCRuo(r()BO!^0Izd$beU(vTbks{uBBr%FOJd;Hqo?O~+k++Q|Wj7!}OOanWaz o;V;5LnnPPf!|DIdO`ats{=sXdaO%f{v1N#|{A;;#8RMY;1GlJKTL1t6 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/000.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/000.png index 0469fddbf42f44b01759d29ff710e540a5af87a9..b0baf1eff669cddcb87d878aaeb7b60fc53144d9 100644 GIT binary patch literal 4897 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 W8ara;yooa}fS#7I=0|mhu>S#I!W*Oj literal 7750 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 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/001.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/001.png index d261774e8c5149715e36de964b64c80aca4f356d..24a4563ae4fb7d07c32a7dcdcb9ef3eb31be334b 100644 GIT binary patch literal 4733 zcmbtYXEYmN_fPEFlprWUX(P2ql@dEf)d+&B*qfr%Dp8~MZ0y}?t&-Sk)@+PciK3-8 ztvyOn7ea?BF`;2?f@1A?lz0W;2&d@-cffh^)000w49-ZVKw26w<`L0ohOcy}LOK4bnc)HkV z&`p#!xJ)?_5X0(p*t#R42EoL_O{r||yA{}+o%c<4RCIJSS&K0~)w(#Mu@?N8SYh&RWGee9S|_ZNXwg*N zrzYq9U8vsa3ur@bgIIItL7r^J!Rm0!W$T z`OV533pK6E3_Dq}ljTVNX7eUzWnFLaWIq!qDlbn_J(?#!JmXw+XSe;(AeO@9t$tdK zb=%uA;`a~!RWH`@gEullc00^>T9z44kEU!^yUCe|r&q^6yzBn{49NncJQ|9^FBM!b zP7Q=qY#he;Ln0_yvS1bh4BT?Wqh_~BUFDMn^47f`y4BY8!i*uTsK`jM=Z~gqBkOat z?9iy6^LYE0m(QE$0w#)Fl9Vqm|9L;}vg?mGu6fitw)`6a`*l2J6aG6NYFf$WN1oeQ z4=Rh>?tT%$bpKE4?6djj<9K^*g~Ji))d6nrSND&n)idu{2{*b;#?u058uM20aya@{`a+!HujKoEHo^^%ff#B1vZbAq^PluwgH9$|QZpxTh-c<`cUnvx z5ltTIbOayi0t9pW?Cz+)WW;hwJ0Vn6BZ%cj>dDGyF4$ZTT{!uI;p=+mFPT*}A9TY` zS25P{+PS7Nj-TQ^qhCs#h?3f1tH0Qi7PayRI&w`}{5mpgTyg@_yfSU!swA#nZcM+4c^Tm8QOADQ21SR3W z(v<6e+y5k(f|#m?5!`1{-}DPT_;5{49u@Te;apAE6EnKjzho13>e%|LG~wyTt){c1 z%`BWxyFLx|H&U)B^IQKsq#;CU{PK8QPrPDoVBU7Nc|NSlmJD1OCkX(tZoQxrGh~0k zJ5XP)0gt!5Jlm|rM&L1~jc%sDe>B&&lfuV$zn^0`ThjiiCkdxa#%mTesEL)NuDuwT zzrgfMmrG(4+=#aditv0_C(BH(6K|73NfNYmVHamQSC<#;s6pOm`MI>^`rmV9-JkNF zEKlUgXZZ&O-Rm@Eb@z{?8VZa(`t>>m>VsM#DL?tP1mfe>w%x?46)1$pXW#{==Kx-3 ze|~RRjH6)~35H&trPrV|gK|BO>qvGeH6Zlr;_pE(lgg(C*9nK;<7L-?bcBR^8vc?y z@$8~Vusz++p!EW15 zuTz3pnO*hTH|vJQGPu23RPXDrMS?YY&fXIq+C3-5&W7Zn7+mu#sBCvN%SPOtd+nXF z#1Q13BB#?6=7f&kmb>)M`93kp+A5*K#ME23Kn|VAc=AwXOa0JuDcOG;$~JU`l)bPHc(5T=Elk+tyrgIPA*lJO)8 zz>}VWz=XiT$eZ~+?fYatRN2k=RZh(A4F7=W$X)c2b-k7_8>sSM=)djeU7;j?&V8X5 zVGRgvr8FdDw>TarFX7=j%@+lko(T+>p-Iuuc;UZ6)R`26#s`8V<$53#N)OaonP*oz zNKRK;OJg)3v!$GU4qhlw3Gdvh|Dt>o+4VP)50_eA+i{$$s|aoa`$!~*0ieco-pm9> z^aCDIdrb5*lL~w7-xh}arve)Sf=d@33;~L1PamD@iFY9FB^I@n0CcH;wq_=#CImi5 zzNZX?bh;v-fc|+~upBRZ03@Jq3sxnPGU4s+fh6vC;RDJ&CsZheX}i*{1*D660l?}V z3(QNnEaf#ltx!9&zYN3yezbwsqVUR37U0+oL<{3!$^)TBYll5y*C_X z8pC6Jx}he%BAyZ$4PwDv-Xz1`y~WM^p2xOg>ns%Fh#bae_?i0MQ{zhmv zNb2#EZe1#NYd%GzZs2f)z<(|ICQ40`OUr8@u|qk6w}%};$s~Dta^a;1PySBXLSWLtg@DNA96-GQ#Rq zbPisRztc{+5kclY|NQUdwe-XOk^mWWvsR&JDftTOT`zpPX%_@@me7k9vh4e-E;#cmnE+HyZt@EG# z49Yd{$A2PcQo@<|Q0}Jv&=k1QPYXy?L$Yonj$gM#aNFKx7M5f@QqKgAXgH?RlGopw zMSFlL->n3tC6m_^qSa`n-c3AIu|7CBP;-uWW0dj5pav@+67lzzv;EH6?3j`sBfCY( zNOZmw5u#Gf7n0yBdoZSNX{3bxuGD)D1j)vb-oon81X;Q=Hpg_RjBKbwu<_NJCtK-3 zGs1PKoerX7cPK}r#|UcG6>2w9L@e(LTO`lho|Edmsvv73(6~<*D#hP#V9^=cDiwP! zF&;(;mvTICQbIEEACS@E(zW!zCpPcHf_AA;E3s+n>^~7Da!0BANVg0HT}Bn|Pd@^N zh@(R2kH5sMKe*rlf9VWk46yWn*$nvx|9-`2O5NCqlkz(Qz~1cbkT5N|X(G}0W{TMK zvY~cET_=ihewes;593lGOLRS8IbO7eIo?*MQXQO{M)>=))SM`g{x#1fmI8wRylX+^ zjRqlL;7v-R(E1{q#0}FChnfQqk}al9crb!NcyT-)peVx+kzD!YK#NPgi;3W+&sZPL zu<|iH1wre?dqi7NvmTF)bZgjs8bOSLu zY^be30NU$4M11yDi?oa!bL-;i>8WKRCL#GL;K{2`_U1V;p4uIStqQ_9-3P(ApGS3s z@&VyFE^f&}T~BJ*Lra8xlo8^cZo)5XTZ?Z5CJC&{mLWWSc_ z?s1apFT_mIF^W&))(!gs;NKXEUIXbQsH;$AMWBu_t{rHsf`;4#nvx94h`ND>EVZ&w zaa{FXe~6r#4Kyzo#l#GnfYFPdK(NQ1GsuH!PCW95gxENZdJ*4}RTL|Y?AYEy3p(l) z0C>as<<(6bPI|NvfrmEo;*`4WvP$bllAyC!6!y0K(70(PfDQ$!<#5&&P%P1RJGd+x zIA$2cfWG~DX?oCV3(i(BMz)ybUfW^j&P1>o{MAWoJXnom z+A~V5-0Q7o+aay#z*cF?LgMF>M$;38`RKzuW)**GtdCqU@&9r>{_oHhQd z6f26EZSaKc|Ye0(hM ziNFw=IBKA+DFE5)YkxK>SOVx&=voOGSQ4Xo{np4lta+*XQTOlXnISsY+$F@5D^VFn zW#4w3XWbRv7kNL{rX4v8^0|Dq5Q)?eX$bvXH{^^B70g_FPl`qC?%-OuWfa>eP7SZ+ z=OuyfTV}Gcy*gp!jRu;#W?ABcqdFd(@hDJl@L6}=D}2S{OmeeI1@!L|MpUMh v+~lxtx2`NTjCUS5Y&`Hb*y8_#Ziat=`!|iO4{Vb9NdO&91C1Ir^o#!k%`D}l literal 8731 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 a*8;o*GH$#<;=*5hAXF3{J@_Vv_WvK2Lc4bW diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/002.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/002.png index 9da1618b8c3db47e5bd9ba59f7ef0699c09d44af..402702b683b4d524f86a6e1e0aa8099b5de462e7 100644 GIT binary patch literal 4654 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 W<#XV78gc^&psjA8R<2?j@qYk*U)T2l literal 9141 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 O5P2CD>2fJp;Qs*pmbG>O diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/003.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/003.png index 7b47aac4157fffd58d21a8fd0b75f1bd6dab4d8d..462489fbf5c13efc8e9dbb97bc73b908aa71a6f4 100644 GIT binary patch literal 4849 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 YtMRX@=n5`5Du)Fy&^6V0rG<_94`IFr)&Kwi literal 13219 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 diff --git a/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/005.png b/test/unit/visual/screenshots/Typography/textAlign/all alignments with multi-lines and wrap char/005.png index 0c1ca0e6566497e02c46c5d8887660cf1b797902..c771765ecc282736e07967aae78e9afc239b08f8 100644 GIT binary patch literal 4588 zcmaiYXEYpM(Eb*7Sr%EWXg`7wA&4$SFDpt!*{r^zmk29b2&=5#h3L^D2}`s@iLiQ$ z-bIZT5mBNO{`-FXpYxvcez_g z&u!kjOBO&cLoHQ6#URHf0C25DTV2K2&uTjt`kdK>v0H!}<|7EBzNHRi&!1)%grO5c zzhc4cKE!F7BavG?JW)LF@svV5+P`7a>Xa(Zp_B|s_`=ZB!Dr1o>*ka5$A$|IE6oiX z9){Dt{c~5jr$cj@divVh+R+#ZYC8-_4nm~W8E-VAzFtX7m5d_cnWHh~M&NWCZUkAy zbFIwVg(Oa^&I1Ia`JQ~zhhri_P<&WYj5=}h1F&C=A)0~~lN>d1PYTNl;Yr2=g%DL{ z?;yhM%6tehtOgHyYaDNXJxUz}A)-25a@i_r!O1A@B9d8iU;`5iiZV=NbYkPzp8o!_eJKYH43Rs5VBD~JNeRXcugube zCtCpA%(;cYvci;_p|`K_z0BG3mz%!e;db=_2MOEv~b*ABc4eFD8@^T8&P&KDO9R5={+x1+=o(HgpEEr0kd5 z2-R*g;vXK@Rg9NeTjOxJ+X}&}$-S4V0*1zXH0whT87d=auL%kZTkga#3)xLs`ldZ= zKGh8NU3_`md%E%FBRhJYE&H;aUJ13*74Pj5%OZ-b&=C3ZTYPh|rNzQ`-WxX{HH9iS z`*d63Q0eMIqUaw%pHD!bf%K#ZMnhwN_3v2J@=EdiH}A8iy$E8<GDMFoRsrI55fO?r{yZ$d&*MAzU82`X|Bdr2b!UrMqo1kV%KjN~z}grs0h9yIi}vd7o4=4|JByvkE+|I6=Q13)?(zqY)i