reamkit 1.20.0 → 1.22.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/dist/esm/core/bytes.d.ts +22 -4
- package/dist/esm/core/bytes.js +73 -5
- package/dist/esm/core/crypto/offcrypto.d.ts +1 -0
- package/dist/esm/core/crypto/offcrypto.js +2 -1
- package/dist/esm/core/document-model/types.d.ts +60 -0
- package/dist/esm/core/drawingml/chart-parser.d.ts +2 -1
- package/dist/esm/core/drawingml/chart-parser.js +23 -1
- package/dist/esm/core/drawingml/colors.d.ts +27 -3
- package/dist/esm/core/drawingml/colors.js +30 -6
- package/dist/esm/core/drawingml/preset-geometry.js +236 -0
- package/dist/esm/core/metafile/emf.js +2 -1
- package/dist/esm/core/metafile/symbol-fonts.d.ts +42 -0
- package/dist/esm/core/metafile/symbol-fonts.js +154 -0
- package/dist/esm/core/metafile/wmf.js +35 -2
- package/dist/esm/core/vector.d.ts +5 -0
- package/dist/esm/excel/sheet-shape-parser.js +1 -12
- package/dist/esm/excel/xlsx-reader.d.ts +1 -1
- package/dist/esm/excel/xlsx-reader.js +3 -3
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/layout/page-doc.d.ts +38 -0
- package/dist/esm/layout/page-doc.js +34 -18
- package/dist/esm/layout/styled-layout.js +174 -49
- package/dist/esm/pdf/shading.d.ts +19 -0
- package/dist/esm/pdf/shading.js +84 -11
- package/dist/esm/pdf/styled-page-emitter.js +614 -444
- package/dist/esm/pptx/ole-preview.d.ts +10 -0
- package/dist/esm/pptx/ole-preview.js +52 -0
- package/dist/esm/pptx/placeholder-cascade.d.ts +69 -5
- package/dist/esm/pptx/placeholder-cascade.js +162 -25
- package/dist/esm/pptx/pptx-reader.js +247 -39
- package/dist/esm/pptx/slide-parser.d.ts +72 -10
- package/dist/esm/pptx/slide-parser.js +310 -82
- package/dist/esm/pptx/sp-helpers.js +19 -4
- package/dist/esm/pptx/table-style.d.ts +56 -0
- package/dist/esm/pptx/table-style.js +161 -0
- package/dist/esm/svg/svg-writer.js +53 -5
- package/dist/esm/word/docx-reader.js +2 -2
- package/dist/esm/word/drawing-parser.d.ts +34 -0
- package/dist/esm/word/drawing-parser.js +159 -13
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import { reverseByCodePoint } from "../core/bidi/index.js";
|
|
|
6
6
|
import { GLUE_SHRINK_RATIO } from "../layout/styled-layout.js";
|
|
7
7
|
import { paintPlan } from "../layout/page-doc.js";
|
|
8
8
|
import { emitClipPath, emitVectorShape, shadowBlurLayers } from "./vector-graphics.js";
|
|
9
|
-
import { buildGradientPattern, shapeBbox } from "./shading.js";
|
|
9
|
+
import { buildGradientAlphaMask, buildGradientPattern, shapeBbox } from "./shading.js";
|
|
10
10
|
import { sanitizeHref } from "../core/links.js";
|
|
11
11
|
import { embedAssociatedFile } from "./embedded-file.js";
|
|
12
12
|
import { buildSrgbIccProfile } from "./icc-profile.js";
|
|
@@ -99,11 +99,20 @@ function assembleStyledPdf(laid, options, doc) {
|
|
|
99
99
|
let annotParentCount = 0;
|
|
100
100
|
const fontResourceDict = buildFontResourceDict(laid.fontResources, embeddedFonts);
|
|
101
101
|
const xobjectResourceDict = buildXObjectResourceDict(laid.imageResources, embeddedImages);
|
|
102
|
+
const imageRefByName = /* @__PURE__ */ new Map();
|
|
103
|
+
for (const [resourceId, res] of laid.imageResources) {
|
|
104
|
+
const r = embeddedImages.get(resourceId);
|
|
105
|
+
if (r) imageRefByName.set(res.resourceName, r);
|
|
106
|
+
}
|
|
102
107
|
const gradientNames = /* @__PURE__ */ new Map();
|
|
108
|
+
const gradientMaskNames = /* @__PURE__ */ new Map();
|
|
103
109
|
const patternEntries = {};
|
|
110
|
+
const extGStateEntries = {};
|
|
104
111
|
if (!pdfaProfile) for (const page of renderedPages) {
|
|
105
112
|
const ph = page.height;
|
|
106
|
-
|
|
113
|
+
const plan = paintPlan(page.commands);
|
|
114
|
+
const shapesNeedingPatterns = [...plan.shapes, ...[...plan.behind, ...plan.pictures.flat()].filter((i) => i.type === "shape")];
|
|
115
|
+
for (const item of shapesNeedingPatterns) {
|
|
107
116
|
const gradient = item.shape.fillGradient;
|
|
108
117
|
if (!gradient) continue;
|
|
109
118
|
const bbox = shapeBbox(item.shape);
|
|
@@ -120,10 +129,65 @@ function assembleStyledPdf(laid, options, doc) {
|
|
|
120
129
|
const nm = `Sh${gradientNames.size}`;
|
|
121
130
|
patternEntries[nm] = ref(buildGradientPattern(doc, gradient, bbox, ctm).id);
|
|
122
131
|
gradientNames.set(item.shape, nm);
|
|
132
|
+
const mask = buildGradientAlphaMask(doc, gradient, bbox, ctm);
|
|
133
|
+
if (mask) {
|
|
134
|
+
const gs = `GSm${gradientMaskNames.size}`;
|
|
135
|
+
gradientMaskNames.set(item.shape, gs);
|
|
136
|
+
extGStateEntries[gs] = dict({ SMask: dict({
|
|
137
|
+
S: name("Luminosity"),
|
|
138
|
+
G: ref(mask.id),
|
|
139
|
+
BC: [0]
|
|
140
|
+
}) });
|
|
141
|
+
}
|
|
123
142
|
}
|
|
124
143
|
}
|
|
144
|
+
const duotoneStates = /* @__PURE__ */ new Map();
|
|
145
|
+
const wantDuotone = (item, pageHeight) => {
|
|
146
|
+
if (!item.duotone || item.imageResourceName === "" || pdfaProfile) return void 0;
|
|
147
|
+
const key = [
|
|
148
|
+
item.imageResourceName,
|
|
149
|
+
Math.round(item.x * 100),
|
|
150
|
+
Math.round(item.y * 100),
|
|
151
|
+
Math.round(item.width * 100),
|
|
152
|
+
Math.round(item.height * 100)
|
|
153
|
+
].join("|");
|
|
154
|
+
const known = duotoneStates.get(key);
|
|
155
|
+
if (known !== void 0) return known;
|
|
156
|
+
const imageRef = imageRefByName.get(item.imageResourceName);
|
|
157
|
+
if (!imageRef) return void 0;
|
|
158
|
+
const form = doc.add(stream({
|
|
159
|
+
Type: name("XObject"),
|
|
160
|
+
Subtype: name("Form"),
|
|
161
|
+
BBox: [
|
|
162
|
+
0,
|
|
163
|
+
0,
|
|
164
|
+
item.width,
|
|
165
|
+
item.height
|
|
166
|
+
],
|
|
167
|
+
Matrix: [
|
|
168
|
+
1,
|
|
169
|
+
0,
|
|
170
|
+
0,
|
|
171
|
+
1,
|
|
172
|
+
item.x,
|
|
173
|
+
pageHeight - item.y - item.height
|
|
174
|
+
],
|
|
175
|
+
Group: dict({
|
|
176
|
+
S: name("Transparency"),
|
|
177
|
+
CS: name("DeviceGray")
|
|
178
|
+
}),
|
|
179
|
+
Resources: dict({ XObject: dict({ [item.imageResourceName]: ref(imageRef.id) }) })
|
|
180
|
+
}, encoder.encode(`q ${formatNumber(item.width)} 0 0 ${formatNumber(item.height)} 0 0 cm /${item.imageResourceName} Do Q`)));
|
|
181
|
+
const nm = `GSd${duotoneStates.size}`;
|
|
182
|
+
duotoneStates.set(key, nm);
|
|
183
|
+
extGStateEntries[nm] = dict({ SMask: dict({
|
|
184
|
+
S: name("Luminosity"),
|
|
185
|
+
G: ref(form.id),
|
|
186
|
+
BC: [0]
|
|
187
|
+
}) });
|
|
188
|
+
return nm;
|
|
189
|
+
};
|
|
125
190
|
const alphaStateNames = /* @__PURE__ */ new Map();
|
|
126
|
-
const extGStateEntries = {};
|
|
127
191
|
const wantAlpha = (alpha) => {
|
|
128
192
|
if (alpha === void 0 || alpha >= 1) return;
|
|
129
193
|
const key = Math.round(alpha * 1e3) / 1e3;
|
|
@@ -142,7 +206,23 @@ function assembleStyledPdf(laid, options, doc) {
|
|
|
142
206
|
if (s) wantAlpha(shadowBlurLayers(s).alpha);
|
|
143
207
|
wantAlpha(item.shape.fillAlpha);
|
|
144
208
|
}
|
|
145
|
-
for (const img of plan.images)
|
|
209
|
+
for (const img of plan.images) {
|
|
210
|
+
wantAlpha(washVeil(img.wash)?.alpha);
|
|
211
|
+
wantAlpha(img.alpha);
|
|
212
|
+
wantDuotone(img, page.height);
|
|
213
|
+
}
|
|
214
|
+
for (const item of [...plan.behind, ...plan.pictures.flat()]) {
|
|
215
|
+
if (item.type === "image") {
|
|
216
|
+
wantAlpha(washVeil(item.wash)?.alpha);
|
|
217
|
+
wantAlpha(item.alpha);
|
|
218
|
+
wantDuotone(item, page.height);
|
|
219
|
+
}
|
|
220
|
+
if (item.type === "shape") {
|
|
221
|
+
const s = item.shape.shadow;
|
|
222
|
+
if (s) wantAlpha(shadowBlurLayers(s).alpha);
|
|
223
|
+
wantAlpha(item.shape.fillAlpha);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
146
226
|
for (const line of plan.lines) for (const tok of line.line.tokens) {
|
|
147
227
|
if (tok.kind === "image" && tok.shadow) wantAlpha(shadowBlurLayers(tok.shadow).alpha);
|
|
148
228
|
if (tok.kind === "image") wantAlpha(washVeil(tok.wash)?.alpha);
|
|
@@ -179,7 +259,7 @@ function assembleStyledPdf(laid, options, doc) {
|
|
|
179
259
|
tagFor: (structId) => builder.node(structId).type
|
|
180
260
|
};
|
|
181
261
|
}
|
|
182
|
-
const { content: contentBytes, links } = emitPageContent(page, pageTagging, gradientNames, alphaStateNames);
|
|
262
|
+
const { content: contentBytes, links } = emitPageContent(page, pageTagging, gradientNames, alphaStateNames, wantDuotone, gradientMaskNames);
|
|
183
263
|
const contentsRef = doc.add(stream({}, contentBytes));
|
|
184
264
|
const pageEntries = {
|
|
185
265
|
Type: name("Page"),
|
|
@@ -449,6 +529,32 @@ function buildFontResourceDict(resources, embedded) {
|
|
|
449
529
|
}
|
|
450
530
|
return dict(entries);
|
|
451
531
|
}
|
|
532
|
+
/**
|
|
533
|
+
* The operators that paint one picture: normally the XObject itself, but for a
|
|
534
|
+
* §20.1.8.23 duotone the two colours it is recoloured between, composited
|
|
535
|
+
* through the picture's own luminosity (`state` is that soft-mask ExtGState).
|
|
536
|
+
*
|
|
537
|
+
* @param item The image to paint.
|
|
538
|
+
* @param yUp Its bottom edge in the page's y-up frame.
|
|
539
|
+
* @param state The duotone's soft-mask state name, when it has one.
|
|
540
|
+
* @returns The operators, without the surrounding `q`/`Q`.
|
|
541
|
+
*/
|
|
542
|
+
function paintImageBody(item, yUp, state) {
|
|
543
|
+
const place = placeImage(item.x, yUp, item.width, item.height, item.crop, item.rotationDeg, item.flipH, item.flipV);
|
|
544
|
+
if (state === void 0 || !item.duotone) return [...place, `/${item.imageResourceName} Do`];
|
|
545
|
+
const rect = `${formatNumber(item.x)} ${formatNumber(yUp)} ${formatNumber(item.width)} ${formatNumber(item.height)} re`;
|
|
546
|
+
const [sr, sg, sb] = hexToRgb01(item.duotone.shadowHex);
|
|
547
|
+
const [hr, hg, hb] = hexToRgb01(item.duotone.highlightHex);
|
|
548
|
+
return [
|
|
549
|
+
`${formatNumber(sr)} ${formatNumber(sg)} ${formatNumber(sb)} rg`,
|
|
550
|
+
rect,
|
|
551
|
+
"f",
|
|
552
|
+
`/${state} gs`,
|
|
553
|
+
`${formatNumber(hr)} ${formatNumber(hg)} ${formatNumber(hb)} rg`,
|
|
554
|
+
rect,
|
|
555
|
+
"f"
|
|
556
|
+
];
|
|
557
|
+
}
|
|
452
558
|
function buildXObjectResourceDict(resources, embedded) {
|
|
453
559
|
if (embedded.size === 0) return void 0;
|
|
454
560
|
const entries = {};
|
|
@@ -520,7 +626,7 @@ function dashPatternFor(style) {
|
|
|
520
626
|
const pattern = style !== void 0 ? BORDER_DASHES.get(style) : void 0;
|
|
521
627
|
return pattern ? `[${pattern.map(formatNumber).join(" ")}]` : "";
|
|
522
628
|
}
|
|
523
|
-
function emitPageContent(page, tagging, gradientNames, alphaStateNames) {
|
|
629
|
+
function emitPageContent(page, tagging, gradientNames, alphaStateNames, duotoneStateFor, gradientMaskNames) {
|
|
524
630
|
const commands = page.commands;
|
|
525
631
|
const links = [];
|
|
526
632
|
if (commands.length === 0) return {
|
|
@@ -530,17 +636,503 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames) {
|
|
|
530
636
|
const H = page.height;
|
|
531
637
|
const out = [];
|
|
532
638
|
const plan = paintPlan(commands);
|
|
639
|
+
const lines = plan.lines;
|
|
640
|
+
let inBT = false;
|
|
641
|
+
let lastFont = "";
|
|
642
|
+
let lastTc = 0;
|
|
643
|
+
let lastSize = -1;
|
|
644
|
+
let lastColor = "";
|
|
645
|
+
const switchFontIfNeeded = (tok) => {
|
|
646
|
+
const fontKey = tok.font.resourceName;
|
|
647
|
+
if (fontKey !== lastFont || tok.fontSizePt !== lastSize) {
|
|
648
|
+
out.push(`/${fontKey} ${formatNumber(tok.fontSizePt)} Tf`);
|
|
649
|
+
lastFont = fontKey;
|
|
650
|
+
lastSize = tok.fontSizePt;
|
|
651
|
+
}
|
|
652
|
+
const tc = tok.resolvedRun.letterSpacingPt ?? 0;
|
|
653
|
+
if (tc !== lastTc) {
|
|
654
|
+
out.push(`${formatNumber(tc)} Tc`);
|
|
655
|
+
lastTc = tc;
|
|
656
|
+
}
|
|
657
|
+
if (tok.resolvedRun.colorHex !== lastColor) {
|
|
658
|
+
const [r, g, b] = hexToRgb01(tok.resolvedRun.colorHex);
|
|
659
|
+
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
660
|
+
lastColor = tok.resolvedRun.colorHex;
|
|
661
|
+
}
|
|
662
|
+
};
|
|
663
|
+
const emitImageToken = (tok, x, baselineY) => {
|
|
664
|
+
const meta = tok.metafile;
|
|
665
|
+
if (meta) {
|
|
666
|
+
if (inBT) {
|
|
667
|
+
out.push("ET");
|
|
668
|
+
inBT = false;
|
|
669
|
+
}
|
|
670
|
+
const b = tok.drawBox;
|
|
671
|
+
const ox = x + (b?.dxPt ?? 0);
|
|
672
|
+
const oy = baselineY + (b?.dyPt ?? 0);
|
|
673
|
+
for (const sh of meta.shapes) for (const op of emitVectorShape({
|
|
674
|
+
...sh,
|
|
675
|
+
transform: [
|
|
676
|
+
1,
|
|
677
|
+
0,
|
|
678
|
+
0,
|
|
679
|
+
1,
|
|
680
|
+
ox,
|
|
681
|
+
oy
|
|
682
|
+
]
|
|
683
|
+
})) out.push(op);
|
|
684
|
+
for (const t of meta.texts) {
|
|
685
|
+
const first = t.line.tokens.find((k) => k.kind === "text");
|
|
686
|
+
if (!first) continue;
|
|
687
|
+
const [r, g, bl] = hexToRgb01(first.resolvedRun.colorHex);
|
|
688
|
+
out.push("BT");
|
|
689
|
+
out.push(`/${first.font.resourceName} ${formatNumber(first.fontSizePt)} Tf`);
|
|
690
|
+
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(bl)} rg`);
|
|
691
|
+
out.push(`1 0 0 1 ${formatNumber(ox + t.x)} ${formatNumber(oy + t.y)} Tm`);
|
|
692
|
+
out.push(first.font.measure.showText(first.text));
|
|
693
|
+
out.push("ET");
|
|
694
|
+
}
|
|
695
|
+
lastFont = "";
|
|
696
|
+
lastSize = -1;
|
|
697
|
+
lastColor = "";
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
700
|
+
if (!tok.imageResourceName) return;
|
|
701
|
+
if (inBT) {
|
|
702
|
+
out.push("ET");
|
|
703
|
+
inBT = false;
|
|
704
|
+
}
|
|
705
|
+
const shdw = tok.shadow;
|
|
706
|
+
if (shdw) {
|
|
707
|
+
const bx = tok.drawBox;
|
|
708
|
+
const [shr, shg, shb] = hexToRgb01(shdw.colorHex);
|
|
709
|
+
const layers = shadowBlurLayers(shdw);
|
|
710
|
+
const state = layers.alpha < 1 ? alphaStateNames?.get(Math.round(layers.alpha * 1e3) / 1e3) : void 0;
|
|
711
|
+
const sx = x + (bx?.dxPt ?? 0) + shdw.dxPt;
|
|
712
|
+
const sy = baselineY + (bx?.dyPt ?? 0) - shdw.dyPt;
|
|
713
|
+
const sw = bx?.widthPt ?? tok.widthPt;
|
|
714
|
+
const sh = bx?.heightPt ?? tok.heightPt;
|
|
715
|
+
out.push("q");
|
|
716
|
+
if (state) out.push(`/${state} gs`);
|
|
717
|
+
out.push(`${formatNumber(shr)} ${formatNumber(shg)} ${formatNumber(shb)} rg`);
|
|
718
|
+
for (let i = 0; i < layers.count; i++) {
|
|
719
|
+
const grow = layers.count > 1 ? -shdw.blurPt / 2 + (i + .5) * shdw.blurPt / layers.count : 0;
|
|
720
|
+
out.push(`${formatNumber(sx - grow)} ${formatNumber(sy - grow)} ${formatNumber(Math.max(sw + 2 * grow, 0))} ${formatNumber(Math.max(sh + 2 * grow, 0))} re`);
|
|
721
|
+
out.push("f");
|
|
722
|
+
}
|
|
723
|
+
out.push("Q");
|
|
724
|
+
}
|
|
725
|
+
out.push("q");
|
|
726
|
+
const b = tok.drawBox;
|
|
727
|
+
out.push(...b ? placeImage(x + b.dxPt, baselineY + b.dyPt, b.widthPt, b.heightPt, tok.crop, tok.rotationDeg, tok.flipH, tok.flipV) : placeImage(x, baselineY, tok.widthPt, tok.heightPt, tok.crop, tok.rotationDeg, tok.flipH, tok.flipV));
|
|
728
|
+
out.push(`/${tok.imageResourceName} Do`);
|
|
729
|
+
out.push(...washItems(tok.wash, alphaStateNames));
|
|
730
|
+
out.push("Q");
|
|
731
|
+
const frame = tok.outline;
|
|
732
|
+
if (frame) {
|
|
733
|
+
const [fr, fg, fb] = hexToRgb01(frame.colorHex);
|
|
734
|
+
out.push("q");
|
|
735
|
+
out.push(`${formatNumber(frame.widthPt)} w`);
|
|
736
|
+
out.push(`${formatNumber(fr)} ${formatNumber(fg)} ${formatNumber(fb)} RG`);
|
|
737
|
+
out.push(`${formatNumber(x + (b?.dxPt ?? 0))} ${formatNumber(baselineY + (b?.dyPt ?? 0))} ${formatNumber(b?.widthPt ?? tok.widthPt)} ${formatNumber(b?.heightPt ?? tok.heightPt)} re`);
|
|
738
|
+
out.push("S");
|
|
739
|
+
out.push("Q");
|
|
740
|
+
}
|
|
741
|
+
lastFont = "";
|
|
742
|
+
lastSize = -1;
|
|
743
|
+
lastColor = "";
|
|
744
|
+
lastTc = 0;
|
|
745
|
+
};
|
|
746
|
+
const emitMathToken = (tok, originX, baselineY) => {
|
|
747
|
+
for (const it of tok.items) if (it.kind === "glyph") {
|
|
748
|
+
if (!inBT) {
|
|
749
|
+
out.push("BT");
|
|
750
|
+
inBT = true;
|
|
751
|
+
}
|
|
752
|
+
if (it.font.resourceName !== lastFont || it.sizePt !== lastSize) {
|
|
753
|
+
out.push(`/${it.font.resourceName} ${formatNumber(it.sizePt)} Tf`);
|
|
754
|
+
lastFont = it.font.resourceName;
|
|
755
|
+
lastSize = it.sizePt;
|
|
756
|
+
}
|
|
757
|
+
if (lastColor !== "000000") {
|
|
758
|
+
out.push("0 0 0 rg");
|
|
759
|
+
lastColor = "000000";
|
|
760
|
+
}
|
|
761
|
+
out.push(`1 0 0 1 ${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} Tm`);
|
|
762
|
+
out.push(it.font.measure.showText(it.text));
|
|
763
|
+
} else if (it.kind === "rule") {
|
|
764
|
+
if (inBT) {
|
|
765
|
+
out.push("ET");
|
|
766
|
+
inBT = false;
|
|
767
|
+
}
|
|
768
|
+
out.push("q");
|
|
769
|
+
out.push("0 0 0 rg");
|
|
770
|
+
out.push(`${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} ${formatNumber(it.w)} ${formatNumber(it.h)} re`);
|
|
771
|
+
out.push("f");
|
|
772
|
+
out.push("Q");
|
|
773
|
+
lastFont = "";
|
|
774
|
+
lastSize = -1;
|
|
775
|
+
lastColor = "";
|
|
776
|
+
} else {
|
|
777
|
+
if (inBT) {
|
|
778
|
+
out.push("ET");
|
|
779
|
+
inBT = false;
|
|
780
|
+
}
|
|
781
|
+
const shape = {
|
|
782
|
+
paths: [{ segments: it.segments }],
|
|
783
|
+
...it.fill ? { fillColorHex: "000000" } : {},
|
|
784
|
+
...it.strokeWidthPt !== void 0 ? { stroke: {
|
|
785
|
+
colorHex: "000000",
|
|
786
|
+
widthPt: it.strokeWidthPt
|
|
787
|
+
} } : {},
|
|
788
|
+
transform: [
|
|
789
|
+
1,
|
|
790
|
+
0,
|
|
791
|
+
0,
|
|
792
|
+
1,
|
|
793
|
+
originX,
|
|
794
|
+
baselineY
|
|
795
|
+
]
|
|
796
|
+
};
|
|
797
|
+
for (const op of emitVectorShape(shape)) out.push(op);
|
|
798
|
+
lastFont = "";
|
|
799
|
+
lastSize = -1;
|
|
800
|
+
lastColor = "";
|
|
801
|
+
}
|
|
802
|
+
};
|
|
803
|
+
const emitClipped = (cmd, body) => {
|
|
804
|
+
const clip = cmd.clip;
|
|
805
|
+
if (!clip) {
|
|
806
|
+
body(cmd);
|
|
807
|
+
return;
|
|
808
|
+
}
|
|
809
|
+
if (inBT) {
|
|
810
|
+
out.push("ET");
|
|
811
|
+
inBT = false;
|
|
812
|
+
}
|
|
813
|
+
out.push("q");
|
|
814
|
+
out.push(`${formatNumber(clip.x)} ${formatNumber(H - clip.y - clip.height)} ${formatNumber(clip.width)} ${formatNumber(clip.height)} re W n`);
|
|
815
|
+
lastFont = "";
|
|
816
|
+
lastSize = -1;
|
|
817
|
+
lastColor = "";
|
|
818
|
+
lastTc = 0;
|
|
819
|
+
out.push("BT");
|
|
820
|
+
inBT = true;
|
|
821
|
+
body(cmd);
|
|
822
|
+
if (inBT) {
|
|
823
|
+
out.push("ET");
|
|
824
|
+
inBT = false;
|
|
825
|
+
}
|
|
826
|
+
out.push("Q");
|
|
827
|
+
lastFont = "";
|
|
828
|
+
lastSize = -1;
|
|
829
|
+
lastColor = "";
|
|
830
|
+
lastTc = 0;
|
|
831
|
+
};
|
|
832
|
+
const emitOneLine = (cmd) => {
|
|
833
|
+
const line = cmd.line;
|
|
834
|
+
const originX = cmd.originX;
|
|
835
|
+
const baselineY = H - cmd.baselineY;
|
|
836
|
+
const rotationDeg = cmd.rotationDeg ?? 0;
|
|
837
|
+
const lineFs = line.maxFontSizePt || 12;
|
|
838
|
+
const linkAscent = Math.max(lineFs, line.mathAscentPt ?? 0);
|
|
839
|
+
const linkDescent = Math.max(lineFs * .2, line.mathDescentPt ?? 0);
|
|
840
|
+
let linkHref;
|
|
841
|
+
let linkAnchor;
|
|
842
|
+
let linkText = "";
|
|
843
|
+
let linkX0 = 0;
|
|
844
|
+
let linkX1 = 0;
|
|
845
|
+
const flushLink = () => {
|
|
846
|
+
if (linkHref === void 0 && linkAnchor === void 0) return;
|
|
847
|
+
const safe = linkHref !== void 0 ? sanitizeHref(linkHref) : void 0;
|
|
848
|
+
const target = safe !== void 0 ? { href: safe } : linkAnchor !== void 0 ? { anchor: linkAnchor } : void 0;
|
|
849
|
+
if (target) links.push({
|
|
850
|
+
...target,
|
|
851
|
+
text: linkText.trim(),
|
|
852
|
+
rect: [
|
|
853
|
+
linkX0,
|
|
854
|
+
baselineY - linkDescent,
|
|
855
|
+
linkX1,
|
|
856
|
+
baselineY + linkAscent
|
|
857
|
+
],
|
|
858
|
+
...cmd.structId !== void 0 ? { structId: cmd.structId } : {}
|
|
859
|
+
});
|
|
860
|
+
linkHref = void 0;
|
|
861
|
+
linkAnchor = void 0;
|
|
862
|
+
linkText = "";
|
|
863
|
+
};
|
|
864
|
+
const trackLink = (href, anchor, text, x0, x1) => {
|
|
865
|
+
if (href !== linkHref || anchor !== linkAnchor) {
|
|
866
|
+
flushLink();
|
|
867
|
+
if (href !== void 0 || anchor !== void 0) {
|
|
868
|
+
linkHref = href;
|
|
869
|
+
linkAnchor = anchor;
|
|
870
|
+
linkX0 = x0;
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (href !== void 0 || anchor !== void 0) {
|
|
874
|
+
linkX1 = x1;
|
|
875
|
+
linkText += text;
|
|
876
|
+
}
|
|
877
|
+
};
|
|
878
|
+
const extraPerSpace = computeJustifyExtra(line);
|
|
879
|
+
const hasImageToken = line.tokens.some((t) => t.kind === "image");
|
|
880
|
+
const hasMathToken = line.tokens.some((t) => t.kind === "math");
|
|
881
|
+
const hasRtl = line.tokens.some((t) => t.bidiLevel % 2 === 1);
|
|
882
|
+
const hasTab = line.tokens.some((t) => t.kind === "text" && t.tab === true);
|
|
883
|
+
/** A text token carrying underline or strikethrough. */
|
|
884
|
+
const isDecorated = (tok) => tok.kind === "text" && (tok.resolvedRun.underline !== "none" || tok.resolvedRun.strike);
|
|
885
|
+
const showToken = (tok) => {
|
|
886
|
+
const text = tok.bidiLevel % 2 === 1 ? reverseByCodePoint(tok.text) : tok.text;
|
|
887
|
+
return tok.font.measure.showText(text);
|
|
888
|
+
};
|
|
889
|
+
if (line.tokens.some((t) => t.kind === "text" && t.resolvedRun.shadingColorHex)) {
|
|
890
|
+
if (inBT) {
|
|
891
|
+
out.push("ET");
|
|
892
|
+
inBT = false;
|
|
893
|
+
}
|
|
894
|
+
const shAscent = Math.max(lineFs, line.mathAscentPt ?? 0);
|
|
895
|
+
const shDescent = Math.max(lineFs * .2, line.mathDescentPt ?? 0);
|
|
896
|
+
out.push("q");
|
|
897
|
+
let sx = originX;
|
|
898
|
+
let painted = "";
|
|
899
|
+
for (const tok of line.tokens) {
|
|
900
|
+
const w = tok.widthPt + (tok.kind === "text" && tok.isSpace ? extraPerSpace : 0);
|
|
901
|
+
const hex = tok.kind === "text" ? tok.resolvedRun.shadingColorHex : void 0;
|
|
902
|
+
if (hex !== void 0) {
|
|
903
|
+
if (hex !== painted) {
|
|
904
|
+
if (painted !== "") out.push("f");
|
|
905
|
+
const [sr, sg, sb] = hexToRgb01(hex);
|
|
906
|
+
out.push(`${formatNumber(sr)} ${formatNumber(sg)} ${formatNumber(sb)} rg`);
|
|
907
|
+
painted = hex;
|
|
908
|
+
}
|
|
909
|
+
out.push(`${formatNumber(sx)} ${formatNumber(baselineY - shDescent)} ${formatNumber(w)} ${formatNumber(shAscent + shDescent)} re`);
|
|
910
|
+
}
|
|
911
|
+
sx += w;
|
|
912
|
+
}
|
|
913
|
+
if (painted !== "") out.push("f");
|
|
914
|
+
out.push("Q");
|
|
915
|
+
}
|
|
916
|
+
if (line.tokens.some((t) => t.kind === "text" && t.highlight === true)) {
|
|
917
|
+
if (inBT) {
|
|
918
|
+
out.push("ET");
|
|
919
|
+
inBT = false;
|
|
920
|
+
}
|
|
921
|
+
const hlAscent = Math.max(lineFs, line.mathAscentPt ?? 0);
|
|
922
|
+
const hlDescent = Math.max(lineFs * .2, line.mathDescentPt ?? 0);
|
|
923
|
+
const [hr, hg, hb] = hexToRgb01("fff3a3");
|
|
924
|
+
out.push("q");
|
|
925
|
+
out.push(`${formatNumber(hr)} ${formatNumber(hg)} ${formatNumber(hb)} rg`);
|
|
926
|
+
let hx = originX;
|
|
927
|
+
for (const tok of line.tokens) {
|
|
928
|
+
const w = tok.widthPt + (tok.kind === "text" && tok.isSpace ? extraPerSpace : 0);
|
|
929
|
+
if (tok.kind === "text" && tok.highlight === true) out.push(`${formatNumber(hx)} ${formatNumber(baselineY - hlDescent)} ${formatNumber(w)} ${formatNumber(hlAscent + hlDescent)} re`);
|
|
930
|
+
hx += w;
|
|
931
|
+
}
|
|
932
|
+
out.push("f");
|
|
933
|
+
out.push("Q");
|
|
934
|
+
}
|
|
935
|
+
if (line.tokens.some(isDecorated)) {
|
|
936
|
+
if (inBT) {
|
|
937
|
+
out.push("ET");
|
|
938
|
+
inBT = false;
|
|
939
|
+
}
|
|
940
|
+
out.push("q");
|
|
941
|
+
let dx = originX;
|
|
942
|
+
for (const tok of line.tokens) {
|
|
943
|
+
const w = tok.widthPt + (tok.kind === "text" && tok.isSpace ? extraPerSpace : 0);
|
|
944
|
+
if (isDecorated(tok)) {
|
|
945
|
+
const thickness = Math.max(.4, tok.fontSizePt * .06);
|
|
946
|
+
const paint = (hex) => {
|
|
947
|
+
const [r, g, b] = hexToRgb01(hex);
|
|
948
|
+
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
949
|
+
};
|
|
950
|
+
paint(tok.resolvedRun.colorHex);
|
|
951
|
+
if (tok.resolvedRun.underline !== "none") {
|
|
952
|
+
if (tok.resolvedRun.underlineColorHex) paint(tok.resolvedRun.underlineColorHex);
|
|
953
|
+
const style = tok.resolvedRun.underline;
|
|
954
|
+
const t = style === "thick" || style === "dottedHeavy" || style === "dashHeavy" ? thickness * 2 : thickness;
|
|
955
|
+
const y = baselineY - tok.fontSizePt * .12 - t;
|
|
956
|
+
const dashed = style === "dotted" || style === "dottedHeavy" ? [t, t * 2] : style === "dash" || style === "dashHeavy" ? [t * 4, t * 3] : void 0;
|
|
957
|
+
if (dashed) {
|
|
958
|
+
out.push(`${formatNumber(t)} w`);
|
|
959
|
+
out.push(`[${dashed.map((n) => formatNumber(n)).join(" ")}] 0 d`);
|
|
960
|
+
const [r, g, b] = hexToRgb01(tok.resolvedRun.underlineColorHex ?? tok.resolvedRun.colorHex);
|
|
961
|
+
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} RG`);
|
|
962
|
+
out.push(`${formatNumber(dx)} ${formatNumber(y + t / 2)} m ${formatNumber(dx + w)} ${formatNumber(y + t / 2)} l S`);
|
|
963
|
+
out.push("[] 0 d");
|
|
964
|
+
} else {
|
|
965
|
+
out.push(`${formatNumber(dx)} ${formatNumber(y)} ${formatNumber(w)} ${formatNumber(t)} re f`);
|
|
966
|
+
if (style === "double") out.push(`${formatNumber(dx)} ${formatNumber(y - t * 2)} ${formatNumber(w)} ${formatNumber(t)} re f`);
|
|
967
|
+
}
|
|
968
|
+
if (tok.resolvedRun.underlineColorHex) paint(tok.resolvedRun.colorHex);
|
|
969
|
+
}
|
|
970
|
+
if (tok.resolvedRun.strike) {
|
|
971
|
+
const y = baselineY + tok.fontSizePt * .26;
|
|
972
|
+
out.push(`${formatNumber(dx)} ${formatNumber(y)} ${formatNumber(w)} ${formatNumber(thickness)} re f`);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
dx += w;
|
|
976
|
+
}
|
|
977
|
+
out.push("Q");
|
|
978
|
+
}
|
|
979
|
+
const hasRise = line.tokens.some((t) => t.kind === "text" && t.risePt !== void 0);
|
|
980
|
+
if (rotationDeg !== 0 && !hasImageToken && !hasMathToken) {
|
|
981
|
+
if (!inBT) {
|
|
982
|
+
out.push("BT");
|
|
983
|
+
inBT = true;
|
|
984
|
+
}
|
|
985
|
+
const rad = rotationDeg * Math.PI / 180;
|
|
986
|
+
const cos = formatNumber(Math.cos(rad));
|
|
987
|
+
const sin = formatNumber(Math.sin(rad));
|
|
988
|
+
out.push(`${cos} ${sin} ${formatNumber(-Math.sin(rad))} ${cos} ${formatNumber(originX)} ${formatNumber(baselineY)} Tm`);
|
|
989
|
+
for (const tok of line.tokens) {
|
|
990
|
+
if (tok.kind !== "text") continue;
|
|
991
|
+
switchFontIfNeeded(tok);
|
|
992
|
+
out.push(tok.font.measure.showText(tok.text));
|
|
993
|
+
}
|
|
994
|
+
} else if (extraPerSpace !== 0 || hasImageToken || hasMathToken || hasRtl || hasRise || hasTab) {
|
|
995
|
+
const order = hasRtl ? lineVisualOrder(line) : line.tokens.map((_, i) => i);
|
|
996
|
+
let x = originX;
|
|
997
|
+
for (const ti of order) {
|
|
998
|
+
const tok = line.tokens[ti];
|
|
999
|
+
if (tok.kind === "image") {
|
|
1000
|
+
flushLink();
|
|
1001
|
+
emitImageToken(tok, x, baselineY);
|
|
1002
|
+
x += tok.widthPt;
|
|
1003
|
+
continue;
|
|
1004
|
+
}
|
|
1005
|
+
if (tok.kind === "math") {
|
|
1006
|
+
flushLink();
|
|
1007
|
+
emitMathToken(tok, x, baselineY);
|
|
1008
|
+
x += tok.widthPt;
|
|
1009
|
+
continue;
|
|
1010
|
+
}
|
|
1011
|
+
if (!inBT) {
|
|
1012
|
+
out.push("BT");
|
|
1013
|
+
inBT = true;
|
|
1014
|
+
}
|
|
1015
|
+
switchFontIfNeeded(tok);
|
|
1016
|
+
out.push(`1 0 0 1 ${formatNumber(x)} ${formatNumber(baselineY + (tok.risePt ?? 0))} Tm`);
|
|
1017
|
+
out.push(showToken(tok));
|
|
1018
|
+
const tokenX0 = x;
|
|
1019
|
+
x += tok.widthPt;
|
|
1020
|
+
if (tok.isSpace) x += extraPerSpace;
|
|
1021
|
+
trackLink(tok.href, tok.anchor, tok.text, tokenX0, x);
|
|
1022
|
+
}
|
|
1023
|
+
flushLink();
|
|
1024
|
+
} else {
|
|
1025
|
+
if (!inBT) {
|
|
1026
|
+
out.push("BT");
|
|
1027
|
+
inBT = true;
|
|
1028
|
+
}
|
|
1029
|
+
out.push(`1 0 0 1 ${formatNumber(originX)} ${formatNumber(baselineY)} Tm`);
|
|
1030
|
+
let x = originX;
|
|
1031
|
+
for (const tok of line.tokens) {
|
|
1032
|
+
if (tok.kind !== "text") continue;
|
|
1033
|
+
switchFontIfNeeded(tok);
|
|
1034
|
+
out.push(tok.font.measure.showText(tok.text));
|
|
1035
|
+
trackLink(tok.href, tok.anchor, tok.text, x, x + tok.widthPt);
|
|
1036
|
+
x += tok.widthPt;
|
|
1037
|
+
}
|
|
1038
|
+
flushLink();
|
|
1039
|
+
}
|
|
1040
|
+
};
|
|
1041
|
+
const emitLinesPass = () => {
|
|
1042
|
+
if (lines.length === 0) return;
|
|
1043
|
+
if (tagging) for (const cmd of lines) {
|
|
1044
|
+
if (inBT) {
|
|
1045
|
+
out.push("ET");
|
|
1046
|
+
inBT = false;
|
|
1047
|
+
}
|
|
1048
|
+
const sid = cmd.structId;
|
|
1049
|
+
if (sid !== void 0) {
|
|
1050
|
+
const mcid = tagging.next++;
|
|
1051
|
+
tagging.assigned = true;
|
|
1052
|
+
tagging.record(sid, mcid);
|
|
1053
|
+
out.push(`/${tagging.tagFor(sid)} <</MCID ${mcid}>> BDC`);
|
|
1054
|
+
} else if (cmd.artifact === "pagination") out.push("/Artifact <</Type /Pagination>> BDC");
|
|
1055
|
+
else out.push("/Artifact BMC");
|
|
1056
|
+
emitClipped(cmd, emitOneLine);
|
|
1057
|
+
if (inBT) {
|
|
1058
|
+
out.push("ET");
|
|
1059
|
+
inBT = false;
|
|
1060
|
+
}
|
|
1061
|
+
out.push("EMC");
|
|
1062
|
+
}
|
|
1063
|
+
else {
|
|
1064
|
+
out.push("BT");
|
|
1065
|
+
inBT = true;
|
|
1066
|
+
for (const cmd of lines) emitClipped(cmd, emitOneLine);
|
|
1067
|
+
if (inBT) out.push("ET");
|
|
1068
|
+
}
|
|
1069
|
+
};
|
|
1070
|
+
const emitInOrder = (item) => {
|
|
1071
|
+
if (item.type === "shape") {
|
|
1072
|
+
const t = item.shape.transform;
|
|
1073
|
+
const fillAlpha = item.shape.fillAlpha;
|
|
1074
|
+
for (const op of emitVectorShape({
|
|
1075
|
+
...item.shape,
|
|
1076
|
+
transform: [
|
|
1077
|
+
t[0],
|
|
1078
|
+
-t[1],
|
|
1079
|
+
t[2],
|
|
1080
|
+
-t[3],
|
|
1081
|
+
t[4],
|
|
1082
|
+
H - t[5]
|
|
1083
|
+
]
|
|
1084
|
+
}, gradientNames?.get(item.shape), void 0, gradientMaskNames?.get(item.shape) ?? (fillAlpha !== void 0 && fillAlpha < 1 ? alphaStateNames?.get(Math.round(fillAlpha * 1e3) / 1e3) : void 0))) out.push(op);
|
|
1085
|
+
return;
|
|
1086
|
+
}
|
|
1087
|
+
if (item.type === "image") {
|
|
1088
|
+
if (item.imageResourceName === "") return;
|
|
1089
|
+
out.push("q");
|
|
1090
|
+
if (item.clip) {
|
|
1091
|
+
const t = item.clip.transform;
|
|
1092
|
+
out.push(...emitClipPath(item.clip.paths, [
|
|
1093
|
+
t[0],
|
|
1094
|
+
-t[1],
|
|
1095
|
+
t[2],
|
|
1096
|
+
-t[3],
|
|
1097
|
+
t[4],
|
|
1098
|
+
H - t[5]
|
|
1099
|
+
]));
|
|
1100
|
+
}
|
|
1101
|
+
const state = item.alpha !== void 0 && item.alpha < 1 ? alphaStateNames?.get(Math.round(item.alpha * 1e3) / 1e3) : void 0;
|
|
1102
|
+
if (state !== void 0) out.push(`/${state} gs`);
|
|
1103
|
+
out.push(...paintImageBody(item, H - item.y - item.height, duotoneStateFor?.(item, H)));
|
|
1104
|
+
out.push(...washItems(item.wash, alphaStateNames));
|
|
1105
|
+
out.push("Q");
|
|
1106
|
+
return;
|
|
1107
|
+
}
|
|
1108
|
+
if (item.type === "fill") {
|
|
1109
|
+
const [r, g, b] = hexToRgb01(item.fillColorHex);
|
|
1110
|
+
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`, `${formatNumber(item.x)} ${formatNumber(H - item.y - item.height)} ${formatNumber(item.width)} ${formatNumber(item.height)} re`, "f");
|
|
1111
|
+
return;
|
|
1112
|
+
}
|
|
1113
|
+
if (item.type !== "line") return;
|
|
1114
|
+
emitClipped(item, emitOneLine);
|
|
1115
|
+
if (inBT) {
|
|
1116
|
+
out.push("ET");
|
|
1117
|
+
inBT = false;
|
|
1118
|
+
}
|
|
1119
|
+
};
|
|
1120
|
+
if (plan.behind.length > 0) {
|
|
1121
|
+
if (tagging) out.push("/Artifact BMC");
|
|
1122
|
+
for (const item of plan.behind) emitInOrder(item);
|
|
1123
|
+
if (tagging) out.push("EMC");
|
|
1124
|
+
}
|
|
533
1125
|
const fills = plan.fills;
|
|
534
1126
|
if (fills.length > 0) {
|
|
535
1127
|
if (tagging) out.push("/Artifact BMC");
|
|
536
1128
|
out.push("q");
|
|
537
|
-
let
|
|
1129
|
+
let lastFill = "";
|
|
538
1130
|
for (const f of fills) {
|
|
539
1131
|
const color = f.fillColorHex;
|
|
540
|
-
if (color !==
|
|
1132
|
+
if (color !== lastFill) {
|
|
541
1133
|
const [r, g, b] = hexToRgb01(color);
|
|
542
1134
|
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
543
|
-
|
|
1135
|
+
lastFill = color;
|
|
544
1136
|
}
|
|
545
1137
|
out.push(`${formatNumber(f.x)} ${formatNumber(H - f.y - f.height)} ${formatNumber(f.width)} ${formatNumber(f.height)} re`);
|
|
546
1138
|
out.push("f");
|
|
@@ -561,8 +1153,9 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames) {
|
|
|
561
1153
|
H - t[5]
|
|
562
1154
|
]));
|
|
563
1155
|
}
|
|
564
|
-
|
|
565
|
-
out.push(`/${
|
|
1156
|
+
const state = img.alpha !== void 0 && img.alpha < 1 ? alphaStateNames?.get(Math.round(img.alpha * 1e3) / 1e3) : void 0;
|
|
1157
|
+
if (state !== void 0) out.push(`/${state} gs`);
|
|
1158
|
+
out.push(...paintImageBody(img, H - img.y - img.height, duotoneStateFor?.(img, H)));
|
|
566
1159
|
out.push(...washItems(img.wash, alphaStateNames));
|
|
567
1160
|
out.push("Q");
|
|
568
1161
|
});
|
|
@@ -572,7 +1165,7 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames) {
|
|
|
572
1165
|
out.push("q");
|
|
573
1166
|
out.push("2 J");
|
|
574
1167
|
let lastWidth = -1;
|
|
575
|
-
let
|
|
1168
|
+
let lastStroke = "";
|
|
576
1169
|
let lastDash = "";
|
|
577
1170
|
for (const b of borders) {
|
|
578
1171
|
const width = b.borderSizePt;
|
|
@@ -587,10 +1180,10 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames) {
|
|
|
587
1180
|
out.push(`${formatNumber(strokeW)} w`);
|
|
588
1181
|
lastWidth = strokeW;
|
|
589
1182
|
}
|
|
590
|
-
if (color !==
|
|
1183
|
+
if (color !== lastStroke) {
|
|
591
1184
|
const [r, g, bl] = hexToRgb01(color);
|
|
592
1185
|
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(bl)} RG`);
|
|
593
|
-
|
|
1186
|
+
lastStroke = color;
|
|
594
1187
|
}
|
|
595
1188
|
const x = b.x;
|
|
596
1189
|
const y = H - b.y - b.height;
|
|
@@ -652,439 +1245,16 @@ function emitPageContent(page, tagging, gradientNames, alphaStateNames) {
|
|
|
652
1245
|
const shadowLayer = sh.shape.shadow ? shadowBlurLayers(sh.shape.shadow) : void 0;
|
|
653
1246
|
const alphaState = shadowLayer && shadowLayer.alpha < 1 ? alphaStateNames?.get(Math.round(shadowLayer.alpha * 1e3) / 1e3) : void 0;
|
|
654
1247
|
const fillAlpha = sh.shape.fillAlpha;
|
|
655
|
-
const fillAlphaState = fillAlpha !== void 0 && fillAlpha < 1 ? alphaStateNames?.get(Math.round(fillAlpha * 1e3) / 1e3) : void 0;
|
|
1248
|
+
const fillAlphaState = gradientMaskNames?.get(sh.shape) ?? (fillAlpha !== void 0 && fillAlpha < 1 ? alphaStateNames?.get(Math.round(fillAlpha * 1e3) / 1e3) : void 0);
|
|
656
1249
|
for (const op of emitVectorShape(shape, gradientNames?.get(sh.shape), alphaState, fillAlphaState)) out.push(op);
|
|
657
1250
|
});
|
|
658
|
-
const
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
let lastSize = -1;
|
|
664
|
-
let lastColor = "";
|
|
665
|
-
const switchFontIfNeeded = (tok) => {
|
|
666
|
-
const fontKey = tok.font.resourceName;
|
|
667
|
-
if (fontKey !== lastFont || tok.fontSizePt !== lastSize) {
|
|
668
|
-
out.push(`/${fontKey} ${formatNumber(tok.fontSizePt)} Tf`);
|
|
669
|
-
lastFont = fontKey;
|
|
670
|
-
lastSize = tok.fontSizePt;
|
|
671
|
-
}
|
|
672
|
-
const tc = tok.resolvedRun.letterSpacingPt ?? 0;
|
|
673
|
-
if (tc !== lastTc) {
|
|
674
|
-
out.push(`${formatNumber(tc)} Tc`);
|
|
675
|
-
lastTc = tc;
|
|
676
|
-
}
|
|
677
|
-
if (tok.resolvedRun.colorHex !== lastColor) {
|
|
678
|
-
const [r, g, b] = hexToRgb01(tok.resolvedRun.colorHex);
|
|
679
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
680
|
-
lastColor = tok.resolvedRun.colorHex;
|
|
681
|
-
}
|
|
682
|
-
};
|
|
683
|
-
const emitImageToken = (tok, x, baselineY) => {
|
|
684
|
-
const meta = tok.metafile;
|
|
685
|
-
if (meta) {
|
|
686
|
-
if (inBT) {
|
|
687
|
-
out.push("ET");
|
|
688
|
-
inBT = false;
|
|
689
|
-
}
|
|
690
|
-
const b = tok.drawBox;
|
|
691
|
-
const ox = x + (b?.dxPt ?? 0);
|
|
692
|
-
const oy = baselineY + (b?.dyPt ?? 0);
|
|
693
|
-
for (const sh of meta.shapes) for (const op of emitVectorShape({
|
|
694
|
-
...sh,
|
|
695
|
-
transform: [
|
|
696
|
-
1,
|
|
697
|
-
0,
|
|
698
|
-
0,
|
|
699
|
-
1,
|
|
700
|
-
ox,
|
|
701
|
-
oy
|
|
702
|
-
]
|
|
703
|
-
})) out.push(op);
|
|
704
|
-
for (const t of meta.texts) {
|
|
705
|
-
const first = t.line.tokens.find((k) => k.kind === "text");
|
|
706
|
-
if (!first) continue;
|
|
707
|
-
const [r, g, bl] = hexToRgb01(first.resolvedRun.colorHex);
|
|
708
|
-
out.push("BT");
|
|
709
|
-
out.push(`/${first.font.resourceName} ${formatNumber(first.fontSizePt)} Tf`);
|
|
710
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(bl)} rg`);
|
|
711
|
-
out.push(`1 0 0 1 ${formatNumber(ox + t.x)} ${formatNumber(oy + t.y)} Tm`);
|
|
712
|
-
out.push(first.font.measure.showText(first.text));
|
|
713
|
-
out.push("ET");
|
|
714
|
-
}
|
|
715
|
-
lastFont = "";
|
|
716
|
-
lastSize = -1;
|
|
717
|
-
lastColor = "";
|
|
718
|
-
return;
|
|
719
|
-
}
|
|
720
|
-
if (!tok.imageResourceName) return;
|
|
721
|
-
if (inBT) {
|
|
722
|
-
out.push("ET");
|
|
723
|
-
inBT = false;
|
|
724
|
-
}
|
|
725
|
-
const shdw = tok.shadow;
|
|
726
|
-
if (shdw) {
|
|
727
|
-
const bx = tok.drawBox;
|
|
728
|
-
const [shr, shg, shb] = hexToRgb01(shdw.colorHex);
|
|
729
|
-
const layers = shadowBlurLayers(shdw);
|
|
730
|
-
const state = layers.alpha < 1 ? alphaStateNames?.get(Math.round(layers.alpha * 1e3) / 1e3) : void 0;
|
|
731
|
-
const sx = x + (bx?.dxPt ?? 0) + shdw.dxPt;
|
|
732
|
-
const sy = baselineY + (bx?.dyPt ?? 0) - shdw.dyPt;
|
|
733
|
-
const sw = bx?.widthPt ?? tok.widthPt;
|
|
734
|
-
const sh = bx?.heightPt ?? tok.heightPt;
|
|
735
|
-
out.push("q");
|
|
736
|
-
if (state) out.push(`/${state} gs`);
|
|
737
|
-
out.push(`${formatNumber(shr)} ${formatNumber(shg)} ${formatNumber(shb)} rg`);
|
|
738
|
-
for (let i = 0; i < layers.count; i++) {
|
|
739
|
-
const grow = layers.count > 1 ? -shdw.blurPt / 2 + (i + .5) * shdw.blurPt / layers.count : 0;
|
|
740
|
-
out.push(`${formatNumber(sx - grow)} ${formatNumber(sy - grow)} ${formatNumber(Math.max(sw + 2 * grow, 0))} ${formatNumber(Math.max(sh + 2 * grow, 0))} re`);
|
|
741
|
-
out.push("f");
|
|
742
|
-
}
|
|
743
|
-
out.push("Q");
|
|
744
|
-
}
|
|
745
|
-
out.push("q");
|
|
746
|
-
const b = tok.drawBox;
|
|
747
|
-
out.push(...b ? placeImage(x + b.dxPt, baselineY + b.dyPt, b.widthPt, b.heightPt, tok.crop, tok.rotationDeg, tok.flipH, tok.flipV) : placeImage(x, baselineY, tok.widthPt, tok.heightPt, tok.crop, tok.rotationDeg, tok.flipH, tok.flipV));
|
|
748
|
-
out.push(`/${tok.imageResourceName} Do`);
|
|
749
|
-
out.push(...washItems(tok.wash, alphaStateNames));
|
|
750
|
-
out.push("Q");
|
|
751
|
-
const frame = tok.outline;
|
|
752
|
-
if (frame) {
|
|
753
|
-
const [fr, fg, fb] = hexToRgb01(frame.colorHex);
|
|
754
|
-
out.push("q");
|
|
755
|
-
out.push(`${formatNumber(frame.widthPt)} w`);
|
|
756
|
-
out.push(`${formatNumber(fr)} ${formatNumber(fg)} ${formatNumber(fb)} RG`);
|
|
757
|
-
out.push(`${formatNumber(x + (b?.dxPt ?? 0))} ${formatNumber(baselineY + (b?.dyPt ?? 0))} ${formatNumber(b?.widthPt ?? tok.widthPt)} ${formatNumber(b?.heightPt ?? tok.heightPt)} re`);
|
|
758
|
-
out.push("S");
|
|
759
|
-
out.push("Q");
|
|
760
|
-
}
|
|
761
|
-
lastFont = "";
|
|
762
|
-
lastSize = -1;
|
|
763
|
-
lastColor = "";
|
|
764
|
-
lastTc = 0;
|
|
765
|
-
};
|
|
766
|
-
const emitMathToken = (tok, originX, baselineY) => {
|
|
767
|
-
for (const it of tok.items) if (it.kind === "glyph") {
|
|
768
|
-
if (!inBT) {
|
|
769
|
-
out.push("BT");
|
|
770
|
-
inBT = true;
|
|
771
|
-
}
|
|
772
|
-
if (it.font.resourceName !== lastFont || it.sizePt !== lastSize) {
|
|
773
|
-
out.push(`/${it.font.resourceName} ${formatNumber(it.sizePt)} Tf`);
|
|
774
|
-
lastFont = it.font.resourceName;
|
|
775
|
-
lastSize = it.sizePt;
|
|
776
|
-
}
|
|
777
|
-
if (lastColor !== "000000") {
|
|
778
|
-
out.push("0 0 0 rg");
|
|
779
|
-
lastColor = "000000";
|
|
780
|
-
}
|
|
781
|
-
out.push(`1 0 0 1 ${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} Tm`);
|
|
782
|
-
out.push(it.font.measure.showText(it.text));
|
|
783
|
-
} else if (it.kind === "rule") {
|
|
784
|
-
if (inBT) {
|
|
785
|
-
out.push("ET");
|
|
786
|
-
inBT = false;
|
|
787
|
-
}
|
|
788
|
-
out.push("q");
|
|
789
|
-
out.push("0 0 0 rg");
|
|
790
|
-
out.push(`${formatNumber(originX + it.x)} ${formatNumber(baselineY + it.y)} ${formatNumber(it.w)} ${formatNumber(it.h)} re`);
|
|
791
|
-
out.push("f");
|
|
792
|
-
out.push("Q");
|
|
793
|
-
lastFont = "";
|
|
794
|
-
lastSize = -1;
|
|
795
|
-
lastColor = "";
|
|
796
|
-
} else {
|
|
797
|
-
if (inBT) {
|
|
798
|
-
out.push("ET");
|
|
799
|
-
inBT = false;
|
|
800
|
-
}
|
|
801
|
-
const shape = {
|
|
802
|
-
paths: [{ segments: it.segments }],
|
|
803
|
-
...it.fill ? { fillColorHex: "000000" } : {},
|
|
804
|
-
...it.strokeWidthPt !== void 0 ? { stroke: {
|
|
805
|
-
colorHex: "000000",
|
|
806
|
-
widthPt: it.strokeWidthPt
|
|
807
|
-
} } : {},
|
|
808
|
-
transform: [
|
|
809
|
-
1,
|
|
810
|
-
0,
|
|
811
|
-
0,
|
|
812
|
-
1,
|
|
813
|
-
originX,
|
|
814
|
-
baselineY
|
|
815
|
-
]
|
|
816
|
-
};
|
|
817
|
-
for (const op of emitVectorShape(shape)) out.push(op);
|
|
818
|
-
lastFont = "";
|
|
819
|
-
lastSize = -1;
|
|
820
|
-
lastColor = "";
|
|
821
|
-
}
|
|
822
|
-
};
|
|
823
|
-
const emitClipped = (cmd, body) => {
|
|
824
|
-
const clip = cmd.clip;
|
|
825
|
-
if (!clip) {
|
|
826
|
-
body(cmd);
|
|
827
|
-
return;
|
|
828
|
-
}
|
|
829
|
-
if (inBT) {
|
|
830
|
-
out.push("ET");
|
|
831
|
-
inBT = false;
|
|
832
|
-
}
|
|
833
|
-
out.push("q");
|
|
834
|
-
out.push(`${formatNumber(clip.x)} ${formatNumber(H - clip.y - clip.height)} ${formatNumber(clip.width)} ${formatNumber(clip.height)} re W n`);
|
|
835
|
-
lastFont = "";
|
|
836
|
-
lastSize = -1;
|
|
837
|
-
lastColor = "";
|
|
838
|
-
lastTc = 0;
|
|
839
|
-
out.push("BT");
|
|
840
|
-
inBT = true;
|
|
841
|
-
body(cmd);
|
|
842
|
-
if (inBT) {
|
|
843
|
-
out.push("ET");
|
|
844
|
-
inBT = false;
|
|
845
|
-
}
|
|
846
|
-
out.push("Q");
|
|
847
|
-
lastFont = "";
|
|
848
|
-
lastSize = -1;
|
|
849
|
-
lastColor = "";
|
|
850
|
-
lastTc = 0;
|
|
851
|
-
};
|
|
852
|
-
const emitOneLine = (cmd) => {
|
|
853
|
-
const line = cmd.line;
|
|
854
|
-
const originX = cmd.originX;
|
|
855
|
-
const baselineY = H - cmd.baselineY;
|
|
856
|
-
const rotationDeg = cmd.rotationDeg ?? 0;
|
|
857
|
-
const lineFs = line.maxFontSizePt || 12;
|
|
858
|
-
const linkAscent = Math.max(lineFs, line.mathAscentPt ?? 0);
|
|
859
|
-
const linkDescent = Math.max(lineFs * .2, line.mathDescentPt ?? 0);
|
|
860
|
-
let linkHref;
|
|
861
|
-
let linkAnchor;
|
|
862
|
-
let linkText = "";
|
|
863
|
-
let linkX0 = 0;
|
|
864
|
-
let linkX1 = 0;
|
|
865
|
-
const flushLink = () => {
|
|
866
|
-
if (linkHref === void 0 && linkAnchor === void 0) return;
|
|
867
|
-
const safe = linkHref !== void 0 ? sanitizeHref(linkHref) : void 0;
|
|
868
|
-
const target = safe !== void 0 ? { href: safe } : linkAnchor !== void 0 ? { anchor: linkAnchor } : void 0;
|
|
869
|
-
if (target) links.push({
|
|
870
|
-
...target,
|
|
871
|
-
text: linkText.trim(),
|
|
872
|
-
rect: [
|
|
873
|
-
linkX0,
|
|
874
|
-
baselineY - linkDescent,
|
|
875
|
-
linkX1,
|
|
876
|
-
baselineY + linkAscent
|
|
877
|
-
],
|
|
878
|
-
...cmd.structId !== void 0 ? { structId: cmd.structId } : {}
|
|
879
|
-
});
|
|
880
|
-
linkHref = void 0;
|
|
881
|
-
linkAnchor = void 0;
|
|
882
|
-
linkText = "";
|
|
883
|
-
};
|
|
884
|
-
const trackLink = (href, anchor, text, x0, x1) => {
|
|
885
|
-
if (href !== linkHref || anchor !== linkAnchor) {
|
|
886
|
-
flushLink();
|
|
887
|
-
if (href !== void 0 || anchor !== void 0) {
|
|
888
|
-
linkHref = href;
|
|
889
|
-
linkAnchor = anchor;
|
|
890
|
-
linkX0 = x0;
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
if (href !== void 0 || anchor !== void 0) {
|
|
894
|
-
linkX1 = x1;
|
|
895
|
-
linkText += text;
|
|
896
|
-
}
|
|
897
|
-
};
|
|
898
|
-
const extraPerSpace = computeJustifyExtra(line);
|
|
899
|
-
const hasImageToken = line.tokens.some((t) => t.kind === "image");
|
|
900
|
-
const hasMathToken = line.tokens.some((t) => t.kind === "math");
|
|
901
|
-
const hasRtl = line.tokens.some((t) => t.bidiLevel % 2 === 1);
|
|
902
|
-
const hasTab = line.tokens.some((t) => t.kind === "text" && t.tab === true);
|
|
903
|
-
/** A text token carrying underline or strikethrough. */
|
|
904
|
-
const isDecorated = (tok) => tok.kind === "text" && (tok.resolvedRun.underline !== "none" || tok.resolvedRun.strike);
|
|
905
|
-
const showToken = (tok) => {
|
|
906
|
-
const text = tok.bidiLevel % 2 === 1 ? reverseByCodePoint(tok.text) : tok.text;
|
|
907
|
-
return tok.font.measure.showText(text);
|
|
908
|
-
};
|
|
909
|
-
if (line.tokens.some((t) => t.kind === "text" && t.resolvedRun.shadingColorHex)) {
|
|
910
|
-
if (inBT) {
|
|
911
|
-
out.push("ET");
|
|
912
|
-
inBT = false;
|
|
913
|
-
}
|
|
914
|
-
const shAscent = Math.max(lineFs, line.mathAscentPt ?? 0);
|
|
915
|
-
const shDescent = Math.max(lineFs * .2, line.mathDescentPt ?? 0);
|
|
916
|
-
out.push("q");
|
|
917
|
-
let sx = originX;
|
|
918
|
-
let painted = "";
|
|
919
|
-
for (const tok of line.tokens) {
|
|
920
|
-
const w = tok.widthPt + (tok.kind === "text" && tok.isSpace ? extraPerSpace : 0);
|
|
921
|
-
const hex = tok.kind === "text" ? tok.resolvedRun.shadingColorHex : void 0;
|
|
922
|
-
if (hex !== void 0) {
|
|
923
|
-
if (hex !== painted) {
|
|
924
|
-
if (painted !== "") out.push("f");
|
|
925
|
-
const [sr, sg, sb] = hexToRgb01(hex);
|
|
926
|
-
out.push(`${formatNumber(sr)} ${formatNumber(sg)} ${formatNumber(sb)} rg`);
|
|
927
|
-
painted = hex;
|
|
928
|
-
}
|
|
929
|
-
out.push(`${formatNumber(sx)} ${formatNumber(baselineY - shDescent)} ${formatNumber(w)} ${formatNumber(shAscent + shDescent)} re`);
|
|
930
|
-
}
|
|
931
|
-
sx += w;
|
|
932
|
-
}
|
|
933
|
-
if (painted !== "") out.push("f");
|
|
934
|
-
out.push("Q");
|
|
935
|
-
}
|
|
936
|
-
if (line.tokens.some((t) => t.kind === "text" && t.highlight === true)) {
|
|
937
|
-
if (inBT) {
|
|
938
|
-
out.push("ET");
|
|
939
|
-
inBT = false;
|
|
940
|
-
}
|
|
941
|
-
const hlAscent = Math.max(lineFs, line.mathAscentPt ?? 0);
|
|
942
|
-
const hlDescent = Math.max(lineFs * .2, line.mathDescentPt ?? 0);
|
|
943
|
-
const [hr, hg, hb] = hexToRgb01("fff3a3");
|
|
944
|
-
out.push("q");
|
|
945
|
-
out.push(`${formatNumber(hr)} ${formatNumber(hg)} ${formatNumber(hb)} rg`);
|
|
946
|
-
let hx = originX;
|
|
947
|
-
for (const tok of line.tokens) {
|
|
948
|
-
const w = tok.widthPt + (tok.kind === "text" && tok.isSpace ? extraPerSpace : 0);
|
|
949
|
-
if (tok.kind === "text" && tok.highlight === true) out.push(`${formatNumber(hx)} ${formatNumber(baselineY - hlDescent)} ${formatNumber(w)} ${formatNumber(hlAscent + hlDescent)} re`);
|
|
950
|
-
hx += w;
|
|
951
|
-
}
|
|
952
|
-
out.push("f");
|
|
953
|
-
out.push("Q");
|
|
954
|
-
}
|
|
955
|
-
if (line.tokens.some(isDecorated)) {
|
|
956
|
-
if (inBT) {
|
|
957
|
-
out.push("ET");
|
|
958
|
-
inBT = false;
|
|
959
|
-
}
|
|
960
|
-
out.push("q");
|
|
961
|
-
let dx = originX;
|
|
962
|
-
for (const tok of line.tokens) {
|
|
963
|
-
const w = tok.widthPt + (tok.kind === "text" && tok.isSpace ? extraPerSpace : 0);
|
|
964
|
-
if (isDecorated(tok)) {
|
|
965
|
-
const thickness = Math.max(.4, tok.fontSizePt * .06);
|
|
966
|
-
const paint = (hex) => {
|
|
967
|
-
const [r, g, b] = hexToRgb01(hex);
|
|
968
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} rg`);
|
|
969
|
-
};
|
|
970
|
-
paint(tok.resolvedRun.colorHex);
|
|
971
|
-
if (tok.resolvedRun.underline !== "none") {
|
|
972
|
-
if (tok.resolvedRun.underlineColorHex) paint(tok.resolvedRun.underlineColorHex);
|
|
973
|
-
const style = tok.resolvedRun.underline;
|
|
974
|
-
const t = style === "thick" || style === "dottedHeavy" || style === "dashHeavy" ? thickness * 2 : thickness;
|
|
975
|
-
const y = baselineY - tok.fontSizePt * .12 - t;
|
|
976
|
-
const dashed = style === "dotted" || style === "dottedHeavy" ? [t, t * 2] : style === "dash" || style === "dashHeavy" ? [t * 4, t * 3] : void 0;
|
|
977
|
-
if (dashed) {
|
|
978
|
-
out.push(`${formatNumber(t)} w`);
|
|
979
|
-
out.push(`[${dashed.map((n) => formatNumber(n)).join(" ")}] 0 d`);
|
|
980
|
-
const [r, g, b] = hexToRgb01(tok.resolvedRun.underlineColorHex ?? tok.resolvedRun.colorHex);
|
|
981
|
-
out.push(`${formatNumber(r)} ${formatNumber(g)} ${formatNumber(b)} RG`);
|
|
982
|
-
out.push(`${formatNumber(dx)} ${formatNumber(y + t / 2)} m ${formatNumber(dx + w)} ${formatNumber(y + t / 2)} l S`);
|
|
983
|
-
out.push("[] 0 d");
|
|
984
|
-
} else {
|
|
985
|
-
out.push(`${formatNumber(dx)} ${formatNumber(y)} ${formatNumber(w)} ${formatNumber(t)} re f`);
|
|
986
|
-
if (style === "double") out.push(`${formatNumber(dx)} ${formatNumber(y - t * 2)} ${formatNumber(w)} ${formatNumber(t)} re f`);
|
|
987
|
-
}
|
|
988
|
-
if (tok.resolvedRun.underlineColorHex) paint(tok.resolvedRun.colorHex);
|
|
989
|
-
}
|
|
990
|
-
if (tok.resolvedRun.strike) {
|
|
991
|
-
const y = baselineY + tok.fontSizePt * .26;
|
|
992
|
-
out.push(`${formatNumber(dx)} ${formatNumber(y)} ${formatNumber(w)} ${formatNumber(thickness)} re f`);
|
|
993
|
-
}
|
|
994
|
-
}
|
|
995
|
-
dx += w;
|
|
996
|
-
}
|
|
997
|
-
out.push("Q");
|
|
998
|
-
}
|
|
999
|
-
const hasRise = line.tokens.some((t) => t.kind === "text" && t.risePt !== void 0);
|
|
1000
|
-
if (rotationDeg !== 0 && !hasImageToken && !hasMathToken) {
|
|
1001
|
-
if (!inBT) {
|
|
1002
|
-
out.push("BT");
|
|
1003
|
-
inBT = true;
|
|
1004
|
-
}
|
|
1005
|
-
const rad = rotationDeg * Math.PI / 180;
|
|
1006
|
-
const cos = formatNumber(Math.cos(rad));
|
|
1007
|
-
const sin = formatNumber(Math.sin(rad));
|
|
1008
|
-
out.push(`${cos} ${sin} ${formatNumber(-Math.sin(rad))} ${cos} ${formatNumber(originX)} ${formatNumber(baselineY)} Tm`);
|
|
1009
|
-
for (const tok of line.tokens) {
|
|
1010
|
-
if (tok.kind !== "text") continue;
|
|
1011
|
-
switchFontIfNeeded(tok);
|
|
1012
|
-
out.push(tok.font.measure.showText(tok.text));
|
|
1013
|
-
}
|
|
1014
|
-
} else if (extraPerSpace !== 0 || hasImageToken || hasMathToken || hasRtl || hasRise || hasTab) {
|
|
1015
|
-
const order = hasRtl ? lineVisualOrder(line) : line.tokens.map((_, i) => i);
|
|
1016
|
-
let x = originX;
|
|
1017
|
-
for (const ti of order) {
|
|
1018
|
-
const tok = line.tokens[ti];
|
|
1019
|
-
if (tok.kind === "image") {
|
|
1020
|
-
flushLink();
|
|
1021
|
-
emitImageToken(tok, x, baselineY);
|
|
1022
|
-
x += tok.widthPt;
|
|
1023
|
-
continue;
|
|
1024
|
-
}
|
|
1025
|
-
if (tok.kind === "math") {
|
|
1026
|
-
flushLink();
|
|
1027
|
-
emitMathToken(tok, x, baselineY);
|
|
1028
|
-
x += tok.widthPt;
|
|
1029
|
-
continue;
|
|
1030
|
-
}
|
|
1031
|
-
if (!inBT) {
|
|
1032
|
-
out.push("BT");
|
|
1033
|
-
inBT = true;
|
|
1034
|
-
}
|
|
1035
|
-
switchFontIfNeeded(tok);
|
|
1036
|
-
out.push(`1 0 0 1 ${formatNumber(x)} ${formatNumber(baselineY + (tok.risePt ?? 0))} Tm`);
|
|
1037
|
-
out.push(showToken(tok));
|
|
1038
|
-
const tokenX0 = x;
|
|
1039
|
-
x += tok.widthPt;
|
|
1040
|
-
if (tok.isSpace) x += extraPerSpace;
|
|
1041
|
-
trackLink(tok.href, tok.anchor, tok.text, tokenX0, x);
|
|
1042
|
-
}
|
|
1043
|
-
flushLink();
|
|
1044
|
-
} else {
|
|
1045
|
-
if (!inBT) {
|
|
1046
|
-
out.push("BT");
|
|
1047
|
-
inBT = true;
|
|
1048
|
-
}
|
|
1049
|
-
out.push(`1 0 0 1 ${formatNumber(originX)} ${formatNumber(baselineY)} Tm`);
|
|
1050
|
-
let x = originX;
|
|
1051
|
-
for (const tok of line.tokens) {
|
|
1052
|
-
if (tok.kind !== "text") continue;
|
|
1053
|
-
switchFontIfNeeded(tok);
|
|
1054
|
-
out.push(tok.font.measure.showText(tok.text));
|
|
1055
|
-
trackLink(tok.href, tok.anchor, tok.text, x, x + tok.widthPt);
|
|
1056
|
-
x += tok.widthPt;
|
|
1057
|
-
}
|
|
1058
|
-
flushLink();
|
|
1059
|
-
}
|
|
1060
|
-
};
|
|
1061
|
-
if (tagging) for (const cmd of lines) {
|
|
1062
|
-
if (inBT) {
|
|
1063
|
-
out.push("ET");
|
|
1064
|
-
inBT = false;
|
|
1065
|
-
}
|
|
1066
|
-
const sid = cmd.structId;
|
|
1067
|
-
if (sid !== void 0) {
|
|
1068
|
-
const mcid = tagging.next++;
|
|
1069
|
-
tagging.assigned = true;
|
|
1070
|
-
tagging.record(sid, mcid);
|
|
1071
|
-
out.push(`/${tagging.tagFor(sid)} <</MCID ${mcid}>> BDC`);
|
|
1072
|
-
} else if (cmd.artifact === "pagination") out.push("/Artifact <</Type /Pagination>> BDC");
|
|
1073
|
-
else out.push("/Artifact BMC");
|
|
1074
|
-
emitClipped(cmd, emitOneLine);
|
|
1075
|
-
if (inBT) {
|
|
1076
|
-
out.push("ET");
|
|
1077
|
-
inBT = false;
|
|
1078
|
-
}
|
|
1079
|
-
out.push("EMC");
|
|
1080
|
-
}
|
|
1081
|
-
else {
|
|
1082
|
-
out.push("BT");
|
|
1083
|
-
inBT = true;
|
|
1084
|
-
for (const cmd of lines) emitClipped(cmd, emitOneLine);
|
|
1085
|
-
if (inBT) out.push("ET");
|
|
1086
|
-
}
|
|
1251
|
+
for (const run of plan.pictures) {
|
|
1252
|
+
if (run.length === 0) continue;
|
|
1253
|
+
if (tagging) out.push("/Artifact BMC");
|
|
1254
|
+
for (const item of run) emitInOrder(item);
|
|
1255
|
+
if (tagging) out.push("EMC");
|
|
1087
1256
|
}
|
|
1257
|
+
emitLinesPass();
|
|
1088
1258
|
return {
|
|
1089
1259
|
content: encoder.encode(out.join("\n")),
|
|
1090
1260
|
links
|