Skip to content

Commit 4af193b

Browse files
Merge pull request #20491 from nicolo-ribaudo/move-text-scaling-logic-to-css
Move text layer scaling logic to CSS
2 parents d946f05 + eb2b7c2 commit 4af193b

3 files changed

Lines changed: 28 additions & 23 deletions

File tree

src/display/text_layer.js

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class TextLayer {
128128
this.#pageHeight = pageHeight;
129129

130130
TextLayer.#ensureMinFontSizeComputed();
131+
container.style.setProperty("--min-font-size", TextLayer.#minFontSize);
131132

132133
setLayerDimensions(container, viewport);
133134

@@ -342,7 +343,6 @@ class TextLayer {
342343
top = tx[5] - fontAscent * Math.cos(angle);
343344
}
344345

345-
const scaleFactorStr = "calc(var(--total-scale-factor) *";
346346
const divStyle = textDiv.style;
347347
// Setting the style properties individually, rather than all at once,
348348
// should be OK since the `textDiv` isn't appended to the document yet.
@@ -351,14 +351,10 @@ class TextLayer {
351351
divStyle.top = `${((100 * top) / this.#pageHeight).toFixed(2)}%`;
352352
} else {
353353
// We're in a marked content span, hence we can't use percents.
354-
divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`;
355-
divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`;
354+
divStyle.left = `calc(var(--total-scale-factor) * ${left.toFixed(2)}px)`;
355+
divStyle.top = `calc(var(--total-scale-factor) * ${top.toFixed(2)}px)`;
356356
}
357-
// We multiply the font size by #minFontSize, and then #layout will
358-
// scale the element by 1/#minFontSize. This allows us to effectively
359-
// ignore the minimum font size enforced by the browser, so that the text
360-
// layer <span>s can always match the size of the text in the canvas.
361-
divStyle.fontSize = `${scaleFactorStr}${(TextLayer.#minFontSize * fontHeight).toFixed(2)}px)`;
357+
divStyle.setProperty("--font-height", `${fontHeight.toFixed(2)}px`);
362358
divStyle.fontFamily = fontFamily;
363359

364360
textDivProperties.fontSize = fontHeight;
@@ -421,11 +417,6 @@ class TextLayer {
421417
const { div, properties, ctx } = params;
422418
const { style } = div;
423419

424-
let transform = "";
425-
if (TextLayer.#minFontSize > 1) {
426-
transform = `scale(${1 / TextLayer.#minFontSize})`;
427-
}
428-
429420
if (properties.canvasWidth !== 0 && properties.hasText) {
430421
const { fontFamily } = style;
431422
const { canvasWidth, fontSize } = properties;
@@ -435,14 +426,11 @@ class TextLayer {
435426
const { width } = ctx.measureText(div.textContent);
436427

437428
if (width > 0) {
438-
transform = `scaleX(${(canvasWidth * this.#scale) / width}) ${transform}`;
429+
style.setProperty("--scale-x", (canvasWidth * this.#scale) / width);
439430
}
440431
}
441432
if (properties.angle !== 0) {
442-
transform = `rotate(${properties.angle}deg) ${transform}`;
443-
}
444-
if (transform.length > 0) {
445-
style.transform = transform;
433+
style.setProperty("--rotate", `${properties.angle}deg`);
446434
}
447435
}
448436

test/unit/text_layer_spec.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@ describe("textLayer", function () {
101101
const getTransform = container => {
102102
const transform = [];
103103

104-
for (const span of container.childNodes) {
105-
const t = span.style.transform;
106-
expect(t).toMatch(/^scaleX\([\d.]+\)$/);
107-
108-
transform.push(t);
104+
for (const { style } of container.childNodes) {
105+
transform.push({
106+
fontHeight: style.getPropertyValue("--font-height"),
107+
scaleX: style.getPropertyValue("--scale-x"),
108+
rotate: style.getPropertyValue("--rotate"),
109+
});
109110
}
110111
return transform;
111112
};

web/text_layer_builder.css

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,25 @@
3838
transform-origin: 0% 0%;
3939
}
4040

41+
/* We multiply the font size by --min-font-size, and then scale the text
42+
* elements by 1/--min-font-size. This allows us to effectively ignore the
43+
* minimum font size enforced by the browser, so that the text layer <span>s
44+
* can always match the size of the text in the canvas. */
45+
--min-font-size: 1;
46+
--text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
47+
--min-font-size-inv: calc(1 / var(--min-font-size));
48+
4149
> :not(.markedContent),
4250
.markedContent span:not(.markedContent) {
4351
z-index: 1;
52+
53+
--font-height: 0; /* set by text_layer.js */
54+
font-size: calc(var(--text-scale-factor) * var(--font-height));
55+
56+
--scale-x: 1;
57+
--rotate: 0deg;
58+
transform: rotate(var(--rotate)) scaleX(var(--scale-x))
59+
scale(var(--min-font-size-inv));
4460
}
4561

4662
/* Only necessary in Google Chrome, see issue 14205, and most unfortunately

0 commit comments

Comments
 (0)