emf-converter 4.18.0 → 4.18.2

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
@@ -144,6 +144,11 @@ Without `fonts`, text is drawn by the host's canvas font engine (supply `fontFam
144
144
 
145
145
  #### `EmfConvertOptions`
146
146
 
147
+ `wmfAnsiCodePage` sets the known ANSI code page of a WMF playback device
148
+ (for example, `936` from Windows `GetACP()`). It applies to ANSI/DEFAULT text
149
+ and ANSI font face names. Its default is `1252`; explicit text charsets and
150
+ EMF text are unchanged. See the [API reference](docs/api.md) for supported values.
151
+
147
152
  | Field | Type | Default | Description |
148
153
  | -------------------- | ------------------------------------- | ----------------- | ----------- |
149
154
  | `maxWidth` | `number` | None | Maximum output width in pixels (aspect ratio preserved) |
package/dist/browser.js CHANGED
@@ -29639,6 +29639,12 @@ function gdiDevicePixelX(r) {
29639
29639
  function gdiDevicePixelY(r) {
29640
29640
  return !r.useMappingMode || r.deviceToCanvas ? r.sy : 1;
29641
29641
  }
29642
+ function gdiDeviceToCanvasX(r, x) {
29643
+ return !r.useMappingMode || r.deviceToCanvas ? (x - r.bounds.left) * r.sx : x;
29644
+ }
29645
+ function gdiDeviceToCanvasY(r, y) {
29646
+ return !r.useMappingMode || r.deviceToCanvas ? (y - r.bounds.top) * r.sy : y;
29647
+ }
29642
29648
  function activateGdiMappingMode(r) {
29643
29649
  r.useMappingMode = true;
29644
29650
  }
@@ -36217,7 +36223,25 @@ var CHARSET_ENCODING = {
36217
36223
  238: "windows-1250",
36218
36224
  255: "ibm437"
36219
36225
  };
36220
- function decodeAnsiRecord(bytes, charSet) {
36226
+ var ANSI_CODE_PAGE_ENCODING = {
36227
+ 874: "windows-874",
36228
+ 932: "shift_jis",
36229
+ 936: "gbk",
36230
+ 949: "euc-kr",
36231
+ 950: "big5",
36232
+ 1250: "windows-1250",
36233
+ 1251: "windows-1251",
36234
+ 1252: "windows-1252",
36235
+ 1253: "windows-1253",
36236
+ 1254: "windows-1254",
36237
+ 1255: "windows-1255",
36238
+ 1256: "windows-1256",
36239
+ 1257: "windows-1257",
36240
+ 1258: "windows-1258",
36241
+ 54936: "gb18030",
36242
+ 65001: "utf-8"
36243
+ };
36244
+ function decodeAnsiRecord(bytes, charSet, ansiCodePage) {
36221
36245
  if (charSet === 2) {
36222
36246
  return { codes: [...bytes], byteLengths: bytes.map(() => 1) };
36223
36247
  }
@@ -36238,10 +36262,13 @@ function decodeAnsiRecord(bytes, charSet) {
36238
36262
  }
36239
36263
  return { codes, byteLengths };
36240
36264
  }
36241
- const label = CHARSET_ENCODING[charSet] ?? "windows-1252";
36265
+ const label = (charSet === 0 || charSet === 1) && ansiCodePage !== void 0 ? ANSI_CODE_PAGE_ENCODING[ansiCodePage] ?? "windows-1252" : CHARSET_ENCODING[charSet] ?? "windows-1252";
36266
+ if (label === "windows-1252") {
36267
+ return { codes: bytes.map((b) => ansiToCode(b, charSet)), byteLengths: bytes.map(() => 1) };
36268
+ }
36242
36269
  try {
36243
- const decoder = new TextDecoder(label, { fatal: true });
36244
- const replacementDecoder = new TextDecoder(label);
36270
+ const decoder = new TextDecoder(label, { fatal: true, ignoreBOM: true });
36271
+ const replacementDecoder = new TextDecoder(label, { ignoreBOM: true });
36245
36272
  const source = new Uint8Array(bytes);
36246
36273
  const codes = [];
36247
36274
  const byteLengths = [];
@@ -37234,11 +37261,13 @@ function handleExtSelectClipRgn(rCtx, dataOff, recSize) {
37234
37261
  const top = view.getInt32(rOff + 4, true);
37235
37262
  const right = view.getInt32(rOff + 8, true);
37236
37263
  const bottom = view.getInt32(rOff + 12, true);
37264
+ const x = gdiDeviceToCanvasX(rCtx, left);
37265
+ const y = gdiDeviceToCanvasY(rCtx, top);
37237
37266
  rects.push({
37238
- x: gmx(rCtx, left),
37239
- y: gmy(rCtx, top),
37240
- w: gmw(rCtx, right - left),
37241
- h: gmh(rCtx, bottom - top)
37267
+ x,
37268
+ y,
37269
+ w: gdiDeviceToCanvasX(rCtx, right) - x,
37270
+ h: gdiDeviceToCanvasY(rCtx, bottom) - y
37242
37271
  });
37243
37272
  }
37244
37273
  if (rects.length === 0) {
@@ -37253,7 +37282,11 @@ function handleOffsetClipRgn(rCtx, dataOff, recSize) {
37253
37282
  const dx = rCtx.view.getInt32(dataOff, true);
37254
37283
  const dy = rCtx.view.getInt32(dataOff + 4, true);
37255
37284
  if (rCtx.clipRegion) {
37256
- rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, gmw(rCtx, dx), gmh(rCtx, dy));
37285
+ const px = gdiDevicePixelX(rCtx);
37286
+ const py = gdiDevicePixelY(rCtx);
37287
+ const ox = Math.round(gmw(rCtx, dx) / px) * px;
37288
+ const oy = Math.round(gmh(rCtx, dy) / py) * py;
37289
+ rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, ox, oy);
37257
37290
  reapplyClipRegion(rCtx, rCtx.clipRegion);
37258
37291
  }
37259
37292
  }
@@ -41494,14 +41527,15 @@ function createFont(p, dataOff, recSize, recEnd) {
41494
41527
  addObject(p, { kind: "other" });
41495
41528
  return;
41496
41529
  }
41497
- let family = "";
41530
+ const faceBytes = [];
41498
41531
  for (let i = 0; i < 32 && dataOff + 18 + i < recEnd; i++) {
41499
41532
  const ch = view.getUint8(dataOff + 18 + i);
41500
41533
  if (ch === 0) {
41501
41534
  break;
41502
41535
  }
41503
- family += String.fromCharCode(ch);
41536
+ faceBytes.push(ch);
41504
41537
  }
41538
+ const family = String.fromCharCode(...decodeAnsiRecord(faceBytes, 1, p.ansiCodePage).codes);
41505
41539
  const font = {
41506
41540
  kind: "font",
41507
41541
  // Sign kept: resolveFontPixelHeight() tells cell from character height by it.
@@ -42528,7 +42562,7 @@ function drawWithFontEngine2(p, call, codes, dx) {
42528
42562
  }
42529
42563
  function playText(p, call) {
42530
42564
  const charSet = p.rCtx.state.fontDetails?.charSet ?? 1;
42531
- const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet);
42565
+ const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet, p.ansiCodePage);
42532
42566
  const n = codes.length;
42533
42567
  if (n === 0) {
42534
42568
  return;
@@ -42660,6 +42694,7 @@ function createWmfPlayer(view, ctx, header, canvasW, canvasH, replayOptions = {}
42660
42694
  };
42661
42695
  const p = {
42662
42696
  rCtx,
42697
+ ansiCodePage: replayOptions.wmfAnsiCodePage,
42663
42698
  view,
42664
42699
  kx,
42665
42700
  ky,
@@ -43191,6 +43226,7 @@ async function replayMetafile(buffer, options2, createSurface) {
43191
43226
  surface.ctx.save();
43192
43227
  replayWmfRecords(view, surface.ctx, header, surface.width, surface.height, {
43193
43228
  wmfReferenceDpi: opts.wmfReferenceDpi,
43229
+ wmfAnsiCodePage: opts.wmfAnsiCodePage,
43194
43230
  maxRecords: opts.maxRecords,
43195
43231
  fontFamilyMap: opts.fontFamilyMap,
43196
43232
  gdiAntialias: opts.gdiAntialias,
package/dist/browser.mjs CHANGED
@@ -29637,6 +29637,12 @@ function gdiDevicePixelX(r) {
29637
29637
  function gdiDevicePixelY(r) {
29638
29638
  return !r.useMappingMode || r.deviceToCanvas ? r.sy : 1;
29639
29639
  }
29640
+ function gdiDeviceToCanvasX(r, x) {
29641
+ return !r.useMappingMode || r.deviceToCanvas ? (x - r.bounds.left) * r.sx : x;
29642
+ }
29643
+ function gdiDeviceToCanvasY(r, y) {
29644
+ return !r.useMappingMode || r.deviceToCanvas ? (y - r.bounds.top) * r.sy : y;
29645
+ }
29640
29646
  function activateGdiMappingMode(r) {
29641
29647
  r.useMappingMode = true;
29642
29648
  }
@@ -36215,7 +36221,25 @@ var CHARSET_ENCODING = {
36215
36221
  238: "windows-1250",
36216
36222
  255: "ibm437"
36217
36223
  };
36218
- function decodeAnsiRecord(bytes, charSet) {
36224
+ var ANSI_CODE_PAGE_ENCODING = {
36225
+ 874: "windows-874",
36226
+ 932: "shift_jis",
36227
+ 936: "gbk",
36228
+ 949: "euc-kr",
36229
+ 950: "big5",
36230
+ 1250: "windows-1250",
36231
+ 1251: "windows-1251",
36232
+ 1252: "windows-1252",
36233
+ 1253: "windows-1253",
36234
+ 1254: "windows-1254",
36235
+ 1255: "windows-1255",
36236
+ 1256: "windows-1256",
36237
+ 1257: "windows-1257",
36238
+ 1258: "windows-1258",
36239
+ 54936: "gb18030",
36240
+ 65001: "utf-8"
36241
+ };
36242
+ function decodeAnsiRecord(bytes, charSet, ansiCodePage) {
36219
36243
  if (charSet === 2) {
36220
36244
  return { codes: [...bytes], byteLengths: bytes.map(() => 1) };
36221
36245
  }
@@ -36236,10 +36260,13 @@ function decodeAnsiRecord(bytes, charSet) {
36236
36260
  }
36237
36261
  return { codes, byteLengths };
36238
36262
  }
36239
- const label = CHARSET_ENCODING[charSet] ?? "windows-1252";
36263
+ const label = (charSet === 0 || charSet === 1) && ansiCodePage !== void 0 ? ANSI_CODE_PAGE_ENCODING[ansiCodePage] ?? "windows-1252" : CHARSET_ENCODING[charSet] ?? "windows-1252";
36264
+ if (label === "windows-1252") {
36265
+ return { codes: bytes.map((b) => ansiToCode(b, charSet)), byteLengths: bytes.map(() => 1) };
36266
+ }
36240
36267
  try {
36241
- const decoder = new TextDecoder(label, { fatal: true });
36242
- const replacementDecoder = new TextDecoder(label);
36268
+ const decoder = new TextDecoder(label, { fatal: true, ignoreBOM: true });
36269
+ const replacementDecoder = new TextDecoder(label, { ignoreBOM: true });
36243
36270
  const source = new Uint8Array(bytes);
36244
36271
  const codes = [];
36245
36272
  const byteLengths = [];
@@ -37232,11 +37259,13 @@ function handleExtSelectClipRgn(rCtx, dataOff, recSize) {
37232
37259
  const top = view.getInt32(rOff + 4, true);
37233
37260
  const right = view.getInt32(rOff + 8, true);
37234
37261
  const bottom = view.getInt32(rOff + 12, true);
37262
+ const x = gdiDeviceToCanvasX(rCtx, left);
37263
+ const y = gdiDeviceToCanvasY(rCtx, top);
37235
37264
  rects.push({
37236
- x: gmx(rCtx, left),
37237
- y: gmy(rCtx, top),
37238
- w: gmw(rCtx, right - left),
37239
- h: gmh(rCtx, bottom - top)
37265
+ x,
37266
+ y,
37267
+ w: gdiDeviceToCanvasX(rCtx, right) - x,
37268
+ h: gdiDeviceToCanvasY(rCtx, bottom) - y
37240
37269
  });
37241
37270
  }
37242
37271
  if (rects.length === 0) {
@@ -37251,7 +37280,11 @@ function handleOffsetClipRgn(rCtx, dataOff, recSize) {
37251
37280
  const dx = rCtx.view.getInt32(dataOff, true);
37252
37281
  const dy = rCtx.view.getInt32(dataOff + 4, true);
37253
37282
  if (rCtx.clipRegion) {
37254
- rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, gmw(rCtx, dx), gmh(rCtx, dy));
37283
+ const px = gdiDevicePixelX(rCtx);
37284
+ const py = gdiDevicePixelY(rCtx);
37285
+ const ox = Math.round(gmw(rCtx, dx) / px) * px;
37286
+ const oy = Math.round(gmh(rCtx, dy) / py) * py;
37287
+ rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, ox, oy);
37255
37288
  reapplyClipRegion(rCtx, rCtx.clipRegion);
37256
37289
  }
37257
37290
  }
@@ -41492,14 +41525,15 @@ function createFont(p, dataOff, recSize, recEnd) {
41492
41525
  addObject(p, { kind: "other" });
41493
41526
  return;
41494
41527
  }
41495
- let family = "";
41528
+ const faceBytes = [];
41496
41529
  for (let i = 0; i < 32 && dataOff + 18 + i < recEnd; i++) {
41497
41530
  const ch = view.getUint8(dataOff + 18 + i);
41498
41531
  if (ch === 0) {
41499
41532
  break;
41500
41533
  }
41501
- family += String.fromCharCode(ch);
41534
+ faceBytes.push(ch);
41502
41535
  }
41536
+ const family = String.fromCharCode(...decodeAnsiRecord(faceBytes, 1, p.ansiCodePage).codes);
41503
41537
  const font = {
41504
41538
  kind: "font",
41505
41539
  // Sign kept: resolveFontPixelHeight() tells cell from character height by it.
@@ -42526,7 +42560,7 @@ function drawWithFontEngine2(p, call, codes, dx) {
42526
42560
  }
42527
42561
  function playText(p, call) {
42528
42562
  const charSet = p.rCtx.state.fontDetails?.charSet ?? 1;
42529
- const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet);
42563
+ const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet, p.ansiCodePage);
42530
42564
  const n = codes.length;
42531
42565
  if (n === 0) {
42532
42566
  return;
@@ -42658,6 +42692,7 @@ function createWmfPlayer(view, ctx, header, canvasW, canvasH, replayOptions = {}
42658
42692
  };
42659
42693
  const p = {
42660
42694
  rCtx,
42695
+ ansiCodePage: replayOptions.wmfAnsiCodePage,
42661
42696
  view,
42662
42697
  kx,
42663
42698
  ky,
@@ -43189,6 +43224,7 @@ async function replayMetafile(buffer, options2, createSurface) {
43189
43224
  surface.ctx.save();
43190
43225
  replayWmfRecords(view, surface.ctx, header, surface.width, surface.height, {
43191
43226
  wmfReferenceDpi: opts.wmfReferenceDpi,
43227
+ wmfAnsiCodePage: opts.wmfAnsiCodePage,
43192
43228
  maxRecords: opts.maxRecords,
43193
43229
  fontFamilyMap: opts.fontFamilyMap,
43194
43230
  gdiAntialias: opts.gdiAntialias,
package/dist/index.d.mts CHANGED
@@ -113,6 +113,14 @@ interface EmfConvertOptions {
113
113
  x: number;
114
114
  y: number;
115
115
  };
116
+ /**
117
+ * ANSI code page of the WMF playback device. Used for ANSI/DEFAULT
118
+ * charset text and LOGFONT face names. Defaults to 1252; supply the
119
+ * original Windows device's GetACP() value when known. Supported values:
120
+ * 874, 932, 936, 949, 950, 1250..1258, 54936 and 65001. Other values
121
+ * fall back to 1252. Explicit text charsets and EMF text are unchanged.
122
+ */
123
+ wmfAnsiCodePage?: number;
116
124
  /** Maximum output width in pixels. */
117
125
  maxWidth?: number;
118
126
  /** Maximum output height in pixels. */
package/dist/index.d.ts CHANGED
@@ -113,6 +113,14 @@ interface EmfConvertOptions {
113
113
  x: number;
114
114
  y: number;
115
115
  };
116
+ /**
117
+ * ANSI code page of the WMF playback device. Used for ANSI/DEFAULT
118
+ * charset text and LOGFONT face names. Defaults to 1252; supply the
119
+ * original Windows device's GetACP() value when known. Supported values:
120
+ * 874, 932, 936, 949, 950, 1250..1258, 54936 and 65001. Other values
121
+ * fall back to 1252. Explicit text charsets and EMF text are unchanged.
122
+ */
123
+ wmfAnsiCodePage?: number;
116
124
  /** Maximum output width in pixels. */
117
125
  maxWidth?: number;
118
126
  /** Maximum output height in pixels. */
package/dist/index.js CHANGED
@@ -29640,6 +29640,12 @@ function gdiDevicePixelX(r) {
29640
29640
  function gdiDevicePixelY(r) {
29641
29641
  return !r.useMappingMode || r.deviceToCanvas ? r.sy : 1;
29642
29642
  }
29643
+ function gdiDeviceToCanvasX(r, x) {
29644
+ return !r.useMappingMode || r.deviceToCanvas ? (x - r.bounds.left) * r.sx : x;
29645
+ }
29646
+ function gdiDeviceToCanvasY(r, y) {
29647
+ return !r.useMappingMode || r.deviceToCanvas ? (y - r.bounds.top) * r.sy : y;
29648
+ }
29643
29649
  function activateGdiMappingMode(r) {
29644
29650
  r.useMappingMode = true;
29645
29651
  }
@@ -36218,7 +36224,25 @@ var CHARSET_ENCODING = {
36218
36224
  238: "windows-1250",
36219
36225
  255: "ibm437"
36220
36226
  };
36221
- function decodeAnsiRecord(bytes, charSet) {
36227
+ var ANSI_CODE_PAGE_ENCODING = {
36228
+ 874: "windows-874",
36229
+ 932: "shift_jis",
36230
+ 936: "gbk",
36231
+ 949: "euc-kr",
36232
+ 950: "big5",
36233
+ 1250: "windows-1250",
36234
+ 1251: "windows-1251",
36235
+ 1252: "windows-1252",
36236
+ 1253: "windows-1253",
36237
+ 1254: "windows-1254",
36238
+ 1255: "windows-1255",
36239
+ 1256: "windows-1256",
36240
+ 1257: "windows-1257",
36241
+ 1258: "windows-1258",
36242
+ 54936: "gb18030",
36243
+ 65001: "utf-8"
36244
+ };
36245
+ function decodeAnsiRecord(bytes, charSet, ansiCodePage) {
36222
36246
  if (charSet === 2) {
36223
36247
  return { codes: [...bytes], byteLengths: bytes.map(() => 1) };
36224
36248
  }
@@ -36239,10 +36263,13 @@ function decodeAnsiRecord(bytes, charSet) {
36239
36263
  }
36240
36264
  return { codes, byteLengths };
36241
36265
  }
36242
- const label = CHARSET_ENCODING[charSet] ?? "windows-1252";
36266
+ const label = (charSet === 0 || charSet === 1) && ansiCodePage !== void 0 ? ANSI_CODE_PAGE_ENCODING[ansiCodePage] ?? "windows-1252" : CHARSET_ENCODING[charSet] ?? "windows-1252";
36267
+ if (label === "windows-1252") {
36268
+ return { codes: bytes.map((b) => ansiToCode(b, charSet)), byteLengths: bytes.map(() => 1) };
36269
+ }
36243
36270
  try {
36244
- const decoder = new TextDecoder(label, { fatal: true });
36245
- const replacementDecoder = new TextDecoder(label);
36271
+ const decoder = new TextDecoder(label, { fatal: true, ignoreBOM: true });
36272
+ const replacementDecoder = new TextDecoder(label, { ignoreBOM: true });
36246
36273
  const source = new Uint8Array(bytes);
36247
36274
  const codes = [];
36248
36275
  const byteLengths = [];
@@ -37235,11 +37262,13 @@ function handleExtSelectClipRgn(rCtx, dataOff, recSize) {
37235
37262
  const top = view.getInt32(rOff + 4, true);
37236
37263
  const right = view.getInt32(rOff + 8, true);
37237
37264
  const bottom = view.getInt32(rOff + 12, true);
37265
+ const x = gdiDeviceToCanvasX(rCtx, left);
37266
+ const y = gdiDeviceToCanvasY(rCtx, top);
37238
37267
  rects.push({
37239
- x: gmx(rCtx, left),
37240
- y: gmy(rCtx, top),
37241
- w: gmw(rCtx, right - left),
37242
- h: gmh(rCtx, bottom - top)
37268
+ x,
37269
+ y,
37270
+ w: gdiDeviceToCanvasX(rCtx, right) - x,
37271
+ h: gdiDeviceToCanvasY(rCtx, bottom) - y
37243
37272
  });
37244
37273
  }
37245
37274
  if (rects.length === 0) {
@@ -37254,7 +37283,11 @@ function handleOffsetClipRgn(rCtx, dataOff, recSize) {
37254
37283
  const dx = rCtx.view.getInt32(dataOff, true);
37255
37284
  const dy = rCtx.view.getInt32(dataOff + 4, true);
37256
37285
  if (rCtx.clipRegion) {
37257
- rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, gmw(rCtx, dx), gmh(rCtx, dy));
37286
+ const px = gdiDevicePixelX(rCtx);
37287
+ const py = gdiDevicePixelY(rCtx);
37288
+ const ox = Math.round(gmw(rCtx, dx) / px) * px;
37289
+ const oy = Math.round(gmh(rCtx, dy) / py) * py;
37290
+ rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, ox, oy);
37258
37291
  reapplyClipRegion(rCtx, rCtx.clipRegion);
37259
37292
  }
37260
37293
  }
@@ -41495,14 +41528,15 @@ function createFont(p, dataOff, recSize, recEnd) {
41495
41528
  addObject(p, { kind: "other" });
41496
41529
  return;
41497
41530
  }
41498
- let family = "";
41531
+ const faceBytes = [];
41499
41532
  for (let i = 0; i < 32 && dataOff + 18 + i < recEnd; i++) {
41500
41533
  const ch = view.getUint8(dataOff + 18 + i);
41501
41534
  if (ch === 0) {
41502
41535
  break;
41503
41536
  }
41504
- family += String.fromCharCode(ch);
41537
+ faceBytes.push(ch);
41505
41538
  }
41539
+ const family = String.fromCharCode(...decodeAnsiRecord(faceBytes, 1, p.ansiCodePage).codes);
41506
41540
  const font = {
41507
41541
  kind: "font",
41508
41542
  // Sign kept: resolveFontPixelHeight() tells cell from character height by it.
@@ -42529,7 +42563,7 @@ function drawWithFontEngine2(p, call, codes, dx) {
42529
42563
  }
42530
42564
  function playText(p, call) {
42531
42565
  const charSet = p.rCtx.state.fontDetails?.charSet ?? 1;
42532
- const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet);
42566
+ const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet, p.ansiCodePage);
42533
42567
  const n = codes.length;
42534
42568
  if (n === 0) {
42535
42569
  return;
@@ -42661,6 +42695,7 @@ function createWmfPlayer(view, ctx, header, canvasW, canvasH, replayOptions = {}
42661
42695
  };
42662
42696
  const p = {
42663
42697
  rCtx,
42698
+ ansiCodePage: replayOptions.wmfAnsiCodePage,
42664
42699
  view,
42665
42700
  kx,
42666
42701
  ky,
@@ -43192,6 +43227,7 @@ async function replayMetafile(buffer, options2, createSurface) {
43192
43227
  surface.ctx.save();
43193
43228
  replayWmfRecords(view, surface.ctx, header, surface.width, surface.height, {
43194
43229
  wmfReferenceDpi: opts.wmfReferenceDpi,
43230
+ wmfAnsiCodePage: opts.wmfAnsiCodePage,
43195
43231
  maxRecords: opts.maxRecords,
43196
43232
  fontFamilyMap: opts.fontFamilyMap,
43197
43233
  gdiAntialias: opts.gdiAntialias,
package/dist/index.mjs CHANGED
@@ -29638,6 +29638,12 @@ function gdiDevicePixelX(r) {
29638
29638
  function gdiDevicePixelY(r) {
29639
29639
  return !r.useMappingMode || r.deviceToCanvas ? r.sy : 1;
29640
29640
  }
29641
+ function gdiDeviceToCanvasX(r, x) {
29642
+ return !r.useMappingMode || r.deviceToCanvas ? (x - r.bounds.left) * r.sx : x;
29643
+ }
29644
+ function gdiDeviceToCanvasY(r, y) {
29645
+ return !r.useMappingMode || r.deviceToCanvas ? (y - r.bounds.top) * r.sy : y;
29646
+ }
29641
29647
  function activateGdiMappingMode(r) {
29642
29648
  r.useMappingMode = true;
29643
29649
  }
@@ -36216,7 +36222,25 @@ var CHARSET_ENCODING = {
36216
36222
  238: "windows-1250",
36217
36223
  255: "ibm437"
36218
36224
  };
36219
- function decodeAnsiRecord(bytes, charSet) {
36225
+ var ANSI_CODE_PAGE_ENCODING = {
36226
+ 874: "windows-874",
36227
+ 932: "shift_jis",
36228
+ 936: "gbk",
36229
+ 949: "euc-kr",
36230
+ 950: "big5",
36231
+ 1250: "windows-1250",
36232
+ 1251: "windows-1251",
36233
+ 1252: "windows-1252",
36234
+ 1253: "windows-1253",
36235
+ 1254: "windows-1254",
36236
+ 1255: "windows-1255",
36237
+ 1256: "windows-1256",
36238
+ 1257: "windows-1257",
36239
+ 1258: "windows-1258",
36240
+ 54936: "gb18030",
36241
+ 65001: "utf-8"
36242
+ };
36243
+ function decodeAnsiRecord(bytes, charSet, ansiCodePage) {
36220
36244
  if (charSet === 2) {
36221
36245
  return { codes: [...bytes], byteLengths: bytes.map(() => 1) };
36222
36246
  }
@@ -36237,10 +36261,13 @@ function decodeAnsiRecord(bytes, charSet) {
36237
36261
  }
36238
36262
  return { codes, byteLengths };
36239
36263
  }
36240
- const label = CHARSET_ENCODING[charSet] ?? "windows-1252";
36264
+ const label = (charSet === 0 || charSet === 1) && ansiCodePage !== void 0 ? ANSI_CODE_PAGE_ENCODING[ansiCodePage] ?? "windows-1252" : CHARSET_ENCODING[charSet] ?? "windows-1252";
36265
+ if (label === "windows-1252") {
36266
+ return { codes: bytes.map((b) => ansiToCode(b, charSet)), byteLengths: bytes.map(() => 1) };
36267
+ }
36241
36268
  try {
36242
- const decoder = new TextDecoder(label, { fatal: true });
36243
- const replacementDecoder = new TextDecoder(label);
36269
+ const decoder = new TextDecoder(label, { fatal: true, ignoreBOM: true });
36270
+ const replacementDecoder = new TextDecoder(label, { ignoreBOM: true });
36244
36271
  const source = new Uint8Array(bytes);
36245
36272
  const codes = [];
36246
36273
  const byteLengths = [];
@@ -37233,11 +37260,13 @@ function handleExtSelectClipRgn(rCtx, dataOff, recSize) {
37233
37260
  const top = view.getInt32(rOff + 4, true);
37234
37261
  const right = view.getInt32(rOff + 8, true);
37235
37262
  const bottom = view.getInt32(rOff + 12, true);
37263
+ const x = gdiDeviceToCanvasX(rCtx, left);
37264
+ const y = gdiDeviceToCanvasY(rCtx, top);
37236
37265
  rects.push({
37237
- x: gmx(rCtx, left),
37238
- y: gmy(rCtx, top),
37239
- w: gmw(rCtx, right - left),
37240
- h: gmh(rCtx, bottom - top)
37266
+ x,
37267
+ y,
37268
+ w: gdiDeviceToCanvasX(rCtx, right) - x,
37269
+ h: gdiDeviceToCanvasY(rCtx, bottom) - y
37241
37270
  });
37242
37271
  }
37243
37272
  if (rects.length === 0) {
@@ -37252,7 +37281,11 @@ function handleOffsetClipRgn(rCtx, dataOff, recSize) {
37252
37281
  const dx = rCtx.view.getInt32(dataOff, true);
37253
37282
  const dy = rCtx.view.getInt32(dataOff + 4, true);
37254
37283
  if (rCtx.clipRegion) {
37255
- rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, gmw(rCtx, dx), gmh(rCtx, dy));
37284
+ const px = gdiDevicePixelX(rCtx);
37285
+ const py = gdiDevicePixelY(rCtx);
37286
+ const ox = Math.round(gmw(rCtx, dx) / px) * px;
37287
+ const oy = Math.round(gmh(rCtx, dy) / py) * py;
37288
+ rCtx.clipRegion = translateClipRegion(rCtx.clipRegion, ox, oy);
37256
37289
  reapplyClipRegion(rCtx, rCtx.clipRegion);
37257
37290
  }
37258
37291
  }
@@ -41493,14 +41526,15 @@ function createFont(p, dataOff, recSize, recEnd) {
41493
41526
  addObject(p, { kind: "other" });
41494
41527
  return;
41495
41528
  }
41496
- let family = "";
41529
+ const faceBytes = [];
41497
41530
  for (let i = 0; i < 32 && dataOff + 18 + i < recEnd; i++) {
41498
41531
  const ch = view.getUint8(dataOff + 18 + i);
41499
41532
  if (ch === 0) {
41500
41533
  break;
41501
41534
  }
41502
- family += String.fromCharCode(ch);
41535
+ faceBytes.push(ch);
41503
41536
  }
41537
+ const family = String.fromCharCode(...decodeAnsiRecord(faceBytes, 1, p.ansiCodePage).codes);
41504
41538
  const font = {
41505
41539
  kind: "font",
41506
41540
  // Sign kept: resolveFontPixelHeight() tells cell from character height by it.
@@ -42527,7 +42561,7 @@ function drawWithFontEngine2(p, call, codes, dx) {
42527
42561
  }
42528
42562
  function playText(p, call) {
42529
42563
  const charSet = p.rCtx.state.fontDetails?.charSet ?? 1;
42530
- const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet);
42564
+ const { codes, byteLengths } = decodeAnsiRecord(call.bytes, charSet, p.ansiCodePage);
42531
42565
  const n = codes.length;
42532
42566
  if (n === 0) {
42533
42567
  return;
@@ -42659,6 +42693,7 @@ function createWmfPlayer(view, ctx, header, canvasW, canvasH, replayOptions = {}
42659
42693
  };
42660
42694
  const p = {
42661
42695
  rCtx,
42696
+ ansiCodePage: replayOptions.wmfAnsiCodePage,
42662
42697
  view,
42663
42698
  kx,
42664
42699
  ky,
@@ -43190,6 +43225,7 @@ async function replayMetafile(buffer, options2, createSurface) {
43190
43225
  surface.ctx.save();
43191
43226
  replayWmfRecords(view, surface.ctx, header, surface.width, surface.height, {
43192
43227
  wmfReferenceDpi: opts.wmfReferenceDpi,
43228
+ wmfAnsiCodePage: opts.wmfAnsiCodePage,
43193
43229
  maxRecords: opts.maxRecords,
43194
43230
  fontFamilyMap: opts.fontFamilyMap,
43195
43231
  gdiAntialias: opts.gdiAntialias,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "4.18.0",
3
+ "version": "4.18.2",
4
4
  "description": "Convert EMF/WMF metafile binaries to PNG data URLs or SVG (markup, data URL, React/JSX)",
5
5
  "keywords": [
6
6
  "canvas",