Skip to content

Commit bf801b4

Browse files
committed
perf: fix painting regression and cleanup
Regressor: 9145d36 I thought it was good to use item.measure() but it does a lot more than sum widths, so it caused a performance regression. Luckily drawText is more simple than it used to be: it only paints one color. The tx changes surrounding b.text must be left over from when drawText handled multiple color changes; it no longer does that and those lines don't do anything. So anther regressor may be d2f6b5e since that added some glyph summing outside of drawText.
1 parent cc5ad59 commit bf801b4

1 file changed

Lines changed: 19 additions & 14 deletions

File tree

src/paint.ts

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ function drawText(
7676
b: PaintBackend
7777
) {
7878
const style = item.attrs.style;
79-
const state = item.createMeasureState();
8079
// Split the colors into spans so that colored diacritics can work.
8180
// Sadly this seems to only work in Firefox and only when the font doesn't do
8281
// any normalizination, so I could probably stop trying to support it
@@ -86,30 +85,36 @@ function drawText(
8685
textStart = Math.max(textStart, collapsed.textStart);
8786
textEnd = Math.min(textEnd, collapsed.textEnd);
8887

89-
if (item.attrs.level & 1) {
90-
tx += item.measure().advance;
91-
tx -= item.measure(textStart, 1, state).advance;
92-
} else {
93-
tx += item.measure(textStart, 1, state).advance;
94-
}
95-
9688
if (textStart < textEnd) {
89+
const toPx = 1 / item.face.hbface.upem * item.attrs.style.fontSize;
90+
let axToStart = 0;
91+
let gi;
92+
93+
// Move tx to the x offset for textStart
94+
if (item.attrs.level & 1) {
95+
for (gi = 0; gi < item.glyphs.length; gi += G_SZ) {
96+
if (item.glyphs[gi + G_CL] < textEnd) break;
97+
axToStart += item.glyphs[gi + G_AX];
98+
}
99+
} else {
100+
for (gi = 0; gi < item.glyphs.length; gi += G_SZ) {
101+
if (item.glyphs[gi + G_CL] >= textStart) break;
102+
axToStart += item.glyphs[gi + G_AX];
103+
}
104+
}
105+
106+
tx += axToStart * toPx;
107+
97108
// TODO: should really have isStartColorBoundary, isEndColorBoundary
98109
const isColorBoundary = textStart !== item.offset && textStart === run.start
99110
|| textEnd !== item.end() && textEnd === run.end;
100-
const ax = item.measure(textEnd, 1, state).advance;
101-
102-
if (item.attrs.level & 1) tx -= ax;
103111

104112
b.fillColor = run.style.color;
105113
b.fontSize = style.fontSize;
106114
b.font = item.face;
107115
b.direction = item.attrs.level & 1 ? 'rtl' : 'ltr';
108116
b.text(tx, item.y, item, textStart, textEnd, isColorBoundary);
109-
110-
if (!(item.attrs.level & 1)) tx += ax;
111117
}
112-
113118
}
114119

115120
/**

0 commit comments

Comments
 (0)