emf-converter 4.10.0 → 4.11.1

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.js CHANGED
@@ -29238,11 +29238,42 @@ function penPolygon(width, height = width) {
29238
29238
  penCache.set(key, pen);
29239
29239
  return pen;
29240
29240
  }
29241
- function drawVertices(pen, dx, dy, width = 1, height = width) {
29241
+ var matrixPenCache = /* @__PURE__ */ new Map();
29242
+ function penPolygonMatrix(width, m) {
29243
+ const key = `${width},${m.join(",")}`;
29244
+ const cached = matrixPenCache.get(key);
29245
+ if (cached) {
29246
+ return cached;
29247
+ }
29248
+ const r = Math.ceil(width / 2);
29249
+ const mirror2 = m[0] * m[3] - m[1] * m[2] < 0 ? -1 : 1;
29250
+ const bez = ellipseBeziers(-r, -r, r, r);
29251
+ const dev = [];
29252
+ for (let i = 0; i < 14; i += 2) {
29253
+ const x = bez[i];
29254
+ const y = bez[i + 1] * mirror2;
29255
+ dev.push(Math.round(m[0] * x + m[2] * y), Math.round(m[1] * x + m[3] * y));
29256
+ }
29257
+ const f = flattenBezierPath(dev);
29258
+ const half = [];
29259
+ for (let i = 0; i + 1 < f.length; i += 2) {
29260
+ half.push([f[i], f[i + 1]]);
29261
+ }
29262
+ half.pop();
29263
+ const pen = [...half, ...half.map((p) => [0 - p[0] || 0, 0 - p[1] || 0])];
29264
+ matrixPenCache.set(key, pen);
29265
+ return pen;
29266
+ }
29267
+ function drawVertices(pen, dx, dy, width = 1, height = width, matrix) {
29242
29268
  const n = pen.length;
29243
29269
  const axisVertex = pen.some((q) => q[1] === 0);
29244
- const yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29245
- const xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29270
+ let yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29271
+ let xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29272
+ if (matrix) {
29273
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29274
+ xMagnitude = Math.abs((matrix[3] * dx - matrix[2] * dy) / det);
29275
+ yMagnitude = Math.abs((-matrix[1] * dx + matrix[0] * dy) / det);
29276
+ }
29246
29277
  const steep = yMagnitude > xMagnitude || yMagnitude === xMagnitude && axisVertex;
29247
29278
  const s = (steep ? dy < 0 : dx < 0 || dx === 0 && dy < 0) ? -1 : 1;
29248
29279
  let best = 0;
@@ -29262,7 +29293,7 @@ function drawVertices(pen, dx, dy, width = 1, height = width) {
29262
29293
  function halfPixel(v) {
29263
29294
  return Math.sign(v) * 8 * Math.floor((Math.abs(v) + 4) / 8);
29264
29295
  }
29265
- function perpendicularVectors(width, dx0, dy0, height = width) {
29296
+ function perpendicularVectors(width, dx0, dy0, height = width, matrixPen) {
29266
29297
  let dx = dx0;
29267
29298
  let dy = dy0;
29268
29299
  const flip = dx < 0 || dx === 0 && dy < 0;
@@ -29270,7 +29301,7 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29270
29301
  dx = -dx;
29271
29302
  dy = -dy;
29272
29303
  }
29273
- const pen = penPolygon(width, height);
29304
+ const pen = matrixPen ?? penPolygon(width, height);
29274
29305
  const n = pen.length;
29275
29306
  const nx = -dy;
29276
29307
  const ny = dx;
@@ -29309,7 +29340,15 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29309
29340
  const vx = rounded[0], vy = rounded[1];
29310
29341
  return { v: flip ? [-vx, -vy] : [vx, vy], ray: flip ? [-x, -y] : [x, y] };
29311
29342
  }
29312
- function squareExtension(width, dx, dy, scale = 1, height = width) {
29343
+ function squareExtension(width, dx, dy, scale = 1, height = width, matrix) {
29344
+ if (matrix) {
29345
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29346
+ const lx = (matrix[3] * dx - matrix[2] * dy) / det;
29347
+ const ly = (-matrix[1] * dx + matrix[0] * dy) / det;
29348
+ const l = Math.hypot(lx, ly);
29349
+ const q = width / 2 * scale / l;
29350
+ return [Math.floor((matrix[0] * lx + matrix[2] * ly) * q + 0.5), Math.floor((matrix[1] * lx + matrix[3] * ly) * q + 0.5)];
29351
+ }
29313
29352
  const len = width === height ? Math.hypot(dx, dy) : Math.hypot(dx, dy * width / height);
29314
29353
  const r = width / 2 * scale;
29315
29354
  return [Math.floor(dx / len * r + 0.5), Math.floor(dy / len * r + 0.5)];
@@ -29332,7 +29371,7 @@ var Outliner = class {
29332
29371
  this.opts = opts;
29333
29372
  this.out = out;
29334
29373
  this.pts = [];
29335
- this.pen = penPolygon(opts.width, opts.height);
29374
+ this.pen = opts.matrix && opts.deviceNib ? penPolygonMatrix(opts.width, opts.matrix) : penPolygon(opts.width, opts.height);
29336
29375
  this.n = this.pen.length;
29337
29376
  this.rr = opts.cap === "round" && opts.join === "round";
29338
29377
  this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
@@ -29347,10 +29386,11 @@ var Outliner = class {
29347
29386
  const dx = dir ? dir[0] : b[0] - a[0];
29348
29387
  const dy = dir ? dir[1] : b[1] - a[1];
29349
29388
  const d = drawDir ?? [dx, dy];
29350
- const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height);
29389
+ const nibMatrix = this.opts.deviceNib ? this.opts.matrix : void 0;
29390
+ const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height, nibMatrix);
29351
29391
  const perpendicular = curve && drawDir ? drawDir : [dx, dy];
29352
- const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height);
29353
- return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29392
+ const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height, nibMatrix ? this.pen : void 0);
29393
+ return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height, nibMatrix), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29354
29394
  }
29355
29395
  push(p, v) {
29356
29396
  this.pts.push([p[0] + v[0], p[1] + v[1]]);
@@ -29463,7 +29503,7 @@ var Outliner = class {
29463
29503
  const sv = this.capSide(s, from);
29464
29504
  const ev = this.capSide(s, to);
29465
29505
  if (cap === "square") {
29466
- const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height);
29506
+ const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height, this.opts.deviceNib ? this.opts.matrix : void 0);
29467
29507
  const e = start ? [-e0[0], -e0[1]] : e0;
29468
29508
  this.push(p, [sv[0] + e[0], sv[1] + e[1]]);
29469
29509
  this.push(p, [ev[0] + e[0], ev[1] + e[1]]);
@@ -29643,7 +29683,7 @@ var Outliner = class {
29643
29683
  this.flush();
29644
29684
  }
29645
29685
  };
29646
- function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric) {
29686
+ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric, matrix) {
29647
29687
  const out = [];
29648
29688
  const dashes = [];
29649
29689
  for (let i = 0; i < pattern.length; i += 2) {
@@ -29663,8 +29703,9 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
29663
29703
  const [x0, y0] = P[i];
29664
29704
  const [x1, y1] = P[i + 1];
29665
29705
  const dir = [x1 - x0, y1 - y0];
29666
- const real = metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29667
- const len = metric ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29706
+ const det = matrix ? matrix[0] * matrix[3] - matrix[1] * matrix[2] : 1;
29707
+ const real = matrix ? Math.hypot((matrix[3] * dir[0] - matrix[2] * dir[1]) / det, (-matrix[1] * dir[0] + matrix[0] * dir[1]) / det) : metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29708
+ const len = metric || matrix ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29668
29709
  if (len === 0) {
29669
29710
  if (on && cur) {
29670
29711
  cur.pts.push(P[i + 1]);
@@ -29734,7 +29775,7 @@ function widenInLogicalSpace(path, opts, m) {
29734
29775
  });
29735
29776
  }
29736
29777
  function widenPath(path, opts) {
29737
- if (opts.matrix) {
29778
+ if (opts.matrix && !(opts.deviceNib && opts.join === "round")) {
29738
29779
  return widenInLogicalSpace(path, opts, opts.matrix);
29739
29780
  }
29740
29781
  const out = [];
@@ -29768,7 +29809,7 @@ function widenPath(path, opts) {
29768
29809
  const shorten = opts.cap === "flat" || opts.shortenDashes === false ? 0 : opts.dashMetric ? opts.width / opts.dashMetric[0] : opts.width;
29769
29810
  const runTangents = closed ? [...dirs, void 0] : dirs;
29770
29811
  const runCurves = closed ? [...curves, !!fig.roundWiden] : curves;
29771
- for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric)) {
29812
+ for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric, opts.deviceNib ? opts.matrix : void 0)) {
29772
29813
  const pts = [piece.pts[0]];
29773
29814
  const pdirs = [];
29774
29815
  const pdraws = [];
@@ -30038,14 +30079,15 @@ function penWidenOptions(rCtx, opts = {}) {
30038
30079
  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;
30039
30080
  const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
30040
30081
  const rotatedOrSheared = Math.abs(matrix[1]) >= 1e-6 || Math.abs(matrix[2]) >= 1e-6;
30041
- const similar = Math.abs(matrix[0] - matrix[3]) < 1e-6 && Math.abs(matrix[1] + matrix[2]) < 1e-6 || Math.abs(matrix[0] + matrix[3]) < 1e-6 && Math.abs(matrix[1] - matrix[2]) < 1e-6;
30042
- const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !similar && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30082
+ const quarterTurn = Math.abs(matrix[0]) < 1e-9 && Math.abs(matrix[3]) < 1e-9;
30083
+ const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !quarterTurn && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30043
30084
  const dashes = state.penExtended ? ellipse || general ? geometricStyle(flags, state.penWidth, state.penUserStyle, 1) : geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
30044
30085
  const dashMetric = ellipse && dashes ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : void 0;
30045
30086
  if (general) {
30046
30087
  return {
30047
30088
  width: Math.round(state.penWidth * 16),
30048
30089
  matrix: [matrix[0], matrix[1], matrix[2], matrix[3]],
30090
+ deviceNib: true,
30049
30091
  cap: opts.roundPen || !state.penExtended || capBits === 0 ? "round" : capBits === 256 ? "square" : "flat",
30050
30092
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
30051
30093
  miterLimit: state.miterLimit ?? 10,
package/dist/browser.mjs CHANGED
@@ -29236,11 +29236,42 @@ function penPolygon(width, height = width) {
29236
29236
  penCache.set(key, pen);
29237
29237
  return pen;
29238
29238
  }
29239
- function drawVertices(pen, dx, dy, width = 1, height = width) {
29239
+ var matrixPenCache = /* @__PURE__ */ new Map();
29240
+ function penPolygonMatrix(width, m) {
29241
+ const key = `${width},${m.join(",")}`;
29242
+ const cached = matrixPenCache.get(key);
29243
+ if (cached) {
29244
+ return cached;
29245
+ }
29246
+ const r = Math.ceil(width / 2);
29247
+ const mirror2 = m[0] * m[3] - m[1] * m[2] < 0 ? -1 : 1;
29248
+ const bez = ellipseBeziers(-r, -r, r, r);
29249
+ const dev = [];
29250
+ for (let i = 0; i < 14; i += 2) {
29251
+ const x = bez[i];
29252
+ const y = bez[i + 1] * mirror2;
29253
+ dev.push(Math.round(m[0] * x + m[2] * y), Math.round(m[1] * x + m[3] * y));
29254
+ }
29255
+ const f = flattenBezierPath(dev);
29256
+ const half = [];
29257
+ for (let i = 0; i + 1 < f.length; i += 2) {
29258
+ half.push([f[i], f[i + 1]]);
29259
+ }
29260
+ half.pop();
29261
+ const pen = [...half, ...half.map((p) => [0 - p[0] || 0, 0 - p[1] || 0])];
29262
+ matrixPenCache.set(key, pen);
29263
+ return pen;
29264
+ }
29265
+ function drawVertices(pen, dx, dy, width = 1, height = width, matrix) {
29240
29266
  const n = pen.length;
29241
29267
  const axisVertex = pen.some((q) => q[1] === 0);
29242
- const yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29243
- const xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29268
+ let yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29269
+ let xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29270
+ if (matrix) {
29271
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29272
+ xMagnitude = Math.abs((matrix[3] * dx - matrix[2] * dy) / det);
29273
+ yMagnitude = Math.abs((-matrix[1] * dx + matrix[0] * dy) / det);
29274
+ }
29244
29275
  const steep = yMagnitude > xMagnitude || yMagnitude === xMagnitude && axisVertex;
29245
29276
  const s = (steep ? dy < 0 : dx < 0 || dx === 0 && dy < 0) ? -1 : 1;
29246
29277
  let best = 0;
@@ -29260,7 +29291,7 @@ function drawVertices(pen, dx, dy, width = 1, height = width) {
29260
29291
  function halfPixel(v) {
29261
29292
  return Math.sign(v) * 8 * Math.floor((Math.abs(v) + 4) / 8);
29262
29293
  }
29263
- function perpendicularVectors(width, dx0, dy0, height = width) {
29294
+ function perpendicularVectors(width, dx0, dy0, height = width, matrixPen) {
29264
29295
  let dx = dx0;
29265
29296
  let dy = dy0;
29266
29297
  const flip = dx < 0 || dx === 0 && dy < 0;
@@ -29268,7 +29299,7 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29268
29299
  dx = -dx;
29269
29300
  dy = -dy;
29270
29301
  }
29271
- const pen = penPolygon(width, height);
29302
+ const pen = matrixPen ?? penPolygon(width, height);
29272
29303
  const n = pen.length;
29273
29304
  const nx = -dy;
29274
29305
  const ny = dx;
@@ -29307,7 +29338,15 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29307
29338
  const vx = rounded[0], vy = rounded[1];
29308
29339
  return { v: flip ? [-vx, -vy] : [vx, vy], ray: flip ? [-x, -y] : [x, y] };
29309
29340
  }
29310
- function squareExtension(width, dx, dy, scale = 1, height = width) {
29341
+ function squareExtension(width, dx, dy, scale = 1, height = width, matrix) {
29342
+ if (matrix) {
29343
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29344
+ const lx = (matrix[3] * dx - matrix[2] * dy) / det;
29345
+ const ly = (-matrix[1] * dx + matrix[0] * dy) / det;
29346
+ const l = Math.hypot(lx, ly);
29347
+ const q = width / 2 * scale / l;
29348
+ return [Math.floor((matrix[0] * lx + matrix[2] * ly) * q + 0.5), Math.floor((matrix[1] * lx + matrix[3] * ly) * q + 0.5)];
29349
+ }
29311
29350
  const len = width === height ? Math.hypot(dx, dy) : Math.hypot(dx, dy * width / height);
29312
29351
  const r = width / 2 * scale;
29313
29352
  return [Math.floor(dx / len * r + 0.5), Math.floor(dy / len * r + 0.5)];
@@ -29330,7 +29369,7 @@ var Outliner = class {
29330
29369
  this.opts = opts;
29331
29370
  this.out = out;
29332
29371
  this.pts = [];
29333
- this.pen = penPolygon(opts.width, opts.height);
29372
+ this.pen = opts.matrix && opts.deviceNib ? penPolygonMatrix(opts.width, opts.matrix) : penPolygon(opts.width, opts.height);
29334
29373
  this.n = this.pen.length;
29335
29374
  this.rr = opts.cap === "round" && opts.join === "round";
29336
29375
  this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
@@ -29345,10 +29384,11 @@ var Outliner = class {
29345
29384
  const dx = dir ? dir[0] : b[0] - a[0];
29346
29385
  const dy = dir ? dir[1] : b[1] - a[1];
29347
29386
  const d = drawDir ?? [dx, dy];
29348
- const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height);
29387
+ const nibMatrix = this.opts.deviceNib ? this.opts.matrix : void 0;
29388
+ const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height, nibMatrix);
29349
29389
  const perpendicular = curve && drawDir ? drawDir : [dx, dy];
29350
- const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height);
29351
- return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29390
+ const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height, nibMatrix ? this.pen : void 0);
29391
+ return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height, nibMatrix), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29352
29392
  }
29353
29393
  push(p, v) {
29354
29394
  this.pts.push([p[0] + v[0], p[1] + v[1]]);
@@ -29461,7 +29501,7 @@ var Outliner = class {
29461
29501
  const sv = this.capSide(s, from);
29462
29502
  const ev = this.capSide(s, to);
29463
29503
  if (cap === "square") {
29464
- const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height);
29504
+ const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height, this.opts.deviceNib ? this.opts.matrix : void 0);
29465
29505
  const e = start ? [-e0[0], -e0[1]] : e0;
29466
29506
  this.push(p, [sv[0] + e[0], sv[1] + e[1]]);
29467
29507
  this.push(p, [ev[0] + e[0], ev[1] + e[1]]);
@@ -29641,7 +29681,7 @@ var Outliner = class {
29641
29681
  this.flush();
29642
29682
  }
29643
29683
  };
29644
- function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric) {
29684
+ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric, matrix) {
29645
29685
  const out = [];
29646
29686
  const dashes = [];
29647
29687
  for (let i = 0; i < pattern.length; i += 2) {
@@ -29661,8 +29701,9 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
29661
29701
  const [x0, y0] = P[i];
29662
29702
  const [x1, y1] = P[i + 1];
29663
29703
  const dir = [x1 - x0, y1 - y0];
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]);
29704
+ const det = matrix ? matrix[0] * matrix[3] - matrix[1] * matrix[2] : 1;
29705
+ const real = matrix ? Math.hypot((matrix[3] * dir[0] - matrix[2] * dir[1]) / det, (-matrix[1] * dir[0] + matrix[0] * dir[1]) / det) : metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29706
+ const len = metric || matrix ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29666
29707
  if (len === 0) {
29667
29708
  if (on && cur) {
29668
29709
  cur.pts.push(P[i + 1]);
@@ -29732,7 +29773,7 @@ function widenInLogicalSpace(path, opts, m) {
29732
29773
  });
29733
29774
  }
29734
29775
  function widenPath(path, opts) {
29735
- if (opts.matrix) {
29776
+ if (opts.matrix && !(opts.deviceNib && opts.join === "round")) {
29736
29777
  return widenInLogicalSpace(path, opts, opts.matrix);
29737
29778
  }
29738
29779
  const out = [];
@@ -29766,7 +29807,7 @@ function widenPath(path, opts) {
29766
29807
  const shorten = opts.cap === "flat" || opts.shortenDashes === false ? 0 : opts.dashMetric ? opts.width / opts.dashMetric[0] : opts.width;
29767
29808
  const runTangents = closed ? [...dirs, void 0] : dirs;
29768
29809
  const runCurves = closed ? [...curves, !!fig.roundWiden] : curves;
29769
- for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric)) {
29810
+ for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric, opts.deviceNib ? opts.matrix : void 0)) {
29770
29811
  const pts = [piece.pts[0]];
29771
29812
  const pdirs = [];
29772
29813
  const pdraws = [];
@@ -30036,14 +30077,15 @@ function penWidenOptions(rCtx, opts = {}) {
30036
30077
  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;
30037
30078
  const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
30038
30079
  const rotatedOrSheared = Math.abs(matrix[1]) >= 1e-6 || Math.abs(matrix[2]) >= 1e-6;
30039
- const similar = Math.abs(matrix[0] - matrix[3]) < 1e-6 && Math.abs(matrix[1] + matrix[2]) < 1e-6 || Math.abs(matrix[0] + matrix[3]) < 1e-6 && Math.abs(matrix[1] - matrix[2]) < 1e-6;
30040
- const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !similar && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30080
+ const quarterTurn = Math.abs(matrix[0]) < 1e-9 && Math.abs(matrix[3]) < 1e-9;
30081
+ const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !quarterTurn && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30041
30082
  const dashes = state.penExtended ? ellipse || general ? geometricStyle(flags, state.penWidth, state.penUserStyle, 1) : geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
30042
30083
  const dashMetric = ellipse && dashes ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : void 0;
30043
30084
  if (general) {
30044
30085
  return {
30045
30086
  width: Math.round(state.penWidth * 16),
30046
30087
  matrix: [matrix[0], matrix[1], matrix[2], matrix[3]],
30088
+ deviceNib: true,
30047
30089
  cap: opts.roundPen || !state.penExtended || capBits === 0 ? "round" : capBits === 256 ? "square" : "flat",
30048
30090
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
30049
30091
  miterLimit: state.miterLimit ?? 10,
package/dist/index.js CHANGED
@@ -29239,11 +29239,42 @@ function penPolygon(width, height = width) {
29239
29239
  penCache.set(key, pen);
29240
29240
  return pen;
29241
29241
  }
29242
- function drawVertices(pen, dx, dy, width = 1, height = width) {
29242
+ var matrixPenCache = /* @__PURE__ */ new Map();
29243
+ function penPolygonMatrix(width, m) {
29244
+ const key = `${width},${m.join(",")}`;
29245
+ const cached = matrixPenCache.get(key);
29246
+ if (cached) {
29247
+ return cached;
29248
+ }
29249
+ const r = Math.ceil(width / 2);
29250
+ const mirror2 = m[0] * m[3] - m[1] * m[2] < 0 ? -1 : 1;
29251
+ const bez = ellipseBeziers(-r, -r, r, r);
29252
+ const dev = [];
29253
+ for (let i = 0; i < 14; i += 2) {
29254
+ const x = bez[i];
29255
+ const y = bez[i + 1] * mirror2;
29256
+ dev.push(Math.round(m[0] * x + m[2] * y), Math.round(m[1] * x + m[3] * y));
29257
+ }
29258
+ const f = flattenBezierPath(dev);
29259
+ const half = [];
29260
+ for (let i = 0; i + 1 < f.length; i += 2) {
29261
+ half.push([f[i], f[i + 1]]);
29262
+ }
29263
+ half.pop();
29264
+ const pen = [...half, ...half.map((p) => [0 - p[0] || 0, 0 - p[1] || 0])];
29265
+ matrixPenCache.set(key, pen);
29266
+ return pen;
29267
+ }
29268
+ function drawVertices(pen, dx, dy, width = 1, height = width, matrix) {
29243
29269
  const n = pen.length;
29244
29270
  const axisVertex = pen.some((q) => q[1] === 0);
29245
- const yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29246
- const xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29271
+ let yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29272
+ let xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29273
+ if (matrix) {
29274
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29275
+ xMagnitude = Math.abs((matrix[3] * dx - matrix[2] * dy) / det);
29276
+ yMagnitude = Math.abs((-matrix[1] * dx + matrix[0] * dy) / det);
29277
+ }
29247
29278
  const steep = yMagnitude > xMagnitude || yMagnitude === xMagnitude && axisVertex;
29248
29279
  const s = (steep ? dy < 0 : dx < 0 || dx === 0 && dy < 0) ? -1 : 1;
29249
29280
  let best = 0;
@@ -29263,7 +29294,7 @@ function drawVertices(pen, dx, dy, width = 1, height = width) {
29263
29294
  function halfPixel(v) {
29264
29295
  return Math.sign(v) * 8 * Math.floor((Math.abs(v) + 4) / 8);
29265
29296
  }
29266
- function perpendicularVectors(width, dx0, dy0, height = width) {
29297
+ function perpendicularVectors(width, dx0, dy0, height = width, matrixPen) {
29267
29298
  let dx = dx0;
29268
29299
  let dy = dy0;
29269
29300
  const flip = dx < 0 || dx === 0 && dy < 0;
@@ -29271,7 +29302,7 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29271
29302
  dx = -dx;
29272
29303
  dy = -dy;
29273
29304
  }
29274
- const pen = penPolygon(width, height);
29305
+ const pen = matrixPen ?? penPolygon(width, height);
29275
29306
  const n = pen.length;
29276
29307
  const nx = -dy;
29277
29308
  const ny = dx;
@@ -29310,7 +29341,15 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29310
29341
  const vx = rounded[0], vy = rounded[1];
29311
29342
  return { v: flip ? [-vx, -vy] : [vx, vy], ray: flip ? [-x, -y] : [x, y] };
29312
29343
  }
29313
- function squareExtension(width, dx, dy, scale = 1, height = width) {
29344
+ function squareExtension(width, dx, dy, scale = 1, height = width, matrix) {
29345
+ if (matrix) {
29346
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29347
+ const lx = (matrix[3] * dx - matrix[2] * dy) / det;
29348
+ const ly = (-matrix[1] * dx + matrix[0] * dy) / det;
29349
+ const l = Math.hypot(lx, ly);
29350
+ const q = width / 2 * scale / l;
29351
+ return [Math.floor((matrix[0] * lx + matrix[2] * ly) * q + 0.5), Math.floor((matrix[1] * lx + matrix[3] * ly) * q + 0.5)];
29352
+ }
29314
29353
  const len = width === height ? Math.hypot(dx, dy) : Math.hypot(dx, dy * width / height);
29315
29354
  const r = width / 2 * scale;
29316
29355
  return [Math.floor(dx / len * r + 0.5), Math.floor(dy / len * r + 0.5)];
@@ -29333,7 +29372,7 @@ var Outliner = class {
29333
29372
  this.opts = opts;
29334
29373
  this.out = out;
29335
29374
  this.pts = [];
29336
- this.pen = penPolygon(opts.width, opts.height);
29375
+ this.pen = opts.matrix && opts.deviceNib ? penPolygonMatrix(opts.width, opts.matrix) : penPolygon(opts.width, opts.height);
29337
29376
  this.n = this.pen.length;
29338
29377
  this.rr = opts.cap === "round" && opts.join === "round";
29339
29378
  this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
@@ -29348,10 +29387,11 @@ var Outliner = class {
29348
29387
  const dx = dir ? dir[0] : b[0] - a[0];
29349
29388
  const dy = dir ? dir[1] : b[1] - a[1];
29350
29389
  const d = drawDir ?? [dx, dy];
29351
- const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height);
29390
+ const nibMatrix = this.opts.deviceNib ? this.opts.matrix : void 0;
29391
+ const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height, nibMatrix);
29352
29392
  const perpendicular = curve && drawDir ? drawDir : [dx, dy];
29353
- const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height);
29354
- return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29393
+ const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height, nibMatrix ? this.pen : void 0);
29394
+ return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height, nibMatrix), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29355
29395
  }
29356
29396
  push(p, v) {
29357
29397
  this.pts.push([p[0] + v[0], p[1] + v[1]]);
@@ -29464,7 +29504,7 @@ var Outliner = class {
29464
29504
  const sv = this.capSide(s, from);
29465
29505
  const ev = this.capSide(s, to);
29466
29506
  if (cap === "square") {
29467
- const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height);
29507
+ const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height, this.opts.deviceNib ? this.opts.matrix : void 0);
29468
29508
  const e = start ? [-e0[0], -e0[1]] : e0;
29469
29509
  this.push(p, [sv[0] + e[0], sv[1] + e[1]]);
29470
29510
  this.push(p, [ev[0] + e[0], ev[1] + e[1]]);
@@ -29644,7 +29684,7 @@ var Outliner = class {
29644
29684
  this.flush();
29645
29685
  }
29646
29686
  };
29647
- function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric) {
29687
+ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric, matrix) {
29648
29688
  const out = [];
29649
29689
  const dashes = [];
29650
29690
  for (let i = 0; i < pattern.length; i += 2) {
@@ -29664,8 +29704,9 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
29664
29704
  const [x0, y0] = P[i];
29665
29705
  const [x1, y1] = P[i + 1];
29666
29706
  const dir = [x1 - x0, y1 - y0];
29667
- const real = metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29668
- const len = metric ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29707
+ const det = matrix ? matrix[0] * matrix[3] - matrix[1] * matrix[2] : 1;
29708
+ const real = matrix ? Math.hypot((matrix[3] * dir[0] - matrix[2] * dir[1]) / det, (-matrix[1] * dir[0] + matrix[0] * dir[1]) / det) : metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29709
+ const len = metric || matrix ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29669
29710
  if (len === 0) {
29670
29711
  if (on && cur) {
29671
29712
  cur.pts.push(P[i + 1]);
@@ -29735,7 +29776,7 @@ function widenInLogicalSpace(path, opts, m) {
29735
29776
  });
29736
29777
  }
29737
29778
  function widenPath(path, opts) {
29738
- if (opts.matrix) {
29779
+ if (opts.matrix && !(opts.deviceNib && opts.join === "round")) {
29739
29780
  return widenInLogicalSpace(path, opts, opts.matrix);
29740
29781
  }
29741
29782
  const out = [];
@@ -29769,7 +29810,7 @@ function widenPath(path, opts) {
29769
29810
  const shorten = opts.cap === "flat" || opts.shortenDashes === false ? 0 : opts.dashMetric ? opts.width / opts.dashMetric[0] : opts.width;
29770
29811
  const runTangents = closed ? [...dirs, void 0] : dirs;
29771
29812
  const runCurves = closed ? [...curves, !!fig.roundWiden] : curves;
29772
- for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric)) {
29813
+ for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric, opts.deviceNib ? opts.matrix : void 0)) {
29773
29814
  const pts = [piece.pts[0]];
29774
29815
  const pdirs = [];
29775
29816
  const pdraws = [];
@@ -30039,14 +30080,15 @@ function penWidenOptions(rCtx, opts = {}) {
30039
30080
  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;
30040
30081
  const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
30041
30082
  const rotatedOrSheared = Math.abs(matrix[1]) >= 1e-6 || Math.abs(matrix[2]) >= 1e-6;
30042
- const similar = Math.abs(matrix[0] - matrix[3]) < 1e-6 && Math.abs(matrix[1] + matrix[2]) < 1e-6 || Math.abs(matrix[0] + matrix[3]) < 1e-6 && Math.abs(matrix[1] - matrix[2]) < 1e-6;
30043
- const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !similar && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30083
+ const quarterTurn = Math.abs(matrix[0]) < 1e-9 && Math.abs(matrix[3]) < 1e-9;
30084
+ const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !quarterTurn && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30044
30085
  const dashes = state.penExtended ? ellipse || general ? geometricStyle(flags, state.penWidth, state.penUserStyle, 1) : geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
30045
30086
  const dashMetric = ellipse && dashes ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : void 0;
30046
30087
  if (general) {
30047
30088
  return {
30048
30089
  width: Math.round(state.penWidth * 16),
30049
30090
  matrix: [matrix[0], matrix[1], matrix[2], matrix[3]],
30091
+ deviceNib: true,
30050
30092
  cap: opts.roundPen || !state.penExtended || capBits === 0 ? "round" : capBits === 256 ? "square" : "flat",
30051
30093
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
30052
30094
  miterLimit: state.miterLimit ?? 10,
package/dist/index.mjs CHANGED
@@ -29237,11 +29237,42 @@ function penPolygon(width, height = width) {
29237
29237
  penCache.set(key, pen);
29238
29238
  return pen;
29239
29239
  }
29240
- function drawVertices(pen, dx, dy, width = 1, height = width) {
29240
+ var matrixPenCache = /* @__PURE__ */ new Map();
29241
+ function penPolygonMatrix(width, m) {
29242
+ const key = `${width},${m.join(",")}`;
29243
+ const cached = matrixPenCache.get(key);
29244
+ if (cached) {
29245
+ return cached;
29246
+ }
29247
+ const r = Math.ceil(width / 2);
29248
+ const mirror2 = m[0] * m[3] - m[1] * m[2] < 0 ? -1 : 1;
29249
+ const bez = ellipseBeziers(-r, -r, r, r);
29250
+ const dev = [];
29251
+ for (let i = 0; i < 14; i += 2) {
29252
+ const x = bez[i];
29253
+ const y = bez[i + 1] * mirror2;
29254
+ dev.push(Math.round(m[0] * x + m[2] * y), Math.round(m[1] * x + m[3] * y));
29255
+ }
29256
+ const f = flattenBezierPath(dev);
29257
+ const half = [];
29258
+ for (let i = 0; i + 1 < f.length; i += 2) {
29259
+ half.push([f[i], f[i + 1]]);
29260
+ }
29261
+ half.pop();
29262
+ const pen = [...half, ...half.map((p) => [0 - p[0] || 0, 0 - p[1] || 0])];
29263
+ matrixPenCache.set(key, pen);
29264
+ return pen;
29265
+ }
29266
+ function drawVertices(pen, dx, dy, width = 1, height = width, matrix) {
29241
29267
  const n = pen.length;
29242
29268
  const axisVertex = pen.some((q) => q[1] === 0);
29243
- const yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29244
- const xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29269
+ let yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29270
+ let xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29271
+ if (matrix) {
29272
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29273
+ xMagnitude = Math.abs((matrix[3] * dx - matrix[2] * dy) / det);
29274
+ yMagnitude = Math.abs((-matrix[1] * dx + matrix[0] * dy) / det);
29275
+ }
29245
29276
  const steep = yMagnitude > xMagnitude || yMagnitude === xMagnitude && axisVertex;
29246
29277
  const s = (steep ? dy < 0 : dx < 0 || dx === 0 && dy < 0) ? -1 : 1;
29247
29278
  let best = 0;
@@ -29261,7 +29292,7 @@ function drawVertices(pen, dx, dy, width = 1, height = width) {
29261
29292
  function halfPixel(v) {
29262
29293
  return Math.sign(v) * 8 * Math.floor((Math.abs(v) + 4) / 8);
29263
29294
  }
29264
- function perpendicularVectors(width, dx0, dy0, height = width) {
29295
+ function perpendicularVectors(width, dx0, dy0, height = width, matrixPen) {
29265
29296
  let dx = dx0;
29266
29297
  let dy = dy0;
29267
29298
  const flip = dx < 0 || dx === 0 && dy < 0;
@@ -29269,7 +29300,7 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29269
29300
  dx = -dx;
29270
29301
  dy = -dy;
29271
29302
  }
29272
- const pen = penPolygon(width, height);
29303
+ const pen = matrixPen ?? penPolygon(width, height);
29273
29304
  const n = pen.length;
29274
29305
  const nx = -dy;
29275
29306
  const ny = dx;
@@ -29308,7 +29339,15 @@ function perpendicularVectors(width, dx0, dy0, height = width) {
29308
29339
  const vx = rounded[0], vy = rounded[1];
29309
29340
  return { v: flip ? [-vx, -vy] : [vx, vy], ray: flip ? [-x, -y] : [x, y] };
29310
29341
  }
29311
- function squareExtension(width, dx, dy, scale = 1, height = width) {
29342
+ function squareExtension(width, dx, dy, scale = 1, height = width, matrix) {
29343
+ if (matrix) {
29344
+ const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
29345
+ const lx = (matrix[3] * dx - matrix[2] * dy) / det;
29346
+ const ly = (-matrix[1] * dx + matrix[0] * dy) / det;
29347
+ const l = Math.hypot(lx, ly);
29348
+ const q = width / 2 * scale / l;
29349
+ return [Math.floor((matrix[0] * lx + matrix[2] * ly) * q + 0.5), Math.floor((matrix[1] * lx + matrix[3] * ly) * q + 0.5)];
29350
+ }
29312
29351
  const len = width === height ? Math.hypot(dx, dy) : Math.hypot(dx, dy * width / height);
29313
29352
  const r = width / 2 * scale;
29314
29353
  return [Math.floor(dx / len * r + 0.5), Math.floor(dy / len * r + 0.5)];
@@ -29331,7 +29370,7 @@ var Outliner = class {
29331
29370
  this.opts = opts;
29332
29371
  this.out = out;
29333
29372
  this.pts = [];
29334
- this.pen = penPolygon(opts.width, opts.height);
29373
+ this.pen = opts.matrix && opts.deviceNib ? penPolygonMatrix(opts.width, opts.matrix) : penPolygon(opts.width, opts.height);
29335
29374
  this.n = this.pen.length;
29336
29375
  this.rr = opts.cap === "round" && opts.join === "round";
29337
29376
  this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
@@ -29346,10 +29385,11 @@ var Outliner = class {
29346
29385
  const dx = dir ? dir[0] : b[0] - a[0];
29347
29386
  const dy = dir ? dir[1] : b[1] - a[1];
29348
29387
  const d = drawDir ?? [dx, dy];
29349
- const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height);
29388
+ const nibMatrix = this.opts.deviceNib ? this.opts.matrix : void 0;
29389
+ const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height, nibMatrix);
29350
29390
  const perpendicular = curve && drawDir ? drawDir : [dx, dy];
29351
- const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height);
29352
- return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29391
+ const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height, nibMatrix ? this.pen : void 0);
29392
+ return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height, nibMatrix), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29353
29393
  }
29354
29394
  push(p, v) {
29355
29395
  this.pts.push([p[0] + v[0], p[1] + v[1]]);
@@ -29462,7 +29502,7 @@ var Outliner = class {
29462
29502
  const sv = this.capSide(s, from);
29463
29503
  const ev = this.capSide(s, to);
29464
29504
  if (cap === "square") {
29465
- const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height);
29505
+ const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height, this.opts.deviceNib ? this.opts.matrix : void 0);
29466
29506
  const e = start ? [-e0[0], -e0[1]] : e0;
29467
29507
  this.push(p, [sv[0] + e[0], sv[1] + e[1]]);
29468
29508
  this.push(p, [ev[0] + e[0], ev[1] + e[1]]);
@@ -29642,7 +29682,7 @@ var Outliner = class {
29642
29682
  this.flush();
29643
29683
  }
29644
29684
  };
29645
- function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric) {
29685
+ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric, matrix) {
29646
29686
  const out = [];
29647
29687
  const dashes = [];
29648
29688
  for (let i = 0; i < pattern.length; i += 2) {
@@ -29662,8 +29702,9 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
29662
29702
  const [x0, y0] = P[i];
29663
29703
  const [x1, y1] = P[i + 1];
29664
29704
  const dir = [x1 - x0, y1 - y0];
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]);
29705
+ const det = matrix ? matrix[0] * matrix[3] - matrix[1] * matrix[2] : 1;
29706
+ const real = matrix ? Math.hypot((matrix[3] * dir[0] - matrix[2] * dir[1]) / det, (-matrix[1] * dir[0] + matrix[0] * dir[1]) / det) : metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : Math.hypot(dir[0], dir[1]);
29707
+ const len = metric || matrix ? real : wholePixelVectors ? Math.hypot(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : Math.hypot(dir[0], dir[1]);
29667
29708
  if (len === 0) {
29668
29709
  if (on && cur) {
29669
29710
  cur.pts.push(P[i + 1]);
@@ -29733,7 +29774,7 @@ function widenInLogicalSpace(path, opts, m) {
29733
29774
  });
29734
29775
  }
29735
29776
  function widenPath(path, opts) {
29736
- if (opts.matrix) {
29777
+ if (opts.matrix && !(opts.deviceNib && opts.join === "round")) {
29737
29778
  return widenInLogicalSpace(path, opts, opts.matrix);
29738
29779
  }
29739
29780
  const out = [];
@@ -29767,7 +29808,7 @@ function widenPath(path, opts) {
29767
29808
  const shorten = opts.cap === "flat" || opts.shortenDashes === false ? 0 : opts.dashMetric ? opts.width / opts.dashMetric[0] : opts.width;
29768
29809
  const runTangents = closed ? [...dirs, void 0] : dirs;
29769
29810
  const runCurves = closed ? [...curves, !!fig.roundWiden] : curves;
29770
- for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric)) {
29811
+ for (const piece of dashPieces(run, runTangents, runCurves, opts.dashes, shorten, !!opts.wholePixelDashVectors, opts.dashMetric, opts.deviceNib ? opts.matrix : void 0)) {
29771
29812
  const pts = [piece.pts[0]];
29772
29813
  const pdirs = [];
29773
29814
  const pdraws = [];
@@ -30037,14 +30078,15 @@ function penWidenOptions(rCtx, opts = {}) {
30037
30078
  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;
30038
30079
  const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
30039
30080
  const rotatedOrSheared = Math.abs(matrix[1]) >= 1e-6 || Math.abs(matrix[2]) >= 1e-6;
30040
- const similar = Math.abs(matrix[0] - matrix[3]) < 1e-6 && Math.abs(matrix[1] + matrix[2]) < 1e-6 || Math.abs(matrix[0] + matrix[3]) < 1e-6 && Math.abs(matrix[1] - matrix[2]) < 1e-6;
30041
- const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !similar && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30081
+ const quarterTurn = Math.abs(matrix[0]) < 1e-9 && Math.abs(matrix[3]) < 1e-9;
30082
+ const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !quarterTurn && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
30042
30083
  const dashes = state.penExtended ? ellipse || general ? geometricStyle(flags, state.penWidth, state.penUserStyle, 1) : geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
30043
30084
  const dashMetric = ellipse && dashes ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : void 0;
30044
30085
  if (general) {
30045
30086
  return {
30046
30087
  width: Math.round(state.penWidth * 16),
30047
30088
  matrix: [matrix[0], matrix[1], matrix[2], matrix[3]],
30089
+ deviceNib: true,
30048
30090
  cap: opts.roundPen || !state.penExtended || capBits === 0 ? "round" : capBits === 256 ? "square" : "flat",
30049
30091
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
30050
30092
  miterLimit: state.miterLimit ?? 10,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emf-converter",
3
- "version": "4.10.0",
3
+ "version": "4.11.1",
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",