From 0b77e8645e9d1e072e2b936f083f4758c33980ea Mon Sep 17 00:00:00 2001 From: LalitNarayanYadav Date: Sat, 10 Oct 2026 19:36:34 +0530 Subject: [PATCH 1/2] Add textToContours() benchmark tests --- test/bench/typography.bench.js | 83 +++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/test/bench/typography.bench.js b/test/bench/typography.bench.js index 8ab9650043..25b2471549 100644 --- a/test/bench/typography.bench.js +++ b/test/bench/typography.bench.js @@ -14,7 +14,7 @@ const strs = { }; // Parameterizing test cases by function ensures consistency in test parameters across all renderers. -// Future tests should follow a similar format (e.g. TO_CONTOURS_CASES, etc) +// Future tests should follow a similar format const TO_POINTS_CASES = [ {label: "textToPoints() single word", str: strs.single, textSize: 20, sampleFactor: 0.5, points: 317, variance: 5, render: false}, {label: "textToPoints() single word, 150pt", str: strs.single, textSize: 150, sampleFactor: 0.5, points: 2336, variance: 50, render: false}, @@ -31,6 +31,11 @@ const TO_MODEL_CASES = [ {label: "textToModel() paragraph", str: strs.paragraph, textSize: 20, sampleFactor: 0.5, render: false}, ]; +const TO_CONTOURS_CASES = TO_POINTS_CASES.map((c) => ({ + ...c, + label: c.label.replace("textToPoints()", "textToContours()"), +})); + async function bootstrap(w = 400, h = 400, renderer = undefined) { var myp5; var font; @@ -58,6 +63,16 @@ function drawPoints(myp5, points) { } } +function drawContours(myp5, contours) { + for (let contour of contours) { + myp5.beginShape(); + for (let pt of contour) { + myp5.vertex(pt.x, pt.y); + } + myp5.endShape(myp5.CLOSE); + } +} + const options = { iterations: 20, time: 500 }; describe("Typography: bench 2D", function() { @@ -84,6 +99,28 @@ describe("Typography: bench 2D", function() { ); } + for (let testCase of TO_CONTOURS_CASES) { + bench( + testCase.label, + async () => { + const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + const total = contours.reduce((n, c) => n + c.length, 0); + assert.closeTo(total, testCase.points, testCase.variance); + if (testCase.render) { + drawContours(myp5, contours); + } + }, + { + ...options, + setup: async () => { + ({myp5, font} = await bootstrap()); + myp5.textSize(testCase.textSize); + }, + teardown: () => myp5.remove() + } + ); + } + }); describe("Typography: bench WebGL", function() { @@ -131,6 +168,28 @@ describe("Typography: bench WebGL", function() { ); } + for (let testCase of TO_CONTOURS_CASES) { + bench( + testCase.label, + async () => { + const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + const total = contours.reduce((n, c) => n + c.length, 0); + assert.closeTo(total, testCase.points, testCase.variance); + if (testCase.render) { + drawContours(myp5, contours); + } + }, + { + ...options, + setup: async () => { + ({myp5, font} = await bootstrap(400, 400, WEBGL)); + myp5.textSize(testCase.textSize); + }, + teardown: () => myp5.remove() + } + ); + } + }); describe("Typography: bench WebGPU", function() { @@ -179,4 +238,26 @@ describe("Typography: bench WebGPU", function() { ); } + for (let testCase of TO_CONTOURS_CASES) { + bench( + testCase.label, + async () => { + const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + const total = contours.reduce((n, c) => n + c.length, 0); + assert.closeTo(total, testCase.points, testCase.variance); + if (testCase.render) { + drawContours(myp5, contours); + } + }, + { + ...options, + setup: async () => { + ({myp5, font} = await bootstrap(400, 400, WEBGPU)); + myp5.textSize(testCase.textSize); + }, + teardown: () => myp5.remove() + } + ); + } + }); \ No newline at end of file From 2a6643baf8eb66c78a2eb3f26989ea0ff93d3f4d Mon Sep 17 00:00:00 2001 From: LalitNarayanYadav Date: Fri, 16 Oct 2026 01:20:50 +0530 Subject: [PATCH 2/2] Sequence textToContours benchmarks after textToPoints and assert contour count --- test/bench/typography.bench.js | 61 +++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/test/bench/typography.bench.js b/test/bench/typography.bench.js index 25b2471549..408123b8fe 100644 --- a/test/bench/typography.bench.js +++ b/test/bench/typography.bench.js @@ -23,6 +23,23 @@ const TO_POINTS_CASES = [ {label: "textToPoints() paragraph", str: strs.paragraph, textSize: 20, sampleFactor: 0.5, points: 21275, variance: 50, render: false}, ]; +// Expected number of contours for each TO_POINTS_CASES entry, in the same order. +// Contour count depends on the glyph outlines (not textSize or sampleFactor), +// so the same string gives the same count. +const EXPECTED_CONTOURS = [ + 16, // single word + 16, // single word, 150pt + 16, // single word, with render + 76, // 10 words + 1167, // paragraph +]; + +const TO_CONTOURS_CASES = TO_POINTS_CASES.map((c, i) => ({ + ...c, + label: c.label.replace("textToPoints()", "textToContours()"), + contours: EXPECTED_CONTOURS[i], +})); + const TO_MODEL_CASES = [ {label: "textToModel() single word", str: strs.single, textSize: 20, sampleFactor: 0.5, render: false}, {label: "textToModel() single word, 150pt", str: strs.single, textSize: 150, sampleFactor: 0.5, render: false}, @@ -31,11 +48,6 @@ const TO_MODEL_CASES = [ {label: "textToModel() paragraph", str: strs.paragraph, textSize: 20, sampleFactor: 0.5, render: false}, ]; -const TO_CONTOURS_CASES = TO_POINTS_CASES.map((c) => ({ - ...c, - label: c.label.replace("textToPoints()", "textToContours()"), -})); - async function bootstrap(w = 400, h = 400, renderer = undefined) { var myp5; var font; @@ -104,6 +116,7 @@ describe("Typography: bench 2D", function() { testCase.label, async () => { const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + assert.equal(contours.length, testCase.contours); const total = contours.reduce((n, c) => n + c.length, 0); assert.closeTo(total, testCase.points, testCase.variance); if (testCase.render) { @@ -147,14 +160,16 @@ describe("Typography: bench WebGL", function() { ); } - for (let testCase of TO_MODEL_CASES) { + for (let testCase of TO_CONTOURS_CASES) { bench( testCase.label, async () => { - const model = font.textToModel(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); - assert.isAbove(model.vertices.length, 0); + const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + assert.equal(contours.length, testCase.contours); + const total = contours.reduce((n, c) => n + c.length, 0); + assert.closeTo(total, testCase.points, testCase.variance); if (testCase.render) { - myp5.model(model); + drawContours(myp5, contours); } }, { @@ -168,15 +183,14 @@ describe("Typography: bench WebGL", function() { ); } - for (let testCase of TO_CONTOURS_CASES) { + for (let testCase of TO_MODEL_CASES) { bench( testCase.label, async () => { - const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); - const total = contours.reduce((n, c) => n + c.length, 0); - assert.closeTo(total, testCase.points, testCase.variance); + const model = font.textToModel(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + assert.isAbove(model.vertices.length, 0); if (testCase.render) { - drawContours(myp5, contours); + myp5.model(model); } }, { @@ -217,14 +231,16 @@ describe("Typography: bench WebGPU", function() { ); } - for (let testCase of TO_MODEL_CASES) { + for (let testCase of TO_CONTOURS_CASES) { bench( testCase.label, async () => { - const model = font.textToModel(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); - assert.isAbove(model.vertices.length, 0); + const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + assert.equal(contours.length, testCase.contours); + const total = contours.reduce((n, c) => n + c.length, 0); + assert.closeTo(total, testCase.points, testCase.variance); if (testCase.render) { - myp5.model(model); + drawContours(myp5, contours); } }, { @@ -238,15 +254,14 @@ describe("Typography: bench WebGPU", function() { ); } - for (let testCase of TO_CONTOURS_CASES) { + for (let testCase of TO_MODEL_CASES) { bench( testCase.label, async () => { - const contours = font.textToContours(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); - const total = contours.reduce((n, c) => n + c.length, 0); - assert.closeTo(total, testCase.points, testCase.variance); + const model = font.textToModel(testCase.str, 10, 20, { sampleFactor: testCase.sampleFactor }); + assert.isAbove(model.vertices.length, 0); if (testCase.render) { - drawContours(myp5, contours); + myp5.model(model); } }, {