mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-26 10:08:06 +02:00
XFA - Fix text positions (bug 1718741)
- font line height is taken into account by acrobat when it isn't with masterpdfeditor: I extracted a font from a pdf, modified some ascent/descent properties thanks to ttx and the reinjected the font in the pdf: only Acrobat is taken it into account. So in this patch, line heights for some substituted fonts are added. - it seems that Acrobat is using a line height of 1.2 when the line height in the font is not enough (it's the only way I found to fix correctly bug 1718741). - don't use flex in wrapper container (which was causing an horizontal overflow in the above bug). - consequently, the above fixes introduced a lot of small regressions, so in order to see real improvements on reftests, I fixed the regressions in this patch: - replace margin by padding in some case where padding is a part of a container dimensions; - remove some flex display: some containers are wrongly sized when rendered; - set letter-spacing to 0.01px: it helps to be sure that text is not broken because of not enough width in Firefox.
This commit is contained in:
parent
0afc785c7d
commit
58e1f51688
15 changed files with 220 additions and 103 deletions
|
@ -80,6 +80,7 @@ import {
|
|||
setAccess,
|
||||
setFontFamily,
|
||||
setMinMaxDimensions,
|
||||
setPara,
|
||||
toStyle,
|
||||
} from "./html_utils.js";
|
||||
import {
|
||||
|
@ -134,12 +135,20 @@ function* getContainedChildren(node) {
|
|||
|
||||
function valueToHtml(value) {
|
||||
return HTMLResult.success({
|
||||
name: "span",
|
||||
name: "div",
|
||||
attributes: {
|
||||
class: ["xfaRich"],
|
||||
style: Object.create(null),
|
||||
},
|
||||
value,
|
||||
children: [
|
||||
{
|
||||
name: "span",
|
||||
attributes: {
|
||||
style: Object.create(null),
|
||||
},
|
||||
value,
|
||||
},
|
||||
],
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -225,6 +234,15 @@ function handleBreak(node) {
|
|||
return true;
|
||||
}
|
||||
|
||||
function handleOverflow(node, extraNode, space) {
|
||||
const root = node[$getTemplateRoot]();
|
||||
const saved = root[$extra].noLayoutFailure;
|
||||
root[$extra].noLayoutFailure = true;
|
||||
const res = extraNode[$toHTML](space);
|
||||
node[$addHTML](res.html, res.bbox);
|
||||
root[$extra].noLayoutFailure = saved;
|
||||
}
|
||||
|
||||
class AppearanceFilter extends StringObject {
|
||||
constructor(attributes) {
|
||||
super(TEMPLATE_NS_ID, "appearanceFilter");
|
||||
|
@ -973,7 +991,7 @@ class Caption extends XFAObject {
|
|||
children.push(value);
|
||||
}
|
||||
|
||||
const style = toStyle(this, "font", "margin", "para", "visibility");
|
||||
const style = toStyle(this, "font", "margin", "visibility");
|
||||
switch (this.placement) {
|
||||
case "left":
|
||||
case "right":
|
||||
|
@ -989,6 +1007,8 @@ class Caption extends XFAObject {
|
|||
break;
|
||||
}
|
||||
|
||||
setPara(this, null, value);
|
||||
|
||||
this.reserve = savedReserve;
|
||||
|
||||
return HTMLResult.success({
|
||||
|
@ -1654,6 +1674,11 @@ class Draw extends XFAObject {
|
|||
|
||||
setMinMaxDimensions(this, style);
|
||||
|
||||
if (style.margin) {
|
||||
style.padding = style.margin;
|
||||
delete style.margin;
|
||||
}
|
||||
|
||||
const classNames = ["xfaDraw"];
|
||||
if (this.font) {
|
||||
classNames.push("xfaFont");
|
||||
|
@ -1688,42 +1713,7 @@ class Draw extends XFAObject {
|
|||
}
|
||||
|
||||
html.children.push(value);
|
||||
if (value.attributes.class && value.attributes.class.includes("xfaRich")) {
|
||||
if (this.h === "") {
|
||||
style.height = "auto";
|
||||
}
|
||||
if (this.w === "") {
|
||||
style.width = "auto";
|
||||
}
|
||||
if (this.para) {
|
||||
// By definition exData are external data so para
|
||||
// has no effect on it.
|
||||
attributes.style.display = "flex";
|
||||
attributes.style.flexDirection = "column";
|
||||
switch (this.para.vAlign) {
|
||||
case "top":
|
||||
attributes.style.justifyContent = "start";
|
||||
break;
|
||||
case "bottom":
|
||||
attributes.style.justifyContent = "end";
|
||||
break;
|
||||
case "middle":
|
||||
attributes.style.justifyContent = "center";
|
||||
break;
|
||||
}
|
||||
|
||||
const paraStyle = this.para[$toStyle]();
|
||||
if (!value.attributes.style) {
|
||||
value.attributes.style = paraStyle;
|
||||
} else {
|
||||
for (const [key, val] of Object.entries(paraStyle)) {
|
||||
if (!(key in value.attributes.style)) {
|
||||
value.attributes.style[key] = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setPara(this, style, value);
|
||||
|
||||
this.w = savedW;
|
||||
this.h = savedH;
|
||||
|
@ -2510,20 +2500,21 @@ class Field extends XFAObject {
|
|||
|
||||
width = w;
|
||||
height = h;
|
||||
if (this.ui instanceof CheckButton) {
|
||||
if (this.ui.checkButton) {
|
||||
switch (this.caption.placement) {
|
||||
case "left":
|
||||
case "right":
|
||||
case "inline":
|
||||
width += this.ui.size;
|
||||
width += this.ui.checkButton.size;
|
||||
break;
|
||||
case "top":
|
||||
case "bottom":
|
||||
height += this.ui.size;
|
||||
height += this.ui.checkButton.size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (width && this.w === "") {
|
||||
this.w = Math.min(
|
||||
this.maxW <= 0 ? Infinity : this.maxW,
|
||||
|
@ -2579,6 +2570,11 @@ class Field extends XFAObject {
|
|||
class: classNames,
|
||||
};
|
||||
|
||||
if (style.margin) {
|
||||
style.padding = style.margin;
|
||||
delete style.margin;
|
||||
}
|
||||
|
||||
setAccess(this, classNames);
|
||||
|
||||
if (this.name) {
|
||||
|
@ -2623,7 +2619,7 @@ class Field extends XFAObject {
|
|||
} else {
|
||||
const htmlValue = this.value[$toHTML]().html;
|
||||
if (htmlValue !== null) {
|
||||
value = htmlValue.value;
|
||||
value = htmlValue.children[0].value;
|
||||
}
|
||||
}
|
||||
if (this.ui.textEdit && this.value.text && this.value.text.maxChars) {
|
||||
|
@ -2652,6 +2648,9 @@ class Field extends XFAObject {
|
|||
}
|
||||
|
||||
if (this.ui.button) {
|
||||
if (style.padding) {
|
||||
delete style.padding;
|
||||
}
|
||||
if (caption.name === "div") {
|
||||
caption.name = "span";
|
||||
}
|
||||
|
@ -2910,11 +2909,7 @@ class Font extends XFAObject {
|
|||
// TODO: overlinePeriod
|
||||
|
||||
style.fontStyle = this.posture;
|
||||
|
||||
const fontSize = measureToString(0.99 * this.size);
|
||||
if (fontSize !== "10px") {
|
||||
style.fontSize = fontSize;
|
||||
}
|
||||
style.fontSize = measureToString(0.99 * this.size);
|
||||
|
||||
setFontFamily(this, this[$globalData].fontFinder, style);
|
||||
|
||||
|
@ -3513,8 +3508,14 @@ class Overflow extends XFAObject {
|
|||
const parent = this[$getParent]();
|
||||
const root = this[$getTemplateRoot]();
|
||||
const target = root[$searchNode](this.target, parent);
|
||||
const leader = root[$searchNode](this.leader, parent);
|
||||
const trailer = root[$searchNode](this.trailer, parent);
|
||||
this[$extra] = {
|
||||
target: (target && target[0]) || null,
|
||||
leader: (leader && leader[0]) || null,
|
||||
trailer: (trailer && trailer[0]) || null,
|
||||
addLeader: false,
|
||||
addTrailer: false,
|
||||
};
|
||||
}
|
||||
return this[$extra];
|
||||
|
@ -3834,16 +3835,16 @@ class Para extends XFAObject {
|
|||
[$toStyle]() {
|
||||
const style = toStyle(this, "hAlign");
|
||||
if (this.marginLeft !== "") {
|
||||
style.marginLeft = measureToString(this.marginLeft);
|
||||
style.paddingLeft = measureToString(this.marginLeft);
|
||||
}
|
||||
if (this.marginRight !== "") {
|
||||
style.marginRight = measureToString(this.marginRight);
|
||||
style.paddingight = measureToString(this.marginRight);
|
||||
}
|
||||
if (this.spaceAbove !== "") {
|
||||
style.marginTop = measureToString(this.spaceAbove);
|
||||
style.paddingTop = measureToString(this.spaceAbove);
|
||||
}
|
||||
if (this.spaceBelow !== "") {
|
||||
style.marginBottom = measureToString(this.spaceBelow);
|
||||
style.paddingBottom = measureToString(this.spaceBelow);
|
||||
}
|
||||
if (this.textIndent !== "") {
|
||||
style.textIndent = measureToString(this.textIndent);
|
||||
|
@ -4658,6 +4659,14 @@ class Subform extends XFAObject {
|
|||
attributes.xfaName = this.name;
|
||||
}
|
||||
|
||||
if (this.overflow) {
|
||||
const overflowExtra = this.overflow[$getExtra]();
|
||||
if (overflowExtra.addLeader) {
|
||||
overflowExtra.addLeader = false;
|
||||
handleOverflow(this, overflowExtra.leader, availableSpace);
|
||||
}
|
||||
}
|
||||
|
||||
const maxRun =
|
||||
this.layout === "lr-tb" || this.layout === "rl-tb"
|
||||
? MAX_ATTEMPTS_FOR_LRTB_LAYOUT
|
||||
|
@ -4699,6 +4708,14 @@ class Subform extends XFAObject {
|
|||
return HTMLResult.FAILURE;
|
||||
}
|
||||
|
||||
if (this.overflow) {
|
||||
const overflowExtra = this.overflow[$getExtra]();
|
||||
if (overflowExtra.addTrailer) {
|
||||
overflowExtra.addTrailer = false;
|
||||
handleOverflow(this, overflowExtra.trailer, availableSpace);
|
||||
}
|
||||
}
|
||||
|
||||
let marginH = 0;
|
||||
let marginV = 0;
|
||||
if (this.margin) {
|
||||
|
@ -5095,24 +5112,13 @@ class Template extends XFAObject {
|
|||
const node = this[$extra].overflowNode;
|
||||
this[$extra].overflowNode = null;
|
||||
|
||||
const overflowExtra = node[$getExtra]();
|
||||
const target = overflowExtra.target;
|
||||
overflowExtra.addLeader = overflowExtra.leader !== null;
|
||||
overflowExtra.addTrailer = overflowExtra.trailer !== null;
|
||||
|
||||
flush(i);
|
||||
|
||||
if (node.leader) {
|
||||
leader = this[$searchNode](node.leader, node[$getParent]());
|
||||
leader = leader ? leader[0] : null;
|
||||
}
|
||||
|
||||
if (node.trailer) {
|
||||
trailer = this[$searchNode](node.trailer, node[$getParent]());
|
||||
trailer = trailer ? trailer[0] : null;
|
||||
}
|
||||
|
||||
let target = null;
|
||||
if (node.target) {
|
||||
target = this[$searchNode](node.target, node[$getParent]());
|
||||
target = target ? target[0] : target;
|
||||
}
|
||||
|
||||
i = Infinity;
|
||||
if (target instanceof PageArea) {
|
||||
// We must stop the contentAreas filling and go to the next page.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue