XFA - Avoid to have containers not pushed in the html
- it aims to fix issue #13668.
This commit is contained in:
parent
8ab65ed32d
commit
dd55e76f5d
@ -52,10 +52,21 @@ import { measureToString } from "./html_utils.js";
|
|||||||
* returning.
|
* returning.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
function createLine(node, children) {
|
||||||
|
return {
|
||||||
|
name: "div",
|
||||||
|
attributes: {
|
||||||
|
class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"],
|
||||||
|
},
|
||||||
|
children,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
function flushHTML(node) {
|
function flushHTML(node) {
|
||||||
if (!node[$extra]) {
|
if (!node[$extra]) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const attributes = node[$extra].attributes;
|
const attributes = node[$extra].attributes;
|
||||||
const html = {
|
const html = {
|
||||||
name: "div",
|
name: "div",
|
||||||
@ -66,18 +77,18 @@ function flushHTML(node) {
|
|||||||
if (node[$extra].failingNode) {
|
if (node[$extra].failingNode) {
|
||||||
const htmlFromFailing = node[$extra].failingNode[$flushHTML]();
|
const htmlFromFailing = node[$extra].failingNode[$flushHTML]();
|
||||||
if (htmlFromFailing) {
|
if (htmlFromFailing) {
|
||||||
|
if (node.layout.endsWith("-tb")) {
|
||||||
|
html.children.push(createLine(node, [htmlFromFailing]));
|
||||||
|
} else {
|
||||||
html.children.push(htmlFromFailing);
|
html.children.push(htmlFromFailing);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (html.children.length === 0) {
|
if (html.children.length === 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
node[$extra].children = [];
|
|
||||||
delete node[$extra].line;
|
|
||||||
node[$extra].numberInLine = 0;
|
|
||||||
|
|
||||||
return html;
|
return html;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,13 +107,7 @@ function addHTML(node, html, bbox) {
|
|||||||
case "lr-tb":
|
case "lr-tb":
|
||||||
case "rl-tb":
|
case "rl-tb":
|
||||||
if (!extra.line || extra.attempt === 1) {
|
if (!extra.line || extra.attempt === 1) {
|
||||||
extra.line = {
|
extra.line = createLine(node, []);
|
||||||
name: "div",
|
|
||||||
attributes: {
|
|
||||||
class: [node.layout === "lr-tb" ? "xfaLr" : "xfaRl"],
|
|
||||||
},
|
|
||||||
children: [],
|
|
||||||
};
|
|
||||||
extra.children.push(extra.line);
|
extra.children.push(extra.line);
|
||||||
extra.numberInLine = 0;
|
extra.numberInLine = 0;
|
||||||
}
|
}
|
||||||
@ -281,8 +286,14 @@ function checkDimensions(node, space) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (node.w !== "") {
|
if (node.w !== "") {
|
||||||
// True if width is enough.
|
if (Math.round(w - space.width) <= ERROR) {
|
||||||
return Math.round(w - space.width) <= ERROR;
|
return true;
|
||||||
|
}
|
||||||
|
if (parent[$extra].numberInLine === 0) {
|
||||||
|
return space.height > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return space.width > 0;
|
return space.width > 0;
|
||||||
|
@ -268,10 +268,17 @@ function handleBreak(node) {
|
|||||||
function handleOverflow(node, extraNode, space) {
|
function handleOverflow(node, extraNode, space) {
|
||||||
const root = node[$getTemplateRoot]();
|
const root = node[$getTemplateRoot]();
|
||||||
const saved = root[$extra].noLayoutFailure;
|
const saved = root[$extra].noLayoutFailure;
|
||||||
|
const savedMethod = extraNode[$getSubformParent];
|
||||||
|
|
||||||
|
// Replace $getSubformParent to emulate that extraNode is just
|
||||||
|
// under node.
|
||||||
|
extraNode[$getSubformParent] = () => node;
|
||||||
|
|
||||||
root[$extra].noLayoutFailure = true;
|
root[$extra].noLayoutFailure = true;
|
||||||
const res = extraNode[$toHTML](space);
|
const res = extraNode[$toHTML](space);
|
||||||
node[$addHTML](res.html, res.bbox);
|
node[$addHTML](res.html, res.bbox);
|
||||||
root[$extra].noLayoutFailure = saved;
|
root[$extra].noLayoutFailure = saved;
|
||||||
|
extraNode[$getSubformParent] = savedMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppearanceFilter extends StringObject {
|
class AppearanceFilter extends StringObject {
|
||||||
@ -2236,6 +2243,7 @@ class ExclGroup extends XFAObject {
|
|||||||
children,
|
children,
|
||||||
attributes,
|
attributes,
|
||||||
attempt: 0,
|
attempt: 0,
|
||||||
|
line: null,
|
||||||
numberInLine: 0,
|
numberInLine: 0,
|
||||||
availableSpace: {
|
availableSpace: {
|
||||||
width: Math.min(this.w || Infinity, availableSpace.width),
|
width: Math.min(this.w || Infinity, availableSpace.width),
|
||||||
@ -2298,12 +2306,10 @@ class ExclGroup extends XFAObject {
|
|||||||
attributes.xfaName = this.name;
|
attributes.xfaName = this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRun =
|
const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb";
|
||||||
this.layout === "lr-tb" || this.layout === "rl-tb"
|
const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;
|
||||||
? MAX_ATTEMPTS_FOR_LRTB_LAYOUT
|
|
||||||
: 1;
|
|
||||||
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
||||||
if (this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
|
if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
|
||||||
// If the layout is lr-tb then having attempt equals to
|
// If the layout is lr-tb then having attempt equals to
|
||||||
// MAX_ATTEMPTS_FOR_LRTB_LAYOUT-1 means that we're trying to layout
|
// MAX_ATTEMPTS_FOR_LRTB_LAYOUT-1 means that we're trying to layout
|
||||||
// on the next line so this on is empty.
|
// on the next line so this on is empty.
|
||||||
@ -2319,6 +2325,16 @@ class ExclGroup extends XFAObject {
|
|||||||
if (result.isBreak()) {
|
if (result.isBreak()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
isLrTb &&
|
||||||
|
this[$extra].attempt === 0 &&
|
||||||
|
this[$extra].numberInLine === 0 &&
|
||||||
|
!this[$getTemplateRoot]()[$extra].noLayoutFailure
|
||||||
|
) {
|
||||||
|
// See comment in Subform::[$toHTML].
|
||||||
|
this[$extra].attempt = maxRun;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isSplittable) {
|
if (!isSplittable) {
|
||||||
@ -4646,6 +4662,7 @@ class Subform extends XFAObject {
|
|||||||
|
|
||||||
Object.assign(this[$extra], {
|
Object.assign(this[$extra], {
|
||||||
children,
|
children,
|
||||||
|
line: null,
|
||||||
attributes,
|
attributes,
|
||||||
attempt: 0,
|
attempt: 0,
|
||||||
numberInLine: 0,
|
numberInLine: 0,
|
||||||
@ -4729,12 +4746,10 @@ class Subform extends XFAObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const maxRun =
|
const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb";
|
||||||
this.layout === "lr-tb" || this.layout === "rl-tb"
|
const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;
|
||||||
? MAX_ATTEMPTS_FOR_LRTB_LAYOUT
|
|
||||||
: 1;
|
|
||||||
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
||||||
if (this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
|
if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
|
||||||
// If the layout is lr-tb then having attempt equals to
|
// If the layout is lr-tb then having attempt equals to
|
||||||
// MAX_ATTEMPTS_FOR_LRTB_LAYOUT-1 means that we're trying to layout
|
// MAX_ATTEMPTS_FOR_LRTB_LAYOUT-1 means that we're trying to layout
|
||||||
// on the next line so this on is empty.
|
// on the next line so this on is empty.
|
||||||
@ -4750,6 +4765,23 @@ class Subform extends XFAObject {
|
|||||||
if (result.isBreak()) {
|
if (result.isBreak()) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
isLrTb &&
|
||||||
|
this[$extra].attempt === 0 &&
|
||||||
|
this[$extra].numberInLine === 0 &&
|
||||||
|
!root[$extra].noLayoutFailure
|
||||||
|
) {
|
||||||
|
// We're failing to put the first element on the line so no
|
||||||
|
// need to test on the next line.
|
||||||
|
// The goal is not only to avoid some useless checks but to avoid
|
||||||
|
// bugs too: if a descendant managed to put a node and failed
|
||||||
|
// on the next one, going to the next step here will imply to
|
||||||
|
// visit the descendant again, clear [$extra].children and restart
|
||||||
|
// on the failing node, consequently the first node just disappears
|
||||||
|
// because it has never been flushed.
|
||||||
|
this[$extra].attempt = maxRun;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isSplittable) {
|
if (!isSplittable) {
|
||||||
|
1
test/pdfs/xfa_issue13668.pdf.link
Normal file
1
test/pdfs/xfa_issue13668.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20210711170923/https://www.placementsmondiauxsunlife.com/content/dam/sunlife/regional/canada/documents/slgi/4839-I-F.pdf
|
@ -1192,6 +1192,14 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_issue13668",
|
||||||
|
"file": "pdfs/xfa_issue13668.pdf",
|
||||||
|
"md5": "8a5ed3c8a58b425b1ec53329334a0f5b",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "xfa_issue13633",
|
{ "id": "xfa_issue13633",
|
||||||
"file": "pdfs/xfa_issue13633.pdf",
|
"file": "pdfs/xfa_issue13633.pdf",
|
||||||
"md5": "e5b0d09285ca6a140eba08d740be0ea0",
|
"md5": "e5b0d09285ca6a140eba08d740be0ea0",
|
||||||
|
Loading…
Reference in New Issue
Block a user