reamkit 1.17.0 → 1.19.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/document-model/types.d.ts +59 -1
- package/dist/esm/core/drawingml/colors.js +13 -6
- package/dist/esm/core/images.d.ts +2 -2
- package/dist/esm/core/images.js +38 -0
- package/dist/esm/core/lzw.d.ts +17 -0
- package/dist/esm/core/lzw.js +83 -0
- package/dist/esm/core/metafile/emf.d.ts +16 -0
- package/dist/esm/core/metafile/emf.js +635 -0
- package/dist/esm/core/metafile/picture.d.ts +106 -0
- package/dist/esm/core/metafile/picture.js +55 -0
- package/dist/esm/core/metafile/wmf.d.ts +9 -0
- package/dist/esm/core/metafile/wmf.js +371 -0
- package/dist/esm/core/po-helpers.d.ts +9 -0
- package/dist/esm/core/po-helpers.js +9 -1
- package/dist/esm/core/tiff.d.ts +20 -0
- package/dist/esm/core/tiff.js +339 -0
- package/dist/esm/core/vector.d.ts +5 -0
- package/dist/esm/excel/print-model.js +3 -1
- package/dist/esm/html/html-writer.js +3 -2
- package/dist/esm/layout/page-doc.d.ts +46 -3
- package/dist/esm/layout/styled-layout.js +649 -108
- package/dist/esm/pdf/styled-page-emitter.js +78 -3
- package/dist/esm/pdf/vector-graphics.d.ts +1 -1
- package/dist/esm/pdf/vector-graphics.js +2 -1
- package/dist/esm/pdf-reader/image-decode.js +7 -75
- package/dist/esm/svg/svg-writer.js +1 -1
- package/dist/esm/word/document-parser.js +3 -0
- package/dist/esm/word/drawing-parser.d.ts +5 -0
- package/dist/esm/word/drawing-parser.js +100 -14
- package/dist/esm/word/paragraph-properties.js +2 -2
- package/dist/esm/word/run-properties.js +2 -2
- package/dist/esm/word/xml-helpers.d.ts +12 -0
- package/dist/esm/word/xml-helpers.js +23 -3
- package/package.json +1 -1
|
@@ -248,6 +248,15 @@ export interface InlineImage {
|
|
|
248
248
|
* six stood flat on the page where both references lift them off it.
|
|
249
249
|
*/
|
|
250
250
|
readonly shadow?: ShapeShadow;
|
|
251
|
+
/**
|
|
252
|
+
* §14.1.2.10 `@gain`/`@blacklevel` — the contrast and brightness the picture
|
|
253
|
+
* is drawn through, about mid grey: `out = (in - 0.5) * gain + 0.5 + black`.
|
|
254
|
+
* Word washes a watermark out this way.
|
|
255
|
+
*/
|
|
256
|
+
readonly wash?: {
|
|
257
|
+
readonly gain: number;
|
|
258
|
+
readonly black: number;
|
|
259
|
+
};
|
|
251
260
|
readonly width: Pt;
|
|
252
261
|
readonly height: Pt;
|
|
253
262
|
/** §20.1.8.55 `a:srcRect` — the part of the source the frame shows. */
|
|
@@ -897,6 +906,15 @@ export interface ImageBlock {
|
|
|
897
906
|
* six stood flat on the page where both references lift them off it.
|
|
898
907
|
*/
|
|
899
908
|
readonly shadow?: ShapeShadow;
|
|
909
|
+
/**
|
|
910
|
+
* §14.1.2.10 `@gain`/`@blacklevel` — the contrast and brightness the picture
|
|
911
|
+
* is drawn through, about mid grey: `out = (in - 0.5) * gain + 0.5 + black`.
|
|
912
|
+
* Word washes a watermark out this way.
|
|
913
|
+
*/
|
|
914
|
+
readonly wash?: {
|
|
915
|
+
readonly gain: number;
|
|
916
|
+
readonly black: number;
|
|
917
|
+
};
|
|
900
918
|
readonly width: Pt;
|
|
901
919
|
readonly height: Pt;
|
|
902
920
|
/** §20.1.8.55 `a:srcRect` — the part of the source the frame shows. */
|
|
@@ -974,6 +992,12 @@ export interface ShapeFill {
|
|
|
974
992
|
readonly kind: ShapeFillKind;
|
|
975
993
|
readonly colorHex?: string;
|
|
976
994
|
readonly gradient?: ShapeGradient;
|
|
995
|
+
/**
|
|
996
|
+
* §14.1.2.5 `@type="tile"` — the picture REPEATS at its own size rather than
|
|
997
|
+
* stretching over the box. A parchment behind a page, a texture behind a
|
|
998
|
+
* text box: stretched, such a fill is a blur where it should be a pattern.
|
|
999
|
+
*/
|
|
1000
|
+
readonly tiled?: boolean;
|
|
977
1001
|
/**
|
|
978
1002
|
* §20.1.8.14 `a:blipFill` — the picture painted across the shape's box. A
|
|
979
1003
|
* DrawingML picture IS a shape with one of these, which is how a `pic:pic`
|
|
@@ -985,6 +1009,12 @@ export interface ShapeFill {
|
|
|
985
1009
|
* of the picture the box shows, as the fractions cut from each side.
|
|
986
1010
|
*/
|
|
987
1011
|
readonly imageCrop?: ImageCrop;
|
|
1012
|
+
/**
|
|
1013
|
+
* §20.1.2.3.1 `a:alpha` / §14.1.2.5 `@opacity` — how opaque the fill is,
|
|
1014
|
+
* `0..1`. Absent is opaque. The colour above is the fill's own, NOT composited
|
|
1015
|
+
* over the paper: what is behind the shape shows through it.
|
|
1016
|
+
*/
|
|
1017
|
+
readonly alpha?: number;
|
|
988
1018
|
}
|
|
989
1019
|
/** §20.1.10.49 ST_PresetLineDashVal — a shape outline's preset dash pattern. */
|
|
990
1020
|
export type ShapeDash = 'solid' | 'dot' | 'dash' | 'dashDot' | 'lgDash' | 'lgDashDot' | 'sysDash' | 'sysDot';
|
|
@@ -1063,6 +1093,16 @@ export interface ShapeTextBody {
|
|
|
1063
1093
|
* WordArt is set at whatever size fills the box it was drawn in.
|
|
1064
1094
|
*/
|
|
1065
1095
|
readonly fitToBox?: boolean;
|
|
1096
|
+
/**
|
|
1097
|
+
* `wps:txbx @id` / `wps:linkedTxbx @id @seq` — the chain of boxes this one
|
|
1098
|
+
* belongs to. Text that overruns a box continues in the next of its chain;
|
|
1099
|
+
* `seq` 0 is the box that holds the words, and the rest carry none of their
|
|
1100
|
+
* own.
|
|
1101
|
+
*/
|
|
1102
|
+
readonly chain?: {
|
|
1103
|
+
readonly id: string;
|
|
1104
|
+
readonly seq: number;
|
|
1105
|
+
};
|
|
1066
1106
|
}
|
|
1067
1107
|
/**
|
|
1068
1108
|
* A block-level DrawingML shape (§20.1): its size, {@link ShapeGeometry}, fill,
|
|
@@ -1417,7 +1457,12 @@ export interface SectionProperties {
|
|
|
1417
1457
|
* modes (square/tight/through) and `topAndBottom` stay in flow as blocks.
|
|
1418
1458
|
*/
|
|
1419
1459
|
export interface FloatAnchor {
|
|
1420
|
-
|
|
1460
|
+
/**
|
|
1461
|
+
* §20.4.2.3 / §17.18.104 — how body text runs past the drawing. `notBeside`
|
|
1462
|
+
* is the FRAME's own mode: the drawing keeps the place its anchor names, but
|
|
1463
|
+
* no text may stand beside it, so its band spans the whole column.
|
|
1464
|
+
*/
|
|
1465
|
+
readonly wrap: 'none' | 'square' | 'tight' | 'through' | 'topAndBottom' | 'notBeside';
|
|
1421
1466
|
readonly behind?: boolean;
|
|
1422
1467
|
/**
|
|
1423
1468
|
* §20.4.2.3 `wp:anchor @relativeHeight` — the z-order among the floats on the
|
|
@@ -1451,6 +1496,19 @@ export interface FloatAnchor {
|
|
|
1451
1496
|
*/
|
|
1452
1497
|
readonly align?: 'top' | 'center' | 'bottom';
|
|
1453
1498
|
};
|
|
1499
|
+
/**
|
|
1500
|
+
* §20.4.2.3 `@wrapText` on the wrap element — which side(s) of the drawing
|
|
1501
|
+
* text may stand on. `bothSides` is the default and the only value that
|
|
1502
|
+
* fills BOTH gaps; `left`/`right` name one, `largest` the wider.
|
|
1503
|
+
*/
|
|
1504
|
+
readonly wrapSide?: 'bothSides' | 'left' | 'right' | 'largest';
|
|
1505
|
+
/**
|
|
1506
|
+
* §20.4.2.3 `wp:anchor @layoutInCell` (VML `o:allowincell`) — present and
|
|
1507
|
+
* false when a drawing anchored inside a TABLE CELL is placed against the
|
|
1508
|
+
* page rather than against the cell. Absent means the default: the cell is
|
|
1509
|
+
* the frame every `relativeFrom` is measured in.
|
|
1510
|
+
*/
|
|
1511
|
+
readonly inCell?: boolean;
|
|
1454
1512
|
/**
|
|
1455
1513
|
* §20.4.2.3 `wp:anchor @distT/@distB/@distL/@distR` — how far the wrapped
|
|
1456
1514
|
* text stands off each edge of the drawing. Absent sides are 0.
|
|
@@ -69,6 +69,13 @@ function hslToRgb(h, s, l) {
|
|
|
69
69
|
b + m
|
|
70
70
|
];
|
|
71
71
|
}
|
|
72
|
+
function toLinear(c) {
|
|
73
|
+
return c <= .04045 ? c / 12.92 : Math.pow((c + .055) / 1.055, 2.4);
|
|
74
|
+
}
|
|
75
|
+
function toSrgb(c) {
|
|
76
|
+
const v = clamp01(c);
|
|
77
|
+
return v <= .0031308 ? v * 12.92 : 1.055 * Math.pow(v, 1 / 2.4) - .055;
|
|
78
|
+
}
|
|
72
79
|
/**
|
|
73
80
|
* Apply DrawingML colour transforms ({@link ColorMod}s) to a 6-hex value,
|
|
74
81
|
* returning a 6-hex value. `shade`/`tint` scale in RGB; `lumMod`/`lumOff` adjust
|
|
@@ -85,13 +92,13 @@ function applyColorMods(hex, mods) {
|
|
|
85
92
|
let g = (n >> 8 & 255) / 255;
|
|
86
93
|
let b = (n & 255) / 255;
|
|
87
94
|
for (const m of mods) if (m.kind === "shade") {
|
|
88
|
-
r
|
|
89
|
-
g
|
|
90
|
-
b
|
|
95
|
+
r = toSrgb(toLinear(r) * m.val);
|
|
96
|
+
g = toSrgb(toLinear(g) * m.val);
|
|
97
|
+
b = toSrgb(toLinear(b) * m.val);
|
|
91
98
|
} else if (m.kind === "tint") {
|
|
92
|
-
r = r * m.val + (1 - m.val);
|
|
93
|
-
g = g * m.val + (1 - m.val);
|
|
94
|
-
b = b * m.val + (1 - m.val);
|
|
99
|
+
r = toSrgb(toLinear(r) * m.val + (1 - m.val));
|
|
100
|
+
g = toSrgb(toLinear(g) * m.val + (1 - m.val));
|
|
101
|
+
b = toSrgb(toLinear(b) * m.val + (1 - m.val));
|
|
95
102
|
} else if (m.kind === "lumMod" || m.kind === "lumOff") {
|
|
96
103
|
const [h, s, l] = rgbToHsl(r, g, b);
|
|
97
104
|
const l2 = m.kind === "lumMod" ? l * m.val : clamp01(l + m.val);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** The raster formats this module recognizes and can prepare for embedding. */
|
|
2
|
-
export type ImageFormat = 'jpeg' | 'png' | 'jpeg2000' | 'gif';
|
|
2
|
+
export type ImageFormat = 'jpeg' | 'png' | 'jpeg2000' | 'gif' | 'tiff';
|
|
3
3
|
/**
|
|
4
4
|
* Sniff the raster format from a file's leading magic bytes (JPEG SOI, the PNG
|
|
5
5
|
* signature, or a JP2 box / raw JPEG 2000 codestream). Returns the
|
|
@@ -24,7 +24,7 @@ export interface EmbedImageOptions {
|
|
|
24
24
|
*/
|
|
25
25
|
export interface PreparedImage {
|
|
26
26
|
readonly format: ImageFormat;
|
|
27
|
-
readonly mimeType: 'image/jp2' | 'image/jpeg' | 'image/png' | 'image/gif';
|
|
27
|
+
readonly mimeType: 'image/jp2' | 'image/jpeg' | 'image/png' | 'image/gif' | 'image/tiff';
|
|
28
28
|
readonly widthPx: number;
|
|
29
29
|
readonly heightPx: number;
|
|
30
30
|
/**
|
package/dist/esm/core/images.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { decodeTiff, isTiff } from "./tiff.js";
|
|
1
2
|
import { unzlibSync, zlibSync } from "fflate";
|
|
2
3
|
//#region src/core/images.ts
|
|
3
4
|
/**
|
|
@@ -11,6 +12,7 @@ function detectImageFormat(bytes) {
|
|
|
11
12
|
if (bytes.length >= 12 && bytes[0] === 0 && bytes[1] === 0 && bytes[2] === 0 && bytes[3] === 12 && bytes[4] === 106 && bytes[5] === 80 && bytes[6] === 32 && bytes[7] === 32 && bytes[8] === 13 && bytes[9] === 10 && bytes[10] === 135 && bytes[11] === 10) return "jpeg2000";
|
|
12
13
|
if (bytes.length >= 4 && bytes[0] === 255 && bytes[1] === 79 && bytes[2] === 255 && bytes[3] === 81) return "jpeg2000";
|
|
13
14
|
if (bytes.length >= 6 && bytes[0] === 71 && bytes[1] === 73 && bytes[2] === 70 && bytes[3] === 56 && (bytes[4] === 55 || bytes[4] === 57) && bytes[5] === 97) return "gif";
|
|
15
|
+
if (isTiff(bytes)) return "tiff";
|
|
14
16
|
return null;
|
|
15
17
|
}
|
|
16
18
|
/**
|
|
@@ -26,6 +28,7 @@ function prepareImage(bytes, options = {}) {
|
|
|
26
28
|
if (format === "png") return preparePng(bytes, options);
|
|
27
29
|
if (format === "jpeg2000") return prepareJpeg2000(bytes);
|
|
28
30
|
if (format === "gif") return prepareGif(bytes, options);
|
|
31
|
+
if (format === "tiff") return prepareTiff(bytes, options);
|
|
29
32
|
throw new Error("Unsupported image format");
|
|
30
33
|
}
|
|
31
34
|
function prepareJpeg2000(bytes) {
|
|
@@ -170,6 +173,41 @@ function prepareGif(bytes, options = {}) {
|
|
|
170
173
|
...alpha && !options.flattenAlpha ? { smaskData: zlibSync(alpha) } : {}
|
|
171
174
|
};
|
|
172
175
|
}
|
|
176
|
+
function prepareTiff(bytes, options = {}) {
|
|
177
|
+
const img = decodeTiff(bytes);
|
|
178
|
+
const channels = img.channels === 4 ? 3 : img.channels;
|
|
179
|
+
const data = img.channels === 4 ? cmykToRgb(img.data) : img.data.slice();
|
|
180
|
+
const alpha = img.alpha;
|
|
181
|
+
if (alpha && options.flattenAlpha) for (let i = 0; i < alpha.length; i++) {
|
|
182
|
+
if (alpha[i] === 255) continue;
|
|
183
|
+
const a = alpha[i] / 255;
|
|
184
|
+
for (let c = 0; c < channels; c++) {
|
|
185
|
+
const at = i * channels + c;
|
|
186
|
+
data[at] = Math.round(data[at] * a + 255 * (1 - a));
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return {
|
|
190
|
+
format: "tiff",
|
|
191
|
+
mimeType: "image/tiff",
|
|
192
|
+
widthPx: img.width,
|
|
193
|
+
heightPx: img.height,
|
|
194
|
+
colorSpace: channels === 3 ? "DeviceRGB" : "DeviceGray",
|
|
195
|
+
bitsPerComponent: 8,
|
|
196
|
+
filter: "FlateDecode",
|
|
197
|
+
data: zlibSync(data),
|
|
198
|
+
...alpha && !options.flattenAlpha ? { smaskData: zlibSync(alpha.slice()) } : {}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
function cmykToRgb(cmyk) {
|
|
202
|
+
const out = new Uint8Array(cmyk.length / 4 * 3);
|
|
203
|
+
for (let i = 0; i * 4 + 3 < cmyk.length; i++) {
|
|
204
|
+
const k = 255 - cmyk[i * 4 + 3];
|
|
205
|
+
out[i * 3] = (255 - cmyk[i * 4]) * k / 255;
|
|
206
|
+
out[i * 3 + 1] = (255 - cmyk[i * 4 + 1]) * k / 255;
|
|
207
|
+
out[i * 3 + 2] = (255 - cmyk[i * 4 + 2]) * k / 255;
|
|
208
|
+
}
|
|
209
|
+
return out;
|
|
210
|
+
}
|
|
173
211
|
function decodeGif(bytes) {
|
|
174
212
|
const u16 = (i) => (bytes[i] ?? 0) | (bytes[i + 1] ?? 0) << 8;
|
|
175
213
|
const screenW = u16(6);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** How to run {@link lzwDecodeMsb}: the early-change flag and an output cap. */
|
|
2
|
+
export interface LzwOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Widen the code one step BEFORE the table fills (PDF `/EarlyChange`,
|
|
5
|
+
* TIFF's own convention). 1 by default, matching both specifications' norm.
|
|
6
|
+
*/
|
|
7
|
+
readonly earlyChange?: number;
|
|
8
|
+
/** Stop after this many output bytes — the guard against a decompression bomb. */
|
|
9
|
+
readonly limit: number;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Decode an MSB-first LZW stream (TIFF 6.0 §13 / ISO 32000-1 §7.4.4.2). The
|
|
13
|
+
* KwKwK case (a code not yet in the table) repeats the previous string plus its
|
|
14
|
+
* own first byte. Truncated input ends the stream where it stops rather than
|
|
15
|
+
* throwing: a partly-decoded strip still prints.
|
|
16
|
+
*/
|
|
17
|
+
export declare function lzwDecodeMsb(data: Uint8Array, options: LzwOptions): Uint8Array;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
//#region src/core/lzw.ts
|
|
2
|
+
/**
|
|
3
|
+
* Decode an MSB-first LZW stream (TIFF 6.0 §13 / ISO 32000-1 §7.4.4.2). The
|
|
4
|
+
* KwKwK case (a code not yet in the table) repeats the previous string plus its
|
|
5
|
+
* own first byte. Truncated input ends the stream where it stops rather than
|
|
6
|
+
* throwing: a partly-decoded strip still prints.
|
|
7
|
+
*/
|
|
8
|
+
function lzwDecodeMsb(data, options) {
|
|
9
|
+
const earlyChange = options.earlyChange ?? 1;
|
|
10
|
+
let out = new Uint8Array(4096);
|
|
11
|
+
let outLen = 0;
|
|
12
|
+
const emit = (e) => {
|
|
13
|
+
if (outLen + e.length > options.limit) return false;
|
|
14
|
+
if (outLen + e.length > out.length) {
|
|
15
|
+
let cap = out.length * 2;
|
|
16
|
+
while (cap < outLen + e.length) cap *= 2;
|
|
17
|
+
const grown = new Uint8Array(cap);
|
|
18
|
+
grown.set(out.subarray(0, outLen));
|
|
19
|
+
out = grown;
|
|
20
|
+
}
|
|
21
|
+
out.set(e, outLen);
|
|
22
|
+
outLen += e.length;
|
|
23
|
+
return true;
|
|
24
|
+
};
|
|
25
|
+
let bitBuffer = 0;
|
|
26
|
+
let bitCount = 0;
|
|
27
|
+
let pos = 0;
|
|
28
|
+
let codeLength = 9;
|
|
29
|
+
const readCode = () => {
|
|
30
|
+
while (bitCount < codeLength) {
|
|
31
|
+
if (pos >= data.length) return -1;
|
|
32
|
+
bitBuffer = (bitBuffer << 8 | data[pos++]) >>> 0;
|
|
33
|
+
bitCount += 8;
|
|
34
|
+
}
|
|
35
|
+
bitCount -= codeLength;
|
|
36
|
+
return bitBuffer >>> bitCount & (1 << codeLength) - 1;
|
|
37
|
+
};
|
|
38
|
+
const dict = new Array(4096);
|
|
39
|
+
let nextCode = 258;
|
|
40
|
+
let prev = -1;
|
|
41
|
+
const reset = () => {
|
|
42
|
+
for (let i = 0; i < 256; i++) dict[i] = Uint8Array.of(i);
|
|
43
|
+
nextCode = 258;
|
|
44
|
+
codeLength = 9;
|
|
45
|
+
prev = -1;
|
|
46
|
+
};
|
|
47
|
+
reset();
|
|
48
|
+
for (;;) {
|
|
49
|
+
const code = readCode();
|
|
50
|
+
if (code < 0 || code === 257) break;
|
|
51
|
+
if (code === 256) {
|
|
52
|
+
reset();
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
if (prev < 0) {
|
|
56
|
+
const first = dict[code];
|
|
57
|
+
if (!first || !emit(first)) break;
|
|
58
|
+
prev = code;
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const prevEntry = dict[prev];
|
|
62
|
+
let entry = code < nextCode ? dict[code] : void 0;
|
|
63
|
+
if (!entry) {
|
|
64
|
+
entry = new Uint8Array(prevEntry.length + 1);
|
|
65
|
+
entry.set(prevEntry);
|
|
66
|
+
entry[prevEntry.length] = prevEntry[0];
|
|
67
|
+
}
|
|
68
|
+
if (!emit(entry)) break;
|
|
69
|
+
if (nextCode < 4096) {
|
|
70
|
+
const added = new Uint8Array(prevEntry.length + 1);
|
|
71
|
+
added.set(prevEntry);
|
|
72
|
+
added[prevEntry.length] = entry[0];
|
|
73
|
+
dict[nextCode++] = added;
|
|
74
|
+
if (nextCode + earlyChange === 512) codeLength = 10;
|
|
75
|
+
else if (nextCode + earlyChange === 1024) codeLength = 11;
|
|
76
|
+
else if (nextCode + earlyChange === 2048) codeLength = 12;
|
|
77
|
+
}
|
|
78
|
+
prev = code;
|
|
79
|
+
}
|
|
80
|
+
return out.subarray(0, outLen);
|
|
81
|
+
}
|
|
82
|
+
//#endregion
|
|
83
|
+
export { lzwDecodeMsb };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { PathSegment } from '../vector.js';
|
|
2
|
+
import { MetaPicture } from './picture.js';
|
|
3
|
+
/** Whether the bytes open with an EMF header (MS-EMF §2.3.4.2: type 1 + " EMF"). */
|
|
4
|
+
export declare function isEmf(bytes: Uint8Array): boolean;
|
|
5
|
+
/**
|
|
6
|
+
* Read an EMF into its primitives.
|
|
7
|
+
*
|
|
8
|
+
* @throws Error when the bytes are not an EMF or its header is malformed.
|
|
9
|
+
*/
|
|
10
|
+
export declare function readEmf(bytes: Uint8Array): MetaPicture;
|
|
11
|
+
type Mapper = (x: number, y: number) => {
|
|
12
|
+
x: number;
|
|
13
|
+
y: number;
|
|
14
|
+
};
|
|
15
|
+
export declare function ellipseSegments(map: Mapper, l: number, t: number, r: number, b: number): Array<PathSegment>;
|
|
16
|
+
export {};
|