reamkit 0.1.0-alpha.0 → 1.0.0
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 +106 -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.js +1 -1
- 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 +16 -0
- package/dist/esm/core/converter/ream.d.ts +35 -0
- package/dist/esm/core/converter/ream.js +100 -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 +1 -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/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.js +1 -1
- 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.js +1 -1
- 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/{style-cascade → core/style-cascade}/index.d.ts +2 -2
- package/dist/esm/core/style-cascade/index.js +2 -0
- package/dist/esm/{style-cascade → core/style-cascade}/resolver.d.ts +1 -0
- package/dist/esm/{style-cascade → core/style-cascade}/resolver.js +14 -9
- package/dist/esm/{style-cascade → core/style-cascade}/types.d.ts +8 -7
- package/dist/esm/{style-cascade → core/style-cascade}/types.js +9 -8
- 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 -11
- package/dist/esm/pdf/chart-geometry.d.ts +1 -1
- package/dist/esm/pdf/cid-font.d.ts +7 -1
- package/dist/esm/pdf/cid-font.js +33 -22
- package/dist/esm/pdf/image-xobject.d.ts +13 -0
- package/dist/esm/pdf/image-xobject.js +55 -54
- package/dist/esm/pdf/index.d.ts +2 -2
- package/dist/esm/pdf/math-layout.d.ts +1 -1
- package/dist/esm/pdf/preset-geometry.d.ts +1 -1
- package/dist/esm/pdf/signature.js +4 -4
- package/dist/esm/pdf/styled-page-emitter.d.ts +5 -0
- package/dist/esm/pdf/styled-page-emitter.js +542 -0
- package/dist/esm/pdf/styled-page-renderer.d.ts +189 -14
- package/dist/esm/pdf/styled-page-renderer.js +168 -654
- package/dist/esm/pdf/text-page-renderer.d.ts +1 -1
- package/dist/esm/svg/svg-writer.d.ts +8 -0
- package/dist/esm/svg/svg-writer.js +138 -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 +190 -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/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/{bidi → core/bidi}/algorithm.d.ts +0 -0
- /package/dist/esm/{bidi → core/bidi}/char-types.d.ts +0 -0
- /package/dist/esm/{bidi → core/bidi}/index.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/{line-breaker → core/line-breaker}/knuth-plass.d.ts +0 -0
- /package/dist/esm/{numbering → core/numbering}/index.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}/package.d.ts +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/{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
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { embedTtfFont } from "./cid-font.js";
|
|
1
|
+
import { resolveFamilyKey } from "../core/fonts/remote-fonts.js";
|
|
2
|
+
import { shapeText } from "../core/font/opentype-layout.js";
|
|
3
|
+
import { createFontMeasure } from "./cid-font.js";
|
|
5
4
|
import { PdfDocument } from "./writer.js";
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
5
|
+
import { halfPtToPt } from "../core/ir/units.js";
|
|
6
|
+
import { ResourceStore } from "../core/ir/resources.js";
|
|
7
|
+
import { computeBidi } from "../core/bidi/algorithm.js";
|
|
8
|
+
import { analyzeString, hasBidiCharacters } from "../core/bidi/index.js";
|
|
9
|
+
import { breakLines } from "../core/line-breaker/knuth-plass.js";
|
|
10
|
+
import { NumberingState } from "../core/numbering/state.js";
|
|
11
|
+
import { DEFAULT_RESOLVED_PARAGRAPH, DEFAULT_RESOLVED_RUN } from "../core/style-cascade/types.js";
|
|
12
|
+
import { resolveParagraphProperties, resolveRunProperties } from "../core/style-cascade/resolver.js";
|
|
13
|
+
import "../core/style-cascade/index.js";
|
|
14
|
+
import { PathBuilder } from "./vector-graphics.js";
|
|
13
15
|
import { arcPoint, arcToBeziers } from "./arc-to-bezier.js";
|
|
14
16
|
import { buildChartScene } from "./chart-geometry.js";
|
|
15
|
-
import {
|
|
16
|
-
import {
|
|
17
|
+
import { prepareImage } from "./image-xobject.js";
|
|
18
|
+
import { emitStyledPdf } from "./styled-page-emitter.js";
|
|
17
19
|
import { layoutMath, mathGlyphSegments, variantStyle } from "./math-layout.js";
|
|
18
20
|
import { customPaths, presetPaths, rectPath } from "./preset-geometry.js";
|
|
19
|
-
import { embedAssociatedFile } from "./embedded-file.js";
|
|
20
21
|
import { StructTreeBuilder } from "./struct-tree.js";
|
|
21
|
-
import { addSignaturePlaceholder } from "./signature.js";
|
|
22
|
-
import { buildXmpPacket } from "./xmp.js";
|
|
23
22
|
//#region src/pdf/styled-page-renderer.ts
|
|
24
23
|
function parsePdfAProfile(pdfA) {
|
|
25
24
|
const part = Number(pdfA.charAt(6));
|
|
@@ -31,206 +30,87 @@ function parsePdfAProfile(pdfA) {
|
|
|
31
30
|
version: part === 1 ? "1.4" : "1.7"
|
|
32
31
|
};
|
|
33
32
|
}
|
|
34
|
-
var A4_WIDTH = 595;
|
|
35
|
-
var A4_HEIGHT = 842;
|
|
36
33
|
var TWIP_TO_PT = 1 / 20;
|
|
37
34
|
var EIGHTH_PT = 1 / 8;
|
|
38
35
|
var DEFAULT_CELL_PADDING_TWIPS = 108;
|
|
39
36
|
var DEFAULT_BORDER_SIZE_EIGHTH = 4;
|
|
40
|
-
|
|
37
|
+
new TextEncoder();
|
|
38
|
+
function paintPlan(commands) {
|
|
39
|
+
const fills = [];
|
|
40
|
+
const images = [];
|
|
41
|
+
const borders = [];
|
|
42
|
+
const shapes = [];
|
|
43
|
+
const lines = [];
|
|
44
|
+
for (const c of commands) switch (c.type) {
|
|
45
|
+
case "fill":
|
|
46
|
+
fills.push(c);
|
|
47
|
+
break;
|
|
48
|
+
case "image":
|
|
49
|
+
images.push(c);
|
|
50
|
+
break;
|
|
51
|
+
case "border":
|
|
52
|
+
borders.push(c);
|
|
53
|
+
break;
|
|
54
|
+
case "shape":
|
|
55
|
+
shapes.push(c);
|
|
56
|
+
break;
|
|
57
|
+
case "line":
|
|
58
|
+
lines.push(c);
|
|
59
|
+
break;
|
|
60
|
+
default: assertNeverPageItem(c);
|
|
61
|
+
}
|
|
62
|
+
return {
|
|
63
|
+
fills,
|
|
64
|
+
images,
|
|
65
|
+
borders,
|
|
66
|
+
shapes,
|
|
67
|
+
lines
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function assertNeverPageItem(item) {
|
|
71
|
+
throw new Error(`Unhandled PageItem kind: ${String(item.type)}`);
|
|
72
|
+
}
|
|
41
73
|
function renderStyledPdf(body, options) {
|
|
74
|
+
return emitStyledPdf(layoutStyledDocument(body, options), options, new PdfDocument());
|
|
75
|
+
}
|
|
76
|
+
function layoutStyledDocument(body, options) {
|
|
42
77
|
const sectionList = resolveSectionList(body, options);
|
|
43
78
|
const numberedBody = applyNumbering(body, options.numbering);
|
|
44
79
|
const numberedHeadersFooters = applyNumberingToHeadersFooters(options.headersFooters, options.numbering);
|
|
45
|
-
const doc = new PdfDocument();
|
|
46
80
|
const pdfaProfile = options.pdfA ? parsePdfAProfile(options.pdfA) : void 0;
|
|
47
81
|
const tagged = options.tagged === true || (pdfaProfile?.tagged ?? false);
|
|
48
82
|
const structBuilder = tagged ? new StructTreeBuilder() : void 0;
|
|
49
|
-
const fontResources =
|
|
50
|
-
const imageResources =
|
|
83
|
+
const fontResources = collectFontResources(numberedBody, numberedHeadersFooters, options);
|
|
84
|
+
const imageResources = collectImageResources(numberedBody, numberedHeadersFooters, options);
|
|
51
85
|
const sectionCtxs = sectionList.map((s) => buildSectionContext(s, options, numberedHeadersFooters, fontResources));
|
|
52
86
|
let sectionIdx = 0;
|
|
53
|
-
const renderedPages = paginateSections(numberedBody.map((el, idx) => {
|
|
54
|
-
while (sectionIdx < sectionCtxs.length - 1 && idx >= sectionCtxs[sectionIdx].endIndex) sectionIdx++;
|
|
55
|
-
const ctx = sectionCtxs[sectionIdx];
|
|
56
|
-
return layoutBodyElement(el, options, fontResources, imageResources, ctx.contentWidth, ctx.pageContentHeight);
|
|
57
|
-
}), sectionCtxs, structBuilder, options.language ?? "en-US");
|
|
58
|
-
const pagesDict = dict({
|
|
59
|
-
Type: name("Pages"),
|
|
60
|
-
Count: 0,
|
|
61
|
-
Kids: []
|
|
62
|
-
});
|
|
63
|
-
const pagesRef = doc.add(pagesDict);
|
|
64
|
-
let firstPageDict;
|
|
65
|
-
const fontResourceDict = buildFontResourceDict(fontResources);
|
|
66
|
-
const xobjectResourceDict = buildXObjectResourceDict(imageResources);
|
|
67
|
-
const resourcesDict = dict({
|
|
68
|
-
Font: fontResourceDict,
|
|
69
|
-
...xobjectResourceDict ? { XObject: xobjectResourceDict } : {}
|
|
70
|
-
});
|
|
71
|
-
let pdfaIccRef;
|
|
72
|
-
let transparencyGroup;
|
|
73
|
-
if (pdfaProfile) {
|
|
74
|
-
pdfaIccRef = doc.add(stream({
|
|
75
|
-
N: 3,
|
|
76
|
-
Alternate: name("DeviceRGB")
|
|
77
|
-
}, buildSrgbIccProfile()));
|
|
78
|
-
if (pdfaProfile.part >= 2) transparencyGroup = dict({
|
|
79
|
-
S: name("Transparency"),
|
|
80
|
-
CS: [name("ICCBased"), ref(pdfaIccRef.id)]
|
|
81
|
-
});
|
|
82
|
-
}
|
|
83
|
-
const pageRefs = [];
|
|
84
|
-
renderedPages.forEach((page, pageIndex) => {
|
|
85
|
-
let pageTagging;
|
|
86
|
-
if (structBuilder) {
|
|
87
|
-
const builder = structBuilder;
|
|
88
|
-
pageTagging = {
|
|
89
|
-
next: 0,
|
|
90
|
-
assigned: false,
|
|
91
|
-
record: (structId, mcid) => builder.addMcref(structId, pageIndex, mcid),
|
|
92
|
-
tagFor: (structId) => builder.node(structId).type
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const contentBytes = emitPageContent(page.commands, pageTagging);
|
|
96
|
-
const contentsRef = doc.add(stream({}, contentBytes));
|
|
97
|
-
const pageEntries = {
|
|
98
|
-
Type: name("Page"),
|
|
99
|
-
Parent: ref(pagesRef.id),
|
|
100
|
-
MediaBox: [
|
|
101
|
-
0,
|
|
102
|
-
0,
|
|
103
|
-
page.width,
|
|
104
|
-
page.height
|
|
105
|
-
],
|
|
106
|
-
Resources: resourcesDict,
|
|
107
|
-
Contents: ref(contentsRef.id)
|
|
108
|
-
};
|
|
109
|
-
if (transparencyGroup) pageEntries["Group"] = transparencyGroup;
|
|
110
|
-
if (pageTagging?.assigned) {
|
|
111
|
-
pageEntries["StructParents"] = pageIndex;
|
|
112
|
-
pageEntries["Tabs"] = name("S");
|
|
113
|
-
}
|
|
114
|
-
const pageDictObj = dict(pageEntries);
|
|
115
|
-
if (firstPageDict === void 0) firstPageDict = pageDictObj;
|
|
116
|
-
pageRefs.push(doc.add(pageDictObj));
|
|
117
|
-
});
|
|
118
|
-
if (pageRefs.length === 0) {
|
|
119
|
-
const fallback = sectionCtxs[0] ?? defaultPageCtx();
|
|
120
|
-
const contentsRef = doc.add(stream({}, new Uint8Array(0)));
|
|
121
|
-
const fallbackDict = dict({
|
|
122
|
-
Type: name("Page"),
|
|
123
|
-
Parent: ref(pagesRef.id),
|
|
124
|
-
MediaBox: [
|
|
125
|
-
0,
|
|
126
|
-
0,
|
|
127
|
-
fallback.pageWidth,
|
|
128
|
-
fallback.pageHeight
|
|
129
|
-
],
|
|
130
|
-
Resources: resourcesDict,
|
|
131
|
-
Contents: ref(contentsRef.id),
|
|
132
|
-
...transparencyGroup ? { Group: transparencyGroup } : {}
|
|
133
|
-
});
|
|
134
|
-
firstPageDict = fallbackDict;
|
|
135
|
-
pageRefs.push(doc.add(fallbackDict));
|
|
136
|
-
}
|
|
137
|
-
pagesDict.set("Count", pageRefs.length);
|
|
138
|
-
pagesDict.set("Kids", pageRefs);
|
|
139
|
-
const catalogEntries = {
|
|
140
|
-
Type: name("Catalog"),
|
|
141
|
-
Pages: ref(pagesRef.id)
|
|
142
|
-
};
|
|
143
|
-
if (pdfaProfile) {
|
|
144
|
-
catalogEntries["OutputIntents"] = [ref(doc.add(dict({
|
|
145
|
-
Type: name("OutputIntent"),
|
|
146
|
-
S: name("GTS_PDFA1"),
|
|
147
|
-
OutputConditionIdentifier: "sRGB",
|
|
148
|
-
Info: "sRGB IEC61966-2.1",
|
|
149
|
-
DestOutputProfile: ref(pdfaIccRef.id)
|
|
150
|
-
})).id)];
|
|
151
|
-
catalogEntries["Metadata"] = ref(doc.add(stream({
|
|
152
|
-
Type: name("Metadata"),
|
|
153
|
-
Subtype: name("XML")
|
|
154
|
-
}, buildXmpPacket(xmpFromInfo(options.info, options.pdfA)))).id);
|
|
155
|
-
}
|
|
156
|
-
if (tagged && structBuilder) {
|
|
157
|
-
const structRootRef = structBuilder.emit(doc, pageRefs);
|
|
158
|
-
catalogEntries["MarkInfo"] = dict({ Marked: true });
|
|
159
|
-
catalogEntries["StructTreeRoot"] = ref(structRootRef.id);
|
|
160
|
-
catalogEntries["Lang"] = options.language ?? "en-US";
|
|
161
|
-
if (options.info?.title) catalogEntries["ViewerPreferences"] = dict({ DisplayDocTitle: true });
|
|
162
|
-
}
|
|
163
|
-
if (options.attachments?.length && (!pdfaProfile || pdfaProfile.part === 3)) {
|
|
164
|
-
const embedded = options.attachments.map((file) => ({
|
|
165
|
-
file,
|
|
166
|
-
ref: embedAssociatedFile(doc, file)
|
|
167
|
-
}));
|
|
168
|
-
catalogEntries["AF"] = embedded.map((e) => ref(e.ref.id));
|
|
169
|
-
const sorted = [...embedded].sort((a, b) => a.file.name < b.file.name ? -1 : a.file.name > b.file.name ? 1 : 0);
|
|
170
|
-
const names = [];
|
|
171
|
-
for (const e of sorted) names.push(e.file.name, ref(e.ref.id));
|
|
172
|
-
catalogEntries["Names"] = dict({ EmbeddedFiles: ref(doc.add(dict({ Names: names })).id) });
|
|
173
|
-
}
|
|
174
|
-
if (options.signaturePlaceholder && firstPageDict) {
|
|
175
|
-
const { fieldRef, acroForm } = addSignaturePlaceholder(doc, options.signaturePlaceholder, pageRefs[0]);
|
|
176
|
-
firstPageDict.set("Annots", [ref(fieldRef.id)]);
|
|
177
|
-
catalogEntries["AcroForm"] = acroForm;
|
|
178
|
-
}
|
|
179
|
-
const catalogRef = doc.add(dict(catalogEntries));
|
|
180
|
-
const infoRef = buildInfoDict(doc, options.info);
|
|
181
|
-
return doc.build(catalogRef, infoRef, { ...pdfaProfile ? {
|
|
182
|
-
version: pdfaProfile.version,
|
|
183
|
-
id: true
|
|
184
|
-
} : {} });
|
|
185
|
-
}
|
|
186
|
-
var DEFAULT_PRODUCER = "Ream";
|
|
187
|
-
function xmpFromInfo(info, pdfA) {
|
|
188
|
-
const p = pdfA ? parsePdfAProfile(pdfA) : void 0;
|
|
189
87
|
return {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
function buildInfoDict(doc, info) {
|
|
203
|
-
const merged = {
|
|
204
|
-
...info,
|
|
205
|
-
producer: info?.producer ?? DEFAULT_PRODUCER
|
|
88
|
+
pages: paginateSections(numberedBody.map((el, idx) => {
|
|
89
|
+
while (sectionIdx < sectionCtxs.length - 1 && idx >= sectionCtxs[sectionIdx].endIndex) sectionIdx++;
|
|
90
|
+
const ctx = sectionCtxs[sectionIdx];
|
|
91
|
+
return layoutBodyElement(el, options, fontResources, imageResources, ctx.contentWidth, ctx.pageContentHeight);
|
|
92
|
+
}), sectionCtxs, structBuilder, options.language ?? "en-US"),
|
|
93
|
+
resources: options.resources ?? new ResourceStore(),
|
|
94
|
+
fontResources,
|
|
95
|
+
imageResources,
|
|
96
|
+
structBuilder,
|
|
97
|
+
sectionCtxs,
|
|
98
|
+
pdfaProfile,
|
|
99
|
+
tagged
|
|
206
100
|
};
|
|
207
|
-
const entries = {};
|
|
208
|
-
if (merged.title) entries["Title"] = unicodeString(merged.title);
|
|
209
|
-
if (merged.author) entries["Author"] = unicodeString(merged.author);
|
|
210
|
-
if (merged.subject) entries["Subject"] = unicodeString(merged.subject);
|
|
211
|
-
if (merged.keywords) entries["Keywords"] = unicodeString(merged.keywords);
|
|
212
|
-
if (merged.creator) entries["Creator"] = unicodeString(merged.creator);
|
|
213
|
-
entries["Producer"] = unicodeString(merged.producer);
|
|
214
|
-
if (merged.creationDate) entries["CreationDate"] = formatPdfDate(merged.creationDate);
|
|
215
|
-
if (merged.modificationDate) entries["ModDate"] = formatPdfDate(merged.modificationDate);
|
|
216
|
-
return doc.add(dict(entries));
|
|
217
|
-
}
|
|
218
|
-
function formatPdfDate(d) {
|
|
219
|
-
const pad = (n, w = 2) => String(n).padStart(w, "0");
|
|
220
|
-
return `D:${pad(d.getUTCFullYear(), 4)}${pad(d.getUTCMonth() + 1)}${pad(d.getUTCDate())}${pad(d.getUTCHours())}${pad(d.getUTCMinutes())}${pad(d.getUTCSeconds())}Z`;
|
|
221
101
|
}
|
|
222
102
|
function resolvePageDimensions(options, section) {
|
|
223
|
-
const sectionPageWidth = section?.pageSize !== void 0 ? section.pageSize.
|
|
224
|
-
const sectionPageHeight = section?.pageSize !== void 0 ? section.pageSize.
|
|
225
|
-
const sectionLeft = section?.margins?.
|
|
226
|
-
const sectionRight = section?.margins?.
|
|
227
|
-
const sectionTop = section?.margins?.
|
|
228
|
-
const sectionBottom = section?.margins?.
|
|
229
|
-
const headerOffsetPt =
|
|
230
|
-
const footerOffsetPt =
|
|
103
|
+
const sectionPageWidth = section?.pageSize !== void 0 ? section.pageSize.width : void 0;
|
|
104
|
+
const sectionPageHeight = section?.pageSize !== void 0 ? section.pageSize.height : void 0;
|
|
105
|
+
const sectionLeft = section?.margins?.left !== void 0 ? section.margins.left : void 0;
|
|
106
|
+
const sectionRight = section?.margins?.right !== void 0 ? section.margins.right : void 0;
|
|
107
|
+
const sectionTop = section?.margins?.top !== void 0 ? section.margins.top : void 0;
|
|
108
|
+
const sectionBottom = section?.margins?.bottom !== void 0 ? section.margins.bottom : void 0;
|
|
109
|
+
const headerOffsetPt = section?.margins?.header ?? 720 * TWIP_TO_PT;
|
|
110
|
+
const footerOffsetPt = section?.margins?.footer ?? 720 * TWIP_TO_PT;
|
|
231
111
|
return {
|
|
232
|
-
pageWidth: options.pageWidth ?? sectionPageWidth ??
|
|
233
|
-
pageHeight: options.pageHeight ?? sectionPageHeight ??
|
|
112
|
+
pageWidth: options.pageWidth ?? sectionPageWidth ?? 595,
|
|
113
|
+
pageHeight: options.pageHeight ?? sectionPageHeight ?? 842,
|
|
234
114
|
marginLeft: options.marginLeft ?? sectionLeft ?? 72,
|
|
235
115
|
marginRight: options.marginRight ?? sectionRight ?? 72,
|
|
236
116
|
marginTop: options.marginTop ?? sectionTop ?? 72,
|
|
@@ -239,34 +119,6 @@ function resolvePageDimensions(options, section) {
|
|
|
239
119
|
footerOffsetPt
|
|
240
120
|
};
|
|
241
121
|
}
|
|
242
|
-
function defaultPageCtx() {
|
|
243
|
-
return {
|
|
244
|
-
endIndex: 0,
|
|
245
|
-
properties: {
|
|
246
|
-
headers: [],
|
|
247
|
-
footers: []
|
|
248
|
-
},
|
|
249
|
-
pageWidth: A4_WIDTH,
|
|
250
|
-
pageHeight: A4_HEIGHT,
|
|
251
|
-
marginLeft: 72,
|
|
252
|
-
marginTop: 72,
|
|
253
|
-
marginBottom: 72,
|
|
254
|
-
contentWidth: A4_WIDTH - 144,
|
|
255
|
-
pageContentHeight: A4_HEIGHT - 144,
|
|
256
|
-
headerSet: {
|
|
257
|
-
default: [],
|
|
258
|
-
first: [],
|
|
259
|
-
even: []
|
|
260
|
-
},
|
|
261
|
-
footerSet: {
|
|
262
|
-
default: [],
|
|
263
|
-
first: [],
|
|
264
|
-
even: []
|
|
265
|
-
},
|
|
266
|
-
titlePg: false,
|
|
267
|
-
evenAndOddHeaders: false
|
|
268
|
-
};
|
|
269
|
-
}
|
|
270
122
|
function resolveSectionList(body, options) {
|
|
271
123
|
if (options.sections && options.sections.length > 0) return options.sections;
|
|
272
124
|
if (options.section) return [{
|
|
@@ -370,14 +222,14 @@ function layoutBodyElement(el, options, fontResources, imageResources, contentWi
|
|
|
370
222
|
}
|
|
371
223
|
var EMU_PER_PT = 12700;
|
|
372
224
|
function layoutImageBlock(image, imageResources, contentWidth) {
|
|
373
|
-
let widthPt = image.
|
|
374
|
-
let heightPt = image.
|
|
225
|
+
let widthPt = image.width;
|
|
226
|
+
let heightPt = image.height;
|
|
375
227
|
if (widthPt > contentWidth) {
|
|
376
228
|
const scale = contentWidth / widthPt;
|
|
377
229
|
widthPt = contentWidth;
|
|
378
230
|
heightPt = heightPt * scale;
|
|
379
231
|
}
|
|
380
|
-
const res = imageResources?.get(image.
|
|
232
|
+
const res = image.resource ? imageResources?.get(image.resource) : void 0;
|
|
381
233
|
const resolvedAlignment = image.paragraphProperties.alignment ?? "left";
|
|
382
234
|
return {
|
|
383
235
|
kind: "image",
|
|
@@ -385,8 +237,8 @@ function layoutImageBlock(image, imageResources, contentWidth) {
|
|
|
385
237
|
heightPt,
|
|
386
238
|
resolvedAlignment,
|
|
387
239
|
resourceName: res?.resourceName ?? "",
|
|
388
|
-
spacingBeforePt:
|
|
389
|
-
spacingAfterPt:
|
|
240
|
+
spacingBeforePt: image.paragraphProperties.spacingBefore ?? 0,
|
|
241
|
+
spacingAfterPt: image.paragraphProperties.spacingAfter ?? 0,
|
|
390
242
|
...image.altText ? { altText: image.altText } : {}
|
|
391
243
|
};
|
|
392
244
|
}
|
|
@@ -394,8 +246,8 @@ var DEFAULT_LINE_WIDTH_EMU = 9525;
|
|
|
394
246
|
var DEFAULT_INSET_LR_EMU = 91440;
|
|
395
247
|
var DEFAULT_INSET_TB_EMU = 45720;
|
|
396
248
|
function layoutShapeBlock(shape, options, fontResources, imageResources, contentWidth, maxHeight) {
|
|
397
|
-
let widthPt = shape.
|
|
398
|
-
let heightPt = shape.
|
|
249
|
+
let widthPt = shape.width;
|
|
250
|
+
let heightPt = shape.height;
|
|
399
251
|
if (widthPt > contentWidth && widthPt > 0) {
|
|
400
252
|
const scale = contentWidth / widthPt;
|
|
401
253
|
widthPt = contentWidth;
|
|
@@ -412,10 +264,10 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
412
264
|
const t = shape.transform;
|
|
413
265
|
const pp = shape.paragraphProperties;
|
|
414
266
|
const text = shape.text;
|
|
415
|
-
const insetLeftPt =
|
|
416
|
-
const insetRightPt =
|
|
417
|
-
const insetTopPt =
|
|
418
|
-
const insetBottomPt =
|
|
267
|
+
const insetLeftPt = text?.insetLeft ?? DEFAULT_INSET_LR_EMU / EMU_PER_PT;
|
|
268
|
+
const insetRightPt = text?.insetRight ?? DEFAULT_INSET_LR_EMU / EMU_PER_PT;
|
|
269
|
+
const insetTopPt = text?.insetTop ?? DEFAULT_INSET_TB_EMU / EMU_PER_PT;
|
|
270
|
+
const insetBottomPt = text?.insetBottom ?? DEFAULT_INSET_TB_EMU / EMU_PER_PT;
|
|
419
271
|
const textLines = [];
|
|
420
272
|
let textHeightPt = 0;
|
|
421
273
|
if (text && text.content.length > 0) {
|
|
@@ -441,8 +293,8 @@ function layoutShapeBlock(shape, options, fontResources, imageResources, content
|
|
|
441
293
|
flipH: t?.flipH ?? false,
|
|
442
294
|
flipV: t?.flipV ?? false,
|
|
443
295
|
resolvedAlignment: pp.alignment ?? "left",
|
|
444
|
-
spacingBeforePt:
|
|
445
|
-
spacingAfterPt:
|
|
296
|
+
spacingBeforePt: pp.spacingBefore ?? 0,
|
|
297
|
+
spacingAfterPt: pp.spacingAfter ?? 0,
|
|
446
298
|
textLines,
|
|
447
299
|
textHeightPt,
|
|
448
300
|
insetLeftPt,
|
|
@@ -460,7 +312,7 @@ function buildShapePaths(geometry, widthPt, heightPt) {
|
|
|
460
312
|
}
|
|
461
313
|
function buildStroke(line) {
|
|
462
314
|
if (!line || line.fill === "none") return void 0;
|
|
463
|
-
const widthPt =
|
|
315
|
+
const widthPt = line.width ?? DEFAULT_LINE_WIDTH_EMU / EMU_PER_PT;
|
|
464
316
|
const dash = line.dash && line.dash !== "solid" ? dashPattern(line.dash, widthPt) : void 0;
|
|
465
317
|
const cap = line.cap === "flat" ? "butt" : line.cap;
|
|
466
318
|
return {
|
|
@@ -517,8 +369,8 @@ function buildShapeTransform(pageX, pageY, widthPt, heightPt, rotation60k, flipH
|
|
|
517
369
|
];
|
|
518
370
|
}
|
|
519
371
|
function layoutChartBlock(block, options, fontResources, contentWidth, maxHeight) {
|
|
520
|
-
let widthPt = block.
|
|
521
|
-
let heightPt = block.
|
|
372
|
+
let widthPt = block.width;
|
|
373
|
+
let heightPt = block.height;
|
|
522
374
|
if (widthPt > contentWidth && widthPt > 0) {
|
|
523
375
|
const scale = contentWidth / widthPt;
|
|
524
376
|
widthPt = contentWidth;
|
|
@@ -544,13 +396,13 @@ function layoutChartBlock(block, options, fontResources, contentWidth, maxHeight
|
|
|
544
396
|
heightPt,
|
|
545
397
|
layout,
|
|
546
398
|
resolvedAlignment: pp.alignment ?? "left",
|
|
547
|
-
spacingBeforePt:
|
|
548
|
-
spacingAfterPt:
|
|
399
|
+
spacingBeforePt: pp.spacingBefore ?? 0,
|
|
400
|
+
spacingAfterPt: pp.spacingAfter ?? 0,
|
|
549
401
|
...altText ? { altText } : {}
|
|
550
402
|
};
|
|
551
403
|
}
|
|
552
404
|
function buildChartLayout(chart, widthPt, heightPt, font) {
|
|
553
|
-
const measure = (text, sizePt) => font.
|
|
405
|
+
const measure = (text, sizePt) => font.measure.textWidthPt(text, sizePt);
|
|
554
406
|
const scene = buildChartScene(chart, widthPt, heightPt, measure);
|
|
555
407
|
if (!scene) return {
|
|
556
408
|
shapes: [{
|
|
@@ -630,7 +482,7 @@ function labelPrim(l, font) {
|
|
|
630
482
|
};
|
|
631
483
|
}
|
|
632
484
|
function makeChartLabelLine(text, font, sizePt, colorHex) {
|
|
633
|
-
const widthPt = font.
|
|
485
|
+
const widthPt = font.measure.textWidthPt(text, sizePt);
|
|
634
486
|
return {
|
|
635
487
|
tokens: [{
|
|
636
488
|
kind: "text",
|
|
@@ -639,7 +491,7 @@ function makeChartLabelLine(text, font, sizePt, colorHex) {
|
|
|
639
491
|
resolvedRun: {
|
|
640
492
|
...DEFAULT_RESOLVED_RUN,
|
|
641
493
|
colorHex,
|
|
642
|
-
|
|
494
|
+
fontSizePt: halfPtToPt(Math.round(sizePt * 2))
|
|
643
495
|
},
|
|
644
496
|
font,
|
|
645
497
|
fontSizePt: sizePt,
|
|
@@ -654,14 +506,15 @@ function makeChartLabelLine(text, font, sizePt, colorHex) {
|
|
|
654
506
|
isLastInParagraph: true
|
|
655
507
|
};
|
|
656
508
|
}
|
|
657
|
-
function
|
|
509
|
+
function collectImageResources(body, headersFooters, options) {
|
|
658
510
|
const out = /* @__PURE__ */ new Map();
|
|
659
|
-
if (!options.
|
|
511
|
+
if (!options.resources || options.resources.size === 0) return out;
|
|
660
512
|
const seen = /* @__PURE__ */ new Set();
|
|
661
513
|
const visit = (elements) => {
|
|
662
|
-
for (const el of elements) if (el.kind === "image")
|
|
663
|
-
|
|
664
|
-
|
|
514
|
+
for (const el of elements) if (el.kind === "image") {
|
|
515
|
+
if (el.image.resource) seen.add(el.image.resource);
|
|
516
|
+
} else if (el.kind === "paragraph") {
|
|
517
|
+
for (const run of el.paragraph.runs) if (run.inlineImage?.resource) seen.add(run.inlineImage.resource);
|
|
665
518
|
} else if (el.kind === "table") for (const row of el.table.rows) for (const cell of row.cells) visit(cell.content);
|
|
666
519
|
else if (el.kind === "shape") {
|
|
667
520
|
if (el.shape.text) visit(el.shape.text.content);
|
|
@@ -671,19 +524,19 @@ function embedUsedImages(doc, body, headersFooters, options) {
|
|
|
671
524
|
for (const hf of headersFooters.values()) visit(hf);
|
|
672
525
|
const flattenAlpha = options.pdfA ? parsePdfAProfile(options.pdfA).part === 1 : false;
|
|
673
526
|
let counter = 0;
|
|
674
|
-
for (const
|
|
675
|
-
const bytes = options.
|
|
527
|
+
for (const resourceId of seen) {
|
|
528
|
+
const bytes = options.resources.get(resourceId);
|
|
676
529
|
if (!bytes) continue;
|
|
677
|
-
let
|
|
530
|
+
let prepared;
|
|
678
531
|
try {
|
|
679
|
-
|
|
532
|
+
prepared = prepareImage(bytes, { flattenAlpha });
|
|
680
533
|
} catch {
|
|
681
534
|
continue;
|
|
682
535
|
}
|
|
683
536
|
counter++;
|
|
684
|
-
out.set(
|
|
537
|
+
out.set(resourceId, {
|
|
685
538
|
resourceName: `Im${counter}`,
|
|
686
|
-
|
|
539
|
+
prepared
|
|
687
540
|
});
|
|
688
541
|
}
|
|
689
542
|
return out;
|
|
@@ -697,7 +550,7 @@ function drawBlocksSequentially(blocks, startX, startY) {
|
|
|
697
550
|
for (const line of block.lines) {
|
|
698
551
|
const h = computeLineHeight(line, block.resolved);
|
|
699
552
|
cursorY -= h;
|
|
700
|
-
const indentLeft = block.resolved.
|
|
553
|
+
const indentLeft = block.resolved.indentLeft + (line.firstLine ? block.resolved.indentFirstLine : 0);
|
|
701
554
|
const offset = alignmentOffset(block.resolved.alignment, line.contentWidthPt, line.availableWidthPt);
|
|
702
555
|
out.push({
|
|
703
556
|
type: "line",
|
|
@@ -756,9 +609,9 @@ function applyNumbering(body, numbering) {
|
|
|
756
609
|
function mergeIndentFromLevel(paragraphProps, levelProps) {
|
|
757
610
|
if (!levelProps) return paragraphProps;
|
|
758
611
|
const out = { ...paragraphProps };
|
|
759
|
-
if (out.
|
|
760
|
-
if (out.
|
|
761
|
-
if (out.
|
|
612
|
+
if (out.indentLeft === void 0 && levelProps.indentLeft !== void 0) out.indentLeft = levelProps.indentLeft;
|
|
613
|
+
if (out.indentRight === void 0 && levelProps.indentRight !== void 0) out.indentRight = levelProps.indentRight;
|
|
614
|
+
if (out.indentFirstLine === void 0 && levelProps.indentFirstLine !== void 0) out.indentFirstLine = levelProps.indentFirstLine;
|
|
762
615
|
return out;
|
|
763
616
|
}
|
|
764
617
|
function runFontKeyAndParsed(options, ascii, bold, italic) {
|
|
@@ -796,7 +649,7 @@ function runFontKeyAndParsed(options, ascii, bold, italic) {
|
|
|
796
649
|
function lookupFont(resources, fontKey) {
|
|
797
650
|
return resources.get(fontKey) ?? resources.values().next().value;
|
|
798
651
|
}
|
|
799
|
-
function
|
|
652
|
+
function collectFontResources(body, headersFooters, options) {
|
|
800
653
|
const used = /* @__PURE__ */ new Map();
|
|
801
654
|
const addRun = (run, para) => {
|
|
802
655
|
const resolved = resolveRunProperties(run.properties, para.properties, options.styles);
|
|
@@ -870,35 +723,20 @@ function embedUsedFonts(doc, body, headersFooters, options) {
|
|
|
870
723
|
gids: new Set([0])
|
|
871
724
|
});
|
|
872
725
|
}
|
|
873
|
-
const cidSet = options.pdfA ? parsePdfAProfile(options.pdfA).part === 1 : false;
|
|
874
726
|
const out = /* @__PURE__ */ new Map();
|
|
875
727
|
let counter = 0;
|
|
876
728
|
for (const [variant, info] of used) {
|
|
877
729
|
counter++;
|
|
878
730
|
const resourceName = `F${counter}`;
|
|
879
|
-
const embedded = embedTtfFont(doc, info.parsed, {
|
|
880
|
-
usedGids: info.gids,
|
|
881
|
-
cidSet
|
|
882
|
-
});
|
|
883
731
|
out.set(variant, {
|
|
884
732
|
resourceName,
|
|
885
733
|
parsed: info.parsed,
|
|
886
|
-
|
|
734
|
+
measure: createFontMeasure(info.parsed),
|
|
735
|
+
gids: info.gids
|
|
887
736
|
});
|
|
888
737
|
}
|
|
889
738
|
return out;
|
|
890
739
|
}
|
|
891
|
-
function buildFontResourceDict(resources) {
|
|
892
|
-
const entries = {};
|
|
893
|
-
for (const res of resources.values()) entries[res.resourceName] = ref(res.embedded.fontRef.id);
|
|
894
|
-
return dict(entries);
|
|
895
|
-
}
|
|
896
|
-
function buildXObjectResourceDict(resources) {
|
|
897
|
-
if (resources.size === 0) return void 0;
|
|
898
|
-
const entries = {};
|
|
899
|
-
for (const res of resources.values()) entries[res.resourceName] = ref(res.ref.id);
|
|
900
|
-
return dict(entries);
|
|
901
|
-
}
|
|
902
740
|
function layoutParagraphBlock(paragraph, options, fontResources, imageResources, contentWidth) {
|
|
903
741
|
const baseResolved = resolveParagraphProperties(paragraph.properties, options.styles);
|
|
904
742
|
const baseDir = paragraphBaseDirection(paragraph, baseResolved);
|
|
@@ -915,8 +753,8 @@ function layoutParagraphBlock(paragraph, options, fontResources, imageResources,
|
|
|
915
753
|
resolved,
|
|
916
754
|
lines,
|
|
917
755
|
heightPt,
|
|
918
|
-
spacingBeforePt: resolved.
|
|
919
|
-
spacingAfterPt: resolved.
|
|
756
|
+
spacingBeforePt: resolved.spacingBefore,
|
|
757
|
+
spacingAfterPt: resolved.spacingAfter,
|
|
920
758
|
...numbering ? { list: {
|
|
921
759
|
numId: numbering.numId,
|
|
922
760
|
level: numbering.ilvl
|
|
@@ -956,18 +794,18 @@ function resolveMathItems(items, fontFor) {
|
|
|
956
794
|
function tokenizeParagraph(paragraph, options, fontResources, imageResources, contentWidth, baseDir) {
|
|
957
795
|
const plans = paragraph.runs.map((run) => {
|
|
958
796
|
if (run.inlineImage) {
|
|
959
|
-
const naturalW = run.inlineImage.
|
|
797
|
+
const naturalW = run.inlineImage.width;
|
|
960
798
|
const widthPt = Math.min(naturalW, contentWidth);
|
|
961
799
|
const scale = naturalW > 0 ? widthPt / naturalW : 1;
|
|
962
|
-
const heightPt = run.inlineImage.
|
|
963
|
-
const res = imageResources?.get(run.inlineImage.
|
|
800
|
+
const heightPt = run.inlineImage.height * scale;
|
|
801
|
+
const res = run.inlineImage.resource ? imageResources?.get(run.inlineImage.resource) : void 0;
|
|
964
802
|
const resolvedRun = resolveRunProperties(run.properties, paragraph.properties, options.styles);
|
|
965
803
|
const { fontKey } = runFontKeyAndParsed(options, resolvedRun.fontFamily.ascii, resolvedRun.bold, resolvedRun.italic);
|
|
966
804
|
return {
|
|
967
805
|
run,
|
|
968
806
|
resolvedRun,
|
|
969
807
|
font: lookupFont(fontResources, fontKey),
|
|
970
|
-
fontSizePt: resolvedRun.
|
|
808
|
+
fontSizePt: resolvedRun.fontSizePt,
|
|
971
809
|
isImage: true,
|
|
972
810
|
imageWidthPt: widthPt,
|
|
973
811
|
imageHeightPt: heightPt,
|
|
@@ -976,13 +814,13 @@ function tokenizeParagraph(paragraph, options, fontResources, imageResources, co
|
|
|
976
814
|
}
|
|
977
815
|
if (run.math) {
|
|
978
816
|
const resolvedRun = resolveRunProperties(run.properties, paragraph.properties, options.styles);
|
|
979
|
-
const sizePt = resolvedRun.
|
|
817
|
+
const sizePt = resolvedRun.fontSizePt;
|
|
980
818
|
const fontFor = (v) => {
|
|
981
819
|
const { bold, italic } = variantStyle(v);
|
|
982
820
|
const r = options.registry.resolveByStyle(bold, italic);
|
|
983
821
|
return fontResources.get(r.variant) ?? fontResources.get(options.registry.resolveByStyle(false, false).variant);
|
|
984
822
|
};
|
|
985
|
-
const measure = (text, sz, v) => fontFor(v).
|
|
823
|
+
const measure = (text, sz, v) => fontFor(v).measure.textWidthPt(text, sz);
|
|
986
824
|
const box = layoutMath(run.math, { sizePt }, measure);
|
|
987
825
|
const { variant } = options.registry.resolveByStyle(resolvedRun.bold, resolvedRun.italic);
|
|
988
826
|
return {
|
|
@@ -1008,7 +846,7 @@ function tokenizeParagraph(paragraph, options, fontResources, imageResources, co
|
|
|
1008
846
|
run,
|
|
1009
847
|
resolvedRun,
|
|
1010
848
|
font: lookupFont(fontResources, fontKey),
|
|
1011
|
-
fontSizePt: resolvedRun.
|
|
849
|
+
fontSizePt: resolvedRun.fontSizePt,
|
|
1012
850
|
isImage: false,
|
|
1013
851
|
imageWidthPt: 0,
|
|
1014
852
|
imageHeightPt: 0,
|
|
@@ -1083,7 +921,7 @@ function tokenizePlansLtr(plans) {
|
|
|
1083
921
|
resolvedRun: plan.resolvedRun,
|
|
1084
922
|
font: plan.font,
|
|
1085
923
|
fontSizePt: plan.fontSizePt,
|
|
1086
|
-
widthPt: plan.font.
|
|
924
|
+
widthPt: plan.font.measure.textWidthPt(t.text, plan.fontSizePt),
|
|
1087
925
|
bidiLevel: 0
|
|
1088
926
|
});
|
|
1089
927
|
}
|
|
@@ -1133,7 +971,7 @@ function tokenizePlansBidi(plans, realLevels) {
|
|
|
1133
971
|
resolvedRun: plan.resolvedRun,
|
|
1134
972
|
font: plan.font,
|
|
1135
973
|
fontSizePt: plan.fontSizePt,
|
|
1136
|
-
widthPt: plan.font.
|
|
974
|
+
widthPt: plan.font.measure.textWidthPt(text, plan.fontSizePt),
|
|
1137
975
|
bidiLevel: curLevel
|
|
1138
976
|
});
|
|
1139
977
|
};
|
|
@@ -1167,9 +1005,9 @@ function paragraphBaseDirection(paragraph, resolved) {
|
|
|
1167
1005
|
return analyzeString(text, "auto").paragraphLevel === 1 ? "rtl" : "ltr";
|
|
1168
1006
|
}
|
|
1169
1007
|
function paragraphMaxWidth(p, contentWidth, firstLine) {
|
|
1170
|
-
const indentLeft = p.
|
|
1171
|
-
const indentRight = p.
|
|
1172
|
-
const firstLineExtra = firstLine ? p.
|
|
1008
|
+
const indentLeft = p.indentLeft;
|
|
1009
|
+
const indentRight = p.indentRight;
|
|
1010
|
+
const firstLineExtra = firstLine ? p.indentFirstLine : 0;
|
|
1173
1011
|
return Math.max(1, contentWidth - indentLeft - indentRight - firstLineExtra);
|
|
1174
1012
|
}
|
|
1175
1013
|
function tokenizeText(text) {
|
|
@@ -1222,12 +1060,12 @@ function wrap(tokens, firstLineWidth, otherWidth, resolved, hyphenator) {
|
|
|
1222
1060
|
}, tok);
|
|
1223
1061
|
continue;
|
|
1224
1062
|
}
|
|
1225
|
-
const hyphenWidth = tok.font.
|
|
1063
|
+
const hyphenWidth = tok.font.measure.textWidthPt("-", tok.fontSizePt);
|
|
1226
1064
|
let prev = 0;
|
|
1227
1065
|
for (let pi = 0; pi <= positions.length; pi++) {
|
|
1228
1066
|
const end = pi < positions.length ? positions[pi] : tok.text.length;
|
|
1229
1067
|
const fragText = tok.text.substring(prev, end);
|
|
1230
|
-
const fragWidth = tok.font.
|
|
1068
|
+
const fragWidth = tok.font.measure.textWidthPt(fragText, tok.fontSizePt);
|
|
1231
1069
|
const fragTok = {
|
|
1232
1070
|
kind: "text",
|
|
1233
1071
|
text: fragText,
|
|
@@ -1325,9 +1163,10 @@ function computeLineHeight(line, p) {
|
|
|
1325
1163
|
const fontSize = line.maxFontSizePt || 12;
|
|
1326
1164
|
const mathH = (line.mathAscentPt ?? 0) + (line.mathDescentPt ?? 0);
|
|
1327
1165
|
const mathNeed = mathH > 0 ? mathH * 1.05 : 0;
|
|
1328
|
-
if (p.spacingLineRule === "exact" && p.
|
|
1329
|
-
if (p.spacingLineRule === "atLeast" && p.
|
|
1330
|
-
const
|
|
1166
|
+
if (p.spacingLineRule === "exact" && p.spacingLine > 0) return Math.max(p.spacingLine, mathNeed);
|
|
1167
|
+
if (p.spacingLineRule === "atLeast" && p.spacingLine > 0) return Math.max(fontSize * 1.2, p.spacingLine, mathNeed);
|
|
1168
|
+
const lineTwips = Math.round(p.spacingLine * 20);
|
|
1169
|
+
const multiple = lineTwips > 0 ? lineTwips / 240 : 1;
|
|
1331
1170
|
return Math.max(fontSize * 1.2 * multiple, mathNeed);
|
|
1332
1171
|
}
|
|
1333
1172
|
function lineDescent(line) {
|
|
@@ -1341,7 +1180,7 @@ function alignmentOffset(alignment, lineWidth, available) {
|
|
|
1341
1180
|
}
|
|
1342
1181
|
function layoutTableBlock(table, options, fontResources, imageResources, contentWidth) {
|
|
1343
1182
|
const columnWidthsPt = computeColumnWidths(table, options, fontResources, contentWidth);
|
|
1344
|
-
const mergeRoles =
|
|
1183
|
+
const mergeRoles = table.rows.map((r) => r.cells.map((c) => c.properties.merge ?? "standalone"));
|
|
1345
1184
|
const rows = [];
|
|
1346
1185
|
const colCount = columnWidthsPt.length;
|
|
1347
1186
|
let aboveBordersByCol = [];
|
|
@@ -1350,7 +1189,7 @@ function layoutTableBlock(table, options, fontResources, imageResources, content
|
|
|
1350
1189
|
const nextAbove = [];
|
|
1351
1190
|
let ci = 0;
|
|
1352
1191
|
for (const cell of table.rows[r].cells) {
|
|
1353
|
-
const span = Math.max(1, cell.properties.
|
|
1192
|
+
const span = Math.max(1, cell.properties.colSpan ?? 1);
|
|
1354
1193
|
for (let k = 0; k < span; k++) nextAbove[ci + k] = cell.properties.borders;
|
|
1355
1194
|
ci += span;
|
|
1356
1195
|
}
|
|
@@ -1378,43 +1217,11 @@ function tableXOffset(alignment, contentWidth, totalWidthPt) {
|
|
|
1378
1217
|
if (slack <= 0 || !alignment || alignment === "left") return 0;
|
|
1379
1218
|
return alignment === "center" ? slack / 2 : slack;
|
|
1380
1219
|
}
|
|
1381
|
-
function computeMergeRoles(table) {
|
|
1382
|
-
const out = table.rows.map((r) => new Array(r.cells.length).fill("standalone"));
|
|
1383
|
-
const colSlots = /* @__PURE__ */ new Map();
|
|
1384
|
-
for (let rowIdx = 0; rowIdx < table.rows.length; rowIdx++) {
|
|
1385
|
-
const row = table.rows[rowIdx];
|
|
1386
|
-
let colIdx = 0;
|
|
1387
|
-
for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx++) {
|
|
1388
|
-
const cell = row.cells[cellIdx];
|
|
1389
|
-
let arr = colSlots.get(colIdx);
|
|
1390
|
-
if (!arr) {
|
|
1391
|
-
arr = [];
|
|
1392
|
-
colSlots.set(colIdx, arr);
|
|
1393
|
-
}
|
|
1394
|
-
arr.push({
|
|
1395
|
-
rowIdx,
|
|
1396
|
-
cellIdx,
|
|
1397
|
-
vMerge: cell.properties.vMerge
|
|
1398
|
-
});
|
|
1399
|
-
colIdx += Math.max(1, cell.properties.gridSpan ?? 1);
|
|
1400
|
-
}
|
|
1401
|
-
}
|
|
1402
|
-
for (const slots of colSlots.values()) for (let i = 0; i < slots.length; i++) {
|
|
1403
|
-
const cur = slots[i];
|
|
1404
|
-
const next = slots[i + 1];
|
|
1405
|
-
const nextIsContinue = !!next && next.vMerge === "continue";
|
|
1406
|
-
let role = "standalone";
|
|
1407
|
-
if (cur.vMerge === "restart") role = nextIsContinue ? "start" : "standalone";
|
|
1408
|
-
else if (cur.vMerge === "continue") role = nextIsContinue ? "middle" : "end";
|
|
1409
|
-
out[cur.rowIdx][cur.cellIdx] = role;
|
|
1410
|
-
}
|
|
1411
|
-
return out;
|
|
1412
|
-
}
|
|
1413
1220
|
function computeColumnWidths(table, options, fontResources, contentWidth) {
|
|
1414
1221
|
let colCount = table.grid.length;
|
|
1415
1222
|
for (const row of table.rows) {
|
|
1416
1223
|
let rowCols = 0;
|
|
1417
|
-
for (const cell of row.cells) rowCols += Math.max(1, cell.properties.
|
|
1224
|
+
for (const cell of row.cells) rowCols += Math.max(1, cell.properties.colSpan ?? 1);
|
|
1418
1225
|
if (rowCols > colCount) colCount = rowCols;
|
|
1419
1226
|
}
|
|
1420
1227
|
if (colCount === 0) return [];
|
|
@@ -1424,9 +1231,9 @@ function computeColumnWidths(table, options, fontResources, contentWidth) {
|
|
|
1424
1231
|
let colIdx = 0;
|
|
1425
1232
|
for (let i = 0; i < row.cells.length; i++) {
|
|
1426
1233
|
const cell = row.cells[i];
|
|
1427
|
-
const span = Math.max(1, cell.properties.
|
|
1428
|
-
const padLeft =
|
|
1429
|
-
const padRight =
|
|
1234
|
+
const span = Math.max(1, cell.properties.colSpan ?? 1);
|
|
1235
|
+
const padLeft = cell.properties.margins?.left ?? table.properties.defaultCellMargins?.left ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
1236
|
+
const padRight = cell.properties.margins?.right ?? table.properties.defaultCellMargins?.right ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
1430
1237
|
let maxContent = 0;
|
|
1431
1238
|
for (const el of cell.content) {
|
|
1432
1239
|
if (el.kind !== "paragraph") continue;
|
|
@@ -1451,11 +1258,15 @@ function computeColumnWidths(table, options, fontResources, contentWidth) {
|
|
|
1451
1258
|
}
|
|
1452
1259
|
return colNaturalWidths;
|
|
1453
1260
|
}
|
|
1261
|
+
function gridColTwips(table) {
|
|
1262
|
+
return table.grid.map((w) => Math.round(w * 20));
|
|
1263
|
+
}
|
|
1454
1264
|
function gridWidthsScaled(table, contentWidth, colCount) {
|
|
1455
|
-
const
|
|
1265
|
+
const gridTwips = gridColTwips(table);
|
|
1266
|
+
const totalGridTwips = gridTwips.reduce((s, w) => s + w, 0);
|
|
1456
1267
|
if (totalGridTwips > 0) {
|
|
1457
1268
|
const target = totalTableTarget(table, contentWidth);
|
|
1458
|
-
return
|
|
1269
|
+
return gridTwips.map((w) => w / totalGridTwips * target);
|
|
1459
1270
|
}
|
|
1460
1271
|
const each = contentWidth / colCount;
|
|
1461
1272
|
return new Array(colCount).fill(each);
|
|
@@ -1463,15 +1274,16 @@ function gridWidthsScaled(table, contentWidth, colCount) {
|
|
|
1463
1274
|
function totalTableTarget(table, contentWidth) {
|
|
1464
1275
|
const explicit = explicitTableTargetWidth(table, contentWidth);
|
|
1465
1276
|
if (explicit !== void 0 && explicit > 0) return explicit;
|
|
1466
|
-
const sum = table.
|
|
1277
|
+
const sum = gridColTwips(table).reduce((s, g) => s + g, 0);
|
|
1467
1278
|
if (sum > 0) return sum * TWIP_TO_PT;
|
|
1468
1279
|
return contentWidth;
|
|
1469
1280
|
}
|
|
1470
1281
|
function explicitTableTargetWidth(table, contentWidth) {
|
|
1471
|
-
const w = table.properties.
|
|
1282
|
+
const w = table.properties.widthPt;
|
|
1472
1283
|
const type = table.properties.widthType;
|
|
1473
|
-
if (w !== void 0 && w > 0 && type === "dxa") return w
|
|
1474
|
-
|
|
1284
|
+
if (w !== void 0 && w > 0 && type === "dxa") return w;
|
|
1285
|
+
const f = table.properties.widthFraction;
|
|
1286
|
+
if (f !== void 0 && type === "pct") return f * contentWidth;
|
|
1475
1287
|
}
|
|
1476
1288
|
function measureSingleLine(paragraph, options, fontResources) {
|
|
1477
1289
|
let total = 0;
|
|
@@ -1479,8 +1291,8 @@ function measureSingleLine(paragraph, options, fontResources) {
|
|
|
1479
1291
|
const resolved = resolveRunProperties(run.properties, paragraph.properties, options.styles);
|
|
1480
1292
|
const { variant } = options.registry.resolveByStyle(resolved.bold, resolved.italic);
|
|
1481
1293
|
const font = fontResources.get(variant);
|
|
1482
|
-
const fontSizePt = resolved.
|
|
1483
|
-
total += font.
|
|
1294
|
+
const fontSizePt = resolved.fontSizePt;
|
|
1295
|
+
total += font.measure.textWidthPt(run.text, fontSizePt);
|
|
1484
1296
|
}
|
|
1485
1297
|
return total;
|
|
1486
1298
|
}
|
|
@@ -1491,7 +1303,7 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
|
|
|
1491
1303
|
let colIdx = 0;
|
|
1492
1304
|
for (let cellIdx = 0; cellIdx < row.cells.length; cellIdx++) {
|
|
1493
1305
|
const cell = row.cells[cellIdx];
|
|
1494
|
-
const span = Math.max(1, cell.properties.
|
|
1306
|
+
const span = Math.max(1, cell.properties.colSpan ?? 1);
|
|
1495
1307
|
let widthPt = 0;
|
|
1496
1308
|
for (let k = 0; k < span && colIdx + k < columnWidthsPt.length; k++) widthPt += columnWidthsPt[colIdx + k];
|
|
1497
1309
|
columnXOffsets.push(cursorX);
|
|
@@ -1504,8 +1316,8 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
|
|
|
1504
1316
|
}
|
|
1505
1317
|
let heightPt = 0;
|
|
1506
1318
|
for (const c of cells) if (c.totalHeightPt > heightPt) heightPt = c.totalHeightPt;
|
|
1507
|
-
if (row.properties.
|
|
1508
|
-
else if (row.properties.
|
|
1319
|
+
if (row.properties.height && row.properties.heightRule === "exact") heightPt = row.properties.height;
|
|
1320
|
+
else if (row.properties.height && row.properties.heightRule === "atLeast") heightPt = Math.max(heightPt, row.properties.height);
|
|
1509
1321
|
return {
|
|
1510
1322
|
heightPt,
|
|
1511
1323
|
cells,
|
|
@@ -1517,10 +1329,10 @@ function layoutTableRow(row, rowIdx, rowCount, colCount, tableProps, columnWidth
|
|
|
1517
1329
|
function layoutTableCell(cell, tableProps, widthPt, options, fontResources, imageResources, rowIdx, colStart, colSpan, rowCount, colCount, mergeRole, leftNeighborBorders, aboveNeighborBorders) {
|
|
1518
1330
|
const cellMar = cell.properties.margins;
|
|
1519
1331
|
const tableMar = tableProps.defaultCellMargins;
|
|
1520
|
-
const padTopPt =
|
|
1521
|
-
const padBottomPt =
|
|
1522
|
-
const padLeftPt =
|
|
1523
|
-
const padRightPt =
|
|
1332
|
+
const padTopPt = cellMar?.top ?? tableMar?.top ?? 0;
|
|
1333
|
+
const padBottomPt = cellMar?.bottom ?? tableMar?.bottom ?? 0;
|
|
1334
|
+
const padLeftPt = cellMar?.left ?? tableMar?.left ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
1335
|
+
const padRightPt = cellMar?.right ?? tableMar?.right ?? DEFAULT_CELL_PADDING_TWIPS * TWIP_TO_PT;
|
|
1524
1336
|
const innerWidth = Math.max(1, widthPt - padLeftPt - padRightPt);
|
|
1525
1337
|
const lines = [];
|
|
1526
1338
|
const nestedTables = [];
|
|
@@ -1569,7 +1381,7 @@ var BORDER_STYLE_RANK = {
|
|
|
1569
1381
|
};
|
|
1570
1382
|
function borderWeight(b) {
|
|
1571
1383
|
if (!b || b.style === "none") return 0;
|
|
1572
|
-
return b.
|
|
1384
|
+
return b.width ?? .5;
|
|
1573
1385
|
}
|
|
1574
1386
|
function heavierBorder(a, b) {
|
|
1575
1387
|
const wa = borderWeight(a);
|
|
@@ -1715,7 +1527,7 @@ function paginateSections(blocks, sectionCtxs, builder, defaultLang = "en-US") {
|
|
|
1715
1527
|
const h = computeLineHeight(line, block.resolved);
|
|
1716
1528
|
if (cursorY - h < ctx.marginBottom && current.length > 0) flushPage();
|
|
1717
1529
|
cursorY -= h;
|
|
1718
|
-
const indentLeft = block.resolved.
|
|
1530
|
+
const indentLeft = block.resolved.indentLeft + (line.firstLine ? block.resolved.indentFirstLine : 0);
|
|
1719
1531
|
const offset = alignmentOffset(block.resolved.alignment, line.contentWidthPt, line.availableWidthPt);
|
|
1720
1532
|
current.push({
|
|
1721
1533
|
type: "line",
|
|
@@ -1998,7 +1810,7 @@ function splitRowIntoChunks(row, capacity) {
|
|
|
1998
1810
|
function emitCellBorders(out, cell, cellX, cellY, rowHeight, rowIdx, rowCount, colCount) {
|
|
1999
1811
|
const pushSide = (side, border) => {
|
|
2000
1812
|
if (!border || border.style === "none") return;
|
|
2001
|
-
const sz =
|
|
1813
|
+
const sz = border.width ?? DEFAULT_BORDER_SIZE_EIGHTH * EIGHTH_PT;
|
|
2002
1814
|
out.push({
|
|
2003
1815
|
type: "border",
|
|
2004
1816
|
side,
|
|
@@ -2015,303 +1827,5 @@ function emitCellBorders(out, cell, cellX, cellY, rowHeight, rowIdx, rowCount, c
|
|
|
2015
1827
|
if (rowIdx === rowCount - 1) pushSide("bottom", cell.borders.bottom);
|
|
2016
1828
|
if (cell.colStart + cell.colSpan - 1 === colCount - 1) pushSide("right", cell.borders.right);
|
|
2017
1829
|
}
|
|
2018
|
-
function emitTaggedRuns(out, cmds, tagging, body) {
|
|
2019
|
-
if (!tagging) {
|
|
2020
|
-
for (const c of cmds) body(c);
|
|
2021
|
-
return;
|
|
2022
|
-
}
|
|
2023
|
-
let openKey = null;
|
|
2024
|
-
const close = () => {
|
|
2025
|
-
if (openKey !== null) {
|
|
2026
|
-
out.push("EMC");
|
|
2027
|
-
openKey = null;
|
|
2028
|
-
}
|
|
2029
|
-
};
|
|
2030
|
-
for (const c of cmds) {
|
|
2031
|
-
const key = c.structId !== void 0 ? `f${c.structId}` : c.artifact === "pagination" ? "p" : "a";
|
|
2032
|
-
if (key !== openKey) {
|
|
2033
|
-
close();
|
|
2034
|
-
if (c.structId !== void 0) {
|
|
2035
|
-
const mcid = tagging.next++;
|
|
2036
|
-
tagging.assigned = true;
|
|
2037
|
-
tagging.record(c.structId, mcid);
|
|
2038
|
-
out.push(`/${tagging.tagFor(c.structId)} <</MCID ${mcid}>> BDC`);
|
|
2039
|
-
} else if (c.artifact === "pagination") out.push("/Artifact <</Type /Pagination>> BDC");
|
|
2040
|
-
else out.push("/Artifact BMC");
|
|
2041
|
-
openKey = key;
|
|
2042
|
-
}
|
|
2043
|
-
body(c);
|
|
2044
|
-
}
|
|
2045
|
-
close();
|
|
2046
|
-
}
|
|
2047
|
-
function emitPageContent(commands, tagging) {
|
|
2048
|
-
if (commands.length === 0) return new Uint8Array(0);
|
|
2049
|
-
const out = [];
|
|
2050
|
-
const fills = commands.filter((c) => c.type === "fill");
|
|
2051
|
-
if (fills.length > 0) {
|
|
2052
|
-
if (tagging) out.push("/Artifact BMC");
|
|
2053
|
-
out.push("q");
|
|
2054
|
-
let lastColor = "";
|
|
2055
|
-
for (const f of fills) {
|
|
2056
|
-
const color = f.fillColorHex;
|
|
2057
|
-
if (color !== lastColor) {
|
|
2058
|
-
const [r, g, b] = hexToRgb01(color);
|
|
2059
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
2060
|
-
lastColor = color;
|
|
2061
|
-
}
|
|
2062
|
-
out.push(`${formatNumber(f.x)} ${formatNumber(f.y)} ${formatNumber(f.width)} ${formatNumber(f.height)} re`);
|
|
2063
|
-
out.push("f");
|
|
2064
|
-
}
|
|
2065
|
-
out.push("Q");
|
|
2066
|
-
if (tagging) out.push("EMC");
|
|
2067
|
-
}
|
|
2068
|
-
emitTaggedRuns(out, commands.filter((c) => c.type === "image" && !!c.imageResourceName), tagging, (img) => {
|
|
2069
|
-
out.push("q");
|
|
2070
|
-
out.push(`${formatNumber(img.width)} 0 0 ${formatNumber(img.height)} ${formatNumber(img.x)} ${formatNumber(img.y)} cm`);
|
|
2071
|
-
out.push(`/${img.imageResourceName} Do`);
|
|
2072
|
-
out.push("Q");
|
|
2073
|
-
});
|
|
2074
|
-
const borders = commands.filter((c) => c.type === "border");
|
|
2075
|
-
if (borders.length > 0) {
|
|
2076
|
-
if (tagging) out.push("/Artifact BMC");
|
|
2077
|
-
out.push("q");
|
|
2078
|
-
let lastWidth = -1;
|
|
2079
|
-
let lastColor = "";
|
|
2080
|
-
for (const b of borders) {
|
|
2081
|
-
const width = b.borderSizePt;
|
|
2082
|
-
const color = b.borderColorHex;
|
|
2083
|
-
if (width !== lastWidth) {
|
|
2084
|
-
out.push(`${formatNumber(width)} w`);
|
|
2085
|
-
lastWidth = width;
|
|
2086
|
-
}
|
|
2087
|
-
if (color !== lastColor) {
|
|
2088
|
-
const [r, g, bl] = hexToRgb01(color);
|
|
2089
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(bl)} RG`);
|
|
2090
|
-
lastColor = color;
|
|
2091
|
-
}
|
|
2092
|
-
const x = b.x;
|
|
2093
|
-
const y = b.y;
|
|
2094
|
-
const w = b.width;
|
|
2095
|
-
const h = b.height;
|
|
2096
|
-
switch (b.side) {
|
|
2097
|
-
case "top":
|
|
2098
|
-
out.push(`${formatNumber(x)} ${formatNumber(y + h)} m`);
|
|
2099
|
-
out.push(`${formatNumber(x + w)} ${formatNumber(y + h)} l`);
|
|
2100
|
-
break;
|
|
2101
|
-
case "bottom":
|
|
2102
|
-
out.push(`${formatNumber(x)} ${formatNumber(y)} m`);
|
|
2103
|
-
out.push(`${formatNumber(x + w)} ${formatNumber(y)} l`);
|
|
2104
|
-
break;
|
|
2105
|
-
case "left":
|
|
2106
|
-
out.push(`${formatNumber(x)} ${formatNumber(y)} m`);
|
|
2107
|
-
out.push(`${formatNumber(x)} ${formatNumber(y + h)} l`);
|
|
2108
|
-
break;
|
|
2109
|
-
case "right":
|
|
2110
|
-
out.push(`${formatNumber(x + w)} ${formatNumber(y)} m`);
|
|
2111
|
-
out.push(`${formatNumber(x + w)} ${formatNumber(y + h)} l`);
|
|
2112
|
-
break;
|
|
2113
|
-
}
|
|
2114
|
-
out.push("S");
|
|
2115
|
-
}
|
|
2116
|
-
out.push("Q");
|
|
2117
|
-
if (tagging) out.push("EMC");
|
|
2118
|
-
}
|
|
2119
|
-
emitTaggedRuns(out, commands.filter((c) => c.type === "shape"), tagging, (sh) => {
|
|
2120
|
-
for (const op of emitVectorShape(sh.shape)) out.push(op);
|
|
2121
|
-
});
|
|
2122
|
-
const lines = commands.filter((c) => c.type === "line");
|
|
2123
|
-
if (lines.length > 0) {
|
|
2124
|
-
let inBT = false;
|
|
2125
|
-
let lastFont = "";
|
|
2126
|
-
let lastSize = -1;
|
|
2127
|
-
let lastColor = "";
|
|
2128
|
-
const switchFontIfNeeded = (tok) => {
|
|
2129
|
-
const fontKey = tok.font.resourceName;
|
|
2130
|
-
if (fontKey !== lastFont || tok.fontSizePt !== lastSize) {
|
|
2131
|
-
out.push(`/${fontKey} ${formatNumber(tok.fontSizePt)} Tf`);
|
|
2132
|
-
lastFont = fontKey;
|
|
2133
|
-
lastSize = tok.fontSizePt;
|
|
2134
|
-
}
|
|
2135
|
-
if (tok.resolvedRun.colorHex !== lastColor) {
|
|
2136
|
-
const [r, g, b] = hexToRgb01(tok.resolvedRun.colorHex);
|
|
2137
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
2138
|
-
lastColor = tok.resolvedRun.colorHex;
|
|
2139
|
-
}
|
|
2140
|
-
};
|
|
2141
|
-
const emitImageToken = (tok, x, baselineY) => {
|
|
2142
|
-
if (!tok.imageResourceName) return;
|
|
2143
|
-
if (inBT) {
|
|
2144
|
-
out.push("ET");
|
|
2145
|
-
inBT = false;
|
|
2146
|
-
}
|
|
2147
|
-
out.push("q");
|
|
2148
|
-
out.push(`${formatNumber(tok.widthPt)} 0 0 ${formatNumber(tok.heightPt)} ${formatNumber(x)} ${formatNumber(baselineY)} cm`);
|
|
2149
|
-
out.push(`/${tok.imageResourceName} Do`);
|
|
2150
|
-
out.push("Q");
|
|
2151
|
-
lastFont = "";
|
|
2152
|
-
lastSize = -1;
|
|
2153
|
-
lastColor = "";
|
|
2154
|
-
};
|
|
2155
|
-
const emitMathToken = (tok, originX, baselineY) => {
|
|
2156
|
-
for (const it of tok.items) if (it.kind === "glyph") {
|
|
2157
|
-
if (!inBT) {
|
|
2158
|
-
out.push("BT");
|
|
2159
|
-
inBT = true;
|
|
2160
|
-
}
|
|
2161
|
-
if (it.font.resourceName !== lastFont || it.sizePt !== lastSize) {
|
|
2162
|
-
out.push(`/${it.font.resourceName} ${formatNumber(it.sizePt)} Tf`);
|
|
2163
|
-
lastFont = it.font.resourceName;
|
|
2164
|
-
lastSize = it.sizePt;
|
|
2165
|
-
}
|
|
2166
|
-
if (lastColor !== "000000") {
|
|
2167
|
-
out.push("0 0 0 rg");
|
|
2168
|
-
lastColor = "000000";
|
|
2169
|
-
}
|
|
2170
|
-
out.push(`1 0 0 1 ${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} Tm`);
|
|
2171
|
-
out.push(`<${it.font.embedded.encodeTextAsCidHex(it.text)}> Tj`);
|
|
2172
|
-
} else if (it.kind === "rule") {
|
|
2173
|
-
if (inBT) {
|
|
2174
|
-
out.push("ET");
|
|
2175
|
-
inBT = false;
|
|
2176
|
-
}
|
|
2177
|
-
out.push("q");
|
|
2178
|
-
out.push("0 0 0 rg");
|
|
2179
|
-
out.push(`${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} ${formatNumber(it.w)} ${formatNumber(it.h)} re`);
|
|
2180
|
-
out.push("f");
|
|
2181
|
-
out.push("Q");
|
|
2182
|
-
lastFont = "";
|
|
2183
|
-
lastSize = -1;
|
|
2184
|
-
lastColor = "";
|
|
2185
|
-
} else {
|
|
2186
|
-
if (inBT) {
|
|
2187
|
-
out.push("ET");
|
|
2188
|
-
inBT = false;
|
|
2189
|
-
}
|
|
2190
|
-
const shape = {
|
|
2191
|
-
paths: [{ segments: it.segments }],
|
|
2192
|
-
...it.fill ? { fillColorHex: "000000" } : {},
|
|
2193
|
-
...it.strokeWidthPt !== void 0 ? { stroke: {
|
|
2194
|
-
colorHex: "000000",
|
|
2195
|
-
widthPt: it.strokeWidthPt
|
|
2196
|
-
} } : {},
|
|
2197
|
-
transform: [
|
|
2198
|
-
1,
|
|
2199
|
-
0,
|
|
2200
|
-
0,
|
|
2201
|
-
1,
|
|
2202
|
-
originX,
|
|
2203
|
-
baselineY
|
|
2204
|
-
]
|
|
2205
|
-
};
|
|
2206
|
-
for (const op of emitVectorShape(shape)) out.push(op);
|
|
2207
|
-
lastFont = "";
|
|
2208
|
-
lastSize = -1;
|
|
2209
|
-
lastColor = "";
|
|
2210
|
-
}
|
|
2211
|
-
};
|
|
2212
|
-
const emitOneLine = (cmd) => {
|
|
2213
|
-
const line = cmd.line;
|
|
2214
|
-
const originX = cmd.originX;
|
|
2215
|
-
const baselineY = cmd.baselineY;
|
|
2216
|
-
const extraPerSpace = computeJustifyExtra(line);
|
|
2217
|
-
const hasImageToken = line.tokens.some((t) => t.kind === "image");
|
|
2218
|
-
const hasMathToken = line.tokens.some((t) => t.kind === "math");
|
|
2219
|
-
const hasRtl = line.tokens.some((t) => t.bidiLevel % 2 === 1);
|
|
2220
|
-
const encodeToken = (tok) => {
|
|
2221
|
-
const text = tok.bidiLevel % 2 === 1 ? reverseByCodePoint(tok.text) : tok.text;
|
|
2222
|
-
return tok.font.embedded.encodeTextAsCidHex(text);
|
|
2223
|
-
};
|
|
2224
|
-
if (extraPerSpace > 0 || hasImageToken || hasMathToken || hasRtl) {
|
|
2225
|
-
const order = hasRtl ? lineVisualOrder(line) : line.tokens.map((_, i) => i);
|
|
2226
|
-
let x = originX;
|
|
2227
|
-
for (const ti of order) {
|
|
2228
|
-
const tok = line.tokens[ti];
|
|
2229
|
-
if (tok.kind === "image") {
|
|
2230
|
-
emitImageToken(tok, x, baselineY);
|
|
2231
|
-
x += tok.widthPt;
|
|
2232
|
-
continue;
|
|
2233
|
-
}
|
|
2234
|
-
if (tok.kind === "math") {
|
|
2235
|
-
emitMathToken(tok, x, baselineY);
|
|
2236
|
-
x += tok.widthPt;
|
|
2237
|
-
continue;
|
|
2238
|
-
}
|
|
2239
|
-
if (!inBT) {
|
|
2240
|
-
out.push("BT");
|
|
2241
|
-
inBT = true;
|
|
2242
|
-
}
|
|
2243
|
-
switchFontIfNeeded(tok);
|
|
2244
|
-
out.push(`1 0 0 1 ${formatNumber(x)} ${formatNumber(baselineY)} Tm`);
|
|
2245
|
-
out.push(`<${encodeToken(tok)}> Tj`);
|
|
2246
|
-
x += tok.widthPt;
|
|
2247
|
-
if (tok.isSpace) x += extraPerSpace;
|
|
2248
|
-
}
|
|
2249
|
-
} else {
|
|
2250
|
-
if (!inBT) {
|
|
2251
|
-
out.push("BT");
|
|
2252
|
-
inBT = true;
|
|
2253
|
-
}
|
|
2254
|
-
out.push(`1 0 0 1 ${formatNumber(originX)} ${formatNumber(baselineY)} Tm`);
|
|
2255
|
-
for (const tok of line.tokens) {
|
|
2256
|
-
if (tok.kind !== "text") continue;
|
|
2257
|
-
switchFontIfNeeded(tok);
|
|
2258
|
-
const hex = tok.font.embedded.encodeTextAsCidHex(tok.text);
|
|
2259
|
-
out.push(`<${hex}> Tj`);
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
};
|
|
2263
|
-
if (tagging) for (const cmd of lines) {
|
|
2264
|
-
if (inBT) {
|
|
2265
|
-
out.push("ET");
|
|
2266
|
-
inBT = false;
|
|
2267
|
-
}
|
|
2268
|
-
const sid = cmd.structId;
|
|
2269
|
-
if (sid !== void 0) {
|
|
2270
|
-
const mcid = tagging.next++;
|
|
2271
|
-
tagging.assigned = true;
|
|
2272
|
-
tagging.record(sid, mcid);
|
|
2273
|
-
out.push(`/${tagging.tagFor(sid)} <</MCID ${mcid}>> BDC`);
|
|
2274
|
-
} else if (cmd.artifact === "pagination") out.push("/Artifact <</Type /Pagination>> BDC");
|
|
2275
|
-
else out.push("/Artifact BMC");
|
|
2276
|
-
emitOneLine(cmd);
|
|
2277
|
-
if (inBT) {
|
|
2278
|
-
out.push("ET");
|
|
2279
|
-
inBT = false;
|
|
2280
|
-
}
|
|
2281
|
-
out.push("EMC");
|
|
2282
|
-
}
|
|
2283
|
-
else {
|
|
2284
|
-
out.push("BT");
|
|
2285
|
-
inBT = true;
|
|
2286
|
-
for (const cmd of lines) emitOneLine(cmd);
|
|
2287
|
-
if (inBT) out.push("ET");
|
|
2288
|
-
}
|
|
2289
|
-
}
|
|
2290
|
-
return encoder.encode(out.join("\n"));
|
|
2291
|
-
}
|
|
2292
|
-
function lineVisualOrder(line) {
|
|
2293
|
-
return reorderVisual(line.tokens.map((t) => t.bidiLevel));
|
|
2294
|
-
}
|
|
2295
|
-
function computeJustifyExtra(line) {
|
|
2296
|
-
if (line.resolved.alignment !== "both") return 0;
|
|
2297
|
-
if (line.isLastInParagraph) return 0;
|
|
2298
|
-
let spaces = 0;
|
|
2299
|
-
for (const tok of line.tokens) if (tok.isSpace) spaces++;
|
|
2300
|
-
if (spaces === 0) return 0;
|
|
2301
|
-
const extra = line.availableWidthPt - line.contentWidthPt;
|
|
2302
|
-
if (extra <= 0) return 0;
|
|
2303
|
-
return extra / spaces;
|
|
2304
|
-
}
|
|
2305
|
-
function hexToRgb01(hex) {
|
|
2306
|
-
return [
|
|
2307
|
-
parseInt(hex.slice(0, 2), 16) / 255,
|
|
2308
|
-
parseInt(hex.slice(2, 4), 16) / 255,
|
|
2309
|
-
parseInt(hex.slice(4, 6), 16) / 255
|
|
2310
|
-
];
|
|
2311
|
-
}
|
|
2312
|
-
function formatNumber(n) {
|
|
2313
|
-
if (Number.isInteger(n)) return String(n);
|
|
2314
|
-
return n.toFixed(3).replace(/0+$/, "").replace(/\.$/, "");
|
|
2315
|
-
}
|
|
2316
1830
|
//#endregion
|
|
2317
|
-
export { renderStyledPdf };
|
|
1831
|
+
export { layoutStyledDocument, paintPlan, renderStyledPdf };
|