pdf-codec.js 5.0.1 → 5.2.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 +43 -0
- package/dist/codec.d.cts +1 -0
- package/dist/codec.d.ts +1 -0
- package/dist/font-read.cjs +94 -12
- package/dist/font-read.d.cts +7 -1
- package/dist/font-read.d.ts +7 -1
- package/dist/font-read.js +94 -12
- package/dist/index.cjs +7 -0
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/interpret.cjs +23 -7
- package/dist/interpret.d.cts +9 -1
- package/dist/interpret.d.ts +9 -1
- package/dist/interpret.js +23 -7
- package/dist/layout.cjs +1 -0
- package/dist/layout.d.cts +4 -0
- package/dist/layout.d.ts +4 -0
- package/dist/layout.js +1 -0
- package/dist/raster.cjs +14 -8
- package/dist/raster.js +14 -8
- package/dist/read.cjs +1 -0
- package/dist/read.js +1 -0
- package/dist/text-group.cjs +227 -0
- package/dist/text-group.d.cts +75 -0
- package/dist/text-group.d.ts +75 -0
- package/dist/text-group.js +221 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -310,6 +310,49 @@ Reading a program's built-in encoding is what stops a symbol-encoded subset —
|
|
|
310
310
|
|
|
311
311
|
**Where nothing states an answer, the answer is the replacement character plus a `text/unmapped-encoding` diagnostic, never a guess.** Two cases reach it in practice: a symbolic font with no embedded program and no `/ToUnicode`, and a subsetted font that both strips its glyph names and maps its glyphs only from private-use code points — a private-use code point identifies a glyph inside one font and says nothing about the character it draws, so it is treated as no answer rather than a wrong one.
|
|
312
312
|
|
|
313
|
+
## Grouping text runs into lines and words
|
|
314
|
+
|
|
315
|
+
`readPdf` reports one positioned run per text-showing operator, and a PDF says nothing about lines or words: a line of prose can arrive as one run, as one run per word, or as one run per glyph, entirely at the producer's discretion. `groupPdfTextRuns` turns those runs back into lines of words, and `pdf-codec/text-group` serves it without the write half or the vendored fonts, alongside `pdf-codec/read`.
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
import { readPdf } from "pdf-codec/read";
|
|
319
|
+
import { groupPdfTextRuns } from "pdf-codec/text-group";
|
|
320
|
+
|
|
321
|
+
const page = readPdf(bytes).pages[0];
|
|
322
|
+
const runs = page.items.filter((item) => item.kind === "text");
|
|
323
|
+
for (const line of groupPdfTextRuns(runs)) {
|
|
324
|
+
console.log(line.text);
|
|
325
|
+
}
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
Two rules decide everything, and both were got wrong often enough by hand ([#1317](https://github.com/ExaDev/documents.js/issues/1317)) to be worth stating.
|
|
329
|
+
|
|
330
|
+
Two runs are on one line when their baselines sit within a fraction of an em of each other, measured against **the smaller of the two**. Taken from the larger, a 30pt heading's own window reaches the 9pt line beneath it, the merged line's runs sort by x into a sequence whose gaps are negative, a negative gap reads as one word, and the two lines concatenate into exactly the run-together text the grouping exists to prevent. The default fraction is two thirds, bounded on both sides by real typography: two consecutive lines are never closer than solid setting puts them, one full em, so it has to stay under 1; a superscript raised by at most a third of its parent's size at no less than half that size shifts by at most two thirds of its own em, so anything tighter cuts footnote markers off the line they annotate.
|
|
331
|
+
|
|
332
|
+
A run whose `widthPt` is absent states no advance, so where it ends is unknown and the gap after it is underivable. `runGapPt` reports `undefined` for that, and an undefined gap is **no evidence of a space**. Reading it as zero puts the previous run's end at its own start, turns its whole advance into an apparent gap, and produces "Com plete ly".
|
|
333
|
+
|
|
334
|
+
Gaps that are derivable become a word space at an eighth of an em (the narrowest genuine one: the standard fourteen faces set their space glyph at 250/1000 em, and justified setting compresses to no less than half of that) and a column boundary past a full em (wider than the em space, the widest single space character there is), so a table's row reads as `"North\t4.2m\t11%"` rather than as one sentence. `runsShareBaseline` and `runGapPt` are exported on their own for a consumer with its own pipeline around them, and every threshold is overridable.
|
|
335
|
+
|
|
336
|
+
Limits, each inherent to what a PDF states rather than to the implementation: grouping is by baseline alone with no page segmentation, so on a multi-column page whose columns sit at different vertical offsets a line of one can fall within tolerance of a line of the next and the two are reported as one line with a column boundary between them, which is the cut a caller needs (`document-outline.js`'s `segmentPdfRegions` finds the gutter first if you want them genuinely apart); text comes out in visual order, so a right-to-left script needs the Unicode Bidi Algorithm applied to the result; a vertically set run groups into a column instead of a line, reported with a `rotationDeg` of 270 and its own `writingMode`, with columns ordered right to left; and a word hyphenated across a line end stays split, hyphen intact, because rejoining it is a paragraph-level judgement this package leaves to its consumers.
|
|
337
|
+
|
|
338
|
+
## Vertical writing mode
|
|
339
|
+
|
|
340
|
+
A composite font's `/Encoding` CMap chooses a writing mode (ISO 32000-1 9.7.5.1). Mode 1 is vertical: the glyphs stay upright but the text position advances **down** the page, by the descendant CIDFont's own `/DW2` and `/W2` vertical metrics rather than by its horizontal widths, and each glyph paints offset from that position by its own position vector. `readPdf` reads all of it ([#1358](https://github.com/ExaDev/documents.js/issues/1358)), from a predefined CMap's `-V` name, from the bare `V` CMap, or from an embedded CMap stream's own `/WMode`.
|
|
341
|
+
|
|
342
|
+
A vertically set run carries `writingMode: "vertical"`, and that is a separate fact from `rotationDeg`, which reports the text rendering matrix turning the glyphs themselves on their side. An ordinary Japanese column is `writingMode: "vertical"` with a `rotationDeg` of 0: upright glyphs, running downward. On such a run, `xPt`/`yPt` is the top of the column and `widthPt` measures downward.
|
|
343
|
+
|
|
344
|
+
```ts
|
|
345
|
+
const runs = page.items.filter((item) => item.kind === "text");
|
|
346
|
+
for (const line of groupPdfTextRuns(runs)) {
|
|
347
|
+
// A vertical column reports rotationDeg 270 (the direction it advances) and writingMode "vertical".
|
|
348
|
+
console.log(line.writingMode ?? "horizontal", line.text);
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
`groupPdfTextRuns` groups such runs into columns, ordered right to left, and never lets a column and a line merge even when they advance along the same axis: a column of upright glyphs and a line of glyphs turned on their side are not the same text, whatever direction they share.
|
|
353
|
+
|
|
354
|
+
What is not supported: a **predefined non-Identity CMap's own byte decoding**. `90ms-RKSJ-V` and its siblings remap multi-byte character codes to CIDs through tables this package does not carry, so a font using one still has its codes read as two-byte CIDs. That is this package's long-standing composite-font limit, unchanged by and unrelated to writing mode; `Identity-V` (what modern producers emit) is read exactly. `writePdf` produces horizontal text only, and has no way to request a vertical one.
|
|
355
|
+
|
|
313
356
|
## JBIG2 scope
|
|
314
357
|
|
|
315
358
|
`src/image/jbig2*.ts` is a hand-written ITU-T T.88 decoder covering what real scanned PDFs actually contain.
|
package/dist/codec.d.cts
CHANGED
|
@@ -54,6 +54,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
widthPt: z.ZodOptional<z.ZodNumber>;
|
|
56
56
|
rotationDeg: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
writingMode: z.ZodOptional<z.ZodLiteral<"vertical">>;
|
|
57
58
|
underline: z.ZodOptional<z.ZodBoolean>;
|
|
58
59
|
layer: z.ZodOptional<z.ZodString>;
|
|
59
60
|
actualText: z.ZodOptional<z.ZodString>;
|
package/dist/codec.d.ts
CHANGED
|
@@ -54,6 +54,7 @@ declare const pdfCodec: z.ZodCodec<z.ZodCustom<Uint8Array<ArrayBuffer>, Uint8Arr
|
|
|
54
54
|
}, z.core.$strip>;
|
|
55
55
|
widthPt: z.ZodOptional<z.ZodNumber>;
|
|
56
56
|
rotationDeg: z.ZodOptional<z.ZodNumber>;
|
|
57
|
+
writingMode: z.ZodOptional<z.ZodLiteral<"vertical">>;
|
|
57
58
|
underline: z.ZodOptional<z.ZodBoolean>;
|
|
58
59
|
layer: z.ZodOptional<z.ZodString>;
|
|
59
60
|
actualText: z.ZodOptional<z.ZodString>;
|
package/dist/font-read.cjs
CHANGED
|
@@ -177,6 +177,63 @@ function readCidWidths(w) {
|
|
|
177
177
|
return map;
|
|
178
178
|
}
|
|
179
179
|
const DEFAULT_CID_WIDTH = 1e3;
|
|
180
|
+
const DEFAULT_VERTICAL_POSITION_Y = 880;
|
|
181
|
+
const DEFAULT_VERTICAL_DISPLACEMENT_Y = -1e3;
|
|
182
|
+
const DW2_ENTRY_COUNT = 2;
|
|
183
|
+
const W2_TRIPLET_LENGTH = 3;
|
|
184
|
+
const VERTICAL_WRITING_MODE = 1;
|
|
185
|
+
function readCidVerticalMetrics(w2) {
|
|
186
|
+
const map = /* @__PURE__ */ new Map();
|
|
187
|
+
if (w2 === void 0) return map;
|
|
188
|
+
let i = 0;
|
|
189
|
+
while (i < w2.length) {
|
|
190
|
+
const first = require_objects.asNumber(w2[i]);
|
|
191
|
+
if (first === void 0) {
|
|
192
|
+
i++;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
const next = w2[i + 1];
|
|
196
|
+
if (next?.kind === "array") {
|
|
197
|
+
tripletsOf(next.items).forEach((triplet, index) => {
|
|
198
|
+
const entry = verticalEntryFrom(require_objects.asNumber(triplet[0]), require_objects.asNumber(triplet[1]), require_objects.asNumber(triplet[2]));
|
|
199
|
+
if (entry !== void 0) map.set(first + index, entry);
|
|
200
|
+
});
|
|
201
|
+
i += 2;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
const last = require_objects.asNumber(next);
|
|
205
|
+
const entry = verticalEntryFrom(require_objects.asNumber(w2[i + 2]), require_objects.asNumber(w2[i + 3]), require_objects.asNumber(w2[i + 4]));
|
|
206
|
+
if (last !== void 0 && entry !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, entry);
|
|
207
|
+
i += 5;
|
|
208
|
+
}
|
|
209
|
+
return map;
|
|
210
|
+
}
|
|
211
|
+
function tripletsOf(items) {
|
|
212
|
+
const groups = [];
|
|
213
|
+
for (const item of items) {
|
|
214
|
+
const last = groups[groups.length - 1];
|
|
215
|
+
if (last !== void 0 && last.length < W2_TRIPLET_LENGTH) last.push(item);
|
|
216
|
+
else groups.push([item]);
|
|
217
|
+
}
|
|
218
|
+
return groups;
|
|
219
|
+
}
|
|
220
|
+
function verticalEntryFrom(displacementY, positionX, positionY) {
|
|
221
|
+
if (displacementY === void 0 || positionX === void 0 || positionY === void 0) return;
|
|
222
|
+
return {
|
|
223
|
+
displacementY,
|
|
224
|
+
positionX,
|
|
225
|
+
positionY
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
function predefinedCMapIsVertical(name) {
|
|
229
|
+
return name === "V" || name.endsWith("-V");
|
|
230
|
+
}
|
|
231
|
+
function readsVertically(fontDict, context) {
|
|
232
|
+
const encoding = context.resolver.resolve(require_objects.dictGet(fontDict, "Encoding"));
|
|
233
|
+
if (encoding?.kind === "name") return predefinedCMapIsVertical(encoding.name);
|
|
234
|
+
if (encoding?.kind === "stream") return require_objects.asNumber(require_objects.dictGet(encoding.dict, "WMode")) === VERTICAL_WRITING_MODE;
|
|
235
|
+
return false;
|
|
236
|
+
}
|
|
180
237
|
function buildCompositeFont(fontDict, context) {
|
|
181
238
|
const baseFont = require_objects.asName(require_objects.dictGet(fontDict, "BaseFont")) ?? "Helvetica";
|
|
182
239
|
const descendants = require_objects.asArray(require_objects.dictGet(fontDict, "DescendantFonts"));
|
|
@@ -186,9 +243,22 @@ function buildCompositeFont(fontDict, context) {
|
|
|
186
243
|
const dw = descendantDict !== void 0 ? require_objects.asNumber(require_objects.dictGet(descendantDict, "DW")) ?? DEFAULT_CID_WIDTH : DEFAULT_CID_WIDTH;
|
|
187
244
|
const widthMap = readCidWidths(descendantDict !== void 0 ? require_objects.asArray(require_objects.dictGet(descendantDict, "W")) : void 0);
|
|
188
245
|
const widthOf = (cid) => widthMap.get(cid) ?? dw;
|
|
246
|
+
const dw2 = descendantDict !== void 0 ? require_objects.asArray(require_objects.dictGet(descendantDict, "DW2")) : void 0;
|
|
247
|
+
const defaultPositionY = (dw2?.length === DW2_ENTRY_COUNT ? require_objects.asNumber(dw2[0]) : void 0) ?? DEFAULT_VERTICAL_POSITION_Y;
|
|
248
|
+
const defaultDisplacementY = (dw2?.length === DW2_ENTRY_COUNT ? require_objects.asNumber(dw2[1]) : void 0) ?? DEFAULT_VERTICAL_DISPLACEMENT_Y;
|
|
249
|
+
const verticalMap = readCidVerticalMetrics(descendantDict !== void 0 ? require_objects.asArray(require_objects.dictGet(descendantDict, "W2")) : void 0);
|
|
250
|
+
const verticalMetricsOf = (cid) => {
|
|
251
|
+
const entry = verticalMap.get(cid);
|
|
252
|
+
return {
|
|
253
|
+
displacementY: entry?.displacementY ?? defaultDisplacementY,
|
|
254
|
+
positionX: entry?.positionX ?? widthOf(cid) / 2,
|
|
255
|
+
positionY: entry?.positionY ?? defaultPositionY
|
|
256
|
+
};
|
|
257
|
+
};
|
|
189
258
|
const toUnicode = readToUnicodeCMap(fontDict, context);
|
|
190
259
|
const cidToGidMap = descendantDict !== void 0 ? require_objects.dictGet(descendantDict, "CIDToGIDMap") : void 0;
|
|
191
|
-
const
|
|
260
|
+
const encodingName = require_objects.dictGet(fontDict, "Encoding");
|
|
261
|
+
const programEncoding = (require_objects.isName(encodingName, "Identity-H") || require_objects.isName(encodingName, "Identity-V")) && (cidToGidMap === void 0 || require_objects.isName(cidToGidMap, "Identity")) ? lazyFontProgram(descriptor, context) : void 0;
|
|
192
262
|
const decodeToUnicode = (codes) => {
|
|
193
263
|
let out = "";
|
|
194
264
|
let glyphCount = 0;
|
|
@@ -222,7 +292,8 @@ function buildCompositeFont(fontDict, context) {
|
|
|
222
292
|
bold,
|
|
223
293
|
italic,
|
|
224
294
|
widthOf,
|
|
225
|
-
decodeToUnicode
|
|
295
|
+
decodeToUnicode,
|
|
296
|
+
...readsVertically(fontDict, context) ? { verticalMetricsOf } : {}
|
|
226
297
|
};
|
|
227
298
|
}
|
|
228
299
|
function createFontResolver(context) {
|
|
@@ -237,16 +308,27 @@ function createFontResolver(context) {
|
|
|
237
308
|
return resolved;
|
|
238
309
|
};
|
|
239
310
|
return {
|
|
240
|
-
metrics: {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
311
|
+
metrics: {
|
|
312
|
+
glyphAdvance(fontResourceName, resources, codes, byteOffset) {
|
|
313
|
+
const font = resolve(fontResourceName, resources);
|
|
314
|
+
if (font === void 0) return;
|
|
315
|
+
const byteLengthConsumed = font.composite ? 2 : 1;
|
|
316
|
+
const code = font.composite ? (codes[byteOffset] ?? 0) << 8 | (codes[byteOffset + 1] ?? 0) : codes[byteOffset] ?? 0;
|
|
317
|
+
const vertical = font.verticalMetricsOf?.(code);
|
|
318
|
+
return {
|
|
319
|
+
widthPer1000: font.widthOf(code),
|
|
320
|
+
byteLengthConsumed,
|
|
321
|
+
...vertical === void 0 ? {} : { vertical: {
|
|
322
|
+
displacementPer1000: vertical.displacementY,
|
|
323
|
+
positionXPer1000: vertical.positionX,
|
|
324
|
+
positionYPer1000: vertical.positionY
|
|
325
|
+
} }
|
|
326
|
+
};
|
|
327
|
+
},
|
|
328
|
+
isVertical(fontResourceName, resources) {
|
|
329
|
+
return resolve(fontResourceName, resources)?.verticalMetricsOf !== void 0;
|
|
330
|
+
}
|
|
331
|
+
},
|
|
250
332
|
resolve
|
|
251
333
|
};
|
|
252
334
|
}
|
package/dist/font-read.d.cts
CHANGED
|
@@ -2,6 +2,11 @@ import { PdfDiagnosticSink } from "./diagnostics.cjs";
|
|
|
2
2
|
import { n as PdfDict } from "./objects-B7HdMeWS.cjs";
|
|
3
3
|
import { FontMetricsPort, PdfObjectResolver } from "./interpret.cjs";
|
|
4
4
|
//#region src/font-read.d.ts
|
|
5
|
+
interface VerticalGlyphMetrics {
|
|
6
|
+
readonly displacementY: number;
|
|
7
|
+
readonly positionX: number;
|
|
8
|
+
readonly positionY: number;
|
|
9
|
+
}
|
|
5
10
|
interface PdfFont {
|
|
6
11
|
readonly composite: boolean;
|
|
7
12
|
readonly family: string;
|
|
@@ -9,6 +14,7 @@ interface PdfFont {
|
|
|
9
14
|
readonly italic: boolean;
|
|
10
15
|
widthOf(code: number): number;
|
|
11
16
|
decodeToUnicode(codes: Uint8Array<ArrayBuffer>): string;
|
|
17
|
+
readonly verticalMetricsOf?: (code: number) => VerticalGlyphMetrics;
|
|
12
18
|
}
|
|
13
19
|
interface FontReadContext {
|
|
14
20
|
readonly resolver: PdfObjectResolver;
|
|
@@ -20,4 +26,4 @@ interface FontResolverService {
|
|
|
20
26
|
}
|
|
21
27
|
declare function createFontResolver(context: FontReadContext): FontResolverService;
|
|
22
28
|
//#endregion
|
|
23
|
-
export { FontReadContext, FontResolverService, PdfFont, createFontResolver };
|
|
29
|
+
export { FontReadContext, FontResolverService, PdfFont, VerticalGlyphMetrics, createFontResolver };
|
package/dist/font-read.d.ts
CHANGED
|
@@ -2,6 +2,11 @@ import { PdfDiagnosticSink } from "./diagnostics.js";
|
|
|
2
2
|
import { n as PdfDict } from "./objects-B7HdMeWS.js";
|
|
3
3
|
import { FontMetricsPort, PdfObjectResolver } from "./interpret.js";
|
|
4
4
|
//#region src/font-read.d.ts
|
|
5
|
+
interface VerticalGlyphMetrics {
|
|
6
|
+
readonly displacementY: number;
|
|
7
|
+
readonly positionX: number;
|
|
8
|
+
readonly positionY: number;
|
|
9
|
+
}
|
|
5
10
|
interface PdfFont {
|
|
6
11
|
readonly composite: boolean;
|
|
7
12
|
readonly family: string;
|
|
@@ -9,6 +14,7 @@ interface PdfFont {
|
|
|
9
14
|
readonly italic: boolean;
|
|
10
15
|
widthOf(code: number): number;
|
|
11
16
|
decodeToUnicode(codes: Uint8Array<ArrayBuffer>): string;
|
|
17
|
+
readonly verticalMetricsOf?: (code: number) => VerticalGlyphMetrics;
|
|
12
18
|
}
|
|
13
19
|
interface FontReadContext {
|
|
14
20
|
readonly resolver: PdfObjectResolver;
|
|
@@ -20,4 +26,4 @@ interface FontResolverService {
|
|
|
20
26
|
}
|
|
21
27
|
declare function createFontResolver(context: FontReadContext): FontResolverService;
|
|
22
28
|
//#endregion
|
|
23
|
-
export { FontReadContext, FontResolverService, PdfFont, createFontResolver };
|
|
29
|
+
export { FontReadContext, FontResolverService, PdfFont, VerticalGlyphMetrics, createFontResolver };
|
package/dist/font-read.js
CHANGED
|
@@ -176,6 +176,63 @@ function readCidWidths(w) {
|
|
|
176
176
|
return map;
|
|
177
177
|
}
|
|
178
178
|
const DEFAULT_CID_WIDTH = 1e3;
|
|
179
|
+
const DEFAULT_VERTICAL_POSITION_Y = 880;
|
|
180
|
+
const DEFAULT_VERTICAL_DISPLACEMENT_Y = -1e3;
|
|
181
|
+
const DW2_ENTRY_COUNT = 2;
|
|
182
|
+
const W2_TRIPLET_LENGTH = 3;
|
|
183
|
+
const VERTICAL_WRITING_MODE = 1;
|
|
184
|
+
function readCidVerticalMetrics(w2) {
|
|
185
|
+
const map = /* @__PURE__ */ new Map();
|
|
186
|
+
if (w2 === void 0) return map;
|
|
187
|
+
let i = 0;
|
|
188
|
+
while (i < w2.length) {
|
|
189
|
+
const first = asNumber(w2[i]);
|
|
190
|
+
if (first === void 0) {
|
|
191
|
+
i++;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
const next = w2[i + 1];
|
|
195
|
+
if (next?.kind === "array") {
|
|
196
|
+
tripletsOf(next.items).forEach((triplet, index) => {
|
|
197
|
+
const entry = verticalEntryFrom(asNumber(triplet[0]), asNumber(triplet[1]), asNumber(triplet[2]));
|
|
198
|
+
if (entry !== void 0) map.set(first + index, entry);
|
|
199
|
+
});
|
|
200
|
+
i += 2;
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
203
|
+
const last = asNumber(next);
|
|
204
|
+
const entry = verticalEntryFrom(asNumber(w2[i + 2]), asNumber(w2[i + 3]), asNumber(w2[i + 4]));
|
|
205
|
+
if (last !== void 0 && entry !== void 0) for (let cid = first; cid <= last; cid++) map.set(cid, entry);
|
|
206
|
+
i += 5;
|
|
207
|
+
}
|
|
208
|
+
return map;
|
|
209
|
+
}
|
|
210
|
+
function tripletsOf(items) {
|
|
211
|
+
const groups = [];
|
|
212
|
+
for (const item of items) {
|
|
213
|
+
const last = groups[groups.length - 1];
|
|
214
|
+
if (last !== void 0 && last.length < W2_TRIPLET_LENGTH) last.push(item);
|
|
215
|
+
else groups.push([item]);
|
|
216
|
+
}
|
|
217
|
+
return groups;
|
|
218
|
+
}
|
|
219
|
+
function verticalEntryFrom(displacementY, positionX, positionY) {
|
|
220
|
+
if (displacementY === void 0 || positionX === void 0 || positionY === void 0) return;
|
|
221
|
+
return {
|
|
222
|
+
displacementY,
|
|
223
|
+
positionX,
|
|
224
|
+
positionY
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function predefinedCMapIsVertical(name) {
|
|
228
|
+
return name === "V" || name.endsWith("-V");
|
|
229
|
+
}
|
|
230
|
+
function readsVertically(fontDict, context) {
|
|
231
|
+
const encoding = context.resolver.resolve(dictGet(fontDict, "Encoding"));
|
|
232
|
+
if (encoding?.kind === "name") return predefinedCMapIsVertical(encoding.name);
|
|
233
|
+
if (encoding?.kind === "stream") return asNumber(dictGet(encoding.dict, "WMode")) === VERTICAL_WRITING_MODE;
|
|
234
|
+
return false;
|
|
235
|
+
}
|
|
179
236
|
function buildCompositeFont(fontDict, context) {
|
|
180
237
|
const baseFont = asName(dictGet(fontDict, "BaseFont")) ?? "Helvetica";
|
|
181
238
|
const descendants = asArray(dictGet(fontDict, "DescendantFonts"));
|
|
@@ -185,9 +242,22 @@ function buildCompositeFont(fontDict, context) {
|
|
|
185
242
|
const dw = descendantDict !== void 0 ? asNumber(dictGet(descendantDict, "DW")) ?? DEFAULT_CID_WIDTH : DEFAULT_CID_WIDTH;
|
|
186
243
|
const widthMap = readCidWidths(descendantDict !== void 0 ? asArray(dictGet(descendantDict, "W")) : void 0);
|
|
187
244
|
const widthOf = (cid) => widthMap.get(cid) ?? dw;
|
|
245
|
+
const dw2 = descendantDict !== void 0 ? asArray(dictGet(descendantDict, "DW2")) : void 0;
|
|
246
|
+
const defaultPositionY = (dw2?.length === DW2_ENTRY_COUNT ? asNumber(dw2[0]) : void 0) ?? DEFAULT_VERTICAL_POSITION_Y;
|
|
247
|
+
const defaultDisplacementY = (dw2?.length === DW2_ENTRY_COUNT ? asNumber(dw2[1]) : void 0) ?? DEFAULT_VERTICAL_DISPLACEMENT_Y;
|
|
248
|
+
const verticalMap = readCidVerticalMetrics(descendantDict !== void 0 ? asArray(dictGet(descendantDict, "W2")) : void 0);
|
|
249
|
+
const verticalMetricsOf = (cid) => {
|
|
250
|
+
const entry = verticalMap.get(cid);
|
|
251
|
+
return {
|
|
252
|
+
displacementY: entry?.displacementY ?? defaultDisplacementY,
|
|
253
|
+
positionX: entry?.positionX ?? widthOf(cid) / 2,
|
|
254
|
+
positionY: entry?.positionY ?? defaultPositionY
|
|
255
|
+
};
|
|
256
|
+
};
|
|
188
257
|
const toUnicode = readToUnicodeCMap(fontDict, context);
|
|
189
258
|
const cidToGidMap = descendantDict !== void 0 ? dictGet(descendantDict, "CIDToGIDMap") : void 0;
|
|
190
|
-
const
|
|
259
|
+
const encodingName = dictGet(fontDict, "Encoding");
|
|
260
|
+
const programEncoding = (isName(encodingName, "Identity-H") || isName(encodingName, "Identity-V")) && (cidToGidMap === void 0 || isName(cidToGidMap, "Identity")) ? lazyFontProgram(descriptor, context) : void 0;
|
|
191
261
|
const decodeToUnicode = (codes) => {
|
|
192
262
|
let out = "";
|
|
193
263
|
let glyphCount = 0;
|
|
@@ -221,7 +291,8 @@ function buildCompositeFont(fontDict, context) {
|
|
|
221
291
|
bold,
|
|
222
292
|
italic,
|
|
223
293
|
widthOf,
|
|
224
|
-
decodeToUnicode
|
|
294
|
+
decodeToUnicode,
|
|
295
|
+
...readsVertically(fontDict, context) ? { verticalMetricsOf } : {}
|
|
225
296
|
};
|
|
226
297
|
}
|
|
227
298
|
function createFontResolver(context) {
|
|
@@ -236,16 +307,27 @@ function createFontResolver(context) {
|
|
|
236
307
|
return resolved;
|
|
237
308
|
};
|
|
238
309
|
return {
|
|
239
|
-
metrics: {
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
310
|
+
metrics: {
|
|
311
|
+
glyphAdvance(fontResourceName, resources, codes, byteOffset) {
|
|
312
|
+
const font = resolve(fontResourceName, resources);
|
|
313
|
+
if (font === void 0) return;
|
|
314
|
+
const byteLengthConsumed = font.composite ? 2 : 1;
|
|
315
|
+
const code = font.composite ? (codes[byteOffset] ?? 0) << 8 | (codes[byteOffset + 1] ?? 0) : codes[byteOffset] ?? 0;
|
|
316
|
+
const vertical = font.verticalMetricsOf?.(code);
|
|
317
|
+
return {
|
|
318
|
+
widthPer1000: font.widthOf(code),
|
|
319
|
+
byteLengthConsumed,
|
|
320
|
+
...vertical === void 0 ? {} : { vertical: {
|
|
321
|
+
displacementPer1000: vertical.displacementY,
|
|
322
|
+
positionXPer1000: vertical.positionX,
|
|
323
|
+
positionYPer1000: vertical.positionY
|
|
324
|
+
} }
|
|
325
|
+
};
|
|
326
|
+
},
|
|
327
|
+
isVertical(fontResourceName, resources) {
|
|
328
|
+
return resolve(fontResourceName, resources)?.verticalMetricsOf !== void 0;
|
|
329
|
+
}
|
|
330
|
+
},
|
|
249
331
|
resolve
|
|
250
332
|
};
|
|
251
333
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -19,8 +19,12 @@ const require_measure = require("./measure.cjs");
|
|
|
19
19
|
const require_write = require("./write.cjs");
|
|
20
20
|
const require_codec = require("./codec.cjs");
|
|
21
21
|
const require_font_face = require("./font-face.cjs");
|
|
22
|
+
const require_text_group = require("./text-group.cjs");
|
|
22
23
|
const require_raster = require("./raster.cjs");
|
|
24
|
+
exports.DEFAULT_BASELINE_TOLERANCE_EM = require_text_group.DEFAULT_BASELINE_TOLERANCE_EM;
|
|
25
|
+
exports.DEFAULT_COLUMN_GAP_EM = require_text_group.DEFAULT_COLUMN_GAP_EM;
|
|
23
26
|
exports.DEFAULT_VERTICAL_METRIC_POLICY = require_measure.DEFAULT_VERTICAL_METRIC_POLICY;
|
|
27
|
+
exports.DEFAULT_WORD_GAP_EM = require_text_group.DEFAULT_WORD_GAP_EM;
|
|
24
28
|
exports.FontFaceParseError = require_font_face.FontFaceParseError;
|
|
25
29
|
exports.Jbig2ParseError = require_image_jbig2_errors.Jbig2ParseError;
|
|
26
30
|
exports.Jbig2UnsupportedError = require_image_jbig2_errors.Jbig2UnsupportedError;
|
|
@@ -66,6 +70,7 @@ exports.decodeCcittFax = require_image_ccitt.decodeCcittFax;
|
|
|
66
70
|
exports.decodeJbig2Embedded = require_image_jbig2.decodeJbig2Embedded;
|
|
67
71
|
exports.decodeJpeg2000 = require_image_jpeg2000.decodeJpeg2000;
|
|
68
72
|
exports.filterScanlines = require_image_png_filter.filterScanlines;
|
|
73
|
+
exports.groupPdfTextRuns = require_text_group.groupPdfTextRuns;
|
|
69
74
|
exports.loadMathFont = require_math_font.loadMathFont;
|
|
70
75
|
exports.looksLikeBareCodestream = require_image_jp2_boxes.looksLikeBareCodestream;
|
|
71
76
|
exports.parseJp2Container = require_image_jp2_boxes.parseJp2Container;
|
|
@@ -76,6 +81,8 @@ exports.readPdf = require_read.readPdf;
|
|
|
76
81
|
exports.renderPdfPage = require_raster.renderPdfPage;
|
|
77
82
|
exports.resolveFaceWithRegistry = require_font_registry.resolveFaceWithRegistry;
|
|
78
83
|
exports.resolveStandardFont = require_fonts.resolveStandardFont;
|
|
84
|
+
exports.runGapPt = require_text_group.runGapPt;
|
|
85
|
+
exports.runsShareBaseline = require_text_group.runsShareBaseline;
|
|
79
86
|
exports.scaleMathStretchConstruction = require_math_stretch.scaleMathStretchConstruction;
|
|
80
87
|
exports.unfilterScanlines = require_image_png_filter.unfilterScanlines;
|
|
81
88
|
exports.writePdf = require_write.writePdf;
|
package/dist/index.d.cts
CHANGED
|
@@ -23,7 +23,8 @@ import { a as MathGlyphPart, c as MathVariants, n as MathGlyphAssembly, o as Mat
|
|
|
23
23
|
import { a as scaleMathStretchConstruction, i as assembleStretchyGlyph, n as MathStretchOptions, r as MathStretchPlacement, t as MathStretchConstruction } from "./math-stretch-C2JanDAz.cjs";
|
|
24
24
|
import { LoadedMathFont, MathFont, MathFontDescriptorMetrics, loadMathFont } from "./math-font.cjs";
|
|
25
25
|
import { DEFAULT_VERTICAL_METRIC_POLICY, FontMeasurerOptions, StandardFontMeasurerOptions, VerticalMetricPolicy, createFontMeasurer, createStandardFontMeasurer } from "./measure.cjs";
|
|
26
|
+
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, groupPdfTextRuns, runGapPt, runsShareBaseline } from "./text-group.cjs";
|
|
26
27
|
import { PageRasteriser, RasterDrawOp, RasterFillRectOp, RasterFillSpec, RasterImageOp, RasterMatrix, RasterPageGeometry, RasterPathOp, RasterPathSegment, RasterRegionPt, RasterStrokeSpec, RasterSubpath, RenderPdfPageOptions, renderPdfPage } from "./raster.cjs";
|
|
27
28
|
import { FontRegistryOptions, FontSubstitution, MathAssembledGlyphs, MathBox, MathColor, MathFontMetrics, MathGlyphMetrics, MathGlyphPlacement, MathGlyphRun, MathLayoutItem, MathRule, MathStretchAxis, MathStretchGlyph, MathStretchResult, MathStroke, Point, PositionedFormula, ProvidedFont, StyledFragment, StyledRun, TextMeasurer, UnderlineMetrics, WrapOptions, WrappedLine } from "document-schema.js";
|
|
28
29
|
export * from "byte-codec";
|
|
29
|
-
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_VERTICAL_METRIC_POLICY, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, PdfParseError, PdfPasswordRequiredError, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, scaleMathStretchConstruction, unfilterScanlines, writePdf };
|
|
30
|
+
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, PdfParseError, PdfPasswordRequiredError, type PdfTextBox, type PdfTextGroupingOptions, type PdfTextLine, type PdfTextRunGeometry, type PdfTextWord, type PdfWordSeparator, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, unfilterScanlines, writePdf };
|
package/dist/index.d.ts
CHANGED
|
@@ -23,7 +23,8 @@ import { a as MathGlyphPart, c as MathVariants, n as MathGlyphAssembly, o as Mat
|
|
|
23
23
|
import { a as scaleMathStretchConstruction, i as assembleStretchyGlyph, n as MathStretchOptions, r as MathStretchPlacement, t as MathStretchConstruction } from "./math-stretch-BbC2o4Br.js";
|
|
24
24
|
import { LoadedMathFont, MathFont, MathFontDescriptorMetrics, loadMathFont } from "./math-font.js";
|
|
25
25
|
import { DEFAULT_VERTICAL_METRIC_POLICY, FontMeasurerOptions, StandardFontMeasurerOptions, VerticalMetricPolicy, createFontMeasurer, createStandardFontMeasurer } from "./measure.js";
|
|
26
|
+
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, groupPdfTextRuns, runGapPt, runsShareBaseline } from "./text-group.js";
|
|
26
27
|
import { PageRasteriser, RasterDrawOp, RasterFillRectOp, RasterFillSpec, RasterImageOp, RasterMatrix, RasterPageGeometry, RasterPathOp, RasterPathSegment, RasterRegionPt, RasterStrokeSpec, RasterSubpath, RenderPdfPageOptions, renderPdfPage } from "./raster.js";
|
|
27
28
|
import { FontRegistryOptions, FontSubstitution, MathAssembledGlyphs, MathBox, MathColor, MathFontMetrics, MathGlyphMetrics, MathGlyphPlacement, MathGlyphRun, MathLayoutItem, MathRule, MathStretchAxis, MathStretchGlyph, MathStretchResult, MathStroke, Point, PositionedFormula, ProvidedFont, StyledFragment, StyledRun, TextMeasurer, UnderlineMetrics, WrapOptions, WrappedLine } from "document-schema.js";
|
|
28
29
|
export * from "byte-codec";
|
|
29
|
-
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_VERTICAL_METRIC_POLICY, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, PdfParseError, PdfPasswordRequiredError, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, scaleMathStretchConstruction, unfilterScanlines, writePdf };
|
|
30
|
+
export { type CcittFaxImage, type CcittFaxOptions, DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, type EmbeddedFace, type EmbeddedFaceMetrics, type EmbeddedFaceSubstitution, type FontFace, FontFaceParseError, type FontMeasurerOptions, type FontMetrics, type FontRegistry, type FontRegistryOptions, type FontSubstitution, type GlyphInkBounds, type Jbig2DecodeOptions, type Jbig2Image, Jbig2ParseError, Jbig2UnsupportedError, type Jp2ChannelDefinition, type Jp2ColourSpace, type Jp2Container, type Jp2ImageHeader, type Jpeg2000ComponentMetadata, type Jpeg2000DecodeOptions, type Jpeg2000Image, type Jpeg2000Metadata, Jpeg2000ParseError, type Jpeg2000ProgressionOrder, type Jpeg2000QuantizationStyle, type Jpeg2000Transform, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotation, LayoutAnnotationQuad, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachment, LayoutAttachmentSchema, LayoutDestination, LayoutDestinationSchema, LayoutDestinationTarget, LayoutDestinationTargetSchema, LayoutDocument, LayoutDocumentSchema, LayoutEllipse, LayoutEllipseSchema, LayoutFormField, LayoutFormFieldSchema, LayoutFormWidget, LayoutFormWidgetSchema, LayoutImage, LayoutImageAsset, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLink, LayoutInternalLinkSchema, LayoutItem, LayoutItemSchema, LayoutLayer, LayoutLayerSchema, LayoutLine, LayoutLineSchema, LayoutLink, LayoutLinkSchema, LayoutOutlineItem, LayoutOutlineItemSchema, LayoutPage, LayoutPageSchema, LayoutPath, LayoutPathSchema, LayoutPathSegment, LayoutPathSegmentSchema, LayoutRect, LayoutRectSchema, LayoutStructureElement, LayoutStructureElementSchema, LayoutSubpath, LayoutSubpathSchema, LayoutText, LayoutTextSchema, type LoadedMathFont, type MathAssembledGlyphs, type MathBox, type MathColor, type MathFont, type MathFontDescriptorMetrics, type MathFontMetrics, type MathGlyphAssembly, type MathGlyphConstruction, type MathGlyphMetrics, type MathGlyphPart, type MathGlyphPlacement, type MathGlyphRun, type MathGlyphVariant, type MathLayoutItem, type MathRule, type MathStretchAxis, type MathStretchConstruction, type MathStretchGlyph, type MathStretchOptions, type MathStretchPlacement, type MathStretchResult, type MathStroke, type MathVariants, NOOP_DIAGNOSTIC_SINK, type PageRasteriser, PdfBytesSchema, type PdfDiagnostic, type PdfDiagnosticSeverity, type PdfDiagnosticSink, PdfEncryptedError, PdfEncryptionError, type PdfEncryptionOptions, type PdfEncryptionPermissions, type PdfEncryptionScheme, PdfParseError, PdfPasswordRequiredError, type PdfTextBox, type PdfTextGroupingOptions, type PdfTextLine, type PdfTextRunGeometry, type PdfTextWord, type PdfWordSeparator, type Point, type PositionedFormula, type ProvidedFont, type RasterDrawOp, type RasterFillRectOp, type RasterFillSpec, type RasterImageOp, type RasterMatrix, type RasterPageGeometry, type RasterPathOp, type RasterPathSegment, type RasterRegionPt, type RasterStrokeSpec, type RasterSubpath, type ReadPdfOptions, type RenderPdfPageOptions, type ResolvedFace, type ResolvedFont, STANDARD_METRICS, type StandardFontMeasurerOptions, type StandardFontName, type StyledFragment, type StyledRun, type TextMeasurer, type UnderlineMetrics, type VerticalMetricPolicy, type WinAnsiSubstitution, type WrapOptions, type WrappedLine, type WritePdfOptions, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, unfilterScanlines, writePdf };
|
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ import { DEFAULT_VERTICAL_METRIC_POLICY, createFontMeasurer, createStandardFontM
|
|
|
18
18
|
import { writePdf } from "./write.js";
|
|
19
19
|
import { PdfBytesSchema, pdfCodec } from "./codec.js";
|
|
20
20
|
import { FontFaceParseError, readFontFace } from "./font-face.js";
|
|
21
|
+
import { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, groupPdfTextRuns, runGapPt, runsShareBaseline } from "./text-group.js";
|
|
21
22
|
import { renderPdfPage } from "./raster.js";
|
|
22
23
|
export * from "byte-codec";
|
|
23
|
-
export { DEFAULT_VERTICAL_METRIC_POLICY, FontFaceParseError, Jbig2ParseError, Jbig2UnsupportedError, Jpeg2000ParseError, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachmentSchema, LayoutDestinationSchema, LayoutDestinationTargetSchema, LayoutDocumentSchema, LayoutEllipseSchema, LayoutFormFieldSchema, LayoutFormWidgetSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLinkSchema, LayoutItemSchema, LayoutLayerSchema, LayoutLineSchema, LayoutLinkSchema, LayoutOutlineItemSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutStructureElementSchema, LayoutSubpathSchema, LayoutTextSchema, NOOP_DIAGNOSTIC_SINK, PdfBytesSchema, PdfEncryptedError, PdfEncryptionError, PdfParseError, PdfPasswordRequiredError, STANDARD_METRICS, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, scaleMathStretchConstruction, unfilterScanlines, writePdf };
|
|
24
|
+
export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_VERTICAL_METRIC_POLICY, DEFAULT_WORD_GAP_EM, FontFaceParseError, Jbig2ParseError, Jbig2UnsupportedError, Jpeg2000ParseError, Jpeg2000UnsupportedError, LAYOUT_FORMAT_VERSION, LayoutAnnotationQuadSchema, LayoutAnnotationSchema, LayoutAttachmentSchema, LayoutDestinationSchema, LayoutDestinationTargetSchema, LayoutDocumentSchema, LayoutEllipseSchema, LayoutFormFieldSchema, LayoutFormWidgetSchema, LayoutImageAssetSchema, LayoutImageSchema, LayoutInternalLinkSchema, LayoutItemSchema, LayoutLayerSchema, LayoutLineSchema, LayoutLinkSchema, LayoutOutlineItemSchema, LayoutPageSchema, LayoutPathSchema, LayoutPathSegmentSchema, LayoutRectSchema, LayoutStructureElementSchema, LayoutSubpathSchema, LayoutTextSchema, NOOP_DIAGNOSTIC_SINK, PdfBytesSchema, PdfEncryptedError, PdfEncryptionError, PdfParseError, PdfPasswordRequiredError, STANDARD_METRICS, assembleStretchyGlyph, createFontMeasurer, createFontRegistry, createStandardFontMeasurer, decodeCcittFax, decodeJbig2Embedded, decodeJpeg2000, filterScanlines, groupPdfTextRuns, loadMathFont, looksLikeBareCodestream, parseJp2Container, pdfCodec, readFontFace, readJpeg2000Metadata, readPdf, renderPdfPage, resolveFaceWithRegistry, resolveStandardFont, runGapPt, runsShareBaseline, scaleMathStretchConstruction, unfilterScanlines, writePdf };
|
package/dist/interpret.cjs
CHANGED
|
@@ -433,24 +433,38 @@ function runContentStream(bytes, resources, initialState, context, items, depth,
|
|
|
433
433
|
const widthPer1000 = glyph?.widthPer1000 ?? FALLBACK_GLYPH_WIDTH_PER_1000;
|
|
434
434
|
const byteLength = glyph?.byteLengthConsumed ?? 1;
|
|
435
435
|
const isSingleByteSpace = byteLength === 1 && codes[offset] === 32;
|
|
436
|
-
const
|
|
437
|
-
|
|
436
|
+
const spacing = gs.charSpace + (isSingleByteSpace ? gs.wordSpace : 0);
|
|
437
|
+
const vertical = glyph?.vertical;
|
|
438
|
+
text.tm = vertical === void 0 ? require_matrix.multiplyMatrices(require_matrix.translationMatrix((widthPer1000 / 1e3 * gs.fontSizePt + spacing) * gs.horizScale, 0), text.tm) : require_matrix.multiplyMatrices(require_matrix.translationMatrix(0, vertical.displacementPer1000 / 1e3 * gs.fontSizePt + spacing), text.tm);
|
|
438
439
|
offset += byteLength;
|
|
439
440
|
}
|
|
440
441
|
};
|
|
442
|
+
const positionVectorOf = (codes) => {
|
|
443
|
+
const fontResourceName = gs.fontResourceName;
|
|
444
|
+
if (fontResourceName === void 0) return;
|
|
445
|
+
const vertical = context.fontMetrics.glyphAdvance(fontResourceName, resources, codes, 0)?.vertical;
|
|
446
|
+
if (vertical === void 0) return;
|
|
447
|
+
return {
|
|
448
|
+
x: vertical.positionXPer1000 / 1e3,
|
|
449
|
+
y: vertical.positionYPer1000 / 1e3
|
|
450
|
+
};
|
|
451
|
+
};
|
|
441
452
|
const showTextArray = (elements) => {
|
|
442
453
|
const fontResourceName = gs.fontResourceName;
|
|
443
454
|
if (fontResourceName === void 0) return;
|
|
455
|
+
const vertical = context.fontMetrics.isVertical(fontResourceName, resources);
|
|
444
456
|
const startMatrix = computeTrm(gs, text);
|
|
445
457
|
const chunks = [];
|
|
446
458
|
let totalLength = 0;
|
|
459
|
+
let firstGlyphPosition;
|
|
447
460
|
for (const el of elements) if (el.kind === "string") {
|
|
461
|
+
firstGlyphPosition ??= vertical ? positionVectorOf(el.bytes) : void 0;
|
|
448
462
|
chunks.push(el.bytes);
|
|
449
463
|
totalLength += el.bytes.length;
|
|
450
464
|
advanceThroughString(el.bytes);
|
|
451
465
|
} else if (el.kind === "number") {
|
|
452
|
-
const adjustment = -(el.value / 1e3) * gs.fontSizePt
|
|
453
|
-
text.tm = require_matrix.multiplyMatrices(require_matrix.translationMatrix(adjustment, 0), text.tm);
|
|
466
|
+
const adjustment = -(el.value / 1e3) * gs.fontSizePt;
|
|
467
|
+
text.tm = require_matrix.multiplyMatrices(vertical ? require_matrix.translationMatrix(0, adjustment) : require_matrix.translationMatrix(adjustment * gs.horizScale, 0), text.tm);
|
|
454
468
|
}
|
|
455
469
|
if (totalLength === 0) return;
|
|
456
470
|
const combined = new Uint8Array(totalLength);
|
|
@@ -460,15 +474,17 @@ function runContentStream(bytes, resources, initialState, context, items, depth,
|
|
|
460
474
|
at += chunk.length;
|
|
461
475
|
}
|
|
462
476
|
const endMatrix = computeTrm(gs, text);
|
|
477
|
+
const shift = firstGlyphPosition === void 0 ? void 0 : require_matrix.translationMatrix(-firstGlyphPosition.x, -firstGlyphPosition.y);
|
|
463
478
|
pushItem({
|
|
464
479
|
kind: "text",
|
|
465
480
|
codes: combined,
|
|
466
481
|
fontResourceName,
|
|
467
482
|
resources,
|
|
468
|
-
startMatrix,
|
|
469
|
-
endMatrix,
|
|
483
|
+
startMatrix: shift === void 0 ? startMatrix : require_matrix.multiplyMatrices(shift, startMatrix),
|
|
484
|
+
endMatrix: shift === void 0 ? endMatrix : require_matrix.multiplyMatrices(shift, endMatrix),
|
|
470
485
|
sizePt: gs.fontSizePt,
|
|
471
|
-
color: gs.fillColor
|
|
486
|
+
color: gs.fillColor,
|
|
487
|
+
...vertical ? { vertical: true } : {}
|
|
472
488
|
});
|
|
473
489
|
};
|
|
474
490
|
const showText = (bytes) => {
|
package/dist/interpret.d.cts
CHANGED
|
@@ -16,6 +16,7 @@ interface ExtractedTextRun {
|
|
|
16
16
|
readonly actualText?: string;
|
|
17
17
|
readonly alt?: string;
|
|
18
18
|
readonly mcid?: number;
|
|
19
|
+
readonly vertical?: boolean;
|
|
19
20
|
}
|
|
20
21
|
interface ExtractedPaint {
|
|
21
22
|
readonly fill: Color | undefined;
|
|
@@ -94,12 +95,19 @@ interface ExtractedInlineImage {
|
|
|
94
95
|
readonly mcid?: number;
|
|
95
96
|
}
|
|
96
97
|
type ExtractedItem = ExtractedTextRun | ExtractedRect | ExtractedEllipse | ExtractedLine | ExtractedPath | ExtractedImage | ExtractedInlineImage;
|
|
98
|
+
interface VerticalGlyphAdvance {
|
|
99
|
+
readonly displacementPer1000: number;
|
|
100
|
+
readonly positionXPer1000: number;
|
|
101
|
+
readonly positionYPer1000: number;
|
|
102
|
+
}
|
|
97
103
|
interface GlyphAdvance {
|
|
98
104
|
readonly widthPer1000: number;
|
|
99
105
|
readonly byteLengthConsumed: number;
|
|
106
|
+
readonly vertical?: VerticalGlyphAdvance;
|
|
100
107
|
}
|
|
101
108
|
interface FontMetricsPort {
|
|
102
109
|
glyphAdvance(fontResourceName: string, resources: PdfDict, codes: Uint8Array<ArrayBuffer>, byteOffset: number): GlyphAdvance | undefined;
|
|
110
|
+
isVertical(fontResourceName: string, resources: PdfDict): boolean;
|
|
103
111
|
}
|
|
104
112
|
interface PdfObjectResolver {
|
|
105
113
|
resolve(obj: PdfObject | undefined): PdfObject | undefined;
|
|
@@ -113,4 +121,4 @@ interface InterpretContext {
|
|
|
113
121
|
}
|
|
114
122
|
declare function interpretContentStream(bytes: Uint8Array<ArrayBuffer>, resources: PdfDict, context: InterpretContext): ExtractedItem[];
|
|
115
123
|
//#endregion
|
|
116
|
-
export { ExtractedEllipse, ExtractedImage, ExtractedInlineImage, ExtractedItem, ExtractedLine, ExtractedPaint, ExtractedPath, ExtractedPathSegment, ExtractedRect, ExtractedSubpath, ExtractedTextRun, FontMetricsPort, GlyphAdvance, InterpretContext, PdfObjectResolver, interpretContentStream };
|
|
124
|
+
export { ExtractedEllipse, ExtractedImage, ExtractedInlineImage, ExtractedItem, ExtractedLine, ExtractedPaint, ExtractedPath, ExtractedPathSegment, ExtractedRect, ExtractedSubpath, ExtractedTextRun, FontMetricsPort, GlyphAdvance, InterpretContext, PdfObjectResolver, VerticalGlyphAdvance, interpretContentStream };
|
package/dist/interpret.d.ts
CHANGED
|
@@ -16,6 +16,7 @@ interface ExtractedTextRun {
|
|
|
16
16
|
readonly actualText?: string;
|
|
17
17
|
readonly alt?: string;
|
|
18
18
|
readonly mcid?: number;
|
|
19
|
+
readonly vertical?: boolean;
|
|
19
20
|
}
|
|
20
21
|
interface ExtractedPaint {
|
|
21
22
|
readonly fill: Color | undefined;
|
|
@@ -94,12 +95,19 @@ interface ExtractedInlineImage {
|
|
|
94
95
|
readonly mcid?: number;
|
|
95
96
|
}
|
|
96
97
|
type ExtractedItem = ExtractedTextRun | ExtractedRect | ExtractedEllipse | ExtractedLine | ExtractedPath | ExtractedImage | ExtractedInlineImage;
|
|
98
|
+
interface VerticalGlyphAdvance {
|
|
99
|
+
readonly displacementPer1000: number;
|
|
100
|
+
readonly positionXPer1000: number;
|
|
101
|
+
readonly positionYPer1000: number;
|
|
102
|
+
}
|
|
97
103
|
interface GlyphAdvance {
|
|
98
104
|
readonly widthPer1000: number;
|
|
99
105
|
readonly byteLengthConsumed: number;
|
|
106
|
+
readonly vertical?: VerticalGlyphAdvance;
|
|
100
107
|
}
|
|
101
108
|
interface FontMetricsPort {
|
|
102
109
|
glyphAdvance(fontResourceName: string, resources: PdfDict, codes: Uint8Array<ArrayBuffer>, byteOffset: number): GlyphAdvance | undefined;
|
|
110
|
+
isVertical(fontResourceName: string, resources: PdfDict): boolean;
|
|
103
111
|
}
|
|
104
112
|
interface PdfObjectResolver {
|
|
105
113
|
resolve(obj: PdfObject | undefined): PdfObject | undefined;
|
|
@@ -113,4 +121,4 @@ interface InterpretContext {
|
|
|
113
121
|
}
|
|
114
122
|
declare function interpretContentStream(bytes: Uint8Array<ArrayBuffer>, resources: PdfDict, context: InterpretContext): ExtractedItem[];
|
|
115
123
|
//#endregion
|
|
116
|
-
export { ExtractedEllipse, ExtractedImage, ExtractedInlineImage, ExtractedItem, ExtractedLine, ExtractedPaint, ExtractedPath, ExtractedPathSegment, ExtractedRect, ExtractedSubpath, ExtractedTextRun, FontMetricsPort, GlyphAdvance, InterpretContext, PdfObjectResolver, interpretContentStream };
|
|
124
|
+
export { ExtractedEllipse, ExtractedImage, ExtractedInlineImage, ExtractedItem, ExtractedLine, ExtractedPaint, ExtractedPath, ExtractedPathSegment, ExtractedRect, ExtractedSubpath, ExtractedTextRun, FontMetricsPort, GlyphAdvance, InterpretContext, PdfObjectResolver, VerticalGlyphAdvance, interpretContentStream };
|