Skip to content

Commit 8010b5d

Browse files
authored
Merge pull request #8747 from processing/fix/webgl-text-measurement
Save + restore 2D text canvas context when font is applied in WebGL mode
2 parents a0047fa + 8bd620b commit 8010b5d

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

src/core/p5.Renderer3D.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ export class Renderer3D extends Renderer {
160160

161161
// clipping
162162
this._clipDepths = [];
163+
this._textContextSavedStack = [];
163164
this._isClipApplied = false;
164165
this._stencilTestOn = false;
165166

@@ -1327,13 +1328,25 @@ export class Renderer3D extends Renderer {
13271328
return this;
13281329
}
13291330

1331+
push() {
1332+
super.push()
1333+
const saved = !!(this.states.textFont?.font);
1334+
if (saved) {
1335+
this.textDrawingContext().save()
1336+
}
1337+
this._textContextSavedStack.push(saved);
1338+
}
1339+
13301340
pop(...args) {
13311341
if (
13321342
this._clipDepths.length > 0 &&
13331343
this._pushPopDepth === this._clipDepths[this._clipDepths.length - 1]
13341344
) {
13351345
this._clearClip();
13361346
}
1347+
if (this._textContextSavedStack.pop()) {
1348+
this.textDrawingContext().restore()
1349+
}
13371350
super.pop(...args);
13381351
this._applyStencilTestIfClipping();
13391352
}

test/unit/webgl/p5.RendererGL.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2998,4 +2998,38 @@ suite('p5.RendererGL', function() {
29982998
expect(myp5.get(5, 5)).toEqual([255, 0, 0, 255]);
29992999
});
30003000
});
3001+
3002+
suite('fontWidth', function() {
3003+
test('respects textSize changes across push/pop', async function() {
3004+
myp5.createCanvas(100, 100, myp5.WEBGL);
3005+
const font = await myp5.loadFont('test/unit/assets/acmesa.ttf');
3006+
3007+
myp5.push();
3008+
myp5.textFont(font);
3009+
myp5.textSize(12);
3010+
myp5.push();
3011+
myp5.textSize(20);
3012+
const widthAt20 = myp5.fontWidth('X');
3013+
myp5.pop();
3014+
const widthAt12 = myp5.fontWidth('X');
3015+
myp5.pop();
3016+
3017+
expect(widthAt20).toBeGreaterThan(widthAt12);
3018+
});
3019+
3020+
test('fontWidth restores correctly when font is unset inside push/pop', async function() {
3021+
myp5.createCanvas(100, 100, myp5.WEBGL);
3022+
const font = await myp5.loadFont('test/unit/assets/acmesa.ttf');
3023+
myp5.textFont(font);
3024+
myp5.textSize(12);
3025+
myp5.push();
3026+
myp5.textFont('sans-serif'); // unset loaded font
3027+
myp5.pop();
3028+
// After pop, should be back to size 12 with loaded font
3029+
const widthAfterPop = myp5.fontWidth('X');
3030+
myp5.textSize(20);
3031+
const widthAt20 = myp5.fontWidth('X');
3032+
expect(widthAfterPop).toBeLessThan(widthAt20);
3033+
});
3034+
});
30013035
});

0 commit comments

Comments
 (0)