Skip to content

Commit a1d8271

Browse files
Measure text bbox independently from the rendering canvas
1 parent 54a18e0 commit a1d8271

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
@@ -1816,7 +1816,9 @@ class CanvasGraphics {
18161816
}
18171817
this.current.fontSizeScale = size / browserFontSize;
18181818

1819-
this.ctx.font = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
1819+
const fontString = `${italic} ${bold} ${browserFontSize}px ${typeface}`;
1820+
this.ctx.font = fontString;
1821+
this.dependencyTracker?.setFont(fontString);
18201822
}
18211823

18221824
setTextRenderingMode(opIdx, mode) {
@@ -1916,7 +1918,7 @@ class CanvasGraphics {
19161918
dt
19171919
.translate(x, y)
19181920
.scale(fontSize, -fontSize)
1919-
.recordCharacterBBox(opIdx, font)
1921+
.recordCharacterBBox(opIdx, null, font)
19201922
);
19211923

19221924
let currentTransform;
@@ -1975,11 +1977,11 @@ class CanvasGraphics {
19751977
ctx.fillText(character, x, y);
19761978
this.dependencyTracker?.recordCharacterBBox(
19771979
opIdx,
1980+
character,
19781981
font,
19791982
fontSize,
19801983
x,
1981-
y,
1982-
() => ctx.measureText(character)
1984+
y
19831985
);
19841986
}
19851987
if (
@@ -1988,9 +1990,7 @@ class CanvasGraphics {
19881990
) {
19891991
if (this.dependencyTracker) {
19901992
this.dependencyTracker
1991-
?.recordCharacterBBox(opIdx, font, fontSize, x, y, () =>
1992-
ctx.measureText(character)
1993-
)
1993+
?.recordCharacterBBox(opIdx, character, font, fontSize, x, y)
19941994
.recordDependencies(opIdx, Dependencies.stroke);
19951995
}
19961996
ctx.strokeText(character, x, y);
@@ -2006,7 +2006,14 @@ class CanvasGraphics {
20062006
fontSize,
20072007
path,
20082008
});
2009-
this.dependencyTracker?.recordCharacterBBox(opIdx, font, fontSize, x, y);
2009+
this.dependencyTracker?.recordCharacterBBox(
2010+
opIdx,
2011+
null,
2012+
font,
2013+
fontSize,
2014+
x,
2015+
y
2016+
);
20102017
}
20112018
}
20122019

@@ -2161,7 +2168,7 @@ class CanvasGraphics {
21612168
const joinedChars = chars.join("");
21622169
ctx.fillText(joinedChars, 0, 0);
21632170
if (dependencyTracker !== null) {
2164-
const measure = ctx.measureText(joinedChars);
2171+
const measure = dependencyTracker.measureText(joinedChars);
21652172
dependencyTracker
21662173
.recordBBox(
21672174
opIdx,
@@ -2239,12 +2246,12 @@ class CanvasGraphics {
22392246

22402247
this.dependencyTracker?.recordCharacterBBox(
22412248
opIdx,
2249+
character,
22422250
// If we already measured the character, force usage of that
22432251
measure ? { bbox: null } : font,
22442252
fontSize / fontSizeScale,
22452253
scaledX,
2246-
scaledY,
2247-
() => measure ?? ctx.measureText(character)
2254+
scaledY
22482255
);
22492256
} else {
22502257
this.paintChar(

src/display/canvas_dependency_tracker.js

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -370,7 +370,15 @@ class CanvasBBoxTracker {
370370
return this;
371371
}
372372

373-
recordCharacterBBox(idx, font, scale = 1, x = 0, y = 0, getMeasure) {
373+
setFont(fontString) {
374+
return this;
375+
}
376+
377+
measureText(text) {
378+
return null;
379+
}
380+
381+
recordCharacterBBox(idx, character, font, scale = 1, x = 0, y = 0) {
374382
return this;
375383
}
376384

@@ -461,6 +469,12 @@ class CanvasDependencyTracker {
461469

462470
#fontBBoxTrustworthy = new Map();
463471

472+
// TODO: No tests are failing, but we should set the lang here as it can
473+
// affect the used fallback fonts. Probably no tests are failing because we
474+
// round bboxes anyway, so it's extremely unlikely that after rounding the
475+
// two fonts still have different bboxes.
476+
#fontMeasureCtx = new OffscreenCanvas(0, 0).getContext("2d");
477+
464478
#debugMetadata;
465479

466480
#recordDebugMetadataDepenencyAfterRestore;
@@ -676,7 +690,16 @@ class CanvasDependencyTracker {
676690
return this;
677691
}
678692

679-
recordCharacterBBox(idx, font, scale = 1, x = 0, y = 0, getMeasure) {
693+
setFont(fontString) {
694+
this.#fontMeasureCtx.font = fontString;
695+
return this;
696+
}
697+
698+
measureText(text) {
699+
return this.#fontMeasureCtx.measureText(text);
700+
}
701+
702+
recordCharacterBBox(idx, character, font, scale = 1, x = 0, y = 0) {
680703
const fontBBox = font.bbox;
681704
let isBBoxTrustworthy;
682705
let computedBBox;
@@ -708,13 +731,13 @@ class CanvasDependencyTracker {
708731
}
709732
}
710733

711-
if (!getMeasure) {
734+
if (!character) {
712735
// We have no way of telling how big this character actually is, record
713736
// a full page bounding box.
714737
return this.recordFullPageBBox(idx);
715738
}
716739

717-
const measure = getMeasure();
740+
const measure = this.#fontMeasureCtx.measureText(character);
718741

719742
if (fontBBox && computedBBox && isBBoxTrustworthy === undefined) {
720743
// If it's the first time we can compare the font bbox with the actual
@@ -937,6 +960,15 @@ class CanvasNestedDependencyTracker {
937960
return this;
938961
}
939962

963+
setFont(fontString) {
964+
this.#dependencyTracker.setFont(fontString);
965+
return this;
966+
}
967+
968+
measureText(text) {
969+
return this.#dependencyTracker.measureText(text);
970+
}
971+
940972
getTransform() {
941973
return this.#dependencyTracker.getTransform();
942974
}
@@ -1057,15 +1089,15 @@ class CanvasNestedDependencyTracker {
10571089
return this;
10581090
}
10591091

1060-
recordCharacterBBox(idx, font, scale, x, y, getMeasure) {
1092+
recordCharacterBBox(idx, character, font, scale, x, y) {
10611093
if (!this.#ignoreBBoxes) {
10621094
this.#dependencyTracker.recordCharacterBBox(
10631095
this.#opIdx,
1096+
character,
10641097
font,
10651098
scale,
10661099
x,
1067-
y,
1068-
getMeasure
1100+
y
10691101
);
10701102
}
10711103
return this;

0 commit comments

Comments
 (0)