From 5f76b6370c91d7a4358edffb9caac667af9dd680 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Tue, 6 Jul 2021 14:11:21 +0200 Subject: [PATCH] XFA - Layout correctly a subform with row layout (bug 1718740) - Fix issues with subformSet elements which are not a real container. --- src/core/xfa/html_utils.js | 40 +++++++++---------------- src/core/xfa/layout.js | 13 ++++++-- src/core/xfa/template.js | 50 +++++++++++-------------------- test/pdfs/xfa_bug1718740.pdf.link | 1 + test/test_manifest.json | 8 +++++ 5 files changed, 52 insertions(+), 60 deletions(-) create mode 100644 test/pdfs/xfa_bug1718740.pdf.link diff --git a/src/core/xfa/html_utils.js b/src/core/xfa/html_utils.js index c089202b8..708e1e344 100644 --- a/src/core/xfa/html_utils.js +++ b/src/core/xfa/html_utils.js @@ -41,7 +41,7 @@ function measureToString(m) { const converters = { anchorType(node, style) { - const parent = node[$getParent](); + const parent = node[$getSubformParent](); if (!parent || (parent.layout && parent.layout !== "position")) { // anchorType is only used in a positioned layout. return; @@ -78,7 +78,7 @@ const converters = { } }, dimensions(node, style) { - const parent = node[$getParent](); + const parent = node[$getSubformParent](); let width = node.w; const height = node.h; if (parent.layout && parent.layout.includes("row")) { @@ -116,7 +116,7 @@ const converters = { } }, position(node, style) { - const parent = node[$getParent](); + const parent = node[$getSubformParent](); if (parent && parent.layout && parent.layout !== "position") { // IRL, we've some x/y in tb layout. // Specs say x/y is only used in positioned layout. @@ -182,14 +182,18 @@ const converters = { }; function setMinMaxDimensions(node, style) { - const parent = node[$getParent](); + const parent = node[$getSubformParent](); if (parent.layout === "position") { - style.minWidth = measureToString(node.minW); - if (node.maxW) { + if (node.minW > 0) { + style.minWidth = measureToString(node.minW); + } + if (node.maxW > 0) { style.maxWidth = measureToString(node.maxW); } - style.minHeight = measureToString(node.minH); - if (node.maxH) { + if (node.minH > 0) { + style.minHeight = measureToString(node.minH); + } + if (node.maxH > 0) { style.maxHeight = measureToString(node.maxH); } } @@ -297,7 +301,7 @@ function computeBbox(node, html, availableSpace) { let width = node.w; if (width === "") { if (node.maxW === 0) { - const parent = node[$getParent](); + const parent = node[$getSubformParent](); if (parent.layout === "position" && parent.w !== "") { width = 0; } else { @@ -312,7 +316,7 @@ function computeBbox(node, html, availableSpace) { let height = node.h; if (height === "") { if (node.maxH === 0) { - const parent = node[$getParent](); + const parent = node[$getSubformParent](); if (parent.layout === "position" && parent.h !== "") { height = 0; } else { @@ -349,25 +353,9 @@ function fixDimensions(node) { } } - if (parent.w && node.w) { - node.w = Math.min(parent.w, node.w); - } - - if (parent.h && node.h) { - node.h = Math.min(parent.h, node.h); - } - if (parent.layout && parent.layout !== "position") { // Useless in this context. node.x = node.y = 0; - if (parent.layout === "tb") { - if ( - parent.w !== "" && - (node.w === "" || node.w === 0 || node.w > parent.w) - ) { - node.w = parent.w; - } - } } if (node.layout === "table") { diff --git a/src/core/xfa/layout.js b/src/core/xfa/layout.js index dc46ac5e5..f82b42bf5 100644 --- a/src/core/xfa/layout.js +++ b/src/core/xfa/layout.js @@ -16,7 +16,7 @@ import { $extra, $flushHTML, - $getParent, + $getSubformParent, $getTemplateRoot, $isSplittable, } from "./xfa_object.js"; @@ -265,7 +265,7 @@ function checkDimensions(node, space) { return true; } - const parent = node[$getParent](); + const parent = node[$getSubformParent](); const attempt = (parent[$extra] && parent[$extra].attempt) || 0; let y, w, h; switch (parent.layout) { @@ -344,6 +344,15 @@ function checkDimensions(node, space) { return h + y > area.h; case "rl-row": case "row": + if (node[$getTemplateRoot]()[$extra].noLayoutFailure) { + return true; + } + + if (node.h !== "") { + [, , , h] = getTransformedBBox(node); + return Math.round(h - space.height) <= 1; + } + return true; default: // No layout, so accept everything. return true; diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js index c57b8194c..b3b87f930 100644 --- a/src/core/xfa/template.js +++ b/src/core/xfa/template.js @@ -1073,7 +1073,7 @@ class CheckButton extends XFAObject { const value = (field.value && field.value[$text]()) || "off"; const checked = value === exportedValue.on || undefined; - const container = field[$getParent](); + const container = field[$getSubformParent](); const fieldId = field[$uid]; let dataId; @@ -2113,27 +2113,15 @@ class ExclGroup extends XFAObject { [$isSplittable]() { // We cannot cache the result here because the contentArea // can change. - if (!this[$getParent]()[$isSplittable]()) { + if (!this[$getSubformParent]()[$isSplittable]()) { return false; } - const root = this[$getTemplateRoot](); - const contentArea = root[$extra].currentContentArea; - if (contentArea && Math.max(this.minH, this.h || 0) >= contentArea.h) { - return true; - } - if (this[$extra]._isSplittable !== undefined) { return this[$extra]._isSplittable; } - if (this.layout === "position") { - this[$extra]._isSplittable = false; - return false; - } - - const parentLayout = this[$getParent]().layout; - if (parentLayout && parentLayout.includes("row")) { + if (this.layout === "position" || this.layout.includes("row")) { this[$extra]._isSplittable = false; return false; } @@ -2205,8 +2193,8 @@ class ExclGroup extends XFAObject { const filter = new Set(["field"]); - if (this.layout === "row") { - const columnWidths = this[$getParent]().columnWidths; + if (this.layout.includes("row")) { + const columnWidths = this[$getSubformParent]().columnWidths; if (Array.isArray(columnWidths) && columnWidths.length > 0) { this[$extra].columnWidths = columnWidths; this[$extra].currentColumn = 0; @@ -4387,6 +4375,14 @@ class Subform extends XFAObject { this.subformSet = new XFAObjectArray(); } + [$getSubformParent]() { + const parent = this[$getParent](); + if (parent instanceof SubformSet) { + return parent[$getSubformParent](); + } + return parent; + } + [$isBindable]() { return true; } @@ -4412,25 +4408,21 @@ class Subform extends XFAObject { [$isSplittable]() { // We cannot cache the result here because the contentArea // can change. - if (!this[$getParent]()[$isSplittable]()) { + if (!this[$getSubformParent]()[$isSplittable]()) { return false; } - const root = this[$getTemplateRoot](); - const contentArea = root[$extra].currentContentArea; - if (contentArea && Math.max(this.minH, this.h || 0) >= contentArea.h) { - return true; - } + const contentArea = this[$getTemplateRoot]()[$extra].currentContentArea; - if (this.overflow) { - return this.overflow[$getExtra]().target !== contentArea; + if (this.overflow && this.overflow[$getExtra]().target === contentArea) { + return false; } if (this[$extra]._isSplittable !== undefined) { return this[$extra]._isSplittable; } - if (this.layout === "position") { + if (this.layout === "position" || this.layout.includes("row")) { this[$extra]._isSplittable = false; return false; } @@ -4440,12 +4432,6 @@ class Subform extends XFAObject { return false; } - const parentLayout = this[$getParent]().layout; - if (parentLayout && parentLayout.includes("row")) { - this[$extra]._isSplittable = false; - return false; - } - this[$extra]._isSplittable = true; return true; diff --git a/test/pdfs/xfa_bug1718740.pdf.link b/test/pdfs/xfa_bug1718740.pdf.link new file mode 100644 index 000000000..7d38b029c --- /dev/null +++ b/test/pdfs/xfa_bug1718740.pdf.link @@ -0,0 +1 @@ +https://bugzilla.mozilla.org/attachment.cgi?id=9229373 diff --git a/test/test_manifest.json b/test/test_manifest.json index 6e4e1df89..3917bf409 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -938,6 +938,14 @@ "lastPage": 2, "type": "eq" }, + { "id": "xfa_bug1718740", + "file": "pdfs/xfa_bug1718740.pdf", + "md5": "fab4277f2c70fd1edb35f597f5fe6819", + "link": true, + "rounds": 1, + "enableXfa": true, + "type": "eq" + }, { "id": "xfa_bug1718521_1", "file": "pdfs/xfa_bug1718521_1.pdf", "md5": "9b89dd9e6a4c6c3258ca24debd806863",