Handle overflowing to new row

This commit is contained in:
Daniel Imms
2025-01-07 06:28:59 -08:00
parent ff9a3a1067
commit a7b98de833
6 changed files with 31 additions and 18 deletions
+18 -13
View File
@@ -66,6 +66,7 @@ export class TextureAtlas implements ITextureAtlas {
// The set of atlas pages that can be written to
private _activePages: AtlasPage[] = [];
private _overflowSizePage: AtlasPage | undefined;
private _tmpCanvas: HTMLCanvasElement;
// A temporary context that glyphs are drawn to before being transfered to the atlas.
@@ -75,8 +76,6 @@ export class TextureAtlas implements ITextureAtlas {
private _workAttributeData: AttributeData = new AttributeData();
private _textureSize: number = 512;
// TODO: Use actual value
private _deviceMaxTextureSize: number = 2048;
public static maxAtlasPages: number | undefined;
public static maxTextureSize: number | undefined;
@@ -433,7 +432,7 @@ export class TextureAtlas implements ITextureAtlas {
// Allow 1 cell width per character, with a minimum of 2 (CJK), plus some padding. This is used
// to draw the glyph to the canvas as well as to restrict the bounding box search to ensure
// giant ligatures (eg. =====>) don't impact overall performance.
const allowedWidth = Math.min(this._config.deviceCellWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2, this._deviceMaxTextureSize);
const allowedWidth = Math.min(this._config.deviceCellWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2, this._config.deviceMaxTextureSize);
if (this._tmpCanvas.width < allowedWidth) {
this._tmpCanvas.width = allowedWidth;
}
@@ -774,19 +773,24 @@ export class TextureAtlas implements ITextureAtlas {
}
}
// TODO: Move below after page merging to ensure page limit isn't hit
// Create a new page for oversized glyphs as they come up
if (rasterizedGlyph.size.x > this._textureSize) {
// TODO: Reuse a single oversized glyphs page
const newPage = new AtlasPage(this._document, this._deviceMaxTextureSize);
this.pages.push(newPage);
if (!this._overflowSizePage) {
this._overflowSizePage = new AtlasPage(this._document, this._config.deviceMaxTextureSize);
this.pages.push(this._overflowSizePage);
// Request the model to be cleared to refresh all texture pages.
this._requestClearModel = true;
this._onAddTextureAtlasCanvas.fire(newPage.canvas);
newPage.addGlyph(rasterizedGlyph);
activePage.fixedRows.push(newPage.currentRow);
// Request the model to be cleared to refresh all texture pages.
this._requestClearModel = true;
this._onAddTextureAtlasCanvas.fire(this._overflowSizePage.canvas);
}
activePage = this._overflowSizePage;
activeRow = this._overflowSizePage.currentRow;
// Move to next row if necessary
if (activeRow.x + rasterizedGlyph.size.x >= activePage.canvas.width) {
activeRow.x = 0;
activeRow.y += activeRow.height;
activeRow.height = 0;
}
break;
}
@@ -800,6 +804,7 @@ export class TextureAtlas implements ITextureAtlas {
if (activePage.currentRow.y + activePage.currentRow.height + rasterizedGlyph.size.y >= activePage.canvas.height) {
// Find the first page with room to create the new row on
let candidatePage: AtlasPage | undefined;
for (const p of this._activePages) {
if (p.currentRow.y + p.currentRow.height + rasterizedGlyph.size.y < p.canvas.height) {
candidatePage = p;