fix atlas callstack exception (#6001)

* fix atlas callstack exception

* remove spread operator, integrate stress test into demo
This commit is contained in:
jerch
2026-06-06 09:01:49 -07:00
committed by GitHub
parent f3f4dcaf9f
commit 0c8271db49
2 changed files with 76 additions and 6 deletions
+22 -6
View File
@@ -1080,17 +1080,33 @@ class AtlasPage {
size: number,
sourcePages?: AtlasPage[]
) {
if (sourcePages) {
for (const p of sourcePages) {
this._glyphs.push(...p.glyphs);
this._usedPixels += p._usedPixels;
}
}
this.canvas = createCanvas(document, size, size);
// The canvas needs alpha because we use clearColor to convert the background color to alpha.
// It might also contain some characters with transparent backgrounds if allowTransparency is
// set.
this.ctx = throwIfFalsy(this.canvas.getContext('2d', { alpha: true }));
if (sourcePages) {
if (sourcePages.length === 4) {
// optimized for quadmerge
this._glyphs = this._glyphs.concat(
sourcePages[0].glyphs,
sourcePages[1].glyphs,
sourcePages[2].glyphs,
sourcePages[3].glyphs
);
this._usedPixels = sourcePages[0]._usedPixels +
sourcePages[1]._usedPixels +
sourcePages[2]._usedPixels +
sourcePages[3]._usedPixels;
} else {
// fallback for non quadmerges (should never be used)
for (let i = 0; i < sourcePages.length; ++i) {
this._glyphs = this._glyphs.concat(sourcePages[i].glyphs);
this._usedPixels += sourcePages[i]._usedPixels;
}
}
}
}
public clear(): void {
@@ -11,8 +11,33 @@ export class WebglWindow extends BaseWindow implements IControlWindow {
public readonly label = 'webgl';
private _textureAtlasContainer!: HTMLElement;
private _stressRunning = false;
private _stressScrolling: HTMLInputElement | undefined;
public build(container: HTMLElement): void {
const stressDiv = document.createElement('div');
const stressStart = document.createElement('button');
stressStart.id = 'stress-start';
stressStart.textContent = 'atlas stress start';
stressStart.addEventListener('click', () => this._stress());
stressDiv.appendChild(stressStart);
const stressStop = document.createElement('button');
stressStop.id = 'stress-stop';
stressStop.textContent = 'atlas stress stop';
stressStop.addEventListener('click', () => this._stressRunning = false);
stressDiv.appendChild(stressStop);
this._stressScrolling = document.createElement('input');
this._stressScrolling.type = 'checkbox';
this._stressScrolling.id = 'stress-scrolling';
stressDiv.appendChild(this._stressScrolling);
const stressScrollingLabel = document.createElement('label');
stressScrollingLabel.htmlFor = 'stress-scrolling';
stressScrollingLabel.textContent = 'stress scrolling';
stressDiv.appendChild(stressScrollingLabel);
container.appendChild(stressDiv);
const zoomCheckbox = document.createElement('input');
zoomCheckbox.type = 'checkbox';
zoomCheckbox.id = 'texture-atlas-zoom';
@@ -48,4 +73,33 @@ export class WebglWindow extends BaseWindow implements IControlWindow {
canvas.style.width = `${canvas.width / dpr}px`;
canvas.style.height = `${canvas.height / dpr}px`;
}
private async _stress(): Promise<void> {
const TEXT = '!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
if (this._stressRunning) {
return;
}
this._stressRunning = true;
const scrolling = !!(this._stressScrolling?.checked);
for (let r = 0; r < 256; r += 2) {
for (let g = 0; g < 256; g += 2) {
let s: string[] = [];
for (let b = 0; b < 256; b += 2) {
if (!this._stressRunning) {
return;
}
const rbg = `RGB: ${[r, g, b]}`;
s.push(`\r\x1b[38;2;${r};${g};${b}m${rbg.padEnd(18, ' ')}${TEXT}`);
if (s.length >= 16) {
if (scrolling) {
await new Promise<void>(r => this._terminal.write(s.join('\r\n') + '\r\n', r));
} else {
await new Promise<void>(r => this._terminal.write('\x1b[H' + s.join('\r\n'), r));
}
s = [];
}
}
}
}
}
}