diff --git a/src/core/xfa/template.js b/src/core/xfa/template.js index 486a2566e01c80..154e97c1bbe82d 100644 --- a/src/core/xfa/template.js +++ b/src/core/xfa/template.js @@ -79,6 +79,7 @@ import { stringToBytes, Util, warn } from "../../shared/util.js"; import { searchNode } from "./som.js"; 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: // - to put the container at the end of a line @@ -226,6 +227,50 @@ class Arc extends XFAObject { this.edge = 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; + const startAngle = (this.startAngle * Math.PI) / 180; + const sweepAngle = (this.sweepAngle * Math.PI) / 180; + const arcSweep = this.sweepAngle - this.startAngle <= 180 ? 0 : 1; + + const [x1, y1, x2, y2] = [ + 0.5 * (1 + Math.cos(startAngle)), + 0.5 * (1 + Math.sin(startAngle)), + 0.5 * (1 + Math.cos(sweepAngle)), + 0.5 * (1 + Math.sin(sweepAngle)), + ]; + + const arc = { + name: "path", + attributes: { + xmlns: SVG_NS, + d: `M ${x1} ${y1} A 0.5 0.5 0 ${arcSweep} 0 ${x2} ${y2} L 0.5 0.5 L ${x1} ${y1}`, + style, + }, + }; + + return HTMLResult.success({ + name: "svg", + children: [arc], + attributes: { + xmlns: SVG_NS, + style: { + width: "100%", + height: "100%", + }, + }, + }); + } } class Area extends XFAObject { @@ -1169,7 +1214,7 @@ class Corner extends XFAObject { // Maybe it's possible to implement them using svg and border-image... // TODO: implement all the missing properties. const style = toStyle(this, "visibility"); - style.radius = measureToString(this.radius); + style.radius = measureToString(this.join === "square" ? 0 : this.radius); return style; } } @@ -1484,7 +1529,7 @@ class Draw extends XFAObject { } html.children.push(value); - if (value.attributes.class.includes("xfaRich")) { + if (value.attributes.class && value.attributes.class.includes("xfaRich")) { if (this.h === "") { style.height = "auto"; } @@ -2374,6 +2419,9 @@ class Fill extends XFAObject { if (parent instanceof Border) { propName = "background"; } + if (parent instanceof Rectangle) { + propName = "fill"; + } const style = Object.create(null); for (const name of Object.getOwnPropertyNames(this)) { if (name === "extras" || name === "color") { @@ -2848,6 +2896,46 @@ class Line extends XFAObject { this.usehref = attributes.usehref || ""; this.edge = null; } + + [$toHTML]() { + 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; + if (this.slope === "\\") { + [x1, y1, x2, y2] = [0, 0, 1, 1]; + } else { + [x1, y1, x2, y2] = [0, 1, 1, 0]; + } + + const line = { + name: "line", + attributes: { + xmlns: SVG_NS, + width: "100%", + height: "100%", + x1, + y1, + x2, + y2, + style, + }, + }; + + return HTMLResult.success({ + name: "svg", + children: [line], + attributes: { + xmlns: SVG_NS, + style: { + width: "100%", + height: "100%", + }, + }, + }); + } } class Linear extends XFAObject { @@ -3626,6 +3714,50 @@ class Rectangle extends XFAObject { this.edge = new XFAObjectArray(4); 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(Math.round(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%", + rx: cornerStyle.radius, + ry: cornerStyle.radius, + style, + }, + }; + + return HTMLResult.success({ + name: "svg", + children: [rect], + attributes: { + xmlns: SVG_NS, + style: { + width: "100%", + height: "100%", + }, + }, + }); + } } class RefElement extends StringObject { diff --git a/src/display/xfa_layer.js b/src/display/xfa_layer.js index e129ca049f272b..f02a0e634070d0 100644 --- a/src/display/xfa_layer.js +++ b/src/display/xfa_layer.js @@ -163,7 +163,14 @@ class XfaLayer { continue; } - const childHtml = document.createElement(name); + let childHtml; + if (child?.attributes?.xmlns) { + childHtml = document.createElementNS(child.attributes.xmlns, name); + delete child.attributes.xmlns; + } else { + childHtml = document.createElement(name); + } + html.appendChild(childHtml); if (child.attributes) { this.setAttributes(childHtml, child, storage, intent);