diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js index 93d6359298110..f8a487d11cd3d 100644 --- a/src/core/xfa/template.js +++ b/src/core/xfa/template.js @@ -19,6 +19,7 @@ import { $appendChild, $childrenToHTML, $clean, + $cleanPage, $content, $extra, $finalize, @@ -37,6 +38,7 @@ import { $isCDATAXml, $isSplittable, $isTransparent, + $isUsable, $namespaceId, $nodeName, $onChild, @@ -2398,8 +2400,10 @@ class Field extends XFAObject { const caption = this.caption ? this.caption[$toHTML]().html : null; if (!caption) { - // Even if no caption this class will help to center the ui. - ui.attributes.class.push("xfaLeft"); + if (ui.attributes.class) { + // Even if no caption this class will help to center the ui. + ui.attributes.class.push("xfaLeft"); + } return HTMLResult.success(createWrapper(this, html), bbox); } @@ -2633,13 +2637,8 @@ class Font extends XFAObject { // TODO: fontHorizontalScale // TODO: fontVerticalScale - if (this.kerningMode !== "none") { - style.fontKerning = "normal"; - } - - if (this.letterSpacing) { - style.letterSpacing = measureToString(this.letterSpacing); - } + style.fontKerning = this.kerningMode === "none" ? "none" : "normal"; + style.letterSpacing = measureToString(this.letterSpacing); if (this.lineThrough !== 0) { style.textDecoration = "line-through"; @@ -2659,9 +2658,7 @@ class Font extends XFAObject { // TODO: overlinePeriod - if (this.posture !== "normal") { - style.fontStyle = this.posture; - } + style.fontStyle = this.posture; const fontSize = measureToString(0.99 * this.size); if (fontSize !== "10px") { @@ -2679,9 +2676,7 @@ class Font extends XFAObject { // TODO: underlinePeriod - if (this.weight !== "normal") { - style.fontWeight = this.weight; - } + style.fontWeight = this.weight; return style; } @@ -3286,24 +3281,39 @@ class PageArea extends XFAObject { this.subform = new XFAObjectArray(); } + [$isUsable]() { + if (!this[$extra]) { + this[$extra] = { + numberOfUse: 0, + }; + return true; + } + return ( + !this.occur || + this.occur.max === -1 || + this[$extra].numberOfUse < this.occur.max + ); + } + + [$cleanPage]() { + delete this[$extra]; + } + [$getNextPage]() { if (!this[$extra]) { this[$extra] = { - numberOfUse: 1, + numberOfUse: 0, }; } + const parent = this[$getParent](); if (parent.relation === "orderedOccurrence") { - if ( - this.occur && - (this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max) - ) { + if (this[$isUsable]()) { this[$extra].numberOfUse += 1; return this; } } - delete this[$extra]; return parent[$getNextPage](); } @@ -3313,12 +3323,6 @@ class PageArea extends XFAObject { [$toHTML]() { // TODO: incomplete. - if (!this[$extra]) { - this[$extra] = { - numberOfUse: 1, - }; - } - const children = []; this[$extra].children = children; @@ -3389,43 +3393,57 @@ class PageSet extends XFAObject { this.pageSet = new XFAObjectArray(); } + [$cleanPage]() { + for (const page of this.pageArea.children) { + page[$cleanPage](); + } + for (const page of this.pageSet.children) { + page[$cleanPage](); + } + } + + [$isUsable]() { + return ( + !this.occur || + this.occur.max === -1 || + this[$extra].numberOfUse < this.occur.max + ); + } + [$getNextPage]() { if (!this[$extra]) { this[$extra] = { numberOfUse: 1, - currentIndex: -1, + pageIndex: -1, + pageSetIndex: -1, }; } if (this.relation === "orderedOccurrence") { - if (this[$extra].currentIndex + 1 < this.pageArea.children.length) { - this[$extra].currentIndex += 1; - return this.pageArea.children[this[$extra].currentIndex]; + if (this[$extra].pageIndex + 1 < this.pageArea.children.length) { + this[$extra].pageIndex += 1; + const pageArea = this.pageArea.children[this[$extra].pageIndex]; + return pageArea[$getNextPage](); } - if (this[$extra].currentIndex + 1 < this.pageSet.children.length) { - this[$extra].currentIndex += 1; - return this.pageSet.children[this[$extra].currentIndex]; + if (this[$extra].pageSetIndex + 1 < this.pageSet.children.length) { + this[$extra].pageSetIndex += 1; + return this.pageSet.children[this[$extra].pageSetIndex][$getNextPage](); } - if ( - this.occur && - (this.occur.max === -1 || this[$extra].numberOfUse < this.occur.max) - ) { + if (this[$isUsable]()) { this[$extra].numberOfUse += 1; - this[$extra].currentIndex = 0; - if (this.pageArea.children.length > 0) { - return this.pageArea.children[0]; - } - return this.pageSet.children[0][$getNextPage](); + this[$extra].pageIndex = -1; + this[$extra].pageSetIndex = -1; + return this[$getNextPage](); } - delete this[$extra]; const parent = this[$getParent](); if (parent instanceof PageSet) { return parent[$getNextPage](); } + this[$cleanPage](); return this[$getNextPage](); } const pageNumber = this[$getTemplateRoot]()[$extra].pageNumber; @@ -4495,6 +4513,8 @@ class Template extends XFAObject { }; const root = this.subform.children[0]; + root.pageSet[$cleanPage](); + const pageAreas = root.pageSet.pageArea.children; const mainHtml = { name: "div", @@ -4541,10 +4561,15 @@ class Template extends XFAObject { pageArea = pageAreas[0]; } + pageArea[$extra] = { + numberOfUse: 1, + }; + const pageAreaParent = pageArea[$getParent](); pageAreaParent[$extra] = { numberOfUse: 1, - currentIndex: pageAreaParent.pageArea.children.indexOf(pageArea), + pageIndex: pageAreaParent.pageArea.children.indexOf(pageArea), + pageSetIndex: 0, }; let targetPageArea; @@ -4645,19 +4670,26 @@ class Template extends XFAObject { } if (node.targetType === "pageArea") { + if (!(target instanceof PageArea)) { + target = null; + } + if (startNew) { + targetPageArea = target || pageArea; flush(i); i = Infinity; - } else if (target === pageArea || !(target instanceof PageArea)) { - // Just ignore the break and do layout again. - i--; - } else { - // We must stop the contentAreas filling and go to the next page. + } 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); @@ -4711,6 +4743,13 @@ class Template extends XFAObject { } this[$extra].pageNumber += 1; + if (targetPageArea) { + if (targetPageArea[$isUsable]()) { + targetPageArea[$extra].numberOfUse += 1; + } else { + targetPageArea = null; + } + } pageArea = targetPageArea || pageArea[$getNextPage](); } } diff --git a/src/core/xfa/xfa_object.js b/src/core/xfa/xfa_object.js index 07e1700b4b579..49ca4d3e7d760 100644 --- a/src/core/xfa/xfa_object.js +++ b/src/core/xfa/xfa_object.js @@ -25,6 +25,7 @@ const $addHTML = Symbol(); const $appendChild = Symbol(); const $childrenToHTML = Symbol(); const $clean = Symbol(); +const $cleanPage = Symbol(); const $cleanup = Symbol(); const $clone = Symbol(); const $consumed = Symbol(); @@ -59,6 +60,7 @@ const $isDataValue = Symbol(); const $isDescendent = Symbol(); const $isSplittable = Symbol(); const $isTransparent = Symbol(); +const $isUsable = Symbol(); const $lastAttribute = Symbol(); const $namespaceId = Symbol("namespaceId"); const $nodeName = Symbol("nodeName"); @@ -978,6 +980,7 @@ export { $appendChild, $childrenToHTML, $clean, + $cleanPage, $cleanup, $clone, $consumed, @@ -1012,6 +1015,7 @@ export { $isDescendent, $isSplittable, $isTransparent, + $isUsable, $namespaceId, $nodeName, $nsAttributes, diff --git a/test/pdfs/xfa_bug1716838.pdf.link b/test/pdfs/xfa_bug1716838.pdf.link new file mode 100644 index 0000000000000..e348452cb4157 --- /dev/null +++ b/test/pdfs/xfa_bug1716838.pdf.link @@ -0,0 +1 @@ +https://bugzilla.mozilla.org/attachment.cgi?id=9227473 diff --git a/test/test_manifest.json b/test/test_manifest.json index 3afe94ec35fe5..f203d4b8aec9f 100644 --- a/test/test_manifest.json +++ b/test/test_manifest.json @@ -962,6 +962,14 @@ "enableXfa": true, "type": "eq" }, + { "id": "xfa_bug1716838", + "file": "pdfs/xfa_bug1716838.pdf", + "md5": "564ecff67be690b43c2a144ae5967034", + "link": true, + "rounds": 1, + "enableXfa": true, + "type": "eq" + }, { "id": "xfa_candidate_petitions", "file": "pdfs/xfa_candidate_petitions.pdf", "md5": "0db96a00667f8f58f94cf81022e69341", diff --git a/test/unit/xfa_tohtml_spec.js b/test/unit/xfa_tohtml_spec.js index 3f77e5c5b2ae0..42767e3623f10 100644 --- a/test/unit/xfa_tohtml_spec.js +++ b/test/unit/xfa_tohtml_spec.js @@ -118,6 +118,10 @@ describe("XFAFactory", function () { expect(draw.attributes.style).toEqual({ color: "#0c1722", fontFamily: '"FooBar"', + fontKerning: "none", + letterSpacing: "0px", + fontStyle: "normal", + fontWeight: "normal", fontSize: "6.93px", margin: "1px 4px 2px 3px", verticalAlign: "2px",