XFA - Remove empty pages
- it aims to fix #13583; - fix the switch to breakBefore target; - force the layout of an unsplittable element on an empty page; - don't fail when there is horizontal overflow (except in lr-tb); - handle correctly overflow in the same content area (bug 1717805, bug 1717668); - fix a typo in radial gradient first argument.
This commit is contained in:
parent
f35e4cc9ab
commit
ff440d13e7
@ -257,70 +257,91 @@ function getTransformedBBox(node) {
|
|||||||
* in case of lr-tb or changing content area...).
|
* in case of lr-tb or changing content area...).
|
||||||
*/
|
*/
|
||||||
function checkDimensions(node, space) {
|
function checkDimensions(node, space) {
|
||||||
|
if (node[$getTemplateRoot]()[$extra].firstUnsplittable === null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (node.w === 0 || node.h === 0) {
|
if (node.w === 0 || node.h === 0) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (space.width <= 0 || space.height <= 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parent = node[$getParent]();
|
const parent = node[$getParent]();
|
||||||
const attempt = (node[$extra] && node[$extra].attempt) || 0;
|
const attempt = (parent[$extra] && parent[$extra].attempt) || 0;
|
||||||
|
let y, w, h;
|
||||||
switch (parent.layout) {
|
switch (parent.layout) {
|
||||||
case "lr-tb":
|
case "lr-tb":
|
||||||
case "rl-tb":
|
case "rl-tb":
|
||||||
switch (attempt) {
|
|
||||||
case 0: {
|
|
||||||
let w, h;
|
|
||||||
if (node.w !== "" || node.h !== "") {
|
if (node.w !== "" || node.h !== "") {
|
||||||
[, , w, h] = getTransformedBBox(node);
|
[, , 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) > 1) {
|
||||||
|
// Not enough height.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (node.w !== "") {
|
||||||
|
// True if width is enough.
|
||||||
|
return Math.round(w - space.width) <= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return space.width > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No layout failure.
|
||||||
|
|
||||||
|
// Put the element on the line but we can fail
|
||||||
|
// and then in the second step (next line) we'll accept.
|
||||||
if (node.w !== "") {
|
if (node.w !== "") {
|
||||||
return Math.round(w - space.width) <= 1;
|
return Math.round(w - space.width) <= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return node.minW <= space.width;
|
return space.width > 0;
|
||||||
}
|
|
||||||
case 1: {
|
|
||||||
if (node.h !== "" && !node[$isSplittable]()) {
|
|
||||||
const [, , , h] = getTransformedBBox(node);
|
|
||||||
if (Math.round(h - space.height) > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Second attempt: try to put the element on the next line.
|
||||||
|
|
||||||
|
if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
|
||||||
|
// We cannot fail.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
return true;
|
if (node.h !== "") {
|
||||||
|
// True if height is enough.
|
||||||
|
return Math.round(h - space.height) <= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return space.height > 0;
|
||||||
case "table":
|
case "table":
|
||||||
case "tb":
|
case "tb":
|
||||||
if (attempt !== 1 && node.h !== "" && !node[$isSplittable]()) {
|
if (node[$getTemplateRoot]()[$extra].noLayoutFailure) {
|
||||||
const [, , , h] = getTransformedBBox(node);
|
|
||||||
if (Math.round(h - space.height) > 1) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
case "position":
|
}
|
||||||
const [x, y, w, h] = getTransformedBBox(node);
|
|
||||||
const isWidthOk = node.w === "" || Math.round(w + x - space.width) <= 1;
|
|
||||||
const isHeightOk = node.h === "" || Math.round(h + y - space.height) <= 1;
|
|
||||||
|
|
||||||
if (isWidthOk && isHeightOk) {
|
// If the node has a height then check
|
||||||
|
// if it's fine with available height. If the node
|
||||||
|
// is breakable then we can return true.
|
||||||
|
if (node.h !== "" && !node[$isSplittable]()) {
|
||||||
|
[, , , h] = getTransformedBBox(node);
|
||||||
|
return Math.round(h - space.height) <= 1;
|
||||||
|
}
|
||||||
|
// Else wait and see: this node will be layed out itself
|
||||||
|
// in the provided space and maybe a children won't fit.
|
||||||
|
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) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const area = node[$getTemplateRoot]()[$extra].currentContentArea;
|
const area = node[$getTemplateRoot]()[$extra].currentContentArea;
|
||||||
if (isWidthOk) {
|
|
||||||
return h + y > area.h;
|
return h + y > area.h;
|
||||||
}
|
|
||||||
|
|
||||||
return w + x > area.w;
|
|
||||||
case "rl-row":
|
case "rl-row":
|
||||||
case "row":
|
case "row":
|
||||||
default:
|
default:
|
||||||
|
@ -28,6 +28,7 @@ import {
|
|||||||
$getAvailableSpace,
|
$getAvailableSpace,
|
||||||
$getChildren,
|
$getChildren,
|
||||||
$getContainedChildren,
|
$getContainedChildren,
|
||||||
|
$getExtra,
|
||||||
$getNextPage,
|
$getNextPage,
|
||||||
$getParent,
|
$getParent,
|
||||||
$getSubformParent,
|
$getSubformParent,
|
||||||
@ -141,6 +142,84 @@ function valueToHtml(value) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setFirstUnsplittable(node) {
|
||||||
|
const root = node[$getTemplateRoot]();
|
||||||
|
if (root[$extra].firstUnsplittable === null) {
|
||||||
|
root[$extra].firstUnsplittable = node;
|
||||||
|
root[$extra].noLayoutFailure = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function unsetFirstUnsplittable(node) {
|
||||||
|
const root = node[$getTemplateRoot]();
|
||||||
|
if (root[$extra].firstUnsplittable === node) {
|
||||||
|
root[$extra].noLayoutFailure = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleBreak(node) {
|
||||||
|
if (node[$extra]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
node[$extra] = Object.create(null);
|
||||||
|
|
||||||
|
if (node.targetType === "auto") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const root = node[$getTemplateRoot]();
|
||||||
|
let target = null;
|
||||||
|
if (node.target) {
|
||||||
|
target = root[$searchNode](node.target, node[$getParent]());
|
||||||
|
target = target ? target[0] : target;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { currentPageArea, currentContentArea } = root[$extra];
|
||||||
|
|
||||||
|
if (node.targetType === "pageArea") {
|
||||||
|
if (!(target instanceof PageArea)) {
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.startNew) {
|
||||||
|
node[$extra].target = target || currentPageArea;
|
||||||
|
return true;
|
||||||
|
} else if (target && target !== currentPageArea) {
|
||||||
|
node[$extra].target = target;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(target instanceof ContentArea)) {
|
||||||
|
target = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageArea = target[$getParent]();
|
||||||
|
const contentAreas = pageArea.contentArea.children;
|
||||||
|
|
||||||
|
let index;
|
||||||
|
if (node.startNew) {
|
||||||
|
if (target) {
|
||||||
|
index = contentAreas.findIndex(e => e === target) - 1;
|
||||||
|
} else {
|
||||||
|
index = currentPageArea.contentArea.children.findIndex(
|
||||||
|
e => e === currentContentArea
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (target && target !== currentContentArea) {
|
||||||
|
index = contentAreas.findIndex(e => e === target) - 1;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
node[$extra].target = pageArea === currentPageArea ? null : pageArea;
|
||||||
|
node[$extra].index = index;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
class AppearanceFilter extends StringObject {
|
class AppearanceFilter extends StringObject {
|
||||||
constructor(attributes) {
|
constructor(attributes) {
|
||||||
super(TEMPLATE_NS_ID, "appearanceFilter");
|
super(TEMPLATE_NS_ID, "appearanceFilter");
|
||||||
@ -718,8 +797,6 @@ class BreakAfter extends XFAObject {
|
|||||||
"auto",
|
"auto",
|
||||||
"contentArea",
|
"contentArea",
|
||||||
"pageArea",
|
"pageArea",
|
||||||
"pageEven",
|
|
||||||
"pageOdd",
|
|
||||||
]);
|
]);
|
||||||
this.trailer = attributes.trailer || "";
|
this.trailer = attributes.trailer || "";
|
||||||
this.use = attributes.use || "";
|
this.use = attributes.use || "";
|
||||||
@ -743,8 +820,6 @@ class BreakBefore extends XFAObject {
|
|||||||
"auto",
|
"auto",
|
||||||
"contentArea",
|
"contentArea",
|
||||||
"pageArea",
|
"pageArea",
|
||||||
"pageEven",
|
|
||||||
"pageOdd",
|
|
||||||
]);
|
]);
|
||||||
this.trailer = attributes.trailer || "";
|
this.trailer = attributes.trailer || "";
|
||||||
this.use = attributes.use || "";
|
this.use = attributes.use || "";
|
||||||
@ -1176,7 +1251,6 @@ class ContentArea extends XFAObject {
|
|||||||
const top = measureToString(this.y);
|
const top = measureToString(this.y);
|
||||||
|
|
||||||
const style = {
|
const style = {
|
||||||
position: "absolute",
|
|
||||||
left,
|
left,
|
||||||
top,
|
top,
|
||||||
width: measureToString(this.w),
|
width: measureToString(this.w),
|
||||||
@ -1550,9 +1624,11 @@ class Draw extends XFAObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setFirstUnsplittable(this);
|
||||||
if (!checkDimensions(this, availableSpace)) {
|
if (!checkDimensions(this, availableSpace)) {
|
||||||
return HTMLResult.FAILURE;
|
return HTMLResult.FAILURE;
|
||||||
}
|
}
|
||||||
|
unsetFirstUnsplittable(this);
|
||||||
|
|
||||||
const style = toStyle(
|
const style = toStyle(
|
||||||
this,
|
this,
|
||||||
@ -2038,21 +2114,32 @@ class ExclGroup extends XFAObject {
|
|||||||
[$isSplittable]() {
|
[$isSplittable]() {
|
||||||
// We cannot cache the result here because the contentArea
|
// We cannot cache the result here because the contentArea
|
||||||
// can change.
|
// can change.
|
||||||
|
if (!this[$getParent]()[$isSplittable]()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const root = this[$getTemplateRoot]();
|
const root = this[$getTemplateRoot]();
|
||||||
const contentArea = root[$extra].currentContentArea;
|
const contentArea = root[$extra].currentContentArea;
|
||||||
if (contentArea && Math.max(this.minH, this.h || 0) >= contentArea.h) {
|
if (contentArea && Math.max(this.minH, this.h || 0) >= contentArea.h) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this[$extra]._isSplittable !== undefined) {
|
||||||
|
return this[$extra]._isSplittable;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.layout === "position") {
|
if (this.layout === "position") {
|
||||||
|
this[$extra]._isSplittable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentLayout = this[$getParent]().layout;
|
const parentLayout = this[$getParent]().layout;
|
||||||
if (parentLayout && parentLayout.includes("row")) {
|
if (parentLayout && parentLayout.includes("row")) {
|
||||||
|
this[$extra]._isSplittable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this[$extra]._isSplittable = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2103,6 +2190,11 @@ class ExclGroup extends XFAObject {
|
|||||||
currentWidth: 0,
|
currentWidth: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const isSplittable = this[$isSplittable]();
|
||||||
|
if (!isSplittable) {
|
||||||
|
setFirstUnsplittable(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (!checkDimensions(this, availableSpace)) {
|
if (!checkDimensions(this, availableSpace)) {
|
||||||
return HTMLResult.FAILURE;
|
return HTMLResult.FAILURE;
|
||||||
}
|
}
|
||||||
@ -2180,6 +2272,10 @@ class ExclGroup extends XFAObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isSplittable) {
|
||||||
|
unsetFirstUnsplittable(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (failure) {
|
if (failure) {
|
||||||
if (this[$isSplittable]()) {
|
if (this[$isSplittable]()) {
|
||||||
delete this[$extra];
|
delete this[$extra];
|
||||||
@ -2366,9 +2462,11 @@ class Field extends XFAObject {
|
|||||||
|
|
||||||
fixDimensions(this);
|
fixDimensions(this);
|
||||||
|
|
||||||
|
setFirstUnsplittable(this);
|
||||||
if (!checkDimensions(this, availableSpace)) {
|
if (!checkDimensions(this, availableSpace)) {
|
||||||
return HTMLResult.FAILURE;
|
return HTMLResult.FAILURE;
|
||||||
}
|
}
|
||||||
|
unsetFirstUnsplittable(this);
|
||||||
|
|
||||||
const style = toStyle(
|
const style = toStyle(
|
||||||
this,
|
this,
|
||||||
@ -3320,6 +3418,18 @@ class Overflow extends XFAObject {
|
|||||||
this.use = attributes.use || "";
|
this.use = attributes.use || "";
|
||||||
this.usehref = attributes.usehref || "";
|
this.usehref = attributes.usehref || "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$getExtra]() {
|
||||||
|
if (!this[$extra]) {
|
||||||
|
const parent = this[$getParent]();
|
||||||
|
const root = this[$getTemplateRoot]();
|
||||||
|
const target = root[$searchNode](this.target, parent);
|
||||||
|
this[$extra] = {
|
||||||
|
target: (target && target[0]) || null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return this[$extra];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PageArea extends XFAObject {
|
class PageArea extends XFAObject {
|
||||||
@ -3457,8 +3567,10 @@ class PageArea extends XFAObject {
|
|||||||
name: "div",
|
name: "div",
|
||||||
children,
|
children,
|
||||||
attributes: {
|
attributes: {
|
||||||
|
class: ["xfaPage"],
|
||||||
id: this[$uid],
|
id: this[$uid],
|
||||||
style,
|
style,
|
||||||
|
xfaName: this.name,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -3875,7 +3987,7 @@ class Radial extends XFAObject {
|
|||||||
this.type === "toEdge"
|
this.type === "toEdge"
|
||||||
? `${startColor},${endColor}`
|
? `${startColor},${endColor}`
|
||||||
: `${endColor},${startColor}`;
|
: `${endColor},${startColor}`;
|
||||||
return `radial-gradient(circle to center, ${colors})`;
|
return `radial-gradient(circle at center, ${colors})`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4235,32 +4347,44 @@ class Subform extends XFAObject {
|
|||||||
return getAvailableSpace(this);
|
return getAvailableSpace(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
[$isSplittable](x) {
|
[$isSplittable]() {
|
||||||
// We cannot cache the result here because the contentArea
|
// We cannot cache the result here because the contentArea
|
||||||
// can change.
|
// can change.
|
||||||
|
if (!this[$getParent]()[$isSplittable]()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const root = this[$getTemplateRoot]();
|
const root = this[$getTemplateRoot]();
|
||||||
const contentArea = root[$extra].currentContentArea;
|
const contentArea = root[$extra].currentContentArea;
|
||||||
if (contentArea && Math.max(this.minH, this.h || 0) >= contentArea.h) {
|
if (contentArea && Math.max(this.minH, this.h || 0) >= contentArea.h) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.overflow) {
|
||||||
|
return this.overflow[$getExtra]().target !== contentArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this[$extra]._isSplittable !== undefined) {
|
||||||
|
return this[$extra]._isSplittable;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.layout === "position") {
|
if (this.layout === "position") {
|
||||||
|
this[$extra]._isSplittable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.keep && this.keep.intact !== "none") {
|
if (this.keep && this.keep.intact !== "none") {
|
||||||
|
this[$extra]._isSplittable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parentLayout = this[$getParent]().layout;
|
const parentLayout = this[$getParent]().layout;
|
||||||
if (parentLayout && parentLayout.includes("row")) {
|
if (parentLayout && parentLayout.includes("row")) {
|
||||||
|
this[$extra]._isSplittable = false;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.overflow && this.overflow.target) {
|
this[$extra]._isSplittable = true;
|
||||||
const target = root[$searchNode](this.overflow.target, this);
|
|
||||||
return target && target[0] === contentArea;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -4323,9 +4447,7 @@ class Subform extends XFAObject {
|
|||||||
|
|
||||||
if (this.breakBefore.children.length >= 1) {
|
if (this.breakBefore.children.length >= 1) {
|
||||||
const breakBefore = this.breakBefore.children[0];
|
const breakBefore = this.breakBefore.children[0];
|
||||||
if (!breakBefore[$extra]) {
|
if (handleBreak(breakBefore)) {
|
||||||
// Set $extra to true to consume it.
|
|
||||||
breakBefore[$extra] = true;
|
|
||||||
return HTMLResult.breakNode(breakBefore);
|
return HTMLResult.breakNode(breakBefore);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4359,6 +4481,24 @@ class Subform extends XFAObject {
|
|||||||
currentWidth: 0,
|
currentWidth: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const root = this[$getTemplateRoot]();
|
||||||
|
const currentContentArea = root[$extra].currentContentArea;
|
||||||
|
const savedNoLayoutFailure = root[$extra].noLayoutFailure;
|
||||||
|
|
||||||
|
if (this.overflow) {
|
||||||
|
// In case of overflow in the current content area,
|
||||||
|
// elements must be kept in this subform so it implies
|
||||||
|
// to have no errors on layout failures.
|
||||||
|
root[$extra].noLayoutFailure =
|
||||||
|
root[$extra].noLayoutFailure ||
|
||||||
|
this.overflow[$getExtra]().target === currentContentArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
const isSplittable = this[$isSplittable]();
|
||||||
|
if (!isSplittable) {
|
||||||
|
setFirstUnsplittable(this);
|
||||||
|
}
|
||||||
|
|
||||||
if (!checkDimensions(this, availableSpace)) {
|
if (!checkDimensions(this, availableSpace)) {
|
||||||
return HTMLResult.FAILURE;
|
return HTMLResult.FAILURE;
|
||||||
}
|
}
|
||||||
@ -4403,16 +4543,10 @@ class Subform extends XFAObject {
|
|||||||
attributes.xfaName = this.name;
|
attributes.xfaName = this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSplittable = this[$isSplittable]();
|
const maxRun =
|
||||||
|
|
||||||
// If the container overflows into itself we add an extra
|
|
||||||
// layout step to accept finally the element which caused
|
|
||||||
// the overflow.
|
|
||||||
let maxRun =
|
|
||||||
this.layout === "lr-tb" || this.layout === "rl-tb"
|
this.layout === "lr-tb" || this.layout === "rl-tb"
|
||||||
? MAX_ATTEMPTS_FOR_LRTB_LAYOUT
|
? MAX_ATTEMPTS_FOR_LRTB_LAYOUT
|
||||||
: 1;
|
: 1;
|
||||||
maxRun += !isSplittable && this.layout !== "position" ? 1 : 0;
|
|
||||||
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
|
||||||
const result = this[$childrenToHTML]({
|
const result = this[$childrenToHTML]({
|
||||||
filter,
|
filter,
|
||||||
@ -4426,6 +4560,11 @@ class Subform extends XFAObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isSplittable) {
|
||||||
|
unsetFirstUnsplittable(this);
|
||||||
|
}
|
||||||
|
root[$extra].noLayoutFailure = savedNoLayoutFailure;
|
||||||
|
|
||||||
if (this[$extra].attempt === maxRun) {
|
if (this[$extra].attempt === maxRun) {
|
||||||
if (this.overflow) {
|
if (this.overflow) {
|
||||||
this[$getTemplateRoot]()[$extra].overflowNode = this.overflow;
|
this[$getTemplateRoot]()[$extra].overflowNode = this.overflow;
|
||||||
@ -4467,9 +4606,11 @@ class Subform extends XFAObject {
|
|||||||
|
|
||||||
if (this.breakAfter.children.length >= 1) {
|
if (this.breakAfter.children.length >= 1) {
|
||||||
const breakAfter = this.breakAfter.children[0];
|
const breakAfter = this.breakAfter.children[0];
|
||||||
|
if (handleBreak(breakAfter)) {
|
||||||
this[$extra].afterBreakAfter = result;
|
this[$extra].afterBreakAfter = result;
|
||||||
return HTMLResult.breakNode(breakAfter);
|
return HTMLResult.breakNode(breakAfter);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delete this[$extra];
|
delete this[$extra];
|
||||||
|
|
||||||
@ -4623,6 +4764,10 @@ class Template extends XFAObject {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$isSplittable]() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
[$searchNode](expr, container) {
|
[$searchNode](expr, container) {
|
||||||
if (expr.startsWith("#")) {
|
if (expr.startsWith("#")) {
|
||||||
// This is an id.
|
// This is an id.
|
||||||
@ -4640,6 +4785,10 @@ class Template extends XFAObject {
|
|||||||
}
|
}
|
||||||
this[$extra] = {
|
this[$extra] = {
|
||||||
overflowNode: null,
|
overflowNode: null,
|
||||||
|
firstUnsplittable: null,
|
||||||
|
currentContentArea: null,
|
||||||
|
currentPageArea: null,
|
||||||
|
noLayoutFailure: false,
|
||||||
pageNumber: 1,
|
pageNumber: 1,
|
||||||
pagePosition: "first",
|
pagePosition: "first",
|
||||||
oddOrEven: "odd",
|
oddOrEven: "odd",
|
||||||
@ -4711,9 +4860,11 @@ class Template extends XFAObject {
|
|||||||
let trailer = null;
|
let trailer = null;
|
||||||
let hasSomething = true;
|
let hasSomething = true;
|
||||||
let hasSomethingCounter = 0;
|
let hasSomethingCounter = 0;
|
||||||
|
let startIndex = 0;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
if (!hasSomething) {
|
if (!hasSomething) {
|
||||||
|
mainHtml.children.pop();
|
||||||
// Nothing has been added in the previous page
|
// Nothing has been added in the previous page
|
||||||
if (++hasSomethingCounter === MAX_EMPTY_PAGES) {
|
if (++hasSomethingCounter === MAX_EMPTY_PAGES) {
|
||||||
warn("XFA - Something goes wrong: please file a bug.");
|
warn("XFA - Something goes wrong: please file a bug.");
|
||||||
@ -4724,15 +4875,18 @@ class Template extends XFAObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
targetPageArea = null;
|
targetPageArea = null;
|
||||||
|
this[$extra].currentPageArea = pageArea;
|
||||||
const page = pageArea[$toHTML]().html;
|
const page = pageArea[$toHTML]().html;
|
||||||
mainHtml.children.push(page);
|
mainHtml.children.push(page);
|
||||||
|
|
||||||
if (leader) {
|
if (leader) {
|
||||||
|
this[$extra].noLayoutFailure = true;
|
||||||
page.children.push(leader[$toHTML](pageArea[$extra].space).html);
|
page.children.push(leader[$toHTML](pageArea[$extra].space).html);
|
||||||
leader = null;
|
leader = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trailer) {
|
if (trailer) {
|
||||||
|
this[$extra].noLayoutFailure = true;
|
||||||
page.children.push(trailer[$toHTML](pageArea[$extra].space).html);
|
page.children.push(trailer[$toHTML](pageArea[$extra].space).html);
|
||||||
trailer = null;
|
trailer = null;
|
||||||
}
|
}
|
||||||
@ -4743,6 +4897,8 @@ class Template extends XFAObject {
|
|||||||
);
|
);
|
||||||
|
|
||||||
hasSomething = false;
|
hasSomething = false;
|
||||||
|
this[$extra].firstUnsplittable = null;
|
||||||
|
this[$extra].noLayoutFailure = false;
|
||||||
|
|
||||||
const flush = index => {
|
const flush = index => {
|
||||||
const html = root[$flushHTML]();
|
const html = root[$flushHTML]();
|
||||||
@ -4753,9 +4909,10 @@ class Template extends XFAObject {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (let i = 0, ii = contentAreas.length; i < ii; i++) {
|
for (let i = startIndex, ii = contentAreas.length; i < ii; i++) {
|
||||||
const contentArea = (this[$extra].currentContentArea = contentAreas[i]);
|
const contentArea = (this[$extra].currentContentArea = contentAreas[i]);
|
||||||
const space = { width: contentArea.w, height: contentArea.h };
|
const space = { width: contentArea.w, height: contentArea.h };
|
||||||
|
startIndex = 0;
|
||||||
|
|
||||||
if (leader) {
|
if (leader) {
|
||||||
htmlContentAreas[i].children.push(leader[$toHTML](space).html);
|
htmlContentAreas[i].children.push(leader[$toHTML](space).html);
|
||||||
@ -4782,14 +4939,12 @@ class Template extends XFAObject {
|
|||||||
|
|
||||||
if (html.isBreak()) {
|
if (html.isBreak()) {
|
||||||
const node = html.breakNode;
|
const node = html.breakNode;
|
||||||
|
flush(i);
|
||||||
|
|
||||||
if (node.targetType === "auto") {
|
if (node.targetType === "auto") {
|
||||||
flush(i);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const startNew = node.startNew === 1;
|
|
||||||
|
|
||||||
if (node.leader) {
|
if (node.leader) {
|
||||||
leader = this[$searchNode](node.leader, node[$getParent]());
|
leader = this[$searchNode](node.leader, node[$getParent]());
|
||||||
leader = leader ? leader[0] : null;
|
leader = leader ? leader[0] : null;
|
||||||
@ -4800,41 +4955,18 @@ class Template extends XFAObject {
|
|||||||
trailer = trailer ? trailer[0] : null;
|
trailer = trailer ? trailer[0] : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
let target = null;
|
|
||||||
if (node.target) {
|
|
||||||
target = this[$searchNode](node.target, node[$getParent]());
|
|
||||||
target = target ? target[0] : target;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (node.targetType === "pageArea") {
|
if (node.targetType === "pageArea") {
|
||||||
if (!(target instanceof PageArea)) {
|
targetPageArea = node[$extra].target;
|
||||||
target = null;
|
i = Infinity;
|
||||||
|
} else if (!node[$extra].target) {
|
||||||
|
// We stay on the same page.
|
||||||
|
i = node[$extra].index;
|
||||||
|
} else {
|
||||||
|
targetPageArea = node[$extra].target;
|
||||||
|
startIndex = node[$extra].index + 1;
|
||||||
|
i = Infinity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (startNew) {
|
|
||||||
targetPageArea = target || pageArea;
|
|
||||||
flush(i);
|
|
||||||
i = Infinity;
|
|
||||||
} else if (target && target !== pageArea) {
|
|
||||||
targetPageArea = target;
|
|
||||||
flush(i);
|
|
||||||
i = Infinity;
|
|
||||||
} else {
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
} else if (node.targetType === "contentArea") {
|
|
||||||
if (!(target instanceof ContentArea)) {
|
|
||||||
target = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const index = contentAreas.findIndex(e => e === target);
|
|
||||||
if (index !== -1) {
|
|
||||||
flush(i);
|
|
||||||
i = index - 1;
|
|
||||||
} else {
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4860,17 +4992,20 @@ class Template extends XFAObject {
|
|||||||
target = target ? target[0] : target;
|
target = target ? target[0] : target;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i = Infinity;
|
||||||
if (target instanceof PageArea) {
|
if (target instanceof PageArea) {
|
||||||
// We must stop the contentAreas filling and go to the next page.
|
// We must stop the contentAreas filling and go to the next page.
|
||||||
targetPageArea = target;
|
targetPageArea = target;
|
||||||
i = Infinity;
|
|
||||||
continue;
|
|
||||||
} else if (target instanceof ContentArea) {
|
} else if (target instanceof ContentArea) {
|
||||||
const index = contentAreas.findIndex(e => e === target);
|
const index = contentAreas.findIndex(e => e === target);
|
||||||
if (index !== -1) {
|
if (index !== -1) {
|
||||||
i = index - 1;
|
i = index - 1;
|
||||||
} else {
|
} else {
|
||||||
i--;
|
targetPageArea = target[$getParent]();
|
||||||
|
startIndex =
|
||||||
|
targetPageArea.contentArea.children.findIndex(
|
||||||
|
e => e === target
|
||||||
|
) - 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
@ -43,6 +43,7 @@ const $getChildrenByClass = Symbol();
|
|||||||
const $getChildrenByName = Symbol();
|
const $getChildrenByName = Symbol();
|
||||||
const $getChildrenByNameIt = Symbol();
|
const $getChildrenByNameIt = Symbol();
|
||||||
const $getDataValue = Symbol();
|
const $getDataValue = Symbol();
|
||||||
|
const $getExtra = Symbol();
|
||||||
const $getRealChildrenByNameIt = Symbol();
|
const $getRealChildrenByNameIt = Symbol();
|
||||||
const $getChildren = Symbol();
|
const $getChildren = Symbol();
|
||||||
const $getContainedChildren = Symbol();
|
const $getContainedChildren = Symbol();
|
||||||
@ -177,11 +178,7 @@ class XFAObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[$getTemplateRoot]() {
|
[$getTemplateRoot]() {
|
||||||
let parent = this[$getParent]();
|
return this[$globalData].template;
|
||||||
while (parent[$nodeName] !== "template") {
|
|
||||||
parent = parent[$getParent]();
|
|
||||||
}
|
|
||||||
return parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[$isSplittable]() {
|
[$isSplittable]() {
|
||||||
@ -1060,6 +1057,7 @@ export {
|
|||||||
$getChildrenByNameIt,
|
$getChildrenByNameIt,
|
||||||
$getContainedChildren,
|
$getContainedChildren,
|
||||||
$getDataValue,
|
$getDataValue,
|
||||||
|
$getExtra,
|
||||||
$getNextPage,
|
$getNextPage,
|
||||||
$getParent,
|
$getParent,
|
||||||
$getRealChildrenByNameIt,
|
$getRealChildrenByNameIt,
|
||||||
|
1
test/pdfs/xfa_bug1717668_1.pdf.link
Normal file
1
test/pdfs/xfa_bug1717668_1.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://bugzilla.mozilla.org/attachment.cgi?id=9228387
|
1
test/pdfs/xfa_bug1717668_2.pdf.link
Normal file
1
test/pdfs/xfa_bug1717668_2.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://bugzilla.mozilla.org/attachment.cgi?id=9228727
|
1
test/pdfs/xfa_bug1717668_3.pdf.link
Normal file
1
test/pdfs/xfa_bug1717668_3.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://bugzilla.mozilla.org/attachment.cgi?id=9228728
|
1
test/pdfs/xfa_bug1717805.pdf.link
Normal file
1
test/pdfs/xfa_bug1717805.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://bugzilla.mozilla.org/attachment.cgi?id=9228507
|
1
test/pdfs/xfa_dhl_shipment.pdf.link
Normal file
1
test/pdfs/xfa_dhl_shipment.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20210621073147/https://www.dhl.com/content/dam/downloads/g0/express/emailship_page/globalpage/dhl_emailship_pdfclient_my_en.pdf
|
1
test/pdfs/xfa_issue13611.pdf.link
Normal file
1
test/pdfs/xfa_issue13611.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://github.com/mozilla/pdf.js/files/6695365/2229E.pdf
|
@ -946,6 +946,38 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_bug1717805",
|
||||||
|
"file": "pdfs/xfa_bug1717805.pdf",
|
||||||
|
"md5": "c68ccebd0d92b8fd70c465660458507f",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "xfa_bug17176688_1",
|
||||||
|
"file": "pdfs/xfa_bug1717668_1.pdf",
|
||||||
|
"md5": "564ecff67be690b43c2a144ae5967034",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "xfa_bug17176688_2",
|
||||||
|
"file": "pdfs/xfa_bug1717668_2.pdf",
|
||||||
|
"md5": "08aa8bf9fec5aa7b8ff13d9ba72ca8ac",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
|
{ "id": "xfa_bug17176688_3",
|
||||||
|
"file": "pdfs/xfa_bug1717668_3.pdf",
|
||||||
|
"md5": "4ff2531dbefebabc3f128d4ae20552a4",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "xfa_bug1718037",
|
{ "id": "xfa_bug1718037",
|
||||||
"file": "pdfs/xfa_bug1718037.pdf",
|
"file": "pdfs/xfa_bug1718037.pdf",
|
||||||
"md5": "a0b53d50e9faed9d57950a5159d5da12",
|
"md5": "a0b53d50e9faed9d57950a5159d5da12",
|
||||||
@ -970,6 +1002,14 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_dhl_shipment",
|
||||||
|
"file": "pdfs/xfa_dhl_shipment.pdf",
|
||||||
|
"md5": "503ece429d69e7d626d6932a475fbe63",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "xfa_bug1716047",
|
{ "id": "xfa_bug1716047",
|
||||||
"file": "pdfs/xfa_bug1716047.pdf",
|
"file": "pdfs/xfa_bug1716047.pdf",
|
||||||
"md5": "2f524163bd8397f43d195090978c3b56",
|
"md5": "2f524163bd8397f43d195090978c3b56",
|
||||||
@ -1050,6 +1090,14 @@
|
|||||||
"enableXfa": true,
|
"enableXfa": true,
|
||||||
"type": "eq"
|
"type": "eq"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_issue13611",
|
||||||
|
"file": "pdfs/xfa_issue13611.pdf",
|
||||||
|
"md5": "e713fb46a6b4637660010f1850559ff6",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "xfa_issue13634",
|
{ "id": "xfa_issue13634",
|
||||||
"file": "pdfs/xfa_issue13634.pdf",
|
"file": "pdfs/xfa_issue13634.pdf",
|
||||||
"md5": "459a04045470811cbab6671772929d3d",
|
"md5": "459a04045470811cbab6671772929d3d",
|
||||||
|
@ -56,14 +56,18 @@ describe("XFAFactory", function () {
|
|||||||
</draw>
|
</draw>
|
||||||
</pageArea>
|
</pageArea>
|
||||||
</pageSet>
|
</pageSet>
|
||||||
<subform name="first">
|
|
||||||
</subform>
|
|
||||||
<subform name="second">
|
<subform name="second">
|
||||||
<breakBefore targetType="pageArea" startNew="1"/>
|
<breakBefore targetType="pageArea" startNew="1"/>
|
||||||
<subform>
|
<subform>
|
||||||
<draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
|
<draw w="1pt" h="1pt"><value><text>foo</text></value></draw>
|
||||||
</subform>
|
</subform>
|
||||||
</subform>
|
</subform>
|
||||||
|
<subform name="third">
|
||||||
|
<breakBefore targetType="pageArea" startNew="1"/>
|
||||||
|
<subform>
|
||||||
|
<draw w="1pt" h="1pt"><value><text>bar</text></value></draw>
|
||||||
|
</subform>
|
||||||
|
</subform>
|
||||||
</subform>
|
</subform>
|
||||||
</template>
|
</template>
|
||||||
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
|
<xfa:datasets xmlns:xfa="http://www.xfa.org/schema/xfa-data/1.0/">
|
||||||
@ -92,7 +96,6 @@ describe("XFAFactory", function () {
|
|||||||
width: "456px",
|
width: "456px",
|
||||||
left: "123px",
|
left: "123px",
|
||||||
top: "0px",
|
top: "0px",
|
||||||
position: "absolute",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const wrapper = page1.children[0];
|
const wrapper = page1.children[0];
|
||||||
|
@ -13,6 +13,15 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
.xfaPage {
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.xfaContentarea {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
|
||||||
.xfaPrintOnly {
|
.xfaPrintOnly {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
@ -139,10 +148,6 @@
|
|||||||
flex: 1 1 auto;
|
flex: 1 1 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.xfaContentArea {
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
.xfaTextfield,
|
.xfaTextfield,
|
||||||
.xfaSelect {
|
.xfaSelect {
|
||||||
background-color: rgba(0, 54, 255, 0.13);
|
background-color: rgba(0, 54, 255, 0.13);
|
||||||
|
Loading…
Reference in New Issue
Block a user