mirror of
https://github.com/mozilla/pdf.js.git
synced 2025-04-20 15:18:08 +02:00
Compress the data when saving annotions
CompressionStream API has been added in Firefox 113 (see https://bugzilla.mozilla.org/show_bug.cgi?id=1823619) hence we can use it to compress the streams with added/modified annotations.
This commit is contained in:
parent
8f2d8f62f3
commit
2486536843
8 changed files with 156 additions and 38 deletions
1
test/pdfs/.gitignore
vendored
1
test/pdfs/.gitignore
vendored
|
@ -590,3 +590,4 @@
|
|||
!copy_paste_ligatures.pdf
|
||||
!issue16316.pdf
|
||||
!issue14565.pdf
|
||||
!multiline.pdf
|
||||
|
|
BIN
test/pdfs/multiline.pdf
Executable file
BIN
test/pdfs/multiline.pdf
Executable file
Binary file not shown.
|
@ -7580,5 +7580,19 @@
|
|||
"rounds": 1,
|
||||
"annotations": true,
|
||||
"type": "eq"
|
||||
},
|
||||
{
|
||||
"id": "multiline_compress",
|
||||
"file": "pdfs/multiline.pdf",
|
||||
"md5": "4727c7d1e4e5c7d45fded8ab7a2e05e5",
|
||||
"rounds": 1,
|
||||
"type": "eq",
|
||||
"save": true,
|
||||
"print": true,
|
||||
"annotationStorage": {
|
||||
"24R": {
|
||||
"value": "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz\nabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
@ -2115,6 +2115,58 @@ describe("annotation", function () {
|
|||
);
|
||||
});
|
||||
|
||||
it("should compress and save text", async function () {
|
||||
const textWidgetRef = Ref.get(123, 0);
|
||||
const xref = new XRefMock([
|
||||
{ ref: textWidgetRef, data: textWidgetDict },
|
||||
helvRefObj,
|
||||
]);
|
||||
partialEvaluator.xref = xref;
|
||||
const task = new WorkerTask("test save");
|
||||
|
||||
const annotation = await AnnotationFactory.create(
|
||||
xref,
|
||||
textWidgetRef,
|
||||
pdfManagerMock,
|
||||
idFactoryMock
|
||||
);
|
||||
const annotationStorage = new Map();
|
||||
const value = "a".repeat(256);
|
||||
annotationStorage.set(annotation.data.id, { value });
|
||||
|
||||
const data = await annotation.save(
|
||||
partialEvaluator,
|
||||
task,
|
||||
annotationStorage
|
||||
);
|
||||
expect(data.length).toEqual(2);
|
||||
const [oldData, newData] = data;
|
||||
expect(oldData.ref).toEqual(Ref.get(123, 0));
|
||||
expect(newData.ref).toEqual(Ref.get(2, 0));
|
||||
|
||||
oldData.data = oldData.data.replace(/\(D:\d+\)/, "(date)");
|
||||
expect(oldData.data).toEqual(
|
||||
"123 0 obj\n" +
|
||||
"<< /Type /Annot /Subtype /Widget /FT /Tx /DA (/Helv 5 Tf) /DR " +
|
||||
"<< /Font << /Helv 314 0 R>>>> /Rect [0 0 32 10] " +
|
||||
`/V (${value}) /AP << /N 2 0 R>> /M (date)>>\nendobj\n`
|
||||
);
|
||||
|
||||
const compressedData = [
|
||||
120, 156, 211, 15, 169, 80, 112, 242, 117, 86, 40, 84, 112, 10, 81, 208,
|
||||
247, 72, 205, 41, 83, 48, 85, 8, 73, 83, 48, 84, 48, 0, 66, 8, 25, 146,
|
||||
171, 96, 164, 96, 172, 103, 96, 174, 16, 146, 162, 160, 145, 56, 194,
|
||||
129, 166, 66, 72, 150, 130, 107, 136, 66, 160, 130, 171, 175, 51, 0,
|
||||
222, 235, 111, 133,
|
||||
];
|
||||
const compressedStream = String.fromCharCode(...compressedData);
|
||||
expect(newData.data).toEqual(
|
||||
"2 0 obj\n<< /Subtype /Form /Resources " +
|
||||
"<< /Font << /Helv 314 0 R>>>> /BBox [0 0 32 10] /Filter /FlateDecode /Length 68>> stream\n" +
|
||||
`${compressedStream}\nendstream\nendobj\n`
|
||||
);
|
||||
});
|
||||
|
||||
it("should get field object for usage in JS sandbox", async function () {
|
||||
const textWidgetRef = Ref.get(123, 0);
|
||||
const xDictRef = Ref.get(141, 0);
|
||||
|
|
|
@ -20,7 +20,7 @@ import { StringStream } from "../../src/core/stream.js";
|
|||
|
||||
describe("Writer", function () {
|
||||
describe("Incremental update", function () {
|
||||
it("should update a file with new objects", function () {
|
||||
it("should update a file with new objects", async function () {
|
||||
const originalData = new Uint8Array();
|
||||
const newRefs = [
|
||||
{ ref: Ref.get(123, 0x2d), data: "abc\n" },
|
||||
|
@ -37,7 +37,7 @@ describe("Writer", function () {
|
|||
info: {},
|
||||
};
|
||||
|
||||
let data = incrementalUpdate({ originalData, xrefInfo, newRefs });
|
||||
let data = await incrementalUpdate({ originalData, xrefInfo, newRefs });
|
||||
data = bytesToString(data);
|
||||
|
||||
const expected =
|
||||
|
@ -60,7 +60,7 @@ describe("Writer", function () {
|
|||
expect(data).toEqual(expected);
|
||||
});
|
||||
|
||||
it("should update a file, missing the /ID-entry, with new objects", function () {
|
||||
it("should update a file, missing the /ID-entry, with new objects", async function () {
|
||||
const originalData = new Uint8Array();
|
||||
const newRefs = [{ ref: Ref.get(123, 0x2d), data: "abc\n" }];
|
||||
const xrefInfo = {
|
||||
|
@ -74,7 +74,7 @@ describe("Writer", function () {
|
|||
info: {},
|
||||
};
|
||||
|
||||
let data = incrementalUpdate({ originalData, xrefInfo, newRefs });
|
||||
let data = await incrementalUpdate({ originalData, xrefInfo, newRefs });
|
||||
data = bytesToString(data);
|
||||
|
||||
const expected =
|
||||
|
@ -96,7 +96,7 @@ describe("Writer", function () {
|
|||
});
|
||||
|
||||
describe("writeDict", function () {
|
||||
it("should write a Dict", function () {
|
||||
it("should write a Dict", async function () {
|
||||
const dict = new Dict(null);
|
||||
dict.set("A", Name.get("B"));
|
||||
dict.set("B", Ref.get(123, 456));
|
||||
|
@ -121,7 +121,7 @@ describe("Writer", function () {
|
|||
dict.set("NullVal", null);
|
||||
|
||||
const buffer = [];
|
||||
writeDict(dict, buffer, null);
|
||||
await writeDict(dict, buffer, null);
|
||||
|
||||
const expected =
|
||||
"<< /A /B /B 123 456 R /C 789 /D (hello world) " +
|
||||
|
@ -134,14 +134,14 @@ describe("Writer", function () {
|
|||
expect(buffer.join("")).toEqual(expected);
|
||||
});
|
||||
|
||||
it("should write a Dict in escaping PDF names", function () {
|
||||
it("should write a Dict in escaping PDF names", async function () {
|
||||
const dict = new Dict(null);
|
||||
dict.set("\xfeA#", Name.get("hello"));
|
||||
dict.set("B", Name.get("#hello"));
|
||||
dict.set("C", Name.get("he\xfello\xff"));
|
||||
|
||||
const buffer = [];
|
||||
writeDict(dict, buffer, null);
|
||||
await writeDict(dict, buffer, null);
|
||||
|
||||
const expected = "<< /#feA#23 /hello /B /#23hello /C /he#fello#ff>>";
|
||||
|
||||
|
@ -150,7 +150,7 @@ describe("Writer", function () {
|
|||
});
|
||||
|
||||
describe("XFA", function () {
|
||||
it("should update AcroForm when no datasets in XFA array", function () {
|
||||
it("should update AcroForm when no datasets in XFA array", async function () {
|
||||
const originalData = new Uint8Array();
|
||||
const newRefs = [];
|
||||
|
||||
|
@ -176,7 +176,7 @@ describe("Writer", function () {
|
|||
info: {},
|
||||
};
|
||||
|
||||
let data = incrementalUpdate({
|
||||
let data = await incrementalUpdate({
|
||||
originalData,
|
||||
xrefInfo,
|
||||
newRefs,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue