pdf-codec 5.7.3 → 5.8.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.
Files changed (58) hide show
  1. package/README.md +6 -3
  2. package/dist/afm-widths.cjs +247 -4
  3. package/dist/afm-widths.js +244 -1
  4. package/dist/builtin-encoding.cjs +75 -16
  5. package/dist/builtin-encoding.d.cts +10 -3
  6. package/dist/builtin-encoding.d.ts +10 -3
  7. package/dist/builtin-encoding.js +74 -15
  8. package/dist/content-write.cjs +2 -2
  9. package/dist/content-write.js +1 -1
  10. package/dist/core-font-glyph-orders.cjs +62 -0
  11. package/dist/core-font-glyph-orders.d.cts +10 -0
  12. package/dist/core-font-glyph-orders.d.ts +10 -0
  13. package/dist/core-font-glyph-orders.js +61 -0
  14. package/dist/encoding.cjs +273 -5
  15. package/dist/encoding.d.cts +1 -2
  16. package/dist/encoding.d.ts +1 -2
  17. package/dist/encoding.js +271 -2
  18. package/dist/font-read.cjs +52 -18
  19. package/dist/font-read.js +49 -15
  20. package/dist/font-style.cjs +12 -1
  21. package/dist/font-style.d.cts +9 -1
  22. package/dist/font-style.d.ts +9 -1
  23. package/dist/font-style.js +12 -2
  24. package/dist/glyph-data/adobe-glyph-list.cjs +7 -0
  25. package/dist/glyph-data/adobe-glyph-list.d.cts +5 -0
  26. package/dist/glyph-data/adobe-glyph-list.d.ts +5 -0
  27. package/dist/glyph-data/adobe-glyph-list.js +5 -0
  28. package/dist/glyph-data/core-font-glyph-orders.cjs +5 -0
  29. package/dist/glyph-data/core-font-glyph-orders.d.cts +4 -0
  30. package/dist/glyph-data/core-font-glyph-orders.d.ts +4 -0
  31. package/dist/glyph-data/core-font-glyph-orders.js +4 -0
  32. package/dist/glyph-names.cjs +63 -0
  33. package/dist/glyph-names.d.cts +9 -0
  34. package/dist/glyph-names.d.ts +9 -0
  35. package/dist/glyph-names.js +62 -0
  36. package/dist/index.cjs +3 -1
  37. package/dist/index.d.cts +2 -2
  38. package/dist/index.d.ts +2 -2
  39. package/dist/index.js +3 -3
  40. package/dist/measure.cjs +3 -2
  41. package/dist/measure.js +2 -1
  42. package/dist/text-group.cjs +19 -2
  43. package/dist/text-group.d.cts +13 -1
  44. package/dist/text-group.d.ts +13 -1
  45. package/dist/text-group.js +18 -3
  46. package/dist/winansi.cjs +162 -4
  47. package/dist/winansi.d.cts +1 -2
  48. package/dist/winansi.d.ts +1 -2
  49. package/dist/winansi.js +161 -2
  50. package/dist/write.cjs +1 -1
  51. package/dist/write.js +1 -1
  52. package/package.json +1 -1
  53. package/dist/afm-widths-BNI8qa2S.js +0 -710
  54. package/dist/afm-widths-sjaRvmQX.cjs +0 -769
  55. package/dist/encoding-glyph-unicode.cjs +0 -353
  56. package/dist/encoding-glyph-unicode.d.cts +0 -4
  57. package/dist/encoding-glyph-unicode.d.ts +0 -4
  58. package/dist/encoding-glyph-unicode.js +0 -352
@@ -37,6 +37,12 @@ interface PdfTextGroupingOptions {
37
37
  declare const DEFAULT_BASELINE_TOLERANCE_EM: number;
38
38
  declare const DEFAULT_WORD_GAP_EM: number;
39
39
  declare const DEFAULT_COLUMN_GAP_EM = 1;
40
+ /**
41
+ * An anticlockwise rotation as one canonical number: normalised into [0, 360) and rounded to remove the last-bit noise atan2 leaves, so two runs set at one angle report the identical value and a comparison against a quarter turn is exact.
42
+ * @param rotationDeg - a rotation in degrees, anticlockwise from the page's x-axis; absent means zero
43
+ * @returns the same angle in [0, 360)
44
+ */
45
+ declare function normalisedRotationDeg(rotationDeg: number | undefined): number;
40
46
  /**
41
47
  * Whether two positioned runs sit on one visual line.
42
48
  *
@@ -47,6 +53,12 @@ declare const DEFAULT_COLUMN_GAP_EM = 1;
47
53
  * @returns true when the two baselines are within tolerance of each other
48
54
  */
49
55
  declare function runsShareBaseline(a: PdfTextRunGeometry, b: PdfTextRunGeometry, options?: PdfTextGroupingOptions): boolean;
56
+ /**
57
+ * Where a run starts along the direction it advances in: the coordinate that puts the runs of one line in reading order, at whatever angle the line is set. For an upright run it is the run's `xPt`; for a run turned a quarter turn anticlockwise, read upward, it is its `yPt`.
58
+ * @param run - a positioned run
59
+ * @returns the run's origin projected onto its own baseline, in points
60
+ */
61
+ declare function runAlongBaselinePt(run: PdfTextRunGeometry): number;
50
62
  /**
51
63
  * The horizontal gap along the baseline between the end of `previous` and the start of `next`, or undefined when the geometry does not state one.
52
64
  *
@@ -95,4 +107,4 @@ declare function attachScriptRuns<TLine, TRun extends PdfTextRunGeometry>(lines:
95
107
  */
96
108
  declare function groupPdfTextRuns<TRun extends PdfTextRunGeometry>(runs: readonly TRun[], options?: PdfTextGroupingOptions): PdfTextLine<TRun>[];
97
109
  //#endregion
98
- export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfLineWithScripts, PdfScriptPosition, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf };
110
+ export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, PdfLineWithScripts, PdfScriptPosition, PdfTextBox, PdfTextGroupingOptions, PdfTextLine, PdfTextRunGeometry, PdfTextWord, PdfWordSeparator, attachScriptRuns, groupPdfTextRuns, normalisedRotationDeg, runAlongBaselinePt, runGapPt, runsShareBaseline, scriptPositionOf };
@@ -4,9 +4,16 @@ const DEFAULT_COLUMN_GAP_EM = 1;
4
4
  const ROTATION_NOISE_DEG = 1e-6;
5
5
  const DEGREES_PER_TURN = 360;
6
6
  const VERTICAL_ADVANCE_OFFSET_DEG = -90;
7
+ /**
8
+ * An anticlockwise rotation as one canonical number: normalised into [0, 360) and rounded to remove the last-bit noise atan2 leaves, so two runs set at one angle report the identical value and a comparison against a quarter turn is exact.
9
+ * @param rotationDeg - a rotation in degrees, anticlockwise from the page's x-axis; absent means zero
10
+ * @returns the same angle in [0, 360)
11
+ */
12
+ function normalisedRotationDeg(rotationDeg) {
13
+ return (Math.round((rotationDeg ?? 0) / ROTATION_NOISE_DEG) * ROTATION_NOISE_DEG % DEGREES_PER_TURN + DEGREES_PER_TURN) % DEGREES_PER_TURN;
14
+ }
7
15
  function advanceAngleDeg(run) {
8
- const raw = (run.rotationDeg ?? 0) + (run.writingMode === "vertical" ? VERTICAL_ADVANCE_OFFSET_DEG : 0);
9
- return (Math.round(raw / ROTATION_NOISE_DEG) * ROTATION_NOISE_DEG % DEGREES_PER_TURN + DEGREES_PER_TURN) % DEGREES_PER_TURN;
16
+ return normalisedRotationDeg((run.rotationDeg ?? 0) + (run.writingMode === "vertical" ? VERTICAL_ADVANCE_OFFSET_DEG : 0));
10
17
  }
11
18
  const RADIANS_PER_TURN = 2 * Math.PI;
12
19
  function baselineAxis(rotationDeg) {
@@ -48,6 +55,14 @@ function runsShareBaseline(a, b, options = {}) {
48
55
  return Math.abs(project(a, rotationDeg).acrossPt - project(b, rotationDeg).acrossPt) <= toleranceEm * Math.min(a.sizePt, b.sizePt);
49
56
  }
50
57
  /**
58
+ * Where a run starts along the direction it advances in: the coordinate that puts the runs of one line in reading order, at whatever angle the line is set. For an upright run it is the run's `xPt`; for a run turned a quarter turn anticlockwise, read upward, it is its `yPt`.
59
+ * @param run - a positioned run
60
+ * @returns the run's origin projected onto its own baseline, in points
61
+ */
62
+ function runAlongBaselinePt(run) {
63
+ return project(run, advanceAngleDeg(run)).alongPt;
64
+ }
65
+ /**
51
66
  * The horizontal gap along the baseline between the end of `previous` and the start of `next`, or undefined when the geometry does not state one.
52
67
  *
53
68
  * Undefined has exactly two causes, and a caller must treat both as "no evidence of a space" rather than substituting zero: `previous` stated no advance width, so where it ends is unknown; or the two runs are set at different angles, so they share no axis to measure along. A negative result is real and means the two runs overlap.
@@ -292,4 +307,4 @@ function groupPdfTextRuns(runs, options = {}) {
292
307
  return result;
293
308
  }
294
309
  //#endregion
295
- export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, attachScriptRuns, groupPdfTextRuns, runGapPt, runsShareBaseline, scriptPositionOf };
310
+ export { DEFAULT_BASELINE_TOLERANCE_EM, DEFAULT_COLUMN_GAP_EM, DEFAULT_WORD_GAP_EM, attachScriptRuns, groupPdfTextRuns, normalisedRotationDeg, runAlongBaselinePt, runGapPt, runsShareBaseline, scriptPositionOf };
package/dist/winansi.cjs CHANGED
@@ -1,5 +1,163 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_afm_widths = require("./afm-widths-sjaRvmQX.cjs");
3
- exports.encodeForShow = require_afm_widths.encodeForShow;
4
- exports.sanitizeToWinAnsi = require_afm_widths.sanitizeToWinAnsi;
5
- exports.winAnsiCodeToUnicode = require_afm_widths.winAnsiCodeToUnicode;
2
+ const require_afm_widths = require("./afm-widths.cjs");
3
+ //#region src/winansi.ts
4
+ const ASCII_PRINTABLE_START = 32;
5
+ const ASCII_PRINTABLE_END = 127;
6
+ const LATIN1_SUPPLEMENT_START = 160;
7
+ const LATIN1_SUPPLEMENT_END = 255;
8
+ function identityRangeEntries(start, end) {
9
+ const entries = [];
10
+ for (let code = start; code <= end; code++) entries.push([code, code]);
11
+ return entries;
12
+ }
13
+ const CP1252_EXTENDED_MAPPINGS = [
14
+ {
15
+ unicode: 338,
16
+ winAnsi: 140
17
+ },
18
+ {
19
+ unicode: 339,
20
+ winAnsi: 156
21
+ },
22
+ {
23
+ unicode: 352,
24
+ winAnsi: 138
25
+ },
26
+ {
27
+ unicode: 353,
28
+ winAnsi: 154
29
+ },
30
+ {
31
+ unicode: 376,
32
+ winAnsi: 159
33
+ },
34
+ {
35
+ unicode: 381,
36
+ winAnsi: 142
37
+ },
38
+ {
39
+ unicode: 382,
40
+ winAnsi: 158
41
+ },
42
+ {
43
+ unicode: 402,
44
+ winAnsi: 131
45
+ },
46
+ {
47
+ unicode: 710,
48
+ winAnsi: 136
49
+ },
50
+ {
51
+ unicode: 732,
52
+ winAnsi: 152
53
+ },
54
+ {
55
+ unicode: 8211,
56
+ winAnsi: 150
57
+ },
58
+ {
59
+ unicode: 8212,
60
+ winAnsi: 151
61
+ },
62
+ {
63
+ unicode: 8216,
64
+ winAnsi: 145
65
+ },
66
+ {
67
+ unicode: 8217,
68
+ winAnsi: 146
69
+ },
70
+ {
71
+ unicode: 8218,
72
+ winAnsi: 130
73
+ },
74
+ {
75
+ unicode: 8220,
76
+ winAnsi: 147
77
+ },
78
+ {
79
+ unicode: 8221,
80
+ winAnsi: 148
81
+ },
82
+ {
83
+ unicode: 8222,
84
+ winAnsi: 132
85
+ },
86
+ {
87
+ unicode: 8224,
88
+ winAnsi: 134
89
+ },
90
+ {
91
+ unicode: 8225,
92
+ winAnsi: 135
93
+ },
94
+ {
95
+ unicode: 8226,
96
+ winAnsi: 149
97
+ },
98
+ {
99
+ unicode: 8230,
100
+ winAnsi: 133
101
+ },
102
+ {
103
+ unicode: 8240,
104
+ winAnsi: 137
105
+ },
106
+ {
107
+ unicode: 8249,
108
+ winAnsi: 139
109
+ },
110
+ {
111
+ unicode: 8250,
112
+ winAnsi: 155
113
+ },
114
+ {
115
+ unicode: 8364,
116
+ winAnsi: 128
117
+ },
118
+ {
119
+ unicode: 8482,
120
+ winAnsi: 153
121
+ }
122
+ ];
123
+ const UNICODE_TO_WINANSI = new Map([
124
+ ...identityRangeEntries(ASCII_PRINTABLE_START, ASCII_PRINTABLE_END),
125
+ ...identityRangeEntries(LATIN1_SUPPLEMENT_START, LATIN1_SUPPLEMENT_END),
126
+ ...CP1252_EXTENDED_MAPPINGS.map((entry) => [entry.unicode, entry.winAnsi])
127
+ ]);
128
+ const FALLBACK_BYTE = 63;
129
+ const FALLBACK_CHAR = "?";
130
+ function sanitizeToWinAnsi(text) {
131
+ const codes = [];
132
+ const substitutions = [];
133
+ for (const ch of text) {
134
+ const codePoint = ch.codePointAt(0);
135
+ const code = codePoint === void 0 ? void 0 : UNICODE_TO_WINANSI.get(codePoint);
136
+ if (code !== void 0) {
137
+ codes.push(code);
138
+ continue;
139
+ }
140
+ codes.push(FALLBACK_BYTE);
141
+ substitutions.push({
142
+ from: ch,
143
+ to: FALLBACK_CHAR
144
+ });
145
+ }
146
+ return {
147
+ codes: new Uint8Array(codes),
148
+ substitutions
149
+ };
150
+ }
151
+ function encodeForShow(text, font) {
152
+ const { codes, substitutions } = sanitizeToWinAnsi(text);
153
+ let width1000 = 0;
154
+ for (const code of codes) width1000 += require_afm_widths.widthOfCode(font, code);
155
+ return {
156
+ codes,
157
+ width1000,
158
+ substitutions
159
+ };
160
+ }
161
+ //#endregion
162
+ exports.encodeForShow = encodeForShow;
163
+ exports.sanitizeToWinAnsi = sanitizeToWinAnsi;
@@ -1,6 +1,5 @@
1
1
  import { r as StandardFontName } from "./afm-widths-D0Lu9kLv.cjs";
2
2
  //#region src/winansi.d.ts
3
- declare function winAnsiCodeToUnicode(code: number): number | undefined;
4
3
  interface WinAnsiSubstitution {
5
4
  readonly from: string;
6
5
  readonly to: string;
@@ -17,4 +16,4 @@ interface EncodedShow {
17
16
  }
18
17
  declare function encodeForShow(text: string, font: StandardFontName): EncodedShow;
19
18
  //#endregion
20
- export { EncodedShow, SanitizeResult, WinAnsiSubstitution, encodeForShow, sanitizeToWinAnsi, winAnsiCodeToUnicode };
19
+ export { EncodedShow, SanitizeResult, WinAnsiSubstitution, encodeForShow, sanitizeToWinAnsi };
package/dist/winansi.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { r as StandardFontName } from "./afm-widths-D0Lu9kLv.js";
2
2
  //#region src/winansi.d.ts
3
- declare function winAnsiCodeToUnicode(code: number): number | undefined;
4
3
  interface WinAnsiSubstitution {
5
4
  readonly from: string;
6
5
  readonly to: string;
@@ -17,4 +16,4 @@ interface EncodedShow {
17
16
  }
18
17
  declare function encodeForShow(text: string, font: StandardFontName): EncodedShow;
19
18
  //#endregion
20
- export { EncodedShow, SanitizeResult, WinAnsiSubstitution, encodeForShow, sanitizeToWinAnsi, winAnsiCodeToUnicode };
19
+ export { EncodedShow, SanitizeResult, WinAnsiSubstitution, encodeForShow, sanitizeToWinAnsi };
package/dist/winansi.js CHANGED
@@ -1,2 +1,161 @@
1
- import { c as encodeForShow, l as sanitizeToWinAnsi, u as winAnsiCodeToUnicode } from "./afm-widths-BNI8qa2S.js";
2
- export { encodeForShow, sanitizeToWinAnsi, winAnsiCodeToUnicode };
1
+ import { widthOfCode } from "./afm-widths.js";
2
+ //#region src/winansi.ts
3
+ const ASCII_PRINTABLE_START = 32;
4
+ const ASCII_PRINTABLE_END = 127;
5
+ const LATIN1_SUPPLEMENT_START = 160;
6
+ const LATIN1_SUPPLEMENT_END = 255;
7
+ function identityRangeEntries(start, end) {
8
+ const entries = [];
9
+ for (let code = start; code <= end; code++) entries.push([code, code]);
10
+ return entries;
11
+ }
12
+ const CP1252_EXTENDED_MAPPINGS = [
13
+ {
14
+ unicode: 338,
15
+ winAnsi: 140
16
+ },
17
+ {
18
+ unicode: 339,
19
+ winAnsi: 156
20
+ },
21
+ {
22
+ unicode: 352,
23
+ winAnsi: 138
24
+ },
25
+ {
26
+ unicode: 353,
27
+ winAnsi: 154
28
+ },
29
+ {
30
+ unicode: 376,
31
+ winAnsi: 159
32
+ },
33
+ {
34
+ unicode: 381,
35
+ winAnsi: 142
36
+ },
37
+ {
38
+ unicode: 382,
39
+ winAnsi: 158
40
+ },
41
+ {
42
+ unicode: 402,
43
+ winAnsi: 131
44
+ },
45
+ {
46
+ unicode: 710,
47
+ winAnsi: 136
48
+ },
49
+ {
50
+ unicode: 732,
51
+ winAnsi: 152
52
+ },
53
+ {
54
+ unicode: 8211,
55
+ winAnsi: 150
56
+ },
57
+ {
58
+ unicode: 8212,
59
+ winAnsi: 151
60
+ },
61
+ {
62
+ unicode: 8216,
63
+ winAnsi: 145
64
+ },
65
+ {
66
+ unicode: 8217,
67
+ winAnsi: 146
68
+ },
69
+ {
70
+ unicode: 8218,
71
+ winAnsi: 130
72
+ },
73
+ {
74
+ unicode: 8220,
75
+ winAnsi: 147
76
+ },
77
+ {
78
+ unicode: 8221,
79
+ winAnsi: 148
80
+ },
81
+ {
82
+ unicode: 8222,
83
+ winAnsi: 132
84
+ },
85
+ {
86
+ unicode: 8224,
87
+ winAnsi: 134
88
+ },
89
+ {
90
+ unicode: 8225,
91
+ winAnsi: 135
92
+ },
93
+ {
94
+ unicode: 8226,
95
+ winAnsi: 149
96
+ },
97
+ {
98
+ unicode: 8230,
99
+ winAnsi: 133
100
+ },
101
+ {
102
+ unicode: 8240,
103
+ winAnsi: 137
104
+ },
105
+ {
106
+ unicode: 8249,
107
+ winAnsi: 139
108
+ },
109
+ {
110
+ unicode: 8250,
111
+ winAnsi: 155
112
+ },
113
+ {
114
+ unicode: 8364,
115
+ winAnsi: 128
116
+ },
117
+ {
118
+ unicode: 8482,
119
+ winAnsi: 153
120
+ }
121
+ ];
122
+ const UNICODE_TO_WINANSI = new Map([
123
+ ...identityRangeEntries(ASCII_PRINTABLE_START, ASCII_PRINTABLE_END),
124
+ ...identityRangeEntries(LATIN1_SUPPLEMENT_START, LATIN1_SUPPLEMENT_END),
125
+ ...CP1252_EXTENDED_MAPPINGS.map((entry) => [entry.unicode, entry.winAnsi])
126
+ ]);
127
+ const FALLBACK_BYTE = 63;
128
+ const FALLBACK_CHAR = "?";
129
+ function sanitizeToWinAnsi(text) {
130
+ const codes = [];
131
+ const substitutions = [];
132
+ for (const ch of text) {
133
+ const codePoint = ch.codePointAt(0);
134
+ const code = codePoint === void 0 ? void 0 : UNICODE_TO_WINANSI.get(codePoint);
135
+ if (code !== void 0) {
136
+ codes.push(code);
137
+ continue;
138
+ }
139
+ codes.push(FALLBACK_BYTE);
140
+ substitutions.push({
141
+ from: ch,
142
+ to: FALLBACK_CHAR
143
+ });
144
+ }
145
+ return {
146
+ codes: new Uint8Array(codes),
147
+ substitutions
148
+ };
149
+ }
150
+ function encodeForShow(text, font) {
151
+ const { codes, substitutions } = sanitizeToWinAnsi(text);
152
+ let width1000 = 0;
153
+ for (const code of codes) width1000 += widthOfCode(font, code);
154
+ return {
155
+ codes,
156
+ width1000,
157
+ substitutions
158
+ };
159
+ }
160
+ //#endregion
161
+ export { encodeForShow, sanitizeToWinAnsi };
package/dist/write.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_afm_widths = require("./afm-widths-sjaRvmQX.cjs");
2
+ const require_afm_widths = require("./afm-widths.cjs");
3
3
  const require_objects = require("./objects.cjs");
4
4
  const require_bytes_writer = require("./bytes/writer.cjs");
5
5
  const require_serialize = require("./serialize.cjs");
package/dist/write.js CHANGED
@@ -1,4 +1,4 @@
1
- import { r as widthOfCode, t as STANDARD_METRICS } from "./afm-widths-BNI8qa2S.js";
1
+ import { STANDARD_METRICS, widthOfCode } from "./afm-widths.js";
2
2
  import { pdfArray, pdfDict, pdfHexString, pdfLiteralString, pdfName, pdfNull, pdfNum, pdfRef, pdfStream } from "./objects.js";
3
3
  import { ByteWriter } from "./bytes/writer.js";
4
4
  import { writeObject } from "./serialize.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pdf-codec",
3
- "version": "5.7.3",
3
+ "version": "5.8.0",
4
4
  "description": "Hand-written, dependency-minimal PDF codec: parses arbitrary real-world PDFs and generates new ones, built on its own codec-owned LayoutDocument item model and Zod 4 codecs.",
5
5
  "type": "module",
6
6
  "repository": {