@pptx-studio/cli 0.1.0 → 0.3.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/CHANGELOG.md +149 -0
- package/README.md +95 -11
- package/dist/cli.js +1 -1
- package/dist/index.d.ts +56 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/{main-DLx2onii.js → main-3sNR_Xlp.js} +262 -99
- package/dist/main-3sNR_Xlp.js.map +1 -0
- package/package.json +9 -9
- package/dist/main-DLx2onii.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,154 @@
|
|
|
1
1
|
# @pptx-studio/cli
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3622457: `render` on macOS lays text out on the box CoreText reads: `hhea` whatever `fsSelection` bit 7 says, rounded half up from the em ratio held as 16.16 fixed point, measured 248/248 on `macos-latest`. `FontBackend` gains `coretext` and `FaceMetrics` says which backend it was read for.
|
|
8
|
+
- 55f3073: `pptx-studio render` writes the face it measured a run in into the markup, and reads the face box
|
|
9
|
+
the way the browser reports it.
|
|
10
|
+
|
|
11
|
+
The SVG said `font-family="Calibri Light"` and nothing else, so a viewer picked its own face while
|
|
12
|
+
the line breaks and origins had been computed for whatever stood in — the one place the two
|
|
13
|
+
renderers could still disagree about what was drawn, open since ADR 0044. Every run now carries a
|
|
14
|
+
list: the face this machine drew it in, then the face the deck asked for, then the substitution
|
|
15
|
+
table's entry, then Calibri and Carlito, then `sans-serif`. `Calibri Light` drawn in Carlito reads
|
|
16
|
+
`"Carlito", "Calibri Light", "Calibri", sans-serif`; a face the machine has leads its own list.
|
|
17
|
+
|
|
18
|
+
`FontMeasurer` gains `cssFamilyFor`, answered from the resolved-face cache the measurer already
|
|
19
|
+
filled, so it cannot name a face other than the one that measured. A face whose name cannot be
|
|
20
|
+
written into a CSS shorthand is no longer claimed by the index, as a blank name already was not.
|
|
21
|
+
|
|
22
|
+
The face box is rounded half up to a whole pixel at the size the browser reads it, and the
|
|
23
|
+
ideographic baseline of a face with no `BASE` table is that rounded descent: T13 on a 2048 and a
|
|
24
|
+
2000 em, 28 of 28 and 36 of 36, where the exact fraction scores 25 and 34. ADR 0052.
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- 55f3073: The help text spells `this platform's own font directories` with its apostrophe, and the
|
|
29
|
+
`render-dom` tarball carries `CHANGELOG.md` like the other eleven.
|
|
30
|
+
- Updated dependencies [55f3073]
|
|
31
|
+
- @pptx-studio/render-svg@0.2.0
|
|
32
|
+
- @pptx-studio/text@0.2.0
|
|
33
|
+
|
|
34
|
+
## 0.2.0
|
|
35
|
+
|
|
36
|
+
### Minor Changes
|
|
37
|
+
|
|
38
|
+
- 725ad6d: `renderDeck` takes only what it draws.
|
|
39
|
+
|
|
40
|
+
Its options were the `render` verb's own, so a caller that wanted SVG strings passed
|
|
41
|
+
`out`, `json` and `quiet` — three fields the function ignores — and five more it had no
|
|
42
|
+
opinion about. `RenderDeckOptions` is the shape now: `slide`, `width`, `fontDirs`,
|
|
43
|
+
`systemFonts` and `text`, all optional. `renderDeck(bytes)` is a whole call, and
|
|
44
|
+
`renderDeck(bytes, { slide: 1, width: 640 })` is a thumbnail.
|
|
45
|
+
|
|
46
|
+
`RenderOptions` is the verb's: it extends `RenderDeckOptions` with `out`, `json` and
|
|
47
|
+
`quiet`, and `runRender` is what takes it. `RENDER_DEFAULTS` is gone, because the
|
|
48
|
+
defaults are in `renderDeck` and `DEFAULT_WIDTH` is still exported. A width that is not
|
|
49
|
+
a positive whole number now throws `CLI_WIDTH` instead of drawing an empty picture.
|
|
50
|
+
|
|
51
|
+
Breaking: a call written against 0.1.0 passes three properties this shape does not have.
|
|
52
|
+
Delete them, and delete any field you were only passing to satisfy the type.
|
|
53
|
+
|
|
54
|
+
- c1d7d7d: The face box is read from the table this machine's rasteriser reads.
|
|
55
|
+
|
|
56
|
+
`pptx-studio render` took a face's ascent and descent from `OS/2.usWinAscent`/`usWinDescent`
|
|
57
|
+
everywhere, or `sTypo` where `fsSelection` bit 7 is set. That is what Chromium answers through
|
|
58
|
+
DirectWrite and it is not what Chromium answers through FreeType, which reads
|
|
59
|
+
`hhea.ascender`/`descender`. Neither reading fits both: the first scores 12/12 against Windows and
|
|
60
|
+
76/79 against Linux, the second 79/79 against Linux and 7/12 against Windows, and the misses are
|
|
61
|
+
75.8 px and 100 px on a 1000 px em rather than roundings.
|
|
62
|
+
|
|
63
|
+
On a Linux server — which is where this verb runs — the old reading put the IPA Gothic descent at
|
|
64
|
+
195.8 px where the browser puts it at 120, 7.6% of the em on every line of Japanese text, moving
|
|
65
|
+
every line break and every autofit decision.
|
|
66
|
+
|
|
67
|
+
`indexFonts` now resolves a `FontBackend` from its platform, and `metricsOf` reads `hhea` under
|
|
68
|
+
FreeType and `usWin` under DirectWrite, with bit 7 moving both onto `sTypo`. `FaceMetrics.source`
|
|
69
|
+
gains `hhea`, which is also what a face carrying no `OS/2` now reports rather than claiming `usWin`
|
|
70
|
+
while returning `hhea`'s numbers. macOS takes the DirectWrite reading and is unmeasured.
|
|
71
|
+
|
|
72
|
+
**Breaking:** `facesIn` and `faceOf` take the backend as a third argument. There is no defensible
|
|
73
|
+
default — a silent one would be a guess about the host — and `backendFor(platform)` is exported for
|
|
74
|
+
callers that want the local answer.
|
|
75
|
+
|
|
76
|
+
The rule is measured, not assumed: 79 real faces on a Linux runner against the 12 probe fonts T13
|
|
77
|
+
built to disagree with themselves, both scored in
|
|
78
|
+
`docs/adr/phase-3-text/0045-the-face-box-belongs-to-the-rasteriser.md`.
|
|
79
|
+
|
|
80
|
+
### Patch Changes
|
|
81
|
+
|
|
82
|
+
- 725ad6d: The ideographic baseline comes out of the font's `BASE` table.
|
|
83
|
+
|
|
84
|
+
`pptx-studio render` placed every upright East Asian glyph on the face's box descent,
|
|
85
|
+
which is right only for a face carrying no `BASE` table. Yu Gothic reports a box descent
|
|
86
|
+
of 0.302 em and an ideographic baseline of 0.1201 em, so a vertical `eaVert` frame was
|
|
87
|
+
drawn 0.18 em out of place on it — and the browser renderer, which asks Chromium, was
|
|
88
|
+
never wrong about the same face.
|
|
89
|
+
|
|
90
|
+
`sfnt.ts` now reads the `BASE` horizontal axis' `ideo` coordinate under the `DFLT`
|
|
91
|
+
script, and `FaceMetrics` carries it as `ideographic`. Where there is none the box
|
|
92
|
+
descent stands, and a coordinate outside the em answers zero, which is what
|
|
93
|
+
`@pptx-studio/text`'s own probe does with an unusable one.
|
|
94
|
+
|
|
95
|
+
The rule is measured, not assumed: four probe fonts whose `DFLT`, `latn` and `hani`
|
|
96
|
+
coordinates all disagree settle it at 30 of 30 in `corpus/ground-truth/font-metrics.json`.
|
|
97
|
+
Chromium reads `DFLT` and no other script — a `BASE` table naming only `latn`, `hani`
|
|
98
|
+
and `kana` is ignored whole — and it reads the same coordinate for a Latin run as for a
|
|
99
|
+
Han one, so the answer is a property of the face rather than of the text.
|
|
100
|
+
|
|
101
|
+
A coordinate outside the em is handed over as written rather than clamped — Chromium
|
|
102
|
+
reported 1.2 em for a font that says so — so both engines see the same unusable number
|
|
103
|
+
and both answer zero.
|
|
104
|
+
|
|
105
|
+
- cec9ef2: Kerning is read through a type 9 GPOS Extension lookup.
|
|
106
|
+
|
|
107
|
+
`pptx-studio render` measured every face whose `kern` feature sits behind an
|
|
108
|
+
`ExtensionPosFormat1` subtable as having no kerning at all — no error, no diagnostic, just
|
|
109
|
+
lines about a twelfth too wide, which moves every break and misfires autofit. Lato is such
|
|
110
|
+
a face, in all eighteen of the styles a Linux runner carries, and so is most of what a
|
|
111
|
+
modern font compiler emits: an extension is how a lookup reaches a subtable past the 64 KB
|
|
112
|
+
a 16-bit offset can address, and compilers wrap unconditionally rather than only when they
|
|
113
|
+
must.
|
|
114
|
+
|
|
115
|
+
`sfnt.ts` read `if (u16(r, lookup) !== 2) continue`, so lookup type 9 was skipped along
|
|
116
|
+
with mark attachment and cursive positioning, which genuinely do not move an advance. It
|
|
117
|
+
now follows a type 9 lookup one level, to the type its `ExtensionPosFormat1` names at the
|
|
118
|
+
32-bit offset from its own start, and reads the `PairPos` there. Exactly one level: the
|
|
119
|
+
specification forbids an extension targeting another, so nothing recurses, and a subtable
|
|
120
|
+
naming any other type is skipped as before.
|
|
121
|
+
|
|
122
|
+
The rule is measured, not assumed. A twelfth probe font wraps the same `PairPos` the
|
|
123
|
+
eleventh carries plainly, and Chromium drew the two identically at all six sizes and on
|
|
124
|
+
all six strings — so the browser honours the wrapper and the reader was wrong rather than
|
|
125
|
+
strict. Following one extension fits 72 of 72 in
|
|
126
|
+
`corpus/ground-truth/font-metrics.json`, alone at the top; the reading that skipped it
|
|
127
|
+
fits 66, exactly the six rows of the wrapped probe.
|
|
128
|
+
|
|
129
|
+
- cec9ef2: `renderDeck` substitutes a typeface nothing stands in for rather than refusing to draw.
|
|
130
|
+
|
|
131
|
+
A deck naming `Calibri Light` on a Linux server holding 53 perfectly good faces threw
|
|
132
|
+
`CLI_NO_FACE` and rendered nothing. The chain ran exact family, the substitution table,
|
|
133
|
+
Calibri, Carlito — and then gave up, which is the one place the font guard's design was
|
|
134
|
+
not applied: `FaceUse` carries `asked`, `drawn` and `substituted` so the answer can be
|
|
135
|
+
"Calibri Light was drawn in DejaVu Sans" rather than an exception.
|
|
136
|
+
|
|
137
|
+
Two steps now follow the measured chain. The shorter forms of the asked-for name, so
|
|
138
|
+
`Calibri Light` draws in Calibri and `Segoe UI Semilight` in Segoe UI where the machine
|
|
139
|
+
has them — DrawingML has no weight axis, so a style word is part of the typeface name.
|
|
140
|
+
Then, past every named candidate, the first family by name draws the run. Both are
|
|
141
|
+
reported as substitutions under the name the deck asked for, and neither displaces the
|
|
142
|
+
measured chain: ADR 0033 scored PowerPoint's own last resort at 22 of 22 and a guess must
|
|
143
|
+
not override a measurement.
|
|
144
|
+
|
|
145
|
+
The choice is by family name, not by the order `readdir` returned, and the font walk now
|
|
146
|
+
sorts its entries — so two machines holding the same faces draw the same picture, where
|
|
147
|
+
before the answer was the filesystem's own.
|
|
148
|
+
|
|
149
|
+
`CLI_NO_FACE` still throws, and now means exactly one thing: no font was found at all,
|
|
150
|
+
which is nothing to draw with rather than an unusual typeface.
|
|
151
|
+
|
|
3
152
|
## 0.1.0
|
|
4
153
|
|
|
5
154
|
### Minor Changes
|
package/README.md
CHANGED
|
@@ -200,14 +200,12 @@ cannot drift apart.
|
|
|
200
200
|
|
|
201
201
|
## Not built yet
|
|
202
202
|
|
|
203
|
-
The plan gives this package
|
|
204
|
-
|
|
203
|
+
The plan gives this package one more verb. Asking for it says which sub-phase brings
|
|
204
|
+
it rather than "unknown command":
|
|
205
205
|
|
|
206
|
-
| verb
|
|
207
|
-
|
|
|
208
|
-
| `
|
|
209
|
-
| `render` | render slides to SVG or PNG without a browser | 3.10 |
|
|
210
|
-
| `resolve` | show where a resolved property came from | 7.x |
|
|
206
|
+
| verb | what it will do | sub-phase |
|
|
207
|
+
| --------- | ---------------------------------------- | --------- |
|
|
208
|
+
| `resolve` | show where a resolved property came from | 7.x |
|
|
211
209
|
|
|
212
210
|
## `render`
|
|
213
211
|
|
|
@@ -226,12 +224,39 @@ the same document, and there is no external reference of any kind to resolve.
|
|
|
226
224
|
face's own `cmap`, `hmtx`, `GPOS` and `OS/2` tables instead. That is a second
|
|
227
225
|
measurement engine, and the risk of a second engine is that it quietly disagrees
|
|
228
226
|
with the first. Experiment T13 settled the arithmetic rather than assuming it:
|
|
229
|
-
|
|
230
|
-
Chromium, and the reader reproduces **all
|
|
227
|
+
fifteen fonts built so their tables disagree on purpose, 540 widths measured in
|
|
228
|
+
Chromium, and the reader reproduces **all 540 exactly**. It also settled where
|
|
229
|
+
an upright East Asian glyph sits: on the `BASE` table's `ideo` coordinate for
|
|
230
|
+
the `DFLT` script, and on the face box descent only where there is none — and
|
|
231
|
+
that the box itself is reported in whole pixels, each side rounded half up at
|
|
232
|
+
the size it is read, which three probes on a 2048, a 2000 and a 2560 em are the
|
|
233
|
+
only ones able to show. The rules it found are
|
|
231
234
|
in [`corpus/ground-truth/font-metrics.json`](../../corpus/ground-truth/font-metrics.json)
|
|
232
235
|
and the reasoning is in
|
|
233
236
|
[ADR 0042](../../docs/adr/phase-3-text/0042-rendering-without-a-browser.md).
|
|
234
237
|
|
|
238
|
+
**The face box depends on the rasteriser**, so the reader takes the answer
|
|
239
|
+
belonging to the platform it runs on. Chromium reports a face's ascent and
|
|
240
|
+
descent from `OS/2.usWinAscent`/`usWinDescent` through DirectWrite and from
|
|
241
|
+
`hhea.ascender`/`descender` through FreeType, with `fsSelection` bit 7 moving
|
|
242
|
+
both onto `sTypo`; through CoreText it reports `hhea` whatever bit 7 says. No
|
|
243
|
+
one reading fits two of them: T13's probes score 15/15, 7/15 and 6/15 on
|
|
244
|
+
Windows, where 94 faces score 94/94 on Linux and 248 score 248/248 on macOS,
|
|
245
|
+
the rivals missing by up to 100 px on a 1000 px em. CoreText also holds the em
|
|
246
|
+
ratio as 16.16 fixed point before it rounds, which moves a box that sits exactly
|
|
247
|
+
on the half; DirectWrite and FreeType do not. See
|
|
248
|
+
[ADR 0045](../../docs/adr/phase-3-text/0045-the-face-box-belongs-to-the-rasteriser.md)
|
|
249
|
+
and [ADR 0053](../../docs/adr/phase-3-text/0053-what-linux-and-macos-said.md).
|
|
250
|
+
|
|
251
|
+
Each reading is measured on its own runner, so a slide is laid out for the
|
|
252
|
+
machine that renders it. Line breaks, line origins and word spacing are
|
|
253
|
+
written into the SVG with that machine's advances, and a viewer flows each
|
|
254
|
+
line's glyphs with its own, so a deck rendered on a Linux server and opened on a
|
|
255
|
+
Windows desktop differs by whatever the two rasterisers disagree by — a rounding
|
|
256
|
+
per glyph on the same face, and the whole difference between two faces where
|
|
257
|
+
the viewer picks another from the list. Opened on the machine that made it, the
|
|
258
|
+
file draws exactly what was measured.
|
|
259
|
+
|
|
235
260
|
Fonts are found in this platform's own directories, plus any `--font-dir` you
|
|
236
261
|
name, which are searched first so you can override a face without installing
|
|
237
262
|
one. `--no-system-fonts` limits it to what you named; `--no-text` draws geometry
|
|
@@ -239,8 +264,36 @@ only and asks no font questions at all.
|
|
|
239
264
|
|
|
240
265
|
A typeface the machine does not have is substituted through the same table
|
|
241
266
|
`@pptx-studio/text` uses in the browser, so the two renderers cannot fall back
|
|
242
|
-
differently, and the substitution is reported rather than hidden.
|
|
243
|
-
|
|
267
|
+
differently, and the substitution is reported rather than hidden. The chain is
|
|
268
|
+
that table's entry for the name, then Calibri and Carlito — what PowerPoint
|
|
269
|
+
itself falls back to, measured 22 of 22 in
|
|
270
|
+
[ADR 0033](../../docs/adr/phase-3-text/0033-font-substitution-and-the-guard.md) —
|
|
271
|
+
then the family the asked-for name is a variation of, so `Calibri Light` draws
|
|
272
|
+
in Calibri where the machine has it.
|
|
273
|
+
|
|
274
|
+
Past all of those the first family by name draws the run. The browser's stack
|
|
275
|
+
ends in a generic and this has none, so something has to be chosen, and it is
|
|
276
|
+
chosen by name rather than by the order the files were read in: two machines
|
|
277
|
+
holding the same faces answer identically. It is still reported as a
|
|
278
|
+
substitution, under the name the deck asked for. **`CLI_NO_FACE` is thrown only
|
|
279
|
+
when no font was found at all** — an empty library is nothing to draw with,
|
|
280
|
+
which is a different thing from an unusual typeface. A code point no indexed
|
|
281
|
+
face can draw is reported too.
|
|
282
|
+
|
|
283
|
+
**The markup names the face that measured it.** Every run's `font-family` is a
|
|
284
|
+
list, not a name: the face this machine drew the run in, then the face the deck
|
|
285
|
+
asked for, then the substitution table's entry, then Calibri and Carlito, then
|
|
286
|
+
`sans-serif`. `Calibri Light` drawn in Carlito comes out as
|
|
287
|
+
`"Carlito", "Calibri Light", "Calibri", sans-serif`; a face the machine has
|
|
288
|
+
leads its own list, so on a machine holding the deck's fonts the markup reads as
|
|
289
|
+
the deck does. The order is the point. Line breaks and line origins are written
|
|
290
|
+
into the SVG with the first face's advances, so a viewer that has it draws
|
|
291
|
+
exactly what was measured; one that has only the face the deck named draws the
|
|
292
|
+
author's face on positions computed for a stand-in, which is right where the two
|
|
293
|
+
are metric-compatible and approximate where they are not; and one that has
|
|
294
|
+
neither lands where PowerPoint would have rather than on the browser's own
|
|
295
|
+
default. `--json` pairs each `asked` with its `drawn`: the drawn face leads that
|
|
296
|
+
run's list, and the asked one follows it wherever the two differ.
|
|
244
297
|
|
|
245
298
|
| flag | |
|
|
246
299
|
| ------------------- | ------------------------------------------------------------------- |
|
|
@@ -251,6 +304,37 @@ no indexed face can draw is reported too.
|
|
|
251
304
|
| `--no-system-fonts` | do not look in this platform's own font directories |
|
|
252
305
|
| `--no-text` | geometry only |
|
|
253
306
|
| `--json` | what was drawn, and which face drew each typeface |
|
|
307
|
+
| `--quiet` | no summary after writing |
|
|
308
|
+
|
|
309
|
+
### From a program
|
|
310
|
+
|
|
311
|
+
`renderDeck` is what the verb runs, without the file handling: it takes bytes and
|
|
312
|
+
returns the markup. Every option has a default, so the smallest call is the deck and
|
|
313
|
+
nothing else.
|
|
314
|
+
|
|
315
|
+
```ts
|
|
316
|
+
import { renderDeck } from '@pptx-studio/cli';
|
|
317
|
+
|
|
318
|
+
const deck = renderDeck(bytes); // every slide, 1920 wide
|
|
319
|
+
const thumb = renderDeck(bytes, { slide: 1, width: 640 }).slides[0]?.svg;
|
|
320
|
+
const shape = renderDeck(bytes, { text: false }); // geometry only, no fonts read
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
| option | default | |
|
|
324
|
+
| ------------- | ----------- | ----------------------------------------------------------- |
|
|
325
|
+
| `slide` | every slide | 1-based; `null` and omitted both mean every slide |
|
|
326
|
+
| `width` | `1920` | the `width` attribute; the height follows the deck's aspect |
|
|
327
|
+
| `fontDirs` | none | searched before the platform's own |
|
|
328
|
+
| `systemFonts` | `true` | also look in this platform's font directories |
|
|
329
|
+
| `text` | `true` | `false` draws geometry only and asks no font questions |
|
|
330
|
+
|
|
331
|
+
`--out`, `--json` and `--quiet` are the command's, not the library's: they say where
|
|
332
|
+
the markup goes and what is printed about it. `runRender` takes those, reads the deck
|
|
333
|
+
off the disk and writes the files. `renderDeck` does neither, and a width that is not
|
|
334
|
+
a positive whole number throws `CLI_WIDTH` rather than drawing an empty picture.
|
|
335
|
+
|
|
336
|
+
Fonts are indexed per call, so a server rendering many decks pays for the scan every
|
|
337
|
+
time.
|
|
254
338
|
|
|
255
339
|
### What it does not do
|
|
256
340
|
|
package/dist/cli.js
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PackageCensus } from "@pptx-studio/census";
|
|
2
|
-
import { FaceBoxProbe, TextMeasurer } from "@pptx-studio/text";
|
|
2
|
+
import { FaceBoxProbe, RunFont, TextMeasurer } from "@pptx-studio/text";
|
|
3
3
|
//#region src/main.d.ts
|
|
4
4
|
interface Streams {
|
|
5
5
|
readonly out: (text: string) => void;
|
|
@@ -60,6 +60,30 @@ declare function runInspect(path: string, options: InspectOptions, write: (text:
|
|
|
60
60
|
* against Chromium in experiment T13 rather than taken from the specification.
|
|
61
61
|
* ADR 0042.
|
|
62
62
|
*/
|
|
63
|
+
/**
|
|
64
|
+
* The rasteriser a Chromium reads a face's vertical metrics through.
|
|
65
|
+
*
|
|
66
|
+
* T13 scored `usWin` 30/30 against DirectWrite on fonts built to disagree; T14
|
|
67
|
+
* scored `hhea` 94/94 against FreeType and 248/248 against CoreText on real
|
|
68
|
+
* faces. One reader cannot answer for all three. ADR 0045, ADR 0053.
|
|
69
|
+
*/
|
|
70
|
+
type FontBackend = 'directwrite' | 'freetype' | 'coretext';
|
|
71
|
+
/** FreeType on Linux, CoreText on macOS, DirectWrite elsewhere. ADR 0045, ADR 0053. */
|
|
72
|
+
declare function backendFor(platform: string): FontBackend;
|
|
73
|
+
/** One ascent and descent in font units, the descent positive below the baseline. */
|
|
74
|
+
interface MetricPair {
|
|
75
|
+
readonly ascent: number;
|
|
76
|
+
readonly descent: number;
|
|
77
|
+
}
|
|
78
|
+
/** Every pair a browser could report a face box from, each as its table wrote it. */
|
|
79
|
+
interface MetricCandidates {
|
|
80
|
+
readonly hhea: MetricPair;
|
|
81
|
+
/** `undefined` on a face with no `OS/2` table long enough to hold version 0. */
|
|
82
|
+
readonly usWin: MetricPair | undefined;
|
|
83
|
+
readonly sTypo: MetricPair | undefined;
|
|
84
|
+
/** `OS/2.fsSelection` bit 7, USE_TYPO_METRICS. */
|
|
85
|
+
readonly useTypoMetrics: boolean;
|
|
86
|
+
}
|
|
63
87
|
interface FaceMetrics {
|
|
64
88
|
/** `head.unitsPerEm`, the denominator of every number here. */
|
|
65
89
|
readonly unitsPerEm: number;
|
|
@@ -68,7 +92,13 @@ interface FaceMetrics {
|
|
|
68
92
|
/** Below the baseline, in font units, positive. */
|
|
69
93
|
readonly descent: number;
|
|
70
94
|
/** Which table `ascent` and `descent` came out of, for the diagnostics. */
|
|
71
|
-
readonly source: 'usWin' | 'sTypo';
|
|
95
|
+
readonly source: 'hhea' | 'usWin' | 'sTypo';
|
|
96
|
+
/** The rasteriser `source` was chosen for, which also fixes how the box rounds. */
|
|
97
|
+
readonly backend: FontBackend;
|
|
98
|
+
/** The `BASE` `ideo` coordinate under `DFLT`, in font units below the baseline. */
|
|
99
|
+
readonly ideographic: number | undefined;
|
|
100
|
+
/** The pairs `ascent` and `descent` were chosen from, so a rival reading is scorable. */
|
|
101
|
+
readonly candidates: MetricCandidates;
|
|
72
102
|
}
|
|
73
103
|
interface Face {
|
|
74
104
|
/** `name` ID 1, which is what PowerPoint matches a typeface on. */
|
|
@@ -86,7 +116,7 @@ interface Face {
|
|
|
86
116
|
kernBetween(left: number, right: number): number;
|
|
87
117
|
}
|
|
88
118
|
/** Every face in a file, which is one unless the file is a collection. */
|
|
89
|
-
declare function facesIn(bytes: Uint8Array, subject: string): readonly Face[];
|
|
119
|
+
declare function facesIn(bytes: Uint8Array, subject: string, backend: FontBackend): readonly Face[];
|
|
90
120
|
//#endregion
|
|
91
121
|
//#region src/render/faces.d.ts
|
|
92
122
|
/** Where fonts live on this platform, whether or not the directories exist. */
|
|
@@ -138,6 +168,8 @@ interface FaceUse {
|
|
|
138
168
|
interface FontMeasurer {
|
|
139
169
|
readonly measurer: TextMeasurer;
|
|
140
170
|
readonly faceBox: FaceBoxProbe;
|
|
171
|
+
/** The CSS family list a run is drawn in: the face that measured it, then the deck's own stack. */
|
|
172
|
+
readonly cssFamilyFor: (font: RunFont) => string;
|
|
141
173
|
/** Every typeface asked for, and what it was drawn in. */
|
|
142
174
|
used(): readonly FaceUse[];
|
|
143
175
|
/** Code points no face in the library could draw. */
|
|
@@ -154,23 +186,26 @@ declare function createFontMeasurer(library: FontLibrary): FontMeasurer;
|
|
|
154
186
|
//#region src/render/render.d.ts
|
|
155
187
|
/** What a slide is drawn at when the caller says nothing. PowerPoint's own. */
|
|
156
188
|
declare const DEFAULT_WIDTH = 1920;
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
readonly
|
|
189
|
+
/** What to draw. Every field has a default, so `renderDeck(bytes)` is a whole call. */
|
|
190
|
+
interface RenderDeckOptions {
|
|
191
|
+
/** 1-based. Omitted, or `null`, is every slide. */
|
|
192
|
+
readonly slide?: number | null;
|
|
193
|
+
/** The `width` attribute in CSS pixels; the height follows the deck's aspect. */
|
|
194
|
+
readonly width?: number;
|
|
195
|
+
/** Searched before the platform's own, so a face can be overridden without installing it. */
|
|
196
|
+
readonly fontDirs?: readonly string[];
|
|
197
|
+
/** Also look in this platform's font directories. Default true. */
|
|
198
|
+
readonly systemFonts?: boolean;
|
|
199
|
+
/** Draw text. `false` draws geometry only and asks no font questions. Default true. */
|
|
200
|
+
readonly text?: boolean;
|
|
201
|
+
}
|
|
202
|
+
/** What the verb adds: where the markup goes, and what is said about it. */
|
|
203
|
+
interface RenderOptions extends RenderDeckOptions {
|
|
161
204
|
/** A directory for many slides, a file for one, or `null` for stdout. */
|
|
162
205
|
readonly out: string | null;
|
|
163
|
-
readonly fontDirs: readonly string[];
|
|
164
|
-
readonly systemFonts: boolean;
|
|
165
|
-
readonly text: boolean;
|
|
166
206
|
readonly json: boolean;
|
|
167
207
|
readonly quiet: boolean;
|
|
168
208
|
}
|
|
169
|
-
declare const RENDER_DEFAULTS: {
|
|
170
|
-
readonly width: 1920;
|
|
171
|
-
readonly systemFonts: true;
|
|
172
|
-
readonly text: true;
|
|
173
|
-
};
|
|
174
209
|
interface RenderedSlide {
|
|
175
210
|
/** 1-based, as the flag and the file name spell it. */
|
|
176
211
|
readonly number: number;
|
|
@@ -190,10 +225,10 @@ interface RenderResult {
|
|
|
190
225
|
/**
|
|
191
226
|
* Render a deck that is already in memory.
|
|
192
227
|
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
228
|
+
* The library entry point: no file system, no process, no stdout. `runRender` is
|
|
229
|
+
* the verb wrapped around it, and the three fields it adds are its own.
|
|
195
230
|
*/
|
|
196
|
-
declare function renderDeck(bytes: Uint8Array, options
|
|
231
|
+
declare function renderDeck(bytes: Uint8Array, options?: RenderDeckOptions): RenderResult;
|
|
197
232
|
/** Read, render, write, and return an exit code. Never calls `process.exit`. */
|
|
198
233
|
declare function runRender(file: string, options: RenderOptions, out: (text: string) => void): number;
|
|
199
234
|
//#endregion
|
|
@@ -216,6 +251,8 @@ type RenderErrorCode =
|
|
|
216
251
|
'CLI_FONT_SIZE' |
|
|
217
252
|
/** A slide index outside the deck. */
|
|
218
253
|
'CLI_NO_SLIDE' |
|
|
254
|
+
/** A width that is not a positive whole number of pixels. */
|
|
255
|
+
'CLI_WIDTH' |
|
|
219
256
|
/** An output path that names no directory, or a directory that is a file. */
|
|
220
257
|
'CLI_OUTPUT_PATH';
|
|
221
258
|
declare const RENDER_ERROR_CODES: readonly RenderErrorCode[];
|
|
@@ -228,5 +265,5 @@ declare class RenderError extends Error {
|
|
|
228
265
|
}
|
|
229
266
|
declare function isRenderError(error: unknown): error is RenderError;
|
|
230
267
|
//#endregion
|
|
231
|
-
export { DEFAULT_WIDTH, type Face, type FaceUse, type FontLibrary, type FontMeasurer, INSPECT_DEFAULTS, type InspectOptions, type InspectResult,
|
|
268
|
+
export { DEFAULT_WIDTH, type Face, type FaceUse, type FontBackend, type FontLibrary, type FontMeasurer, INSPECT_DEFAULTS, type InspectOptions, type InspectResult, RENDER_ERROR_CODES, type RenderDeckOptions, RenderError, type RenderErrorCode, type RenderOptions, type RenderResult, type RenderedSlide, type Streams, backendFor, createFontMeasurer, facesIn, indexFonts, inspectFile, isRenderError, main, renderDeck, runInspect, runRender, systemFontDirectories };
|
|
232
269
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/main.ts","../src/inspect.ts","../src/render/sfnt.ts","../src/render/faces.ts","../src/render/measure.ts","../src/render/render.ts","../src/render/errors.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/main.ts","../src/inspect.ts","../src/render/sfnt.ts","../src/render/faces.ts","../src/render/measure.ts","../src/render/render.ts","../src/render/errors.ts"],"mappings":";;;UAyHiB;WACN,MAAM;WACN,MAAM;;;iBASD,KAAK,yBAAyB,UAAS;;;;;;;;;;;;;;;UCpHtC;WACN;WACA;WACA;WACA;;WAEA;;cAGE,kBAAkB;UAQd;WACN,QAAQ;WACR;;;;;;;;;;WAUA;;;iBAIK,YACd,cACA,UAAS,iBACR;;iBAiBa,WACd,cACA,SAAS,gBACT,QAAQ;;;;;;;;;;;;;;;;;;;;KC7CE;;iBAGI,WAAW,mBAAmB;;UAO7B;WACN;WACA;;;UAIM;WACN,MAAM;;WAEN,OAAO;WACP,OAAO;;WAEP;;UAGM;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA,SAAS;;WAET;;WAEA,YAAY;;UAGN;;WAEN;;WAEA;;WAEA;WACA,SAAS;WACT;WACA;;EAET,UAAU;;EAEV,YAAY,cAAc;;;iBAyjBZ,QAAQ,OAAO,YAAY,iBAAiB,SAAS,uBAAuB;;;;iBC5lB5E,sBAAsB;UAyCrB;WACN,MAAM;WACN;;;UAIM;WACN,MAAM;;WAEN;;WAEA;WACA;WACA;;UAGM;;WAEN,kBAAkB;;WAElB;EACT,QAAQ,gBAAgB,eAAe,kBAAkB;;UAG1C;;WAEN;;WAEA;WACA;;;;;;;;;iBAuDK,WAAW,UAAS,eAAoB;;;UC9GvC;WACN;WACA;WACA;WACA;;UAGM;WACN,UAAU;WACV,SAAS;;WAET,eAAe,MAAM;;EAE9B,iBAAiB;;EAEjB;;;;;;;;iBASc,mBAAmB,SAAS,cAAc;;;;cChE7C;;UAGI;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;;;UAIM,sBAAsB;;WAE5B;WACA;WACA;;UAQM;;WAEN;WACA;;UAGM;WACN,iBAAiB;WACjB;WACA;;WAEA,gBAAgB;;WAEhB;WACA;WACA;;;;;;;;iBAoBK,WAAW,OAAO,YAAY,UAAS,oBAAyB;;iBAqJhE,UACd,cACA,SAAS,eACT,MAAM;;;;;;;;;;KCvOI;;;;;;;;;;;;;;;cAgBC,6BAA6B;cAU7B,oBAAoB;WACb;WACT,MAAM;;WAEN;EAEG,YAAA,MAAM,iBAAiB,iBAAiB;;iBAOtC,cAAc,iBAAiB,SAAS"}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { DEFAULT_WIDTH, INSPECT_DEFAULTS,
|
|
1
|
+
import { a as createFontMeasurer, c as backendFor, d as RenderError, f as isRenderError, h as runInspect, i as runRender, l as facesIn, m as inspectFile, n as DEFAULT_WIDTH, o as indexFonts, p as INSPECT_DEFAULTS, r as renderDeck, s as systemFontDirectories, t as main, u as RENDER_ERROR_CODES } from "./main-3sNR_Xlp.js";
|
|
2
|
+
export { DEFAULT_WIDTH, INSPECT_DEFAULTS, RENDER_ERROR_CODES, RenderError, backendFor, createFontMeasurer, facesIn, indexFonts, inspectFile, isRenderError, main, renderDeck, runInspect, runRender, systemFontDirectories };
|