emf-converter 4.8.20 → 4.9.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/index.mjs CHANGED
@@ -11660,11 +11660,20 @@ function ellipseBeziersBox(box, clockwise = false) {
11660
11660
  if (!clockwise) {
11661
11661
  return ellipsePoints(box, false);
11662
11662
  }
11663
- const e = clockwiseEllipseBeziersBox(box);
11663
+ const { halfX, ...plain } = box;
11664
+ const e = clockwiseEllipseBeziersBox(plain);
11664
11665
  const out = [];
11665
11666
  for (let i = e.length - 2; i >= 0; i -= 2) {
11666
11667
  out.push(e[i], e[i + 1]);
11667
11668
  }
11669
+ const odd = Math.abs(plain.exx) % 2;
11670
+ out[18] += odd;
11671
+ out[6] -= odd;
11672
+ if (halfX) {
11673
+ for (const k of [0, 1, 2, 3, 4, 5, 12]) {
11674
+ out[2 * k]++;
11675
+ }
11676
+ }
11668
11677
  return out;
11669
11678
  }
11670
11679
  function clockwiseEllipseBeziersBox(box) {
@@ -11680,10 +11689,10 @@ function ellipsePoints(box, cwControls) {
11680
11689
  const vMidHi = (v) => half(v, true);
11681
11690
  const vCtl = (v) => Math.floor(v / 2) - Math.floor(KAPPA * Math.floor(v / 2));
11682
11691
  const vCtlR = (v) => v - vCtl(v);
11683
- const vDist = (v) => Math.ceil(KAPPA * Math.floor(v / 2));
11684
- const rightUpper = cwControls ? (v) => vMidHi(v) - vDist(v) : vCtl;
11692
+ const vDist = (v) => v % 2 === 0 ? Math.ceil(KAPPA * Math.floor(v / 2)) : Math.floor(KAPPA * Math.ceil(v / 2));
11693
+ const rightUpper = cwControls ? (v) => vMidLo(v) - vDist(v) : vCtl;
11685
11694
  const leftUpper = cwControls ? (v) => vMidLo(v) - vDist(v) : vCtl;
11686
- const leftLower = cwControls ? (v) => vMidLo(v) + vDist(v) : vCtlR;
11695
+ const leftLower = cwControls ? (v) => vMidHi(v) + vDist(v) : vCtlR;
11687
11696
  const rightLower = cwControls ? (v) => vMidHi(v) + vDist(v) : vCtlR;
11688
11697
  const zero = () => 0;
11689
11698
  const full = (v) => v;
@@ -11925,7 +11934,7 @@ function unitPiece(from, to, small) {
11925
11934
  }
11926
11935
  return { start: p0, ctrl };
11927
11936
  }
11928
- function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise) {
11937
+ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise, halfX = false, framed = false) {
11929
11938
  const w = r - l;
11930
11939
  const h = b - t;
11931
11940
  const Q = Math.PI / 2;
@@ -11945,11 +11954,25 @@ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise) {
11945
11954
  } else {
11946
11955
  while (a1 >= a0) a1 -= 2 * Math.PI;
11947
11956
  }
11948
- const px = (u) => Math.round(cx + rx * u);
11957
+ const px = (u, v) => clockwise && halfX ? Math.ceil(cx + rx * u + 0.5 - v) : Math.round(cx + rx * u + (halfX ? 1 + v : 0));
11949
11958
  const py = (v) => Math.round(cy - ry * v);
11950
- const E = clockwise ? clockwiseEllipseBeziersBox(axisBox(l, t, r, b)) : ellipseBeziers(l, t, r, b);
11959
+ const eb = axisBox(l, t, r, b);
11960
+ if (halfX) eb.halfX = true;
11961
+ const E = ellipseBeziersBox(eb);
11962
+ if (clockwise) {
11963
+ const cwPts = ellipseBeziersBox(eb, true);
11964
+ for (let i = 0; i < cwPts.length; i += 2) {
11965
+ E[cwPts.length - 2 - i] = cwPts[i];
11966
+ E[cwPts.length - 1 - i] = cwPts[i + 1];
11967
+ }
11968
+ }
11951
11969
  const startUnit = small ? [Math.cos(a0), Math.sin(a0)] : polygonTrig(a0);
11952
- const out = [px(startUnit[0]), py(startUnit[1])];
11970
+ const out = [px(startUnit[0], startUnit[1]), py(startUnit[1])];
11971
+ const onAxis = (angle2) => Math.abs(angle2 / Q - Math.round(angle2 / Q)) < 1e-9;
11972
+ const axisQuadrant = (angle2) => (Math.round(angle2 / Q) % 4 + 4) % 4;
11973
+ if (framed && onAxis(a0) && (s > 0 ? axisQuadrant(a0) === 1 || axisQuadrant(a0) === 2 : axisQuadrant(a0) === 2 || axisQuadrant(a0) === 3)) {
11974
+ out.push(out[0], out[1], out[0], out[1], out[0], out[1]);
11975
+ }
11953
11976
  let a = a0;
11954
11977
  for (let guard = 0; guard < 8 && (s > 0 ? a < a1 - 1e-12 : a > a1 + 1e-12); guard++) {
11955
11978
  const next = s > 0 ? Math.floor(a / Q + 1e-9) * Q + Q : Math.ceil(a / Q - 1e-9) * Q - Q;
@@ -11971,10 +11994,16 @@ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise) {
11971
11994
  const e = s > 0 ? Math.min(next, a1) : Math.max(next, a1);
11972
11995
  const piece = unitPiece(a, e, small);
11973
11996
  for (let i = 0; i < 6; i += 2) {
11974
- out.push(px(piece.ctrl[i]), py(piece.ctrl[i + 1]));
11997
+ out.push(px(piece.ctrl[i], piece.ctrl[i + 1]), py(piece.ctrl[i + 1]));
11975
11998
  }
11976
11999
  a = e;
11977
12000
  }
12001
+ if (framed && onAxis(a1) && (s > 0 ? axisQuadrant(a1) === 3 || axisQuadrant(a1) === 0 : axisQuadrant(a1) === 1 || axisQuadrant(a1) === 0)) {
12002
+ const endUnit = polygonTrig(a1);
12003
+ const ex = px(endUnit[0], endUnit[1]);
12004
+ const ey = py(endUnit[1]);
12005
+ out.push(ex, ey, ex, ey, ex, ey);
12006
+ }
11978
12007
  return out;
11979
12008
  }
11980
12009
  var GdiRasterPath = class {
@@ -29613,7 +29642,7 @@ var Outliner = class {
29613
29642
  this.flush();
29614
29643
  }
29615
29644
  };
29616
- function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors) {
29645
+ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric) {
29617
29646
  const out = [];
29618
29647
  const dashes = [];
29619
29648
  for (let i = 0; i < pattern.length; i += 2) {
@@ -29633,8 +29662,8 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
29633
29662
  const [x0, y0] = P[i];
29634
29663
  const [x1, y1] = P[i + 1];
29635
29664
  const dir = [x1 - x0, y1 - y0];
29636
- const real = Math.hypot(dir[0], dir[1]);
29637
- const len = wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29665
+ const real = metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29666
+ const len = metric ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29638
29667
  if (len === 0) {
29639
29668
  if (on && cur) {
29640
29669
  cur.pts.push(P[i + 1]);
@@ -29707,10 +29736,10 @@ function widenPath(path, opts) {
29707
29736
  }
29708
29737
  if (dashed) {
29709
29738
  const run = closed ? [...P, P[0]] : P;
29710
- const shorten = opts.cap === "flat" || opts.shortenDashes === false ? 0 : opts.width;
29739
+ const shorten = opts.cap === "flat" || opts.shortenDashes === false ? 0 : opts.dashMetric ? opts.width / opts.dashMetric[0] : opts.width;
29711
29740
  const runTangents = closed ? [...dirs, void 0] : dirs;
29712
29741
  const runCurves = closed ? [...curves, !!fig.roundWiden] : curves;
29713
- for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors)) {
29742
+ for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric)) {
29714
29743
  const pts = [piece.pts[0]];
29715
29744
  const pdirs = [];
29716
29745
  const pdraws = [];
@@ -29792,6 +29821,10 @@ function flipBox(box) {
29792
29821
  }
29793
29822
  function rectRasterPath(box, clockwise = false) {
29794
29823
  const c = boxCorners(clockwise ? flipBox(box) : box);
29824
+ if (box.halfXRect) {
29825
+ c[4]--;
29826
+ c[6]--;
29827
+ }
29795
29828
  const path = new GdiRasterPath();
29796
29829
  path.moveTo(c[0], c[1]);
29797
29830
  path.lineTo(c[2], c[3]);
@@ -29838,8 +29871,49 @@ function roundRectDeviceBeziers(box, cw, ch, clockwise = false, compatible = fal
29838
29871
  pts.push(...map(q[i], clockwise ? f.t + f.b - q[i + 1] : q[i + 1]));
29839
29872
  }
29840
29873
  if (box.halfX) {
29841
- for (const k of [1, 2, 3, 4, 5, 6, 8, 15]) {
29842
- pts[2 * k]++;
29874
+ if (box.halfXCompat || !clockwise) {
29875
+ const cy = (f.t + f.b) / 2;
29876
+ const ry = (f.b - f.t) / 2 || 1;
29877
+ for (let k = 0; k < 16; k++) {
29878
+ const v = (cy - pts[2 * k + 1]) / ry;
29879
+ pts[2 * k] += k >= 8 ? Math.round(1 + v) : Math.ceil(v - 0.5);
29880
+ }
29881
+ } else {
29882
+ const tall = box.cornerExact !== void 0 && box.cornerExact[1] * 2 >= Math.abs(box.eyy) - 1e-9;
29883
+ for (const k of tall ? [1, 2, 3, 4, 5, 6, 8, 15] : [0, 1, 2, 3, 4, 5, 6, 7]) {
29884
+ pts[2 * k]++;
29885
+ }
29886
+ }
29887
+ }
29888
+ if (box.cornerExact && isAxisBox(box)) {
29889
+ const w = f.r - f.l;
29890
+ const h = f.b - f.t;
29891
+ if (w >= 0 && h >= 0) {
29892
+ const hx = w === 0 ? 0 : Math.round(box.cornerExact[0] * (w + w % 2) / w / 2);
29893
+ const hy = h === 0 ? 0 : Math.round(box.cornerExact[1] * (clockwise ? h + h % 2 : h - h % 2) / h / 2);
29894
+ const hc = Math.ceil(KAPPA * hx);
29895
+ const vc = clockwise ? Math.ceil(KAPPA * hy) : Math.floor(KAPPA * hy);
29896
+ const set = (k, x, y) => {
29897
+ if (x !== null) pts[2 * k] = x;
29898
+ pts[2 * k + 1] = clockwise ? f.t + f.b - y : y;
29899
+ };
29900
+ const a = box.halfX ? 1 : 0;
29901
+ set(0, null, f.t + hy);
29902
+ set(1, null, f.t + hy - vc);
29903
+ set(2, f.r + a - hx + hc, f.t);
29904
+ set(3, f.r + a - hx, f.t);
29905
+ set(4, f.l + a + hx, f.t);
29906
+ set(5, f.l + a + hx - hc, f.t);
29907
+ set(6, null, f.t + hy - vc);
29908
+ set(7, null, f.t + hy);
29909
+ set(8, null, f.b - hy);
29910
+ set(9, null, f.b - hy + vc);
29911
+ set(10, f.l + hx - hc, f.b);
29912
+ set(11, f.l + hx, f.b);
29913
+ set(12, f.r - hx, f.b);
29914
+ set(13, f.r - hx + hc, f.b);
29915
+ set(14, null, f.b - hy + vc);
29916
+ set(15, null, f.b - hy);
29843
29917
  }
29844
29918
  }
29845
29919
  return pts;
@@ -29882,7 +29956,7 @@ function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPat
29882
29956
  cw = !cw;
29883
29957
  }
29884
29958
  }
29885
- const bz = arcBeziers(f.l, f.t, f.r, f.b, sx, sy, ex, ey, cw);
29959
+ const bz = arcBeziers(f.l, f.t, f.r, f.b, sx, sy, ex, ey, cw, !!box.halfX, !!box.framed);
29886
29960
  const pts = [];
29887
29961
  for (let i = 0; i < bz.length; i += 2) {
29888
29962
  pts.push(...map(bz[i], bz[i + 1]));
@@ -29896,7 +29970,7 @@ function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPat
29896
29970
  if (kind === "pie") {
29897
29971
  const w = f.r - f.l;
29898
29972
  const h = f.b - f.t;
29899
- const [cx, cy] = map(f.l + Math.ceil(w / 2), f.t + Math.ceil(h / 2));
29973
+ const [cx, cy] = map(f.l + Math.ceil(w / 2) + (box.halfX ? 1 : 0), f.t + Math.ceil(h / 2));
29900
29974
  path.lineTo(cx, cy);
29901
29975
  }
29902
29976
  if (kind === "pie" || kind === "chord") {
@@ -29932,8 +30006,9 @@ function penWidenOptions(rCtx, opts = {}) {
29932
30006
  const widthPx = rCtx.wholeDevicePixels && (flags & 15) === 6 ? state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) : penDeviceWidth(rCtx);
29933
30007
  const capBits = flags & 3840;
29934
30008
  const joinBits = flags & 61440;
29935
- const dashes = state.penExtended ? geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
29936
- const ellipse = !dashes && !rCtx.wholeDevicePixels && state.penWidth * Math.abs(matrix[0]) * 16 >= 1 && state.penWidth * Math.abs(matrix[3]) * 16 >= 1 && Math.abs(matrix[1]) < 1e-6 && Math.abs(matrix[2]) < 1e-6 && Math.abs(Math.abs(matrix[0]) - Math.abs(matrix[3])) > 1e-6;
30009
+ const ellipse = !rCtx.wholeDevicePixels && state.penWidth * Math.abs(matrix[0]) * 16 >= 1 && state.penWidth * Math.abs(matrix[3]) * 16 >= 1 && Math.abs(matrix[1]) < 1e-6 && Math.abs(matrix[2]) < 1e-6 && Math.abs(Math.abs(matrix[0]) - Math.abs(matrix[3])) > 1e-6;
30010
+ const dashes = state.penExtended ? ellipse ? geometricStyle(flags, state.penWidth, state.penUserStyle, 1) : geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
30011
+ const dashMetric = ellipse && dashes ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : void 0;
29937
30012
  return {
29938
30013
  width: Math.round((ellipse ? state.penWidth * Math.abs(matrix[0]) : widthPx) * 16),
29939
30014
  ...ellipse ? { height: Math.round(state.penWidth * Math.abs(matrix[3]) * 16) } : {},
@@ -29941,6 +30016,7 @@ function penWidenOptions(rCtx, opts = {}) {
29941
30016
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
29942
30017
  miterLimit: state.miterLimit ?? 10,
29943
30018
  dashes: dashes ? dashes.map((v) => v * 16) : null,
30019
+ ...dashMetric ? { dashMetric } : {},
29944
30020
  shortenDashes: (flags & 15) !== 7,
29945
30021
  // One logical unit per device pixel, unrotated: GDI measures dash
29946
30022
  // segments in whole pixels.
@@ -30953,9 +31029,24 @@ function insideFrameInset(rCtx, box, rectangle = false, clockwiseRoundRect = fal
30953
31029
  right: Math.round((rectangle ? lo : hi) * px),
30954
31030
  top: y,
30955
31031
  bottom: y,
30956
- half: wx % 2 === 1 && !rectangle
31032
+ half: wx % 2 === 1 && !rectangle,
31033
+ halfRect: wx % 2 === 1 && rectangle
30957
31034
  };
30958
31035
  }
31036
+ function insideFramePenTooWide(rCtx, box) {
31037
+ if ((rCtx.state.penStyle & 15) !== PS_INSIDEFRAME || !isAxisBox(box) || hasWorldRotation(rCtx)) {
31038
+ return false;
31039
+ }
31040
+ const m = gdiDeviceMatrix(rCtx);
31041
+ const px = gdiDevicePixelX(rCtx);
31042
+ const py = gdiDevicePixelY(rCtx);
31043
+ const widthX = Math.abs(rCtx.state.penWidth * m[0]) / px * 16;
31044
+ const widthY = Math.abs(rCtx.state.penWidth * m[3]) / py * 16;
31045
+ if (Math.max(widthX, widthY) < 24) {
31046
+ return false;
31047
+ }
31048
+ return Math.abs(box.exx) / px < Math.round(widthX) || Math.abs(box.eyy) / py < Math.round(widthY);
31049
+ }
30959
31050
  function insetFixBox(box, inset) {
30960
31051
  const sx = box.exx < 0 ? -1 : 1;
30961
31052
  const sy = box.eyy < 0 ? -1 : 1;
@@ -30965,11 +31056,15 @@ function insetFixBox(box, inset) {
30965
31056
  exx: box.exx - sx * (inset.left + inset.right),
30966
31057
  exy: 0,
30967
31058
  eyx: 0,
30968
- eyy: box.eyy - sy * (inset.top + inset.bottom)
31059
+ eyy: box.eyy - sy * (inset.top + inset.bottom),
31060
+ framed: true
30969
31061
  };
30970
31062
  if (inset.half && sx > 0) {
30971
31063
  framed.halfX = true;
30972
31064
  }
31065
+ if (inset.halfRect && sx > 0) {
31066
+ framed.halfXRect = true;
31067
+ }
30973
31068
  return framed;
30974
31069
  }
30975
31070
  function sameEllipseRay(l, t, r, b, sx, sy, ex, ey) {
@@ -31052,7 +31147,7 @@ function handleRectangle(rCtx, dataOff, recSize) {
31052
31147
  const r = view.getInt32(dataOff + 8, true);
31053
31148
  const b = view.getInt32(dataOff + 12, true);
31054
31149
  const unframed = uprightFixBox(rCtx, l, t, r, b);
31055
- const inset = insideFrameInset(rCtx, unframed, true);
31150
+ const inset = insideFrameInset(rCtx, unframed, true, rCtx.state.arcDirection === 2);
31056
31151
  const box = inset ? insetFixBox(unframed, inset) : unframed;
31057
31152
  const clockwise = rCtx.state.arcDirection === 2;
31058
31153
  if (!inPath) {
@@ -31238,6 +31333,13 @@ function handleRoundRect(rCtx, dataOff, recSize) {
31238
31333
  gmh(rCtx, cornerH) / 2,
31239
31334
  null
31240
31335
  );
31336
+ if (inset) {
31337
+ const fullW = Math.abs((r - l) * devM[0]) * 16;
31338
+ const fullH = Math.abs((b - t) * devM[3]) * 16;
31339
+ if (fullW > 0 && fullH > 0) {
31340
+ framed.cornerExact = [Math.min(cornerFixW, fullW) * Math.abs(framed.exx) / fullW, Math.min(cornerFixH, fullH) * Math.abs(framed.eyy) / fullH];
31341
+ }
31342
+ }
31241
31343
  const raster = (box = framed) => roundRectRasterPath(box, cw, ch, clockwise, cornerW === 0 || cornerH === 0);
31242
31344
  if (inPath) {
31243
31345
  const box = framed;
@@ -31291,7 +31393,7 @@ function handleEllipse(rCtx, dataOff, recSize) {
31291
31393
  const b = view.getInt32(dataOff + 12, true);
31292
31394
  const clockwise = rCtx.state.arcDirection === 2;
31293
31395
  const unframed = uprightFixBox(rCtx, l, t, r, b);
31294
- const inset = insideFrameInset(rCtx, unframed);
31396
+ const inset = insideFrameInset(rCtx, unframed, false, rCtx.state.arcDirection === 2);
31295
31397
  const framed = inset ? insetFixBox(unframed, inset) : unframed;
31296
31398
  const params = inset ? { cx: (framed.ax + framed.exx / 2) / 16, cy: (framed.ay + framed.eyy / 2) / 16, rx: Math.abs(framed.exx) / 32, ry: Math.abs(framed.eyy) / 32, rotation: 0 } : hasWorldRotation(rCtx) ? gdiEllipseParams(rCtx, (l + r) / 2, (t + b) / 2, Math.abs(r - l) / 2, Math.abs(b - t) / 2) : {
31297
31399
  cx: gmx(rCtx, (l + r) / 2),
@@ -31341,7 +31443,10 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
31341
31443
  const endAngle = fullEllipse ? startAngle + (clockwise ? 2 : -2) * Math.PI : Math.atan2((endY - cyA) / (ry || 1), (endX - cxA) / (rx || 1));
31342
31444
  const rotated = hasWorldRotation(rCtx);
31343
31445
  const unframed = fixBox(rCtx, l, t, r, b);
31344
- const inset = insideFrameInset(rCtx, unframed);
31446
+ if (recType !== EMR_ARCTO && insideFramePenTooWide(rCtx, unframed)) {
31447
+ return true;
31448
+ }
31449
+ const inset = insideFrameInset(rCtx, unframed, false, rCtx.state.arcDirection === 2);
31345
31450
  const framed = inset ? insetFixBox(unframed, inset) : unframed;
31346
31451
  const params = inset ? { cx: (framed.ax + framed.exx / 2) / 16, cy: (framed.ay + framed.eyy / 2) / 16, rx: Math.abs(framed.exx) / 32, ry: Math.abs(framed.eyy) / 32, rotation: 0 } : rotated ? gdiEllipseParams(rCtx, cxA, cyA, rx, ry) : {
31347
31452
  cx: gmx(rCtx, cxA),
@@ -31372,20 +31477,25 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
31372
31477
  }
31373
31478
  };
31374
31479
  const kind = isArcTo ? "arcto" : recType === EMR_PIE ? "pie" : recType === EMR_CHORD ? "chord" : "arc";
31375
- const radialOnBox = (p) => {
31480
+ const devM = gdiDeviceMatrix(rCtx);
31481
+ const rawFix = (x, y) => [(devM[0] * x + devM[2] * y + devM[4]) * 16, (devM[1] * x + devM[3] * y + devM[5]) * 16];
31482
+ const radialOnBox = (p, raw) => {
31376
31483
  if (!inset) {
31377
31484
  return p;
31378
31485
  }
31379
- const kx = unframed.exx !== 0 ? framed.exx / unframed.exx : 1;
31380
- const ky = unframed.eyy !== 0 ? framed.eyy / unframed.eyy : 1;
31381
- return [framed.ax + framed.exx / 2 + (p[0] - (unframed.ax + unframed.exx / 2)) * kx, framed.ay + framed.eyy / 2 + (p[1] - (unframed.ay + unframed.eyy / 2)) * ky];
31486
+ const [rl, rt] = rawFix(l, t);
31487
+ const [rr, rb] = rawFix(r, b);
31488
+ const kx = rr !== rl ? framed.exx / (rr - rl) : 1;
31489
+ const ky = rb !== rt ? framed.eyy / (rb - rt) : 1;
31490
+ const snap = (v) => Math.abs(v) < 1e-6 ? 0 : v;
31491
+ return [framed.ax + framed.exx / 2 + snap(raw[0] - (rl + rr) / 2) * kx, framed.ay + framed.eyy / 2 + snap(raw[1] - (rt + rb) / 2) * ky];
31382
31492
  };
31383
31493
  const rasterArgs = (immediate = false) => ({
31384
31494
  box: inset ? framed : immediate && needsFill ? curvedFixBox(rCtx, l, t, r, b) : unframed,
31385
- s: radialOnBox(fixPoint(rCtx, startX, startY)),
31495
+ s: radialOnBox(fixPoint(rCtx, startX, startY), rawFix(startX, startY)),
31386
31496
  // Device FIX rounding can separate distinct radial points on the
31387
31497
  // same logical ray. Preserve their proven endpoint identity.
31388
- e: fullEllipse ? radialOnBox(fixPoint(rCtx, startX, startY)) : radialOnBox(fixPoint(rCtx, endX, endY)),
31498
+ e: fullEllipse ? radialOnBox(fixPoint(rCtx, startX, startY), rawFix(startX, startY)) : radialOnBox(fixPoint(rCtx, endX, endY), rawFix(endX, endY)),
31389
31499
  from: currentFix(rCtx)
31390
31500
  });
31391
31501
  if (inPath) {
@@ -39682,6 +39792,7 @@ function compatBox(p, l, t, r, b, opts = {}) {
39682
39792
  if ((p.rCtx.state.penStyle & 15) === PS_INSIDEFRAME2) {
39683
39793
  const w = Math.round(penDeviceWidth(p.rCtx) / p.kx);
39684
39794
  if (w > 1) {
39795
+ const whole = { ...box };
39685
39796
  const matrix = gdiDeviceMatrix(p.rCtx);
39686
39797
  const wx = Math.round(Math.abs(p.rCtx.state.penWidth * matrix[0]) / p.kx * 16);
39687
39798
  const wy = Math.round(Math.abs(p.rCtx.state.penWidth * matrix[3]) / p.ky * 16);
@@ -39695,14 +39806,21 @@ function compatBox(p, l, t, r, b, opts = {}) {
39695
39806
  if (half) {
39696
39807
  box.halfX = true;
39697
39808
  }
39809
+ if (opts.clampEmpty && (box.x1 < box.x0 || box.y1 < box.y0)) {
39810
+ return { x0: whole.x0, y0: whole.y0, x1: whole.x1 + Math.round(ux), y1: whole.y1 + Math.round(uy) };
39811
+ }
39698
39812
  }
39699
39813
  }
39700
39814
  return box;
39701
39815
  }
39702
- function fixBoxOf(box) {
39703
- const fix = axisBox(box.x0, box.y0, Math.max(box.x0, box.x1), Math.max(box.y0, box.y1));
39816
+ function fixBoxOf(box, cornerExact, keepInverted = false) {
39817
+ const fix = keepInverted ? axisBox(box.x0, box.y0, box.x1, box.y1) : axisBox(box.x0, box.y0, Math.max(box.x0, box.x1), Math.max(box.y0, box.y1));
39704
39818
  if (box.halfX) {
39705
39819
  fix.halfX = true;
39820
+ fix.halfXCompat = true;
39821
+ }
39822
+ if (cornerExact) {
39823
+ fix.cornerExact = cornerExact;
39706
39824
  }
39707
39825
  return fix;
39708
39826
  }
@@ -39766,7 +39884,8 @@ function compatCorner(p, w, h, box, logical) {
39766
39884
  const width2 = box.x1 - box.x0, height2 = box.y1 - box.y0;
39767
39885
  const fullW2 = Math.abs((logical[2] - logical[0]) * m[0]) * 16 || width2;
39768
39886
  const fullH2 = Math.abs((logical[3] - logical[1]) * m[3]) * 16 || height2;
39769
- return [Math.floor(Math.min(Math.abs(w * m[0]) * 16, fullW2) * width2 / fullW2), Math.floor(Math.min(Math.abs(h * m[3]) * 16, fullH2) * height2 / fullH2)];
39887
+ const cornerW = Math.min(Math.abs(w * m[0]) * 16, fullW2) * width2 / fullW2;
39888
+ return [Math.floor(cornerW), Math.floor(Math.min(Math.abs(h * m[3]) * 16, fullH2) * height2 / fullH2), [cornerW, Math.min(Math.abs(h * m[3]) * 16, fullH2) * height2 / fullH2]];
39770
39889
  }
39771
39890
  const width = box.x1 - box.x0, height = box.y1 - box.y0;
39772
39891
  const fullW = Math.abs((logical[2] - logical[0]) * m[0]) * 16 || width + ux;
@@ -39775,11 +39894,11 @@ function compatCorner(p, w, h, box, logical) {
39775
39894
  return penIsCosmetic(p.rCtx) && !penIsNull(p) ? scaled2 : [Math.floor(scaled2[0]), Math.floor(scaled2[1])];
39776
39895
  }
39777
39896
  function wmfRoundRect(p, l, t, r, b, w, h) {
39778
- const box = compatBox(p, l, t, r, b, { curved: true, half: true });
39897
+ const box = compatBox(p, l, t, r, b, { curved: true, half: true, clampEmpty: true });
39779
39898
  if (box.x1 < box.x0 || box.y1 < box.y0) {
39780
39899
  return;
39781
39900
  }
39782
- const [cw, ch] = compatCorner(p, w, h, box, [l, t, r, b]);
39901
+ const [cw, ch, half] = compatCorner(p, w, h, box, [l, t, r, b]);
39783
39902
  const cr = canvasRect(box);
39784
39903
  paintGdiShape(p.rCtx, {
39785
39904
  build: (c) => {
@@ -39804,14 +39923,14 @@ function wmfRoundRect(p, l, t, r, b, w, h) {
39804
39923
  c.ellipse(cr.x + ex, cr.y + ey, ex, ey, 0, 2 * q, 3 * q);
39805
39924
  c.closePath();
39806
39925
  },
39807
- raster: () => roundRectRasterPath(fixBoxOf(box), cw, ch, clockwiseOf(p), w === 0 || h === 0, !penIsNull(p) && penIsCosmetic(p.rCtx)),
39926
+ raster: () => roundRectRasterPath(fixBoxOf(box, half), cw, ch, clockwiseOf(p), w === 0 || h === 0, !penIsNull(p) && penIsCosmetic(p.rCtx)),
39808
39927
  roundPen: true,
39809
39928
  fill: true,
39810
39929
  stroke: true
39811
39930
  });
39812
39931
  }
39813
39932
  function wmfEllipse(p, l, t, r, b) {
39814
- const box = compatBox(p, l, t, r, b, { curved: true, half: true });
39933
+ const box = compatBox(p, l, t, r, b, { curved: true, half: true, clampEmpty: true });
39815
39934
  if (box.x1 < box.x0 || box.y1 < box.y0) {
39816
39935
  return;
39817
39936
  }
@@ -39827,9 +39946,9 @@ function wmfEllipse(p, l, t, r, b) {
39827
39946
  stroke: true
39828
39947
  });
39829
39948
  }
39830
- function compatArc(p, kind, l, t, r, b, xs, ys, xe, ye) {
39831
- const box = compatBox(p, l, t, r, b, { curved: kind === "chord" || kind === "pie", roundFrame: true });
39832
- if (box.x1 < box.x0 || box.y1 < box.y0) {
39949
+ function compatArc(p, kind, l, t, r, b, xs, ys, xe, ye, keepInverted = false) {
39950
+ const box = compatBox(p, l, t, r, b, { curved: kind === "chord" || kind === "pie", roundFrame: true, half: true });
39951
+ if (box.y1 < box.y0 || !keepInverted && box.x1 < box.x0) {
39833
39952
  return null;
39834
39953
  }
39835
39954
  const m = gdiDeviceMatrix(p.rCtx);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "4.8.20",
3
+ "version": "4.9.0",
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",