UNPKG

pdf-lib

Version:

Create and modify PDF files with JavaScript

186 lines (158 loc) 5.85 kB
import PDFBool from 'src/core/objects/PDFBool'; import PDFDict from 'src/core/objects/PDFDict'; import PDFHexString from 'src/core/objects/PDFHexString'; import PDFName from 'src/core/objects/PDFName'; import PDFNull from 'src/core/objects/PDFNull'; import PDFNumber from 'src/core/objects/PDFNumber'; import PDFObject from 'src/core/objects/PDFObject'; import PDFRef from 'src/core/objects/PDFRef'; import PDFStream from 'src/core/objects/PDFStream'; import PDFString from 'src/core/objects/PDFString'; import PDFContext from 'src/core/PDFContext'; import CharCodes from 'src/core/syntax/CharCodes'; import { PDFArrayIsNotRectangleError } from 'src/core/errors'; import PDFRawStream from 'src/core/objects/PDFRawStream'; class PDFArray extends PDFObject { static withContext = (context: PDFContext) => new PDFArray(context); private readonly array: PDFObject[]; private readonly context: PDFContext; private constructor(context: PDFContext) { super(); this.array = []; this.context = context; } size(): number { return this.array.length; } push(object: PDFObject): void { this.array.push(object); } insert(index: number, object: PDFObject): void { this.array.splice(index, 0, object); } indexOf(object: PDFObject): number | undefined { const index = this.array.indexOf(object); return index === -1 ? undefined : index; } remove(index: number): void { this.array.splice(index, 1); } set(idx: number, object: PDFObject): void { this.array[idx] = object; } get(index: number): 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 PDFRawStream, ): PDFRawStream | undefined; lookupMaybe(index: number, type: typeof PDFRef): PDFRef | undefined; lookupMaybe(index: number, type: typeof PDFString): PDFString | undefined; lookupMaybe( index: number, type1: typeof PDFString, type2: typeof PDFHexString, ): PDFString | PDFHexString | undefined; lookupMaybe(index: number, ...types: any[]) { return this.context.lookupMaybe( this.get(index), // @ts-ignore ...types, ) as any; } lookup(index: number): PDFObject | undefined; lookup(index: number, type: typeof PDFArray): PDFArray; lookup(index: number, type: typeof PDFBool): PDFBool; lookup(index: number, type: typeof PDFDict): PDFDict; lookup(index: number, type: typeof PDFHexString): PDFHexString; lookup(index: number, type: typeof PDFName): PDFName; lookup(index: number, type: typeof PDFNull): typeof PDFNull; lookup(index: number, type: typeof PDFNumber): PDFNumber; lookup(index: number, type: typeof PDFStream): PDFStream; lookup(index: number, type: typeof PDFRawStream): PDFRawStream; lookup(index: number, type: typeof PDFRef): PDFRef; lookup(index: number, type: typeof PDFString): PDFString; lookup( index: number, type1: typeof PDFString, type2: typeof PDFHexString, ): PDFString | PDFHexString; lookup(index: number, ...types: any[]) { return this.context.lookup( this.get(index), // @ts-ignore ...types, ) as any; } asRectangle(): { x: number; y: number; width: number; height: number } { if (this.size() !== 4) throw new PDFArrayIsNotRectangleError(this.size()); 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; const width = upperRightX - lowerLeftX; const height = upperRightY - lowerLeftY; 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++) { clone.push(this.array[idx]); } return clone; } toString(): string { let arrayString = '[ '; for (let idx = 0, len = this.size(); idx < len; idx++) { arrayString += this.get(idx).toString(); arrayString += ' '; } arrayString += ']'; return arrayString; } sizeInBytes(): number { let size = 3; for (let idx = 0, len = this.size(); idx < len; idx++) { size += this.get(idx).sizeInBytes() + 1; } return size; } copyBytesInto(buffer: Uint8Array, offset: number): number { const initialOffset = offset; buffer[offset++] = CharCodes.LeftSquareBracket; buffer[offset++] = CharCodes.Space; for (let idx = 0, len = this.size(); idx < len; idx++) { offset += this.get(idx).copyBytesInto(buffer, offset); buffer[offset++] = CharCodes.Space; } buffer[offset++] = CharCodes.RightSquareBracket; return offset - initialOffset; } scalePDFNumbers(x: number, y: number): void { for (let idx = 0, len = this.size(); idx < len; idx++) { const el = this.lookup(idx); if (el instanceof PDFNumber) { const factor = idx % 2 === 0 ? x : y; this.set(idx, PDFNumber.of(el.asNumber() * factor)); } } } } export default PDFArray;