mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-02-08 00:21:11 +01:00
Move text layer scaling logic to CSS
This commit moves all the logic to scale up&down `<span>`s in the text layer, introduced in #18283, to CSS. The motivation for this change is that #18283 is still not enough for all cases. That PR fixed the problem in Chrome&Firefox desktop, which allow users to set an actual minimum font size in the browser settings. However, other browsers (e.g. the Chrome-based WebView on Android) have more complex logic and they scale up small text rather than simply applying a minimum. A workaround for that behavior is probably out of scope for PDF.js itself as it only affects not officially supported platforms. However, having access to the actual expected font height (through `--font-height`) allows embedders of PDF.js to implement a workaround by themselves.
This commit is contained in:
parent
f75812b0af
commit
eb2b7c2c86
@ -128,6 +128,7 @@ class TextLayer {
|
||||
this.#pageHeight = pageHeight;
|
||||
|
||||
TextLayer.#ensureMinFontSizeComputed();
|
||||
container.style.setProperty("--min-font-size", TextLayer.#minFontSize);
|
||||
|
||||
setLayerDimensions(container, viewport);
|
||||
|
||||
@ -342,7 +343,6 @@ class TextLayer {
|
||||
top = tx[5] - fontAscent * Math.cos(angle);
|
||||
}
|
||||
|
||||
const scaleFactorStr = "calc(var(--total-scale-factor) *";
|
||||
const divStyle = textDiv.style;
|
||||
// Setting the style properties individually, rather than all at once,
|
||||
// should be OK since the `textDiv` isn't appended to the document yet.
|
||||
@ -351,14 +351,10 @@ class TextLayer {
|
||||
divStyle.top = `${((100 * top) / this.#pageHeight).toFixed(2)}%`;
|
||||
} else {
|
||||
// We're in a marked content span, hence we can't use percents.
|
||||
divStyle.left = `${scaleFactorStr}${left.toFixed(2)}px)`;
|
||||
divStyle.top = `${scaleFactorStr}${top.toFixed(2)}px)`;
|
||||
divStyle.left = `calc(var(--total-scale-factor) * ${left.toFixed(2)}px)`;
|
||||
divStyle.top = `calc(var(--total-scale-factor) * ${top.toFixed(2)}px)`;
|
||||
}
|
||||
// We multiply the font size by #minFontSize, and then #layout will
|
||||
// scale the element by 1/#minFontSize. This allows us to effectively
|
||||
// ignore the minimum font size enforced by the browser, so that the text
|
||||
// layer <span>s can always match the size of the text in the canvas.
|
||||
divStyle.fontSize = `${scaleFactorStr}${(TextLayer.#minFontSize * fontHeight).toFixed(2)}px)`;
|
||||
divStyle.setProperty("--font-height", `${fontHeight.toFixed(2)}px`);
|
||||
divStyle.fontFamily = fontFamily;
|
||||
|
||||
textDivProperties.fontSize = fontHeight;
|
||||
@ -421,11 +417,6 @@ class TextLayer {
|
||||
const { div, properties, ctx } = params;
|
||||
const { style } = div;
|
||||
|
||||
let transform = "";
|
||||
if (TextLayer.#minFontSize > 1) {
|
||||
transform = `scale(${1 / TextLayer.#minFontSize})`;
|
||||
}
|
||||
|
||||
if (properties.canvasWidth !== 0 && properties.hasText) {
|
||||
const { fontFamily } = style;
|
||||
const { canvasWidth, fontSize } = properties;
|
||||
@ -435,14 +426,11 @@ class TextLayer {
|
||||
const { width } = ctx.measureText(div.textContent);
|
||||
|
||||
if (width > 0) {
|
||||
transform = `scaleX(${(canvasWidth * this.#scale) / width}) ${transform}`;
|
||||
style.setProperty("--scale-x", (canvasWidth * this.#scale) / width);
|
||||
}
|
||||
}
|
||||
if (properties.angle !== 0) {
|
||||
transform = `rotate(${properties.angle}deg) ${transform}`;
|
||||
}
|
||||
if (transform.length > 0) {
|
||||
style.transform = transform;
|
||||
style.setProperty("--rotate", `${properties.angle}deg`);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -101,11 +101,12 @@ describe("textLayer", function () {
|
||||
const getTransform = container => {
|
||||
const transform = [];
|
||||
|
||||
for (const span of container.childNodes) {
|
||||
const t = span.style.transform;
|
||||
expect(t).toMatch(/^scaleX\([\d.]+\)$/);
|
||||
|
||||
transform.push(t);
|
||||
for (const { style } of container.childNodes) {
|
||||
transform.push({
|
||||
fontHeight: style.getPropertyValue("--font-height"),
|
||||
scaleX: style.getPropertyValue("--scale-x"),
|
||||
rotate: style.getPropertyValue("--rotate"),
|
||||
});
|
||||
}
|
||||
return transform;
|
||||
};
|
||||
|
||||
@ -38,9 +38,25 @@
|
||||
transform-origin: 0% 0%;
|
||||
}
|
||||
|
||||
/* We multiply the font size by --min-font-size, and then scale the text
|
||||
* elements by 1/--min-font-size. This allows us to effectively ignore the
|
||||
* minimum font size enforced by the browser, so that the text layer <span>s
|
||||
* can always match the size of the text in the canvas. */
|
||||
--min-font-size: 1;
|
||||
--text-scale-factor: calc(var(--total-scale-factor) * var(--min-font-size));
|
||||
--min-font-size-inv: calc(1 / var(--min-font-size));
|
||||
|
||||
> :not(.markedContent),
|
||||
.markedContent span:not(.markedContent) {
|
||||
z-index: 1;
|
||||
|
||||
--font-height: 0; /* set by text_layer.js */
|
||||
font-size: calc(var(--text-scale-factor) * var(--font-height));
|
||||
|
||||
--scale-x: 1;
|
||||
--rotate: 0deg;
|
||||
transform: rotate(var(--rotate)) scaleX(var(--scale-x))
|
||||
scale(var(--min-font-size-inv));
|
||||
}
|
||||
|
||||
/* Only necessary in Google Chrome, see issue 14205, and most unfortunately
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user