Skip to content

Commit

Permalink
Merge pull request #19469 from Snuffleupagus/bug-1947248
Browse files Browse the repository at this point in the history
[api-major] Apply the `userUnit` using CSS, to fix the text/annotation layers (bug 1947248)
  • Loading branch information
Snuffleupagus authored Feb 11, 2025
2 parents 5b13ea1 + bd05b25 commit d6f63d0
Show file tree
Hide file tree
Showing 16 changed files with 81 additions and 46 deletions.
2 changes: 1 addition & 1 deletion src/core/xfa/template.js
Original file line number Diff line number Diff line change
Expand Up @@ -1421,7 +1421,7 @@ class ChoiceList extends XFAObject {
const field = ui[$getParent]();
const fontSize = field.font?.size || 10;
const optionStyle = {
fontSize: `calc(${fontSize}px * var(--scale-factor))`,
fontSize: `calc(${fontSize}px * var(--total-scale-factor))`,
};
const children = [];

Expand Down
2 changes: 1 addition & 1 deletion src/core/xfa/xhtml.js
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ function mapStyle(styleStr, node, richText) {
}

if (richText && style.fontSize) {
style.fontSize = `calc(${style.fontSize} * var(--scale-factor))`;
style.fontSize = `calc(${style.fontSize} * var(--total-scale-factor))`;
}

fixTextIndent(style);
Expand Down
10 changes: 5 additions & 5 deletions src/display/annotation_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,10 @@ class AnnotationElement {
const horizontalRadius = data.borderStyle.horizontalCornerRadius;
const verticalRadius = data.borderStyle.verticalCornerRadius;
if (horizontalRadius > 0 || verticalRadius > 0) {
const radius = `calc(${horizontalRadius}px * var(--scale-factor)) / calc(${verticalRadius}px * var(--scale-factor))`;
const radius = `calc(${horizontalRadius}px * var(--total-scale-factor)) / calc(${verticalRadius}px * var(--total-scale-factor))`;
style.borderRadius = radius;
} else if (this instanceof RadioButtonWidgetAnnotationElement) {
const radius = `calc(${width}px * var(--scale-factor)) / calc(${height}px * var(--scale-factor))`;
const radius = `calc(${width}px * var(--total-scale-factor)) / calc(${height}px * var(--total-scale-factor))`;
style.borderRadius = radius;
}

Expand Down Expand Up @@ -1194,7 +1194,7 @@ class WidgetAnnotationElement extends AnnotationElement {
roundToOneDecimal(height / LINE_FACTOR)
);
}
style.fontSize = `calc(${computedFontSize}px * var(--scale-factor))`;
style.fontSize = `calc(${computedFontSize}px * var(--total-scale-factor))`;

style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);

Expand Down Expand Up @@ -1553,7 +1553,7 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
const combWidth = fieldWidth / maxLen;

element.classList.add("comb");
element.style.letterSpacing = `calc(${combWidth}px * var(--scale-factor) - 1ch)`;
element.style.letterSpacing = `calc(${combWidth}px * var(--total-scale-factor) - 1ch)`;
}
} else {
element = document.createElement("div");
Expand Down Expand Up @@ -2279,7 +2279,7 @@ class PopupElement {
style: {
color: this.#fontColor,
fontSize: this.#fontSize
? `calc(${this.#fontSize}px * var(--scale-factor))`
? `calc(${this.#fontSize}px * var(--total-scale-factor))`
: "",
},
};
Expand Down
11 changes: 5 additions & 6 deletions src/display/display_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,7 @@ class PageViewport {
* @type {Object}
*/
get rawDims() {
const { userUnit, viewBox } = this;
const dims = viewBox.map(x => x * userUnit);
const dims = this.viewBox;

return shadow(this, "rawDims", {
pageWidth: dims[2] - dims[0],
Expand Down Expand Up @@ -597,13 +596,13 @@ function setLayerDimensions(
const { style } = div;
const useRound = FeatureTest.isCSSRoundSupported;

const w = `var(--scale-factor) * ${pageWidth}px`,
h = `var(--scale-factor) * ${pageHeight}px`;
const w = `var(--total-scale-factor) * ${pageWidth}px`,
h = `var(--total-scale-factor) * ${pageHeight}px`;
const widthStr = useRound
? `round(down, ${w}, var(--scale-round-x, 1px))`
? `round(down, ${w}, var(--scale-round-x))`
: `calc(${w})`,
heightStr = useRound
? `round(down, ${h}, var(--scale-round-y, 1px))`
? `round(down, ${h}, var(--scale-round-y))`
: `calc(${h})`;

if (!mustFlip || viewport.rotation % 180 === 0) {
Expand Down
6 changes: 3 additions & 3 deletions src/display/editor/freetext.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ class FreeTextEditor extends AnnotationEditor {
*/
#updateFontSize(fontSize) {
const setFontsize = size => {
this.editorDiv.style.fontSize = `calc(${size}px * var(--scale-factor))`;
this.editorDiv.style.fontSize = `calc(${size}px * var(--total-scale-factor))`;
this.translate(0, -(size - this.#fontSize) * this.parentScale);
this.#fontSize = size;
this.#setEditorDimensions();
Expand Down Expand Up @@ -570,7 +570,7 @@ class FreeTextEditor extends AnnotationEditor {
this.editorDiv.contentEditable = true;

const { style } = this.editorDiv;
style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;
style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`;
style.color = this.#color;

this.div.append(this.editorDiv);
Expand Down Expand Up @@ -878,7 +878,7 @@ class FreeTextEditor extends AnnotationEditor {
return content;
}
const { style } = content;
style.fontSize = `calc(${this.#fontSize}px * var(--scale-factor))`;
style.fontSize = `calc(${this.#fontSize}px * var(--total-scale-factor))`;
style.color = this.#color;

content.replaceChildren();
Expand Down
2 changes: 1 addition & 1 deletion src/display/text_layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ class TextLayer {
top = tx[5] - fontAscent * Math.cos(angle);
}

const scaleFactorStr = "calc(var(--scale-factor)*";
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.
Expand Down
28 changes: 17 additions & 11 deletions test/driver.js
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,18 @@ class Rasterize {
return { svg, foreignObject, style, div };
}

static createRootCSS(viewport) {
const { scale, userUnit } = viewport;
return [
":root {",
" --scale-round-x: 1px; --scale-round-y: 1px;",
` --scale-factor: ${scale};`,
` --user-unit: ${userUnit};`,
` --total-scale-factor: ${scale * userUnit};`,
"}",
].join("\n");
}

static async annotationLayer(
ctx,
viewport,
Expand All @@ -232,9 +244,7 @@ class Rasterize {
div.className = "annotationLayer";

const [common, overrides] = await this.annotationStylePromise;
style.textContent =
`${common}\n${overrides}\n` +
`:root { --scale-factor: ${viewport.scale} }`;
style.textContent = `${common}\n${overrides}\n${this.createRootCSS(viewport)}`;

const annotationViewport = viewport.clone({ dontFlip: true });
const annotationImageMap = await convertCanvasesToImages(
Expand Down Expand Up @@ -293,9 +303,7 @@ class Rasterize {
svg.setAttribute("font-size", 1);

const [common, overrides] = await this.textStylePromise;
style.textContent =
`${common}\n${overrides}\n` +
`:root { --scale-factor: ${viewport.scale} }`;
style.textContent = `${common}\n${overrides}\n${this.createRootCSS(viewport)}`;

// Rendering text layer as HTML.
const textLayer = new TextLayer({
Expand All @@ -322,9 +330,7 @@ class Rasterize {
svg.setAttribute("font-size", 1);

const [common, overrides] = await this.drawLayerStylePromise;
style.textContent =
`${common}\n${overrides}` +
`:root { --scale-factor: ${viewport.scale} }`;
style.textContent = `${common}\n${overrides}\n${this.createRootCSS(viewport)}`;

// Rendering text layer as HTML.
const textLayer = new TextLayer({
Expand All @@ -346,9 +352,9 @@ class Rasterize {
let x = parseFloat(left) / 100;
let y = parseFloat(top) / 100;
if (isNaN(x)) {
posRegex ||= /^calc\(var\(--scale-factor\)\*(.*)px\)$/;
posRegex ||= /^calc\(var\(--total-scale-factor\)\s*\*(.*)px\)$/;
// The element is tagged so we've to extract the position from the
// string, e.g. `calc(var(--scale-factor)*66.32px)`.
// string, e.g. `calc(var(--total-scale-factor)*66.32px)`.
let match = left.match(posRegex);
if (match) {
x = parseFloat(match[1]) / pageWidth;
Expand Down
2 changes: 2 additions & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,8 @@
!poppler-85140-0.pdf
!issue15012.pdf
!issue19176.pdf
!bug1947248_text.pdf
!bug1947248_forms.pdf
!issue15150.pdf
!poppler-395-0-fuzzed.pdf
!issue14165.pdf
Expand Down
Binary file added test/pdfs/bug1947248_forms.pdf
Binary file not shown.
Binary file added test/pdfs/bug1947248_text.pdf
Binary file not shown.
15 changes: 15 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2749,6 +2749,21 @@
"rounds": 1,
"type": "eq"
},
{
"id": "bug1947248-text",
"file": "pdfs/bug1947248_text.pdf",
"md5": "491f1df75b77d2762ff96ce51f5e019b",
"rounds": 1,
"type": "text"
},
{
"id": "bug1947248-forms",
"file": "pdfs/bug1947248_forms.pdf",
"md5": "456c974d7d4351719f36ef10e603d29c",
"rounds": 1,
"type": "eq",
"forms": true
},
{
"id": "issue4801",
"file": "pdfs/issue4801.pdf",
Expand Down
4 changes: 2 additions & 2 deletions web/annotation_editor_layer_builder.css
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@
background: transparent;
position: absolute;
inset: 0;
font-size: calc(100px * var(--scale-factor));
font-size: calc(100px * var(--total-scale-factor));
transform-origin: 0 0;
cursor: auto;

Expand Down Expand Up @@ -512,7 +512,7 @@
}

.annotationEditorLayer .freeTextEditor {
padding: calc(var(--freetext-padding) * var(--scale-factor));
padding: calc(var(--freetext-padding) * var(--total-scale-factor));
width: auto;
height: auto;
touch-action: none;
Expand Down
26 changes: 13 additions & 13 deletions web/annotation_layer_builder.css
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
}

.popupAnnotation .popup {
outline: calc(1.5px * var(--scale-factor)) solid CanvasText !important;
outline: calc(1.5px * var(--total-scale-factor)) solid CanvasText !important;
background-color: ButtonFace !important;
color: ButtonText !important;
}
Expand All @@ -67,7 +67,7 @@
}

.popupAnnotation.focused .popup {
outline: calc(3px * var(--scale-factor)) solid Highlight !important;
outline: calc(3px * var(--total-scale-factor)) solid Highlight !important;
}
}

Expand Down Expand Up @@ -169,7 +169,7 @@
background-image: var(--annotation-unfocused-field-background);
border: 2px solid var(--input-unfocused-border-color);
box-sizing: border-box;
font: calc(9px * var(--scale-factor)) sans-serif;
font: calc(9px * var(--total-scale-factor)) sans-serif;
height: 100%;
margin: 0;
vertical-align: top;
Expand Down Expand Up @@ -296,7 +296,7 @@

.popupAnnotation {
position: absolute;
font-size: calc(9px * var(--scale-factor));
font-size: calc(9px * var(--total-scale-factor));
pointer-events: none;
width: max-content;
max-width: 45%;
Expand All @@ -305,11 +305,11 @@

.popup {
background-color: rgb(255 255 153);
box-shadow: 0 calc(2px * var(--scale-factor))
calc(5px * var(--scale-factor)) rgb(136 136 136);
border-radius: calc(2px * var(--scale-factor));
box-shadow: 0 calc(2px * var(--total-scale-factor))
calc(5px * var(--total-scale-factor)) rgb(136 136 136);
border-radius: calc(2px * var(--total-scale-factor));
outline: 1.5px solid rgb(255 255 74);
padding: calc(6px * var(--scale-factor));
padding: calc(6px * var(--total-scale-factor));
cursor: pointer;
font: message-box;
white-space: normal;
Expand All @@ -323,7 +323,7 @@
}

.popup * {
font-size: calc(9px * var(--scale-factor));
font-size: calc(9px * var(--total-scale-factor));
}

.popup > .header {
Expand All @@ -336,19 +336,19 @@

.popup > .header .popupDate {
display: inline-block;
margin-left: calc(5px * var(--scale-factor));
margin-left: calc(5px * var(--total-scale-factor));
width: fit-content;
}

.popupContent {
border-top: 1px solid rgb(51 51 51);
margin-top: calc(2px * var(--scale-factor));
padding-top: calc(2px * var(--scale-factor));
margin-top: calc(2px * var(--total-scale-factor));
padding-top: calc(2px * var(--total-scale-factor));
}

.richText > * {
white-space: pre-wrap;
font-size: calc(9px * var(--scale-factor));
font-size: calc(9px * var(--total-scale-factor));
}

.popupTriggerArea {
Expand Down
15 changes: 13 additions & 2 deletions web/pdf_page_view.js
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,8 @@ class PDFPageView {

#textLayerMode = TextLayerMode.ENABLE;

#userUnit = 1;

#useThumbnailCanvas = {
directDrawing: true,
initialOptionalContent: true,
Expand Down Expand Up @@ -314,7 +316,16 @@ class PDFPageView {
}

#setDimensions() {
const { viewport } = this;
const { div, viewport } = this;

if (viewport.userUnit !== this.#userUnit) {
if (viewport.userUnit !== 1) {
div.style.setProperty("--user-unit", viewport.userUnit);
} else {
div.style.removeProperty("--user-unit");
}
this.#userUnit = viewport.userUnit;
}
if (this.pdfPage) {
if (this.#previousRotation === viewport.rotation) {
return;
Expand All @@ -323,7 +334,7 @@ class PDFPageView {
}

setLayerDimensions(
this.div,
div,
viewport,
/* mustFlip = */ true,
/* mustRotate = */ false
Expand Down
2 changes: 2 additions & 0 deletions web/pdf_viewer.css
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@
}

.pdfViewer .page {
--user-unit: 1;
--total-scale-factor: calc(var(--scale-factor) * var(--user-unit));
--scale-round-x: 1px;
--scale-round-y: 1px;

Expand Down
2 changes: 1 addition & 1 deletion web/struct_tree_layer_builder.js
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ class StructTreeLayerBuilder {
img.setAttribute("aria-label", removeNullCharacters(alt));

const { pageHeight, pageX, pageY } = this.#rawDims;
const calc = "calc(var(--scale-factor)*";
const calc = "calc(var(--total-scale-factor) *";
const { style } = img;
style.width = `${calc}${bbox[2] - bbox[0]}px)`;
style.height = `${calc}${bbox[3] - bbox[1]}px)`;
Expand Down

0 comments on commit d6f63d0

Please sign in to comment.