Skip to content

Commit a320efd

Browse files
Measure text bbox independently from the rendering canvas
1 parent 24e8849 commit a320efd

2 files changed

Lines changed: 57 additions & 18 deletions

File tree

src/display/canvas.js

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1987,7 +1987,9 @@ class CanvasGraphics {
19871987
}
19881988
this.current.fontSizeScale = size / browserFontSize;
19891989

1990-
this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
1990+
const fontString = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
1991+
this.ctx.font = fontString;
1992+
this.dependencyTracker?.setFont(fontString);
19911993
}
19921994

19931995
setTextRenderingMode(opIdx, mode) {
@@ -2087,7 +2089,7 @@ class CanvasGraphics {
20872089
dt
20882090
.translate(x, y)
20892091
.scale(fontSize, -fontSize)
2090-
.recordCharacterBBox(opIdx, font)
2092+
.recordCharacterBBox(opIdx, null, font)
20912093
);
20922094

20932095
let currentTransform;
@@ -2146,11 +2148,11 @@ class CanvasGraphics {
21462148
ctx.fillText(character, x, y);
21472149
this.dependencyTracker?.recordCharacterBBox(
21482150
opIdx,
2151+
character,
21492152
font,
21502153
fontSize,
21512154
x,
2152-
y,
2153-
() => ctx.measureText(character)
2155+
y
21542156
);
21552157
}
21562158
if (
@@ -2159,9 +2161,7 @@ class CanvasGraphics {
21592161
) {
21602162
if (this.dependencyTracker) {
21612163
this.dependencyTracker
2162-
?.recordCharacterBBox(opIdx, font, fontSize, x, y, () =>
2163-
ctx.measureText(character)
2164-
)
2164+
?.recordCharacterBBox(opIdx, character, font, fontSize, x, y)
21652165
.recordDependencies(opIdx, Dependencies.stroke);
21662166
}
21672167
ctx.strokeText(character, x, y);
@@ -2177,7 +2177,14 @@ class CanvasGraphics {
21772177
fontSize,
21782178
path,
21792179
});
2180-
this.dependencyTracker?.recordCharacterBBox(opIdx, font, fontSize, x, y);
2180+
this.dependencyTracker?.recordCharacterBBox(
2181+
opIdx,
2182+
null,
2183+
font,
2184+
fontSize,
2185+
x,
2186+
y
2187+
);
21812188
}
21822189
}
21832190

@@ -2332,7 +2339,7 @@ class CanvasGraphics {
23322339
const joinedChars = chars.join("");
23332340
ctx.fillText(joinedChars, 0, 0);
23342341
if (dependencyTracker !== null) {
2335-
const measure = ctx.measureText(joinedChars);
2342+
const measure = dependencyTracker.measureText(joinedChars);
23362343
dependencyTracker
23372344
.recordBBox(
23382345
opIdx,
@@ -2410,12 +2417,12 @@ class CanvasGraphics {
24102417

24112418
this.dependencyTracker?.recordCharacterBBox(
24122419
opIdx,
2420+
character,
24132421
// If we already measured the character, force usage of that
24142422
measure ? { bbox: null } : font,
24152423
fontSize / fontSizeScale,
24162424
scaledX,
2417-
scaledY,
2418-
() => measure ?? ctx.measureText(character)
2425+
scaledY
24192426
);
24202427
} else {
24212428
this.paintChar(

src/display/canvas_dependency_tracker.js

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,15 @@ class CanvasBBoxTracker {
358358
return this;
359359
}
360360

361-
recordCharacterBBox(idx, font, scale = 1, x = 0, y = 0, getMeasure) {
361+
setFont(fontString) {
362+
return this;
363+
}
364+
365+
measureText(text) {
366+
return null;
367+
}
368+
369+
recordCharacterBBox(idx, character, font, scale = 1, x = 0, y = 0) {
362370
return this;
363371
}
364372

@@ -449,6 +457,12 @@ class CanvasDependencyTracker {
449457

450458
#fontBBoxTrustworthy = new Map();
451459

460+
// TODO: No tests are failing, but we should set the lang here as it can
461+
// affect the used fallback fonts. Probably no tests are failing because we
462+
// round bboxes anyway, so it's extremely unlikely that after rounding the
463+
// two fonts still have different bboxes.
464+
#fontMeasureCtx = new OffscreenCanvas(0, 0).getContext("2d");
465+
452466
#debugMetadata;
453467

454468
#recordDebugMetadataDepenencyAfterRestore;
@@ -664,7 +678,16 @@ class CanvasDependencyTracker {
664678
return this;
665679
}
666680

667-
recordCharacterBBox(idx, font, scale = 1, x = 0, y = 0, getMeasure) {
681+
setFont(fontString) {
682+
this.#fontMeasureCtx.font = fontString;
683+
return this;
684+
}
685+
686+
measureText(text) {
687+
return this.#fontMeasureCtx.measureText(text);
688+
}
689+
690+
recordCharacterBBox(idx, character, font, scale = 1, x = 0, y = 0) {
668691
const fontBBox = font.bbox;
669692
let isBBoxTrustworthy;
670693
let computedBBox;
@@ -696,13 +719,13 @@ class CanvasDependencyTracker {
696719
}
697720
}
698721

699-
if (!getMeasure) {
722+
if (!character) {
700723
// We have no way of telling how big this character actually is, record
701724
// a full page bounding box.
702725
return this.recordFullPageBBox(idx);
703726
}
704727

705-
const measure = getMeasure();
728+
const measure = this.#fontMeasureCtx.measureText(character);
706729

707730
if (fontBBox && computedBBox && isBBoxTrustworthy === undefined) {
708731
// If it's the first time we can compare the font bbox with the actual
@@ -925,6 +948,15 @@ class CanvasNestedDependencyTracker {
925948
return this;
926949
}
927950

951+
setFont(fontString) {
952+
this.#dependencyTracker.setFont(fontString);
953+
return this;
954+
}
955+
956+
measureText(text) {
957+
return this.#dependencyTracker.measureText(text);
958+
}
959+
928960
getTransform() {
929961
return this.#dependencyTracker.getTransform();
930962
}
@@ -1045,15 +1077,15 @@ class CanvasNestedDependencyTracker {
10451077
return this;
10461078
}
10471079

1048-
recordCharacterBBox(idx, font, scale, x, y, getMeasure) {
1080+
recordCharacterBBox(idx, character, font, scale, x, y) {
10491081
if (!this.#ignoreBBoxes) {
10501082
this.#dependencyTracker.recordCharacterBBox(
10511083
this.#opIdx,
1084+
character,
10521085
font,
10531086
scale,
10541087
x,
1055-
y,
1056-
getMeasure
1088+
y
10571089
);
10581090
}
10591091
return this;

0 commit comments

Comments
 (0)