reamkit 1.27.0 → 1.28.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 +6 -5
- package/dist/esm/core/converter/ream.d.ts +0 -9
- package/dist/esm/core/converter/ream.js +0 -1
- package/dist/esm/core/document-model/types.d.ts +5 -3
- package/dist/esm/core/font/index.d.ts +1 -0
- package/dist/esm/core/font/ligatures.d.ts +17 -0
- package/dist/esm/core/font/ligatures.js +49 -0
- package/dist/esm/core/font/ttf-parser.d.ts +2 -1
- package/dist/esm/core/font/ttf-parser.js +11 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +1 -1
- package/dist/esm/core/fonts/remote-fonts.js +47 -2
- package/dist/esm/core/fonts/scripts.js +10 -5
- package/dist/esm/excel/header-footer.js +53 -8
- package/dist/esm/layout/styled-layout.js +53 -3
- package/dist/esm/pdf/cid-font.js +35 -8
- package/dist/esm/pdf-reader/annot-draw.js +114 -1
- package/dist/esm/pdf-reader/annots.d.ts +0 -14
- package/dist/esm/pdf-reader/annots.js +13 -1
- package/dist/esm/pdf-reader/ccitt.d.ts +2 -3
- package/dist/esm/pdf-reader/ccitt.js +32 -4
- package/dist/esm/pdf-reader/cff-outline.d.ts +36 -0
- package/dist/esm/pdf-reader/cff-outline.js +1122 -0
- package/dist/esm/pdf-reader/cmap.js +5 -2
- package/dist/esm/pdf-reader/content.d.ts +76 -0
- package/dist/esm/pdf-reader/content.js +142 -59
- package/dist/esm/pdf-reader/dingbats.d.ts +11 -0
- package/dist/esm/pdf-reader/dingbats.js +1033 -0
- package/dist/esm/pdf-reader/display.js +41 -1
- package/dist/esm/pdf-reader/document.js +26 -9
- package/dist/esm/pdf-reader/embedded-fonts.d.ts +11 -0
- package/dist/esm/pdf-reader/embedded-fonts.js +14 -1
- package/dist/esm/pdf-reader/encodings.d.ts +25 -0
- package/dist/esm/pdf-reader/encodings.js +110 -0
- package/dist/esm/pdf-reader/flow-build.d.ts +9 -3
- package/dist/esm/pdf-reader/flow-build.js +13 -7
- package/dist/esm/pdf-reader/font.js +329 -8
- package/dist/esm/pdf-reader/glyf-outline.d.ts +43 -0
- package/dist/esm/pdf-reader/glyf-outline.js +351 -0
- package/dist/esm/pdf-reader/glyph-names.js +20 -0
- package/dist/esm/pdf-reader/icc.d.ts +10 -0
- package/dist/esm/pdf-reader/icc.js +210 -0
- package/dist/esm/pdf-reader/image-decode.d.ts +4 -3
- package/dist/esm/pdf-reader/image-decode.js +85 -64
- package/dist/esm/pdf-reader/images.d.ts +6 -0
- package/dist/esm/pdf-reader/images.js +50 -7
- package/dist/esm/pdf-reader/jbig2.js +104 -19
- package/dist/esm/pdf-reader/layout.js +1148 -45
- package/dist/esm/pdf-reader/math-rows.d.ts +23 -0
- package/dist/esm/pdf-reader/math-rows.js +198 -0
- package/dist/esm/pdf-reader/predefined-cmap.d.ts +21 -0
- package/dist/esm/pdf-reader/predefined-cmap.js +102 -0
- package/dist/esm/pdf-reader/reader.d.ts +6 -9
- package/dist/esm/pdf-reader/reader.js +34 -21
- package/dist/esm/pdf-reader/shading.d.ts +81 -2
- package/dist/esm/pdf-reader/shading.js +191 -25
- package/dist/esm/pdf-reader/stream-filters.d.ts +6 -0
- package/dist/esm/pdf-reader/stream-filters.js +67 -0
- package/dist/esm/pdf-reader/text-rules.js +83 -10
- package/dist/esm/pdf-reader/text.js +82 -3
- package/dist/esm/pdf-reader/type1-outline.d.ts +21 -0
- package/dist/esm/pdf-reader/type1-outline.js +576 -0
- package/dist/esm/pdf-reader/vector.js +43 -4
- package/dist/esm/word/document-parser.js +4 -1
- package/dist/esm/word/docx-writer.js +1 -0
- package/package.json +1 -1
|
@@ -74,8 +74,11 @@ function utf16be(bytes) {
|
|
|
74
74
|
}
|
|
75
75
|
function incString(base, i) {
|
|
76
76
|
if (i === 0) return base;
|
|
77
|
-
|
|
78
|
-
return base;
|
|
77
|
+
const chars = [...base];
|
|
78
|
+
if (chars.length === 0) return base;
|
|
79
|
+
const last = chars[chars.length - 1].codePointAt(0) + i;
|
|
80
|
+
if (last > 1114111 || last >= 55296 && last <= 57343) return base;
|
|
81
|
+
return chars.slice(0, -1).join("") + String.fromCodePoint(last);
|
|
79
82
|
}
|
|
80
83
|
//#endregion
|
|
81
84
|
export { parseToUnicodeCMap };
|
|
@@ -11,10 +11,25 @@ import { PdfDict, PdfStream } from '../pdf/objects.js';
|
|
|
11
11
|
export interface ContentFont {
|
|
12
12
|
/** Bytes per character code: simple fonts read 1 byte/code, Type0 reads 2. */
|
|
13
13
|
readonly bytesPerCode: 1 | 2;
|
|
14
|
+
/**
|
|
15
|
+
* §9.7.6.2 — how a shown string breaks into codes, where the CMap is not
|
|
16
|
+
* fixed-width. A named CMap like `90ms-RKSJ-H` mixes one-byte and two-byte
|
|
17
|
+
* codes, and split down the middle a Japanese line came apart into nonsense.
|
|
18
|
+
* Absent means the fixed width above.
|
|
19
|
+
*/
|
|
20
|
+
readonly splitCodes?: (bytes: Uint8Array) => Array<number>;
|
|
14
21
|
/** Decode a sequence of character codes to a Unicode string. */
|
|
15
22
|
decode: (codes: ReadonlyArray<number>) => string;
|
|
16
23
|
/** Glyph advance for one code, in 1000-unit text space. */
|
|
17
24
|
width: (code: number) => number;
|
|
25
|
+
/**
|
|
26
|
+
* §9.4.4 / §9.7.4.3 — the face sets its text DOWN the page, not across, and
|
|
27
|
+
* the pen advances by the vertical displacement `w1` rather than by `w0`.
|
|
28
|
+
* A `…-V` CMap asks for this; `/DW2`'s default `[880 -1000]` is one em down.
|
|
29
|
+
* The number here is that displacement in 1000-unit text space, and it is
|
|
30
|
+
* negative because the page's y runs up.
|
|
31
|
+
*/
|
|
32
|
+
readonly verticalAdvance?: (code: number) => number;
|
|
18
33
|
/** §9.6.2 — the face's own `/BaseFont` name, for a document that embeds it. */
|
|
19
34
|
readonly name?: string;
|
|
20
35
|
/** §9.8.1 — the face is a bold one (weight, the ForceBold flag, or its name). */
|
|
@@ -27,6 +42,19 @@ export interface ContentFont {
|
|
|
27
42
|
* procedure paints, in the resources the font states.
|
|
28
43
|
*/
|
|
29
44
|
readonly type3?: Type3Face;
|
|
45
|
+
/**
|
|
46
|
+
* §9.6.6 — the OUTLINE a code draws, for a code that stands for no
|
|
47
|
+
* character. A face that can say what its characters are never has one:
|
|
48
|
+
* this is the last resort before a blank page.
|
|
49
|
+
*/
|
|
50
|
+
readonly outline?: GlyphOutline;
|
|
51
|
+
}
|
|
52
|
+
/** §9.6.6 — the outlines of a face read by glyph index, and their glyph space. */
|
|
53
|
+
export interface GlyphOutline {
|
|
54
|
+
/** Glyph space to text space, as a Type 3 font's `/FontMatrix` is. */
|
|
55
|
+
readonly matrix: Matrix;
|
|
56
|
+
/** The contours one code draws, or `undefined` where it draws none. */
|
|
57
|
+
readonly path: (code: number) => Array<PathSeg> | undefined;
|
|
30
58
|
}
|
|
31
59
|
/** §9.6.5 — the parts of a Type 3 font a caller needs to run its glyphs. */
|
|
32
60
|
export interface Type3Face {
|
|
@@ -94,6 +122,12 @@ export interface TextRun {
|
|
|
94
122
|
* fill colour still standing from before is not what the page shows.
|
|
95
123
|
*/
|
|
96
124
|
readonly fillPatternName?: string;
|
|
125
|
+
/**
|
|
126
|
+
* §8.7.4.5 — the glyphs are filled with a SHADING pattern: a sweep from one
|
|
127
|
+
* colour to another, of which the run carries the middle. The colour is not
|
|
128
|
+
* lost, the shape of it is.
|
|
129
|
+
*/
|
|
130
|
+
readonly gradientFill?: boolean;
|
|
97
131
|
/**
|
|
98
132
|
* §9.3.6 — the page painted these glyphs NOWHERE: mode 3 shows nothing and
|
|
99
133
|
* mode 7 only adds to the clip. A scanned page carries its recognised words
|
|
@@ -157,6 +191,8 @@ export interface ImagePlacement {
|
|
|
157
191
|
*/
|
|
158
192
|
readonly fillHex: string;
|
|
159
193
|
readonly mcid?: number;
|
|
194
|
+
/** §11.6.4.4 `/ca` — how opaque the picture is drawn, when the page asked for less. */
|
|
195
|
+
readonly alpha?: number;
|
|
160
196
|
/** §11.3.5 `/BM` — a blend the page asked for that nothing here performs. */
|
|
161
197
|
readonly blend?: string;
|
|
162
198
|
/** §11.6.5 `/SMask` — the paint faded from place to place; nothing here does. */
|
|
@@ -222,6 +258,13 @@ export interface VectorPlacement {
|
|
|
222
258
|
readonly blend?: string;
|
|
223
259
|
/** §11.6.5 `/SMask` — the paint faded from place to place; nothing here does. */
|
|
224
260
|
readonly masked?: boolean;
|
|
261
|
+
/**
|
|
262
|
+
* §9.6.6 — this path is a GLYPH, traced from the face because its code stands
|
|
263
|
+
* for no character. It is type, not artwork, so the de-cluttering a page's
|
|
264
|
+
* paths go through does not apply: a full stop is a mark one point across and
|
|
265
|
+
* every filter there would throw it out.
|
|
266
|
+
*/
|
|
267
|
+
readonly glyph?: boolean;
|
|
225
268
|
/**
|
|
226
269
|
* §8.7.3 — the TILING pattern resource name the path is filled with. Its
|
|
227
270
|
* content is a stream of its own, so what the fill actually shows is only
|
|
@@ -241,11 +284,44 @@ export interface InterpretResult {
|
|
|
241
284
|
readonly vectors: Array<VectorPlacement>;
|
|
242
285
|
/** §9.6.5 — every Type 3 glyph the stream showed, with where to run it. */
|
|
243
286
|
readonly glyphs: Array<Type3Call>;
|
|
287
|
+
/**
|
|
288
|
+
* §8.7.4.3 — every region the stream painted with a bare `sh`, which fills
|
|
289
|
+
* the CLIP rather than a path. What a caller can do with one depends on the
|
|
290
|
+
* shading's own type, so the placement is carried rather than counted.
|
|
291
|
+
*/
|
|
292
|
+
readonly shadings: Array<ShadingPaint>;
|
|
293
|
+
/**
|
|
294
|
+
* §9.6.6 — every glyph the stream showed that stands for NO character, as
|
|
295
|
+
* the path it draws in page space. There is nothing to write for one, and
|
|
296
|
+
* there is something to draw.
|
|
297
|
+
*/
|
|
298
|
+
readonly outlines: Array<VectorPlacement>;
|
|
244
299
|
}
|
|
245
300
|
/**
|
|
246
301
|
* §9.6.5 — one showing of a Type 3 glyph: which procedure, and the matrix that
|
|
247
302
|
* puts glyph space on the page.
|
|
248
303
|
*/
|
|
304
|
+
/** §8.7.4.3 — one `sh`: which shading, where the CTM put it, what bounded it. */
|
|
305
|
+
export interface ShadingPaint {
|
|
306
|
+
/** The `/Shading` resource name (no leading slash). */
|
|
307
|
+
readonly name: string;
|
|
308
|
+
/** The CTM in force, which maps the shading's own space onto the page. */
|
|
309
|
+
readonly ctm: Matrix;
|
|
310
|
+
/** §8.5.4 — the clip the paint was bounded by, which is its whole extent. */
|
|
311
|
+
readonly clip?: ClipRegion;
|
|
312
|
+
/**
|
|
313
|
+
* §11.6.5 `/SMask` — the paint was faded from place to place. For a `sh` that
|
|
314
|
+
* is not a detail: the mask is the SHAPE, and the clip is only its outer
|
|
315
|
+
* bound.
|
|
316
|
+
*/
|
|
317
|
+
readonly masked?: boolean;
|
|
318
|
+
/** §11.6.4.4 `/ca` — how opaque the paint is, when the page asked for less. */
|
|
319
|
+
readonly alpha?: number;
|
|
320
|
+
/** §11.3.5 `/BM` — the paint only DARKENS what it covers. */
|
|
321
|
+
readonly darkens?: boolean;
|
|
322
|
+
/** Where it fell in the painting order (§8.5.3). */
|
|
323
|
+
readonly order: number;
|
|
324
|
+
}
|
|
249
325
|
export interface Type3Call {
|
|
250
326
|
readonly stream: PdfStream;
|
|
251
327
|
readonly resources: PdfDict | undefined;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { PDF_NULL, PdfHexString, PdfName } from "../pdf/objects.js";
|
|
2
2
|
import { Lexer } from "./lexer.js";
|
|
3
|
-
import {
|
|
3
|
+
import { cmykHex, grayHex, rgbHex, spaceColor } from "./shading.js";
|
|
4
4
|
//#region src/pdf-reader/content.ts
|
|
5
5
|
/**
|
|
6
6
|
* A painted path emitted by the path-painting operators (§8.5.3), captured in
|
|
@@ -136,39 +136,42 @@ function spaceOf(operands, spaces) {
|
|
|
136
136
|
}
|
|
137
137
|
}
|
|
138
138
|
/**
|
|
139
|
-
* §8.
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
* there is. One number is the ambiguous case — grey in a device space, but the
|
|
144
|
-
* strength of a colorant in a Separation, where 1 is the ink at full and reads
|
|
145
|
-
* dark — so a lone component is only taken where the space said what it means.
|
|
139
|
+
* §8.7.4.5 — one colour for a whole sweep: the stop at its middle, or the mean
|
|
140
|
+
* of the two it falls between. A gradient is a shape a run cannot carry, and
|
|
141
|
+
* the end it starts at is no more the colour of the words than the end it
|
|
142
|
+
* finishes at.
|
|
146
143
|
*/
|
|
147
|
-
function
|
|
148
|
-
const
|
|
149
|
-
if (
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
144
|
+
function midGradient(gradient) {
|
|
145
|
+
const stops = [...gradient.stops].sort((a, b) => a.offset - b.offset);
|
|
146
|
+
if (stops.length === 0) return "000000";
|
|
147
|
+
const exact = stops.find((s) => Math.abs(s.offset - .5) < 1e-6);
|
|
148
|
+
if (exact) return exact.colorHex;
|
|
149
|
+
const before = [...stops].reverse().find((s) => s.offset <= .5) ?? stops[0];
|
|
150
|
+
const after = stops.find((s) => s.offset >= .5) ?? stops[stops.length - 1];
|
|
151
|
+
const span = after.offset - before.offset;
|
|
152
|
+
const t = span > 0 ? (.5 - before.offset) / span : 0;
|
|
153
|
+
const mix = (at) => {
|
|
154
|
+
const a = parseInt(before.colorHex.slice(at, at + 2), 16);
|
|
155
|
+
const b = parseInt(after.colorHex.slice(at, at + 2), 16);
|
|
156
|
+
return Number.isFinite(a) && Number.isFinite(b) ? Math.round(a + (b - a) * t) : 0;
|
|
157
|
+
};
|
|
158
|
+
return [
|
|
159
|
+
mix(0),
|
|
160
|
+
mix(2),
|
|
161
|
+
mix(4)
|
|
162
|
+
].map((c) => Math.max(0, Math.min(255, c)).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
163
|
+
}
|
|
164
|
+
/** §8.6.8 — the colour a run of `sc` / `scn` operands comes to (see `spaceColor`). */
|
|
165
|
+
function colorOfOperands(operands, space) {
|
|
166
|
+
return spaceColor(operands.filter((o) => typeof o === "number"), space);
|
|
166
167
|
}
|
|
167
168
|
function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__PURE__ */ new Map(), alphas = /* @__PURE__ */ new Map(), spaces = /* @__PURE__ */ new Map(), hiddenOc = /* @__PURE__ */ new Set()) {
|
|
168
169
|
const runs = [];
|
|
169
170
|
const images = [];
|
|
170
171
|
const vectors = [];
|
|
171
172
|
const glyphs = [];
|
|
173
|
+
const painted = [];
|
|
174
|
+
const outlines = [];
|
|
172
175
|
const lexer = new Lexer(bytes);
|
|
173
176
|
const stack = [];
|
|
174
177
|
let state = initialState();
|
|
@@ -285,12 +288,41 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
285
288
|
});
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
|
-
const
|
|
291
|
+
const outline = state.font.outline;
|
|
292
|
+
if (outline && visible() && state.renderMode !== 3 && state.renderMode !== 7) {
|
|
293
|
+
const segs = outline.path(code);
|
|
294
|
+
if (segs) {
|
|
295
|
+
const scale = [
|
|
296
|
+
state.fontSize * state.hScale,
|
|
297
|
+
0,
|
|
298
|
+
0,
|
|
299
|
+
state.fontSize,
|
|
300
|
+
0,
|
|
301
|
+
state.rise
|
|
302
|
+
];
|
|
303
|
+
const place = multiply(outline.matrix, multiply(scale, multiply(tm, state.ctm)));
|
|
304
|
+
outlines.push({
|
|
305
|
+
order: paintOrder++,
|
|
306
|
+
segs: segs.map((seg) => mapSeg(seg, place)),
|
|
307
|
+
...state.clip ? { clip: state.clip } : {},
|
|
308
|
+
fillHex: state.fillColor,
|
|
309
|
+
...state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
310
|
+
glyph: true
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
}
|
|
289
314
|
const isSpace = state.font.bytesPerCode === 1 && code === 32;
|
|
290
|
-
|
|
315
|
+
const spacing = state.charSpacing + (isSpace ? state.wordSpacing : 0);
|
|
316
|
+
const down = state.font.verticalAdvance;
|
|
317
|
+
if (down) {
|
|
318
|
+
tm = multiply(translation(0, down(code) / 1e3 * state.fontSize - spacing), tm);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
321
|
+
tm = multiply(translation((state.font.width(code) / 1e3 * state.fontSize + spacing) * state.hScale, 0), tm);
|
|
291
322
|
};
|
|
292
323
|
const consume = (operand) => {
|
|
293
|
-
const
|
|
324
|
+
const bytes = toBytes(operand);
|
|
325
|
+
const codes = state.font.splitCodes ? state.font.splitCodes(bytes) : splitCodes(bytes, state.font.bytesPerCode);
|
|
294
326
|
for (const code of codes) advanceGlyph(code);
|
|
295
327
|
return state.font.decode(codes);
|
|
296
328
|
};
|
|
@@ -316,13 +348,14 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
316
348
|
...state.font.type3 ? { type3: true } : {},
|
|
317
349
|
...state.renderMode === 3 || state.renderMode === 7 ? { invisible: true } : {},
|
|
318
350
|
...state.fillPattern !== void 0 ? { fillPatternName: state.fillPattern } : {},
|
|
351
|
+
...state.fillGradient ? { gradientFill: true } : {},
|
|
319
352
|
...strokesText(state.renderMode) ? {
|
|
320
353
|
outlineHex: state.strokeColor,
|
|
321
354
|
outlineWidthPt: ctmLineWidth()
|
|
322
355
|
} : {},
|
|
323
356
|
...state.font.bold ? { bold: true } : {},
|
|
324
357
|
...state.font.italic ? { italic: true } : {},
|
|
325
|
-
colorHex: state.fillColor,
|
|
358
|
+
colorHex: state.fillGradient ? midGradient(state.fillGradient) : state.fillColor,
|
|
326
359
|
...mcid !== void 0 ? { mcid } : {}
|
|
327
360
|
});
|
|
328
361
|
};
|
|
@@ -438,7 +471,9 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
438
471
|
...state.clip ? { clip: state.clip } : {},
|
|
439
472
|
fillHex: state.fillColor,
|
|
440
473
|
...mcid !== void 0 ? { mcid } : {},
|
|
441
|
-
...state.
|
|
474
|
+
...state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
475
|
+
...state.blendMode !== void 0 ? { blend: state.blendMode } : {},
|
|
476
|
+
...state.softMask ? { masked: true } : {}
|
|
442
477
|
});
|
|
443
478
|
}
|
|
444
479
|
break;
|
|
@@ -473,7 +508,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
473
508
|
state.fillPattern = state.fillGradient ? void 0 : named;
|
|
474
509
|
break;
|
|
475
510
|
}
|
|
476
|
-
const hex =
|
|
511
|
+
const hex = colorOfOperands(operands, state.fillSpace);
|
|
477
512
|
if (hex !== void 0) {
|
|
478
513
|
state.fillColor = hex;
|
|
479
514
|
state.fillGradient = void 0;
|
|
@@ -484,7 +519,7 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
484
519
|
case "SCN":
|
|
485
520
|
case "SC": {
|
|
486
521
|
if (operands[operands.length - 1] instanceof PdfName) break;
|
|
487
|
-
const hex =
|
|
522
|
+
const hex = colorOfOperands(operands, state.strokeSpace);
|
|
488
523
|
if (hex !== void 0) state.strokeColor = hex;
|
|
489
524
|
break;
|
|
490
525
|
}
|
|
@@ -536,17 +571,32 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
536
571
|
path.push({ op: "close" });
|
|
537
572
|
paintPath(true, true);
|
|
538
573
|
break;
|
|
574
|
+
case "sh": {
|
|
575
|
+
const nm = operands[0];
|
|
576
|
+
if (nm instanceof PdfName && visible()) painted.push({
|
|
577
|
+
name: nm.value,
|
|
578
|
+
ctm: state.ctm,
|
|
579
|
+
...state.clip ? { clip: state.clip } : {},
|
|
580
|
+
...state.softMask ? { masked: true } : {},
|
|
581
|
+
...state.fillAlpha < 1 ? { alpha: state.fillAlpha } : {},
|
|
582
|
+
...state.fillDarkens ? { darkens: true } : {},
|
|
583
|
+
order: paintOrder++
|
|
584
|
+
});
|
|
585
|
+
break;
|
|
586
|
+
}
|
|
539
587
|
case "n":
|
|
540
588
|
paintPath(false, false);
|
|
541
589
|
break;
|
|
542
590
|
case "gs": {
|
|
543
591
|
const nm = operands[operands.length - 1];
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
state.fillAlpha = paint
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
592
|
+
const paint = nm instanceof PdfName ? alphas.get(nm.value) : void 0;
|
|
593
|
+
if (paint) {
|
|
594
|
+
if (paint.alpha !== void 0) state.fillAlpha = paint.alpha;
|
|
595
|
+
if (paint.statesBlend === true) {
|
|
596
|
+
state.fillDarkens = paint.darkens ?? false;
|
|
597
|
+
state.blendMode = paint.blend;
|
|
598
|
+
}
|
|
599
|
+
if (paint.masked !== void 0) state.softMask = paint.masked;
|
|
550
600
|
}
|
|
551
601
|
break;
|
|
552
602
|
}
|
|
@@ -605,7 +655,34 @@ function interpretContent(bytes, fonts, initialCtm = IDENTITY, shadings = /* @__
|
|
|
605
655
|
texts: runs,
|
|
606
656
|
images,
|
|
607
657
|
vectors,
|
|
608
|
-
glyphs
|
|
658
|
+
glyphs,
|
|
659
|
+
shadings: painted,
|
|
660
|
+
outlines
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
/** One path segment through a matrix — the glyph's own space onto the page. */
|
|
664
|
+
function mapSeg(seg, m) {
|
|
665
|
+
const at = (x, y) => [m[0] * x + m[2] * y + m[4], m[1] * x + m[3] * y + m[5]];
|
|
666
|
+
if (seg.op === "close") return seg;
|
|
667
|
+
if (seg.op === "cubic") {
|
|
668
|
+
const [x1, y1] = at(seg.x1, seg.y1);
|
|
669
|
+
const [x2, y2] = at(seg.x2, seg.y2);
|
|
670
|
+
const [x, y] = at(seg.x, seg.y);
|
|
671
|
+
return {
|
|
672
|
+
op: "cubic",
|
|
673
|
+
x1,
|
|
674
|
+
y1,
|
|
675
|
+
x2,
|
|
676
|
+
y2,
|
|
677
|
+
x,
|
|
678
|
+
y
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
const [x, y] = at(seg.x, seg.y);
|
|
682
|
+
return {
|
|
683
|
+
op: seg.op,
|
|
684
|
+
x,
|
|
685
|
+
y
|
|
609
686
|
};
|
|
610
687
|
}
|
|
611
688
|
/** §9.3.6 — the rendering modes that put a line round the glyphs. */
|
|
@@ -657,21 +734,6 @@ function isRightToLeft(text) {
|
|
|
657
734
|
function isRtl(cp) {
|
|
658
735
|
return cp >= 1424 && cp <= 1535 || cp >= 1536 && cp <= 1791 || cp >= 1792 && cp <= 1871 || cp >= 1920 && cp <= 1983 || cp >= 2208 && cp <= 2303 || cp >= 64285 && cp <= 65023 || cp >= 65136 && cp <= 65279;
|
|
659
736
|
}
|
|
660
|
-
function clamp255(v) {
|
|
661
|
-
return Math.max(0, Math.min(255, Math.round(v * 255)));
|
|
662
|
-
}
|
|
663
|
-
function hex2(v) {
|
|
664
|
-
return clamp255(v).toString(16).padStart(2, "0");
|
|
665
|
-
}
|
|
666
|
-
function rgbHex(r, g, b) {
|
|
667
|
-
return (hex2(r) + hex2(g) + hex2(b)).toUpperCase();
|
|
668
|
-
}
|
|
669
|
-
function grayHex(v) {
|
|
670
|
-
return rgbHex(v, v, v);
|
|
671
|
-
}
|
|
672
|
-
function cmykHex(c, m, y, k) {
|
|
673
|
-
return rgbHex((1 - c) * (1 - k), (1 - m) * (1 - k), (1 - y) * (1 - k));
|
|
674
|
-
}
|
|
675
737
|
function matrixFromOperands(operands) {
|
|
676
738
|
const n = (i) => typeof operands[i] === "number" ? operands[i] : 0;
|
|
677
739
|
return [
|
|
@@ -705,9 +767,30 @@ function readArray(lexer) {
|
|
|
705
767
|
for (;;) {
|
|
706
768
|
const tok = lexer.nextToken();
|
|
707
769
|
if (tok.kind === "arrayClose" || tok.kind === "eof") break;
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
770
|
+
switch (tok.kind) {
|
|
771
|
+
case "num":
|
|
772
|
+
out.push(tok.value);
|
|
773
|
+
break;
|
|
774
|
+
case "str":
|
|
775
|
+
out.push(tok.value);
|
|
776
|
+
break;
|
|
777
|
+
case "hexstr":
|
|
778
|
+
out.push(new PdfHexString(tok.bytes));
|
|
779
|
+
break;
|
|
780
|
+
case "name":
|
|
781
|
+
out.push(new PdfName(tok.value));
|
|
782
|
+
break;
|
|
783
|
+
case "arrayOpen":
|
|
784
|
+
out.push(readArray(lexer));
|
|
785
|
+
break;
|
|
786
|
+
case "dictOpen":
|
|
787
|
+
out.push(readDict(lexer));
|
|
788
|
+
break;
|
|
789
|
+
case "keyword":
|
|
790
|
+
if (tok.value === "true" || tok.value === "false") out.push(tok.value === "true");
|
|
791
|
+
break;
|
|
792
|
+
default: break;
|
|
793
|
+
}
|
|
711
794
|
}
|
|
712
795
|
return out;
|
|
713
796
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The character a ZapfDingbats code stands for, or `undefined` for an unused one. */
|
|
2
|
+
export declare function zapfDingbatsChar(code: number): string | undefined;
|
|
3
|
+
/**
|
|
4
|
+
* The character a dingbat's glyph NAME stands for — `a38` is ✫ — for a font
|
|
5
|
+
* that names its glyphs through `/Differences` (§9.6.6.1).
|
|
6
|
+
*
|
|
7
|
+
* @param name The glyph name.
|
|
8
|
+
*/
|
|
9
|
+
export declare function dingbatChar(name: string): string | undefined;
|
|
10
|
+
/** Whether a base font names the ZapfDingbats face (§9.6.2.2 Table 109). */
|
|
11
|
+
export declare function isZapfDingbats(baseFont: string): boolean;
|