reamkit 0.1.0-alpha.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +107 -30
- package/dist/esm/{bidi → core/bidi}/algorithm.js +1 -1
- package/dist/esm/{bidi → core/bidi}/char-types.js +1 -1
- package/dist/esm/{bidi → core/bidi}/index.d.ts +2 -0
- package/dist/esm/{bidi → core/bidi}/index.js +2 -1
- package/dist/esm/core/bidi/segments.d.ts +6 -0
- package/dist/esm/core/bidi/segments.js +41 -0
- package/dist/esm/core/bytes.d.ts +1 -0
- package/dist/esm/core/bytes.js +11 -0
- package/dist/esm/core/converter/facade.d.ts +45 -0
- package/dist/esm/core/converter/facade.js +89 -0
- package/dist/esm/core/converter/index.d.ts +4 -0
- package/dist/esm/core/converter/project.d.ts +4 -0
- package/dist/esm/core/converter/project.js +17 -0
- package/dist/esm/core/converter/ream.d.ts +35 -0
- package/dist/esm/core/converter/ream.js +101 -0
- package/dist/esm/{crypto → core/crypto}/asn1.js +1 -1
- package/dist/esm/{crypto → core/crypto}/cms.js +1 -1
- package/dist/esm/core/document-model/index.d.ts +1 -0
- package/dist/esm/{document-model → core/document-model}/types.d.ts +57 -41
- package/dist/esm/{ooxml → core}/drawingml/chart-parser.d.ts +1 -1
- package/dist/esm/{ooxml → core}/drawingml/chart-parser.js +6 -29
- package/dist/esm/{ooxml → core}/drawingml/colors.d.ts +3 -0
- package/dist/esm/{ooxml → core}/drawingml/colors.js +32 -2
- package/dist/esm/{ooxml → core}/drawingml/theme-parser.js +2 -2
- package/dist/esm/{font → core/font}/arabic-joining.js +1 -1
- package/dist/esm/{font → core/font}/binary-reader.js +1 -1
- package/dist/esm/{font → core/font}/font-registry.d.ts +1 -0
- package/dist/esm/{font → core/font}/font-registry.js +17 -16
- package/dist/esm/{font → core/font}/index.d.ts +3 -0
- package/dist/esm/core/font/measure.d.ts +7 -0
- package/dist/esm/core/font/measure.js +30 -0
- package/dist/esm/{font → core/font}/opentype-layout.js +1 -1
- package/dist/esm/{font → core/font}/ttf-parser.js +1 -1
- package/dist/esm/{font → core/font}/ttf-subset.js +1 -1
- package/dist/esm/core/fonts/provider.d.ts +60 -0
- package/dist/esm/core/fonts/provider.js +163 -0
- package/dist/esm/{fonts → core/fonts}/remote-fonts.js +1 -1
- package/dist/esm/{hyphenation → core/hyphenation}/index.js +1 -1
- package/dist/esm/{hyphenation → core/hyphenation}/liang.js +1 -1
- package/dist/esm/{hyphenation → core/hyphenation}/patterns-en-us.js +1 -1
- package/dist/esm/{hyphenation → core/hyphenation}/patterns-ru.js +1 -1
- package/dist/esm/core/images.d.ts +17 -0
- package/dist/esm/core/images.js +308 -0
- package/dist/esm/core/ir/adapters.d.ts +37 -0
- package/dist/esm/core/ir/features.d.ts +25 -0
- package/dist/esm/core/ir/features.js +24 -0
- package/dist/esm/core/ir/flow.d.ts +24 -0
- package/dist/esm/core/ir/index.d.ts +11 -0
- package/dist/esm/core/ir/loss.d.ts +22 -0
- package/dist/esm/core/ir/loss.js +15 -0
- package/dist/esm/core/ir/resources.d.ts +16 -0
- package/dist/esm/core/ir/resources.js +50 -0
- package/dist/esm/core/ir/units.d.ts +16 -0
- package/dist/esm/core/ir/units.js +41 -0
- package/dist/esm/core/line-breaker/index.d.ts +2 -0
- package/dist/esm/{line-breaker → core/line-breaker}/knuth-plass.d.ts +1 -0
- package/dist/esm/{line-breaker → core/line-breaker}/knuth-plass.js +3 -3
- package/dist/esm/core/numbering/apply.d.ts +3 -0
- package/dist/esm/core/numbering/apply.js +62 -0
- package/dist/esm/core/numbering/index.d.ts +2 -0
- package/dist/esm/{numbering → core/numbering}/state.js +1 -1
- package/dist/esm/{opc → core/opc}/core-properties.js +1 -1
- package/dist/esm/{opc → core/opc}/package.d.ts +2 -1
- package/dist/esm/{opc → core/opc}/package.js +7 -3
- package/dist/esm/{opc → core/opc}/relationship-types.js +1 -1
- package/dist/esm/{opc → core/opc}/relationships.js +1 -1
- package/dist/esm/{ooxml/wordproc → core}/po-helpers.js +1 -1
- package/dist/esm/core/style-cascade/index.d.ts +3 -0
- package/dist/esm/core/style-cascade/index.js +2 -0
- package/dist/esm/core/style-cascade/resolver.d.ts +7 -0
- package/dist/esm/{style-cascade → core/style-cascade}/resolver.js +82 -10
- package/dist/esm/{style-cascade → core/style-cascade}/types.d.ts +10 -8
- package/dist/esm/{style-cascade → core/style-cascade}/types.js +9 -8
- package/dist/esm/core/vector.d.ts +45 -0
- package/dist/esm/core/vector.js +48 -0
- package/dist/esm/{ooxml/spreadsheet → excel}/cell-reference.js +1 -1
- package/dist/esm/{ooxml/spreadsheet → excel}/defined-name-ref.js +1 -1
- package/dist/esm/{ooxml/spreadsheet → excel}/index.d.ts +1 -1
- package/dist/esm/{ooxml/spreadsheet → excel}/number-format.js +1 -1
- package/dist/esm/excel/print-model.d.ts +18 -0
- package/dist/esm/{converter/xlsx-to-pdf.js → excel/print-model.js} +39 -148
- package/dist/esm/{ooxml/spreadsheet → excel}/shared-strings-parser.js +1 -1
- package/dist/esm/{ooxml/spreadsheet → excel}/styles-parser.js +1 -1
- package/dist/esm/{ooxml/spreadsheet → excel}/workbook-parser.js +1 -1
- package/dist/esm/{ooxml/spreadsheet → excel}/worksheet-parser.js +1 -1
- package/dist/esm/excel/xlsx-reader.d.ts +4 -0
- package/dist/esm/excel/xlsx-reader.js +91 -0
- package/dist/esm/{converter → excel}/xlsx-to-pdf.d.ts +13 -2
- package/dist/esm/excel/xlsx-to-pdf.js +69 -0
- package/dist/esm/index.d.ts +23 -8
- package/dist/esm/index.js +18 -10
- package/dist/esm/{pdf → layout}/arc-to-bezier.d.ts +1 -1
- package/dist/esm/{pdf → layout}/arc-to-bezier.js +2 -2
- package/dist/esm/{pdf → layout}/chart-geometry.d.ts +1 -1
- package/dist/esm/{pdf → layout}/math-layout.d.ts +2 -2
- package/dist/esm/{pdf → layout}/math-layout.js +1 -1
- package/dist/esm/layout/page-doc.d.ts +133 -0
- package/dist/esm/layout/page-doc.js +38 -0
- package/dist/esm/{pdf → layout}/preset-geometry.d.ts +2 -2
- package/dist/esm/{pdf → layout}/preset-geometry.js +2 -2
- package/dist/esm/layout/styled-layout.d.ts +84 -0
- package/dist/esm/layout/styled-layout.js +1729 -0
- package/dist/esm/pdf/cid-font.d.ts +1 -1
- package/dist/esm/pdf/cid-font.js +6 -21
- package/dist/esm/pdf/image-xobject.d.ts +4 -5
- package/dist/esm/pdf/image-xobject.js +21 -324
- package/dist/esm/pdf/index.d.ts +2 -2
- package/dist/esm/pdf/index.js +1 -0
- package/dist/esm/pdf/signature.js +4 -4
- package/dist/esm/pdf/styled-page-emitter.d.ts +11 -0
- package/dist/esm/pdf/styled-page-emitter.js +557 -0
- package/dist/esm/pdf/styled-page-renderer.d.ts +4 -42
- package/dist/esm/pdf/styled-page-renderer.js +4 -2311
- package/dist/esm/pdf/text-page-renderer.d.ts +1 -1
- package/dist/esm/pdf/vector-graphics.d.ts +3 -45
- package/dist/esm/pdf/vector-graphics.js +2 -46
- package/dist/esm/svg/svg-writer.d.ts +8 -0
- package/dist/esm/svg/svg-writer.js +137 -0
- package/dist/esm/word/document-parser.d.ts +16 -0
- package/dist/esm/{ooxml/wordproc → word}/document-parser.js +55 -47
- package/dist/esm/word/docx-reader.d.ts +4 -0
- package/dist/esm/word/docx-reader.js +191 -0
- package/dist/esm/word/docx-to-pdf.d.ts +34 -0
- package/dist/esm/word/docx-to-pdf.js +112 -0
- package/dist/esm/{ooxml/wordproc → word}/drawing-parser.d.ts +10 -9
- package/dist/esm/{ooxml/wordproc → word}/drawing-parser.js +15 -42
- package/dist/esm/{ooxml/wordproc → word}/font-table.d.ts +2 -2
- package/dist/esm/{ooxml/wordproc → word}/font-table.js +2 -2
- package/dist/esm/{ooxml/wordproc → word}/index.d.ts +3 -2
- package/dist/esm/{ooxml/wordproc → word}/numbering-parser.d.ts +1 -1
- package/dist/esm/{ooxml/wordproc → word}/numbering-parser.js +1 -1
- package/dist/esm/{ooxml/math → word}/omml-parser.d.ts +2 -2
- package/dist/esm/{ooxml/math → word}/omml-parser.js +2 -2
- package/dist/esm/{ooxml/wordproc → word}/paragraph-properties.d.ts +1 -1
- package/dist/esm/{ooxml/wordproc → word}/paragraph-properties.js +9 -8
- package/dist/esm/{ooxml/wordproc → word}/po-to-flat.d.ts +1 -1
- package/dist/esm/{ooxml/wordproc → word}/po-to-flat.js +2 -2
- package/dist/esm/{ooxml/wordproc → word}/run-properties.d.ts +1 -1
- package/dist/esm/{ooxml/wordproc → word}/run-properties.js +3 -2
- package/dist/esm/{ooxml/wordproc → word}/settings-parser.js +2 -2
- package/dist/esm/word/styles-parser.d.ts +2 -0
- package/dist/esm/{ooxml/wordproc → word}/styles-parser.js +4 -7
- package/dist/esm/word/table-parser.d.ts +4 -0
- package/dist/esm/{ooxml/wordproc → word}/table-parser.js +80 -26
- package/dist/esm/{ooxml/wordproc → word}/xml-helpers.js +1 -1
- package/package.json +5 -6
- package/dist/esm/converter/docx-to-pdf.d.ts +0 -15
- package/dist/esm/converter/docx-to-pdf.js +0 -227
- package/dist/esm/converter/index.d.ts +0 -4
- package/dist/esm/converter/index.js +0 -2
- package/dist/esm/document-model/index.d.ts +0 -1
- package/dist/esm/line-breaker/index.d.ts +0 -2
- package/dist/esm/numbering/index.d.ts +0 -1
- package/dist/esm/ooxml/index.d.ts +0 -1
- package/dist/esm/ooxml/wordproc/document-parser.d.ts +0 -9
- package/dist/esm/ooxml/wordproc/styles-parser.d.ts +0 -3
- package/dist/esm/ooxml/wordproc/table-parser.d.ts +0 -3
- package/dist/esm/style-cascade/index.d.ts +0 -3
- package/dist/esm/style-cascade/resolver.d.ts +0 -4
- /package/dist/esm/{bidi → core/bidi}/algorithm.d.ts +0 -0
- /package/dist/esm/{bidi → core/bidi}/char-types.d.ts +0 -0
- /package/dist/esm/{crypto → core/crypto}/asn1.d.ts +0 -0
- /package/dist/esm/{crypto → core/crypto}/cms.d.ts +0 -0
- /package/dist/esm/{crypto → core/crypto}/index.d.ts +0 -0
- /package/dist/esm/{crypto → core/crypto}/index.js +0 -0
- /package/dist/esm/{document-model → core/document-model}/index.js +0 -0
- /package/dist/esm/{ooxml → core}/drawingml/theme-parser.d.ts +0 -0
- /package/dist/esm/{font → core/font}/arabic-joining.d.ts +0 -0
- /package/dist/esm/{font → core/font}/binary-reader.d.ts +0 -0
- /package/dist/esm/{font → core/font}/opentype-layout.d.ts +0 -0
- /package/dist/esm/{font → core/font}/ttf-parser.d.ts +0 -0
- /package/dist/esm/{font → core/font}/ttf-subset.d.ts +0 -0
- /package/dist/esm/{fonts → core/fonts}/index.d.ts +0 -0
- /package/dist/esm/{fonts → core/fonts}/remote-fonts.d.ts +0 -0
- /package/dist/esm/{hyphenation → core/hyphenation}/index.d.ts +0 -0
- /package/dist/esm/{hyphenation → core/hyphenation}/liang.d.ts +0 -0
- /package/dist/esm/{hyphenation → core/hyphenation}/patterns-en-us.d.ts +0 -0
- /package/dist/esm/{hyphenation → core/hyphenation}/patterns-ru.d.ts +0 -0
- /package/dist/esm/{numbering → core/numbering}/state.d.ts +0 -0
- /package/dist/esm/{opc → core/opc}/core-properties.d.ts +0 -0
- /package/dist/esm/{opc → core/opc}/index.d.ts +0 -0
- /package/dist/esm/{opc → core/opc}/index.js +0 -0
- /package/dist/esm/{opc → core/opc}/relationship-types.d.ts +0 -0
- /package/dist/esm/{opc → core/opc}/relationships.d.ts +0 -0
- /package/dist/esm/{ooxml/wordproc → core}/po-helpers.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/cell-reference.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/defined-name-ref.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/index.js +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/number-format.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/shared-strings-parser.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/styles-parser.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/workbook-parser.d.ts +0 -0
- /package/dist/esm/{ooxml/spreadsheet → excel}/worksheet-parser.d.ts +0 -0
- /package/dist/esm/{pdf → layout}/chart-geometry.js +0 -0
- /package/dist/esm/{ooxml/wordproc → word}/index.js +0 -0
- /package/dist/esm/{ooxml/wordproc → word}/settings-parser.d.ts +0 -0
- /package/dist/esm/{ooxml/wordproc → word}/text-extractor.d.ts +0 -0
- /package/dist/esm/{ooxml/wordproc → word}/text-extractor.js +0 -0
- /package/dist/esm/{ooxml/wordproc → word}/xml-helpers.d.ts +0 -0
package/dist/esm/pdf/cid-font.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { glyphClosure, subsetTtf } from "../core/font/ttf-subset.js";
|
|
2
|
+
import { createFontMeasure } from "../core/font/measure.js";
|
|
3
3
|
import { dict, name, ref, stream } from "./objects.js";
|
|
4
4
|
//#region src/pdf/cid-font.ts
|
|
5
5
|
var encoder = new TextEncoder();
|
|
@@ -55,28 +55,13 @@ function embedTtfFont(doc, parsed, options = {}) {
|
|
|
55
55
|
DescendantFonts: [ref(cidFontRef.id)],
|
|
56
56
|
ToUnicode: ref(toUnicodeRef.id)
|
|
57
57
|
}));
|
|
58
|
-
const
|
|
59
|
-
if (gid < 0 || gid >= parsed.numGlyphs) return 1e3;
|
|
60
|
-
return widths[gid];
|
|
61
|
-
};
|
|
62
|
-
const textWidthPt = (text, fontSize) => {
|
|
63
|
-
const shaped = shapeText(text, parsed.glyphForCodepoint, parsed.advanceWidths, parsed.ligatures, parsed.kerning, parsed.joiningForms);
|
|
64
|
-
let totalEm = 0;
|
|
65
|
-
for (const a of shaped.advances) totalEm += a;
|
|
66
|
-
return totalEm * fontSize / parsed.unitsPerEm;
|
|
67
|
-
};
|
|
68
|
-
const encodeTextAsCidHexFn = (text) => {
|
|
69
|
-
const shaped = shapeText(text, parsed.glyphForCodepoint, parsed.advanceWidths, parsed.ligatures, parsed.kerning, parsed.joiningForms);
|
|
70
|
-
let out = "";
|
|
71
|
-
for (const gid of shaped.gids) out += gid.toString(16).padStart(4, "0").toUpperCase();
|
|
72
|
-
return out;
|
|
73
|
-
};
|
|
58
|
+
const measure = createFontMeasure(parsed);
|
|
74
59
|
return {
|
|
75
60
|
fontRef: type0Ref,
|
|
76
61
|
parsed,
|
|
77
|
-
pdfWidthForGid,
|
|
78
|
-
textWidthPt,
|
|
79
|
-
encodeTextAsCidHex:
|
|
62
|
+
pdfWidthForGid: measure.pdfWidthForGid,
|
|
63
|
+
textWidthPt: measure.textWidthPt,
|
|
64
|
+
encodeTextAsCidHex: measure.encodeTextAsCidHex
|
|
80
65
|
};
|
|
81
66
|
}
|
|
82
67
|
function buildCidSet(cids) {
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { PdfRef } from './objects.js';
|
|
2
2
|
import { PdfDocument } from './writer.js';
|
|
3
|
-
|
|
3
|
+
import { EmbedImageOptions, PreparedImage } from '../core/images.js';
|
|
4
|
+
export { detectImageFormat, prepareImage } from '../core/images.js';
|
|
5
|
+
export type { EmbedImageOptions, ImageFormat, PreparedImage } from '../core/images.js';
|
|
4
6
|
export interface EmbeddedImage {
|
|
5
7
|
readonly ref: PdfRef;
|
|
6
8
|
readonly widthPx: number;
|
|
7
9
|
readonly heightPx: number;
|
|
8
10
|
}
|
|
9
|
-
export declare function
|
|
10
|
-
export interface EmbedImageOptions {
|
|
11
|
-
readonly flattenAlpha?: boolean;
|
|
12
|
-
}
|
|
11
|
+
export declare function addImage(doc: PdfDocument, prepared: PreparedImage): EmbeddedImage;
|
|
13
12
|
export declare function embedImage(doc: PdfDocument, bytes: Uint8Array, options?: EmbedImageOptions): EmbeddedImage;
|
|
@@ -1,335 +1,32 @@
|
|
|
1
1
|
import { name, stream } from "./objects.js";
|
|
2
|
-
import
|
|
2
|
+
import "../core/images.js";
|
|
3
3
|
//#region src/pdf/image-xobject.ts
|
|
4
|
-
function
|
|
5
|
-
|
|
6
|
-
if (
|
|
7
|
-
if (bytes.length >= 12 && bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 0 && bytes[3] === 12 && bytes[4] === 106 && bytes[5] === 80 && bytes[6] === 32 && bytes[7] === 32 && bytes[8] === 13 && bytes[9] === 10 && bytes[10] === 135 && bytes[11] === 10) return "jpeg2000";
|
|
8
|
-
if (bytes.length >= 4 && bytes[0] === 255 && bytes[1] === 79 && bytes[2] === 255 && bytes[3] === 81) return "jpeg2000";
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
function embedImage(doc, bytes, options = {}) {
|
|
12
|
-
const format = detectImageFormat(bytes);
|
|
13
|
-
if (format === "jpeg") return embedJpeg(doc, bytes);
|
|
14
|
-
if (format === "png") return embedPng(doc, bytes, options);
|
|
15
|
-
if (format === "jpeg2000") return embedJpeg2000(doc, bytes);
|
|
16
|
-
throw new Error("Unsupported image format");
|
|
17
|
-
}
|
|
18
|
-
function embedJpeg2000(doc, bytes) {
|
|
19
|
-
const { width, height } = readJpeg2000Info(bytes);
|
|
20
|
-
return {
|
|
21
|
-
ref: doc.add(stream({
|
|
22
|
-
Type: name("XObject"),
|
|
23
|
-
Subtype: name("Image"),
|
|
24
|
-
Width: width,
|
|
25
|
-
Height: height,
|
|
26
|
-
Filter: name("JPXDecode")
|
|
27
|
-
}, bytes)),
|
|
28
|
-
widthPx: width,
|
|
29
|
-
heightPx: height
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
function readU32(b, o) {
|
|
33
|
-
return b[o] * 16777216 + (b[o + 1] << 16) + (b[o + 2] << 8) + b[o + 3];
|
|
34
|
-
}
|
|
35
|
-
var boxType = (b, o) => String.fromCharCode(b[o], b[o + 1], b[o + 2], b[o + 3]);
|
|
36
|
-
function readJpeg2000Info(bytes) {
|
|
37
|
-
if (bytes[0] === 255 && bytes[1] === 79) return readSiz(bytes, 2);
|
|
38
|
-
let p = 0;
|
|
39
|
-
while (p + 8 <= bytes.length) {
|
|
40
|
-
let len = readU32(bytes, p);
|
|
41
|
-
const type = boxType(bytes, p + 4);
|
|
42
|
-
let contentStart = p + 8;
|
|
43
|
-
if (len === 1) {
|
|
44
|
-
len = readU32(bytes, p + 12);
|
|
45
|
-
contentStart = p + 16;
|
|
46
|
-
}
|
|
47
|
-
const end = len === 0 ? bytes.length : p + len;
|
|
48
|
-
if (type === "jp2h") {
|
|
49
|
-
let q = contentStart;
|
|
50
|
-
while (q + 8 <= end) {
|
|
51
|
-
const clen = readU32(bytes, q);
|
|
52
|
-
if (boxType(bytes, q + 4) === "ihdr") return {
|
|
53
|
-
height: readU32(bytes, q + 8),
|
|
54
|
-
width: readU32(bytes, q + 12)
|
|
55
|
-
};
|
|
56
|
-
if (clen === 0) break;
|
|
57
|
-
q += clen;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
if (len === 0) break;
|
|
61
|
-
p = end;
|
|
62
|
-
}
|
|
63
|
-
for (let i = 0; i + 22 < bytes.length; i++) if (bytes[i] === 255 && bytes[i + 1] === 81) return readSiz(bytes, i);
|
|
64
|
-
throw new Error("JPEG 2000: no ihdr/SIZ found");
|
|
65
|
-
}
|
|
66
|
-
function readSiz(bytes, sizOffset) {
|
|
67
|
-
const xsiz = readU32(bytes, sizOffset + 6);
|
|
68
|
-
const ysiz = readU32(bytes, sizOffset + 10);
|
|
69
|
-
const xo = readU32(bytes, sizOffset + 14);
|
|
70
|
-
const yo = readU32(bytes, sizOffset + 18);
|
|
71
|
-
const width = xsiz - xo;
|
|
72
|
-
const height = ysiz - yo;
|
|
73
|
-
if (width <= 0 || height <= 0) throw new Error("JPEG 2000: invalid SIZ dimensions");
|
|
74
|
-
return {
|
|
75
|
-
width,
|
|
76
|
-
height
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
function embedJpeg(doc, bytes) {
|
|
80
|
-
const info = readJpegInfo(bytes);
|
|
81
|
-
const colorSpace = info.numComponents === 1 ? "DeviceGray" : "DeviceRGB";
|
|
82
|
-
return {
|
|
83
|
-
ref: doc.add(stream({
|
|
84
|
-
Type: name("XObject"),
|
|
85
|
-
Subtype: name("Image"),
|
|
86
|
-
Width: info.width,
|
|
87
|
-
Height: info.height,
|
|
88
|
-
ColorSpace: name(colorSpace),
|
|
89
|
-
BitsPerComponent: info.precision,
|
|
90
|
-
Filter: name("DCTDecode")
|
|
91
|
-
}, bytes)),
|
|
92
|
-
widthPx: info.width,
|
|
93
|
-
heightPx: info.height
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
function readJpegInfo(bytes) {
|
|
97
|
-
if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216) throw new Error("Not a JPEG (missing SOI)");
|
|
98
|
-
let i = 2;
|
|
99
|
-
while (i + 9 < bytes.length) {
|
|
100
|
-
if (bytes[i] !== 255) {
|
|
101
|
-
i++;
|
|
102
|
-
continue;
|
|
103
|
-
}
|
|
104
|
-
let marker = bytes[i + 1];
|
|
105
|
-
while (marker === 255) {
|
|
106
|
-
i++;
|
|
107
|
-
marker = bytes[i + 1];
|
|
108
|
-
}
|
|
109
|
-
if (marker === 1 || marker >= 208 && marker <= 217) {
|
|
110
|
-
i += 2;
|
|
111
|
-
continue;
|
|
112
|
-
}
|
|
113
|
-
if (marker >= 192 && marker <= 207 && marker !== 196 && marker !== 200 && marker !== 204) return {
|
|
114
|
-
precision: bytes[i + 4],
|
|
115
|
-
height: bytes[i + 5] << 8 | bytes[i + 6],
|
|
116
|
-
width: bytes[i + 7] << 8 | bytes[i + 8],
|
|
117
|
-
numComponents: bytes[i + 9]
|
|
118
|
-
};
|
|
119
|
-
const length = bytes[i + 2] << 8 | bytes[i + 3];
|
|
120
|
-
i += 2 + length;
|
|
121
|
-
}
|
|
122
|
-
throw new Error("JPEG SOFn marker not found");
|
|
123
|
-
}
|
|
124
|
-
function embedPng(doc, bytes, options = {}) {
|
|
125
|
-
let decoded = decodePng(bytes);
|
|
126
|
-
if (options.flattenAlpha && decoded.smaskRaw) decoded = flattenAlphaOnWhite(decoded);
|
|
127
|
-
const compressedColor = zlibSync(decoded.raw);
|
|
128
|
-
const baseDict = {
|
|
4
|
+
function addImage(doc, prepared) {
|
|
5
|
+
let smaskRef;
|
|
6
|
+
if (prepared.smaskData) smaskRef = doc.add(stream({
|
|
129
7
|
Type: name("XObject"),
|
|
130
8
|
Subtype: name("Image"),
|
|
131
|
-
Width:
|
|
132
|
-
Height:
|
|
133
|
-
ColorSpace: name(
|
|
134
|
-
BitsPerComponent:
|
|
9
|
+
Width: prepared.widthPx,
|
|
10
|
+
Height: prepared.heightPx,
|
|
11
|
+
ColorSpace: name("DeviceGray"),
|
|
12
|
+
BitsPerComponent: 8,
|
|
135
13
|
Filter: name("FlateDecode")
|
|
14
|
+
}, prepared.smaskData));
|
|
15
|
+
const entries = {
|
|
16
|
+
Type: name("XObject"),
|
|
17
|
+
Subtype: name("Image"),
|
|
18
|
+
Width: prepared.widthPx,
|
|
19
|
+
Height: prepared.heightPx,
|
|
20
|
+
...prepared.colorSpace ? { ColorSpace: name(prepared.colorSpace) } : {},
|
|
21
|
+
...prepared.bitsPerComponent !== void 0 ? { BitsPerComponent: prepared.bitsPerComponent } : {},
|
|
22
|
+
Filter: name(prepared.filter)
|
|
136
23
|
};
|
|
137
|
-
let smaskRef;
|
|
138
|
-
if (decoded.smaskRaw) {
|
|
139
|
-
const compressedAlpha = zlibSync(decoded.smaskRaw);
|
|
140
|
-
smaskRef = doc.add(stream({
|
|
141
|
-
Type: name("XObject"),
|
|
142
|
-
Subtype: name("Image"),
|
|
143
|
-
Width: decoded.width,
|
|
144
|
-
Height: decoded.height,
|
|
145
|
-
ColorSpace: name("DeviceGray"),
|
|
146
|
-
BitsPerComponent: 8,
|
|
147
|
-
Filter: name("FlateDecode")
|
|
148
|
-
}, compressedAlpha));
|
|
149
|
-
}
|
|
150
|
-
const entries = { ...baseDict };
|
|
151
24
|
if (smaskRef) entries["SMask"] = smaskRef;
|
|
152
25
|
return {
|
|
153
|
-
ref: doc.add(stream(entries,
|
|
154
|
-
widthPx:
|
|
155
|
-
heightPx:
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
function decodePng(bytes) {
|
|
159
|
-
let width = 0;
|
|
160
|
-
let height = 0;
|
|
161
|
-
let bitDepth = 0;
|
|
162
|
-
let colorType = 0;
|
|
163
|
-
let interlaceMethod = 0;
|
|
164
|
-
const idatChunks = [];
|
|
165
|
-
let pos = 8;
|
|
166
|
-
while (pos + 12 <= bytes.length) {
|
|
167
|
-
const len = readU32BE(bytes, pos);
|
|
168
|
-
const type = chunkType(bytes, pos + 4);
|
|
169
|
-
const dataOff = pos + 8;
|
|
170
|
-
if (type === "IHDR") {
|
|
171
|
-
width = readU32BE(bytes, dataOff);
|
|
172
|
-
height = readU32BE(bytes, dataOff + 4);
|
|
173
|
-
bitDepth = bytes[dataOff + 8];
|
|
174
|
-
colorType = bytes[dataOff + 9];
|
|
175
|
-
interlaceMethod = bytes[dataOff + 12];
|
|
176
|
-
} else if (type === "IDAT") idatChunks.push(bytes.subarray(dataOff, dataOff + len));
|
|
177
|
-
else if (type === "IEND") break;
|
|
178
|
-
pos = dataOff + len + 4;
|
|
179
|
-
}
|
|
180
|
-
if (width === 0 || height === 0) throw new Error("PNG: missing IHDR");
|
|
181
|
-
if (idatChunks.length === 0) throw new Error("PNG: no IDAT");
|
|
182
|
-
if (interlaceMethod !== 0) throw new Error("PNG: interlaced not supported");
|
|
183
|
-
if (bitDepth !== 8) throw new Error(`PNG: bit depth ${bitDepth} not supported`);
|
|
184
|
-
const inflated = unzlibSync(concatBytes(idatChunks));
|
|
185
|
-
const channels = pngChannels(colorType);
|
|
186
|
-
if (channels === 0) throw new Error(`PNG color type ${colorType} not supported`);
|
|
187
|
-
const bpp = channels;
|
|
188
|
-
const scanlineBytes = width * bpp;
|
|
189
|
-
const expected = height * (1 + scanlineBytes);
|
|
190
|
-
if (inflated.length !== expected) throw new Error(`PNG: inflated size ${inflated.length} != expected ${expected} (interlaced or malformed)`);
|
|
191
|
-
const raw = new Uint8Array(height * scanlineBytes);
|
|
192
|
-
let prev = null;
|
|
193
|
-
for (let y = 0; y < height; y++) {
|
|
194
|
-
const inOff = y * (1 + scanlineBytes);
|
|
195
|
-
const filterType = inflated[inOff];
|
|
196
|
-
const decoded = new Uint8Array(scanlineBytes);
|
|
197
|
-
for (let x = 0; x < scanlineBytes; x++) {
|
|
198
|
-
const filt = inflated[inOff + 1 + x];
|
|
199
|
-
const a = x < bpp ? 0 : decoded[x - bpp];
|
|
200
|
-
const b = prev ? prev[x] : 0;
|
|
201
|
-
const c = !prev || x < bpp ? 0 : prev[x - bpp];
|
|
202
|
-
let v;
|
|
203
|
-
switch (filterType) {
|
|
204
|
-
case 0:
|
|
205
|
-
v = filt;
|
|
206
|
-
break;
|
|
207
|
-
case 1:
|
|
208
|
-
v = filt + a;
|
|
209
|
-
break;
|
|
210
|
-
case 2:
|
|
211
|
-
v = filt + b;
|
|
212
|
-
break;
|
|
213
|
-
case 3:
|
|
214
|
-
v = filt + Math.floor((a + b) / 2);
|
|
215
|
-
break;
|
|
216
|
-
case 4:
|
|
217
|
-
v = filt + paethPredictor(a, b, c);
|
|
218
|
-
break;
|
|
219
|
-
default: throw new Error(`PNG: unknown filter type ${filterType}`);
|
|
220
|
-
}
|
|
221
|
-
decoded[x] = v & 255;
|
|
222
|
-
}
|
|
223
|
-
raw.set(decoded, y * scanlineBytes);
|
|
224
|
-
prev = decoded;
|
|
225
|
-
}
|
|
226
|
-
return splitChannels(width, height, colorType, raw);
|
|
227
|
-
}
|
|
228
|
-
function flattenAlphaOnWhite(decoded) {
|
|
229
|
-
const alpha = decoded.smaskRaw;
|
|
230
|
-
if (!alpha) return decoded;
|
|
231
|
-
const channels = decoded.colorSpace === "DeviceRGB" ? 3 : 1;
|
|
232
|
-
const pixelCount = decoded.width * decoded.height;
|
|
233
|
-
const out = new Uint8Array(pixelCount * channels);
|
|
234
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
235
|
-
const a = alpha[i] / 255;
|
|
236
|
-
for (let c = 0; c < channels; c++) {
|
|
237
|
-
const src = decoded.raw[i * channels + c];
|
|
238
|
-
out[i * channels + c] = Math.round(src * a + 255 * (1 - a));
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
return {
|
|
242
|
-
width: decoded.width,
|
|
243
|
-
height: decoded.height,
|
|
244
|
-
raw: out,
|
|
245
|
-
colorSpace: decoded.colorSpace,
|
|
246
|
-
bitsPerComponent: decoded.bitsPerComponent
|
|
26
|
+
ref: doc.add(stream(entries, prepared.data)),
|
|
27
|
+
widthPx: prepared.widthPx,
|
|
28
|
+
heightPx: prepared.heightPx
|
|
247
29
|
};
|
|
248
30
|
}
|
|
249
|
-
function splitChannels(width, height, colorType, raw) {
|
|
250
|
-
const pixelCount = width * height;
|
|
251
|
-
if (colorType === 0) return {
|
|
252
|
-
width,
|
|
253
|
-
height,
|
|
254
|
-
raw,
|
|
255
|
-
colorSpace: "DeviceGray",
|
|
256
|
-
bitsPerComponent: 8
|
|
257
|
-
};
|
|
258
|
-
if (colorType === 2) return {
|
|
259
|
-
width,
|
|
260
|
-
height,
|
|
261
|
-
raw,
|
|
262
|
-
colorSpace: "DeviceRGB",
|
|
263
|
-
bitsPerComponent: 8
|
|
264
|
-
};
|
|
265
|
-
if (colorType === 4) {
|
|
266
|
-
const gray = new Uint8Array(pixelCount);
|
|
267
|
-
const alpha = new Uint8Array(pixelCount);
|
|
268
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
269
|
-
gray[i] = raw[i * 2];
|
|
270
|
-
alpha[i] = raw[i * 2 + 1];
|
|
271
|
-
}
|
|
272
|
-
return {
|
|
273
|
-
width,
|
|
274
|
-
height,
|
|
275
|
-
raw: gray,
|
|
276
|
-
colorSpace: "DeviceGray",
|
|
277
|
-
bitsPerComponent: 8,
|
|
278
|
-
smaskRaw: alpha
|
|
279
|
-
};
|
|
280
|
-
}
|
|
281
|
-
if (colorType === 6) {
|
|
282
|
-
const rgb = new Uint8Array(pixelCount * 3);
|
|
283
|
-
const alpha = new Uint8Array(pixelCount);
|
|
284
|
-
for (let i = 0; i < pixelCount; i++) {
|
|
285
|
-
rgb[i * 3] = raw[i * 4];
|
|
286
|
-
rgb[i * 3 + 1] = raw[i * 4 + 1];
|
|
287
|
-
rgb[i * 3 + 2] = raw[i * 4 + 2];
|
|
288
|
-
alpha[i] = raw[i * 4 + 3];
|
|
289
|
-
}
|
|
290
|
-
return {
|
|
291
|
-
width,
|
|
292
|
-
height,
|
|
293
|
-
raw: rgb,
|
|
294
|
-
colorSpace: "DeviceRGB",
|
|
295
|
-
bitsPerComponent: 8,
|
|
296
|
-
smaskRaw: alpha
|
|
297
|
-
};
|
|
298
|
-
}
|
|
299
|
-
throw new Error(`PNG color type ${colorType} not supported (palette/indexed?)`);
|
|
300
|
-
}
|
|
301
|
-
function pngChannels(colorType) {
|
|
302
|
-
if (colorType === 0) return 1;
|
|
303
|
-
if (colorType === 2) return 3;
|
|
304
|
-
if (colorType === 4) return 2;
|
|
305
|
-
if (colorType === 6) return 4;
|
|
306
|
-
return 0;
|
|
307
|
-
}
|
|
308
|
-
function paethPredictor(a, b, c) {
|
|
309
|
-
const p = a + b - c;
|
|
310
|
-
const pa = Math.abs(p - a);
|
|
311
|
-
const pb = Math.abs(p - b);
|
|
312
|
-
const pc = Math.abs(p - c);
|
|
313
|
-
if (pa <= pb && pa <= pc) return a;
|
|
314
|
-
if (pb <= pc) return b;
|
|
315
|
-
return c;
|
|
316
|
-
}
|
|
317
|
-
function readU32BE(bytes, offset) {
|
|
318
|
-
return bytes[offset] * 16777216 + (bytes[offset + 1] << 16 | bytes[offset + 2] << 8 | bytes[offset + 3]);
|
|
319
|
-
}
|
|
320
|
-
function chunkType(bytes, offset) {
|
|
321
|
-
return String.fromCharCode(bytes[offset], bytes[offset + 1], bytes[offset + 2], bytes[offset + 3]);
|
|
322
|
-
}
|
|
323
|
-
function concatBytes(parts) {
|
|
324
|
-
let total = 0;
|
|
325
|
-
for (const p of parts) total += p.length;
|
|
326
|
-
const out = new Uint8Array(total);
|
|
327
|
-
let off = 0;
|
|
328
|
-
for (const p of parts) {
|
|
329
|
-
out.set(p, off);
|
|
330
|
-
off += p.length;
|
|
331
|
-
}
|
|
332
|
-
return out;
|
|
333
|
-
}
|
|
334
31
|
//#endregion
|
|
335
|
-
export {
|
|
32
|
+
export { addImage };
|
package/dist/esm/pdf/index.d.ts
CHANGED
|
@@ -7,5 +7,5 @@ export type { SignaturePlaceholder, SignerCredentials, SignatureOptions } from '
|
|
|
7
7
|
export type { AttachedFile, AFRelationship } from './embedded-file.js';
|
|
8
8
|
export { embedTtfFont } from './cid-font.js';
|
|
9
9
|
export type { EmbeddedFont } from './cid-font.js';
|
|
10
|
-
export {
|
|
11
|
-
export type { EmbeddedImage, ImageFormat } from './image-xobject.js';
|
|
10
|
+
export { addImage, detectImageFormat, embedImage, prepareImage } from './image-xobject.js';
|
|
11
|
+
export type { EmbeddedImage, ImageFormat, PreparedImage } from './image-xobject.js';
|
package/dist/esm/pdf/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { PdfHexString, PdfRawToken, dict, name, ref } from "./objects.js";
|
|
2
|
-
import { integer, seq } from "../crypto/asn1.js";
|
|
3
|
-
import { buildPkcs7Detached } from "../crypto/cms.js";
|
|
4
|
-
import "../crypto/index.js";
|
|
2
|
+
import { integer, seq } from "../core/crypto/asn1.js";
|
|
3
|
+
import { buildPkcs7Detached } from "../core/crypto/cms.js";
|
|
4
|
+
import "../core/crypto/index.js";
|
|
5
5
|
//#region src/pdf/signature.ts
|
|
6
6
|
var BYTE_RANGE_PLACEHOLDER = "[0 0000000000 0000000000 0000000000]";
|
|
7
7
|
var DEFAULT_RESERVE_BYTES = 8192;
|
|
@@ -80,7 +80,7 @@ function toHex(bytes) {
|
|
|
80
80
|
}
|
|
81
81
|
async function signPdf(pdf, cred) {
|
|
82
82
|
const out = pdf.slice();
|
|
83
|
-
const brKey = indexOfAscii(out,
|
|
83
|
+
const brKey = indexOfAscii(out, `/ByteRange ${BYTE_RANGE_PLACEHOLDER}`);
|
|
84
84
|
if (brKey < 0) throw new Error("signPdf: no /ByteRange placeholder found");
|
|
85
85
|
const brOpen = indexOfAscii(out, "[", brKey);
|
|
86
86
|
const brClose = indexOfAscii(out, "]", brOpen);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LaidOutPdfDocument, StyledRenderOptions } from '../layout/styled-layout.js';
|
|
2
|
+
import { PdfDocument } from './writer.js';
|
|
3
|
+
type EmitOptions = Pick<StyledRenderOptions, 'attachments' | 'info' | 'language' | 'signaturePlaceholder'>;
|
|
4
|
+
export declare function emitStyledPdf(laid: LaidOutPdfDocument, options: EmitOptions, doc: PdfDocument): Uint8Array;
|
|
5
|
+
export interface PageTagging {
|
|
6
|
+
next: number;
|
|
7
|
+
assigned: boolean;
|
|
8
|
+
record: (structId: number, mcid: number) => void;
|
|
9
|
+
tagFor: (structId: number) => string;
|
|
10
|
+
}
|
|
11
|
+
export {};
|