Skip to content

Commit 702a12c

Browse files
Measure text bbox independently from the rendering canvas
1 parent 3c1022d commit 702a12c

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
@@ -357,7 +357,15 @@ class CanvasBBoxTracker {
357357
return this;
358358
}
359359

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

@@ -448,6 +456,12 @@ class CanvasDependencyTracker {
448456

449457
#fontBBoxTrustworthy = new Map();
450458

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

453467
#recordDebugMetadataDepenencyAfterRestore;
@@ -663,7 +677,16 @@ class CanvasDependencyTracker {
663677
return this;
664678
}
665679

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

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

704-
const measure = getMeasure();
727+
const measure = this.#fontMeasureCtx.measureText(character);
705728

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

950+
setFont(fontString) {
951+
this.#dependencyTracker.setFont(fontString);
952+
return this;
953+
}
954+
955+
measureText(text) {
956+
return this.#dependencyTracker.measureText(text);
957+
}
958+
927959
getTransform() {
928960
return this.#dependencyTracker.getTransform();
929961
}
@@ -1044,15 +1076,15 @@ class CanvasNestedDependencyTracker {
10441076
return this;
10451077
}
10461078

1047-
recordCharacterBBox(idx, font, scale, x, y, getMeasure) {
1079+
recordCharacterBBox(idx, character, font, scale, x, y) {
10481080
if (!this.#ignoreBBoxes) {
10491081
this.#dependencyTracker.recordCharacterBBox(
10501082
this.#opIdx,
1083+
character,
10511084
font,
10521085
scale,
10531086
x,
1054-
y,
1055-
getMeasure
1087+
y
10561088
);
10571089
}
10581090
return this;

0 commit comments

Comments
 (0)