Skip to content

Commit

Permalink
XFA - Handle correctly nested containers with lr-tb layout (bug 1718670)
Browse files Browse the repository at this point in the history
  - and avoid to push a field with no dimensions when we have some available space in width in a parent.
  • Loading branch information
calixteman committed Jul 7, 2021
1 parent 1eb9a3e commit 0f7d958
Show file tree
Hide file tree
Showing 7 changed files with 159 additions and 48 deletions.
5 changes: 4 additions & 1 deletion src/core/xfa/html_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ function layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) {
function layoutNode(node, availableSpace) {
let height = null;
let width = null;
let isBroken = false;

if ((!node.w || !node.h) && node.value) {
let marginH = 0;
Expand Down Expand Up @@ -263,6 +264,7 @@ function layoutNode(node, availableSpace) {
);
width = res.width;
height = res.height;
isBroken = res.isBroken;
} else {
const text = node.value[$text]();
if (text) {
Expand All @@ -276,6 +278,7 @@ function layoutNode(node, availableSpace) {
);
width = res.width;
height = res.height;
isBroken = res.isBroken;
}
}

Expand All @@ -287,7 +290,7 @@ function layoutNode(node, availableSpace) {
height += marginV;
}
}
return [width, height];
return { w: width, h: height, isBroken };
}

function computeBbox(node, html, availableSpace) {
Expand Down
49 changes: 34 additions & 15 deletions src/core/xfa/layout.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
$getSubformParent,
$getTemplateRoot,
$isSplittable,
$isThereMoreWidth,
} from "./xfa_object.js";
import { measureToString } from "./html_utils.js";

Expand Down Expand Up @@ -75,6 +76,7 @@ function flushHTML(node) {

node[$extra].children = [];
delete node[$extra].line;
node[$extra].numberInLine = 0;

return html;
}
Expand All @@ -83,9 +85,9 @@ function addHTML(node, html, bbox) {
const extra = node[$extra];
const availableSpace = extra.availableSpace;

const [x, y, w, h] = bbox;
switch (node.layout) {
case "position": {
const [x, y, w, h] = bbox;
extra.width = Math.max(extra.width, x + w);
extra.height = Math.max(extra.height, y + h);
extra.children.push(html);
Expand All @@ -102,16 +104,17 @@ function addHTML(node, html, bbox) {
children: [],
};
extra.children.push(extra.line);
extra.numberInLine = 0;
}

extra.numberInLine += 1;
extra.line.children.push(html);

if (extra.attempt === 0) {
// Add the element on the line
const [, , w, h] = bbox;
extra.currentWidth += w;
extra.height = Math.max(extra.height, extra.prevHeight + h);
} else {
const [, , w, h] = bbox;
extra.currentWidth = w;
extra.prevHeight = extra.height;
extra.height += h;
Expand All @@ -124,7 +127,6 @@ function addHTML(node, html, bbox) {
case "rl-row":
case "row": {
extra.children.push(html);
const [, , w, h] = bbox;
extra.width += w;
extra.height = Math.max(extra.height, h);
const height = measureToString(extra.height);
Expand All @@ -134,14 +136,12 @@ function addHTML(node, html, bbox) {
break;
}
case "table": {
const [, , w, h] = bbox;
extra.width = Math.min(availableSpace.width, Math.max(extra.width, w));
extra.height += h;
extra.children.push(html);
break;
}
case "tb": {
const [, , , h] = bbox;
extra.width = availableSpace.width;
extra.height += h;
extra.children.push(html);
Expand Down Expand Up @@ -265,6 +265,7 @@ function checkDimensions(node, space) {
return true;
}

const ERROR = 2;
const parent = node[$getSubformParent]();
const attempt = (parent[$extra] && parent[$extra].attempt) || 0;
let y, w, h;
Expand All @@ -274,17 +275,19 @@ function checkDimensions(node, space) {
if (node.w !== "" || node.h !== "") {
[, , w, h] = getTransformedBBox(node);
}

if (attempt === 0) {
// Try to put an element in the line.

if (!node[$getTemplateRoot]()[$extra].noLayoutFailure) {
if (node.h !== "" && Math.round(h - space.height) > 1) {
if (node.h !== "" && Math.round(h - space.height) > ERROR) {
// Not enough height.
return false;
}

if (node.w !== "") {
// True if width is enough.
return Math.round(w - space.width) <= 1;
return Math.round(w - space.width) <= ERROR;
}

return space.width > 0;
Expand All @@ -295,7 +298,7 @@ function checkDimensions(node, space) {
// Put the element on the line but we can fail
// and then in the second step (next line) we'll accept.
if (node.w !== "") {
return Math.round(w - space.width) <= 1;
return Math.round(w - space.width) <= ERROR;
}

return space.width > 0;
Expand All @@ -308,9 +311,16 @@ function checkDimensions(node, space) {
return true;
}

if (node.h !== "") {
// True if height is enough.
return Math.round(h - space.height) <= 1;
if (node.h !== "" && Math.round(h - space.height) > ERROR) {
return false;
}

if (node.w === "" || Math.round(w - space.width) <= ERROR) {
return space.height > 0;
}

if (parent[$isThereMoreWidth]()) {
return false;
}

return space.height > 0;
Expand All @@ -325,18 +335,27 @@ function checkDimensions(node, space) {
// is breakable then we can return true.
if (node.h !== "" && !node[$isSplittable]()) {
[, , , h] = getTransformedBBox(node);
return Math.round(h - space.height) <= 1;
return Math.round(h - space.height) <= ERROR;
}
// Else wait and see: this node will be layed out itself
// in the provided space and maybe a children won't fit.

if (node.w === "" || Math.round(w - space.width) <= ERROR) {
return space.height > 0;
}

if (parent[$isThereMoreWidth]()) {
return false;
}

return space.height > 0;
case "position":
if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
return true;
}

[, y, , h] = getTransformedBBox(node);
if (node.h === "" || Math.round(h + y - space.height) <= 1) {
if (node.h === "" || Math.round(h + y - space.height) <= ERROR) {
return true;
}

Expand All @@ -350,7 +369,7 @@ function checkDimensions(node, space) {

if (node.h !== "") {
[, , , h] = getTransformedBBox(node);
return Math.round(h - space.height) <= 1;
return Math.round(h - space.height) <= ERROR;
}
return true;
default:
Expand Down
Loading

0 comments on commit 0f7d958

Please sign in to comment.