Skip to content

Commit

Permalink
Workaround for Safari font loading bug (pixijs-userland#32)
Browse files Browse the repository at this point in the history
  • Loading branch information
bigtimebuddy authored Dec 16, 2022
1 parent c68b62c commit 68c6dab
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 18 deletions.
40 changes: 23 additions & 17 deletions src/HTMLText.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ export class HTMLText extends Sprite
* @param {boolean} respectDirty - Whether to abort updating the
* text if the Text isn't dirty and the function is called.
*/
updateText(respectDirty = true): void
async updateText(respectDirty = true): Promise<void>
{
const { style, canvas, context } = this;

Expand All @@ -211,24 +211,30 @@ export class HTMLText extends Sprite

if (!this._loading)
{
const image = this._image;
const svgURL = new XMLSerializer().serializeToString(this._svgRoot);

this._loading = true;
image.src = `data:image/svg+xml;charset=utf8,${encodeURIComponent(svgURL)}`;
image.onload = () =>
await new Promise<void>((resolve) =>
{
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(
image,
0, 0, width, height,
0, 0, width, height,
);
image.src = '';
image.onload = null;
this._loading = false;
this.updateTexture();
};
const image = this._image;

image.onload = async () =>
{
await style.onBeforeDraw();
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(
image,
0, 0, width, height,
0, 0, width, height,
);
image.src = '';
image.onload = null;
this._loading = false;
this.updateTexture();
resolve();
};
const svgURL = new XMLSerializer().serializeToString(this._svgRoot);

image.src = `data:image/svg+xml;charset=utf8,${encodeURIComponent(svgURL)}`;
});
}
}

Expand Down
34 changes: 33 additions & 1 deletion src/HTMLTextStyle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ class HTMLTextStyle extends TextStyle
/** Global rules or stylesheet, useful for creating rules for rendering */
private _stylesheet = '';

/** Track font changes internally */
private fontsDirty = false;

/**
* Convert a TextStyle to HTMLTextStyle
* @example
Expand Down Expand Up @@ -134,6 +137,7 @@ class HTMLTextStyle extends TextStyle
this.fontFamily = 'Arial';
this._fonts.length = 0;
this.styleID++;
this.fontsDirty = true;
}
}

Expand All @@ -150,6 +154,7 @@ class HTMLTextStyle extends TextStyle
this._fonts.push(font);
font.refs++;
this.styleID++;
this.fontsDirty = true;

return Promise.resolve();
}
Expand Down Expand Up @@ -196,6 +201,7 @@ class HTMLTextStyle extends TextStyle
await document.fonts.ready;

this.styleID++;
this.fontsDirty = true;
});
}

Expand Down Expand Up @@ -351,7 +357,33 @@ class HTMLTextStyle extends TextStyle
Object.assign(this, HTMLTextStyle.defaultOptions);
}

/** Proving that Safari is the new IE */
/**
* Called after the image is loaded but before drawing to the canvas.
* Mostly used to handle Safari's font loading bug.
* @ignore
*/
public onBeforeDraw()
{
const { fontsDirty: prevFontsDirty } = this;

this.fontsDirty = false;

// Safari has a known bug where embedded fonts are not available
// immediately after the image loads, to compensate we wait an
// arbitrary amount of time
// @see https://bugs.webkit.org/show_bug.cgi?id=219770
if (this.isSafari && this._fonts.length > 0 && prevFontsDirty)
{
return new Promise<void>((resolve) => setTimeout(resolve, 100));
}

return Promise.resolve();
}

/**
* Proving that Safari is the new IE
* @ignore
*/
private get isSafari(): boolean
{
const { userAgent } = settings.ADAPTER.getNavigator();
Expand Down

0 comments on commit 68c6dab

Please sign in to comment.