Merge pull request #13495 from calixteman/draws
XFA - Display rectangle, line and arc
This commit is contained in:
commit
f2b9f0d6ea
@ -80,6 +80,7 @@ import { stringToBytes, Util, warn } from "../../shared/util.js";
|
|||||||
import { searchNode } from "./som.js";
|
import { searchNode } from "./som.js";
|
||||||
|
|
||||||
const TEMPLATE_NS_ID = NamespaceIds.template.id;
|
const TEMPLATE_NS_ID = NamespaceIds.template.id;
|
||||||
|
const SVG_NS = "http://www.w3.org/2000/svg";
|
||||||
|
|
||||||
// In case of lr-tb (and rl-tb) layouts, we try:
|
// In case of lr-tb (and rl-tb) layouts, we try:
|
||||||
// - to put the container at the end of a line
|
// - to put the container at the end of a line
|
||||||
@ -171,6 +172,10 @@ const NOSPACE = 1;
|
|||||||
const VALID = 2;
|
const VALID = 2;
|
||||||
function checkDimensions(node, space) {
|
function checkDimensions(node, space) {
|
||||||
const [x, y, w, h] = getTransformedBBox(node);
|
const [x, y, w, h] = getTransformedBBox(node);
|
||||||
|
if (node.w === 0 || node.h === 0) {
|
||||||
|
return VALID;
|
||||||
|
}
|
||||||
|
|
||||||
if (node.w !== "" && Math.round(x + w - space.width) > 1) {
|
if (node.w !== "" && Math.round(x + w - space.width) > 1) {
|
||||||
const area = getRoot(node)[$extra].currentContentArea;
|
const area = getRoot(node)[$extra].currentContentArea;
|
||||||
if (x + w > area.w) {
|
if (x + w > area.w) {
|
||||||
@ -227,6 +232,73 @@ class Arc extends XFAObject {
|
|||||||
this.edge = null;
|
this.edge = null;
|
||||||
this.fill = null;
|
this.fill = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$toHTML]() {
|
||||||
|
const edge = this.edge ? this.edge : new Edge({});
|
||||||
|
const edgeStyle = edge[$toStyle]();
|
||||||
|
const style = Object.create(null);
|
||||||
|
if (this.fill) {
|
||||||
|
Object.assign(style, this.fill[$toStyle]());
|
||||||
|
} else {
|
||||||
|
style.fill = "transparent";
|
||||||
|
}
|
||||||
|
style.strokeWidth = measureToString(Math.round(edge.thickness));
|
||||||
|
style.stroke = edgeStyle.color;
|
||||||
|
let arc;
|
||||||
|
const attributes = {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
style: {
|
||||||
|
position: "absolute",
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (this.startAngle === 0 && this.sweepAngle === 360) {
|
||||||
|
arc = {
|
||||||
|
name: "ellipse",
|
||||||
|
attributes: {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
cx: "50%",
|
||||||
|
cy: "50%",
|
||||||
|
rx: "50%",
|
||||||
|
ry: "50%",
|
||||||
|
style,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const startAngle = (this.startAngle * Math.PI) / 180;
|
||||||
|
const sweepAngle = (this.sweepAngle * Math.PI) / 180;
|
||||||
|
const largeArc = this.sweepAngle - this.startAngle > 180 ? 1 : 0;
|
||||||
|
const [x1, y1, x2, y2] = [
|
||||||
|
50 * (1 + Math.cos(startAngle)),
|
||||||
|
50 * (1 - Math.sin(startAngle)),
|
||||||
|
50 * (1 + Math.cos(sweepAngle)),
|
||||||
|
50 * (1 - Math.sin(sweepAngle)),
|
||||||
|
];
|
||||||
|
|
||||||
|
arc = {
|
||||||
|
name: "path",
|
||||||
|
attributes: {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
d: `M ${x1} ${y1} A 50 50 0 ${largeArc} 0 ${x2} ${y2}`,
|
||||||
|
vectorEffect: "non-scaling-stroke",
|
||||||
|
style,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(attributes, {
|
||||||
|
viewBox: "0 0 100 100",
|
||||||
|
preserveAspectRatio: "none",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return HTMLResult.success({
|
||||||
|
name: "svg",
|
||||||
|
children: [arc],
|
||||||
|
attributes,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Area extends XFAObject {
|
class Area extends XFAObject {
|
||||||
@ -1170,7 +1242,7 @@ class Corner extends XFAObject {
|
|||||||
// Maybe it's possible to implement them using svg and border-image...
|
// Maybe it's possible to implement them using svg and border-image...
|
||||||
// TODO: implement all the missing properties.
|
// TODO: implement all the missing properties.
|
||||||
const style = toStyle(this, "visibility");
|
const style = toStyle(this, "visibility");
|
||||||
style.radius = measureToString(this.radius);
|
style.radius = measureToString(this.join === "square" ? 0 : this.radius);
|
||||||
return style;
|
return style;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1412,12 +1484,7 @@ class Draw extends XFAObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
[$toHTML](availableSpace) {
|
[$toHTML](availableSpace) {
|
||||||
if (
|
if (this.presence === "hidden" || this.presence === "inactive") {
|
||||||
this.presence === "hidden" ||
|
|
||||||
this.presence === "inactive" ||
|
|
||||||
this.h === 0 ||
|
|
||||||
this.w === 0
|
|
||||||
) {
|
|
||||||
return HTMLResult.EMPTY;
|
return HTMLResult.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1485,7 +1552,7 @@ class Draw extends XFAObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
html.children.push(value);
|
html.children.push(value);
|
||||||
if (value.attributes.class.includes("xfaRich")) {
|
if (value.attributes.class && value.attributes.class.includes("xfaRich")) {
|
||||||
if (this.h === "") {
|
if (this.h === "") {
|
||||||
style.height = "auto";
|
style.height = "auto";
|
||||||
}
|
}
|
||||||
@ -2379,6 +2446,9 @@ class Fill extends XFAObject {
|
|||||||
if (parent instanceof Border) {
|
if (parent instanceof Border) {
|
||||||
propName = "background";
|
propName = "background";
|
||||||
}
|
}
|
||||||
|
if (parent instanceof Rectangle) {
|
||||||
|
propName = "fill";
|
||||||
|
}
|
||||||
const style = Object.create(null);
|
const style = Object.create(null);
|
||||||
for (const name of Object.getOwnPropertyNames(this)) {
|
for (const name of Object.getOwnPropertyNames(this)) {
|
||||||
if (name === "extras" || name === "color") {
|
if (name === "extras" || name === "color") {
|
||||||
@ -2853,6 +2923,57 @@ class Line extends XFAObject {
|
|||||||
this.usehref = attributes.usehref || "";
|
this.usehref = attributes.usehref || "";
|
||||||
this.edge = null;
|
this.edge = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$toHTML]() {
|
||||||
|
const parent = this[$getParent]()[$getParent]();
|
||||||
|
const edge = this.edge ? this.edge : new Edge({});
|
||||||
|
const edgeStyle = edge[$toStyle]();
|
||||||
|
const style = Object.create(null);
|
||||||
|
style.strokeWidth = measureToString(Math.round(edge.thickness));
|
||||||
|
style.stroke = edgeStyle.color;
|
||||||
|
let x1, y1, x2, y2;
|
||||||
|
let width = "100%";
|
||||||
|
let height = "100%";
|
||||||
|
|
||||||
|
if (parent.w <= edge.thickness) {
|
||||||
|
[x1, y1, x2, y2] = ["50%", 0, "50%", "100%"];
|
||||||
|
width = style.strokeWidth;
|
||||||
|
} else if (parent.h <= edge.thickness) {
|
||||||
|
[x1, y1, x2, y2] = [0, "50%", "100%", "50%"];
|
||||||
|
height = style.strokeWidth;
|
||||||
|
} else {
|
||||||
|
if (this.slope === "\\") {
|
||||||
|
[x1, y1, x2, y2] = [0, 0, "100%", "100%"];
|
||||||
|
} else {
|
||||||
|
[x1, y1, x2, y2] = [0, "100%", "100%", 0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const line = {
|
||||||
|
name: "line",
|
||||||
|
attributes: {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
x1,
|
||||||
|
y1,
|
||||||
|
x2,
|
||||||
|
y2,
|
||||||
|
style,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return HTMLResult.success({
|
||||||
|
name: "svg",
|
||||||
|
children: [line],
|
||||||
|
attributes: {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
style: {
|
||||||
|
position: "absolute",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Linear extends XFAObject {
|
class Linear extends XFAObject {
|
||||||
@ -3631,6 +3752,53 @@ class Rectangle extends XFAObject {
|
|||||||
this.edge = new XFAObjectArray(4);
|
this.edge = new XFAObjectArray(4);
|
||||||
this.fill = null;
|
this.fill = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[$toHTML]() {
|
||||||
|
const edge = this.edge.children.length
|
||||||
|
? this.edge.children[0]
|
||||||
|
: new Edge({});
|
||||||
|
const edgeStyle = edge[$toStyle]();
|
||||||
|
const style = Object.create(null);
|
||||||
|
if (this.fill) {
|
||||||
|
Object.assign(style, this.fill[$toStyle]());
|
||||||
|
} else {
|
||||||
|
style.fill = "transparent";
|
||||||
|
}
|
||||||
|
style.strokeWidth = measureToString(2 * edge.thickness);
|
||||||
|
style.stroke = edgeStyle.color;
|
||||||
|
|
||||||
|
const corner = this.corner.children.length
|
||||||
|
? this.corner.children[0]
|
||||||
|
: new Corner({});
|
||||||
|
const cornerStyle = corner[$toStyle]();
|
||||||
|
|
||||||
|
const rect = {
|
||||||
|
name: "rect",
|
||||||
|
attributes: {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
rx: cornerStyle.radius,
|
||||||
|
ry: cornerStyle.radius,
|
||||||
|
style,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return HTMLResult.success({
|
||||||
|
name: "svg",
|
||||||
|
children: [rect],
|
||||||
|
attributes: {
|
||||||
|
xmlns: SVG_NS,
|
||||||
|
style: {
|
||||||
|
position: "absolute",
|
||||||
|
},
|
||||||
|
width: "100%",
|
||||||
|
height: "100%",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class RefElement extends StringObject {
|
class RefElement extends StringObject {
|
||||||
|
@ -163,7 +163,13 @@ class XfaLayer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const childHtml = document.createElement(name);
|
let childHtml;
|
||||||
|
if (child?.attributes?.xmlns) {
|
||||||
|
childHtml = document.createElementNS(child.attributes.xmlns, name);
|
||||||
|
} else {
|
||||||
|
childHtml = document.createElement(name);
|
||||||
|
}
|
||||||
|
|
||||||
html.appendChild(childHtml);
|
html.appendChild(childHtml);
|
||||||
if (child.attributes) {
|
if (child.attributes) {
|
||||||
this.setAttributes(childHtml, child, storage, intent);
|
this.setAttributes(childHtml, child, storage, intent);
|
||||||
|
1
test/pdfs/xfa_fish_licence.pdf.link
Normal file
1
test/pdfs/xfa_fish_licence.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20210609130056/https://inspection.canada.ca/DAM/DAM-food-aliments/STAGING/text-texte/c5704_re_1357758804123_eng.pdf
|
1
test/pdfs/xfa_imm1295e.pdf.link
Normal file
1
test/pdfs/xfa_imm1295e.pdf.link
Normal file
@ -0,0 +1 @@
|
|||||||
|
https://web.archive.org/web/20210506174920/https://www.canada.ca/content/dam/ircc/migration/ircc/english/pdf/kits/forms/imm1295e.pdf
|
@ -930,6 +930,14 @@
|
|||||||
"link": true,
|
"link": true,
|
||||||
"type": "load"
|
"type": "load"
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_fish_licence",
|
||||||
|
"file": "pdfs/xfa_fish_licence.pdf",
|
||||||
|
"md5": "9b993128bbd7f4217098fd44116ebec2",
|
||||||
|
"link": true,
|
||||||
|
"rounds": 1,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "issue10272",
|
{ "id": "issue10272",
|
||||||
"file": "pdfs/issue10272.pdf",
|
"file": "pdfs/issue10272.pdf",
|
||||||
"md5": "bf3b2f74c6878d38a70dc0825f1b9a02",
|
"md5": "bf3b2f74c6878d38a70dc0825f1b9a02",
|
||||||
@ -4201,6 +4209,14 @@
|
|||||||
"type": "eq",
|
"type": "eq",
|
||||||
"about": "A CIDFontType0 font with a CFF font that isn't actually CID."
|
"about": "A CIDFontType0 font with a CFF font that isn't actually CID."
|
||||||
},
|
},
|
||||||
|
{ "id": "xfa_imm1295e",
|
||||||
|
"file": "pdfs/xfa_imm1295e.pdf",
|
||||||
|
"md5": "b995232fda9bb7fa57856ff7f4cda046",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": true,
|
||||||
|
"enableXfa": true,
|
||||||
|
"type": "eq"
|
||||||
|
},
|
||||||
{ "id": "scorecard_reduced",
|
{ "id": "scorecard_reduced",
|
||||||
"file": "pdfs/scorecard_reduced.pdf",
|
"file": "pdfs/scorecard_reduced.pdf",
|
||||||
"md5": "aa8ed0827092c963eea64adb718a3806",
|
"md5": "aa8ed0827092c963eea64adb718a3806",
|
||||||
|
Loading…
Reference in New Issue
Block a user