: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
class SignData extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "signData", true);
this.id = attributes.id || "";
this.operation = getStringOption(attributes.operation, ["sign", "clear", "verify"]);
this.ref = attributes.ref || "";
this.target = attributes.target || "";
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
class Signature extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "signature", true);
this.id = attributes.id || "";
this.type = getStringOption(attributes.type, ["PDF1.3", "PDF1.6"]);
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
class Signing extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "signing", true);
this.id = attributes.id || "";
this.type = getStringOption(attributes.type, ["optional", "required"]);
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
this.certificate = new XFAObjectArray();
class Solid extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "solid", true);
this.id = attributes.id || "";
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
return startColor ? startColor[$toStyle]() : "#FFFFFF";
class Speak extends StringObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "speak");
this.disable = getInteger({
data: attributes.disable,
this.id = attributes.id || "";
this.priority = getStringOption(attributes.priority, ["custom", "caption", "name", "toolTip"]);
this.rid = attributes.rid || "";
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
class Stipple extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "stipple", true);
this.id = attributes.id || "";
validate: x => x >= 0 && x <= 100
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
const alpha = this.rate / 100;
return Util.makeHexColor(Math.round(bgColor.value.r * (1 - alpha) + this.value.r * alpha), Math.round(bgColor.value.g * (1 - alpha) + this.value.g * alpha), Math.round(bgColor.value.b * (1 - alpha) + this.value.b * alpha));
class Subform extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "subform", true);
this.access = getStringOption(attributes.access, ["open", "nonInteractive", "protected", "readOnly"]);
this.allowMacro = getInteger({
data: attributes.allowMacro,
this.anchorType = getStringOption(attributes.anchorType, ["topLeft", "bottomCenter", "bottomLeft", "bottomRight", "middleCenter", "middleLeft", "middleRight", "topCenter", "topRight"]);
this.colSpan = getInteger({
data: attributes.colSpan,
validate: n => n >= 1 || n === -1
this.columnWidths = (attributes.columnWidths || "").trim().split(/\s+/).map(x => x === "-1" ? -1 : getMeasurement(x));
this.h = attributes.h ? getMeasurement(attributes.h) : "";
this.hAlign = getStringOption(attributes.hAlign, ["left", "center", "justify", "justifyAll", "radix", "right"]);
this.id = attributes.id || "";
this.layout = getStringOption(attributes.layout, ["position", "lr-tb", "rl-row", "rl-tb", "row", "table", "tb"]);
this.locale = attributes.locale || "";
this.maxH = getMeasurement(attributes.maxH, "0pt");
this.maxW = getMeasurement(attributes.maxW, "0pt");
this.mergeMode = getStringOption(attributes.mergeMode, ["consumeData", "matchTemplate"]);
this.minH = getMeasurement(attributes.minH, "0pt");
this.minW = getMeasurement(attributes.minW, "0pt");
this.name = attributes.name || "";
this.presence = getStringOption(attributes.presence, ["visible", "hidden", "inactive", "invisible"]);
this.relevant = getRelevant(attributes.relevant);
this.restoreState = getStringOption(attributes.restoreState, ["manual", "auto"]);
this.scope = getStringOption(attributes.scope, ["name", "none"]);
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
this.w = attributes.w ? getMeasurement(attributes.w) : "";
this.x = getMeasurement(attributes.x, "0pt");
this.y = getMeasurement(attributes.y, "0pt");
this.area = new XFAObjectArray();
this.breakAfter = new XFAObjectArray();
this.breakBefore = new XFAObjectArray();
this.connect = new XFAObjectArray();
this.draw = new XFAObjectArray();
this.event = new XFAObjectArray();
this.exObject = new XFAObjectArray();
this.exclGroup = new XFAObjectArray();
this.field = new XFAObjectArray();
this.proto = new XFAObjectArray();
this.setProperty = new XFAObjectArray();
this.subform = new XFAObjectArray();
this.subformSet = new XFAObjectArray();
const parent = this[$getParent]();
if (parent instanceof SubformSet) {
return parent[$getSubformParent]();
return this.layout.endsWith("-tb") && this[$extra].attempt === 0 && this[$extra].numberInLine > 0 || this[$getParent]()[$isThereMoreWidth]();
*[$getContainedChildren]() {
yield* getContainedChildren(this);
addHTML(this, html, bbox);
return getAvailableSpace(this);
const parent = this[$getSubformParent]();
if (!parent[$isSplittable]()) {
if (this[$extra]._isSplittable !== undefined) {
return this[$extra]._isSplittable;
if (this.layout === "position" || this.layout.includes("row")) {
this[$extra]._isSplittable = false;
if (this.keep && this.keep.intact !== "none") {
this[$extra]._isSplittable = false;
if (parent.layout?.endsWith("-tb") && parent[$extra].numberInLine !== 0) {
this[$extra]._isSplittable = true;
[$toHTML](availableSpace) {
if (this.break.after !== "auto" || this.break.afterTarget !== "") {
const node = new BreakAfter({
targetType: this.break.after,
target: this.break.afterTarget,
startNew: this.break.startNew.toString()
node[$globalData] = this[$globalData];
this[$appendChild](node);
this.breakAfter.push(node);
if (this.break.before !== "auto" || this.break.beforeTarget !== "") {
const node = new BreakBefore({
targetType: this.break.before,
target: this.break.beforeTarget,
startNew: this.break.startNew.toString()
node[$globalData] = this[$globalData];
this[$appendChild](node);
this.breakBefore.push(node);
if (this.break.overflowTarget !== "") {
const node = new Overflow({
target: this.break.overflowTarget,
leader: this.break.overflowLeader,
trailer: this.break.overflowTrailer
node[$globalData] = this[$globalData];
this[$appendChild](node);
this.overflow.push(node);
this[$removeChild](this.break);
if (this.presence === "hidden" || this.presence === "inactive") {
if (this.breakBefore.children.length > 1 || this.breakAfter.children.length > 1) {
warn("XFA - Several breakBefore or breakAfter in subforms: please file a bug.");
if (this.breakBefore.children.length >= 1) {
const breakBefore = this.breakBefore.children[0];
if (handleBreak(breakBefore)) {
return HTMLResult.breakNode(breakBefore);
if (this[$extra]?.afterBreakAfter) {
setAccess(this, attributes.class);
this[$extra] = Object.create(null);
Object.assign(this[$extra], {
width: Math.min(this.w || Infinity, availableSpace.width),
height: Math.min(this.h || Infinity, availableSpace.height)
const root = this[$getTemplateRoot]();
const savedNoLayoutFailure = root[$extra].noLayoutFailure;
const isSplittable = this[$isSplittable]();
setFirstUnsplittable(this);
if (!checkDimensions(this, availableSpace)) {
return HTMLResult.FAILURE;
const filter = new Set(["area", "draw", "exclGroup", "field", "subform", "subformSet"]);
if (this.layout.includes("row")) {
const columnWidths = this[$getSubformParent]().columnWidths;
if (Array.isArray(columnWidths) && columnWidths.length > 0) {
this[$extra].columnWidths = columnWidths;
this[$extra].currentColumn = 0;
const style = toStyle(this, "anchorType", "dimensions", "position", "presence", "border", "margin", "hAlign");
const classNames = ["xfaSubform"];
const cl = layoutClass(this);
attributes.style = style;
attributes.class = classNames;
attributes.xfaName = this.name;
const overflowExtra = this.overflow[$getExtra]();
if (overflowExtra.addLeader) {
overflowExtra.addLeader = false;
handleOverflow(this, overflowExtra.leader, availableSpace);
const isLrTb = this.layout === "lr-tb" || this.layout === "rl-tb";
const maxRun = isLrTb ? MAX_ATTEMPTS_FOR_LRTB_LAYOUT : 1;
for (; this[$extra].attempt < maxRun; this[$extra].attempt++) {
if (isLrTb && this[$extra].attempt === MAX_ATTEMPTS_FOR_LRTB_LAYOUT - 1) {
this[$extra].numberInLine = 0;
const result = this[$childrenToHTML]({
if (isLrTb && this[$extra].attempt === 0 && this[$extra].numberInLine === 0 && !root[$extra].noLayoutFailure) {
this[$extra].attempt = maxRun;
unsetFirstUnsplittable(this);
root[$extra].noLayoutFailure = savedNoLayoutFailure;
if (this[$extra].attempt === maxRun) {
this[$getTemplateRoot]()[$extra].overflowNode = this.overflow;
return HTMLResult.FAILURE;
const overflowExtra = this.overflow[$getExtra]();
if (overflowExtra.addTrailer) {
overflowExtra.addTrailer = false;
handleOverflow(this, overflowExtra.trailer, availableSpace);
marginH = this.margin.leftInset + this.margin.rightInset;
marginV = this.margin.topInset + this.margin.bottomInset;
const width = Math.max(this[$extra].width + marginH, this.w || 0);
const height = Math.max(this[$extra].height + marginV, this.h || 0);
const bbox = [this.x, this.y, width, height];
style.width = measureToString(width);
style.height = measureToString(height);
if ((style.width === "0px" || style.height === "0px") && children.length === 0) {
applyAssist(this, attributes);
const result = HTMLResult.success(createWrapper(this, html), bbox);
if (this.breakAfter.children.length >= 1) {
const breakAfter = this.breakAfter.children[0];
if (handleBreak(breakAfter)) {
this[$extra].afterBreakAfter = result;
return HTMLResult.breakNode(breakAfter);
class SubformSet extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "subformSet", true);
this.id = attributes.id || "";
this.name = attributes.name || "";
this.relation = getStringOption(attributes.relation, ["ordered", "choice", "unordered"]);
this.relevant = getRelevant(attributes.relevant);
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
this.breakAfter = new XFAObjectArray();
this.breakBefore = new XFAObjectArray();
this.subform = new XFAObjectArray();
this.subformSet = new XFAObjectArray();
*[$getContainedChildren]() {
yield* getContainedChildren(this);
let parent = this[$getParent]();
while (!(parent instanceof Subform)) {
parent = parent[$getParent]();
class SubjectDN extends ContentObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "subjectDN");
this.delimiter = attributes.delimiter || ",";
this.id = attributes.id || "";
this.name = attributes.name || "";
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
this[$content] = new Map(this[$content].split(this.delimiter).map(kv => {
class SubjectDNs extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "subjectDNs", true);
this.id = attributes.id || "";
this.type = getStringOption(attributes.type, ["optional", "required"]);
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
this.subjectDN = new XFAObjectArray();
class Submit extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "submit", true);
this.embedPDF = getInteger({
data: attributes.embedPDF,
this.format = getStringOption(attributes.format, ["xdp", "formdata", "pdf", "urlencoded", "xfd", "xml"]);
this.id = attributes.id || "";
this.target = attributes.target || "";
this.textEncoding = getKeyword({
data: attributes.textEncoding ? attributes.textEncoding.toLowerCase() : "",
validate: k => ["utf-8", "big-five", "fontspecific", "gbk", "gb-18030", "gb-2312", "ksc-5601", "none", "shift-jis", "ucs-2", "utf-16"].includes(k) || k.match(/iso-8859-\d{2}/)
this.use = attributes.use || "";
this.usehref = attributes.usehref || "";
this.xdpContent = attributes.xdpContent || "";
this.encryptData = new XFAObjectArray();
this.signData = new XFAObjectArray();
class Template extends XFAObject {
constructor(attributes) {
super(TEMPLATE_NS_ID, "template", true);
this.baseProfile = getStringOption(attributes.baseProfile, ["full", "interactiveForms"]);
this.subform = new XFAObjectArray();
if (this.subform.children.length === 0) {
warn("XFA - No subforms in template node.");
if (this.subform.children.length >= 2) {
warn("XFA - Several subforms in template node: please file a bug.");
this[$tabIndex] = DEFAULT_TAB_INDEX;
[$searchNode](expr, container) {
if (expr.startsWith("#")) {
return [this[$ids].get(expr.slice(1))];
return searchNode(this, container, expr, true, true);