wpd-codec 3.4.6 → 3.5.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 (38) hide show
  1. package/README.md +31 -27
  2. package/dist/container/container.cjs +12 -5
  3. package/dist/container/container.d.cts +2 -1
  4. package/dist/container/container.d.ts +2 -1
  5. package/dist/container/container.js +12 -5
  6. package/dist/container/encryption.d.cts +1 -1
  7. package/dist/container/encryption.d.ts +1 -1
  8. package/dist/container/header.d.cts +1 -19
  9. package/dist/container/header.d.ts +1 -19
  10. package/dist/container/prefix.d.cts +1 -1
  11. package/dist/container/prefix.d.ts +1 -1
  12. package/dist/{diagnostics-DhO7mgqJ.d.cts → diagnostics-fHTFHZ-d.d.cts} +2 -0
  13. package/dist/{diagnostics-DhO7mgqJ.d.ts → diagnostics-fHTFHZ-d.d.ts} +2 -0
  14. package/dist/diagnostics.cjs +2 -0
  15. package/dist/diagnostics.d.cts +1 -1
  16. package/dist/diagnostics.d.ts +1 -1
  17. package/dist/diagnostics.js +2 -0
  18. package/dist/header-Ca8QZVe3.d.cts +20 -0
  19. package/dist/header-Ca8QZVe3.d.ts +20 -0
  20. package/dist/index.d.cts +2 -2
  21. package/dist/index.d.ts +2 -2
  22. package/dist/read.cjs +85 -14
  23. package/dist/read.d.cts +1 -1
  24. package/dist/read.d.ts +1 -1
  25. package/dist/read.js +85 -14
  26. package/dist/stream/furniture.cjs +1 -2
  27. package/dist/stream/furniture.d.cts +2 -2
  28. package/dist/stream/furniture.d.ts +2 -2
  29. package/dist/stream/furniture.js +1 -2
  30. package/dist/stream/ole.cjs +71 -0
  31. package/dist/stream/ole.d.cts +22 -0
  32. package/dist/stream/ole.d.ts +22 -0
  33. package/dist/stream/ole.js +64 -0
  34. package/dist/stream/wpg.cjs +620 -0
  35. package/dist/stream/wpg.d.cts +18 -0
  36. package/dist/stream/wpg.d.ts +18 -0
  37. package/dist/stream/wpg.js +619 -0
  38. package/package.json +3 -3
@@ -0,0 +1,620 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_bytes_view = require("../bytes/view.cjs");
3
+ //#region src/stream/wpg.ts
4
+ const RECORD_START_WPG = 1;
5
+ const RECORD_END_WPG = 2;
6
+ const RECORD_TEXT_DATA = 15;
7
+ const RECORD_POLYLINE = 21;
8
+ const RECORD_RECTANGLE = 24;
9
+ const RECORD_ARC = 25;
10
+ const RECORD_TEXT_BLOCK = 29;
11
+ const RECORD_GROUP = 32;
12
+ const RECORD_PEN_FORE_COLOR = 37;
13
+ const RECORD_DP_PEN_FORE_COLOR = 38;
14
+ const RECORD_PEN_SIZE = 43;
15
+ const RECORD_DP_PEN_SIZE = 44;
16
+ const RECORD_BRUSH_FORE_COLOR = 49;
17
+ const RECORD_DP_BRUSH_FORE_COLOR = 50;
18
+ const RECORD_NAMES = /* @__PURE__ */ new Map([
19
+ [1, "Start WPG"],
20
+ [3, "Form Settings"],
21
+ [4, "Ruler Settings"],
22
+ [5, "Grid Settings"],
23
+ [6, "Layer"],
24
+ [7, "ObjectLink"],
25
+ [8, "Pen Style Definition"],
26
+ [9, "Pattern Definition"],
27
+ [10, "Comment"],
28
+ [11, "Color Transfer"],
29
+ [12, "Color Palette"],
30
+ [13, "DP Color Palette"],
31
+ [14, "Bitmap Data"],
32
+ [15, "Text Data"],
33
+ [16, "Chart Style"],
34
+ [17, "Chart Data"],
35
+ [18, "Object Image"],
36
+ [21, "Polyline"],
37
+ [22, "Polyspline"],
38
+ [23, "Polycurve"],
39
+ [24, "Rectangle"],
40
+ [25, "Arc"],
41
+ [26, "Compound Polygon"],
42
+ [27, "Bitmap"],
43
+ [28, "Text Line"],
44
+ [29, "Text Block"],
45
+ [30, "Text Path"],
46
+ [31, "Chart"],
47
+ [33, "Object Capsule"],
48
+ [34, "Font Settings"],
49
+ [39, "Pen Back Color"],
50
+ [40, "DP Pen Back Color"],
51
+ [41, "Pen Style"],
52
+ [42, "Pen Pattern"],
53
+ [45, "Line Cap"],
54
+ [46, "Line Join"],
55
+ [47, "Brush Gradient"],
56
+ [48, "DP Brush Gradient"],
57
+ [51, "Brush Back Color"],
58
+ [52, "DP Brush Back Color"],
59
+ [53, "Brush Pattern"],
60
+ [54, "Horizontal Line"],
61
+ [55, "Vertical Line"],
62
+ [56, "Poster Settings"],
63
+ [57, "Image State"],
64
+ [58, "Envelope Definition"],
65
+ [59, "Envelope"],
66
+ [60, "Texture Definition"],
67
+ [61, "Brush Texture"],
68
+ [62, "Texture Alignment"],
69
+ [63, "Pen Texture"]
70
+ ]);
71
+ const FLAG_OBJECT_ID = 32;
72
+ const FLAG_EDIT_LOCK = 128;
73
+ const FLAG_PATH_WINDING = 4096;
74
+ const FLAG_FILL = 8192;
75
+ const FLAG_CLOSE = 16384;
76
+ const FLAG_FRAME = 32768;
77
+ const QUARTER_ELLIPSE_KAPPA = 4 / 3 * (Math.SQRT2 - 1);
78
+ const WPG_PRODUCT_TYPE = 1;
79
+ const WPG_FILE_TYPE = 22;
80
+ const WPG_MAJOR_2 = 2;
81
+ const WPG_MAJOR_1 = 1;
82
+ const WPG_PREFIX_HEAD_SIZE = 26;
83
+ const POINTS_PER_INCH = 72;
84
+ const WPG_DEFAULT_BLACK = {
85
+ r: 0,
86
+ g: 0,
87
+ b: 0,
88
+ a: 0
89
+ };
90
+ function readCountField(bytes, cursor) {
91
+ const first = bytes[cursor];
92
+ if (first === void 0) return;
93
+ if (first <= 254) return {
94
+ value: first,
95
+ next: cursor + 1
96
+ };
97
+ if (cursor + 3 > bytes.length) return;
98
+ const shortValue = require_bytes_view.uint16At(bytes, cursor + 1);
99
+ if ((shortValue & 32768) === 0) return {
100
+ value: shortValue,
101
+ next: cursor + 3
102
+ };
103
+ if (cursor + 5 > bytes.length) return;
104
+ const lowHalf = require_bytes_view.uint16At(bytes, cursor + 3);
105
+ return {
106
+ value: ((shortValue & 32767) << 16) + lowHalf,
107
+ next: cursor + 5
108
+ };
109
+ }
110
+ function coordinateAt(bytes, offset, doublePrecision) {
111
+ if (!doublePrecision) return require_bytes_view.int16At(bytes, offset);
112
+ return require_bytes_view.uint32At(bytes, offset) / 65536;
113
+ }
114
+ function readCharacterization(bytes, cursor, recordEnd) {
115
+ if (cursor + 2 > recordEnd) return;
116
+ const flags = require_bytes_view.uint16At(bytes, cursor);
117
+ if ((flags & 31) !== 0) return {
118
+ flags,
119
+ geometryAt: -1
120
+ };
121
+ let geometryAt = cursor + 2;
122
+ if ((flags & FLAG_EDIT_LOCK) !== 0) geometryAt += 4;
123
+ if ((flags & FLAG_OBJECT_ID) !== 0) {
124
+ if (geometryAt + 2 > recordEnd) return;
125
+ geometryAt += (require_bytes_view.uint16At(bytes, geometryAt) & 32768) !== 0 ? 4 : 2;
126
+ }
127
+ if (geometryAt > recordEnd) return;
128
+ return {
129
+ flags,
130
+ geometryAt
131
+ };
132
+ }
133
+ function xToPt(geometry, x) {
134
+ return x / geometry.xPpi * POINTS_PER_INCH;
135
+ }
136
+ function yToPt(geometry, y) {
137
+ return geometry.heightPt - y / geometry.yPpi * POINTS_PER_INCH;
138
+ }
139
+ function strokeOf(geometry, state) {
140
+ if (state.penWidthUnits <= 0) return;
141
+ const opacity = 1 - state.penColor.a;
142
+ return {
143
+ color: {
144
+ r: state.penColor.r,
145
+ g: state.penColor.g,
146
+ b: state.penColor.b
147
+ },
148
+ widthPt: state.penWidthUnits / geometry.xPpi * POINTS_PER_INCH,
149
+ ...opacity < 1 ? { opacity } : {}
150
+ };
151
+ }
152
+ function fillOf(state) {
153
+ return {
154
+ fill: {
155
+ r: state.brushColor.r,
156
+ g: state.brushColor.g,
157
+ b: state.brushColor.b
158
+ },
159
+ fillOpacity: 1 - state.brushColor.a
160
+ };
161
+ }
162
+ function readSingleColor(data) {
163
+ if (data.length < 4) return;
164
+ return {
165
+ r: require_bytes_view.byteAt(data, 0) / 255,
166
+ g: require_bytes_view.byteAt(data, 1) / 255,
167
+ b: require_bytes_view.byteAt(data, 2) / 255,
168
+ a: require_bytes_view.byteAt(data, 3) / 255
169
+ };
170
+ }
171
+ function readDoubleColor(data) {
172
+ if (data.length < 8) return;
173
+ return {
174
+ r: require_bytes_view.uint16At(data, 0) / 65535,
175
+ g: require_bytes_view.uint16At(data, 2) / 65535,
176
+ b: require_bytes_view.uint16At(data, 4) / 65535,
177
+ a: require_bytes_view.uint16At(data, 6) / 65535
178
+ };
179
+ }
180
+ function decodeWpgGraphic(bytes, options) {
181
+ let start = -1;
182
+ for (let index = 0; index + WPG_PREFIX_HEAD_SIZE <= bytes.length; index += 1) {
183
+ if (require_bytes_view.byteAt(bytes, index) !== 255 || require_bytes_view.byteAt(bytes, index + 1) !== 87 || require_bytes_view.byteAt(bytes, index + 2) !== 80 || require_bytes_view.byteAt(bytes, index + 3) !== 67) continue;
184
+ if (require_bytes_view.byteAt(bytes, index + 8) !== WPG_PRODUCT_TYPE || require_bytes_view.byteAt(bytes, index + 9) !== WPG_FILE_TYPE) continue;
185
+ start = index;
186
+ break;
187
+ }
188
+ if (start < 0) return;
189
+ const majorVersion = require_bytes_view.byteAt(bytes, start + 10);
190
+ if (majorVersion === WPG_MAJOR_1) return {
191
+ status: "refused",
192
+ reason: "wpg1"
193
+ };
194
+ if (majorVersion !== WPG_MAJOR_2) return {
195
+ status: "refused",
196
+ reason: "malformed"
197
+ };
198
+ if (require_bytes_view.uint16At(bytes, start + 12) !== 0) return {
199
+ status: "refused",
200
+ reason: "encrypted"
201
+ };
202
+ const recordStart = require_bytes_view.uint32At(bytes, start + 4);
203
+ if (recordStart < start + WPG_PREFIX_HEAD_SIZE || recordStart >= bytes.length) return {
204
+ status: "refused",
205
+ reason: "malformed"
206
+ };
207
+ const state = {
208
+ penColor: { ...WPG_DEFAULT_BLACK },
209
+ penWidthUnits: 0,
210
+ brushColor: { ...WPG_DEFAULT_BLACK }
211
+ };
212
+ const vectors = [];
213
+ const shapes = [];
214
+ const skipped = /* @__PURE__ */ new Set();
215
+ const groups = [];
216
+ let geometry;
217
+ let paintOrder = 0;
218
+ let pendingTextBlockFrame;
219
+ let cursor = start + recordStart;
220
+ const recordName = (type) => RECORD_NAMES.get(type) ?? `record type 0x${type.toString(16)}`;
221
+ while (cursor < bytes.length) {
222
+ if (cursor + 2 > bytes.length) break;
223
+ const type = require_bytes_view.byteAt(bytes, cursor + 1);
224
+ let after = cursor + 2;
225
+ const extension = readCountField(bytes, after);
226
+ if (extension === void 0) break;
227
+ after = extension.next;
228
+ const length = readCountField(bytes, after);
229
+ if (length === void 0) break;
230
+ after = length.next;
231
+ const recordEnd = after + length.value;
232
+ if (recordEnd > bytes.length) break;
233
+ const data = bytes.subarray(after, recordEnd);
234
+ const innermostBefore = groups[groups.length - 1];
235
+ if (innermostBefore !== void 0) innermostBefore.remaining -= 1;
236
+ const swallowed = swallowedByOpenGroup(groups);
237
+ if (type === RECORD_END_WPG && !swallowed) break;
238
+ if (!swallowed) {
239
+ switch (type) {
240
+ case RECORD_START_WPG: {
241
+ if (data.length < 13) {
242
+ skipped.add(recordName(type));
243
+ break;
244
+ }
245
+ const xPpi = require_bytes_view.uint16At(data, 0);
246
+ const yPpi = require_bytes_view.uint16At(data, 2);
247
+ const precision = require_bytes_view.byteAt(data, 4);
248
+ if (xPpi === 0 || yPpi === 0 || precision !== 0 && precision !== 1) return {
249
+ status: "refused",
250
+ reason: "malformed"
251
+ };
252
+ const doublePrecision = precision === 1;
253
+ const coordinateSize = doublePrecision ? 4 : 2;
254
+ const extentAt = 5 + coordinateSize * 4;
255
+ if (extentAt + coordinateSize * 4 > data.length) return {
256
+ status: "refused",
257
+ reason: "malformed"
258
+ };
259
+ const left = coordinateAt(data, extentAt, doublePrecision);
260
+ const bottom = coordinateAt(data, extentAt + coordinateSize, doublePrecision);
261
+ const right = coordinateAt(data, extentAt + coordinateSize * 2, doublePrecision);
262
+ const top = coordinateAt(data, extentAt + coordinateSize * 3, doublePrecision);
263
+ geometry = {
264
+ widthPt: Math.abs(right - left) / xPpi * POINTS_PER_INCH,
265
+ heightPt: Math.abs(top - bottom) / yPpi * POINTS_PER_INCH,
266
+ xPpi,
267
+ yPpi,
268
+ doublePrecision,
269
+ coordinateSize
270
+ };
271
+ break;
272
+ }
273
+ case RECORD_PEN_FORE_COLOR:
274
+ case RECORD_DP_PEN_FORE_COLOR: {
275
+ const color = type === RECORD_PEN_FORE_COLOR ? readSingleColor(data) : readDoubleColor(data);
276
+ if (color !== void 0) state.penColor = color;
277
+ break;
278
+ }
279
+ case RECORD_BRUSH_FORE_COLOR:
280
+ case RECORD_DP_BRUSH_FORE_COLOR: {
281
+ const color = type === RECORD_BRUSH_FORE_COLOR ? readSingleColor(data) : readDoubleColor(data);
282
+ if (color !== void 0) state.brushColor = color;
283
+ break;
284
+ }
285
+ case RECORD_PEN_SIZE:
286
+ if (data.length >= 4) state.penWidthUnits = require_bytes_view.uint16At(data, 0);
287
+ break;
288
+ case RECORD_DP_PEN_SIZE:
289
+ if (data.length >= 8) state.penWidthUnits = require_bytes_view.uint32At(data, 0) / 65536;
290
+ break;
291
+ case RECORD_TEXT_BLOCK:
292
+ pendingTextBlockFrame = readTextBlockFrame(data, geometry);
293
+ if (pendingTextBlockFrame === void 0) skipped.add(recordName(type));
294
+ break;
295
+ case RECORD_TEXT_DATA: {
296
+ const frame = pendingTextBlockFrame;
297
+ pendingTextBlockFrame = void 0;
298
+ if (frame === void 0) {
299
+ skipped.add(recordName(type));
300
+ break;
301
+ }
302
+ const blocks = options.foldTextData(data);
303
+ shapes.push({
304
+ frame,
305
+ insetLeftPt: 0,
306
+ insetTopPt: 0,
307
+ insetRightPt: 0,
308
+ insetBottomPt: 0,
309
+ blocks: [...blocks],
310
+ paintOrder
311
+ });
312
+ paintOrder += 1;
313
+ break;
314
+ }
315
+ case RECORD_GROUP: break;
316
+ default: {
317
+ const vector = geometry === void 0 ? void 0 : readPrimitiveVector(type, data, geometry, state);
318
+ if (vector === void 0) skipped.add(recordName(type));
319
+ else {
320
+ vectors.push({
321
+ ...vector,
322
+ paintOrder
323
+ });
324
+ paintOrder += 1;
325
+ }
326
+ break;
327
+ }
328
+ }
329
+ if (type !== RECORD_TEXT_BLOCK) pendingTextBlockFrame = void 0;
330
+ }
331
+ while (groups.length > 0 && groups[groups.length - 1]?.remaining === 0) groups.pop();
332
+ if (extension.value > 0) groups.push({
333
+ remaining: extension.value,
334
+ membersWalk: !swallowed && (type === RECORD_GROUP || type === RECORD_TEXT_BLOCK && pendingTextBlockFrame !== void 0)
335
+ });
336
+ cursor = recordEnd;
337
+ }
338
+ if (geometry === void 0) return {
339
+ status: "refused",
340
+ reason: "malformed"
341
+ };
342
+ return {
343
+ status: "decoded",
344
+ sizePt: {
345
+ widthPt: geometry.widthPt,
346
+ heightPt: geometry.heightPt
347
+ },
348
+ vectors,
349
+ shapes,
350
+ skippedRecords: [...skipped]
351
+ };
352
+ }
353
+ function swallowedByOpenGroup(groups) {
354
+ const innermost = groups[groups.length - 1];
355
+ return innermost !== void 0 && !innermost.membersWalk;
356
+ }
357
+ function readTextBlockFrame(data, geometry) {
358
+ if (geometry === void 0) return;
359
+ const characterization = readCharacterization(data, 0, data.length);
360
+ if (characterization === void 0 || characterization.geometryAt < 0 || characterization.geometryAt + geometry.coordinateSize * 4 > data.length) return;
361
+ const at = characterization.geometryAt;
362
+ return frameFromCorners(geometry, coordinateAt(data, at, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize * 2, geometry.doublePrecision), coordinateAt(data, at + geometry.coordinateSize * 3, geometry.doublePrecision));
363
+ }
364
+ function frameFromCorners(geometry, x1, y1, x2, y2) {
365
+ const left = Math.min(xToPt(geometry, x1), xToPt(geometry, x2));
366
+ const right = Math.max(xToPt(geometry, x1), xToPt(geometry, x2));
367
+ const top = Math.min(yToPt(geometry, y1), yToPt(geometry, y2));
368
+ const bottom = Math.max(yToPt(geometry, y1), yToPt(geometry, y2));
369
+ return {
370
+ xPt: left,
371
+ yPt: top,
372
+ widthPt: right - left,
373
+ heightPt: bottom - top
374
+ };
375
+ }
376
+ function readPrimitiveVector(type, data, geometry, state) {
377
+ const characterization = readCharacterization(data, 0, data.length);
378
+ if (characterization === void 0 || characterization.geometryAt < 0) return;
379
+ const { flags, geometryAt } = characterization;
380
+ const stroke = (flags & FLAG_FRAME) !== 0 ? strokeOf(geometry, state) : void 0;
381
+ switch (type) {
382
+ case RECORD_POLYLINE: return readPolyline(data, geometry, flags, geometryAt, stroke, state);
383
+ case RECORD_RECTANGLE: return readWpgRectangle(data, geometry, flags, geometryAt, stroke, state);
384
+ case RECORD_ARC: return readWpgFullEllipse(data, geometry, flags, geometryAt, stroke, state);
385
+ default: return;
386
+ }
387
+ }
388
+ function readPolyline(data, geometry, flags, geometryAt, stroke, state) {
389
+ if (geometryAt + 2 > data.length) return;
390
+ const count = require_bytes_view.uint16At(data, geometryAt);
391
+ let at = geometryAt + 2;
392
+ const points = [];
393
+ for (let index = 0; index < count; index += 1) {
394
+ if (at + geometry.coordinateSize * 2 > data.length) return;
395
+ points.push({
396
+ xPt: xToPt(geometry, coordinateAt(data, at, geometry.doublePrecision)),
397
+ yPt: yToPt(geometry, coordinateAt(data, at + geometry.coordinateSize, geometry.doublePrecision))
398
+ });
399
+ at += geometry.coordinateSize * 2;
400
+ }
401
+ const firstPoint = points[0];
402
+ if (firstPoint === void 0) return;
403
+ const secondPoint = points[1];
404
+ const closed = (flags & FLAG_CLOSE) !== 0;
405
+ const filled = (flags & FLAG_FILL) !== 0;
406
+ if (points.length === 2 && secondPoint !== void 0 && !closed && stroke !== void 0) return {
407
+ kind: "line",
408
+ from: firstPoint,
409
+ to: secondPoint,
410
+ stroke
411
+ };
412
+ const frame = boundingFrame(points);
413
+ const local = points.map((point) => ({
414
+ xPt: point.xPt - frame.xPt,
415
+ yPt: point.yPt - frame.yPt
416
+ }));
417
+ const subpath = {
418
+ start: {
419
+ xPt: firstPoint.xPt - frame.xPt,
420
+ yPt: firstPoint.yPt - frame.yPt
421
+ },
422
+ segments: local.slice(1).map((point) => ({
423
+ kind: "line",
424
+ to: point
425
+ })),
426
+ closed
427
+ };
428
+ const fill = filled ? fillOf(state) : void 0;
429
+ return {
430
+ kind: "path",
431
+ frame,
432
+ subpaths: [subpath],
433
+ ...fill !== void 0 ? {
434
+ fill: fill.fill,
435
+ ...fill.fillOpacity < 1 ? { fillOpacity: fill.fillOpacity } : {},
436
+ ...(flags & FLAG_PATH_WINDING) !== 0 ? { fillRule: "nonzero" } : {}
437
+ } : {},
438
+ ...stroke !== void 0 ? { stroke } : {}
439
+ };
440
+ }
441
+ function boundingFrame(points) {
442
+ let minX = Number.POSITIVE_INFINITY;
443
+ let minY = Number.POSITIVE_INFINITY;
444
+ let maxX = Number.NEGATIVE_INFINITY;
445
+ let maxY = Number.NEGATIVE_INFINITY;
446
+ for (const point of points) {
447
+ minX = Math.min(minX, point.xPt);
448
+ minY = Math.min(minY, point.yPt);
449
+ maxX = Math.max(maxX, point.xPt);
450
+ maxY = Math.max(maxY, point.yPt);
451
+ }
452
+ return {
453
+ xPt: minX,
454
+ yPt: minY,
455
+ widthPt: maxX - minX,
456
+ heightPt: maxY - minY
457
+ };
458
+ }
459
+ function readWpgRectangle(data, geometry, flags, geometryAt, stroke, state) {
460
+ const coordinateSize = geometry.coordinateSize;
461
+ if (geometryAt + coordinateSize * 6 > data.length) return;
462
+ const xll = coordinateAt(data, geometryAt, geometry.doublePrecision);
463
+ const yll = coordinateAt(data, geometryAt + coordinateSize, geometry.doublePrecision);
464
+ const xur = coordinateAt(data, geometryAt + coordinateSize * 2, geometry.doublePrecision);
465
+ const yur = coordinateAt(data, geometryAt + coordinateSize * 3, geometry.doublePrecision);
466
+ const rx = coordinateAt(data, geometryAt + coordinateSize * 4, geometry.doublePrecision);
467
+ const ry = coordinateAt(data, geometryAt + coordinateSize * 5, geometry.doublePrecision);
468
+ const frame = frameFromCorners(geometry, xll, yll, xur, yur);
469
+ const fill = (flags & FLAG_FILL) !== 0 ? fillOf(state) : void 0;
470
+ const fillFields = fill !== void 0 ? {
471
+ fill: fill.fill,
472
+ ...fill.fillOpacity < 1 ? { fillOpacity: fill.fillOpacity } : {}
473
+ } : {};
474
+ if (rx <= 0 || ry <= 0) return {
475
+ kind: "rect",
476
+ frame,
477
+ ...fillFields,
478
+ ...stroke !== void 0 ? { stroke } : {}
479
+ };
480
+ const cornerRxPt = Math.min(rx / geometry.xPpi * POINTS_PER_INCH, frame.widthPt / 2);
481
+ const cornerRyPt = Math.min(ry / geometry.yPpi * POINTS_PER_INCH, frame.heightPt / 2);
482
+ const kx = cornerRxPt * QUARTER_ELLIPSE_KAPPA;
483
+ const ky = cornerRyPt * QUARTER_ELLIPSE_KAPPA;
484
+ const width = frame.widthPt;
485
+ const height = frame.heightPt;
486
+ const left = {
487
+ xPt: 0,
488
+ yPt: height / 2
489
+ };
490
+ return {
491
+ kind: "path",
492
+ frame,
493
+ subpaths: [{
494
+ start: left,
495
+ closed: true,
496
+ segments: [
497
+ {
498
+ kind: "line",
499
+ to: {
500
+ xPt: cornerRxPt,
501
+ yPt: 0
502
+ }
503
+ },
504
+ {
505
+ kind: "cubic",
506
+ control1: {
507
+ xPt: cornerRxPt - kx,
508
+ yPt: 0
509
+ },
510
+ control2: {
511
+ xPt: width,
512
+ yPt: cornerRyPt - ky
513
+ },
514
+ to: {
515
+ xPt: width,
516
+ yPt: cornerRyPt
517
+ }
518
+ },
519
+ {
520
+ kind: "line",
521
+ to: {
522
+ xPt: width,
523
+ yPt: height - cornerRyPt
524
+ }
525
+ },
526
+ {
527
+ kind: "cubic",
528
+ control1: {
529
+ xPt: width,
530
+ yPt: height - cornerRyPt + ky
531
+ },
532
+ control2: {
533
+ xPt: width - cornerRxPt + kx,
534
+ yPt: height
535
+ },
536
+ to: {
537
+ xPt: width - cornerRxPt,
538
+ yPt: height
539
+ }
540
+ },
541
+ {
542
+ kind: "line",
543
+ to: {
544
+ xPt: cornerRxPt,
545
+ yPt: height
546
+ }
547
+ },
548
+ {
549
+ kind: "cubic",
550
+ control1: {
551
+ xPt: cornerRxPt - kx,
552
+ yPt: height
553
+ },
554
+ control2: {
555
+ xPt: 0,
556
+ yPt: height - cornerRyPt + ky
557
+ },
558
+ to: {
559
+ xPt: 0,
560
+ yPt: height - cornerRyPt
561
+ }
562
+ },
563
+ {
564
+ kind: "line",
565
+ to: {
566
+ xPt: 0,
567
+ yPt: cornerRyPt
568
+ }
569
+ },
570
+ {
571
+ kind: "cubic",
572
+ control1: {
573
+ xPt: 0,
574
+ yPt: cornerRyPt - ky
575
+ },
576
+ control2: {
577
+ xPt: cornerRxPt - kx,
578
+ yPt: 0
579
+ },
580
+ to: {
581
+ xPt: cornerRxPt,
582
+ yPt: 0
583
+ }
584
+ },
585
+ {
586
+ kind: "line",
587
+ to: left
588
+ }
589
+ ]
590
+ }],
591
+ ...fillFields,
592
+ ...stroke !== void 0 ? { stroke } : {}
593
+ };
594
+ }
595
+ function readWpgFullEllipse(data, geometry, flags, geometryAt, stroke, state) {
596
+ const coordinateSize = geometry.coordinateSize;
597
+ if (geometryAt + coordinateSize * 8 + 1 > data.length) return;
598
+ const cx = coordinateAt(data, geometryAt, geometry.doublePrecision);
599
+ const cy = coordinateAt(data, geometryAt + coordinateSize, geometry.doublePrecision);
600
+ const rx = coordinateAt(data, geometryAt + coordinateSize * 2, geometry.doublePrecision);
601
+ const ry = coordinateAt(data, geometryAt + coordinateSize * 3, geometry.doublePrecision);
602
+ const ix = coordinateAt(data, geometryAt + coordinateSize * 4, geometry.doublePrecision);
603
+ const iy = coordinateAt(data, geometryAt + coordinateSize * 5, geometry.doublePrecision);
604
+ const ex = coordinateAt(data, geometryAt + coordinateSize * 6, geometry.doublePrecision);
605
+ const ey = coordinateAt(data, geometryAt + coordinateSize * 7, geometry.doublePrecision);
606
+ if (ix !== ex || iy !== ey) return;
607
+ const frame = frameFromCorners(geometry, cx - rx, cy - ry, cx + rx, cy + ry);
608
+ const fill = (flags & FLAG_FILL) !== 0 ? fillOf(state) : void 0;
609
+ return {
610
+ kind: "ellipse",
611
+ frame,
612
+ ...fill !== void 0 ? {
613
+ fill: fill.fill,
614
+ ...fill.fillOpacity < 1 ? { fillOpacity: fill.fillOpacity } : {}
615
+ } : {},
616
+ ...stroke !== void 0 ? { stroke } : {}
617
+ };
618
+ }
619
+ //#endregion
620
+ exports.decodeWpgGraphic = decodeWpgGraphic;
@@ -0,0 +1,18 @@
1
+ import { ContentBlock, ContentShape, ContentVector, PageSize } from "document-schema.js";
2
+ //#region src/stream/wpg.d.ts
3
+ type WpgTextFold = (documentArea: Uint8Array) => readonly ContentBlock[];
4
+ type WpgDecode = {
5
+ readonly status: "decoded";
6
+ readonly sizePt: PageSize;
7
+ readonly vectors: readonly ContentVector[];
8
+ readonly shapes: readonly ContentShape[];
9
+ readonly skippedRecords: readonly string[];
10
+ } | {
11
+ readonly status: "refused";
12
+ readonly reason: "wpg1" | "encrypted" | "malformed";
13
+ };
14
+ declare function decodeWpgGraphic(bytes: Uint8Array, options: {
15
+ readonly foldTextData: WpgTextFold;
16
+ }): WpgDecode | undefined;
17
+ //#endregion
18
+ export { WpgDecode, WpgTextFold, decodeWpgGraphic };
@@ -0,0 +1,18 @@
1
+ import { ContentBlock, ContentShape, ContentVector, PageSize } from "document-schema.js";
2
+ //#region src/stream/wpg.d.ts
3
+ type WpgTextFold = (documentArea: Uint8Array) => readonly ContentBlock[];
4
+ type WpgDecode = {
5
+ readonly status: "decoded";
6
+ readonly sizePt: PageSize;
7
+ readonly vectors: readonly ContentVector[];
8
+ readonly shapes: readonly ContentShape[];
9
+ readonly skippedRecords: readonly string[];
10
+ } | {
11
+ readonly status: "refused";
12
+ readonly reason: "wpg1" | "encrypted" | "malformed";
13
+ };
14
+ declare function decodeWpgGraphic(bytes: Uint8Array, options: {
15
+ readonly foldTextData: WpgTextFold;
16
+ }): WpgDecode | undefined;
17
+ //#endregion
18
+ export { WpgDecode, WpgTextFold, decodeWpgGraphic };