{"ScriptPreparationCode":"const font = \u002712px sans-serif\u0027;\r\nconst charset = [...Array(100)].map((_, i) =\u003E String.fromCharCode(0x200 \u002B i));\r\nconst testTexts = [...Array(50)].map(() =\u003E randomString(10, 30));\r\n\r\nfunction randomString(minLen, maxLen) {\r\n const len = Math.floor(Math.random() * (maxLen - minLen \u002B 1)) \u002B minLen;\r\n let result = \u0027\u0027;\r\n for (let i = 0; i \u003C len; i\u002B\u002B) {\r\n result \u002B= charset[Math.floor(Math.random() * charset.length)];\r\n }\r\n return result;\r\n}\r\n\r\nfunction charWidth(c, ctx, cache) {\r\n return cache[c] || (cache[c] = ctx.measureText(c).width);\r\n}\r\n\r\nfunction textWidth(txt, ctx, cache) {\r\n let w = 0;\r\n txt = txt \u002B \u0027\u0027;\r\n for (const c of txt) {\r\n w \u002B= charWidth(c, ctx, cache);\r\n }\r\n return w;\r\n}\r\n\r\nfunction cachedMeasureText(txt, ctx, cache) {\r\n return cache[txt] || (cache[txt] = ctx.measureText(txt).width);\r\n}\r\n\r\nwindow.measureText = (() =\u003E {\r\n const canvas = document.createElement(\u0027canvas\u0027);\r\n const ctx = canvas.getContext(\u00272d\u0027);\r\n ctx.font = font;\r\n return (txt) =\u003E ctx.measureText(txt);\r\n})();\r\n\r\nwindow.oscMeasureText = (() =\u003E {\r\n const canvas = new window.OffscreenCanvas(0, 0);\r\n const ctx = canvas.getContext(\u00272d\u0027);\r\n ctx.font = font;\r\n return (txt) =\u003E ctx.measureText(txt);\r\n})();\r\n\r\nwindow.byChars = (() =\u003E {\r\n const canvas = document.createElement(\u0027canvas\u0027);\r\n const ctx = canvas.getContext(\u00272d\u0027);\r\n ctx.font = font;\r\n charWidthCache = {};\r\n return (txt) =\u003E textWidth(txt, ctx, charWidthCache);\r\n})();\r\n\r\nwindow.byStrings = (() =\u003E {\r\n const canvas = document.createElement(\u0027canvas\u0027);\r\n const ctx = canvas.getContext(\u00272d\u0027);\r\n ctx.font = font;\r\n return (stringWidthCache, txt) =\u003E cachedMeasureText(txt, ctx, stringWidthCache);\r\n})();","TestCases":[{"Name":"measureText via Canvas","Code":"for (let i = 0; i \u003C 50; i\u002B\u002B) testTexts.map(txt =\u003E measureText(txt))","IsDeferred":false},{"Name":"measureText via OffsetScreenCanvas","Code":"for (let i = 0; i \u003C 50; i\u002B\u002B) testTexts.map(txt =\u003E oscMeasureText(txt))","IsDeferred":false},{"Name":"byChars","Code":"for (let i = 0; i \u003C 50; i\u002B\u002B) testTexts.map(txt =\u003E byChars(txt))","IsDeferred":false},{"Name":"byStrings","Code":"(x = {}); for (let i = 0; i \u003C 50; i\u002B\u002B) testTexts.map(txt =\u003E byStrings(x, txt))","IsDeferred":false}]}