emf-converter 1.4.1 โ†’ 1.4.3

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/README.md CHANGED
@@ -1,11 +1,12 @@
1
1
  # emf-converter
2
2
 
3
3
  [![npm version](https://img.shields.io/npm/v/emf-converter.svg)](https://www.npmjs.com/package/emf-converter)
4
- [![license](https://img.shields.io/npm/l/emf-converter.svg)](https://github.com/ChristopherVR/pptx-viewer/blob/main/LICENSE)
4
+ [![CI](https://github.com/ChristopherVR/emf-converter/actions/workflows/ci.yml/badge.svg)](https://github.com/ChristopherVR/emf-converter/actions/workflows/ci.yml)
5
+ [![license](https://img.shields.io/npm/l/emf-converter.svg)](LICENSE)
5
6
 
6
- A zero-dependency TypeScript library that converts **EMF** (Enhanced Metafile) and **WMF** (Windows Metafile) binary buffers into **PNG data URLs** by parsing their record streams and replaying drawing commands onto an HTML Canvas.
7
+ A zero-dependency TypeScript library that converts **EMF** (Enhanced Metafile) and **WMF** (Windows Metafile) binary buffers into **PNG data URLs** by parsing their record streams and replaying the drawing commands onto an HTML Canvas.
7
8
 
8
- Windows Metafiles store a sequence of GDI drawing commands and are commonly embedded inside Office documents (PPTX, DOCX). This converter reads the raw binary, interprets each record, and replays the drawing operations onto a Canvas to produce a rasterised PNG. It handles three formats:
9
+ Windows Metafiles store a sequence of GDI drawing commands and are commonly embedded inside Office documents (Word, PowerPoint) and Windows clipboard data. This converter reads the raw binary, interprets each record, and replays the drawing operations onto a Canvas to produce a rasterised PNG. It handles three formats:
9
10
 
10
11
  | Format | Description | Coordinate system |
11
12
  | -------- | ------------------------------ | ----------------------- |
@@ -13,10 +14,16 @@ Windows Metafiles store a sequence of GDI drawing commands and are commonly embe
13
14
  | **EMF** | Enhanced Metafile (32-bit GDI) | Bounds-based scaling |
14
15
  | **EMF+** | GDI+ extension embedded in EMF | World transform matrix |
15
16
 
16
- <samp>**[๐Ÿ“ฆ npm](https://www.npmjs.com/package/emf-converter)** ยท **[๐Ÿ“– Full docs](https://christophervr.github.io/pptx-viewer/)**</samp>
17
+ <samp>**[โ–ถ๏ธ Live demo](https://christophervr.github.io/emf-converter/)** ยท **[๐Ÿ“ฆ npm](https://www.npmjs.com/package/emf-converter)**</samp>
17
18
 
18
19
  ---
19
20
 
21
+ ## Demo
22
+
23
+ Try it right in your browser โ€” drop in an `.emf` or `.wmf` file and see the rendered PNG, conversion time, and output size:
24
+
25
+ **https://christophervr.github.io/emf-converter/**
26
+
20
27
  ## Install
21
28
 
22
29
  ```bash
@@ -57,7 +64,7 @@ Both functions return `Promise<string | null>` โ€” `null` if the buffer is inval
57
64
 
58
65
  A three-phase pipeline: **parse โ†’ replay โ†’ export**. The header parser extracts the drawing bounds, a Canvas is created and clamped to 4096ร—4096, then records are scanned sequentially and dispatched to GDI, EMF+, or WMF handlers that drive the Canvas 2D context. Embedded bitmaps (DIB and GDI+ pixel formats) and recursively embedded metafiles are resolved asynchronously after the synchronous replay completes.
59
66
 
60
- It supports 300+ EMF GDI record types, the EMF+ (GDI+) record set, and legacy WMF records, including state, transforms, objects, shapes, poly/path operations, text, bitmaps, and clipping. For the full record-type coverage, coordinate-system details, object tables, and module maps, see the [full documentation](https://christophervr.github.io/pptx-viewer/).
67
+ It supports 300+ EMF GDI record types, the EMF+ (GDI+) record set, and legacy WMF records, including state, transforms, objects, shapes, poly/path operations, text, bitmaps, and clipping.
61
68
 
62
69
  ## Limitations
63
70
 
@@ -70,4 +77,4 @@ It supports 300+ EMF GDI record types, the EMF+ (GDI+) record set, and legacy WM
70
77
 
71
78
  ## License
72
79
 
73
- [Apache-2.0](LICENSE). Please keep the [`NOTICE`](NOTICE) file with redistributions.
80
+ [Apache-2.0](LICENSE) โ€” free for commercial and closed-source use, with an explicit patent grant.
package/dist/index.js CHANGED
@@ -3893,7 +3893,13 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3893
3893
  const windowExt = { cx: logicalW, cy: logicalH };
3894
3894
  const coord = createWmfCoord(windowOrg, windowExt, canvasW, canvasH);
3895
3895
  const objectTable = /* @__PURE__ */ new Map();
3896
- let nextObjectSlot = 0;
3896
+ const allocObjectSlot = () => {
3897
+ let slot = 0;
3898
+ while (objectTable.has(slot)) {
3899
+ slot++;
3900
+ }
3901
+ return slot;
3902
+ };
3897
3903
  const state = defaultState();
3898
3904
  const stateStack = [];
3899
3905
  const wCtx = { view, ctx, state, coord };
@@ -3969,7 +3975,7 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3969
3975
  break;
3970
3976
  case META_CREATEPENINDIRECT:
3971
3977
  if (recSize >= 16) {
3972
- const slot = nextObjectSlot++;
3978
+ const slot = allocObjectSlot();
3973
3979
  objectTable.set(slot, {
3974
3980
  kind: "pen",
3975
3981
  style: view.getUint16(dataOff, true) & 255,
@@ -3980,7 +3986,7 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3980
3986
  break;
3981
3987
  case META_CREATEBRUSHINDIRECT:
3982
3988
  if (recSize >= 14) {
3983
- const slot = nextObjectSlot++;
3989
+ const slot = allocObjectSlot();
3984
3990
  objectTable.set(slot, {
3985
3991
  kind: "brush",
3986
3992
  style: view.getUint16(dataOff, true),
@@ -3998,7 +4004,7 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3998
4004
  }
3999
4005
  family += String.fromCharCode(ch);
4000
4006
  }
4001
- const slot = nextObjectSlot++;
4007
+ const slot = allocObjectSlot();
4002
4008
  objectTable.set(slot, {
4003
4009
  kind: "font",
4004
4010
  height: Math.abs(view.getInt16(dataOff, true)),
package/dist/index.mjs CHANGED
@@ -3891,7 +3891,13 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3891
3891
  const windowExt = { cx: logicalW, cy: logicalH };
3892
3892
  const coord = createWmfCoord(windowOrg, windowExt, canvasW, canvasH);
3893
3893
  const objectTable = /* @__PURE__ */ new Map();
3894
- let nextObjectSlot = 0;
3894
+ const allocObjectSlot = () => {
3895
+ let slot = 0;
3896
+ while (objectTable.has(slot)) {
3897
+ slot++;
3898
+ }
3899
+ return slot;
3900
+ };
3895
3901
  const state = defaultState();
3896
3902
  const stateStack = [];
3897
3903
  const wCtx = { view, ctx, state, coord };
@@ -3967,7 +3973,7 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3967
3973
  break;
3968
3974
  case META_CREATEPENINDIRECT:
3969
3975
  if (recSize >= 16) {
3970
- const slot = nextObjectSlot++;
3976
+ const slot = allocObjectSlot();
3971
3977
  objectTable.set(slot, {
3972
3978
  kind: "pen",
3973
3979
  style: view.getUint16(dataOff, true) & 255,
@@ -3978,7 +3984,7 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3978
3984
  break;
3979
3985
  case META_CREATEBRUSHINDIRECT:
3980
3986
  if (recSize >= 14) {
3981
- const slot = nextObjectSlot++;
3987
+ const slot = allocObjectSlot();
3982
3988
  objectTable.set(slot, {
3983
3989
  kind: "brush",
3984
3990
  style: view.getUint16(dataOff, true),
@@ -3996,7 +4002,7 @@ function replayWmfRecords(view, ctx, header, canvasW, canvasH) {
3996
4002
  }
3997
4003
  family += String.fromCharCode(ch);
3998
4004
  }
3999
- const slot = nextObjectSlot++;
4005
+ const slot = allocObjectSlot();
4000
4006
  objectTable.set(slot, {
4001
4007
  kind: "font",
4002
4008
  height: Math.abs(view.getInt16(dataOff, true)),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "Convert EMF/WMF metafile binaries to PNG data URLs using Canvas",
5
5
  "keywords": [
6
6
  "canvas",
@@ -47,6 +47,6 @@
47
47
  "devDependencies": {
48
48
  "tsup": "^8.5.1",
49
49
  "typescript": "^6.0.3",
50
- "vitest": "^4.1.8"
50
+ "vitest": "^4.1.9"
51
51
  }
52
52
  }