Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 18 additions & 9 deletions src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -2586,6 +2586,21 @@ class WidgetAnnotation extends Annotation {
);
const alignment = this.data.textAlignment;

let { ascent: fontAscent, descent: fontDescent } = font;
if (
isNaN(fontAscent) ||
isNaN(fontDescent) ||
(!fontAscent && !fontDescent)
) {
fontAscent = LINE_FACTOR - LINE_DESCENT_FACTOR;
fontDescent = LINE_DESCENT_FACTOR;
} else {
fontDescent = Math.abs(fontDescent);
}
const vShift =
(totalHeight - (fontAscent + fontDescent) * fontSize) / 2 +
fontDescent * fontSize;

if (this.data.multiLine) {
return this._getMultilineAppearance(
defaultAppearance,
Expand All @@ -2610,14 +2625,14 @@ class WidgetAnnotation extends Annotation {
encodedLines[0],
fontSize,
totalWidth,
totalHeight,
vShift,
alignment,
bidi(lines[0]).dir === "rtl",
annotationStorage
);
}

const bottomPadding = defaultVPadding + descent;
const bottomPadding = vShift;
if (alignment === 0 || alignment > 2) {
// Left alignment: nothing to do
return (
Expand Down Expand Up @@ -2971,7 +2986,7 @@ class TextWidgetAnnotation extends WidgetAnnotation {
text,
fontSize,
width,
height,
vShift,
alignment,
isRTL,
annotationStorage
Expand Down Expand Up @@ -3009,12 +3024,6 @@ class TextWidgetAnnotation extends WidgetAnnotation {
}
const renderedComb = buf.join(" ");

// Vertically center the glyphs within the field: comb fields are mostly
// filled with uppercase letters and/or digits, hence we use the cap height
// (with a fallback on the ascent or the font size) to center them.
const vShift =
(height - (font.capHeight || font.ascent || 1) * fontSize) / 2;

return (
`/Tx BMC q ${colors}BT ` +
defaultAppearance +
Expand Down
4 changes: 2 additions & 2 deletions src/core/decrypt_stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ class DecryptStream extends DecodeStream {

readBlock() {
let chunk = this.#nextChunk ?? this.stream.getBytes(chunkSize);
if (!chunk?.length) {
if (!chunk.length) {
this.eof = true;
return;
}
this.#nextChunk = this.stream.getBytes(chunkSize);
const hasMoreData = this.#nextChunk?.length > 0;
const hasMoreData = this.#nextChunk.length > 0;

const decrypt = this.decrypt;
chunk = decrypt(chunk, !hasMoreData);
Expand Down
7 changes: 4 additions & 3 deletions src/core/obj_bin_transform_core.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ import { assert, FeatureTest } from "../shared/util.js";
import {
CSS_FONT_INFO,
FONT_INFO,
InfoUtils,
PATTERN_INFO,
SYSTEM_FONT_INFO,
} from "../shared/obj_bin_transform_utils.js";

function compileCssFontInfo(info) {
const encoder = new TextEncoder();
const { encoder } = InfoUtils;
const encodedStrings = {};
let stringsLength = 0;
for (const prop of CSS_FONT_INFO.strings) {
Expand All @@ -48,7 +49,7 @@ function compileCssFontInfo(info) {
}

function compileSystemFontInfo(info) {
const encoder = new TextEncoder();
const { encoder } = InfoUtils;
const encodedStrings = {};
let stringsLength = 0;
for (const prop of SYSTEM_FONT_INFO.strings) {
Expand Down Expand Up @@ -106,7 +107,7 @@ function compileFontInfo(font) {
? compileCssFontInfo(font.cssFontInfo)
: null;

const encoder = new TextEncoder();
const { encoder } = InfoUtils;
const encodedStrings = {};
let stringsLength = 0;
for (const prop of FONT_INFO.strings) {
Expand Down
2 changes: 1 addition & 1 deletion src/core/run_length_stream.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class RunLengthStream extends DecodeStream {
// (in addition to the second byte from the header), n = 129 through 255 -
// duplicate the second byte from the header (257 - n) times, n = 128 - end.
const repeatHeader = this.stream.getBytes(2);
if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {
if (repeatHeader.length < 2 || repeatHeader[0] === 128) {
this.eof = true;
return;
}
Expand Down
27 changes: 10 additions & 17 deletions src/display/obj_bin_transform_display.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,14 @@ import { assert, BBOX_INIT, FeatureTest, Util } from "../shared/util.js";
import {
CSS_FONT_INFO,
FONT_INFO,
InfoUtils,
PATTERN_INFO,
SYSTEM_FONT_INFO,
} from "../shared/obj_bin_transform_utils.js";

class CssFontInfo {
#buffer;

#decoder = new TextDecoder();

#view;

constructor(buffer) {
Expand All @@ -35,14 +34,13 @@ class CssFontInfo {

#readString(index) {
assert(index < CSS_FONT_INFO.strings.length, "Invalid string index");
const { decoder } = InfoUtils;
let offset = 0;
for (let i = 0; i < index; i++) {
offset += this.#view.getUint32(offset) + 4;
}
const length = this.#view.getUint32(offset);
return this.#decoder.decode(
new Uint8Array(this.#buffer, offset + 4, length)
);
return decoder.decode(new Uint8Array(this.#buffer, offset + 4, length));
}

get fontFamily() {
Expand All @@ -61,8 +59,6 @@ class CssFontInfo {
class SystemFontInfo {
#buffer;

#decoder = new TextDecoder();

#view;

constructor(buffer) {
Expand All @@ -76,14 +72,13 @@ class SystemFontInfo {

#readString(index) {
assert(index < SYSTEM_FONT_INFO.strings.length, "Invalid string index");
const { decoder } = InfoUtils;
let offset = 5;
for (let i = 0; i < index; i++) {
offset += this.#view.getUint32(offset) + 4;
}
const length = this.#view.getUint32(offset);
return this.#decoder.decode(
new Uint8Array(this.#buffer, offset + 4, length)
);
return decoder.decode(new Uint8Array(this.#buffer, offset + 4, length));
}

get css() {
Expand All @@ -103,15 +98,16 @@ class SystemFontInfo {
}

get style() {
const { decoder } = InfoUtils;
let offset = 1;
offset += 4 + this.#view.getUint32(offset);
const styleLength = this.#view.getUint32(offset);
const style = this.#decoder.decode(
const style = decoder.decode(
new Uint8Array(this.#buffer, offset + 4, styleLength)
);
offset += 4 + styleLength;
const weightLength = this.#view.getUint32(offset);
const weight = this.#decoder.decode(
const weight = decoder.decode(
new Uint8Array(this.#buffer, offset + 4, weightLength)
);
return { style, weight };
Expand All @@ -121,8 +117,6 @@ class SystemFontInfo {
class FontInfo {
#buffer;

#decoder = new TextDecoder();

#view;

constructor({ buffer, extra }) {
Expand Down Expand Up @@ -242,14 +236,13 @@ class FontInfo {

#readString(index) {
assert(index < FONT_INFO.strings.length, "Invalid string index");
const { decoder } = InfoUtils;
let offset = FONT_INFO.OFFSET_STRINGS + 4;
for (let i = 0; i < index; i++) {
offset += this.#view.getUint32(offset) + 4;
}
const length = this.#view.getUint32(offset);
return this.#decoder.decode(
new Uint8Array(this.#buffer, offset + 4, length)
);
return decoder.decode(new Uint8Array(this.#buffer, offset + 4, length));
}

get fallbackName() {
Expand Down
14 changes: 13 additions & 1 deletion src/shared/obj_bin_transform_utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* limitations under the License.
*/

import { shadow } from "./util.js";

class CSS_FONT_INFO {
static strings = ["fontFamily", "fontWeight", "italicAngle"];
}
Expand Down Expand Up @@ -68,4 +70,14 @@ class PATTERN_INFO {
static N_FIGURES = 16; // number of figures
}

export { CSS_FONT_INFO, FONT_INFO, PATTERN_INFO, SYSTEM_FONT_INFO };
class InfoUtils {
static get decoder() {
return shadow(this, "decoder", new TextDecoder());
}

static get encoder() {
return shadow(this, "encoder", new TextEncoder());
}
}

export { CSS_FONT_INFO, FONT_INFO, InfoUtils, PATTERN_INFO, SYSTEM_FONT_INFO };
1 change: 1 addition & 0 deletions test/pdfs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -952,3 +952,4 @@
!function_based_shading_cmyk.pdf
!large_jpeg_downscale.pdf
!bug1898053_minimal.pdf
!bug2055455.pdf
Binary file added test/pdfs/bug2055455.pdf
Binary file not shown.
9 changes: 9 additions & 0 deletions test/test_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -14524,5 +14524,14 @@
"rounds": 1,
"lastPage": 1,
"type": "eq"
},
{
"id": "bug2055455",
"file": "pdfs/bug2055455.pdf",
"md5": "e9a7d04240532aa4c6849f291f275895",
"rounds": 1,
"lastPage": 1,
"type": "eq",
"print": true
}
]
22 changes: 11 additions & 11 deletions test/unit/annotation_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1764,7 +1764,7 @@ describe("annotation", function () {
);
expect(appearance).toEqual(
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm" +
" 2 3.07 Td (test\\\\print) Tj ET Q EMC"
" 2 3.72 Td (test\\\\print) Tj ET Q EMC"
);
});

Expand Down Expand Up @@ -1801,7 +1801,7 @@ describe("annotation", function () {
"\x30\x53\x30\x93\x30\x6b\x30\x61\x30\x6f\x4e\x16\x75\x4c\x30\x6e";
expect(appearance).toEqual(
"/Tx BMC q BT /Goth 5 Tf 1 0 0 1 0 0 Tm" +
` 2 3.07 Td (${utf16String}) Tj ET Q EMC`
` 2 3.38 Td (${utf16String}) Tj ET Q EMC`
);
});

Expand Down Expand Up @@ -1884,7 +1884,7 @@ describe("annotation", function () {
);
expect(appearance).toEqual(
"/Tx BMC q BT /Helv 5.92 Tf 0 g 1 0 0 1 0 0 Tm" +
" 2 3.07 Td (test \\(print\\)) Tj ET Q EMC"
" 2 3.49 Td (test \\(print\\)) Tj ET Q EMC"
);
});

Expand Down Expand Up @@ -1921,7 +1921,7 @@ describe("annotation", function () {
"\x30\x53\x30\x93\x30\x6b\x30\x61\x30\x6f\x4e\x16\x75\x4c\x30\x6e";
expect(appearance).toEqual(
"/Tx BMC q BT /Goth 3.5 Tf 0 g 1 0 0 1 0 0 Tm" +
` 2 3.07 Td (${utf16String}) Tj ET Q EMC`
` 2 3.86 Td (${utf16String}) Tj ET Q EMC`
);
});

Expand Down Expand Up @@ -2124,7 +2124,7 @@ describe("annotation", function () {
annotationStorage
);
expect(appearance).toEqual(
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 3.21 Tm" +
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 3.72 Tm" +
" 2.61 0 Td (a) Tj 8 0 Td (a) Tj 8.56 0 Td (\\() Tj" +
" 7.44 0 Td (a) Tj 8 0 Td (a) Tj" +
" 8.56 0 Td (\\)) Tj 7.44 0 Td (a) Tj" +
Expand Down Expand Up @@ -2165,7 +2165,7 @@ describe("annotation", function () {
annotationStorage
);
expect(appearance).toEqual(
"/Tx BMC q BT /Goth 5 Tf 1 0 0 1 0 2.5 Tm" +
"/Tx BMC q BT /Goth 5 Tf 1 0 0 1 0 3.38 Tm" +
" 1.5 0 Td (\x30\x53) Tj 8 0 Td (\x30\x93) Tj 8 0 Td (\x30\x6b) Tj" +
" 8 0 Td (\x30\x61) Tj 8 0 Td (\x30\x6f) Tj" +
" 8 0 Td (\x4e\x16) Tj 8 0 Td (\x75\x4c) Tj" +
Expand Down Expand Up @@ -2209,7 +2209,7 @@ describe("annotation", function () {
expect(newData.data).toEqual(
"2 0 obj\n<< /Subtype /Form /Resources " +
"<< /Font << /Helv 314 0 R>>>> /BBox [0 0 32 10] /Length 74>> stream\n" +
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm 2 3.07 Td (hello world) Tj " +
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm 2 3.72 Td (hello world) Tj " +
"ET Q EMC\nendstream\nendobj\n"
);
});
Expand Down Expand Up @@ -2327,8 +2327,8 @@ describe("annotation", function () {
);
expect(newData.data).toEqual(
"2 0 obj\n<< /Subtype /Form /Resources " +
"<< /Font << /Helv 314 0 R>>>> /BBox [0 0 10 32] /Matrix [0 1 -1 0 32 0] /Length 74>> stream\n" +
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm 2 2.94 Td (hello world) Tj " +
"<< /Font << /Helv 314 0 R>>>> /BBox [0 0 10 32] /Matrix [0 1 -1 0 32 0] /Length 75>> stream\n" +
"/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm 2 14.72 Td (hello world) Tj " +
"ET Q EMC\nendstream\nendobj\n"
);
});
Expand Down Expand Up @@ -2388,7 +2388,7 @@ describe("annotation", function () {
// generated data with the PDF.js library.
const flateStream = new FlateStream(new StringStream(compressedStream));
expect(flateStream.getString()).toEqual(
`/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm 2 3.07 Td (${value}) Tj ET Q EMC`
`/Tx BMC q BT /Helv 5 Tf 1 0 0 1 0 0 Tm 2 3.72 Td (${value}) Tj ET Q EMC`
);
});

Expand Down Expand Up @@ -2513,7 +2513,7 @@ describe("annotation", function () {
expect(newData.data).toEqual(
"2 0 obj\n<< /Subtype /Form /Resources " +
"<< /Font << /Helv 314 0 R /Goth 159 0 R>>>> /BBox [0 0 32 10] /Length 79>> stream\n" +
`/Tx BMC q BT /Goth 5 Tf 1 0 0 1 0 0 Tm 2 3.07 Td (${utf16String}) Tj ` +
`/Tx BMC q BT /Goth 5 Tf 1 0 0 1 0 0 Tm 2 3.38 Td (${utf16String}) Tj ` +
"ET Q EMC\nendstream\nendobj\n"
);
});
Expand Down
7 changes: 4 additions & 3 deletions test/unit/obj_bin_transform_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import {
SystemFontInfo,
} from "../../src/display/obj_bin_transform_display.js";
import { FeatureTest } from "../../src/shared/util.js";
import { InfoUtils } from "../../src/shared/obj_bin_transform_utils.js";

describe("obj_bin_transform", function () {
describe("Font data", function () {
Expand Down Expand Up @@ -80,7 +81,7 @@ describe("obj_bin_transform", function () {
describe("font data serialization and deserialization", function () {
describe("CssFontInfo", function () {
it("must roundtrip correctly for CssFontInfo", function () {
const encoder = new TextEncoder();
const { encoder } = InfoUtils;
let sizeEstimate = 0;
for (const string of ["Sample Family", "not a number", "angle"]) {
sizeEstimate += 4 + encoder.encode(string).length;
Expand All @@ -97,7 +98,7 @@ describe("obj_bin_transform", function () {

describe("SystemFontInfo", function () {
it("must roundtrip correctly for SystemFontInfo", function () {
const encoder = new TextEncoder();
const { encoder } = InfoUtils;
let sizeEstimate = 1 + 4;
for (const string of [
"some string",
Expand Down Expand Up @@ -127,7 +128,7 @@ describe("obj_bin_transform", function () {
describe("FontInfo", function () {
it("must roundtrip correctly for FontInfo", function () {
let sizeEstimate = 92; // fixed offset until the strings
const encoder = new TextEncoder();
const { encoder } = InfoUtils;
sizeEstimate += 4 + 4 * (4 + encoder.encode("string").length);
sizeEstimate += 4 + 4; // cssFontInfo and systemFontInfo
sizeEstimate += 4 + fontInfo.data.length;
Expand Down
Loading