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.
- package/dist/esm/core/bmp.d.ts +33 -0
- package/dist/esm/core/bmp.js +276 -0
- 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 +55 -0
- package/dist/esm/core/drawingml/chart-geometry.js +14 -7
- package/dist/esm/core/drawingml/colors.d.ts +4 -2
- package/dist/esm/core/drawingml/colors.js +15 -0
- package/dist/esm/core/drawingml/diagram/colors.d.ts +52 -0
- package/dist/esm/core/drawingml/diagram/colors.js +125 -0
- package/dist/esm/core/drawingml/diagram/data-model.d.ts +47 -0
- package/dist/esm/core/drawingml/diagram/data-model.js +119 -0
- package/dist/esm/core/drawingml/diagram/layout-engine.d.ts +46 -0
- package/dist/esm/core/drawingml/diagram/layout-engine.js +948 -0
- package/dist/esm/core/drawingml/diagram/run.d.ts +37 -0
- package/dist/esm/core/drawingml/diagram/run.js +50 -0
- package/dist/esm/core/drawingml/diagram/to-drawing.d.ts +16 -0
- package/dist/esm/core/drawingml/diagram/to-drawing.js +86 -0
- package/dist/esm/core/drawingml/preset-geometry.js +116 -6
- package/dist/esm/core/drawingml/text-warp.d.ts +58 -0
- package/dist/esm/core/drawingml/text-warp.js +355 -0
- package/dist/esm/core/drawingml/theme-parser.d.ts +38 -0
- package/dist/esm/core/drawingml/theme-parser.js +73 -4
- package/dist/esm/core/font/measure.d.ts +12 -0
- package/dist/esm/core/font/measure.js +36 -0
- 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/images.d.ts +30 -2
- package/dist/esm/core/images.js +121 -5
- 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 +280 -38
- package/dist/esm/core/metafile/picture.d.ts +61 -1
- package/dist/esm/core/metafile/picture.js +70 -1
- package/dist/esm/core/metafile/wmf.js +202 -13
- package/dist/esm/core/ole/escher-blip.d.ts +12 -0
- package/dist/esm/core/ole/escher-blip.js +98 -0
- package/dist/esm/{pdf-reader → core}/png-encode.js +1 -1
- package/dist/esm/excel/print-model.js +5 -3
- package/dist/esm/excel/sheet-drawing.js +1 -1
- package/dist/esm/excel/sheet-to-flow.js +16 -2
- 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/html/html-writer.js +2 -1
- package/dist/esm/layout/page-doc.d.ts +74 -0
- package/dist/esm/layout/page-doc.js +14 -1
- package/dist/esm/layout/styled-layout.d.ts +2 -2
- package/dist/esm/layout/styled-layout.js +475 -48
- package/dist/esm/pdf/shading.js +8 -6
- package/dist/esm/pdf/styled-page-emitter.js +77 -5
- package/dist/esm/pdf/vector-graphics.js +1 -1
- 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 +191 -13
- package/dist/esm/pptx/ppt/ppt-text.d.ts +107 -1
- package/dist/esm/pptx/ppt/ppt-text.js +873 -144
- package/dist/esm/pptx/pptx-reader.d.ts +8 -0
- package/dist/esm/pptx/pptx-reader.js +117 -15
- 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 +11 -2
- package/dist/esm/pptx/slide-parser.js +203 -44
- package/dist/esm/pptx/sp-helpers.d.ts +9 -4
- package/dist/esm/pptx/sp-helpers.js +48 -9
- package/dist/esm/pptx/table-style.d.ts +16 -1
- package/dist/esm/pptx/table-style.js +104 -10
- package/dist/esm/svg/svg-writer.js +1 -0
- package/dist/esm/word/document-parser.d.ts +11 -2
- package/dist/esm/word/document-parser.js +10 -7
- package/dist/esm/word/docx-reader.js +32 -16
- 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/docx-writer.js +4 -0
- package/dist/esm/word/drawing-parser.d.ts +20 -0
- package/dist/esm/word/drawing-parser.js +67 -22
- 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 +6 -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
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** One decoded bitmap: chunky 8-bit samples, plus alpha when the file carries it. */
|
|
2
|
+
export interface DecodedBmp {
|
|
3
|
+
readonly width: number;
|
|
4
|
+
readonly height: number;
|
|
5
|
+
/** Row-major RGB samples, `width * height * 3` long. */
|
|
6
|
+
readonly data: Uint8Array;
|
|
7
|
+
/** One byte per pixel, present only when the file states real transparency. */
|
|
8
|
+
readonly alpha?: Uint8Array;
|
|
9
|
+
/** `biXPelsPerMeter`/`biYPelsPerMeter` turned into pixels per inch. */
|
|
10
|
+
readonly dpiX?: number;
|
|
11
|
+
readonly dpiY?: number;
|
|
12
|
+
}
|
|
13
|
+
/** Whether these bytes open with the `BM` signature of a bitmap FILE. */
|
|
14
|
+
export declare function isBmp(bytes: Uint8Array): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* MS-ODRAW §2.2.28 — a `BlipDIB`'s payload is a bitmap without its 14-byte
|
|
17
|
+
* BITMAPFILEHEADER, which the Escher record makes redundant. Put it back.
|
|
18
|
+
*
|
|
19
|
+
* @param dib The bytes from the DIB header onwards.
|
|
20
|
+
* @returns A complete BMP file, or `undefined` when the header does not read
|
|
21
|
+
* as a bitmap at all.
|
|
22
|
+
*/
|
|
23
|
+
export declare function dibToBmp(dib: Uint8Array): Uint8Array | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Decode a Windows bitmap into 8-bit RGB samples.
|
|
26
|
+
*
|
|
27
|
+
* @param bytes A complete BMP file (`BM` signature included).
|
|
28
|
+
* @returns The samples, their size and any alpha channel.
|
|
29
|
+
* @throws Error when the file is malformed, or carries a bitmap this does not
|
|
30
|
+
* read — a JPEG or PNG smuggled inside a DIB (`BI_JPEG`/`BI_PNG`),
|
|
31
|
+
* which is a whole other file wearing a bitmap header.
|
|
32
|
+
*/
|
|
33
|
+
export declare function decodeBmp(bytes: Uint8Array): DecodedBmp;
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
//#region src/core/bmp.ts
|
|
2
|
+
var FILE_HEADER_BYTES = 14;
|
|
3
|
+
var CORE_HEADER_BYTES = 12;
|
|
4
|
+
var INFO_HEADER_BYTES = 40;
|
|
5
|
+
var MAX_PIXELS = 4e7;
|
|
6
|
+
var BI_RGB = 0;
|
|
7
|
+
var BI_RLE8 = 1;
|
|
8
|
+
var BI_RLE4 = 2;
|
|
9
|
+
var BI_BITFIELDS = 3;
|
|
10
|
+
var BI_ALPHABITFIELDS = 6;
|
|
11
|
+
/** Whether these bytes open with the `BM` signature of a bitmap FILE. */
|
|
12
|
+
function isBmp(bytes) {
|
|
13
|
+
return bytes.length >= FILE_HEADER_BYTES && bytes[0] === 66 && bytes[1] === 77;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* MS-ODRAW §2.2.28 — a `BlipDIB`'s payload is a bitmap without its 14-byte
|
|
17
|
+
* BITMAPFILEHEADER, which the Escher record makes redundant. Put it back.
|
|
18
|
+
*
|
|
19
|
+
* @param dib The bytes from the DIB header onwards.
|
|
20
|
+
* @returns A complete BMP file, or `undefined` when the header does not read
|
|
21
|
+
* as a bitmap at all.
|
|
22
|
+
*/
|
|
23
|
+
function dibToBmp(dib) {
|
|
24
|
+
const head = readDibHeader(dib, 0);
|
|
25
|
+
if (!head) return void 0;
|
|
26
|
+
const offBits = FILE_HEADER_BYTES + head.headerBytes + head.maskBytes + head.paletteBytes;
|
|
27
|
+
const out = new Uint8Array(FILE_HEADER_BYTES + dib.length);
|
|
28
|
+
const view = new DataView(out.buffer);
|
|
29
|
+
out[0] = 66;
|
|
30
|
+
out[1] = 77;
|
|
31
|
+
view.setUint32(2, out.length, true);
|
|
32
|
+
view.setUint32(10, offBits, true);
|
|
33
|
+
out.set(dib, FILE_HEADER_BYTES);
|
|
34
|
+
return out;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Decode a Windows bitmap into 8-bit RGB samples.
|
|
38
|
+
*
|
|
39
|
+
* @param bytes A complete BMP file (`BM` signature included).
|
|
40
|
+
* @returns The samples, their size and any alpha channel.
|
|
41
|
+
* @throws Error when the file is malformed, or carries a bitmap this does not
|
|
42
|
+
* read — a JPEG or PNG smuggled inside a DIB (`BI_JPEG`/`BI_PNG`),
|
|
43
|
+
* which is a whole other file wearing a bitmap header.
|
|
44
|
+
*/
|
|
45
|
+
function decodeBmp(bytes) {
|
|
46
|
+
if (!isBmp(bytes)) throw new Error("BMP: not a bitmap");
|
|
47
|
+
const file = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
48
|
+
const head = readDibHeader(bytes, FILE_HEADER_BYTES);
|
|
49
|
+
if (!head) throw new Error("BMP: unreadable header");
|
|
50
|
+
const { width, height, topDown, bitCount, compression } = head;
|
|
51
|
+
if (width <= 0 || height <= 0) throw new Error("BMP: empty bitmap");
|
|
52
|
+
if (width * height > MAX_PIXELS) throw new Error("BMP: image too large");
|
|
53
|
+
if (compression === 4 || compression === 5) throw new Error("BMP: embedded JPEG/PNG bitmaps are not supported");
|
|
54
|
+
const stated = file.getUint32(10, true);
|
|
55
|
+
const computed = FILE_HEADER_BYTES + head.headerBytes + head.maskBytes + head.paletteBytes;
|
|
56
|
+
const pixelsAt = stated >= computed && stated < bytes.length ? stated : computed;
|
|
57
|
+
const palette = readPalette(bytes, FILE_HEADER_BYTES + head.headerBytes, head);
|
|
58
|
+
const count = width * height;
|
|
59
|
+
const data = new Uint8Array(count * 3);
|
|
60
|
+
const rowOf = (y) => topDown ? y : height - 1 - y;
|
|
61
|
+
if (compression === BI_RLE8 || compression === BI_RLE4) {
|
|
62
|
+
const indices = decodeRle(bytes.subarray(pixelsAt), width, height, compression === BI_RLE4);
|
|
63
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
64
|
+
const at = (rowOf(y) * width + x) * 3;
|
|
65
|
+
const p = (indices[y * width + x] ?? 0) * 3;
|
|
66
|
+
data[at] = palette[p] ?? 0;
|
|
67
|
+
data[at + 1] = palette[p + 1] ?? 0;
|
|
68
|
+
data[at + 2] = palette[p + 2] ?? 0;
|
|
69
|
+
}
|
|
70
|
+
return {
|
|
71
|
+
width,
|
|
72
|
+
height,
|
|
73
|
+
data,
|
|
74
|
+
...density(head)
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const stride = ((width * bitCount + 31) / 32 | 0) * 4;
|
|
78
|
+
const alpha = head.alphaMask !== 0 ? new Uint8Array(count) : void 0;
|
|
79
|
+
const shifts = {
|
|
80
|
+
r: maskShift(head.redMask),
|
|
81
|
+
g: maskShift(head.greenMask),
|
|
82
|
+
b: maskShift(head.blueMask),
|
|
83
|
+
a: maskShift(head.alphaMask)
|
|
84
|
+
};
|
|
85
|
+
for (let y = 0; y < height; y++) {
|
|
86
|
+
const row = pixelsAt + y * stride;
|
|
87
|
+
if (row + stride > bytes.length + stride) break;
|
|
88
|
+
for (let x = 0; x < width; x++) {
|
|
89
|
+
const at = (rowOf(y) * width + x) * 3;
|
|
90
|
+
if (bitCount <= 8) {
|
|
91
|
+
const p = paletteIndex(bytes, row, x, bitCount) * 3;
|
|
92
|
+
data[at] = palette[p] ?? 0;
|
|
93
|
+
data[at + 1] = palette[p + 1] ?? 0;
|
|
94
|
+
data[at + 2] = palette[p + 2] ?? 0;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
if (bitCount === 24) {
|
|
98
|
+
const o = row + x * 3;
|
|
99
|
+
data[at] = bytes[o + 2] ?? 0;
|
|
100
|
+
data[at + 1] = bytes[o + 1] ?? 0;
|
|
101
|
+
data[at + 2] = bytes[o] ?? 0;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const raw = bitCount === 16 ? (bytes[row + x * 2] ?? 0) | (bytes[row + x * 2 + 1] ?? 0) << 8 : ((bytes[row + x * 4] ?? 0) | (bytes[row + x * 4 + 1] ?? 0) << 8 | (bytes[row + x * 4 + 2] ?? 0) << 16 | (bytes[row + x * 4 + 3] ?? 0) << 24) >>> 0;
|
|
105
|
+
data[at] = channel(raw, head.redMask, shifts.r);
|
|
106
|
+
data[at + 1] = channel(raw, head.greenMask, shifts.g);
|
|
107
|
+
data[at + 2] = channel(raw, head.blueMask, shifts.b);
|
|
108
|
+
if (alpha) alpha[rowOf(y) * width + x] = channel(raw, head.alphaMask, shifts.a);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const opaque = alpha?.every((v) => v === 0) ?? true;
|
|
112
|
+
return {
|
|
113
|
+
width,
|
|
114
|
+
height,
|
|
115
|
+
data,
|
|
116
|
+
...alpha && !opaque ? { alpha } : {},
|
|
117
|
+
...density(head)
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function readDibHeader(bytes, at) {
|
|
121
|
+
if (bytes.length < at + 4) return void 0;
|
|
122
|
+
const v = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
|
|
123
|
+
const headerBytes = v.getUint32(at, true);
|
|
124
|
+
const core = headerBytes === CORE_HEADER_BYTES;
|
|
125
|
+
if (!core && headerBytes < INFO_HEADER_BYTES) return void 0;
|
|
126
|
+
if (bytes.length < at + headerBytes) return void 0;
|
|
127
|
+
const width = core ? v.getInt16(at + 4, true) : v.getInt32(at + 4, true);
|
|
128
|
+
const rawHeight = core ? v.getInt16(at + 6, true) : v.getInt32(at + 8, true);
|
|
129
|
+
const planes = core ? v.getUint16(at + 6, true) : v.getUint16(at + 12, true);
|
|
130
|
+
const bitCount = core ? v.getUint16(at + 8, true) : v.getUint16(at + 14, true);
|
|
131
|
+
const compression = core ? BI_RGB : v.getUint32(at + 16, true);
|
|
132
|
+
if (planes !== 1) return void 0;
|
|
133
|
+
if (![
|
|
134
|
+
1,
|
|
135
|
+
2,
|
|
136
|
+
4,
|
|
137
|
+
8,
|
|
138
|
+
16,
|
|
139
|
+
24,
|
|
140
|
+
32
|
|
141
|
+
].includes(bitCount)) return void 0;
|
|
142
|
+
if (compression > 6) return void 0;
|
|
143
|
+
if (width <= 0 || rawHeight === 0) return void 0;
|
|
144
|
+
const clrUsed = core ? 0 : v.getUint32(at + 32, true);
|
|
145
|
+
const inHeader = headerBytes >= 52;
|
|
146
|
+
const maskBytes = !inHeader && (compression === BI_BITFIELDS || compression === BI_ALPHABITFIELDS) ? compression === BI_ALPHABITFIELDS ? 16 : 12 : 0;
|
|
147
|
+
const maskAt = inHeader ? at + 40 : at + headerBytes;
|
|
148
|
+
const stated = compression === BI_BITFIELDS || compression === BI_ALPHABITFIELDS || inHeader;
|
|
149
|
+
const readMask = (i) => stated && bytes.length >= maskAt + (i + 1) * 4 ? v.getUint32(maskAt + i * 4, true) : 0;
|
|
150
|
+
const defaults = bitCount === 16 ? [
|
|
151
|
+
31744,
|
|
152
|
+
992,
|
|
153
|
+
31
|
|
154
|
+
] : [
|
|
155
|
+
16711680,
|
|
156
|
+
65280,
|
|
157
|
+
255
|
|
158
|
+
];
|
|
159
|
+
const red = readMask(0) || defaults[0];
|
|
160
|
+
const green = readMask(1) || defaults[1];
|
|
161
|
+
const blue = readMask(2) || defaults[2];
|
|
162
|
+
const alphaMask = headerBytes >= 56 && bytes.length >= maskAt + 16 ? v.getUint32(maskAt + 12, true) : 0;
|
|
163
|
+
const paletteEntryBytes = core ? 3 : 4;
|
|
164
|
+
return {
|
|
165
|
+
headerBytes,
|
|
166
|
+
maskBytes,
|
|
167
|
+
paletteBytes: (bitCount <= 8 ? clrUsed || 1 << bitCount : 0) * paletteEntryBytes,
|
|
168
|
+
paletteEntryBytes,
|
|
169
|
+
width,
|
|
170
|
+
height: Math.abs(rawHeight),
|
|
171
|
+
topDown: rawHeight < 0,
|
|
172
|
+
bitCount,
|
|
173
|
+
compression,
|
|
174
|
+
redMask: red,
|
|
175
|
+
greenMask: green,
|
|
176
|
+
blueMask: blue,
|
|
177
|
+
alphaMask,
|
|
178
|
+
pxPerMeterX: core ? 0 : v.getInt32(at + 24, true),
|
|
179
|
+
pxPerMeterY: core ? 0 : v.getInt32(at + 28, true)
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
/** The palette as flat RGB triples, whichever entry width the header uses. */
|
|
183
|
+
function readPalette(bytes, at, head) {
|
|
184
|
+
const entries = head.paletteBytes / head.paletteEntryBytes;
|
|
185
|
+
const out = new Uint8Array(entries * 3);
|
|
186
|
+
for (let i = 0; i < entries; i++) {
|
|
187
|
+
const o = at + i * head.paletteEntryBytes;
|
|
188
|
+
out[i * 3] = bytes[o + 2] ?? 0;
|
|
189
|
+
out[i * 3 + 1] = bytes[o + 1] ?? 0;
|
|
190
|
+
out[i * 3 + 2] = bytes[o] ?? 0;
|
|
191
|
+
}
|
|
192
|
+
return out;
|
|
193
|
+
}
|
|
194
|
+
/** The palette index of one pixel of a 1/2/4/8-bit row. */
|
|
195
|
+
function paletteIndex(bytes, row, x, bitCount) {
|
|
196
|
+
if (bitCount === 8) return bytes[row + x] ?? 0;
|
|
197
|
+
const perByte = 8 / bitCount;
|
|
198
|
+
return (bytes[row + (x / perByte | 0)] ?? 0) >> 8 - bitCount * (x % perByte + 1) & (1 << bitCount) - 1;
|
|
199
|
+
}
|
|
200
|
+
/** How far right a mask's field sits, so its bits can be read off. */
|
|
201
|
+
function maskShift(mask) {
|
|
202
|
+
if (mask === 0) return 0;
|
|
203
|
+
let shift = 0;
|
|
204
|
+
while ((mask >>> shift & 1) === 0) shift++;
|
|
205
|
+
return shift;
|
|
206
|
+
}
|
|
207
|
+
/** One channel of a packed pixel, stretched to the full byte range. */
|
|
208
|
+
function channel(raw, mask, shift) {
|
|
209
|
+
if (mask === 0) return 0;
|
|
210
|
+
const width = (mask >>> shift).toString(2).length;
|
|
211
|
+
const value = (raw & mask) >>> shift;
|
|
212
|
+
const max = (1 << width) - 1;
|
|
213
|
+
return max === 0 ? 0 : Math.round(value * 255 / max);
|
|
214
|
+
}
|
|
215
|
+
/** §biXPelsPerMeter — the resolution the bitmap claims, in pixels per inch. */
|
|
216
|
+
function density(head) {
|
|
217
|
+
if (head.pxPerMeterX <= 0 || head.pxPerMeterY <= 0) return {};
|
|
218
|
+
return {
|
|
219
|
+
dpiX: head.pxPerMeterX * .0254,
|
|
220
|
+
dpiY: head.pxPerMeterY * .0254
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* §BI_RLE8 / §BI_RLE4 — run-length rows of palette indices.
|
|
225
|
+
*
|
|
226
|
+
* Each pair is either a run (a non-zero count and the index to repeat) or an
|
|
227
|
+
* escape (a zero count and a code): 0 ends the row, 1 ends the bitmap, 2 is a
|
|
228
|
+
* delta that skips forward, and anything else is that many literal pixels,
|
|
229
|
+
* padded to a two-byte boundary.
|
|
230
|
+
*
|
|
231
|
+
* @param data The bytes from the first run onwards.
|
|
232
|
+
* @param width The bitmap's width in pixels.
|
|
233
|
+
* @param height Its height in rows.
|
|
234
|
+
* @param four Whether this is the four-bit form, which packs two indices per byte.
|
|
235
|
+
* @returns One palette index per pixel, top row first.
|
|
236
|
+
*/
|
|
237
|
+
function decodeRle(data, width, height, four) {
|
|
238
|
+
const out = new Uint8Array(width * height);
|
|
239
|
+
let x = 0;
|
|
240
|
+
let y = 0;
|
|
241
|
+
let at = 0;
|
|
242
|
+
const put = (index) => {
|
|
243
|
+
if (x < width && y < height) out[y * width + x] = index;
|
|
244
|
+
x++;
|
|
245
|
+
};
|
|
246
|
+
while (at + 1 < data.length && y < height) {
|
|
247
|
+
const count = data[at];
|
|
248
|
+
const value = data[at + 1];
|
|
249
|
+
at += 2;
|
|
250
|
+
if (count > 0) {
|
|
251
|
+
for (let i = 0; i < count; i++) put(four ? i % 2 === 0 ? value >> 4 : value & 15 : value);
|
|
252
|
+
continue;
|
|
253
|
+
}
|
|
254
|
+
if (value === 0) {
|
|
255
|
+
x = 0;
|
|
256
|
+
y++;
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
if (value === 1) break;
|
|
260
|
+
if (value === 2) {
|
|
261
|
+
x += data[at] ?? 0;
|
|
262
|
+
y += data[at + 1] ?? 0;
|
|
263
|
+
at += 2;
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const bytesUsed = four ? (value + 1) / 2 | 0 : value;
|
|
267
|
+
for (let i = 0; i < value; i++) {
|
|
268
|
+
const byte = data[at + (four ? i / 2 | 0 : i)] ?? 0;
|
|
269
|
+
put(four ? i % 2 === 0 ? byte >> 4 : byte & 15 : byte);
|
|
270
|
+
}
|
|
271
|
+
at += bytesUsed + bytesUsed % 2;
|
|
272
|
+
}
|
|
273
|
+
return out;
|
|
274
|
+
}
|
|
275
|
+
//#endregion
|
|
276
|
+
export { decodeBmp, dibToBmp, isBmp };
|
|
@@ -143,6 +143,22 @@ export declare class Ream {
|
|
|
143
143
|
* @returns The font bytes and, for docx, optional per-family registries.
|
|
144
144
|
*/
|
|
145
145
|
private resolveFonts;
|
|
146
|
+
/**
|
|
147
|
+
* Fetch one face per writing system the document holds text in — the curated
|
|
148
|
+
* families are Latin, and Han, Kana, Hangul, Arabic and the geometric symbols
|
|
149
|
+
* are a notdef box in every one of them.
|
|
150
|
+
*
|
|
151
|
+
* Only the regular weight is fetched: Noto Sans SC is ten megabytes, and a
|
|
152
|
+
* bold run in it is better stroked (see `SyntheticFace`) than downloaded four
|
|
153
|
+
* times over. A face that fails to arrive is a recorded loss, not a throw —
|
|
154
|
+
* the rest of the document still renders.
|
|
155
|
+
*
|
|
156
|
+
* @param into The registry map the run resolver looks in.
|
|
157
|
+
* @param flow The parsed document.
|
|
158
|
+
* @param options The convert options (for the injectable `fetch`).
|
|
159
|
+
* @param losses Where a face that could not be fetched records itself.
|
|
160
|
+
*/
|
|
161
|
+
private addScriptFonts;
|
|
146
162
|
/**
|
|
147
163
|
* In strict mode, throw {@link ConversionLossError} for the first recorded loss.
|
|
148
164
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { fetchFontSet } from "../fonts/remote-fonts.js";
|
|
1
|
+
import { fetchFontSet, fetchScriptFont, resolveFamilyKey } from "../fonts/remote-fonts.js";
|
|
2
|
+
import { scriptsInFlow } from "../fonts/scripts.js";
|
|
2
3
|
import { FontRegistry } from "../font/font-registry.js";
|
|
3
4
|
import { createFontMeasure } from "../font/measure.js";
|
|
4
5
|
import { ConversionLossError } from "../ir/loss.js";
|
|
@@ -12,8 +13,8 @@ import { writeDocx } from "../../word/docx-writer.js";
|
|
|
12
13
|
import { writeXlsx } from "../../excel/xlsx-writer.js";
|
|
13
14
|
import { writeHtml } from "../../html/html-writer.js";
|
|
14
15
|
import { writeSvg } from "../../svg/svg-writer.js";
|
|
15
|
-
import { resolveDocxAutoFonts } from "../../word/docx-to-pdf.js";
|
|
16
16
|
import { DEFAULT_READERS, resolveFontsViaChain, toFlowDoc } from "./facade.js";
|
|
17
|
+
import { familiesInFlow } from "../fonts/families.js";
|
|
17
18
|
import { decryptPackage, isEncryptedPackage } from "../crypto/offcrypto.js";
|
|
18
19
|
//#region src/core/converter/ream.ts
|
|
19
20
|
/**
|
|
@@ -150,7 +151,7 @@ var Ream = class Ream {
|
|
|
150
151
|
losses
|
|
151
152
|
};
|
|
152
153
|
}
|
|
153
|
-
const { fonts, registriesByFamily } = await this.resolveFonts(options, losses);
|
|
154
|
+
const { fonts, registriesByFamily } = await this.resolveFonts(options, losses, flow);
|
|
154
155
|
const registry = FontRegistry.fromBytes(fonts);
|
|
155
156
|
const paginated = this.sheet ? projectSheetDoc(this.sheet, {
|
|
156
157
|
...options.now ? { now: options.now } : {},
|
|
@@ -209,7 +210,7 @@ var Ream = class Ream {
|
|
|
209
210
|
* @param losses The mutable loss list a substitution is appended to.
|
|
210
211
|
* @returns The font bytes and, for docx, optional per-family registries.
|
|
211
212
|
*/
|
|
212
|
-
async resolveFonts(options, losses) {
|
|
213
|
+
async resolveFonts(options, losses, flow) {
|
|
213
214
|
const explicit = options.fonts ?? (options.fontBytes ? { regular: options.fontBytes } : void 0);
|
|
214
215
|
if (explicit) return { fonts: explicit };
|
|
215
216
|
if (options.fontProviders && options.fontProviders.length > 0) {
|
|
@@ -217,11 +218,60 @@ var Ream = class Ream {
|
|
|
217
218
|
if (loss) losses.push(loss);
|
|
218
219
|
if (fonts) return { fonts };
|
|
219
220
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
221
|
+
const fetchOpt = options.fontFetch ? { fetch: options.fontFetch } : {};
|
|
222
|
+
const keys = options.fontFamily ? new Set([resolveFamilyKey(options.fontFamily)]) : familiesInFlow(flow);
|
|
223
|
+
if (keys.size <= 1 && scriptsInFlow(flow).scripts.size === 0) {
|
|
224
|
+
const family = keys.values().next().value;
|
|
225
|
+
return { fonts: await fetchFontSet({
|
|
226
|
+
...family ? { family } : {},
|
|
227
|
+
...fetchOpt
|
|
228
|
+
}) };
|
|
229
|
+
}
|
|
230
|
+
const registriesByFamily = /* @__PURE__ */ new Map();
|
|
231
|
+
let baseBytes;
|
|
232
|
+
for (const key of keys) {
|
|
233
|
+
const bytes = await fetchFontSet({
|
|
234
|
+
family: key,
|
|
235
|
+
...fetchOpt
|
|
236
|
+
});
|
|
237
|
+
registriesByFamily.set(key, FontRegistry.fromBytes(bytes));
|
|
238
|
+
if (key === "arimo" || !baseBytes) baseBytes = bytes;
|
|
239
|
+
}
|
|
240
|
+
await this.addScriptFonts(registriesByFamily, flow, options, losses);
|
|
241
|
+
return {
|
|
242
|
+
fonts: baseBytes,
|
|
243
|
+
registriesByFamily
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Fetch one face per writing system the document holds text in — the curated
|
|
248
|
+
* families are Latin, and Han, Kana, Hangul, Arabic and the geometric symbols
|
|
249
|
+
* are a notdef box in every one of them.
|
|
250
|
+
*
|
|
251
|
+
* Only the regular weight is fetched: Noto Sans SC is ten megabytes, and a
|
|
252
|
+
* bold run in it is better stroked (see `SyntheticFace`) than downloaded four
|
|
253
|
+
* times over. A face that fails to arrive is a recorded loss, not a throw —
|
|
254
|
+
* the rest of the document still renders.
|
|
255
|
+
*
|
|
256
|
+
* @param into The registry map the run resolver looks in.
|
|
257
|
+
* @param flow The parsed document.
|
|
258
|
+
* @param options The convert options (for the injectable `fetch`).
|
|
259
|
+
* @param losses Where a face that could not be fetched records itself.
|
|
260
|
+
*/
|
|
261
|
+
async addScriptFonts(into, flow, options, losses) {
|
|
262
|
+
const { scripts } = scriptsInFlow(flow);
|
|
263
|
+
for (const script of scripts) {
|
|
264
|
+
const bytes = await fetchScriptFont(script, options.fontFetch);
|
|
265
|
+
if (!bytes) {
|
|
266
|
+
losses.push({
|
|
267
|
+
feature: "font",
|
|
268
|
+
detail: `no face could be fetched for the ${script} script; its text draws as boxes`,
|
|
269
|
+
severity: "substituted"
|
|
270
|
+
});
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
into.set(script, FontRegistry.fromBytes(bytes));
|
|
274
|
+
}
|
|
225
275
|
}
|
|
226
276
|
/**
|
|
227
277
|
* In strict mode, throw {@link ConversionLossError} for the first recorded loss.
|
|
@@ -787,6 +787,13 @@ export interface CellProperties {
|
|
|
787
787
|
* is a word-processor table's default.
|
|
788
788
|
*/
|
|
789
789
|
readonly verticalAlign?: 'top' | 'center' | 'bottom';
|
|
790
|
+
/**
|
|
791
|
+
* §17.4.71 `w:textDirection` / §21.1.3.17 `a:tcPr@vert` — the cell's text is
|
|
792
|
+
* turned a quarter: `vert` reads top-to-bottom (turned clockwise), `vert270`
|
|
793
|
+
* bottom-to-top. Its lines then run along the cell's HEIGHT and stack across
|
|
794
|
+
* its width, which is what makes a narrow header column readable.
|
|
795
|
+
*/
|
|
796
|
+
readonly textDirection?: 'vert' | 'vert270';
|
|
790
797
|
}
|
|
791
798
|
/** §17.4.81 `w:trPr` — a table row's properties: height, split/header flags. */
|
|
792
799
|
export interface RowProperties {
|
|
@@ -1025,6 +1032,34 @@ export interface ShapeFill {
|
|
|
1025
1032
|
* text box: stretched, such a fill is a blur where it should be a pattern.
|
|
1026
1033
|
*/
|
|
1027
1034
|
readonly tiled?: boolean;
|
|
1035
|
+
/**
|
|
1036
|
+
* The size ONE copy of a tiled fill occupies, when the shape states it —
|
|
1037
|
+
* MS-ODRAW §2.3.7.11/.12 `fillWidth` / `fillHeight`. Absent, a tile is the
|
|
1038
|
+
* picture at its own resolution, which is the default both formats give.
|
|
1039
|
+
*/
|
|
1040
|
+
readonly tileSizePt?: {
|
|
1041
|
+
readonly widthPt: number;
|
|
1042
|
+
readonly heightPt: number;
|
|
1043
|
+
};
|
|
1044
|
+
/**
|
|
1045
|
+
* §20.1.8.58 `a:tile @sx @sy` — how far the picture is scaled BEFORE it is
|
|
1046
|
+
* repeated, as fractions of its own size (1 = 100 %). A texture halved tiles
|
|
1047
|
+
* four times as often, and read as a plain repeat it tiles once.
|
|
1048
|
+
*/
|
|
1049
|
+
readonly tileScale?: {
|
|
1050
|
+
readonly sx: number;
|
|
1051
|
+
readonly sy: number;
|
|
1052
|
+
};
|
|
1053
|
+
/**
|
|
1054
|
+
* Where the grid of copies is anchored. DrawingML pins it to the shape's
|
|
1055
|
+
* top-left corner (§20.1.8.58 `a:tile @algn`, which defaults to `tl`); an
|
|
1056
|
+
* MS-ODRAW texture fill (§2.3.7.13 `fillOriginX`/`fillOriginY`, both
|
|
1057
|
+
* defaulting to nothing) centres it on the shape instead. It only shows when
|
|
1058
|
+
* the copies do not divide the box evenly — and it shows most when ONE copy
|
|
1059
|
+
* is larger than the box, where the difference is which part of the picture
|
|
1060
|
+
* is visible at all.
|
|
1061
|
+
*/
|
|
1062
|
+
readonly tileFromCentre?: boolean;
|
|
1028
1063
|
/**
|
|
1029
1064
|
* §20.1.8.14 `a:blipFill` — the picture painted across the shape's box. A
|
|
1030
1065
|
* DrawingML picture IS a shape with one of these, which is how a `pic:pic`
|
|
@@ -1144,6 +1179,26 @@ export interface ShapeTextBody {
|
|
|
1144
1179
|
* WordArt is set at whatever size fills the box it was drawn in.
|
|
1145
1180
|
*/
|
|
1146
1181
|
readonly fitToBox?: boolean;
|
|
1182
|
+
/**
|
|
1183
|
+
* §20.1.9.10 `a:prstTxWarp` — DrawingML WordArt: the preset curve the text is
|
|
1184
|
+
* bent through, and the `a:avLst` `adj` guide when the file states one. The
|
|
1185
|
+
* warped text does not wrap and is stretched to fill the shape's box, so the
|
|
1186
|
+
* size its runs state stops deciding how large it is drawn. `textNoShape` is
|
|
1187
|
+
* not carried: it is the enumeration's "no warp" member, and a body under it
|
|
1188
|
+
* is an ordinary text box.
|
|
1189
|
+
*/
|
|
1190
|
+
readonly warp?: {
|
|
1191
|
+
readonly preset: string;
|
|
1192
|
+
readonly adjust?: number;
|
|
1193
|
+
};
|
|
1194
|
+
/**
|
|
1195
|
+
* §20.1.10.42 `a:normAutofit` — the text SHRINKS to fit the box, and only
|
|
1196
|
+
* shrinks: a size that already fits is left alone. PowerPoint writes the
|
|
1197
|
+
* scale it settled on into `@fontScale` and that is applied at parse; this
|
|
1198
|
+
* is for the text that arrives without one, which is every box of a diagram
|
|
1199
|
+
* laid out from its layout part rather than from a cached drawing.
|
|
1200
|
+
*/
|
|
1201
|
+
readonly shrinkToFit?: boolean;
|
|
1147
1202
|
/**
|
|
1148
1203
|
* `wps:txbx @id` / `wps:linkedTxbx @id @seq` — the chain of boxes this one
|
|
1149
1204
|
* belongs to. Text that overruns a box continues in the next of its chain;
|
|
@@ -46,7 +46,7 @@ function niceScale(dataMin, dataMax, maxTicks = 6) {
|
|
|
46
46
|
const lo = Math.min(dataMin, dataMax);
|
|
47
47
|
let hi = Math.max(dataMin, dataMax);
|
|
48
48
|
if (lo === hi) hi = lo + 1;
|
|
49
|
-
const step = niceNum(
|
|
49
|
+
const step = niceNum((hi - lo) / Math.max(1, maxTicks - 1), true);
|
|
50
50
|
const headroom = hi > 0 ? hi * 1.05 : hi;
|
|
51
51
|
return {
|
|
52
52
|
min: Math.floor(lo / step) * step,
|
|
@@ -712,11 +712,17 @@ function autoRange(vals) {
|
|
|
712
712
|
return [lo > 0 && lo < 5 / 6 * hi ? 0 : lo, hi];
|
|
713
713
|
}
|
|
714
714
|
/**
|
|
715
|
-
*
|
|
716
|
-
*
|
|
717
|
-
*
|
|
715
|
+
* How many ticks an axis `extentPt` long carries (mirrors {@link axisScale}).
|
|
716
|
+
*
|
|
717
|
+
* A tall axis takes more of them — a fixed six drew 0/100/200/300 down a plot
|
|
718
|
+
* where both references fit 0/50/…/300 — but the appetite is milder than it
|
|
719
|
+
* looks: asked for one every 32pt, a 427pt chart wanted ten, and Excel labels
|
|
720
|
+
* that chart's 0…5 data 0/1/…/6 where we drew half-steps (chart-texture-bg
|
|
721
|
+
* .pptx). One per ~48pt and never more than eight satisfies both, now that
|
|
722
|
+
* {@link niceScale} measures its step against the range the data spans rather
|
|
723
|
+
* than against Heckbert's rounded-up one.
|
|
718
724
|
*/
|
|
719
|
-
var tickBudget = (extentPt) => Math.min(
|
|
725
|
+
var tickBudget = (extentPt) => Math.min(8, Math.max(4, Math.round(extentPt / 48)));
|
|
720
726
|
/** Side (points) of the square stamped for a series that names no symbol. */
|
|
721
727
|
var DEFAULT_MARKER_PT = 4;
|
|
722
728
|
/**
|
|
@@ -869,9 +875,10 @@ function buildPieScene(chart, wPt, hPt, measure) {
|
|
|
869
875
|
});
|
|
870
876
|
const mid = ang + sweep / 2;
|
|
871
877
|
const pct = Math.round(v / total * 100);
|
|
878
|
+
const own = chart.showValues ? fmtDataLabel(chart, v) : `${pct}%`;
|
|
872
879
|
const custom = series.pointLabels?.find((l) => l.idx === i)?.text;
|
|
873
|
-
if (custom !== void 0 || pct >= 5) labels.push({
|
|
874
|
-
text: custom ??
|
|
880
|
+
if (custom !== void 0 || chart.showValues || pct >= 5) labels.push({
|
|
881
|
+
text: custom ?? own,
|
|
875
882
|
x: cx + Math.cos(mid) * labelR,
|
|
876
883
|
y: cy + Math.sin(mid) * labelR - 9 / 3,
|
|
877
884
|
sizePt: 9,
|
|
@@ -3,10 +3,12 @@ import { PoNode } from '../po-helpers.js';
|
|
|
3
3
|
* A colour transform child (§20.1.2.3): `lumMod`/`lumOff` modulate luminance,
|
|
4
4
|
* `shade` darkens toward black, `tint` lightens toward white. `val` is normalised
|
|
5
5
|
* to 0..1 (the XML stores thousandths of a percent). `alpha` composites over white
|
|
6
|
-
* (solid fills emit no transparency).
|
|
6
|
+
* (solid fills emit no transparency). `gamma`/`invGamma` carry no value: they
|
|
7
|
+
* shift the colour into the other light and back, which changes what the
|
|
8
|
+
* transforms between them mean.
|
|
7
9
|
*/
|
|
8
10
|
export interface ColorMod {
|
|
9
|
-
readonly kind: 'lumMod' | 'lumOff' | 'shade' | 'tint' | 'alpha' | 'satMod' | 'hueMod' | 'hueOff' | 'satOff';
|
|
11
|
+
readonly kind: 'lumMod' | 'lumOff' | 'shade' | 'tint' | 'alpha' | 'satMod' | 'hueMod' | 'hueOff' | 'satOff' | 'gamma' | 'invGamma';
|
|
10
12
|
readonly val: number;
|
|
11
13
|
}
|
|
12
14
|
/**
|
|
@@ -99,6 +99,13 @@ function applyColorMods(hex, mods) {
|
|
|
99
99
|
r = toSrgb(toLinear(r) * m.val + (1 - m.val));
|
|
100
100
|
g = toSrgb(toLinear(g) * m.val + (1 - m.val));
|
|
101
101
|
b = toSrgb(toLinear(b) * m.val + (1 - m.val));
|
|
102
|
+
} else if (m.kind === "gamma" || m.kind === "invGamma") {
|
|
103
|
+
const shift = m.kind === "gamma" ? toSrgb : toLinear;
|
|
104
|
+
[r, g, b] = [
|
|
105
|
+
shift(r),
|
|
106
|
+
shift(g),
|
|
107
|
+
shift(b)
|
|
108
|
+
];
|
|
102
109
|
} else if (m.kind === "lumMod" || m.kind === "lumOff") {
|
|
103
110
|
const [h, s, l] = rgbToHsl(r, g, b);
|
|
104
111
|
const l2 = m.kind === "lumMod" ? l * m.val : clamp01(l + m.val);
|
|
@@ -230,6 +237,14 @@ function readColorMods(colorNode) {
|
|
|
230
237
|
val: v / 1e5
|
|
231
238
|
});
|
|
232
239
|
}
|
|
240
|
+
if (poIs(c, "a:gamma")) mods.push({
|
|
241
|
+
kind: "gamma",
|
|
242
|
+
val: 0
|
|
243
|
+
});
|
|
244
|
+
if (poIs(c, "a:invGamma")) mods.push({
|
|
245
|
+
kind: "invGamma",
|
|
246
|
+
val: 0
|
|
247
|
+
});
|
|
233
248
|
if (poIs(c, "a:hueOff")) {
|
|
234
249
|
const v = poIntAttr(c, "val");
|
|
235
250
|
if (v !== void 0) mods.push({
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { PoNode } from '../../po-helpers.js';
|
|
2
|
+
/** The colours part, as the drawing writer asks it. */
|
|
3
|
+
export declare class DiagramColors {
|
|
4
|
+
private readonly byLabel;
|
|
5
|
+
constructor(tree: ReadonlyArray<PoNode>);
|
|
6
|
+
/**
|
|
7
|
+
* The `a:solidFill` for a box, or undefined when the part states none.
|
|
8
|
+
*
|
|
9
|
+
* @param label The layout node's `styleLbl`.
|
|
10
|
+
* @param index The box's place in the run of siblings.
|
|
11
|
+
*/
|
|
12
|
+
fill(label: string | undefined, index: number): string | undefined;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the part states this label at all.
|
|
15
|
+
*
|
|
16
|
+
* A label it names but gives no fill — `revTx`, the reversed text of a
|
|
17
|
+
* process arrow — is a box with NO fill, which is not the same as a file
|
|
18
|
+
* that ships no colours and falls back to one accent for everything.
|
|
19
|
+
*/
|
|
20
|
+
knows(label: string | undefined): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* The `a:ln` for a box's OUTLINE, where the part states one.
|
|
23
|
+
*
|
|
24
|
+
* A follower box is often a near-white wash with the node's own accent drawn
|
|
25
|
+
* round it (`conFgAcc1` is `lt1` at 90% inside an `accent1` line): without the
|
|
26
|
+
* line it is a white rectangle on a white slide and reads as nothing at all.
|
|
27
|
+
*
|
|
28
|
+
* @param label The layout node's `styleLbl`.
|
|
29
|
+
* @param index The box's place in the run of siblings.
|
|
30
|
+
*/
|
|
31
|
+
line(label: string | undefined, index: number): string | undefined;
|
|
32
|
+
/** The `a:solidFill` for a box's TEXT, where the part overrides the style. */
|
|
33
|
+
textFill(label: string | undefined, index: number): string | undefined;
|
|
34
|
+
private pick;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* §21.4.2.20 `dgm:pt/dgm:spPr` — the formatting the AUTHOR set on one point,
|
|
38
|
+
* which beats whatever the colours part gives that point's style label.
|
|
39
|
+
*
|
|
40
|
+
* A cycle-matrix whose second quarter was recoloured by hand states it here and
|
|
41
|
+
* nowhere else: read only from the colours part, all four quarters came out the
|
|
42
|
+
* one accent the label names, and the orange quarter and the orange outline
|
|
43
|
+
* round its callout both vanished.
|
|
44
|
+
*
|
|
45
|
+
* @param spPr The point's `dgm:spPr`, when it has one.
|
|
46
|
+
* @returns The fill and the outline it overrides, each as DrawingML, when it
|
|
47
|
+
* overrides them.
|
|
48
|
+
*/
|
|
49
|
+
export declare function pointPaint(spPr: PoNode | undefined): {
|
|
50
|
+
fill?: string;
|
|
51
|
+
line?: string;
|
|
52
|
+
};
|