mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-10-04 06:18:00 +02:00
Compare commits
8
Commits
735ea6285c
...
c33c32aed4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c33c32aed4 | ||
|
|
d9080794fa | ||
|
|
f786355550 | ||
|
|
e3e606de23 | ||
|
|
62de7c55e1 | ||
|
|
29a06285dc | ||
|
|
a02decd96c | ||
|
|
40cc2082df |
Vendored
+2
-2
File diff suppressed because one or more lines are too long
Vendored
BIN
Binary file not shown.
+10
-10
File diff suppressed because one or more lines are too long
@@ -3004,10 +3004,7 @@ class PartialEvaluator {
|
||||
}
|
||||
let charSpacing = baseCharSpacing + (i + 1 === ii ? extraSpacing : 0);
|
||||
|
||||
let glyphWidth = glyph.width;
|
||||
if (font.vertical) {
|
||||
glyphWidth = glyph.vmetric ? glyph.vmetric[0] : -glyphWidth;
|
||||
}
|
||||
const glyphWidth = font.vertical ? glyph.vmetric[0] : glyph.width;
|
||||
let scaledDim = glyphWidth * scale;
|
||||
|
||||
if (originalCharCode === 0x20) {
|
||||
|
||||
+7
-2
@@ -87,7 +87,6 @@ const EXPORT_DATA_PROPERTIES = [
|
||||
// "charProcOperatorList" is handled separately, since it's not compiled.
|
||||
"cssFontInfo",
|
||||
"data",
|
||||
"defaultVMetrics",
|
||||
"descent",
|
||||
"disableFontFace",
|
||||
"fallbackName",
|
||||
@@ -108,6 +107,7 @@ const EXPORT_DATA_PROPERTIES = [
|
||||
const EXPORT_DATA_EXTRA_PROPERTIES = [
|
||||
"composite",
|
||||
"defaultEncoding",
|
||||
"defaultVMetrics",
|
||||
"defaultWidth",
|
||||
"differences",
|
||||
"isMonospace",
|
||||
@@ -3561,7 +3561,12 @@ class Font {
|
||||
if (typeof width !== "number") {
|
||||
width = this.defaultWidth;
|
||||
}
|
||||
const vmetric = this.vmetrics?.[widthCode] || this.defaultVMetrics;
|
||||
let vmetric = this.vmetrics?.[widthCode];
|
||||
if (!vmetric && this.defaultVMetrics) {
|
||||
// Without a W2 entry, vx is half the glyph width (PDF 32000-1, 9.7.4.3).
|
||||
const [w1y, , vy] = this.defaultVMetrics;
|
||||
vmetric = [w1y, width * 0.5, vy];
|
||||
}
|
||||
|
||||
let unicode = this.toUnicode.get(charcode) || charcode;
|
||||
if (typeof unicode === "number") {
|
||||
|
||||
@@ -193,20 +193,9 @@ function compileFontInfo(font) {
|
||||
/* writerName = */ "setFloat64",
|
||||
/* increment = */ 8
|
||||
);
|
||||
assert(
|
||||
offset === FONT_INFO.OFFSET_DEFAULT_VMETRICS,
|
||||
"compileFontInfo: FontMatrix properties offset mismatch"
|
||||
);
|
||||
|
||||
writeArray(
|
||||
/* arr = */ font.defaultVMetrics,
|
||||
/* arrLen = */ 3,
|
||||
/* writerName = */ "setInt16",
|
||||
/* increment = */ 2
|
||||
);
|
||||
assert(
|
||||
offset === FONT_INFO.OFFSET_STRINGS,
|
||||
"compileFontInfo: DefaultVMetrics properties offset mismatch"
|
||||
"compileFontInfo: FontMatrix properties offset mismatch"
|
||||
);
|
||||
|
||||
view.setUint32(offset, stringsLength);
|
||||
|
||||
@@ -2772,7 +2772,6 @@ class CanvasGraphics {
|
||||
const glyphsLength = glyphs.length;
|
||||
const vertical = font.vertical;
|
||||
const spacingDir = vertical ? 1 : -1;
|
||||
const defaultVMetrics = font.defaultVMetrics;
|
||||
const widthAdvanceScale = fontSize * current.fontMatrix[0];
|
||||
|
||||
const simpleFillText =
|
||||
@@ -2896,12 +2895,11 @@ class CanvasGraphics {
|
||||
let scaledX, scaledY;
|
||||
let width = glyph.width;
|
||||
if (vertical) {
|
||||
const vmetric = glyph.vmetric || defaultVMetrics;
|
||||
const vx =
|
||||
-(glyph.vmetric ? vmetric[1] : width * 0.5) * widthAdvanceScale;
|
||||
const vmetric = glyph.vmetric;
|
||||
const vx = -vmetric[1] * widthAdvanceScale;
|
||||
const vy = vmetric[2] * widthAdvanceScale;
|
||||
|
||||
width = vmetric ? -vmetric[0] : width;
|
||||
width = -vmetric[0];
|
||||
scaledX = vx / fontSizeScale;
|
||||
scaledY = (x + vy) / fontSizeScale;
|
||||
} else {
|
||||
|
||||
@@ -589,10 +589,6 @@ class FontFaceObject {
|
||||
get systemFontInfo() {
|
||||
return this.#fontData.systemFontInfo;
|
||||
}
|
||||
|
||||
get defaultVMetrics() {
|
||||
return this.#fontData.defaultVMetrics;
|
||||
}
|
||||
}
|
||||
|
||||
export { FontFaceObject, FontLoader };
|
||||
|
||||
@@ -206,15 +206,6 @@ class FontInfo {
|
||||
);
|
||||
}
|
||||
|
||||
get defaultVMetrics() {
|
||||
return this.#readArray(
|
||||
/* offset = */ FONT_INFO.OFFSET_DEFAULT_VMETRICS,
|
||||
/* arrLen = */ 3,
|
||||
/* lookup = */ "getInt16",
|
||||
/* increment = */ 2
|
||||
);
|
||||
}
|
||||
|
||||
#readString(index) {
|
||||
assert(index < FONT_INFO.strings.length, "Invalid string index");
|
||||
return readString(
|
||||
|
||||
@@ -1236,7 +1236,7 @@ class Doc extends PDFObject {
|
||||
let mustCalculate = false;
|
||||
let fieldsToReset;
|
||||
if (aFields) {
|
||||
fieldsToReset = [];
|
||||
fieldsToReset = new Set();
|
||||
for (const fieldName of aFields) {
|
||||
if (!fieldName) {
|
||||
continue;
|
||||
@@ -1250,12 +1250,23 @@ class Doc extends PDFObject {
|
||||
if (!field) {
|
||||
continue;
|
||||
}
|
||||
fieldsToReset.push(field);
|
||||
fieldsToReset.add(field);
|
||||
mustCalculate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!fieldsToReset) {
|
||||
if (fieldsToReset) {
|
||||
// A non-terminal field stands for all its descendants, hence add the
|
||||
// kids (the Set iterator also visits the newly added fields).
|
||||
for (const { obj } of fieldsToReset) {
|
||||
for (const id of obj._kidIds || []) {
|
||||
const kid = obj._appObjects[id];
|
||||
if (kid) {
|
||||
fieldsToReset.add(kid);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fieldsToReset = this._fields.values();
|
||||
mustCalculate = this._fields.size !== 0;
|
||||
}
|
||||
|
||||
@@ -47,9 +47,7 @@ class FONT_INFO {
|
||||
|
||||
static OFFSET_FONT_MATRIX = this.OFFSET_BBOX + 1 + 2 * 4;
|
||||
|
||||
static OFFSET_DEFAULT_VMETRICS = this.OFFSET_FONT_MATRIX + 1 + 8 * 6;
|
||||
|
||||
static OFFSET_STRINGS = this.OFFSET_DEFAULT_VMETRICS + 1 + 2 * 3;
|
||||
static OFFSET_STRINGS = this.OFFSET_FONT_MATRIX + 1 + 8 * 6;
|
||||
}
|
||||
|
||||
class PATTERN_INFO {
|
||||
|
||||
@@ -14,9 +14,58 @@
|
||||
*/
|
||||
|
||||
import { Font } from "../../src/core/fonts.js";
|
||||
import { IdentityCMap } from "../../src/core/cmap.js";
|
||||
import { IdentityToUnicodeMap } from "../../src/core/to_unicode_map.js";
|
||||
|
||||
describe("Font", () => {
|
||||
describe("charsToGlyphs", () => {
|
||||
// Match the sparse metric arrays from PartialEvaluator.extractWidths.
|
||||
function createFont(vertical) {
|
||||
return new Font(
|
||||
"TestFont",
|
||||
null,
|
||||
{
|
||||
type: "CIDFontType2",
|
||||
composite: true,
|
||||
vertical,
|
||||
cMap: new IdentityCMap(vertical, 2),
|
||||
cidEncoding: vertical ? "Identity-V" : "Identity-H",
|
||||
toUnicode: new IdentityToUnicodeMap(65, 68),
|
||||
differences: new Map(),
|
||||
defaultEncoding: [],
|
||||
widths: Object.assign([], { 65: 600, 66: 0, 68: 800 }),
|
||||
defaultWidth: 1000,
|
||||
vmetrics: vertical ? Object.assign([], { 68: [-800, 175, 700] }) : [],
|
||||
defaultVMetrics: vertical ? [-1200, 500, 900] : undefined,
|
||||
},
|
||||
{}
|
||||
);
|
||||
}
|
||||
|
||||
it("should use half the glyph width for the default vertical origin", () => {
|
||||
const font = createFont(/* vertical = */ true);
|
||||
const glyphs = font.charsToGlyphs("\x00A\x00B\x00C\x00D");
|
||||
|
||||
// Cover per-glyph widths, zero width, DW fallback, and explicit W2.
|
||||
expect(glyphs.map(glyph => glyph.vmetric)).toEqual([
|
||||
[-1200, 300, 900],
|
||||
[-1200, 0, 900],
|
||||
[-1200, 500, 900],
|
||||
[-800, 175, 700],
|
||||
]);
|
||||
expect(font.defaultVMetrics).toEqual([-1200, 500, 900]);
|
||||
});
|
||||
|
||||
it("should not set a vertical metric for horizontal fonts", () => {
|
||||
const font = createFont(/* vertical = */ false);
|
||||
const glyphs = font.charsToGlyphs("\x00A\x00B\x00C\x00D");
|
||||
|
||||
for (const glyph of glyphs) {
|
||||
expect(glyph.vmetric).toBeUndefined();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe("encodeString", () => {
|
||||
// `encodeString` only reads `this.toUnicode` and `this.cMap`, so a
|
||||
// full `Font` (which needs a complete properties/font-file setup) isn't
|
||||
|
||||
@@ -68,7 +68,6 @@ describe("obj_bin_transform", function () {
|
||||
descent: -1,
|
||||
bbox: [1, 1, 1, 1],
|
||||
fontMatrix: [1, 1, 1, 1, 1, 1],
|
||||
defaultVMetrics: [1, 1, 1],
|
||||
fallbackName: "string",
|
||||
loadedName: "string",
|
||||
mimetype: "string",
|
||||
@@ -125,7 +124,7 @@ describe("obj_bin_transform", function () {
|
||||
|
||||
describe("FontInfo", function () {
|
||||
it("must roundtrip correctly for FontInfo", function () {
|
||||
let sizeEstimate = 84; // fixed offset until the strings
|
||||
let sizeEstimate = 77; // fixed offset until the strings
|
||||
const { encoder } = InfoUtils;
|
||||
sizeEstimate += 4 + 4 * (4 + encoder.encode("string").length);
|
||||
sizeEstimate += 4 + 4; // cssFontInfo and systemFontInfo
|
||||
@@ -147,7 +146,6 @@ describe("obj_bin_transform", function () {
|
||||
expect(deserialized.descent).toEqual(-1);
|
||||
expect(deserialized.bbox).toEqual([1, 1, 1, 1]);
|
||||
expect(deserialized.fontMatrix).toEqual([1, 1, 1, 1, 1, 1]);
|
||||
expect(deserialized.defaultVMetrics).toEqual([1, 1, 1]);
|
||||
expect(deserialized.fallbackName).toEqual("string");
|
||||
expect(deserialized.loadedName).toEqual("string");
|
||||
expect(deserialized.mimetype).toEqual("string");
|
||||
|
||||
@@ -197,6 +197,55 @@ describe("Scripting", function () {
|
||||
);
|
||||
expect(value).toEqual([4, 5, 6, 7]);
|
||||
});
|
||||
|
||||
it("should reset the descendants of a non-terminal field", async () => {
|
||||
const refIds = [0, 1, 2, 3, 4].map(_ => getId());
|
||||
const text = id => ({
|
||||
id,
|
||||
value: "",
|
||||
defaultValue: "",
|
||||
actions: {},
|
||||
type: "text",
|
||||
});
|
||||
const data = {
|
||||
objects: {
|
||||
A: [{ id: refIds[0], type: "", kidIds: [refIds[1], refIds[2]] }],
|
||||
"A.B": [text(refIds[1])],
|
||||
"A.C": [{ id: refIds[2], type: "", kidIds: [refIds[3]] }],
|
||||
"A.C.D": [text(refIds[3])],
|
||||
E: [text(refIds[4])],
|
||||
},
|
||||
appInfo: { language: "en-US", platform: "Linux x86_64" },
|
||||
calculationOrder: [],
|
||||
dispatchEventName: "_dispatchMe",
|
||||
};
|
||||
sandbox.createSandbox(data);
|
||||
|
||||
await myeval(
|
||||
`(["A.B", "A.C.D", "E"].forEach(n => this.getField(n).value = "hello"), 0)`
|
||||
);
|
||||
for (const id of [refIds[1], refIds[3], refIds[4]]) {
|
||||
send_queue.delete(id);
|
||||
}
|
||||
|
||||
await myeval(`(this.resetForm(["A"]), 0)`);
|
||||
|
||||
for (const id of [refIds[1], refIds[3]]) {
|
||||
expect(send_queue.get(id)).toEqual({
|
||||
id,
|
||||
siblings: null,
|
||||
value: "",
|
||||
formattedValue: null,
|
||||
selRange: [0, 0],
|
||||
});
|
||||
}
|
||||
expect(send_queue.has(refIds[4])).toBeFalse();
|
||||
|
||||
const values = await myeval(
|
||||
`["A.B", "A.C.D", "E"].map(n => this.getField(n).value)`
|
||||
);
|
||||
expect(values).toEqual(["", "", "hello"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Util", function () {
|
||||
|
||||
Reference in New Issue
Block a user