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