2021-03-19 18:11:40 +09:00
|
|
|
/* Copyright 2021 Mozilla Foundation
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
2021-05-19 18:09:21 +09:00
|
|
|
import {
|
2021-07-03 00:53:27 +09:00
|
|
|
$content,
|
2021-05-19 18:09:21 +09:00
|
|
|
$extra,
|
|
|
|
$getParent,
|
2021-06-12 00:49:13 +09:00
|
|
|
$getSubformParent,
|
2021-07-03 00:53:27 +09:00
|
|
|
$getTemplateRoot,
|
|
|
|
$globalData,
|
2021-05-19 18:09:21 +09:00
|
|
|
$nodeName,
|
2021-06-15 02:16:42 +09:00
|
|
|
$pushGlyphs,
|
2021-07-03 00:53:27 +09:00
|
|
|
$text,
|
2021-05-19 18:09:21 +09:00
|
|
|
$toStyle,
|
|
|
|
XFAObject,
|
|
|
|
} from "./xfa_object.js";
|
2021-06-23 18:10:20 +09:00
|
|
|
import { getMeasurement, stripQuotes } from "./utils.js";
|
|
|
|
import { selectFont } from "./fonts.js";
|
2021-06-15 02:16:42 +09:00
|
|
|
import { TextMeasure } from "./text.js";
|
2021-03-25 21:02:39 +09:00
|
|
|
import { warn } from "../../shared/util.js";
|
2021-03-19 18:11:40 +09:00
|
|
|
|
|
|
|
function measureToString(m) {
|
2021-03-31 22:42:21 +09:00
|
|
|
if (typeof m === "string") {
|
|
|
|
return "0px";
|
|
|
|
}
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-03-25 21:02:39 +09:00
|
|
|
return Number.isInteger(m) ? `${m}px` : `${m.toFixed(2)}px`;
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
|
|
|
|
2021-03-25 21:02:39 +09:00
|
|
|
const converters = {
|
|
|
|
anchorType(node, style) {
|
2021-07-06 21:11:21 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-05-19 18:09:21 +09:00
|
|
|
if (!parent || (parent.layout && parent.layout !== "position")) {
|
|
|
|
// anchorType is only used in a positioned layout.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-03-25 21:02:39 +09:00
|
|
|
if (!("transform" in style)) {
|
|
|
|
style.transform = "";
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
2021-03-25 21:02:39 +09:00
|
|
|
switch (node.anchorType) {
|
|
|
|
case "bottomCenter":
|
|
|
|
style.transform += "translate(-50%, -100%)";
|
|
|
|
break;
|
|
|
|
case "bottomLeft":
|
|
|
|
style.transform += "translate(0,-100%)";
|
|
|
|
break;
|
|
|
|
case "bottomRight":
|
|
|
|
style.transform += "translate(-100%,-100%)";
|
|
|
|
break;
|
|
|
|
case "middleCenter":
|
|
|
|
style.transform += "translate(-50%,-50%)";
|
|
|
|
break;
|
|
|
|
case "middleLeft":
|
|
|
|
style.transform += "translate(0,-50%)";
|
|
|
|
break;
|
|
|
|
case "middleRight":
|
|
|
|
style.transform += "translate(-100%,-50%)";
|
|
|
|
break;
|
|
|
|
case "topCenter":
|
|
|
|
style.transform += "translate(-50%,0)";
|
|
|
|
break;
|
|
|
|
case "topRight":
|
|
|
|
style.transform += "translate(-100%,0)";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
dimensions(node, style) {
|
2021-07-06 21:11:21 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-03-26 00:54:36 +09:00
|
|
|
let width = node.w;
|
2021-05-19 18:09:21 +09:00
|
|
|
const height = node.h;
|
|
|
|
if (parent.layout && parent.layout.includes("row")) {
|
|
|
|
const extra = parent[$extra];
|
|
|
|
const colSpan = node.colSpan;
|
|
|
|
let w;
|
|
|
|
if (colSpan === -1) {
|
|
|
|
w = extra.columnWidths
|
|
|
|
.slice(extra.currentColumn)
|
|
|
|
.reduce((a, x) => a + x, 0);
|
|
|
|
extra.currentColumn = 0;
|
|
|
|
} else {
|
|
|
|
w = extra.columnWidths
|
|
|
|
.slice(extra.currentColumn, extra.currentColumn + colSpan)
|
|
|
|
.reduce((a, x) => a + x, 0);
|
|
|
|
extra.currentColumn =
|
|
|
|
(extra.currentColumn + node.colSpan) % extra.columnWidths.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!isNaN(w)) {
|
|
|
|
width = node.w = w;
|
|
|
|
}
|
2021-03-26 00:54:36 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
if (width !== "") {
|
|
|
|
style.width = measureToString(width);
|
2021-03-25 21:02:39 +09:00
|
|
|
} else {
|
2021-03-31 22:42:21 +09:00
|
|
|
style.width = "auto";
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
|
|
|
|
2021-05-19 18:09:21 +09:00
|
|
|
if (height !== "") {
|
|
|
|
style.height = measureToString(height);
|
2021-03-25 21:02:39 +09:00
|
|
|
} else {
|
2021-03-31 22:42:21 +09:00
|
|
|
style.height = "auto";
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
2021-03-25 21:02:39 +09:00
|
|
|
},
|
|
|
|
position(node, style) {
|
2021-07-06 21:11:21 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-03-31 22:42:21 +09:00
|
|
|
if (parent && parent.layout && parent.layout !== "position") {
|
|
|
|
// IRL, we've some x/y in tb layout.
|
|
|
|
// Specs say x/y is only used in positioned layout.
|
|
|
|
return;
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
2021-03-31 22:42:21 +09:00
|
|
|
|
|
|
|
style.position = "absolute";
|
|
|
|
style.left = measureToString(node.x);
|
|
|
|
style.top = measureToString(node.y);
|
2021-03-25 21:02:39 +09:00
|
|
|
},
|
|
|
|
rotate(node, style) {
|
|
|
|
if (node.rotate) {
|
|
|
|
if (!("transform" in style)) {
|
|
|
|
style.transform = "";
|
|
|
|
}
|
|
|
|
style.transform += `rotate(-${node.rotate}deg)`;
|
|
|
|
style.transformOrigin = "top left";
|
|
|
|
}
|
|
|
|
},
|
2021-03-31 22:42:21 +09:00
|
|
|
presence(node, style) {
|
|
|
|
switch (node.presence) {
|
|
|
|
case "invisible":
|
|
|
|
style.visibility = "hidden";
|
|
|
|
break;
|
|
|
|
case "hidden":
|
|
|
|
case "inactive":
|
|
|
|
style.display = "none";
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
2021-03-26 00:54:36 +09:00
|
|
|
hAlign(node, style) {
|
2021-05-19 18:09:21 +09:00
|
|
|
if (node[$nodeName] === "para") {
|
|
|
|
switch (node.hAlign) {
|
|
|
|
case "justifyAll":
|
|
|
|
style.textAlign = "justify-all";
|
|
|
|
break;
|
|
|
|
case "radix":
|
|
|
|
// TODO: implement this correctly !
|
|
|
|
style.textAlign = "left";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
style.textAlign = node.hAlign;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (node.hAlign) {
|
2021-06-03 02:14:41 +09:00
|
|
|
case "left":
|
|
|
|
style.alignSelf = "start";
|
|
|
|
break;
|
2021-05-19 18:09:21 +09:00
|
|
|
case "center":
|
2021-06-03 02:14:41 +09:00
|
|
|
style.alignSelf = "center";
|
|
|
|
break;
|
|
|
|
case "right":
|
|
|
|
style.alignSelf = "end";
|
2021-05-19 18:09:21 +09:00
|
|
|
break;
|
|
|
|
}
|
2021-03-26 00:54:36 +09:00
|
|
|
}
|
|
|
|
},
|
2021-06-03 02:14:41 +09:00
|
|
|
margin(node, style) {
|
2021-05-19 18:09:21 +09:00
|
|
|
if (node.margin) {
|
2021-06-03 02:14:41 +09:00
|
|
|
style.margin = node.margin[$toStyle]().margin;
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
2021-03-26 00:54:36 +09:00
|
|
|
},
|
2021-03-25 21:02:39 +09:00
|
|
|
};
|
2021-03-19 18:11:40 +09:00
|
|
|
|
2021-06-16 23:02:41 +09:00
|
|
|
function setMinMaxDimensions(node, style) {
|
2021-07-06 21:11:21 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-06-16 23:02:41 +09:00
|
|
|
if (parent.layout === "position") {
|
2021-07-06 21:11:21 +09:00
|
|
|
if (node.minW > 0) {
|
|
|
|
style.minWidth = measureToString(node.minW);
|
|
|
|
}
|
|
|
|
if (node.maxW > 0) {
|
2021-06-16 23:02:41 +09:00
|
|
|
style.maxWidth = measureToString(node.maxW);
|
|
|
|
}
|
2021-07-06 21:11:21 +09:00
|
|
|
if (node.minH > 0) {
|
|
|
|
style.minHeight = measureToString(node.minH);
|
|
|
|
}
|
|
|
|
if (node.maxH > 0) {
|
2021-06-16 23:02:41 +09:00
|
|
|
style.maxHeight = measureToString(node.maxH);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-03 00:53:27 +09:00
|
|
|
function layoutText(text, xfaFont, margin, lineHeight, fontFinder, width) {
|
|
|
|
const measure = new TextMeasure(xfaFont, margin, lineHeight, fontFinder);
|
2021-06-15 02:16:42 +09:00
|
|
|
if (typeof text === "string") {
|
|
|
|
measure.addString(text);
|
|
|
|
} else {
|
|
|
|
text[$pushGlyphs](measure);
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
|
|
|
|
2021-06-15 02:16:42 +09:00
|
|
|
return measure.compute(width);
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
|
|
|
|
2021-07-03 00:53:27 +09:00
|
|
|
function layoutNode(node, availableSpace) {
|
|
|
|
let height = null;
|
|
|
|
let width = null;
|
|
|
|
|
|
|
|
if ((!node.w || !node.h) && node.value) {
|
|
|
|
let marginH = 0;
|
|
|
|
let marginV = 0;
|
|
|
|
if (node.margin) {
|
|
|
|
marginH = node.margin.leftInset + node.margin.rightInset;
|
|
|
|
marginV = node.margin.topInset + node.margin.bottomInset;
|
|
|
|
}
|
|
|
|
|
|
|
|
let lineHeight = null;
|
|
|
|
let margin = null;
|
|
|
|
if (node.para) {
|
|
|
|
margin = Object.create(null);
|
|
|
|
lineHeight = node.para.lineHeight === "" ? null : node.para.lineHeight;
|
|
|
|
margin.top = node.para.spaceAbove === "" ? 0 : node.para.spaceAbove;
|
|
|
|
margin.bottom = node.para.spaceBelow === "" ? 0 : node.para.spaceBelow;
|
|
|
|
margin.left = node.para.marginLeft === "" ? 0 : node.para.marginLeft;
|
|
|
|
margin.right = node.para.marginRight === "" ? 0 : node.para.marginRight;
|
|
|
|
}
|
|
|
|
|
|
|
|
let font = node.font;
|
|
|
|
if (!font) {
|
|
|
|
const root = node[$getTemplateRoot]();
|
|
|
|
let parent = node[$getParent]();
|
|
|
|
while (parent !== root) {
|
|
|
|
if (parent.font) {
|
|
|
|
font = parent.font;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
parent = parent[$getParent]();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const maxWidth = !node.w ? availableSpace.width : node.w;
|
|
|
|
const fontFinder = node[$globalData].fontFinder;
|
|
|
|
if (
|
|
|
|
node.value.exData &&
|
|
|
|
node.value.exData[$content] &&
|
|
|
|
node.value.exData.contentType === "text/html"
|
|
|
|
) {
|
|
|
|
const res = layoutText(
|
|
|
|
node.value.exData[$content],
|
|
|
|
font,
|
|
|
|
margin,
|
|
|
|
lineHeight,
|
|
|
|
fontFinder,
|
|
|
|
maxWidth
|
|
|
|
);
|
|
|
|
width = res.width;
|
|
|
|
height = res.height;
|
|
|
|
} else {
|
|
|
|
const text = node.value[$text]();
|
|
|
|
if (text) {
|
|
|
|
const res = layoutText(
|
|
|
|
text,
|
|
|
|
font,
|
|
|
|
margin,
|
|
|
|
lineHeight,
|
|
|
|
fontFinder,
|
|
|
|
maxWidth
|
|
|
|
);
|
|
|
|
width = res.width;
|
|
|
|
height = res.height;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (width !== null && !node.w) {
|
|
|
|
width += marginH;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (height !== null && !node.h) {
|
|
|
|
height += marginV;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return [width, height];
|
|
|
|
}
|
|
|
|
|
2021-05-19 18:09:21 +09:00
|
|
|
function computeBbox(node, html, availableSpace) {
|
|
|
|
let bbox;
|
|
|
|
if (node.w !== "" && node.h !== "") {
|
|
|
|
bbox = [node.x, node.y, node.w, node.h];
|
|
|
|
} else {
|
|
|
|
if (!availableSpace) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
let width = node.w;
|
|
|
|
if (width === "") {
|
|
|
|
if (node.maxW === 0) {
|
2021-07-06 21:11:21 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-05-19 18:09:21 +09:00
|
|
|
if (parent.layout === "position" && parent.w !== "") {
|
|
|
|
width = 0;
|
|
|
|
} else {
|
|
|
|
width = node.minW;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
width = Math.min(node.maxW, availableSpace.width);
|
|
|
|
}
|
|
|
|
html.attributes.style.width = measureToString(width);
|
|
|
|
}
|
|
|
|
|
|
|
|
let height = node.h;
|
|
|
|
if (height === "") {
|
|
|
|
if (node.maxH === 0) {
|
2021-07-06 21:11:21 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-05-19 18:09:21 +09:00
|
|
|
if (parent.layout === "position" && parent.h !== "") {
|
|
|
|
height = 0;
|
|
|
|
} else {
|
|
|
|
height = node.minH;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
height = Math.min(node.maxH, availableSpace.height);
|
|
|
|
}
|
|
|
|
html.attributes.style.height = measureToString(height);
|
|
|
|
}
|
|
|
|
|
|
|
|
bbox = [node.x, node.y, width, height];
|
|
|
|
}
|
|
|
|
return bbox;
|
|
|
|
}
|
|
|
|
|
|
|
|
function fixDimensions(node) {
|
2021-06-12 00:49:13 +09:00
|
|
|
const parent = node[$getSubformParent]();
|
2021-05-19 18:09:21 +09:00
|
|
|
if (parent.layout && parent.layout.includes("row")) {
|
|
|
|
const extra = parent[$extra];
|
|
|
|
const colSpan = node.colSpan;
|
|
|
|
let width;
|
|
|
|
if (colSpan === -1) {
|
|
|
|
width = extra.columnWidths
|
|
|
|
.slice(extra.currentColumn)
|
|
|
|
.reduce((a, w) => a + w, 0);
|
|
|
|
} else {
|
|
|
|
width = extra.columnWidths
|
|
|
|
.slice(extra.currentColumn, extra.currentColumn + colSpan)
|
|
|
|
.reduce((a, w) => a + w, 0);
|
|
|
|
}
|
|
|
|
if (!isNaN(width)) {
|
|
|
|
node.w = width;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent.layout && parent.layout !== "position") {
|
|
|
|
// Useless in this context.
|
|
|
|
node.x = node.y = 0;
|
|
|
|
}
|
|
|
|
|
2021-06-16 23:02:41 +09:00
|
|
|
if (node.layout === "table") {
|
|
|
|
if (node.w === "" && Array.isArray(node.columnWidths)) {
|
|
|
|
node.w = node.columnWidths.reduce((a, x) => a + x, 0);
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-31 22:42:21 +09:00
|
|
|
function layoutClass(node) {
|
|
|
|
switch (node.layout) {
|
|
|
|
case "position":
|
|
|
|
return "xfaPosition";
|
|
|
|
case "lr-tb":
|
|
|
|
return "xfaLrTb";
|
|
|
|
case "rl-row":
|
|
|
|
return "xfaRlRow";
|
|
|
|
case "rl-tb":
|
|
|
|
return "xfaRlTb";
|
|
|
|
case "row":
|
|
|
|
return "xfaRow";
|
|
|
|
case "table":
|
|
|
|
return "xfaTable";
|
|
|
|
case "tb":
|
|
|
|
return "xfaTb";
|
|
|
|
default:
|
|
|
|
return "xfaPosition";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-25 21:02:39 +09:00
|
|
|
function toStyle(node, ...names) {
|
|
|
|
const style = Object.create(null);
|
|
|
|
for (const name of names) {
|
|
|
|
const value = node[name];
|
|
|
|
if (value === null) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (value instanceof XFAObject) {
|
|
|
|
const newStyle = value[$toStyle]();
|
|
|
|
if (newStyle) {
|
|
|
|
Object.assign(style, newStyle);
|
|
|
|
} else {
|
|
|
|
warn(`(DEBUG) - XFA - style for ${name} not implemented yet`);
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2021-03-19 18:11:40 +09:00
|
|
|
|
2021-03-25 21:02:39 +09:00
|
|
|
if (converters.hasOwnProperty(name)) {
|
|
|
|
converters[name](node, style);
|
|
|
|
}
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
2021-03-25 21:02:39 +09:00
|
|
|
return style;
|
2021-03-19 18:11:40 +09:00
|
|
|
}
|
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
function createWrapper(node, html) {
|
|
|
|
const { attributes } = html;
|
|
|
|
const { style } = attributes;
|
2021-03-26 00:54:36 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
const wrapper = {
|
|
|
|
name: "div",
|
|
|
|
attributes: {
|
|
|
|
class: ["xfaWrapper"],
|
|
|
|
style: Object.create(null),
|
|
|
|
},
|
|
|
|
children: [html],
|
2021-05-19 18:09:21 +09:00
|
|
|
};
|
2021-03-26 00:54:36 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
attributes.class.push("xfaWrapped");
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
if (node.border) {
|
|
|
|
const { widths, insets } = node.border[$extra];
|
|
|
|
let shiftH = 0;
|
|
|
|
let shiftW = 0;
|
|
|
|
switch (node.border.hand) {
|
|
|
|
case "even":
|
|
|
|
shiftW = widths[0] / 2;
|
|
|
|
shiftH = widths[3] / 2;
|
|
|
|
break;
|
|
|
|
case "left":
|
|
|
|
shiftW = widths[0];
|
|
|
|
shiftH = widths[3];
|
|
|
|
break;
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
2021-06-03 02:14:41 +09:00
|
|
|
const insetsW = insets[1] + insets[3];
|
|
|
|
const insetsH = insets[0] + insets[2];
|
2021-06-20 22:38:58 +09:00
|
|
|
const classNames = ["xfaBorder"];
|
|
|
|
if (isPrintOnly(node.border)) {
|
|
|
|
classNames.push("xfaPrintOnly");
|
|
|
|
}
|
2021-06-03 02:14:41 +09:00
|
|
|
const border = {
|
|
|
|
name: "div",
|
|
|
|
attributes: {
|
2021-06-20 22:38:58 +09:00
|
|
|
class: classNames,
|
2021-06-03 02:14:41 +09:00
|
|
|
style: {
|
|
|
|
top: `${insets[0] - widths[0] + shiftW}px`,
|
|
|
|
left: `${insets[3] - widths[3] + shiftH}px`,
|
|
|
|
width: insetsW ? `calc(100% - ${insetsW}px)` : "100%",
|
|
|
|
height: insetsH ? `calc(100% - ${insetsH}px)` : "100%",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
children: [],
|
2021-05-19 18:09:21 +09:00
|
|
|
};
|
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
for (const key of [
|
|
|
|
"border",
|
|
|
|
"borderWidth",
|
|
|
|
"borderColor",
|
|
|
|
"borderRadius",
|
|
|
|
"borderStyle",
|
|
|
|
]) {
|
|
|
|
if (style[key] !== undefined) {
|
|
|
|
border.attributes.style[key] = style[key];
|
|
|
|
delete style[key];
|
|
|
|
}
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
2021-06-03 02:14:41 +09:00
|
|
|
wrapper.children.push(border);
|
|
|
|
}
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
for (const key of [
|
|
|
|
"background",
|
|
|
|
"backgroundClip",
|
|
|
|
"top",
|
|
|
|
"left",
|
|
|
|
"width",
|
|
|
|
"height",
|
|
|
|
"minWidth",
|
|
|
|
"minHeight",
|
|
|
|
"maxWidth",
|
|
|
|
"maxHeight",
|
|
|
|
"transform",
|
|
|
|
"transformOrigin",
|
2021-06-17 00:29:02 +09:00
|
|
|
"visibility",
|
2021-06-03 02:14:41 +09:00
|
|
|
]) {
|
|
|
|
if (style[key] !== undefined) {
|
|
|
|
wrapper.attributes.style[key] = style[key];
|
|
|
|
delete style[key];
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
2021-06-03 02:14:41 +09:00
|
|
|
}
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
if (style.position === "absolute") {
|
|
|
|
wrapper.attributes.style.position = "absolute";
|
|
|
|
} else {
|
|
|
|
wrapper.attributes.style.position = "relative";
|
2021-03-26 00:54:36 +09:00
|
|
|
}
|
2021-06-03 02:14:41 +09:00
|
|
|
delete style.position;
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
if (style.alignSelf) {
|
|
|
|
wrapper.attributes.style.alignSelf = style.alignSelf;
|
|
|
|
delete style.alignSelf;
|
|
|
|
}
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
return wrapper;
|
2021-03-26 00:54:36 +09:00
|
|
|
}
|
|
|
|
|
2021-05-19 18:09:21 +09:00
|
|
|
function fixTextIndent(styles) {
|
|
|
|
const indent = getMeasurement(styles.textIndent, "0px");
|
|
|
|
if (indent >= 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-06-03 02:14:41 +09:00
|
|
|
// If indent is negative then it's a hanging indent.
|
2021-07-04 01:06:59 +09:00
|
|
|
const align = styles.textAlign === "right" ? "right" : "left";
|
|
|
|
const name = "padding" + (align === "left" ? "Left" : "Right");
|
|
|
|
const padding = getMeasurement(styles[name], "0px");
|
|
|
|
styles[name] = `${padding - indent}px`;
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
|
|
|
|
2021-06-21 01:56:14 +09:00
|
|
|
function setAccess(node, classNames) {
|
|
|
|
switch (node.access) {
|
|
|
|
case "nonInteractive":
|
|
|
|
case "readOnly":
|
|
|
|
classNames.push("xfaReadOnly");
|
|
|
|
break;
|
|
|
|
case "protected":
|
|
|
|
classNames.push("xfaDisabled");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-20 22:38:58 +09:00
|
|
|
function isPrintOnly(node) {
|
|
|
|
return (
|
|
|
|
node.relevant.length > 0 &&
|
|
|
|
!node.relevant[0].excluded &&
|
|
|
|
node.relevant[0].viewname === "print"
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-06-23 18:10:20 +09:00
|
|
|
function setFontFamily(xfaFont, fontFinder, style) {
|
|
|
|
const name = stripQuotes(xfaFont.typeface);
|
|
|
|
const typeface = fontFinder.find(name);
|
2021-05-19 18:09:21 +09:00
|
|
|
|
2021-06-23 18:10:20 +09:00
|
|
|
style.fontFamily = `"${name}"`;
|
|
|
|
if (typeface) {
|
|
|
|
const { fontFamily } = typeface.regular.cssFontInfo;
|
|
|
|
if (fontFamily !== name) {
|
2021-07-03 22:13:51 +09:00
|
|
|
style.fontFamily = `"${fontFamily}"`;
|
2021-06-23 18:10:20 +09:00
|
|
|
}
|
|
|
|
if (style.lineHeight) {
|
|
|
|
// Already something so don't overwrite.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const pdfFont = selectFont(xfaFont, typeface);
|
|
|
|
if (pdfFont && pdfFont.lineHeight > 0) {
|
|
|
|
style.lineHeight = pdfFont.lineHeight;
|
2021-06-20 21:03:59 +09:00
|
|
|
}
|
|
|
|
}
|
2021-05-19 18:09:21 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
export {
|
|
|
|
computeBbox,
|
2021-06-03 02:14:41 +09:00
|
|
|
createWrapper,
|
2021-05-19 18:09:21 +09:00
|
|
|
fixDimensions,
|
|
|
|
fixTextIndent,
|
2021-06-20 22:38:58 +09:00
|
|
|
isPrintOnly,
|
2021-05-19 18:09:21 +09:00
|
|
|
layoutClass,
|
2021-07-03 00:53:27 +09:00
|
|
|
layoutNode,
|
2021-05-19 18:09:21 +09:00
|
|
|
measureToString,
|
2021-06-21 01:56:14 +09:00
|
|
|
setAccess,
|
2021-06-23 18:10:20 +09:00
|
|
|
setFontFamily,
|
2021-06-16 23:02:41 +09:00
|
|
|
setMinMaxDimensions,
|
2021-05-19 18:09:21 +09:00
|
|
|
toStyle,
|
|
|
|
};
|