reamkit 1.22.0 → 1.24.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 (101) hide show
  1. package/dist/esm/core/bmp.d.ts +33 -0
  2. package/dist/esm/core/bmp.js +276 -0
  3. package/dist/esm/core/converter/ream.d.ts +16 -0
  4. package/dist/esm/core/converter/ream.js +59 -9
  5. package/dist/esm/core/document-model/types.d.ts +55 -0
  6. package/dist/esm/core/drawingml/chart-geometry.js +14 -7
  7. package/dist/esm/core/drawingml/colors.d.ts +4 -2
  8. package/dist/esm/core/drawingml/colors.js +15 -0
  9. package/dist/esm/core/drawingml/diagram/colors.d.ts +52 -0
  10. package/dist/esm/core/drawingml/diagram/colors.js +125 -0
  11. package/dist/esm/core/drawingml/diagram/data-model.d.ts +47 -0
  12. package/dist/esm/core/drawingml/diagram/data-model.js +119 -0
  13. package/dist/esm/core/drawingml/diagram/layout-engine.d.ts +46 -0
  14. package/dist/esm/core/drawingml/diagram/layout-engine.js +948 -0
  15. package/dist/esm/core/drawingml/diagram/run.d.ts +37 -0
  16. package/dist/esm/core/drawingml/diagram/run.js +50 -0
  17. package/dist/esm/core/drawingml/diagram/to-drawing.d.ts +16 -0
  18. package/dist/esm/core/drawingml/diagram/to-drawing.js +86 -0
  19. package/dist/esm/core/drawingml/preset-geometry.js +116 -6
  20. package/dist/esm/core/drawingml/text-warp.d.ts +58 -0
  21. package/dist/esm/core/drawingml/text-warp.js +355 -0
  22. package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
  23. package/dist/esm/core/drawingml/theme-parser.js +73 -4
  24. package/dist/esm/core/font/measure.d.ts +12 -0
  25. package/dist/esm/core/font/measure.js +36 -0
  26. package/dist/esm/core/fonts/families.d.ts +10 -0
  27. package/dist/esm/core/fonts/families.js +44 -0
  28. package/dist/esm/core/fonts/index.d.ts +3 -2
  29. package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
  30. package/dist/esm/core/fonts/remote-fonts.js +114 -8
  31. package/dist/esm/core/fonts/scripts.d.ts +26 -0
  32. package/dist/esm/core/fonts/scripts.js +177 -0
  33. package/dist/esm/core/images.d.ts +30 -2
  34. package/dist/esm/core/images.js +121 -5
  35. package/dist/esm/core/metafile/blit.d.ts +33 -0
  36. package/dist/esm/core/metafile/blit.js +67 -0
  37. package/dist/esm/core/metafile/dib.d.ts +61 -0
  38. package/dist/esm/core/metafile/dib.js +205 -0
  39. package/dist/esm/core/metafile/emf.js +280 -38
  40. package/dist/esm/core/metafile/picture.d.ts +61 -1
  41. package/dist/esm/core/metafile/picture.js +70 -1
  42. package/dist/esm/core/metafile/wmf.js +202 -13
  43. package/dist/esm/core/ole/escher-blip.d.ts +12 -0
  44. package/dist/esm/core/ole/escher-blip.js +98 -0
  45. package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
  46. package/dist/esm/excel/print-model.js +5 -3
  47. package/dist/esm/excel/sheet-drawing.js +1 -1
  48. package/dist/esm/excel/sheet-to-flow.js +16 -2
  49. package/dist/esm/excel/styles-parser.js +1 -1
  50. package/dist/esm/excel/xls/biff-reader.js +53 -18
  51. package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
  52. package/dist/esm/excel/xls/biff-styles.js +9 -7
  53. package/dist/esm/excel/xls/escher.js +90 -24
  54. package/dist/esm/html/html-writer.js +2 -1
  55. package/dist/esm/layout/page-doc.d.ts +74 -0
  56. package/dist/esm/layout/page-doc.js +14 -1
  57. package/dist/esm/layout/styled-layout.d.ts +2 -2
  58. package/dist/esm/layout/styled-layout.js +475 -48
  59. package/dist/esm/pdf/shading.js +8 -6
  60. package/dist/esm/pdf/styled-page-emitter.js +77 -5
  61. package/dist/esm/pdf/vector-graphics.js +1 -1
  62. package/dist/esm/pdf-reader/image-decode.js +1 -1
  63. package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
  64. package/dist/esm/pptx/embedded-fonts.js +104 -0
  65. package/dist/esm/pptx/placeholder-cascade.d.ts +73 -6
  66. package/dist/esm/pptx/placeholder-cascade.js +114 -18
  67. package/dist/esm/pptx/ppt/ppt-reader.js +191 -13
  68. package/dist/esm/pptx/ppt/ppt-text.d.ts +107 -1
  69. package/dist/esm/pptx/ppt/ppt-text.js +873 -144
  70. package/dist/esm/pptx/pptx-reader.d.ts +8 -0
  71. package/dist/esm/pptx/pptx-reader.js +117 -15
  72. package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
  73. package/dist/esm/pptx/preset-table-styles.js +27 -0
  74. package/dist/esm/pptx/slide-parser.d.ts +11 -2
  75. package/dist/esm/pptx/slide-parser.js +203 -44
  76. package/dist/esm/pptx/sp-helpers.d.ts +9 -4
  77. package/dist/esm/pptx/sp-helpers.js +48 -9
  78. package/dist/esm/pptx/table-style.d.ts +16 -1
  79. package/dist/esm/pptx/table-style.js +104 -10
  80. package/dist/esm/svg/svg-writer.js +1 -0
  81. package/dist/esm/word/document-parser.d.ts +11 -2
  82. package/dist/esm/word/document-parser.js +10 -7
  83. package/dist/esm/word/docx-reader.js +32 -16
  84. package/dist/esm/word/docx-to-pdf.d.ts +8 -7
  85. package/dist/esm/word/docx-to-pdf.js +25 -7
  86. package/dist/esm/word/docx-writer.js +4 -0
  87. package/dist/esm/word/drawing-parser.d.ts +20 -0
  88. package/dist/esm/word/drawing-parser.js +67 -22
  89. package/dist/esm/word/numbering-parser.d.ts +2 -1
  90. package/dist/esm/word/numbering-parser.js +6 -6
  91. package/dist/esm/word/paragraph-properties.d.ts +2 -1
  92. package/dist/esm/word/paragraph-properties.js +2 -2
  93. package/dist/esm/word/run-properties.d.ts +5 -2
  94. package/dist/esm/word/run-properties.js +13 -8
  95. package/dist/esm/word/styles-parser.d.ts +2 -1
  96. package/dist/esm/word/styles-parser.js +12 -12
  97. package/dist/esm/word/table-parser.js +6 -3
  98. package/dist/esm/word/theme-fonts.d.ts +10 -0
  99. package/dist/esm/word/theme-fonts.js +28 -0
  100. package/package.json +1 -1
  101. /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
@@ -1,5 +1,7 @@
1
1
  import { PathBuilder } from "../vector.js";
2
- import { cloneDc, colorRef, newDeviceContext } from "./picture.js";
2
+ import { clippedAway, cloneDc, colorRef, intersectClip, newDeviceContext, primBounds } from "./picture.js";
3
+ import { cropDib, readDib } from "./dib.js";
4
+ import { makeBlitter } from "./blit.js";
3
5
  import { fromSymbolFont, symbolGeometryOf, symbolOutline } from "./symbol-fonts.js";
4
6
  import { ellipseSegments } from "./emf.js";
5
7
  //#region src/core/metafile/wmf.ts
@@ -14,9 +16,6 @@ function isWmf(bytes) {
14
16
  return (type === 1 || type === 2) && headerWords === 9;
15
17
  }
16
18
  var RECORD_NAMES = new Map([
17
- [2368, "bitmap"],
18
- [2881, "bitmap"],
19
- [3907, "bitmap"],
20
19
  [2338, "pie"],
21
20
  [2096, "chord"],
22
21
  [2071, "arc"],
@@ -61,6 +60,17 @@ function readWmf(bytes) {
61
60
  cx: 0,
62
61
  cy: 0
63
62
  };
63
+ let origin;
64
+ const emit = (prim) => {
65
+ if (clippedAway(dc, primBounds(prim))) return;
66
+ origin ??= {
67
+ x: win.x,
68
+ y: win.y
69
+ };
70
+ const dx = origin.x - win.x;
71
+ const dy = origin.y - win.y;
72
+ prims.push(dx === 0 && dy === 0 ? prim : shiftPrim(prim, dx, dy));
73
+ };
64
74
  const strokeOf = () => {
65
75
  if (dc.pen.style === "none") return void 0;
66
76
  const w = Math.max(1, dc.pen.widthLu);
@@ -79,7 +89,7 @@ function readWmf(bytes) {
79
89
  const st = stroke ? strokeOf() : void 0;
80
90
  const fillHex = fill && !dc.brush.hollow ? dc.brush.colorHex : void 0;
81
91
  if (fillHex === void 0 && !st) return;
82
- prims.push({
92
+ emit({
83
93
  kind: "path",
84
94
  paths: [path],
85
95
  ...fillHex !== void 0 ? { fillColorHex: fillHex } : {},
@@ -87,6 +97,27 @@ function readWmf(bytes) {
87
97
  });
88
98
  };
89
99
  const rectSegments = (l, t, r, b) => new PathBuilder().moveTo(l, t).lineTo(r, t).lineTo(r, b).lineTo(l, b).close().build().segments;
100
+ const blitter = makeBlitter(emit);
101
+ /**
102
+ * §2.3.1 — one blit record: the packed bitmap the record ends with, into the
103
+ * destination rectangle its fields name. A WMF's coordinates are its own
104
+ * logical units, which is the frame the primitives are already in.
105
+ */
106
+ const blit = (o) => {
107
+ const dib = readDib(bytes, off + o.dibAt);
108
+ if (!dib) {
109
+ skipped.add("bitmap");
110
+ return;
111
+ }
112
+ const s = o.src;
113
+ const part = s.x !== 0 || s.y !== 0 || s.w !== dib.width || s.h !== dib.height ? cropDib(dib, s.x, dib.bottomUp === true ? dib.height - s.y - s.h : s.y, s.w, s.h) : dib;
114
+ blitter.blit(part, {
115
+ x: Math.min(o.dest.x, o.dest.x + o.dest.w),
116
+ y: Math.min(o.dest.y, o.dest.y + o.dest.h),
117
+ width: Math.abs(o.dest.w),
118
+ height: Math.abs(o.dest.h)
119
+ }, o.rop);
120
+ };
90
121
  let off = placeable ? 22 : 0;
91
122
  off += 18;
92
123
  let guard = 0;
@@ -115,6 +146,17 @@ function readWmf(bytes) {
115
146
  cy: p(0)
116
147
  };
117
148
  break;
149
+ case 1046:
150
+ dc = {
151
+ ...dc,
152
+ clip: intersectClip(dc, {
153
+ bottom: p(0),
154
+ right: p(1),
155
+ top: p(2),
156
+ left: p(3)
157
+ })
158
+ };
159
+ break;
118
160
  case 30:
119
161
  stack.push(cloneDc(dc));
120
162
  break;
@@ -135,6 +177,12 @@ function readWmf(bytes) {
135
177
  case 496:
136
178
  objects[pu(0)] = void 0;
137
179
  break;
180
+ case 247:
181
+ case 322:
182
+ case 505:
183
+ case 1791:
184
+ put({ kind: "other" });
185
+ break;
138
186
  case 762:
139
187
  put({
140
188
  kind: "pen",
@@ -223,6 +271,79 @@ function readWmf(bytes) {
223
271
  dc.brush = brush;
224
272
  }
225
273
  break;
274
+ case 2368:
275
+ case 2881:
276
+ case 3907:
277
+ {
278
+ const rop = p32(0);
279
+ const f = fn === 2368 ? {
280
+ dib: 22,
281
+ srcH: 4,
282
+ srcW: 5,
283
+ ySrc: 2,
284
+ xSrc: 3,
285
+ h: 4,
286
+ w: 5,
287
+ y: 6,
288
+ x: 7
289
+ } : fn === 2881 ? {
290
+ dib: 26,
291
+ srcH: 2,
292
+ srcW: 3,
293
+ ySrc: 4,
294
+ xSrc: 5,
295
+ h: 6,
296
+ w: 7,
297
+ y: 8,
298
+ x: 9
299
+ } : {
300
+ dib: 28,
301
+ srcH: 3,
302
+ srcW: 4,
303
+ ySrc: 5,
304
+ xSrc: 6,
305
+ h: 7,
306
+ w: 8,
307
+ y: 9,
308
+ x: 10
309
+ };
310
+ if (f.dib + 12 > size * 2) {
311
+ const hex = rop === 66 ? "000000" : rop === 16711778 ? "FFFFFF" : void 0;
312
+ const brush = dc.brush;
313
+ if (hex !== void 0) dc.brush = {
314
+ kind: "brush",
315
+ colorHex: hex,
316
+ hollow: false
317
+ };
318
+ const shift = fn === 2368 ? 1 : 0;
319
+ const [h, w, y, x] = [
320
+ p(f.h + shift),
321
+ p(f.w + shift),
322
+ p(f.y + shift),
323
+ p(f.x + shift)
324
+ ];
325
+ paint(rectSegments(x, y, x + w, y + h), true, false);
326
+ dc.brush = brush;
327
+ break;
328
+ }
329
+ blit({
330
+ dibAt: f.dib,
331
+ dest: {
332
+ x: p(f.x),
333
+ y: p(f.y),
334
+ w: p(f.w),
335
+ h: p(f.h)
336
+ },
337
+ src: {
338
+ x: p(f.xSrc),
339
+ y: p(f.ySrc),
340
+ w: p(f.srcW),
341
+ h: p(f.srcH)
342
+ },
343
+ rop
344
+ });
345
+ }
346
+ break;
226
347
  case 804:
227
348
  case 805:
228
349
  {
@@ -251,7 +372,7 @@ function readWmf(bytes) {
251
372
  const count = pu(0);
252
373
  const text = readString(bytes, off + 8, count, false);
253
374
  const words = count + 1 >> 1;
254
- pushText(prims, dc, text, p(1 + words + 1), p(1 + words));
375
+ pushText(emit, dc, text, p(1 + words + 1), p(1 + words));
255
376
  }
256
377
  break;
257
378
  case 2610:
@@ -261,7 +382,7 @@ function readWmf(bytes) {
261
382
  const count = pu(2);
262
383
  const hasRect = (pu(3) & 6) !== 0;
263
384
  const text = readString(bytes, off + 6 + (4 + (hasRect ? 4 : 0)) * 2, count, false);
264
- pushText(prims, dc, text, x, y);
385
+ pushText(emit, dc, text, x, y);
265
386
  }
266
387
  break;
267
388
  default:
@@ -279,24 +400,25 @@ function readWmf(bytes) {
279
400
  right: win.x + (win.cx || 1e3),
280
401
  bottom: win.y + (win.cy || 1e3)
281
402
  };
403
+ const flipped = win.cy < 0 ? prims.map((p) => mirrorPrimY(p, box.top + box.bottom)) : prims;
282
404
  return {
283
- left: box.left,
284
- top: box.top,
405
+ left: Math.min(box.left, box.right),
406
+ top: Math.min(box.top, box.bottom),
285
407
  width: Math.max(1, Math.abs(box.right - box.left)),
286
408
  height: Math.max(1, Math.abs(box.bottom - box.top)),
287
- prims,
409
+ prims: flipped,
288
410
  skipped: [...skipped]
289
411
  };
290
412
  }
291
- function pushText(prims, dc, text, x, y) {
413
+ function pushText(emit, dc, text, x, y) {
292
414
  if (text.trim() === "") return;
293
415
  const em = Math.abs(dc.font?.heightLu ?? 12);
294
416
  const drawn = symbolPrims(text, dc, x, y, em);
295
417
  if (drawn) {
296
- prims.push(...drawn);
418
+ for (const prim of drawn) emit(prim);
297
419
  return;
298
420
  }
299
- prims.push({
421
+ emit({
300
422
  kind: "text",
301
423
  text: fromSymbolFont(text, dc.font?.family),
302
424
  x,
@@ -311,6 +433,73 @@ function pushText(prims, dc, text, x, y) {
311
433
  ...dc.font?.escapement ? { escapement: dc.font.escapement } : {}
312
434
  });
313
435
  }
436
+ function shiftPrim(prim, dx, dy) {
437
+ if (prim.kind === "text") return {
438
+ ...prim,
439
+ x: prim.x + dx,
440
+ y: prim.y + dy
441
+ };
442
+ if (prim.kind === "image") return {
443
+ ...prim,
444
+ x: prim.x + dx,
445
+ y: prim.y + dy
446
+ };
447
+ return {
448
+ ...prim,
449
+ paths: prim.paths.map((path) => ({
450
+ ...path,
451
+ segments: path.segments.map((sg) => "x" in sg ? {
452
+ ...sg,
453
+ x: sg.x + dx,
454
+ y: sg.y + dy,
455
+ ..."x1" in sg ? {
456
+ x1: sg.x1 + dx,
457
+ y1: sg.y1 + dy
458
+ } : {},
459
+ ..."x2" in sg ? {
460
+ x2: sg.x2 + dx,
461
+ y2: sg.y2 + dy
462
+ } : {}
463
+ } : sg)
464
+ }))
465
+ };
466
+ }
467
+ /**
468
+ * A primitive mirrored about a horizontal axis, for a window whose y grows UP.
469
+ *
470
+ * Only the geometry turns over. A text run's reference point names a corner of
471
+ * the cell IN DEVICE SPACE — GDI never draws the glyphs themselves upside down —
472
+ * so the point moves and the alignment flags stay as they are. An image states
473
+ * the TOP of its destination rectangle, which after the mirror is where its
474
+ * bottom used to be.
475
+ *
476
+ * @param prim The primitive, in the metafile's own logical units.
477
+ * @param twiceAxis Twice the y the mirror runs along, so `y' = twiceAxis - y`.
478
+ * @returns The primitive with its y coordinates turned over.
479
+ */
480
+ function mirrorPrimY(prim, twiceAxis) {
481
+ const at = (y) => twiceAxis - y;
482
+ if (prim.kind === "text") return {
483
+ ...prim,
484
+ y: at(prim.y)
485
+ };
486
+ if (prim.kind === "image") return {
487
+ ...prim,
488
+ y: at(prim.y + prim.height)
489
+ };
490
+ return {
491
+ ...prim,
492
+ paths: prim.paths.map((path) => ({
493
+ ...path,
494
+ segments: path.segments.map((sg) => "x" in sg ? {
495
+ ...sg,
496
+ y: at(sg.y),
497
+ ..."y1" in sg ? { y1: at(sg.y1) } : {},
498
+ ..."y2" in sg ? { y2: at(sg.y2) } : {}
499
+ } : sg)
500
+ }))
501
+ };
502
+ }
314
503
  function penStyle(style) {
315
504
  switch (style & 15) {
316
505
  case 1: return "dash";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The picture bytes inside one Escher BLIP record — a raster as it stands, or a
3
+ * metafile unpacked out of its header.
4
+ *
5
+ * @param type The blip record type (`0xF01A`…`0xF02A`).
6
+ * @param instance The record's `recInstance`, which says how many UIDs precede
7
+ * the payload.
8
+ * @param data The record's body, without the 8-byte header.
9
+ * @returns The bytes to hand the renderer, or `undefined` when the blip holds
10
+ * nothing this can read.
11
+ */
12
+ export declare function readEscherBlip(type: number, instance: number, data: Uint8Array): Uint8Array | undefined;
@@ -0,0 +1,98 @@
1
+ import { dibToBmp } from "../bmp.js";
2
+ import { unzlibSync } from "fflate";
3
+ //#region src/core/ole/escher-blip.ts
4
+ var BLIP_EMF = 61466;
5
+ var BLIP_WMF = 61467;
6
+ var BLIP_PICT = 61468;
7
+ var BLIP_JPEG = 61469;
8
+ var BLIP_PNG = 61470;
9
+ var BLIP_DIB = 61471;
10
+ var BLIP_TIFF = 61481;
11
+ var BLIP_JPEG_CMYK = 61482;
12
+ var METAFILE_HEADER_BYTES = 34;
13
+ var COMPRESSION_DEFLATE = 0;
14
+ var TWO_UID_INSTANCES = new Set([
15
+ 981,
16
+ 535,
17
+ 1347,
18
+ 1761,
19
+ 1763,
20
+ 1961,
21
+ 1765,
22
+ 481
23
+ ]);
24
+ /** The signatures of the rasters a blip may hold, for the scan fallback. */
25
+ var RASTER_MAGICS = [
26
+ [
27
+ 137,
28
+ 80,
29
+ 78,
30
+ 71
31
+ ],
32
+ [
33
+ 255,
34
+ 216,
35
+ 255
36
+ ],
37
+ [
38
+ 71,
39
+ 73,
40
+ 70,
41
+ 56
42
+ ],
43
+ [66, 77]
44
+ ];
45
+ /**
46
+ * The picture bytes inside one Escher BLIP record — a raster as it stands, or a
47
+ * metafile unpacked out of its header.
48
+ *
49
+ * @param type The blip record type (`0xF01A`…`0xF02A`).
50
+ * @param instance The record's `recInstance`, which says how many UIDs precede
51
+ * the payload.
52
+ * @param data The record's body, without the 8-byte header.
53
+ * @returns The bytes to hand the renderer, or `undefined` when the blip holds
54
+ * nothing this can read.
55
+ */
56
+ function readEscherBlip(type, instance, data) {
57
+ if (type === BLIP_EMF || type === BLIP_WMF || type === BLIP_PICT) return readMetafileBlip(instance, data);
58
+ if (type === BLIP_DIB) return readDibBlip(instance, data) ?? scanRaster(data);
59
+ if (type === BLIP_JPEG || type === BLIP_PNG || type === BLIP_TIFF || type === BLIP_JPEG_CMYK) return scanRaster(data);
60
+ return scanRaster(data);
61
+ }
62
+ function readDibBlip(instance, data) {
63
+ const uidBytes = TWO_UID_INSTANCES.has(instance) ? 32 : 16;
64
+ for (const at of [uidBytes + 1, uidBytes]) {
65
+ if (data.length <= at) continue;
66
+ const bmp = dibToBmp(data.subarray(at));
67
+ if (bmp) return bmp;
68
+ }
69
+ }
70
+ function readMetafileBlip(instance, data) {
71
+ const uidBytes = TWO_UID_INSTANCES.has(instance) ? 32 : 16;
72
+ const head = uidBytes + METAFILE_HEADER_BYTES;
73
+ if (data.length < head) return void 0;
74
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
75
+ const uncompressed = view.getUint32(uidBytes, true);
76
+ const compressed = view.getUint32(uidBytes + 24, true);
77
+ const compression = data[uidBytes + 32];
78
+ const payload = data.subarray(head, Math.min(data.length, head + (compressed || Infinity)));
79
+ if (payload.length === 0) return void 0;
80
+ if (compression !== COMPRESSION_DEFLATE) return payload;
81
+ try {
82
+ const out = unzlibSync(payload, uncompressed > 0 ? { out: new Uint8Array(uncompressed) } : {});
83
+ return out.length > 0 ? out : void 0;
84
+ } catch {
85
+ return;
86
+ }
87
+ }
88
+ function scanRaster(data) {
89
+ const limit = Math.min(data.length, 80);
90
+ for (let off = 0; off < limit; off++) for (const magic of RASTER_MAGICS) if (matches(data, off, magic)) return data.subarray(off);
91
+ }
92
+ function matches(d, off, magic) {
93
+ if (off + magic.length > d.length) return false;
94
+ for (let i = 0; i < magic.length; i++) if (d[off + i] !== magic[i]) return false;
95
+ return true;
96
+ }
97
+ //#endregion
98
+ export { readEscherBlip };
@@ -1,5 +1,5 @@
1
1
  import { zlibSync } from "fflate";
2
- //#region src/pdf-reader/png-encode.ts
2
+ //#region src/core/png-encode.ts
3
3
  var COLOR_TYPE = {
4
4
  gray: 0,
5
5
  rgb: 2,
@@ -101,7 +101,8 @@ var DIGIT_EM = [
101
101
  [/^(arial|helvetica|liberation sans|arimo|arial unicode ms)$/i, 1139 / 2048],
102
102
  [/^(times new roman|liberation serif|tinos)$/i, 1024 / 2048],
103
103
  [/^(tahoma)$/i, 1118 / 2048],
104
- [/^(verdana|dejavu sans)$/i, 1303 / 2048]
104
+ [/^(verdana|dejavu sans)$/i, 1303 / 2048],
105
+ [/* @__PURE__ */ new RegExp("^(新細明體|細明體|pmingliu|mingliu|標楷體|dfkai-sb|宋体|新宋体|simsun|nsimsun|黑体|simhei|微软雅黑|microsoft yahei|微軟正黑體|microsoft jhenghei|MS [P]?明朝|MS [P]?ゴシック|ms [p]?mincho|ms [p]?gothic|meiryo|メイリオ|游ゴシック|yu gothic|굴림체?|gulim(che)?|돋움체?|dotum(che)?|바탕체?|batang(che)?|맑은 고딕|malgun gothic)$", "iu"), 1024 / 2048]
105
106
  ];
106
107
  /**
107
108
  * §18.3.1.13 — the Maximum Digit Width, in twips, of the normal style's font.
@@ -1021,6 +1022,7 @@ function runPropsFromXf(xf, styles) {
1021
1022
  if (font.strike) props.strike = true;
1022
1023
  if (font.sizePt !== void 0) props.fontSizePt = halfPtToPt(Math.round(font.sizePt * 2));
1023
1024
  if (font.colorHex) props.colorHex = font.colorHex;
1025
+ if (font.name) props.fontFamily = { ascii: font.name };
1024
1026
  return props;
1025
1027
  }
1026
1028
  function stackedVerticalContent(text, runProps, href) {
@@ -1120,8 +1122,8 @@ function shadingFromXf(xf, styles) {
1120
1122
  if (!pattern || pattern === "none") return void 0;
1121
1123
  if (pattern === "solid") return fill.fgColorHex ? { colorHex: fill.fgColorHex } : void 0;
1122
1124
  const density = PATTERN_DENSITY[pattern];
1123
- if (density === void 0 || !fill.fgColorHex) return void 0;
1124
- const blended = blendHex(fill.fgColorHex, fill.bgColorHex ?? "FFFFFF", density);
1125
+ if (density === void 0) return void 0;
1126
+ const blended = blendHex(fill.fgColorHex ?? "000000", fill.bgColorHex ?? "FFFFFF", density);
1125
1127
  return blended ? { colorHex: blended } : void 0;
1126
1128
  }
1127
1129
  function blendHex(fg, bg, fraction) {
@@ -162,7 +162,7 @@ function makeColWidthPt(ws) {
162
162
  return (col) => {
163
163
  for (const c of ws.columns) if (col >= c.min - 1 && col <= c.max - 1) return widthPt(c.widthChars);
164
164
  if (ws.defaultColWidthChars !== void 0) return widthPt(ws.defaultColWidthChars);
165
- if (ws.baseColWidthChars !== void 0) return (columnTwips(ws.baseColWidthChars, 105) + 75) / TWIPS_PER_PT;
165
+ if (ws.baseColWidthChars !== void 0) return (columnTwips(ws.baseColWidthChars, 105) + 150) / TWIPS_PER_PT;
166
166
  return 960 / TWIPS_PER_PT;
167
167
  };
168
168
  }
@@ -401,8 +401,16 @@ function withDrawingsByBand(drawings, gridBody, lefts) {
401
401
  const byBand = lefts.map(() => []);
402
402
  for (const el of drawings) {
403
403
  const x = floatLeftPt(el);
404
- const band = x === void 0 ? 0 : bandOf(x);
405
- byBand[band].push(x === void 0 ? el : shiftFloatLeft(el, lefts[band]));
404
+ if (x === void 0) {
405
+ byBand[0].push(el);
406
+ continue;
407
+ }
408
+ const start = bandOf(x);
409
+ const right = x + (floatWidthPt(el) ?? 0);
410
+ for (let band = start; band < lefts.length; band++) {
411
+ if (band > start && right <= lefts[band]) break;
412
+ byBand[band].push(shiftFloatLeft(el, lefts[band]));
413
+ }
406
414
  }
407
415
  const out = [];
408
416
  let seen = 0;
@@ -416,6 +424,12 @@ function withDrawingsByBand(drawings, gridBody, lefts) {
416
424
  function floatLeftPt(el) {
417
425
  return (el.kind === "chart" ? el.chart.float : el.kind === "image" ? el.image.float : el.kind === "shape" ? el.shape.float : void 0)?.posH?.offsetPt;
418
426
  }
427
+ /** A float's own width, for the block kinds a sheet anchors. */
428
+ function floatWidthPt(el) {
429
+ if (el.kind === "chart") return el.chart.width;
430
+ if (el.kind === "image") return el.image.width;
431
+ if (el.kind === "shape") return el.shape.width;
432
+ }
419
433
  /** The same block with its horizontal anchor measured from `by` points later. */
420
434
  function shiftFloatLeft(el, by) {
421
435
  if (by === 0) return el;
@@ -1,7 +1,7 @@
1
1
  import { INDEXED_COLORS } from "../core/indexed-colors.js";
2
2
  import { applyColorMods } from "../core/drawingml/colors.js";
3
- import { resolveInternalEntities } from "../core/opc/xml-entities.js";
4
3
  import { resolveAlternateContent } from "../core/opc/alternate-content.js";
4
+ import { resolveInternalEntities } from "../core/opc/xml-entities.js";
5
5
  import { XMLParser } from "fast-xml-parser";
6
6
  //#region src/excel/styles-parser.ts
7
7
  var decoder = new TextDecoder("utf-8");
@@ -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 } : {},