| 33 | |
| 34 | class PDFObject { |
| 35 | static convert(object) { |
| 36 | // String literals are converted to the PDF name type |
| 37 | if (typeof object === 'string') { |
| 38 | return `/${object}`; |
| 39 | } |
| 40 | |
| 41 | // String objects are converted to PDF strings (UTF-16) |
| 42 | if (object instanceof String) { |
| 43 | let string = object; |
| 44 | // Detect if this is a unicode string |
| 45 | let isUnicode = false; |
| 46 | for (let i = 0, end = string.length; i < end; i++) { |
| 47 | if (string.charCodeAt(i) > 0x7f) { |
| 48 | isUnicode = true; |
| 49 | break; |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | // If so, encode it as big endian UTF-16 |
| 54 | if (isUnicode) { |
| 55 | string = swapBytes(Buffer.from(`\ufeff${string}`, 'utf16le')).toString( |
| 56 | 'binary' |
| 57 | ); |
| 58 | } |
| 59 | |
| 60 | // Escape characters as required by the spec |
| 61 | string = string.replace(escapableRe, c => escapable[c]); |
| 62 | |
| 63 | return `(${string})`; |
| 64 | |
| 65 | // Buffers are converted to PDF hex strings |
| 66 | } |
| 67 | |
| 68 | if (Buffer.isBuffer(object)) { |
| 69 | return `<${object.toString('hex')}>`; |
| 70 | } |
| 71 | |
| 72 | if (object instanceof PDFReference || object instanceof PDFNameTree) { |
| 73 | return object.toString(); |
| 74 | } |
| 75 | |
| 76 | if (object instanceof Date) { |
| 77 | return ( |
| 78 | `(D:${pad(object.getUTCFullYear(), 4)}` + |
| 79 | pad(object.getUTCMonth() + 1, 2) + |
| 80 | pad(object.getUTCDate(), 2) + |
| 81 | pad(object.getUTCHours(), 2) + |
| 82 | pad(object.getUTCMinutes(), 2) + |
| 83 | pad(object.getUTCSeconds(), 2) + |
| 84 | 'Z)' |
| 85 | ); |
| 86 | } |
| 87 | |
| 88 | if (Array.isArray(object)) { |
| 89 | const items = Array.from(object) |
| 90 | .map(e => PDFObject.convert(e)) |
| 91 | .join(' '); |
| 92 | return `[${items}]`; |