reamkit 1.22.0 → 1.23.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 (72) hide show
  1. package/dist/esm/core/converter/ream.d.ts +16 -0
  2. package/dist/esm/core/converter/ream.js +59 -9
  3. package/dist/esm/core/document-model/types.d.ts +18 -0
  4. package/dist/esm/core/drawingml/chart-geometry.js +11 -5
  5. package/dist/esm/core/drawingml/colors.d.ts +4 -2
  6. package/dist/esm/core/drawingml/colors.js +15 -0
  7. package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
  8. package/dist/esm/core/drawingml/theme-parser.js +64 -1
  9. package/dist/esm/core/fonts/families.d.ts +10 -0
  10. package/dist/esm/core/fonts/families.js +44 -0
  11. package/dist/esm/core/fonts/index.d.ts +3 -2
  12. package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
  13. package/dist/esm/core/fonts/remote-fonts.js +114 -8
  14. package/dist/esm/core/fonts/scripts.d.ts +26 -0
  15. package/dist/esm/core/fonts/scripts.js +177 -0
  16. package/dist/esm/core/metafile/blit.d.ts +33 -0
  17. package/dist/esm/core/metafile/blit.js +67 -0
  18. package/dist/esm/core/metafile/dib.d.ts +61 -0
  19. package/dist/esm/core/metafile/dib.js +205 -0
  20. package/dist/esm/core/metafile/emf.js +137 -23
  21. package/dist/esm/core/metafile/picture.d.ts +12 -1
  22. package/dist/esm/core/metafile/wmf.js +149 -9
  23. package/dist/esm/core/ole/escher-blip.d.ts +12 -0
  24. package/dist/esm/core/ole/escher-blip.js +88 -0
  25. package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
  26. package/dist/esm/excel/print-model.js +3 -1
  27. package/dist/esm/excel/styles-parser.js +1 -1
  28. package/dist/esm/excel/xls/biff-reader.js +53 -18
  29. package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
  30. package/dist/esm/excel/xls/biff-styles.js +9 -7
  31. package/dist/esm/excel/xls/escher.js +90 -24
  32. package/dist/esm/layout/page-doc.d.ts +39 -0
  33. package/dist/esm/layout/styled-layout.d.ts +2 -2
  34. package/dist/esm/layout/styled-layout.js +301 -35
  35. package/dist/esm/pdf/styled-page-emitter.js +35 -2
  36. package/dist/esm/pdf-reader/image-decode.js +1 -1
  37. package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
  38. package/dist/esm/pptx/embedded-fonts.js +104 -0
  39. package/dist/esm/pptx/placeholder-cascade.d.ts +73 -6
  40. package/dist/esm/pptx/placeholder-cascade.js +114 -18
  41. package/dist/esm/pptx/ppt/ppt-reader.js +120 -10
  42. package/dist/esm/pptx/ppt/ppt-text.d.ts +66 -1
  43. package/dist/esm/pptx/ppt/ppt-text.js +576 -137
  44. package/dist/esm/pptx/pptx-reader.d.ts +8 -0
  45. package/dist/esm/pptx/pptx-reader.js +27 -5
  46. package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
  47. package/dist/esm/pptx/preset-table-styles.js +27 -0
  48. package/dist/esm/pptx/slide-parser.d.ts +7 -1
  49. package/dist/esm/pptx/slide-parser.js +106 -33
  50. package/dist/esm/pptx/sp-helpers.d.ts +2 -1
  51. package/dist/esm/pptx/sp-helpers.js +3 -2
  52. package/dist/esm/pptx/table-style.d.ts +9 -1
  53. package/dist/esm/pptx/table-style.js +49 -7
  54. package/dist/esm/word/document-parser.d.ts +7 -1
  55. package/dist/esm/word/document-parser.js +6 -6
  56. package/dist/esm/word/docx-reader.js +6 -3
  57. package/dist/esm/word/docx-to-pdf.d.ts +8 -7
  58. package/dist/esm/word/docx-to-pdf.js +25 -7
  59. package/dist/esm/word/drawing-parser.js +31 -19
  60. package/dist/esm/word/numbering-parser.d.ts +2 -1
  61. package/dist/esm/word/numbering-parser.js +6 -6
  62. package/dist/esm/word/paragraph-properties.d.ts +2 -1
  63. package/dist/esm/word/paragraph-properties.js +2 -2
  64. package/dist/esm/word/run-properties.d.ts +5 -2
  65. package/dist/esm/word/run-properties.js +13 -8
  66. package/dist/esm/word/styles-parser.d.ts +2 -1
  67. package/dist/esm/word/styles-parser.js +12 -12
  68. package/dist/esm/word/table-parser.js +3 -3
  69. package/dist/esm/word/theme-fonts.d.ts +10 -0
  70. package/dist/esm/word/theme-fonts.js +28 -0
  71. package/package.json +1 -1
  72. /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
@@ -1,5 +1,6 @@
1
1
  import { pt } from "../../core/ir/units.js";
2
2
  import { ResourceStore } from "../../core/ir/resources.js";
3
+ import { makeColWidthPt, makeRowHeightPt } from "../sheet-drawing.js";
3
4
  import { openCfb } from "../../core/ole/cfb.js";
4
5
  import { parseBiffChart } from "./biff-chart.js";
5
6
  import { buildBiffPalette, parseBiffStyles } from "./biff-styles.js";
@@ -333,7 +334,8 @@ function readSheet(wb, view, start, blips, resources, sharedStrings, chartData,
333
334
  ...pane ? { pane } : {}
334
335
  };
335
336
  const drawing = gatherDrawing(records, REC.MSODRAWING);
336
- const images = drawing.length > 0 && blips.length > 0 ? buildImages(drawing, blips, resources) : [];
337
+ const place = anchorPlacer(grid);
338
+ const images = drawing.length > 0 && blips.length > 0 ? buildImages(drawing, blips, resources, place) : [];
337
339
  const charts = [];
338
340
  for (let i = 0; i < records.length; i++) {
339
341
  if (records[i].type !== REC.BOF || readU16(records[i].data, 2) !== 32) continue;
@@ -361,7 +363,7 @@ function readSheet(wb, view, start, blips, resources, sharedStrings, chartData,
361
363
  grid,
362
364
  images,
363
365
  charts,
364
- shapes: drawing.length > 0 ? buildShapes(parseSheetShapes(drawing), gatherTxoTexts(records)) : [],
366
+ shapes: drawing.length > 0 ? buildShapes(parseSheetShapes(drawing), gatherTxoTexts(records), place) : [],
365
367
  hyperlinks,
366
368
  comments: parseComments(records)
367
369
  };
@@ -1174,13 +1176,24 @@ function parseComments(records) {
1174
1176
  }
1175
1177
  return out;
1176
1178
  }
1177
- function buildShapes(escherShapes, txoTexts) {
1179
+ function buildShapes(escherShapes, txoTexts, place) {
1178
1180
  const out = [];
1179
1181
  let textIdx = 0;
1180
1182
  for (const s of escherShapes) {
1181
1183
  const text = s.hasText ? txoTexts[textIdx++] ?? "" : "";
1182
- const { widthPt, heightPt } = anchorSize(s.anchor);
1184
+ const { xPt, yPt, widthPt, heightPt } = place(s.anchor);
1183
1185
  out.push({
1186
+ float: {
1187
+ wrap: "none",
1188
+ posH: {
1189
+ relativeFrom: "margin",
1190
+ offsetPt: pt(xPt)
1191
+ },
1192
+ posV: {
1193
+ relativeFrom: "margin",
1194
+ offsetPt: pt(yPt)
1195
+ }
1196
+ },
1184
1197
  width: pt(widthPt),
1185
1198
  height: pt(heightPt),
1186
1199
  geometry: {
@@ -1222,34 +1235,56 @@ function shapePreset(type) {
1222
1235
  default: return "rect";
1223
1236
  }
1224
1237
  }
1225
- function buildImages(drawing, blips, resources) {
1238
+ function buildImages(drawing, blips, resources, place) {
1226
1239
  const out = [];
1227
1240
  for (const pic of parseSheetPictures(drawing)) {
1228
1241
  const bytes = blips[pic.blipIndex - 1];
1229
1242
  if (!bytes) continue;
1230
- const { widthPt, heightPt } = anchorSize(pic.anchor);
1243
+ const { xPt, yPt, widthPt, heightPt } = place(pic.anchor);
1231
1244
  out.push({
1232
1245
  resourceId: resources.put(bytes),
1233
1246
  widthPt,
1234
- heightPt
1247
+ heightPt,
1248
+ xPt,
1249
+ yPt
1235
1250
  });
1236
1251
  }
1237
1252
  return out;
1238
1253
  }
1239
- function anchorSize(anchor) {
1240
- if (!anchor) return {
1241
- widthPt: 96,
1242
- heightPt: 72
1254
+ function anchorPlacer(grid) {
1255
+ const colPt = makeColWidthPt(grid);
1256
+ const rowPt = makeRowHeightPt(grid);
1257
+ const before = (track) => {
1258
+ const sums = [0];
1259
+ return (index) => {
1260
+ const n = Math.min(Math.max(Math.trunc(index), 0), MAX_ANCHOR_TRACKS);
1261
+ while (sums.length <= n) sums.push(sums[sums.length - 1] + track(sums.length - 1));
1262
+ return sums[n];
1263
+ };
1243
1264
  };
1244
- const DEFAULT_COL_PT = 48;
1245
- const DEFAULT_ROW_PT = 15;
1246
- const cols = anchor.col2 + anchor.dx2 / 1024 - (anchor.col1 + anchor.dx1 / 1024);
1247
- const rows = anchor.row2 + anchor.dy2 / 1024 - (anchor.row1 + anchor.dy1 / 1024);
1248
- return {
1249
- widthPt: Math.max(8, cols * DEFAULT_COL_PT),
1250
- heightPt: Math.max(8, rows * DEFAULT_ROW_PT)
1265
+ const beforeCol = before(colPt);
1266
+ const beforeRow = before(rowPt);
1267
+ const at = (index, off, start, track) => start(index) + off / 1024 * track(index);
1268
+ return (anchor) => {
1269
+ if (!anchor) return {
1270
+ xPt: 0,
1271
+ yPt: 0,
1272
+ widthPt: 96,
1273
+ heightPt: 72
1274
+ };
1275
+ const x1 = at(anchor.col1, anchor.dx1, beforeCol, colPt);
1276
+ const x2 = at(anchor.col2, anchor.dx2, beforeCol, colPt);
1277
+ const y1 = at(anchor.row1, anchor.dy1, beforeRow, rowPt);
1278
+ const y2 = at(anchor.row2, anchor.dy2, beforeRow, rowPt);
1279
+ return {
1280
+ xPt: x1,
1281
+ yPt: y1,
1282
+ widthPt: Math.max(1, x2 - x1),
1283
+ heightPt: Math.max(1, y2 - y1)
1284
+ };
1251
1285
  };
1252
1286
  }
1287
+ var MAX_ANCHOR_TRACKS = 65536;
1253
1288
  function numCell(row, column, style, rawValue) {
1254
1289
  return {
1255
1290
  column,
@@ -4,8 +4,11 @@ interface BiffRec {
4
4
  readonly data: Uint8Array;
5
5
  }
6
6
  /**
7
- * Build a palette-index → `"FFRRGGBB"` (8-hex ARGB, like the xlsx `rgb` attr)
8
- * resolver from the default 56-colour palette plus any `PALETTE` override.
7
+ * Build a palette-index → `"RRGGBB"` resolver from the default 56-colour palette
8
+ * plus any `PALETTE` override. Six hex digits, not the eight an xlsx `rgb`
9
+ * attribute carries: by the time styles are parsed the alpha is gone, and a
10
+ * colour that kept it was read from its first six characters — silver `C0C0C0`
11
+ * reaching the page as the pink `FFC0C0`.
9
12
  * `0x7FFF` / 64 / 65 are automatic or system colours → `undefined` (the renderer
10
13
  * default). Exported so the conditional-format reader (XLS-13) resolves its dxf
11
14
  * colours the same way.
@@ -116,8 +116,11 @@ var PALETTE56 = [
116
116
  "333333"
117
117
  ];
118
118
  /**
119
- * Build a palette-index → `"FFRRGGBB"` (8-hex ARGB, like the xlsx `rgb` attr)
120
- * resolver from the default 56-colour palette plus any `PALETTE` override.
119
+ * Build a palette-index → `"RRGGBB"` resolver from the default 56-colour palette
120
+ * plus any `PALETTE` override. Six hex digits, not the eight an xlsx `rgb`
121
+ * attribute carries: by the time styles are parsed the alpha is gone, and a
122
+ * colour that kept it was read from its first six characters — silver `C0C0C0`
123
+ * reaching the page as the pink `FFC0C0`.
121
124
  * `0x7FFF` / 64 / 65 are automatic or system colours → `undefined` (the renderer
122
125
  * default). Exported so the conditional-format reader (XLS-13) resolves its dxf
123
126
  * colours the same way.
@@ -130,8 +133,7 @@ function buildBiffPalette(records) {
130
133
  for (const rec of records) if (rec.type === REC_PALETTE) applyPalette(rec.data, palette);
131
134
  return (icv) => {
132
135
  if (icv === 32767 || icv === 64 || icv === 65) return void 0;
133
- const rgb = palette[icv];
134
- return rgb ? `FF${rgb}` : void 0;
136
+ return palette[icv];
135
137
  };
136
138
  }
137
139
  /**
@@ -252,11 +254,11 @@ function parseXf(d, color, internFill, internBorder) {
252
254
  if (right) border.right = right;
253
255
  if (top) border.top = top;
254
256
  if (bottom) border.bottom = bottom;
255
- const patternType = FILL_PATTERNS[brd3 >> 26 & 63];
257
+ const patternType = FILL_PATTERNS[brd3 >> 10 & 63];
256
258
  let fill;
257
259
  if (patternType && patternType !== "none") {
258
- const fg = color(brd3 & 127);
259
- const bg = color(brd3 >> 7 & 127);
260
+ const fg = color(brd3 >> 16 & 127);
261
+ const bg = color(brd3 >> 23 & 127);
260
262
  fill = {
261
263
  patternType,
262
264
  ...fg ? { fgColorHex: fg } : {},
@@ -1,3 +1,4 @@
1
+ import { readEscherBlip } from "../../core/ole/escher-blip.js";
1
2
  //#region src/excel/xls/escher.ts
2
3
  var FBT_BSTORE_CONTAINER = 61441;
3
4
  var FBT_BSE = 61447;
@@ -6,6 +7,7 @@ var FBT_OPT = 61451;
6
7
  var FBT_CLIENT_ANCHOR = 61456;
7
8
  var PROP_PIB = 260;
8
9
  var MAX_DEPTH = 24;
10
+ var BSE_HEADER_BYTES = 36;
9
11
  function* records(d) {
10
12
  let off = 0;
11
13
  while (off + 8 <= d.length) {
@@ -37,7 +39,11 @@ function parseBlipStore(msoDrawingGroup) {
37
39
  const store = findContainer(msoDrawingGroup, FBT_BSTORE_CONTAINER, 0);
38
40
  if (!store) return [];
39
41
  const out = [];
40
- for (const r of records(store)) if (r.type === FBT_BSE) out.push(findImageBytes(r.data));
42
+ for (const r of records(store)) {
43
+ if (r.type !== FBT_BSE) continue;
44
+ const nested = [...records(r.data.subarray(BSE_HEADER_BYTES))][0];
45
+ out.push(nested ? readEscherBlip(nested.type, nested.instance, nested.data) ?? findImageBytes(r.data) : findImageBytes(r.data));
46
+ }
41
47
  return out;
42
48
  }
43
49
  function findContainer(d, type, depth) {
@@ -74,6 +80,9 @@ function collectPictures(d, out, depth) {
74
80
  }
75
81
  var FBT_SP = 61450;
76
82
  var FBT_CLIENT_TEXTBOX = 61453;
83
+ var FBT_SPGR_CONTAINER = 61443;
84
+ var FBT_SPGR = 61449;
85
+ var FBT_CHILD_ANCHOR = 61455;
77
86
  var PROP_FILL_COLOR = 385;
78
87
  var PROP_LINE_COLOR = 448;
79
88
  /**
@@ -86,30 +95,84 @@ function parseSheetShapes(msoDrawing) {
86
95
  collectShapes(msoDrawing, out, 0);
87
96
  return out;
88
97
  }
89
- function collectShapes(d, out, depth) {
98
+ function collectShapes(d, out, depth, group) {
90
99
  if (depth > MAX_DEPTH) return;
91
- for (const r of records(d)) if (r.type === FBT_SP_CONTAINER) {
92
- let shapeType = 0;
93
- let hasText = false;
94
- let pib;
95
- let anchor;
96
- let fill;
97
- let line;
98
- for (const child of records(r.data)) if (child.type === FBT_SP) shapeType = child.instance;
99
- else if (child.type === FBT_OPT) {
100
- pib = optProperty(child.data, child.instance, PROP_PIB);
101
- fill = optColor(child.data, child.instance, PROP_FILL_COLOR);
102
- line = optColor(child.data, child.instance, PROP_LINE_COLOR);
103
- } else if (child.type === FBT_CLIENT_ANCHOR) anchor = parseAnchor(child.data);
104
- else if (child.type === FBT_CLIENT_TEXTBOX) hasText = true;
105
- if (pib === void 0 && shapeType !== 0) out.push({
106
- shapeType,
107
- hasText,
108
- ...anchor ? { anchor } : {},
109
- ...fill ? { fillColorHex: fill } : {},
110
- ...line ? { lineColorHex: line } : {}
111
- });
112
- } else if (r.isContainer) collectShapes(r.data, out, depth + 1);
100
+ for (const r of records(d)) {
101
+ if (r.type === FBT_SPGR_CONTAINER) {
102
+ collectShapes(r.data, out, depth + 1, groupFrame(r.data) ?? group);
103
+ continue;
104
+ }
105
+ if (r.type === FBT_SP_CONTAINER) {
106
+ let shapeType = 0;
107
+ let hasText = false;
108
+ let pib;
109
+ let anchor;
110
+ let fill;
111
+ let line;
112
+ for (const child of records(r.data)) if (child.type === FBT_SP) shapeType = child.instance;
113
+ else if (child.type === FBT_OPT) {
114
+ pib = optProperty(child.data, child.instance, PROP_PIB);
115
+ fill = optColor(child.data, child.instance, PROP_FILL_COLOR);
116
+ line = optColor(child.data, child.instance, PROP_LINE_COLOR);
117
+ } else if (child.type === FBT_CLIENT_ANCHOR) anchor = parseAnchor(child.data);
118
+ else if (child.type === FBT_CHILD_ANCHOR && group) anchor = childAnchor(child.data, group);
119
+ else if (child.type === FBT_CLIENT_TEXTBOX) hasText = true;
120
+ if (pib === void 0 && shapeType !== 0) out.push({
121
+ shapeType,
122
+ hasText,
123
+ ...anchor ? { anchor } : {},
124
+ ...fill ? { fillColorHex: fill } : {},
125
+ ...line ? { lineColorHex: line } : {}
126
+ });
127
+ } else if (r.isContainer) collectShapes(r.data, out, depth + 1, group);
128
+ }
129
+ }
130
+ function groupFrame(spgrData) {
131
+ const sp = [...records(spgrData)].find((r) => r.type === FBT_SP_CONTAINER);
132
+ if (!sp) return void 0;
133
+ let box;
134
+ let anchor;
135
+ for (const child of records(sp.data)) if (child.type === FBT_SPGR && child.data.length >= 16) {
136
+ const x = i32(child.data, 0);
137
+ const y = i32(child.data, 4);
138
+ box = {
139
+ x,
140
+ y,
141
+ w: i32(child.data, 8) - x,
142
+ h: i32(child.data, 12) - y
143
+ };
144
+ } else if (child.type === FBT_CLIENT_ANCHOR) anchor = parseAnchor(child.data);
145
+ if (!box || !anchor || box.w <= 0 || box.h <= 0) return void 0;
146
+ return {
147
+ anchor,
148
+ ...box
149
+ };
150
+ }
151
+ function childAnchor(d, g) {
152
+ if (d.length < 16) return void 0;
153
+ const from = (v, lo, hi, min, size) => lo + (v - min) / size * (hi - lo);
154
+ const x1 = g.anchor.col1 + g.anchor.dx1 / 1024;
155
+ const x2 = g.anchor.col2 + g.anchor.dx2 / 1024;
156
+ const y1 = g.anchor.row1 + g.anchor.dy1 / 1024;
157
+ const y2 = g.anchor.row2 + g.anchor.dy2 / 1024;
158
+ const cell = (v) => {
159
+ const whole = Math.max(0, Math.min(65535, Math.floor(v)));
160
+ return [whole, Math.max(0, Math.min(1023, Math.round((v - whole) * 1024)))];
161
+ };
162
+ const [col1, dx1] = cell(from(i32(d, 0), x1, x2, g.x, g.w));
163
+ const [row1, dy1] = cell(from(i32(d, 4), y1, y2, g.y, g.h));
164
+ const [col2, dx2] = cell(from(i32(d, 8), x1, x2, g.x, g.w));
165
+ const [row2, dy2] = cell(from(i32(d, 12), y1, y2, g.y, g.h));
166
+ return {
167
+ col1,
168
+ dx1,
169
+ row1,
170
+ dy1,
171
+ col2,
172
+ dx2,
173
+ row2,
174
+ dy2
175
+ };
113
176
  }
114
177
  function optColor(d, count, wantId) {
115
178
  const v = optProperty(d, count, wantId);
@@ -179,6 +242,9 @@ function matches(d, off, magic) {
179
242
  for (let i = 0; i < magic.length; i++) if (d[off + i] !== magic[i]) return false;
180
243
  return true;
181
244
  }
245
+ function i32(d, off) {
246
+ return u32(d, off) | 0;
247
+ }
182
248
  function u16(d, off) {
183
249
  return (d[off] ?? 0) | (d[off + 1] ?? 0) << 8;
184
250
  }
@@ -17,6 +17,23 @@ export interface FontResource {
17
17
  /** Glyphs collected by the usage walk — the emit phase subsets to these. */
18
18
  readonly gids: ReadonlySet<number>;
19
19
  }
20
+ /**
21
+ * The face a run asked for and the registry could not give — what the page has
22
+ * to draw itself. A font set carries only `regular` by contract, so a caller
23
+ * who supplies one file still asks for bold headings and italic quotes.
24
+ */
25
+ export interface SyntheticFace {
26
+ /** No bold cut: the glyphs are stroked as well as filled. */
27
+ readonly bold?: true;
28
+ /** No italic cut: the glyphs are sheared. */
29
+ readonly italic?: true;
30
+ /**
31
+ * No condensed cut: the glyphs are set at this fraction of their advance
32
+ * (`Arial Narrow` is 82 % of Arial). Layout measures through it too — the
33
+ * squeeze decides where the line breaks, not just how it looks.
34
+ */
35
+ readonly widthScale?: number;
36
+ }
20
37
  /** A run of text on a {@link Line}: the string plus its resolved font, size, width and link/tagging state. */
21
38
  export interface TextToken {
22
39
  readonly kind: 'text';
@@ -61,6 +78,8 @@ export interface TextToken {
61
78
  readonly highlight?: true;
62
79
  readonly resolvedRun: ResolvedRunProperties;
63
80
  readonly font: FontResource;
81
+ /** What the chosen face lacks and the emitter must fake (see {@link SyntheticFace}). */
82
+ readonly synthetic?: SyntheticFace;
64
83
  readonly fontSizePt: number;
65
84
  /**
66
85
  * §17.3.2.42 / §18.4.2 `vertAlign` — how far off the baseline this token
@@ -205,6 +224,19 @@ export interface MetafileDrawing {
205
224
  readonly y: number;
206
225
  readonly rotationDeg?: number;
207
226
  }>;
227
+ /**
228
+ * MS-EMF §2.3.1 — the bitmaps the picture blits into itself, each already a
229
+ * page resource of its own. `x`/`y` are the box's BOTTOM-left corner, in the
230
+ * same local frame as the shapes.
231
+ */
232
+ readonly images?: ReadonlyArray<{
233
+ readonly resourceName: string;
234
+ readonly x: number;
235
+ readonly y: number;
236
+ readonly width: number;
237
+ readonly height: number;
238
+ readonly rotationDeg?: number;
239
+ }>;
208
240
  }
209
241
  export interface ImageResource {
210
242
  readonly resourceName: string;
@@ -220,6 +252,13 @@ export interface ImageResource {
220
252
  * turns these into the same primitives a chart is made of.
221
253
  */
222
254
  readonly metafile?: MetaPicture;
255
+ /**
256
+ * The resource name of each bitmap `metafile` blits, in the order its
257
+ * primitives hold them. A metafile draws its own pictures, and each is an
258
+ * ordinary image resource — entered under a key of its own, so the emitters
259
+ * embed and name it without knowing where it came from.
260
+ */
261
+ readonly metafileImages?: ReadonlyArray<string>;
223
262
  }
224
263
  /**
225
264
  * The fields every {@link PageItem} shares (ir-design §6, frozen at stage 6.4):
@@ -1,6 +1,6 @@
1
1
  import { BodyElement, Chart, Comment, DocumentInfo, Numbering, Section, SectionProperties, ShapeFill, StyleSheet } from '../core/document-model/index.js';
2
2
  import { FontRegistry } from '../core/font/index.js';
3
- import { FamilyKey } from '../core/fonts/index.js';
3
+ import { SubstituteKey } from '../core/fonts/index.js';
4
4
  import { Hyphenator } from '../core/hyphenation/index.js';
5
5
  import { Pt, ResourceStore } from '../core/ir/index.js';
6
6
  import { LaidOutDocument, PageItem } from './page-doc.js';
@@ -53,7 +53,7 @@ export interface StyledRenderOptions {
53
53
  * run uses `registry`), byte-identical to before. `registry` remains the
54
54
  * guaranteed fallback for math/chart/default glyphs and any missing family.
55
55
  */
56
- readonly registriesByFamily?: ReadonlyMap<FamilyKey, FontRegistry>;
56
+ readonly registriesByFamily?: ReadonlyMap<SubstituteKey, FontRegistry>;
57
57
  /**
58
58
  * The document's OWN embedded fonts (`word/fonts/*.odttf`, de-obfuscated),
59
59
  * keyed by normalized font name. A run whose `w:ascii` matches one renders with