Merge pull request #14936 from calixteman/input_font_size
Set the text fields font size based on their height
This commit is contained in:
commit
9bdf27e8e0
@ -24,6 +24,7 @@ import {
|
|||||||
escapeString,
|
escapeString,
|
||||||
getModificationDate,
|
getModificationDate,
|
||||||
isAscii,
|
isAscii,
|
||||||
|
LINE_FACTOR,
|
||||||
OPS,
|
OPS,
|
||||||
RenderingIntentFlag,
|
RenderingIntentFlag,
|
||||||
shadow,
|
shadow,
|
||||||
@ -55,11 +56,6 @@ import { StringStream } from "./stream.js";
|
|||||||
import { writeDict } from "./writer.js";
|
import { writeDict } from "./writer.js";
|
||||||
import { XFAFactory } from "./xfa/factory.js";
|
import { XFAFactory } from "./xfa/factory.js";
|
||||||
|
|
||||||
// Represent the percentage of the height of a single-line field over
|
|
||||||
// the font size.
|
|
||||||
// Acrobat seems to use this value.
|
|
||||||
const LINE_FACTOR = 1.35;
|
|
||||||
|
|
||||||
class AnnotationFactory {
|
class AnnotationFactory {
|
||||||
/**
|
/**
|
||||||
* Create an `Annotation` object of the correct type for the given reference
|
* Create an `Annotation` object of the correct type for the given reference
|
||||||
@ -1921,6 +1917,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||||||
!this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
|
!this.hasFieldFlag(AnnotationFieldFlag.PASSWORD) &&
|
||||||
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
|
!this.hasFieldFlag(AnnotationFieldFlag.FILESELECT) &&
|
||||||
this.data.maxLen !== null;
|
this.data.maxLen !== null;
|
||||||
|
this.data.doNotScroll = this.hasFieldFlag(AnnotationFieldFlag.DONOTSCROLL);
|
||||||
}
|
}
|
||||||
|
|
||||||
_getCombAppearance(defaultAppearance, font, text, width, hPadding, vPadding) {
|
_getCombAppearance(defaultAppearance, font, text, width, hPadding, vPadding) {
|
||||||
@ -2788,6 +2785,9 @@ class LinkAnnotation extends Annotation {
|
|||||||
this.data.quadPoints = quadPoints;
|
this.data.quadPoints = quadPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The color entry for a link annotation is the color of the border.
|
||||||
|
this.data.borderColor = this.data.borderColor || this.data.color;
|
||||||
|
|
||||||
Catalog.parseDestDictionary({
|
Catalog.parseDestDictionary({
|
||||||
destDict: params.dict,
|
destDict: params.dict,
|
||||||
resultObj: this.data,
|
resultObj: this.data,
|
||||||
|
@ -22,6 +22,7 @@ import {
|
|||||||
AnnotationBorderStyleType,
|
AnnotationBorderStyleType,
|
||||||
AnnotationType,
|
AnnotationType,
|
||||||
assert,
|
assert,
|
||||||
|
LINE_FACTOR,
|
||||||
shadow,
|
shadow,
|
||||||
unreachable,
|
unreachable,
|
||||||
Util,
|
Util,
|
||||||
@ -37,6 +38,7 @@ import { ColorConverters } from "../shared/scripting_utils.js";
|
|||||||
import { XfaLayer } from "./xfa_layer.js";
|
import { XfaLayer } from "./xfa_layer.js";
|
||||||
|
|
||||||
const DEFAULT_TAB_INDEX = 1000;
|
const DEFAULT_TAB_INDEX = 1000;
|
||||||
|
const DEFAULT_FONT_SIZE = 9;
|
||||||
const GetElementsByNameSet = new WeakSet();
|
const GetElementsByNameSet = new WeakSet();
|
||||||
|
|
||||||
function getRectDims(rect) {
|
function getRectDims(rect) {
|
||||||
@ -271,12 +273,12 @@ class AnnotationElement {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const borderColor = data.borderColor || data.color || null;
|
const borderColor = data.borderColor || null;
|
||||||
if (borderColor) {
|
if (borderColor) {
|
||||||
container.style.borderColor = Util.makeHexColor(
|
container.style.borderColor = Util.makeHexColor(
|
||||||
data.color[0] | 0,
|
borderColor[0] | 0,
|
||||||
data.color[1] | 0,
|
borderColor[1] | 0,
|
||||||
data.color[2] | 0
|
borderColor[2] | 0
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Transparent (invisible) border, so do not draw it at all.
|
// Transparent (invisible) border, so do not draw it at all.
|
||||||
@ -897,6 +899,53 @@ class WidgetAnnotationElement extends AnnotationElement {
|
|||||||
? "transparent"
|
? "transparent"
|
||||||
: Util.makeHexColor(color[0], color[1], color[2]);
|
: Util.makeHexColor(color[0], color[1], color[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply text styles to the text in the element.
|
||||||
|
*
|
||||||
|
* @private
|
||||||
|
* @param {HTMLDivElement} element
|
||||||
|
* @memberof TextWidgetAnnotationElement
|
||||||
|
*/
|
||||||
|
_setTextStyle(element) {
|
||||||
|
const TEXT_ALIGNMENT = ["left", "center", "right"];
|
||||||
|
const { fontColor } = this.data.defaultAppearanceData;
|
||||||
|
const fontSize =
|
||||||
|
this.data.defaultAppearanceData.fontSize || DEFAULT_FONT_SIZE;
|
||||||
|
|
||||||
|
const style = element.style;
|
||||||
|
|
||||||
|
// TODO: If the font-size is zero, calculate it based on the height and
|
||||||
|
// width of the element.
|
||||||
|
// Not setting `style.fontSize` will use the default font-size for now.
|
||||||
|
|
||||||
|
// We don't use the font, as specified in the PDF document, for the <input>
|
||||||
|
// element. Hence using the original `fontSize` could look bad, which is why
|
||||||
|
// it's instead based on the field height.
|
||||||
|
// If the height is "big" then it could lead to a too big font size
|
||||||
|
// so in this case use the one we've in the pdf (hence the min).
|
||||||
|
if (this.data.multiLine) {
|
||||||
|
const height = Math.abs(this.data.rect[3] - this.data.rect[1]);
|
||||||
|
const numberOfLines = Math.round(height / (LINE_FACTOR * fontSize)) || 1;
|
||||||
|
const lineHeight = height / numberOfLines;
|
||||||
|
style.fontSize = `${Math.min(
|
||||||
|
fontSize,
|
||||||
|
Math.round(lineHeight / LINE_FACTOR)
|
||||||
|
)}px`;
|
||||||
|
} else {
|
||||||
|
const height = Math.abs(this.data.rect[3] - this.data.rect[1]);
|
||||||
|
style.fontSize = `${Math.min(
|
||||||
|
fontSize,
|
||||||
|
Math.round(height / LINE_FACTOR)
|
||||||
|
)}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);
|
||||||
|
|
||||||
|
if (this.data.textAlignment !== null) {
|
||||||
|
style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||||
@ -944,10 +993,16 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
if (this.data.multiLine) {
|
if (this.data.multiLine) {
|
||||||
element = document.createElement("textarea");
|
element = document.createElement("textarea");
|
||||||
element.textContent = textContent;
|
element.textContent = textContent;
|
||||||
|
if (this.data.doNotScroll) {
|
||||||
|
element.style.overflowY = "hidden";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
element = document.createElement("input");
|
element = document.createElement("input");
|
||||||
element.type = "text";
|
element.type = "text";
|
||||||
element.setAttribute("value", textContent);
|
element.setAttribute("value", textContent);
|
||||||
|
if (this.data.doNotScroll) {
|
||||||
|
element.style.overflowX = "hidden";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
GetElementsByNameSet.add(element);
|
GetElementsByNameSet.add(element);
|
||||||
element.disabled = this.data.readOnly;
|
element.disabled = this.data.readOnly;
|
||||||
@ -1177,32 +1232,6 @@ class TextWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
this.container.appendChild(element);
|
this.container.appendChild(element);
|
||||||
return this.container;
|
return this.container;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Apply text styles to the text in the element.
|
|
||||||
*
|
|
||||||
* @private
|
|
||||||
* @param {HTMLDivElement} element
|
|
||||||
* @memberof TextWidgetAnnotationElement
|
|
||||||
*/
|
|
||||||
_setTextStyle(element) {
|
|
||||||
const TEXT_ALIGNMENT = ["left", "center", "right"];
|
|
||||||
const { fontSize, fontColor } = this.data.defaultAppearanceData;
|
|
||||||
const style = element.style;
|
|
||||||
|
|
||||||
// TODO: If the font-size is zero, calculate it based on the height and
|
|
||||||
// width of the element.
|
|
||||||
// Not setting `style.fontSize` will use the default font-size for now.
|
|
||||||
if (fontSize) {
|
|
||||||
style.fontSize = `${fontSize}px`;
|
|
||||||
}
|
|
||||||
|
|
||||||
style.color = Util.makeHexColor(fontColor[0], fontColor[1], fontColor[2]);
|
|
||||||
|
|
||||||
if (this.data.textAlignment !== null) {
|
|
||||||
style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
class CheckboxWidgetAnnotationElement extends WidgetAnnotationElement {
|
||||||
@ -1413,10 +1442,8 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
value: this.data.fieldValue,
|
value: this.data.fieldValue,
|
||||||
});
|
});
|
||||||
|
|
||||||
let { fontSize } = this.data.defaultAppearanceData;
|
const fontSize =
|
||||||
if (!fontSize) {
|
this.data.defaultAppearanceData.fontSize || DEFAULT_FONT_SIZE;
|
||||||
fontSize = 9;
|
|
||||||
}
|
|
||||||
const fontSizeStyle = `calc(${fontSize}px * var(--zoom-factor))`;
|
const fontSizeStyle = `calc(${fontSize}px * var(--zoom-factor))`;
|
||||||
|
|
||||||
const selectElement = document.createElement("select");
|
const selectElement = document.createElement("select");
|
||||||
@ -1426,8 +1453,6 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
selectElement.setAttribute("id", id);
|
selectElement.setAttribute("id", id);
|
||||||
selectElement.tabIndex = DEFAULT_TAB_INDEX;
|
selectElement.tabIndex = DEFAULT_TAB_INDEX;
|
||||||
|
|
||||||
selectElement.style.fontSize = `${fontSize}px`;
|
|
||||||
|
|
||||||
if (!this.data.combo) {
|
if (!this.data.combo) {
|
||||||
// List boxes have a size and (optionally) multiple selection.
|
// List boxes have a size and (optionally) multiple selection.
|
||||||
selectElement.size = this.data.options.length;
|
selectElement.size = this.data.options.length;
|
||||||
@ -1606,6 +1631,12 @@ class ChoiceWidgetAnnotationElement extends WidgetAnnotationElement {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.data.combo) {
|
||||||
|
this._setTextStyle(selectElement);
|
||||||
|
} else {
|
||||||
|
// Just use the default font size...
|
||||||
|
// it's a bit hard to guess what is a good size.
|
||||||
|
}
|
||||||
this._setBackgroundColor(selectElement);
|
this._setBackgroundColor(selectElement);
|
||||||
this._setDefaultPropertiesFromJS(selectElement);
|
this._setDefaultPropertiesFromJS(selectElement);
|
||||||
|
|
||||||
|
@ -18,6 +18,10 @@ import "./compatibility.js";
|
|||||||
const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
const IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
|
||||||
const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
|
const FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
|
||||||
|
|
||||||
|
// Represent the percentage of the height of a single-line field over
|
||||||
|
// the font size. Acrobat seems to use this value.
|
||||||
|
const LINE_FACTOR = 1.35;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refer to the `WorkerTransport.getRenderingIntent`-method in the API, to see
|
* Refer to the `WorkerTransport.getRenderingIntent`-method in the API, to see
|
||||||
* how these flags are being used:
|
* how these flags are being used:
|
||||||
@ -1162,6 +1166,7 @@ export {
|
|||||||
isArrayBuffer,
|
isArrayBuffer,
|
||||||
isArrayEqual,
|
isArrayEqual,
|
||||||
isAscii,
|
isAscii,
|
||||||
|
LINE_FACTOR,
|
||||||
MissingPDFException,
|
MissingPDFException,
|
||||||
objectFromMap,
|
objectFromMap,
|
||||||
objectSize,
|
objectSize,
|
||||||
|
@ -751,7 +751,9 @@ class Driver {
|
|||||||
transform,
|
transform,
|
||||||
};
|
};
|
||||||
if (renderForms) {
|
if (renderForms) {
|
||||||
renderContext.annotationMode = AnnotationMode.ENABLE_FORMS;
|
renderContext.annotationMode = task.annotationStorage
|
||||||
|
? AnnotationMode.ENABLE_STORAGE
|
||||||
|
: AnnotationMode.ENABLE_FORMS;
|
||||||
} else if (renderPrint) {
|
} else if (renderPrint) {
|
||||||
if (task.annotationStorage) {
|
if (task.annotationStorage) {
|
||||||
renderContext.annotationMode = AnnotationMode.ENABLE_STORAGE;
|
renderContext.annotationMode = AnnotationMode.ENABLE_STORAGE;
|
||||||
|
2
test/pdfs/issue14301.pdf.link
Normal file
2
test/pdfs/issue14301.pdf.link
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
https://github.com/mozilla/pdf.js/files/7594316/formulairecerfa90nov00-1.pdf
|
||||||
|
|
@ -6507,5 +6507,26 @@
|
|||||||
"rounds": 1,
|
"rounds": 1,
|
||||||
"link": true,
|
"link": true,
|
||||||
"type": "other"
|
"type": "other"
|
||||||
|
},
|
||||||
|
{ "id": "issue14301",
|
||||||
|
"file": "pdfs/issue14301.pdf",
|
||||||
|
"md5": "9973936dcf8dd41daa62c04a4eb621f0",
|
||||||
|
"rounds": 1,
|
||||||
|
"link": true,
|
||||||
|
"firstPage": 2,
|
||||||
|
"lastPage": 2,
|
||||||
|
"type": "eq",
|
||||||
|
"forms": true,
|
||||||
|
"annotationStorage": {
|
||||||
|
"1832R": {
|
||||||
|
"value": "3"
|
||||||
|
},
|
||||||
|
"1827R": {
|
||||||
|
"value": "2"
|
||||||
|
},
|
||||||
|
"1808R": {
|
||||||
|
"value": "1"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
@ -59,10 +59,9 @@
|
|||||||
background-image: var(--annotation-unfocused-field-background);
|
background-image: var(--annotation-unfocused-field-background);
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
font-size: 9px;
|
font: 9px sans-serif;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 3px;
|
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
@ -76,8 +75,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.annotationLayer .textWidgetAnnotation textarea {
|
.annotationLayer .textWidgetAnnotation textarea {
|
||||||
font: message-box;
|
|
||||||
font-size: 9px;
|
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +164,6 @@
|
|||||||
.annotationLayer .buttonWidgetAnnotation.checkBox input,
|
.annotationLayer .buttonWidgetAnnotation.checkBox input,
|
||||||
.annotationLayer .buttonWidgetAnnotation.radioButton input {
|
.annotationLayer .buttonWidgetAnnotation.radioButton input {
|
||||||
appearance: none;
|
appearance: none;
|
||||||
padding: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.annotationLayer .popupWrapper {
|
.annotationLayer .popupWrapper {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user