mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-22 16:18:08 +02:00
Display background when printing or saving a text widget (issue #14928)
This commit is contained in:
parent
60e9065bf6
commit
60498c67e4
8 changed files with 150 additions and 90 deletions
|
@ -33,9 +33,14 @@ import {
|
|||
Util,
|
||||
warn,
|
||||
} from "../shared/util.js";
|
||||
import { collectActions, getInheritableProperty } from "./core_utils.js";
|
||||
import {
|
||||
collectActions,
|
||||
getInheritableProperty,
|
||||
numberToString,
|
||||
} from "./core_utils.js";
|
||||
import {
|
||||
createDefaultAppearance,
|
||||
getPdfColor,
|
||||
parseDefaultAppearance,
|
||||
} from "./default_appearance.js";
|
||||
import { Dict, isName, Name, Ref, RefSet } from "./primitives.js";
|
||||
|
@ -663,6 +668,27 @@ class Annotation {
|
|||
}
|
||||
}
|
||||
|
||||
getBorderAndBackgroundAppearances() {
|
||||
if (!this.backgroundColor && !this.borderColor) {
|
||||
return "";
|
||||
}
|
||||
const width = this.data.rect[2] - this.data.rect[0];
|
||||
const height = this.data.rect[3] - this.data.rect[1];
|
||||
const rect = `0 0 ${width} ${height} re`;
|
||||
|
||||
let str = "";
|
||||
if (this.backgroundColor) {
|
||||
str = `${getPdfColor(this.backgroundColor)} ${rect} f `;
|
||||
}
|
||||
|
||||
if (this.borderColor) {
|
||||
const borderWidth = this.borderStyle.width || 1;
|
||||
str += `${borderWidth} w ${getPdfColor(this.borderColor)} ${rect} S `;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the border style (as AnnotationBorderStyle object).
|
||||
*
|
||||
|
@ -1609,7 +1635,13 @@ class WidgetAnnotation extends Annotation {
|
|||
descent = 0;
|
||||
}
|
||||
|
||||
const vPadding = defaultPadding + Math.abs(descent) * fontSize;
|
||||
// Take into account the space we have to compute the default vertical
|
||||
// padding.
|
||||
const defaultVPadding = Math.min(
|
||||
Math.floor((totalHeight - fontSize) / 2),
|
||||
defaultPadding
|
||||
);
|
||||
const vPadding = defaultVPadding + Math.abs(descent) * fontSize;
|
||||
const alignment = this.data.textAlignment;
|
||||
|
||||
if (this.data.multiLine) {
|
||||
|
@ -1640,10 +1672,13 @@ class WidgetAnnotation extends Annotation {
|
|||
);
|
||||
}
|
||||
|
||||
// Empty or it has a trailing whitespace.
|
||||
const colors = this.getBorderAndBackgroundAppearances();
|
||||
|
||||
if (alignment === 0 || alignment > 2) {
|
||||
// Left alignment: nothing to do
|
||||
return (
|
||||
"/Tx BMC q BT " +
|
||||
`/Tx BMC q ${colors}BT ` +
|
||||
defaultAppearance +
|
||||
` 1 0 0 1 ${hPadding} ${vPadding} Tm (${escapeString(
|
||||
encodedString
|
||||
|
@ -1662,7 +1697,7 @@ class WidgetAnnotation extends Annotation {
|
|||
vPadding
|
||||
);
|
||||
return (
|
||||
"/Tx BMC q BT " +
|
||||
`/Tx BMC q ${colors}BT ` +
|
||||
defaultAppearance +
|
||||
` 1 0 0 1 0 0 Tm ${renderedText}` +
|
||||
" ET Q EMC"
|
||||
|
@ -1790,8 +1825,8 @@ class WidgetAnnotation extends Annotation {
|
|||
} else {
|
||||
shift = hPadding;
|
||||
}
|
||||
shift = shift.toFixed(2);
|
||||
vPadding = vPadding.toFixed(2);
|
||||
shift = numberToString(shift);
|
||||
vPadding = numberToString(vPadding);
|
||||
|
||||
return `${shift} ${vPadding} Td (${escapeString(text)}) Tj`;
|
||||
}
|
||||
|
@ -1889,16 +1924,18 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||
}
|
||||
|
||||
_getCombAppearance(defaultAppearance, font, text, width, hPadding, vPadding) {
|
||||
const combWidth = (width / this.data.maxLen).toFixed(2);
|
||||
const combWidth = numberToString(width / this.data.maxLen);
|
||||
const buf = [];
|
||||
const positions = font.getCharPositions(text);
|
||||
for (const [start, end] of positions) {
|
||||
buf.push(`(${escapeString(text.substring(start, end))}) Tj`);
|
||||
}
|
||||
|
||||
// Empty or it has a trailing whitespace.
|
||||
const colors = this.getBorderAndBackgroundAppearances();
|
||||
const renderedComb = buf.join(` ${combWidth} 0 Td `);
|
||||
return (
|
||||
"/Tx BMC q BT " +
|
||||
`/Tx BMC q ${colors}BT ` +
|
||||
defaultAppearance +
|
||||
` 1 0 0 1 ${hPadding} ${vPadding} Tm ${renderedComb}` +
|
||||
" ET Q EMC"
|
||||
|
@ -1938,8 +1975,12 @@ class TextWidgetAnnotation extends WidgetAnnotation {
|
|||
}
|
||||
|
||||
const renderedText = buf.join("\n");
|
||||
|
||||
// Empty or it has a trailing whitespace.
|
||||
const colors = this.getBorderAndBackgroundAppearances();
|
||||
|
||||
return (
|
||||
"/Tx BMC q BT " +
|
||||
`/Tx BMC q ${colors}BT ` +
|
||||
defaultAppearance +
|
||||
` 1 0 0 1 0 ${height} Tm ${renderedText}` +
|
||||
" ET Q EMC"
|
||||
|
@ -2295,8 +2336,8 @@ class ButtonWidgetAnnotation extends WidgetAnnotation {
|
|||
}
|
||||
|
||||
// Values to center the glyph in the bbox.
|
||||
const xShift = (width - metrics.width) / 2;
|
||||
const yShift = (height - metrics.height) / 2;
|
||||
const xShift = numberToString((width - metrics.width) / 2);
|
||||
const yShift = numberToString((height - metrics.height) / 2);
|
||||
|
||||
const appearance = `q BT /PdfJsZaDb ${fontSize} Tf 0 g ${xShift} ${yShift} Td (${char}) Tj ET Q`;
|
||||
|
||||
|
|
|
@ -531,6 +531,23 @@ function recoverJsURL(str) {
|
|||
return null;
|
||||
}
|
||||
|
||||
function numberToString(value) {
|
||||
if (Number.isInteger(value)) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
const roundedValue = Math.round(value * 100);
|
||||
if (roundedValue % 100 === 0) {
|
||||
return (roundedValue / 100).toString();
|
||||
}
|
||||
|
||||
if (roundedValue % 10 === 0) {
|
||||
return value.toFixed(1);
|
||||
}
|
||||
|
||||
return value.toFixed(2);
|
||||
}
|
||||
|
||||
export {
|
||||
collectActions,
|
||||
DocStats,
|
||||
|
@ -542,6 +559,7 @@ export {
|
|||
isWhiteSpace,
|
||||
log2,
|
||||
MissingDataException,
|
||||
numberToString,
|
||||
ParserEOFException,
|
||||
parseXFAPath,
|
||||
readInt8,
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { escapePDFName, numberToString } from "./core_utils.js";
|
||||
import { OPS, warn } from "../shared/util.js";
|
||||
import { ColorSpace } from "./colorspace.js";
|
||||
import { escapePDFName } from "./core_utils.js";
|
||||
import { EvaluatorPreprocessor } from "./evaluator.js";
|
||||
import { Name } from "./primitives.js";
|
||||
import { StringStream } from "./stream.js";
|
||||
|
@ -82,18 +82,21 @@ function parseDefaultAppearance(str) {
|
|||
return new DefaultAppearanceEvaluator(str).parse();
|
||||
}
|
||||
|
||||
// Create default appearance string from some information.
|
||||
function createDefaultAppearance({ fontSize, fontName, fontColor }) {
|
||||
let colorCmd;
|
||||
if (fontColor.every(c => c === 0)) {
|
||||
colorCmd = "0 g";
|
||||
} else {
|
||||
colorCmd =
|
||||
Array.from(fontColor)
|
||||
.map(c => (c / 255).toFixed(2))
|
||||
.join(" ") + " rg";
|
||||
function getPdfColor(color) {
|
||||
if (color[0] === color[1] && color[1] === color[2]) {
|
||||
const gray = color[0] / 255;
|
||||
return `${numberToString(gray)} g`;
|
||||
}
|
||||
return `/${escapePDFName(fontName)} ${fontSize} Tf ${colorCmd}`;
|
||||
return (
|
||||
Array.from(color)
|
||||
.map(c => numberToString(c / 255))
|
||||
.join(" ") + " rg"
|
||||
);
|
||||
}
|
||||
|
||||
export { createDefaultAppearance, parseDefaultAppearance };
|
||||
// Create default appearance string from some information.
|
||||
function createDefaultAppearance({ fontSize, fontName, fontColor }) {
|
||||
return `/${escapePDFName(fontName)} ${fontSize} Tf ${getPdfColor(fontColor)}`;
|
||||
}
|
||||
|
||||
export { createDefaultAppearance, getPdfColor, parseDefaultAppearance };
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
import { bytesToString, escapeString, warn } from "../shared/util.js";
|
||||
import { Dict, Name, Ref } from "./primitives.js";
|
||||
import { escapePDFName, parseXFAPath } from "./core_utils.js";
|
||||
import { escapePDFName, numberToString, parseXFAPath } from "./core_utils.js";
|
||||
import { SimpleDOMNode, SimpleXMLParser } from "./xml_parser.js";
|
||||
import { BaseStream } from "./base_stream.js";
|
||||
import { calculateMD5 } from "./crypto.js";
|
||||
|
@ -53,23 +53,6 @@ function writeArray(array, buffer, transform) {
|
|||
buffer.push("]");
|
||||
}
|
||||
|
||||
function numberToString(value) {
|
||||
if (Number.isInteger(value)) {
|
||||
return value.toString();
|
||||
}
|
||||
|
||||
const roundedValue = Math.round(value * 100);
|
||||
if (roundedValue % 100 === 0) {
|
||||
return (roundedValue / 100).toString();
|
||||
}
|
||||
|
||||
if (roundedValue % 10 === 0) {
|
||||
return value.toFixed(1);
|
||||
}
|
||||
|
||||
return value.toFixed(2);
|
||||
}
|
||||
|
||||
function writeValue(value, buffer, transform) {
|
||||
if (value instanceof Name) {
|
||||
buffer.push(`/${escapePDFName(value.name)}`);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue