Skip to content

Commit

Permalink
Add PDFObject accessors (#414)
Browse files Browse the repository at this point in the history
* Add PDFObject.value() methods

* Change wording

* Change accessor names

* Update tests for PDFObject accessor
  • Loading branch information
Hopding authored Apr 18, 2020
1 parent 129b846 commit ac74e89
Show file tree
Hide file tree
Showing 28 changed files with 166 additions and 68 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -814,7 +814,7 @@ We welcome contributions from the open source community! If you are interested i

- [Möbius Printing helper](https://shreevatsa.net/mobius-print/) - a tool created by @shreevatsa
- [Extract PDF pages](https://shreevatsa.net/pdf-pages/) - a tool created by @shreevatsa
- [COVID-19 travel certificate generator](https://github.com/LAB-MI/deplacement-covid-19) - a tool that creates travel certificates for French citizens under quarantine due to COVID-19
- [Travel certificate generator](https://github.com/LAB-MI/deplacement-covid-19) - a tool that creates travel certificates for French citizens under quarantine due to COVID-19
- [How to use pdf-lib in AWS Lambdas](https://medium.com/swlh/create-pdf-using-pdf-lib-on-serverless-aws-lambda-e9506246dc88) - a tutorial written by Crespo Wang
- [Working With PDFs in Node.js Using pdf-lib](http://thecodebarbarian.com/working-with-pdfs-in-node-js.html) - a tutorial by Valeri Karpov

Expand Down
2 changes: 1 addition & 1 deletion src/api/PDFPage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export default class PDFPage {
*/
getRotation(): Rotation {
const Rotate = this.node.Rotate();
return degrees(Rotate ? Rotate.value() : 0);
return degrees(Rotate ? Rotate.asNumber() : 0);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/api/objects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ export const asPDFNumber = (num: number | PDFNumber) =>
num instanceof PDFNumber ? num : PDFNumber.of(num);

export const asNumber = (num: number | PDFNumber) =>
num instanceof PDFNumber ? num.value() : num;
num instanceof PDFNumber ? num.asNumber() : num;
8 changes: 4 additions & 4 deletions src/core/embedders/PDFPageEmbedder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,12 @@ const fullPageBoundingBox = (page: PDFPageLeaf) => {
const mediaBox = page.MediaBox();

const width =
mediaBox.lookup(2, PDFNumber).value() -
mediaBox.lookup(0, PDFNumber).value();
mediaBox.lookup(2, PDFNumber).asNumber() -
mediaBox.lookup(0, PDFNumber).asNumber();

const height =
mediaBox.lookup(3, PDFNumber).value() -
mediaBox.lookup(1, PDFNumber).value();
mediaBox.lookup(3, PDFNumber).asNumber() -
mediaBox.lookup(1, PDFNumber).asNumber();

return { left: 0, bottom: 0, right: width, top: height };
};
Expand Down
12 changes: 8 additions & 4 deletions src/core/objects/PDFArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,10 @@ class PDFArray extends PDFObject {
asRectangle(): { x: number; y: number; width: number; height: number } {
if (this.size() !== 4) throw new PDFArrayIsNotRectangleError(this.size());

const lowerLeftX = this.lookup(0, PDFNumber).value();
const lowerLeftY = this.lookup(1, PDFNumber).value();
const upperRightX = this.lookup(2, PDFNumber).value();
const upperRightY = this.lookup(3, PDFNumber).value();
const lowerLeftX = this.lookup(0, PDFNumber).asNumber();
const lowerLeftY = this.lookup(1, PDFNumber).asNumber();
const upperRightX = this.lookup(2, PDFNumber).asNumber();
const upperRightY = this.lookup(3, PDFNumber).asNumber();

const x = lowerLeftX;
const y = lowerLeftY;
Expand All @@ -98,6 +98,10 @@ class PDFArray extends PDFObject {
return { x, y, width, height };
}

asArray(): PDFObject[] {
return this.array.slice();
}

clone(context?: PDFContext): PDFArray {
const clone = PDFArray.withContext(context || this.context);
for (let idx = 0, len = this.size(); idx < len; idx++) {
Expand Down
4 changes: 4 additions & 0 deletions src/core/objects/PDFBool.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ class PDFBool extends PDFObject {
this.value = value;
}

asBoolean(): boolean {
return this.value;
}

clone(): PDFBool {
return this;
}
Expand Down
6 changes: 5 additions & 1 deletion src/core/objects/PDFDict.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class PDFDict extends PDFObject {

private readonly dict: DictMap;

protected constructor(map: Map<PDFName, PDFObject>, context: PDFContext) {
protected constructor(map: DictMap, context: PDFContext) {
super();
this.dict = map;
this.context = context;
Expand Down Expand Up @@ -83,6 +83,10 @@ class PDFDict extends PDFObject {
return this.dict.delete(key);
}

asMap(): Map<PDFName, PDFObject> {
return new Map(this.dict);
}

clone(context?: PDFContext): PDFDict {
const clone = PDFDict.withContext(context || this.context);
const entries = this.entries();
Expand Down
4 changes: 4 additions & 0 deletions src/core/objects/PDFHexString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ class PDFHexString extends PDFObject {
this.value = value;
}

asString(): string {
return this.value;
}

clone(): PDFHexString {
return PDFHexString.of(this.value);
}
Expand Down
5 changes: 5 additions & 0 deletions src/core/objects/PDFName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ class PDFName extends PDFObject {
this.encodedName = encodedName;
}

asString(): string {
return this.encodedName;
}

/** @deprecated in favor of [[PDFName.asString]] */
value(): string {
return this.encodedName;
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/objects/PDFNull.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import PDFObject from 'src/core/objects/PDFObject';
import CharCodes from 'src/core/syntax/CharCodes';

class PDFNull extends PDFObject {
asNull(): null {
return null;
}

clone(): PDFNull {
return this;
}
Expand Down
5 changes: 5 additions & 0 deletions src/core/objects/PDFNumber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ class PDFNumber extends PDFObject {
this.stringValue = numberToString(value);
}

asNumber(): number {
return this.numberValue;
}

/** @deprecated in favor of [[PDFNumber.asNumber]] */
value(): number {
return this.numberValue;
}
Expand Down
4 changes: 4 additions & 0 deletions src/core/objects/PDFRawStream.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ class PDFRawStream extends PDFStream {
this.contents = contents;
}

asUint8Array(): Uint8Array {
return this.contents.slice();
}

clone(context?: PDFContext): PDFRawStream {
return PDFRawStream.of(this.dict.clone(context), this.contents.slice());
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/objects/PDFRef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class PDFRef extends PDFObject {
this.tag = `${objectNumber} ${generationNumber} R`;
}

clone() {
clone(): PDFRef {
return this;
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/objects/PDFString.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ class PDFString extends PDFObject {
this.value = value;
}

asString(): string {
return this.value;
}

clone(): PDFString {
return PDFString.of(this.value);
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/parser/PDFObjectParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ class PDFObjectParser extends BaseParser {

const Length = dict.get(PDFName.of('Length'));
if (Length instanceof PDFNumber) {
end = start + Length.value();
end = start + Length.asNumber();
this.bytes.moveTo(end);
this.skipWhitespaceAndComments();
if (!this.matchKeyword(Keywords.endstream)) {
Expand Down
4 changes: 2 additions & 2 deletions src/core/parser/PDFObjectStreamParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ class PDFObjectStreamParser extends PDFObjectParser {

this.alreadyParsed = false;
this.shouldWaitForTick = shouldWaitForTick || (() => false);
this.firstOffset = dict.lookup(PDFName.of('First'), PDFNumber).value();
this.objectCount = dict.lookup(PDFName.of('N'), PDFNumber).value();
this.firstOffset = dict.lookup(PDFName.of('First'), PDFNumber).asNumber();
this.objectCount = dict.lookup(PDFName.of('N'), PDFNumber).asNumber();
}

async parseIntoContext(): Promise<void> {
Expand Down
8 changes: 4 additions & 4 deletions src/core/parser/PDFXRefStreamParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,18 +43,18 @@ class PDFXRefStreamParser {
if (Index instanceof PDFArray) {
this.subsections = [];
for (let idx = 0, len = Index.size(); idx < len; idx += 2) {
const firstObjectNumber = Index.lookup(idx + 0, PDFNumber).value();
const length = Index.lookup(idx + 1, PDFNumber).value();
const firstObjectNumber = Index.lookup(idx + 0, PDFNumber).asNumber();
const length = Index.lookup(idx + 1, PDFNumber).asNumber();
this.subsections.push({ firstObjectNumber, length });
}
} else {
this.subsections = [{ firstObjectNumber: 0, length: Size.value() }];
this.subsections = [{ firstObjectNumber: 0, length: Size.asNumber() }];
}

const W = this.dict.lookup(PDFName.of('W'), PDFArray);
this.byteWidths = [-1, -1, -1];
for (let idx = 0, len = W.size(); idx < len; idx++) {
this.byteWidths[idx] = W.lookup(idx, PDFNumber).value();
this.byteWidths[idx] = W.lookup(idx, PDFNumber).asNumber();
}
}

Expand Down
12 changes: 8 additions & 4 deletions src/core/streams/decode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ const decodeStream = (
if (params instanceof PDFDict) {
const EarlyChange = params.lookup(PDFName.of('EarlyChange'));
if (EarlyChange instanceof PDFNumber) {
earlyChange = EarlyChange.value();
earlyChange = EarlyChange.asNumber();
}
}
return new LZWStream(stream, undefined, earlyChange as 0 | 1);
Expand All @@ -42,7 +42,7 @@ const decodeStream = (
if (encoding === PDFName.of('RunLengthDecode')) {
return new RunLengthStream(stream);
}
throw new UnsupportedEncodingError(encoding.value());
throw new UnsupportedEncodingError(encoding.asString());
};

export const decodePDFRawStream = ({ dict, contents }: PDFRawStream) => {
Expand All @@ -52,13 +52,17 @@ export const decodePDFRawStream = ({ dict, contents }: PDFRawStream) => {
const DecodeParms = dict.lookup(PDFName.of('DecodeParms'));

if (Filter instanceof PDFName) {
stream = decodeStream(stream, Filter, DecodeParms);
stream = decodeStream(
stream,
Filter,
DecodeParms as PDFDict | typeof PDFNull | undefined,
);
} else if (Filter instanceof PDFArray) {
for (let idx = 0, len = Filter.size(); idx < len; idx++) {
stream = decodeStream(
stream,
Filter.lookup(idx, PDFName),
DecodeParms && (DecodeParms as PDFArray).lookup(idx),
DecodeParms && (DecodeParms as PDFArray).lookupMaybe(idx, PDFDict),
);
}
} else if (!!Filter) {
Expand Down
10 changes: 5 additions & 5 deletions src/core/structures/PDFPageTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class PDFPageTree extends PDFDict {
Kids.push(leafRef);
this.ascend((node) => {
const Count = node.Count();
node.set(PDFName.of('Count'), PDFNumber.of(Count.value() + 1));
node.set(PDFName.of('Count'), PDFNumber.of(Count.asNumber() + 1));
});
}

Expand Down Expand Up @@ -71,7 +71,7 @@ class PDFPageTree extends PDFDict {
const kid = this.context.lookup(kidRef) as TreeNode;

if (kid instanceof PDFPageTree) {
const kidCount = kid.Count().value();
const kidCount = kid.Count().asNumber();
if (pageIdx + kidCount > targetIndex) {
return kid.insertLeafNode(leafRef, targetIndex - pageIdx) || kidRef;
} else {
Expand All @@ -85,7 +85,7 @@ class PDFPageTree extends PDFDict {
Kids.insert(kidIdx, leafRef);
this.ascend((node) => {
const Count = node.Count();
node.set(PDFName.of('Count'), PDFNumber.of(Count.value() + 1));
node.set(PDFName.of('Count'), PDFNumber.of(Count.asNumber() + 1));
});

return undefined;
Expand All @@ -111,7 +111,7 @@ class PDFPageTree extends PDFDict {
const kid = this.context.lookup(kidRef) as TreeNode;

if (kid instanceof PDFPageTree) {
const kidCount = kid.Count().value();
const kidCount = kid.Count().asNumber();
if (pageIdx + kidCount > targetIndex) {
kid.removeLeafNode(targetIndex - pageIdx);
return;
Expand All @@ -134,7 +134,7 @@ class PDFPageTree extends PDFDict {
Kids.remove(kidIdx);
this.ascend((node) => {
const Count = node.Count();
node.set(PDFName.of('Count'), PDFNumber.of(Count.value() - 1));
node.set(PDFName.of('Count'), PDFNumber.of(Count.asNumber() - 1));
});
}
}
Expand Down
13 changes: 13 additions & 0 deletions tests/core/objects/PDFArray.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ describe(`PDFArray`, () => {
expect(array.size()).toBe(2);
});

it(`can be converted to an Array`, () => {
expect(pdfArray.asArray()).toEqual([
pdfBool,
pdfHexString,
pdfName,
pdfNull,
pdfNumber,
pdfString,
pdfSubArray,
pdfRef,
]);
});

it(`can be cloned`, () => {
const original = pdfArray;
const clone = original.clone();
Expand Down
5 changes: 5 additions & 0 deletions tests/core/objects/PDFBool.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ describe(`PDFBool`, () => {
);
});

it(`can be converted to a boolean`, () => {
expect(PDFBool.True.asBoolean()).toBe(true);
expect(PDFBool.False.asBoolean()).toBe(false);
});

it(`can be cloned`, () => {
expect(PDFBool.True.clone()).toBe(PDFBool.True);
expect(PDFBool.False.clone()).toBe(PDFBool.False);
Expand Down
16 changes: 16 additions & 0 deletions tests/core/objects/PDFDict.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
PDFNumber,
PDFRef,
PDFString,
PDFObject,
} from 'src/core';
import { toCharCode, typedArrayFor } from 'src/utils';

Expand Down Expand Up @@ -60,6 +61,21 @@ describe(`PDFDict`, () => {
expect(pdfSubDict.get(PDFName.of('Array'))).toBe(pdfArray);
});

it(`can be converted to a Map`, () => {
expect(pdfDict.asMap()).toEqual(
new Map<PDFName, PDFObject>([
[PDFName.of('Boolean'), pdfBool],
[PDFName.of('HexString'), pdfHexString],
[PDFName.of('Name'), pdfName],
[PDFName.of('Null'), pdfNull],
[PDFName.of('Number'), pdfNumber],
[PDFName.of('String'), pdfString],
[PDFName.of('Ref'), pdfRef],
[PDFName.of('Dictionary'), pdfSubDict],
]),
);
});

it(`can be cloned`, () => {
const original = pdfDict;
const clone = original.clone();
Expand Down
7 changes: 7 additions & 0 deletions tests/core/objects/PDFHexString.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@ describe(`PDFHexString`, () => {
);
});

it(`can be converted to a string`, () => {
expect(PDFHexString.of('901FA').asString()).toBe('901FA');
expect(PDFHexString.fromText('stuff 💩 and 🎂things').asString()).toBe(
'FEFF007300740075006600660020D83DDCA900200061006E00640020D83CDF82007400680069006E00670073',
);
});

it(`can be cloned`, () => {
const original = PDFHexString.of('901FA');
const clone = original.clone();
Expand Down
4 changes: 4 additions & 0 deletions tests/core/objects/PDFNull.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ describe(`PDFNull`, () => {
expect(() => new (PDFNull as any)()).toThrow();
});

it(`can be converted to null`, () => {
expect(PDFNull.asNull()).toBe(null);
});

it(`can be cloned`, () => {
expect(PDFNull.clone()).toBe(PDFNull);
});
Expand Down
4 changes: 4 additions & 0 deletions tests/core/objects/PDFRawStream.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ describe(`PDFRawStream`, () => {
expect(PDFRawStream.of(dict, data)).toBeInstanceOf(PDFRawStream);
});

it(`can be converted to a Uint8Array`, () => {
expect(PDFRawStream.of(dict, data).asUint8Array()).toEqual(data);
});

it(`can be cloned`, () => {
const original = PDFRawStream.of(dict, data);
const clone = original.clone();
Expand Down
Loading

0 comments on commit ac74e89

Please sign in to comment.