Skip to content

Commit

Permalink
Include inherited resources when normalizing (#222)
Browse files Browse the repository at this point in the history
  • Loading branch information
Hopding authored Oct 19, 2019
1 parent acb837a commit 4a3d795
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 54 deletions.
22 changes: 22 additions & 0 deletions src/core/PDFContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,28 @@ class PDFContext {
return this.indirectObjects.delete(ref);
}

lookupMaybe(ref: LookupKey, type: typeof PDFArray): PDFArray | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFBool): PDFBool | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFDict): PDFDict | undefined;
lookupMaybe(
ref: LookupKey,
type: typeof PDFHexString,
): PDFHexString | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFName): PDFName | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFNull): typeof PDFNull | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFNumber): PDFNumber | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFStream): PDFStream | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFRef): PDFRef | undefined;
lookupMaybe(ref: LookupKey, type: typeof PDFString): PDFString | undefined;

lookupMaybe(ref: LookupKey, type: any) {
const result = ref instanceof PDFRef ? this.indirectObjects.get(ref) : ref;
if (result && !(result instanceof type)) {
throw new UnexpectedObjectTypeError(type, result);
}
return result;
}

lookup(ref: LookupKey): PDFObject | undefined;
lookup(ref: LookupKey, type: typeof PDFArray): PDFArray;
lookup(ref: LookupKey, type: typeof PDFBool): PDFBool;
Expand Down
18 changes: 18 additions & 0 deletions src/core/objects/PDFArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,24 @@ class PDFArray extends PDFObject {
return this.array[index];
}

lookupMaybe(index: number, type: typeof PDFArray): PDFArray | undefined;
lookupMaybe(index: number, type: typeof PDFBool): PDFBool | undefined;
lookupMaybe(index: number, type: typeof PDFDict): PDFDict | undefined;
lookupMaybe(
index: number,
type: typeof PDFHexString,
): PDFHexString | undefined;
lookupMaybe(index: number, type: typeof PDFName): PDFName | undefined;
lookupMaybe(index: number, type: typeof PDFNull): typeof PDFNull | undefined;
lookupMaybe(index: number, type: typeof PDFNumber): PDFNumber | undefined;
lookupMaybe(index: number, type: typeof PDFStream): PDFStream | undefined;
lookupMaybe(index: number, type: typeof PDFRef): PDFRef | undefined;
lookupMaybe(index: number, type: typeof PDFString): PDFString | undefined;

lookupMaybe(index: number, type: any) {
return this.context.lookupMaybe(this.get(index), type) as any;
}

lookup(index: number): PDFObject | undefined;
lookup(index: number, type: typeof PDFArray): PDFArray;
lookup(index: number, type: typeof PDFBool): PDFBool;
Expand Down
22 changes: 22 additions & 0 deletions src/core/objects/PDFDict.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,28 @@ class PDFDict extends PDFObject {
return this.dict.get(key);
}

has(key: PDFName): boolean {
return this.dict.has(key);
}

lookupMaybe(key: PDFName, type: typeof PDFArray): PDFArray | undefined;
lookupMaybe(key: PDFName, type: typeof PDFBool): PDFBool | undefined;
lookupMaybe(key: PDFName, type: typeof PDFDict): PDFDict | undefined;
lookupMaybe(
key: PDFName,
type: typeof PDFHexString,
): PDFHexString | undefined;
lookupMaybe(key: PDFName, type: typeof PDFName): PDFName | undefined;
lookupMaybe(key: PDFName, type: typeof PDFNull): typeof PDFNull | undefined;
lookupMaybe(key: PDFName, type: typeof PDFNumber): PDFNumber | undefined;
lookupMaybe(key: PDFName, type: typeof PDFStream): PDFStream | undefined;
lookupMaybe(key: PDFName, type: typeof PDFRef): PDFRef | undefined;
lookupMaybe(key: PDFName, type: typeof PDFString): PDFString | undefined;

lookupMaybe(key: PDFName, type: any) {
return this.context.lookupMaybe(this.get(key), type) as any;
}

lookup(key: PDFName): PDFObject | undefined;
lookup(key: PDFName, type: typeof PDFArray): PDFArray;
lookup(key: PDFName, type: typeof PDFBool): PDFBool;
Expand Down
13 changes: 13 additions & 0 deletions src/core/objects/PDFName.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ class PDFName extends PDFObject {
/* tslint:disable member-ordering */
static readonly Length = PDFName.of('Length');
static readonly FlateDecode = PDFName.of('FlateDecode');
static readonly Resources = PDFName.of('Resources');
static readonly Font = PDFName.of('Font');
static readonly XObject = PDFName.of('XObject');
static readonly Contents = PDFName.of('Contents');
static readonly Type = PDFName.of('Type');
static readonly Parent = PDFName.of('Parent');
static readonly MediaBox = PDFName.of('MediaBox');
static readonly Page = PDFName.of('Page');
static readonly Annots = PDFName.of('Annots');
static readonly TrimBox = PDFName.of('TrimBox');
static readonly BleedBox = PDFName.of('BleedBox');
static readonly CropBox = PDFName.of('CropBox');
static readonly Rotate = PDFName.of('Rotate');
/* tslint:enable member-ordering */

private readonly encodedName: string;
Expand Down
99 changes: 55 additions & 44 deletions src/core/structures/PDFPageLeaf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ class PDFPageLeaf extends PDFDict {

static withContextAndParent = (context: PDFContext, parent: PDFRef) => {
const dict = new Map();
dict.set(PDFName.of('Type'), PDFName.of('Page'));
dict.set(PDFName.of('Parent'), parent);
dict.set(PDFName.of('Resources'), context.obj({}));
dict.set(PDFName.of('MediaBox'), context.obj([0, 0, 612, 792]));
dict.set(PDFName.Type, PDFName.Page);
dict.set(PDFName.Parent, parent);
dict.set(PDFName.Resources, context.obj({}));
dict.set(PDFName.MediaBox, context.obj([0, 0, 612, 792]));
return new PDFPageLeaf(dict, context, false);
};

Expand Down Expand Up @@ -57,8 +57,8 @@ class PDFPageLeaf extends PDFDict {
return clone;
}

Parent(): PDFPageTree {
return this.lookup(PDFName.of('Parent')) as PDFPageTree;
Parent(): PDFPageTree | undefined {
return this.lookupMaybe(PDFName.Parent, PDFDict) as PDFPageTree | undefined;
}

Contents(): PDFStream | PDFArray | undefined {
Expand All @@ -69,35 +69,35 @@ class PDFPageLeaf extends PDFDict {
}

Annots(): PDFArray | undefined {
return this.lookup(PDFName.of('Annots')) as PDFArray | undefined;
return this.lookupMaybe(PDFName.Annots, PDFArray);
}

BleedBox(): PDFArray | undefined {
return this.lookup(PDFName.of('BleedBox')) as PDFArray | undefined;
return this.lookupMaybe(PDFName.BleedBox, PDFArray);
}

TrimBox(): PDFArray | undefined {
return this.lookup(PDFName.of('TrimBox')) as PDFArray | undefined;
return this.lookupMaybe(PDFName.TrimBox, PDFArray);
}

Resources(): PDFDict {
const dictOrRef = this.getInheritableAttribute(PDFName.of('Resources'));
return this.context.lookup(dictOrRef, PDFDict);
Resources(): PDFDict | undefined {
const dictOrRef = this.getInheritableAttribute(PDFName.Resources);
return this.context.lookupMaybe(dictOrRef, PDFDict);
}

MediaBox(): PDFArray {
const arrayOrRef = this.getInheritableAttribute(PDFName.of('MediaBox'));
const arrayOrRef = this.getInheritableAttribute(PDFName.MediaBox);
return this.context.lookup(arrayOrRef, PDFArray);
}

CropBox(): PDFArray | undefined {
const maybeArrayOrRef = this.getInheritableAttribute(PDFName.of('CropBox'));
return this.context.lookup(maybeArrayOrRef) as PDFArray | undefined;
const arrayOrRef = this.getInheritableAttribute(PDFName.CropBox);
return this.context.lookupMaybe(arrayOrRef, PDFArray);
}

Rotate(): PDFNumber | undefined {
const numberOrRef = this.getInheritableAttribute(PDFName.of('Rotate'));
return this.context.lookup(numberOrRef) as PDFNumber | undefined;
const numberOrRef = this.getInheritableAttribute(PDFName.Rotate);
return this.context.lookupMaybe(numberOrRef, PDFNumber);
}

getInheritableAttribute(name: PDFName): PDFObject | undefined {
Expand All @@ -109,38 +109,32 @@ class PDFPageLeaf extends PDFDict {
}

setParent(parentRef: PDFRef): void {
this.set(PDFName.of('Parent'), parentRef);
this.set(PDFName.Parent, parentRef);
}

addContentStream(contentStreamRef: PDFRef): void {
this.normalize();
let Contents = this.Contents();
if (!Contents) {
Contents = this.context.obj([]);
this.set(PDFName.of('Contents'), Contents);
}
(Contents as PDFArray).push(contentStreamRef);
const Contents = this.normalizedEntries().Contents || this.context.obj([]);
this.set(PDFName.Contents, Contents);
Contents.push(contentStreamRef);
}

wrapContentStreams(startStream: PDFRef, endStream: PDFRef): boolean {
const contents = this.lookup(PDFName.of('Contents'));
if (contents instanceof PDFArray) {
contents.insert(0, startStream);
contents.push(endStream);
const Contents = this.Contents();
if (Contents instanceof PDFArray) {
Contents.insert(0, startStream);
Contents.push(endStream);
return true;
}
return false;
}

setFontDictionary(name: PDFName, fontDictRef: PDFRef): void {
this.normalize();
const Font = this.Resources().lookup(PDFName.of('Font'), PDFDict);
const { Font } = this.normalizedEntries();
Font.set(name, fontDictRef);
}

setXObject(name: PDFName, xObjectRef: PDFRef): void {
this.normalize();
const XObject = this.Resources().lookup(PDFName.of('XObject'), PDFDict);
const { XObject } = this.normalizedEntries();
XObject.set(name, xObjectRef);
}

Expand All @@ -150,15 +144,15 @@ class PDFPageLeaf extends PDFDict {
if (Parent) Parent.ascend(visitor);
}

normalize(): void {
normalize() {
if (this.normalized) return;

const { context } = this;

const contentsRef = this.get(PDFName.of('Contents'));
const contentsRef = this.get(PDFName.Contents);
const contents = this.context.lookup(contentsRef);
if (contents instanceof PDFStream) {
this.set(PDFName.of('Contents'), context.obj([contentsRef]));
this.set(PDFName.Contents, context.obj([contentsRef]));
}

if (this.autoNormalizeCTM) {
Expand All @@ -168,19 +162,36 @@ class PDFPageLeaf extends PDFDict {
);
}

const Resources = this.get(PDFName.of('Resources'))
? this.Resources()
: context.obj({});
this.set(PDFName.of('Resources'), Resources);
// TODO: Clone `Resources` if it is inherited
const dictOrRef = this.getInheritableAttribute(PDFName.Resources);
const Resources =
context.lookupMaybe(dictOrRef, PDFDict) || context.obj({});
this.set(PDFName.Resources, Resources);

const Font = Resources.lookup(PDFName.of('Font')) || context.obj({});
Resources.set(PDFName.of('Font'), Font);
// TODO: Clone `Font` if it is inherited
const Font =
Resources.lookupMaybe(PDFName.Font, PDFDict) || context.obj({});
Resources.set(PDFName.Font, Font);

const XObject = Resources.lookup(PDFName.of('XObject')) || context.obj({});
Resources.set(PDFName.of('XObject'), XObject);
// TODO: Clone `XObject` if it is inherited
const XObject =
Resources.lookupMaybe(PDFName.XObject, PDFDict) || context.obj({});
Resources.set(PDFName.XObject, XObject);

this.normalized = true;
}

normalizedEntries() {
this.normalize();
const Resources = this.Resources()!;
const Contents = this.Contents() as PDFArray | undefined;
return {
Resources,
Contents,
Font: Resources.lookup(PDFName.Font, PDFDict),
XObject: Resources.lookup(PDFName.XObject, PDFDict),
};
}
}

export default PDFPageLeaf;
Loading

0 comments on commit 4a3d795

Please sign in to comment.