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.
- package/dist/esm/core/converter/ream.d.ts +16 -0
- package/dist/esm/core/converter/ream.js +59 -9
- package/dist/esm/core/document-model/types.d.ts +18 -0
- package/dist/esm/core/drawingml/chart-geometry.js +11 -5
- package/dist/esm/core/drawingml/colors.d.ts +4 -2
- package/dist/esm/core/drawingml/colors.js +15 -0
- package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
- package/dist/esm/core/drawingml/theme-parser.js +64 -1
- package/dist/esm/core/fonts/families.d.ts +10 -0
- package/dist/esm/core/fonts/families.js +44 -0
- package/dist/esm/core/fonts/index.d.ts +3 -2
- package/dist/esm/core/fonts/remote-fonts.d.ts +50 -0
- package/dist/esm/core/fonts/remote-fonts.js +114 -8
- package/dist/esm/core/fonts/scripts.d.ts +26 -0
- package/dist/esm/core/fonts/scripts.js +177 -0
- package/dist/esm/core/metafile/blit.d.ts +33 -0
- package/dist/esm/core/metafile/blit.js +67 -0
- package/dist/esm/core/metafile/dib.d.ts +61 -0
- package/dist/esm/core/metafile/dib.js +205 -0
- package/dist/esm/core/metafile/emf.js +137 -23
- package/dist/esm/core/metafile/picture.d.ts +12 -1
- package/dist/esm/core/metafile/wmf.js +149 -9
- package/dist/esm/core/ole/escher-blip.d.ts +12 -0
- package/dist/esm/core/ole/escher-blip.js +88 -0
- package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
- package/dist/esm/excel/print-model.js +3 -1
- package/dist/esm/excel/styles-parser.js +1 -1
- package/dist/esm/excel/xls/biff-reader.js +53 -18
- package/dist/esm/excel/xls/biff-styles.d.ts +5 -2
- package/dist/esm/excel/xls/biff-styles.js +9 -7
- package/dist/esm/excel/xls/escher.js +90 -24
- package/dist/esm/layout/page-doc.d.ts +39 -0
- package/dist/esm/layout/styled-layout.d.ts +2 -2
- package/dist/esm/layout/styled-layout.js +301 -35
- package/dist/esm/pdf/styled-page-emitter.js +35 -2
- package/dist/esm/pdf-reader/image-decode.js +1 -1
- package/dist/esm/pptx/embedded-fonts.d.ts +31 -0
- package/dist/esm/pptx/embedded-fonts.js +104 -0
- package/dist/esm/pptx/placeholder-cascade.d.ts +73 -6
- package/dist/esm/pptx/placeholder-cascade.js +114 -18
- package/dist/esm/pptx/ppt/ppt-reader.js +120 -10
- package/dist/esm/pptx/ppt/ppt-text.d.ts +66 -1
- package/dist/esm/pptx/ppt/ppt-text.js +576 -137
- package/dist/esm/pptx/pptx-reader.d.ts +8 -0
- package/dist/esm/pptx/pptx-reader.js +27 -5
- package/dist/esm/pptx/preset-table-styles.d.ts +9 -0
- package/dist/esm/pptx/preset-table-styles.js +27 -0
- package/dist/esm/pptx/slide-parser.d.ts +7 -1
- package/dist/esm/pptx/slide-parser.js +106 -33
- package/dist/esm/pptx/sp-helpers.d.ts +2 -1
- package/dist/esm/pptx/sp-helpers.js +3 -2
- package/dist/esm/pptx/table-style.d.ts +9 -1
- package/dist/esm/pptx/table-style.js +49 -7
- package/dist/esm/word/document-parser.d.ts +7 -1
- package/dist/esm/word/document-parser.js +6 -6
- package/dist/esm/word/docx-reader.js +6 -3
- package/dist/esm/word/docx-to-pdf.d.ts +8 -7
- package/dist/esm/word/docx-to-pdf.js +25 -7
- package/dist/esm/word/drawing-parser.js +31 -19
- package/dist/esm/word/numbering-parser.d.ts +2 -1
- package/dist/esm/word/numbering-parser.js +6 -6
- package/dist/esm/word/paragraph-properties.d.ts +2 -1
- package/dist/esm/word/paragraph-properties.js +2 -2
- package/dist/esm/word/run-properties.d.ts +5 -2
- package/dist/esm/word/run-properties.js +13 -8
- package/dist/esm/word/styles-parser.d.ts +2 -1
- package/dist/esm/word/styles-parser.js +12 -12
- package/dist/esm/word/table-parser.js +3 -3
- package/dist/esm/word/theme-fonts.d.ts +10 -0
- package/dist/esm/word/theme-fonts.js +28 -0
- package/package.json +1 -1
- /package/dist/esm/{pdf-reader → core}/png-encode.d.ts +0 -0
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PathBuilder } from "../vector.js";
|
|
2
2
|
import { applyTransform, cloneDc, colorRef, newDeviceContext } from "./picture.js";
|
|
3
|
+
import { cropDib, fadedDib, readDib } from "./dib.js";
|
|
4
|
+
import { makeBlitter } from "./blit.js";
|
|
3
5
|
import { fromSymbolFont } from "./symbol-fonts.js";
|
|
4
6
|
//#region src/core/metafile/emf.ts
|
|
5
7
|
/** Whether the bytes open with an EMF header (MS-EMF §2.3.4.2: type 1 + " EMF"). */
|
|
@@ -21,11 +23,6 @@ var RECORD_NAMES = new Map([
|
|
|
21
23
|
[74, "region paint"],
|
|
22
24
|
[78, "masked blit"],
|
|
23
25
|
[79, "parallelogram blit"],
|
|
24
|
-
[80, "device bitmap"],
|
|
25
|
-
[81, "bitmap"],
|
|
26
|
-
[76, "bitmap"],
|
|
27
|
-
[77, "bitmap"],
|
|
28
|
-
[114, "alpha blit"],
|
|
29
26
|
[116, "transparent blit"],
|
|
30
27
|
[118, "gradient fill"]
|
|
31
28
|
]);
|
|
@@ -74,6 +71,34 @@ function readEmf(bytes) {
|
|
|
74
71
|
};
|
|
75
72
|
let building;
|
|
76
73
|
const open = () => building ?? [];
|
|
74
|
+
const blitter = makeBlitter((prim) => prims.push(prim));
|
|
75
|
+
/**
|
|
76
|
+
* §2.3.1 — one blit record: the source bitmap into the destination
|
|
77
|
+
* rectangle, both stated in the record's own fields. The rectangle is mapped
|
|
78
|
+
* the way every other coordinate here is, so the picture lands in the same
|
|
79
|
+
* device frame as the paths around it.
|
|
80
|
+
*/
|
|
81
|
+
const blit = (o) => {
|
|
82
|
+
const dib = o.cbBmi > 0 ? readDib(bytes, off + o.bmiAt, {
|
|
83
|
+
bitsAt: off + o.bitsAt,
|
|
84
|
+
cbBits: o.cbBits,
|
|
85
|
+
...o.blend?.perPixel === true ? { alpha: true } : {}
|
|
86
|
+
}) : void 0;
|
|
87
|
+
if (!dib) {
|
|
88
|
+
skipped.add("bitmap");
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const s = o.src;
|
|
92
|
+
const part = s && (s.x !== 0 || s.y !== 0 || s.w !== dib.width || s.h !== dib.height) ? cropDib(dib, s.x, o.inBitmap === true && dib.bottomUp === true ? dib.height - s.y - s.h : s.y, s.w, s.h) : dib;
|
|
93
|
+
const a = px(o.dest.x, o.dest.y);
|
|
94
|
+
const b = px(o.dest.x + o.dest.w, o.dest.y + o.dest.h);
|
|
95
|
+
blitter.blit(o.blend && o.blend.alpha < 255 ? fadedDib(part, o.blend.alpha / 255) : part, {
|
|
96
|
+
x: Math.min(a.x, b.x),
|
|
97
|
+
y: Math.min(a.y, b.y),
|
|
98
|
+
width: Math.abs(b.x - a.x),
|
|
99
|
+
height: Math.abs(b.y - a.y)
|
|
100
|
+
}, o.rop);
|
|
101
|
+
};
|
|
77
102
|
const strokeOf = () => {
|
|
78
103
|
if (dc.pen.style === "none") return void 0;
|
|
79
104
|
const w = dc.pen.widthLu <= 1 ? 1 : dc.pen.widthLu * Math.abs(sx());
|
|
@@ -388,25 +413,114 @@ function readEmf(bytes) {
|
|
|
388
413
|
}
|
|
389
414
|
break;
|
|
390
415
|
case 76:
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
416
|
+
case 77: {
|
|
417
|
+
const cbBmiSrc = u(88);
|
|
418
|
+
const rop = u(40);
|
|
419
|
+
const x = at(24);
|
|
420
|
+
const y = at(28);
|
|
421
|
+
const w = at(32);
|
|
422
|
+
const h = at(36);
|
|
423
|
+
if (cbBmiSrc === 0) {
|
|
424
|
+
const hex = rop === 66 ? "000000" : rop === 16711778 ? "FFFFFF" : void 0;
|
|
425
|
+
const brush = dc.brush;
|
|
426
|
+
if (hex !== void 0) dc.brush = {
|
|
427
|
+
kind: "brush",
|
|
428
|
+
colorHex: hex,
|
|
429
|
+
hollow: false
|
|
430
|
+
};
|
|
431
|
+
paint(rectSegments(x, y, x + w, y + h), true, false);
|
|
432
|
+
dc.brush = brush;
|
|
433
|
+
break;
|
|
409
434
|
}
|
|
435
|
+
blit({
|
|
436
|
+
bmiAt: u(84),
|
|
437
|
+
cbBmi: cbBmiSrc,
|
|
438
|
+
bitsAt: u(92),
|
|
439
|
+
cbBits: u(96),
|
|
440
|
+
dest: {
|
|
441
|
+
x,
|
|
442
|
+
y,
|
|
443
|
+
w,
|
|
444
|
+
h
|
|
445
|
+
},
|
|
446
|
+
src: {
|
|
447
|
+
x: at(44),
|
|
448
|
+
y: at(48),
|
|
449
|
+
w: type === 77 ? at(100) : w,
|
|
450
|
+
h: type === 77 ? at(104) : h
|
|
451
|
+
},
|
|
452
|
+
rop
|
|
453
|
+
});
|
|
454
|
+
break;
|
|
455
|
+
}
|
|
456
|
+
case 80:
|
|
457
|
+
blit({
|
|
458
|
+
bmiAt: u(48),
|
|
459
|
+
cbBmi: u(52),
|
|
460
|
+
bitsAt: u(56),
|
|
461
|
+
cbBits: u(60),
|
|
462
|
+
dest: {
|
|
463
|
+
x: at(24),
|
|
464
|
+
y: at(28),
|
|
465
|
+
w: at(40),
|
|
466
|
+
h: at(44)
|
|
467
|
+
},
|
|
468
|
+
src: {
|
|
469
|
+
x: at(32),
|
|
470
|
+
y: at(36),
|
|
471
|
+
w: at(40),
|
|
472
|
+
h: at(44)
|
|
473
|
+
},
|
|
474
|
+
inBitmap: true,
|
|
475
|
+
rop: 13369376
|
|
476
|
+
});
|
|
477
|
+
break;
|
|
478
|
+
case 81:
|
|
479
|
+
blit({
|
|
480
|
+
bmiAt: u(48),
|
|
481
|
+
cbBmi: u(52),
|
|
482
|
+
bitsAt: u(56),
|
|
483
|
+
cbBits: u(60),
|
|
484
|
+
dest: {
|
|
485
|
+
x: at(24),
|
|
486
|
+
y: at(28),
|
|
487
|
+
w: at(72),
|
|
488
|
+
h: at(76)
|
|
489
|
+
},
|
|
490
|
+
src: {
|
|
491
|
+
x: at(32),
|
|
492
|
+
y: at(36),
|
|
493
|
+
w: at(40),
|
|
494
|
+
h: at(44)
|
|
495
|
+
},
|
|
496
|
+
inBitmap: true,
|
|
497
|
+
rop: u(68)
|
|
498
|
+
});
|
|
499
|
+
break;
|
|
500
|
+
case 114:
|
|
501
|
+
blit({
|
|
502
|
+
bmiAt: u(84),
|
|
503
|
+
cbBmi: u(88),
|
|
504
|
+
bitsAt: u(92),
|
|
505
|
+
cbBits: u(96),
|
|
506
|
+
dest: {
|
|
507
|
+
x: at(24),
|
|
508
|
+
y: at(28),
|
|
509
|
+
w: at(32),
|
|
510
|
+
h: at(36)
|
|
511
|
+
},
|
|
512
|
+
src: {
|
|
513
|
+
x: at(44),
|
|
514
|
+
y: at(48),
|
|
515
|
+
w: at(100),
|
|
516
|
+
h: at(104)
|
|
517
|
+
},
|
|
518
|
+
blend: {
|
|
519
|
+
alpha: u(40) >>> 16 & 255,
|
|
520
|
+
perPixel: u(40) >>> 24 === 1
|
|
521
|
+
},
|
|
522
|
+
rop: 13369376
|
|
523
|
+
});
|
|
410
524
|
break;
|
|
411
525
|
default:
|
|
412
526
|
{
|
|
@@ -74,7 +74,18 @@ export interface MetaFont {
|
|
|
74
74
|
readonly italic?: boolean;
|
|
75
75
|
readonly escapement?: number;
|
|
76
76
|
}
|
|
77
|
-
|
|
77
|
+
/**
|
|
78
|
+
* An object the reader does not model — a palette, a region, a pattern brush.
|
|
79
|
+
* It still OCCUPIES a slot in the metafile's object table: handles are indices
|
|
80
|
+
* into that table, so a creation the reader passed over silently shifted every
|
|
81
|
+
* one that followed. 23884's chart selects its coloured pens by handle, and one
|
|
82
|
+
* unrecorded palette put every selection one slot back — on the black pen the
|
|
83
|
+
* pens had displaced.
|
|
84
|
+
*/
|
|
85
|
+
export interface MetaOther {
|
|
86
|
+
readonly kind: 'other';
|
|
87
|
+
}
|
|
88
|
+
export type MetaObject = MetaPen | MetaBrush | MetaFont | MetaOther;
|
|
78
89
|
/** The device context: everything a record draws THROUGH. */
|
|
79
90
|
export interface DeviceContext {
|
|
80
91
|
pen: MetaPen;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { PathBuilder } from "../vector.js";
|
|
2
2
|
import { cloneDc, colorRef, newDeviceContext } 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,16 @@ function readWmf(bytes) {
|
|
|
61
60
|
cx: 0,
|
|
62
61
|
cy: 0
|
|
63
62
|
};
|
|
63
|
+
let origin;
|
|
64
|
+
const emit = (prim) => {
|
|
65
|
+
origin ??= {
|
|
66
|
+
x: win.x,
|
|
67
|
+
y: win.y
|
|
68
|
+
};
|
|
69
|
+
const dx = origin.x - win.x;
|
|
70
|
+
const dy = origin.y - win.y;
|
|
71
|
+
prims.push(dx === 0 && dy === 0 ? prim : shiftPrim(prim, dx, dy));
|
|
72
|
+
};
|
|
64
73
|
const strokeOf = () => {
|
|
65
74
|
if (dc.pen.style === "none") return void 0;
|
|
66
75
|
const w = Math.max(1, dc.pen.widthLu);
|
|
@@ -79,7 +88,7 @@ function readWmf(bytes) {
|
|
|
79
88
|
const st = stroke ? strokeOf() : void 0;
|
|
80
89
|
const fillHex = fill && !dc.brush.hollow ? dc.brush.colorHex : void 0;
|
|
81
90
|
if (fillHex === void 0 && !st) return;
|
|
82
|
-
|
|
91
|
+
emit({
|
|
83
92
|
kind: "path",
|
|
84
93
|
paths: [path],
|
|
85
94
|
...fillHex !== void 0 ? { fillColorHex: fillHex } : {},
|
|
@@ -87,6 +96,27 @@ function readWmf(bytes) {
|
|
|
87
96
|
});
|
|
88
97
|
};
|
|
89
98
|
const rectSegments = (l, t, r, b) => new PathBuilder().moveTo(l, t).lineTo(r, t).lineTo(r, b).lineTo(l, b).close().build().segments;
|
|
99
|
+
const blitter = makeBlitter(emit);
|
|
100
|
+
/**
|
|
101
|
+
* §2.3.1 — one blit record: the packed bitmap the record ends with, into the
|
|
102
|
+
* destination rectangle its fields name. A WMF's coordinates are its own
|
|
103
|
+
* logical units, which is the frame the primitives are already in.
|
|
104
|
+
*/
|
|
105
|
+
const blit = (o) => {
|
|
106
|
+
const dib = readDib(bytes, off + o.dibAt);
|
|
107
|
+
if (!dib) {
|
|
108
|
+
skipped.add("bitmap");
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const s = o.src;
|
|
112
|
+
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;
|
|
113
|
+
blitter.blit(part, {
|
|
114
|
+
x: Math.min(o.dest.x, o.dest.x + o.dest.w),
|
|
115
|
+
y: Math.min(o.dest.y, o.dest.y + o.dest.h),
|
|
116
|
+
width: Math.abs(o.dest.w),
|
|
117
|
+
height: Math.abs(o.dest.h)
|
|
118
|
+
}, o.rop);
|
|
119
|
+
};
|
|
90
120
|
let off = placeable ? 22 : 0;
|
|
91
121
|
off += 18;
|
|
92
122
|
let guard = 0;
|
|
@@ -135,6 +165,12 @@ function readWmf(bytes) {
|
|
|
135
165
|
case 496:
|
|
136
166
|
objects[pu(0)] = void 0;
|
|
137
167
|
break;
|
|
168
|
+
case 247:
|
|
169
|
+
case 322:
|
|
170
|
+
case 505:
|
|
171
|
+
case 1791:
|
|
172
|
+
put({ kind: "other" });
|
|
173
|
+
break;
|
|
138
174
|
case 762:
|
|
139
175
|
put({
|
|
140
176
|
kind: "pen",
|
|
@@ -223,6 +259,79 @@ function readWmf(bytes) {
|
|
|
223
259
|
dc.brush = brush;
|
|
224
260
|
}
|
|
225
261
|
break;
|
|
262
|
+
case 2368:
|
|
263
|
+
case 2881:
|
|
264
|
+
case 3907:
|
|
265
|
+
{
|
|
266
|
+
const rop = p32(0);
|
|
267
|
+
const f = fn === 2368 ? {
|
|
268
|
+
dib: 22,
|
|
269
|
+
srcH: 4,
|
|
270
|
+
srcW: 5,
|
|
271
|
+
ySrc: 2,
|
|
272
|
+
xSrc: 3,
|
|
273
|
+
h: 4,
|
|
274
|
+
w: 5,
|
|
275
|
+
y: 6,
|
|
276
|
+
x: 7
|
|
277
|
+
} : fn === 2881 ? {
|
|
278
|
+
dib: 26,
|
|
279
|
+
srcH: 2,
|
|
280
|
+
srcW: 3,
|
|
281
|
+
ySrc: 4,
|
|
282
|
+
xSrc: 5,
|
|
283
|
+
h: 6,
|
|
284
|
+
w: 7,
|
|
285
|
+
y: 8,
|
|
286
|
+
x: 9
|
|
287
|
+
} : {
|
|
288
|
+
dib: 28,
|
|
289
|
+
srcH: 3,
|
|
290
|
+
srcW: 4,
|
|
291
|
+
ySrc: 5,
|
|
292
|
+
xSrc: 6,
|
|
293
|
+
h: 7,
|
|
294
|
+
w: 8,
|
|
295
|
+
y: 9,
|
|
296
|
+
x: 10
|
|
297
|
+
};
|
|
298
|
+
if (f.dib + 12 > size * 2) {
|
|
299
|
+
const hex = rop === 66 ? "000000" : rop === 16711778 ? "FFFFFF" : void 0;
|
|
300
|
+
const brush = dc.brush;
|
|
301
|
+
if (hex !== void 0) dc.brush = {
|
|
302
|
+
kind: "brush",
|
|
303
|
+
colorHex: hex,
|
|
304
|
+
hollow: false
|
|
305
|
+
};
|
|
306
|
+
const shift = fn === 2368 ? 1 : 0;
|
|
307
|
+
const [h, w, y, x] = [
|
|
308
|
+
p(f.h + shift),
|
|
309
|
+
p(f.w + shift),
|
|
310
|
+
p(f.y + shift),
|
|
311
|
+
p(f.x + shift)
|
|
312
|
+
];
|
|
313
|
+
paint(rectSegments(x, y, x + w, y + h), true, false);
|
|
314
|
+
dc.brush = brush;
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
blit({
|
|
318
|
+
dibAt: f.dib,
|
|
319
|
+
dest: {
|
|
320
|
+
x: p(f.x),
|
|
321
|
+
y: p(f.y),
|
|
322
|
+
w: p(f.w),
|
|
323
|
+
h: p(f.h)
|
|
324
|
+
},
|
|
325
|
+
src: {
|
|
326
|
+
x: p(f.xSrc),
|
|
327
|
+
y: p(f.ySrc),
|
|
328
|
+
w: p(f.srcW),
|
|
329
|
+
h: p(f.srcH)
|
|
330
|
+
},
|
|
331
|
+
rop
|
|
332
|
+
});
|
|
333
|
+
}
|
|
334
|
+
break;
|
|
226
335
|
case 804:
|
|
227
336
|
case 805:
|
|
228
337
|
{
|
|
@@ -251,7 +360,7 @@ function readWmf(bytes) {
|
|
|
251
360
|
const count = pu(0);
|
|
252
361
|
const text = readString(bytes, off + 8, count, false);
|
|
253
362
|
const words = count + 1 >> 1;
|
|
254
|
-
pushText(
|
|
363
|
+
pushText(emit, dc, text, p(1 + words + 1), p(1 + words));
|
|
255
364
|
}
|
|
256
365
|
break;
|
|
257
366
|
case 2610:
|
|
@@ -261,7 +370,7 @@ function readWmf(bytes) {
|
|
|
261
370
|
const count = pu(2);
|
|
262
371
|
const hasRect = (pu(3) & 6) !== 0;
|
|
263
372
|
const text = readString(bytes, off + 6 + (4 + (hasRect ? 4 : 0)) * 2, count, false);
|
|
264
|
-
pushText(
|
|
373
|
+
pushText(emit, dc, text, x, y);
|
|
265
374
|
}
|
|
266
375
|
break;
|
|
267
376
|
default:
|
|
@@ -288,15 +397,15 @@ function readWmf(bytes) {
|
|
|
288
397
|
skipped: [...skipped]
|
|
289
398
|
};
|
|
290
399
|
}
|
|
291
|
-
function pushText(
|
|
400
|
+
function pushText(emit, dc, text, x, y) {
|
|
292
401
|
if (text.trim() === "") return;
|
|
293
402
|
const em = Math.abs(dc.font?.heightLu ?? 12);
|
|
294
403
|
const drawn = symbolPrims(text, dc, x, y, em);
|
|
295
404
|
if (drawn) {
|
|
296
|
-
|
|
405
|
+
for (const prim of drawn) emit(prim);
|
|
297
406
|
return;
|
|
298
407
|
}
|
|
299
|
-
|
|
408
|
+
emit({
|
|
300
409
|
kind: "text",
|
|
301
410
|
text: fromSymbolFont(text, dc.font?.family),
|
|
302
411
|
x,
|
|
@@ -311,6 +420,37 @@ function pushText(prims, dc, text, x, y) {
|
|
|
311
420
|
...dc.font?.escapement ? { escapement: dc.font.escapement } : {}
|
|
312
421
|
});
|
|
313
422
|
}
|
|
423
|
+
function shiftPrim(prim, dx, dy) {
|
|
424
|
+
if (prim.kind === "text") return {
|
|
425
|
+
...prim,
|
|
426
|
+
x: prim.x + dx,
|
|
427
|
+
y: prim.y + dy
|
|
428
|
+
};
|
|
429
|
+
if (prim.kind === "image") return {
|
|
430
|
+
...prim,
|
|
431
|
+
x: prim.x + dx,
|
|
432
|
+
y: prim.y + dy
|
|
433
|
+
};
|
|
434
|
+
return {
|
|
435
|
+
...prim,
|
|
436
|
+
paths: prim.paths.map((path) => ({
|
|
437
|
+
...path,
|
|
438
|
+
segments: path.segments.map((sg) => "x" in sg ? {
|
|
439
|
+
...sg,
|
|
440
|
+
x: sg.x + dx,
|
|
441
|
+
y: sg.y + dy,
|
|
442
|
+
..."x1" in sg ? {
|
|
443
|
+
x1: sg.x1 + dx,
|
|
444
|
+
y1: sg.y1 + dy
|
|
445
|
+
} : {},
|
|
446
|
+
..."x2" in sg ? {
|
|
447
|
+
x2: sg.x2 + dx,
|
|
448
|
+
y2: sg.y2 + dy
|
|
449
|
+
} : {}
|
|
450
|
+
} : sg)
|
|
451
|
+
}))
|
|
452
|
+
};
|
|
453
|
+
}
|
|
314
454
|
function penStyle(style) {
|
|
315
455
|
switch (style & 15) {
|
|
316
456
|
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,88 @@
|
|
|
1
|
+
import { unzlibSync } from "fflate";
|
|
2
|
+
//#region src/core/ole/escher-blip.ts
|
|
3
|
+
var BLIP_EMF = 61466;
|
|
4
|
+
var BLIP_WMF = 61467;
|
|
5
|
+
var BLIP_PICT = 61468;
|
|
6
|
+
var BLIP_JPEG = 61469;
|
|
7
|
+
var BLIP_PNG = 61470;
|
|
8
|
+
var BLIP_DIB = 61471;
|
|
9
|
+
var BLIP_TIFF = 61481;
|
|
10
|
+
var BLIP_JPEG_CMYK = 61482;
|
|
11
|
+
var METAFILE_HEADER_BYTES = 34;
|
|
12
|
+
var COMPRESSION_DEFLATE = 0;
|
|
13
|
+
var TWO_UID_INSTANCES = new Set([
|
|
14
|
+
981,
|
|
15
|
+
535,
|
|
16
|
+
1347,
|
|
17
|
+
1761,
|
|
18
|
+
1763,
|
|
19
|
+
1961,
|
|
20
|
+
1765,
|
|
21
|
+
481
|
|
22
|
+
]);
|
|
23
|
+
/** The signatures of the rasters a blip may hold, for the scan fallback. */
|
|
24
|
+
var RASTER_MAGICS = [
|
|
25
|
+
[
|
|
26
|
+
137,
|
|
27
|
+
80,
|
|
28
|
+
78,
|
|
29
|
+
71
|
|
30
|
+
],
|
|
31
|
+
[
|
|
32
|
+
255,
|
|
33
|
+
216,
|
|
34
|
+
255
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
71,
|
|
38
|
+
73,
|
|
39
|
+
70,
|
|
40
|
+
56
|
|
41
|
+
],
|
|
42
|
+
[66, 77]
|
|
43
|
+
];
|
|
44
|
+
/**
|
|
45
|
+
* The picture bytes inside one Escher BLIP record — a raster as it stands, or a
|
|
46
|
+
* metafile unpacked out of its header.
|
|
47
|
+
*
|
|
48
|
+
* @param type The blip record type (`0xF01A`…`0xF02A`).
|
|
49
|
+
* @param instance The record's `recInstance`, which says how many UIDs precede
|
|
50
|
+
* the payload.
|
|
51
|
+
* @param data The record's body, without the 8-byte header.
|
|
52
|
+
* @returns The bytes to hand the renderer, or `undefined` when the blip holds
|
|
53
|
+
* nothing this can read.
|
|
54
|
+
*/
|
|
55
|
+
function readEscherBlip(type, instance, data) {
|
|
56
|
+
if (type === BLIP_EMF || type === BLIP_WMF || type === BLIP_PICT) return readMetafileBlip(instance, data);
|
|
57
|
+
if (type === BLIP_JPEG || type === BLIP_PNG || type === BLIP_DIB || type === BLIP_TIFF || type === BLIP_JPEG_CMYK) return scanRaster(data);
|
|
58
|
+
return scanRaster(data);
|
|
59
|
+
}
|
|
60
|
+
function readMetafileBlip(instance, data) {
|
|
61
|
+
const uidBytes = TWO_UID_INSTANCES.has(instance) ? 32 : 16;
|
|
62
|
+
const head = uidBytes + METAFILE_HEADER_BYTES;
|
|
63
|
+
if (data.length < head) return void 0;
|
|
64
|
+
const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
|
|
65
|
+
const uncompressed = view.getUint32(uidBytes, true);
|
|
66
|
+
const compressed = view.getUint32(uidBytes + 24, true);
|
|
67
|
+
const compression = data[uidBytes + 32];
|
|
68
|
+
const payload = data.subarray(head, Math.min(data.length, head + (compressed || Infinity)));
|
|
69
|
+
if (payload.length === 0) return void 0;
|
|
70
|
+
if (compression !== COMPRESSION_DEFLATE) return payload;
|
|
71
|
+
try {
|
|
72
|
+
const out = unzlibSync(payload, uncompressed > 0 ? { out: new Uint8Array(uncompressed) } : {});
|
|
73
|
+
return out.length > 0 ? out : void 0;
|
|
74
|
+
} catch {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function scanRaster(data) {
|
|
79
|
+
const limit = Math.min(data.length, 80);
|
|
80
|
+
for (let off = 0; off < limit; off++) for (const magic of RASTER_MAGICS) if (matches(data, off, magic)) return data.subarray(off);
|
|
81
|
+
}
|
|
82
|
+
function matches(d, off, magic) {
|
|
83
|
+
if (off + magic.length > d.length) return false;
|
|
84
|
+
for (let i = 0; i < magic.length; i++) if (d[off + i] !== magic[i]) return false;
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
//#endregion
|
|
88
|
+
export { readEscherBlip };
|
|
@@ -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) {
|
|
@@ -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");
|