Skip to content

Commit 65a5228

Browse files
committed
fix: enhance text node measurement and font loading handling on domRenderer
1 parent db347ab commit 65a5228

File tree

1 file changed

+79
-11
lines changed

1 file changed

+79
-11
lines changed

src/core/dom-renderer/domRenderer.ts

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -882,6 +882,8 @@ function updateNodeStyles(node: DOMNode | DOMText) {
882882
}
883883

884884
const textNodesToMeasure = new Set<DOMText>();
885+
const containTextNodes = new Set<DOMText>();
886+
let fontLoadingListenerSetup = false;
885887

886888
type Size = { width: number; height: number };
887889

@@ -958,21 +960,68 @@ function updateDOMTextMeasurements() {
958960
textNodesToMeasure.clear();
959961
}
960962

963+
function shouldTrackContainTextNode(node: DOMText): boolean {
964+
return node.contain === 'width' || node.contain === 'none';
965+
}
966+
967+
function syncContainTextNodeTracking(node: DOMText): void {
968+
if (shouldTrackContainTextNode(node)) {
969+
containTextNodes.add(node);
970+
} else {
971+
containTextNodes.delete(node);
972+
}
973+
}
974+
975+
function scheduleContainTextNodesMeasurement(): void {
976+
if (containTextNodes.size === 0) return;
977+
978+
containTextNodes.forEach((node) => {
979+
if (node.div.isConnected) {
980+
textNodesToMeasure.add(node);
981+
}
982+
});
983+
984+
if (textNodesToMeasure.size > 0) {
985+
setTimeout(updateDOMTextMeasurements);
986+
}
987+
}
988+
989+
function setupFontLoadingListeners(): void {
990+
if (fontLoadingListenerSetup) return;
991+
if (
992+
typeof document === 'undefined' ||
993+
!(document.fonts as FontFaceSet | undefined)
994+
) {
995+
return;
996+
}
997+
998+
const fonts = document.fonts;
999+
if (typeof fonts.addEventListener === 'function') {
1000+
fonts.addEventListener('loadingdone', scheduleContainTextNodesMeasurement);
1001+
}
1002+
1003+
fontLoadingListenerSetup = true;
1004+
}
1005+
9611006
function scheduleUpdateDOMTextMeasurement(node: DOMText) {
9621007
/*
9631008
Make sure the font is loaded before measuring
9641009
*/
9651010

1011+
setupFontLoadingListeners();
1012+
9661013
if (textNodesToMeasure.size === 0) {
967-
const fonts = document.fonts;
968-
if (document.fonts.status === 'loaded') {
969-
setTimeout(updateDOMTextMeasurements);
970-
} else {
971-
if (fonts && fonts.ready && typeof fonts.ready.then === 'function') {
1014+
if (typeof document !== 'undefined' && 'fonts' in document) {
1015+
const fonts = document.fonts;
1016+
if (fonts.status === 'loaded') {
1017+
setTimeout(updateDOMTextMeasurements);
1018+
} else if (fonts.ready && typeof fonts.ready.then === 'function') {
9721019
fonts.ready.then(updateDOMTextMeasurements);
9731020
} else {
9741021
setTimeout(updateDOMTextMeasurements, 500);
9751022
}
1023+
} else {
1024+
setTimeout(updateDOMTextMeasurements, 500);
9761025
}
9771026
}
9781027

@@ -1570,9 +1619,16 @@ class DOMText extends DOMNode {
15701619
) {
15711620
super(stage, props);
15721621
this.div.innerText = props.text;
1622+
syncContainTextNodeTracking(this);
15731623
scheduleUpdateDOMTextMeasurement(this);
15741624
}
15751625

1626+
override destroy(): void {
1627+
textNodesToMeasure.delete(this);
1628+
containTextNodes.delete(this);
1629+
super.destroy();
1630+
}
1631+
15761632
get text() {
15771633
return this.props.text;
15781634
}
@@ -1700,6 +1756,7 @@ class DOMText extends DOMNode {
17001756
set contain(v) {
17011757
if (this.props.contain === v) return;
17021758
this.props.contain = v;
1759+
syncContainTextNodeTracking(this);
17031760
updateNodeStyles(this);
17041761
scheduleUpdateDOMTextMeasurement(this);
17051762
}
@@ -1982,14 +2039,25 @@ export function loadFontToDom(font: FontLoadOptions): void {
19822039
// atlasUrl?: string;
19832040
// atlasDataUrl?: string;
19842041

2042+
if (
2043+
typeof document === 'undefined' ||
2044+
!('fonts' in document) ||
2045+
typeof FontFace === 'undefined' ||
2046+
!font.fontUrl
2047+
) {
2048+
return;
2049+
}
2050+
19852051
const fontFace = new FontFace(font.fontFamily, `url(${font.fontUrl})`);
2052+
const fontSet = document.fonts as FontFaceSet & {
2053+
add?: (font: FontFace) => FontFaceSet;
2054+
};
2055+
fontSet.add?.(fontFace);
19862056

1987-
if (typeof document !== 'undefined' && 'fonts' in document) {
1988-
const fontSet = document.fonts as FontFaceSet & {
1989-
add?: (font: FontFace) => FontFaceSet;
1990-
};
1991-
fontSet.add?.(fontFace);
1992-
}
2057+
fontFace
2058+
.load()
2059+
.then(scheduleContainTextNodesMeasurement)
2060+
.catch(() => {});
19932061
}
19942062

19952063
export function isDomRenderer(

0 commit comments

Comments
 (0)