emf-converter 4.15.1 → 4.16.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.js CHANGED
@@ -21044,6 +21044,7 @@ function invert2(m) {
21044
21044
  }
21045
21045
  var COVERAGE_NUDGE_X = 1e-6;
21046
21046
  var COVERAGE_NUDGE_Y = 1e-9;
21047
+ var AXIS_ALIGNED_SHEAR = 5e-4;
21047
21048
  var SUBPIXEL_GRID = 16;
21048
21049
  function snapToDeviceGrid(spec) {
21049
21050
  const m = spec.toDevice;
@@ -21093,8 +21094,11 @@ function fadeAt(d, bilinear) {
21093
21094
  const i = Math.floor(x);
21094
21095
  return FAR_FADE[i] + (FAR_FADE[i + 1] - FAR_FADE[i]) * (x - i);
21095
21096
  }
21097
+ function ceilExtent(len) {
21098
+ return Math.ceil(len * (1 - 15e-8));
21099
+ }
21096
21100
  function nearSourceExtent(deviceLen, srcLen) {
21097
- const d = Math.ceil(deviceLen - 1e-6) - srcLen;
21101
+ const d = ceilExtent(deviceLen) - srcLen;
21098
21102
  return d >= -1 && d <= 1;
21099
21103
  }
21100
21104
  var BICUBIC_A = -0.5;
@@ -21123,7 +21127,7 @@ function axisFilter(kernel, scale, copy) {
21123
21127
  return { radius: 0.5, weight: (i, c) => Math.floor(c + 0.5) === i ? 1 : 0 };
21124
21128
  }
21125
21129
  }
21126
- function blendSeparable(rgba, width, box, iu0, wu, iv0, wv, verticalFirst, edge = { wrap: void 0, clamp: null }, integerBicubic = false) {
21130
+ function blendSeparable(rgba, width, box, iu0, wu, iv0, wv, verticalFirst, edge = { wrap: void 0, clamp: null }, integerBicubic = false, premult = false) {
21127
21131
  const [outer0, outerW, inner0, innerW] = verticalFirst ? [iu0, wu, iv0, wv] : [iv0, wv, iu0, wu];
21128
21132
  const [oMin, oMax, iMin, iMax] = verticalFirst ? [box.x0, box.x1, box.y0, box.y1] : [box.y0, box.y1, box.x0, box.x1];
21129
21133
  let r = 0;
@@ -21164,9 +21168,9 @@ function blendSeparable(rgba, width, box, iu0, wu, iv0, wv, verticalFirst, edge
21164
21168
  }
21165
21169
  const alpha = px[s + 3];
21166
21170
  const wa = wi * alpha / 255;
21167
- lr += integerBicubic ? wi * Math.round(alpha * px[s] / 255) : wa * px[s];
21168
- lg += integerBicubic ? wi * Math.round(alpha * px[s + 1] / 255) : wa * px[s + 1];
21169
- lb += integerBicubic ? wi * Math.round(alpha * px[s + 2] / 255) : wa * px[s + 2];
21171
+ lr += premult ? wi * px[s] : integerBicubic ? wi * Math.round(alpha * px[s] / 255) : wa * px[s];
21172
+ lg += premult ? wi * px[s + 1] : integerBicubic ? wi * Math.round(alpha * px[s + 1] / 255) : wa * px[s + 1];
21173
+ lb += premult ? wi * px[s + 2] : integerBicubic ? wi * Math.round(alpha * px[s + 2] / 255) : wa * px[s + 2];
21170
21174
  la += wi * alpha;
21171
21175
  }
21172
21176
  if (integerBicubic) {
@@ -21206,7 +21210,8 @@ function mirroredOrigin(o) {
21206
21210
  const f = o - Math.floor(o);
21207
21211
  return f === 0 ? o : Math.floor(o) + 1 - f;
21208
21212
  }
21209
- function resampleImage(rgba, width, height, spec, surface) {
21213
+ function resampleImage(rgba, width, height, spec, surface, options2 = {}) {
21214
+ const { plainRotated: plainRotatedPass = false, keepOrigin = false, premultSource = false, premultOut = false } = typeof options2 === "boolean" ? { plainRotated: options2 } : options2;
21210
21215
  if (spec.rightHalo && spec.rightHalo.length === height * 4) {
21211
21216
  const grown = new Uint8ClampedArray((width + 1) * height * 4);
21212
21217
  for (let y = 0; y < height; y++) {
@@ -21218,20 +21223,27 @@ function resampleImage(rgba, width, height, spec, surface) {
21218
21223
  if (spec.kernel === "nearest" && !spec.wrap) {
21219
21224
  return resampleNearest(rgba, width, height, spec, surface);
21220
21225
  }
21221
- let m = snapToDeviceGrid(spec);
21226
+ let m = keepOrigin ? spec.toDevice : snapToDeviceGrid(spec);
21222
21227
  let kernel = spec.kernel;
21223
21228
  const hq = kernel === "hq-bilinear" || kernel === "hq-bicubic";
21229
+ if (hq && (m[1] !== 0 || m[2] !== 0) && Math.abs(m[1]) <= AXIS_ALIGNED_SHEAR * Math.abs(m[0]) && Math.abs(m[2]) <= AXIS_ALIGNED_SHEAR * Math.abs(m[3])) {
21230
+ m = [m[0], 0, 0, m[3], m[4], m[5]];
21231
+ }
21224
21232
  const axisAligned = m[1] === 0 && m[2] === 0;
21225
- const integerBicubic = kernel === "bicubic" && axisAligned;
21226
- const unitBicubicCopy = integerBicubic && !spec.halfPixelOffset && m[0] === 1 && m[3] === 1 && m[4] - Math.round(m[4]) > -1 / 64 && m[4] - Math.round(m[4]) <= 1 / 64 && m[5] - Math.round(m[5]) > -1 / 64 && m[5] - Math.round(m[5]) <= 1 / 64;
21233
+ let plainRotated = plainRotatedPass;
21234
+ const unitBicubicCopy = kernel === "bicubic" && axisAligned && !spec.halfPixelOffset && m[0] === 1 && m[3] === 1 && m[4] - Math.round(m[4]) > -1 / 64 && m[4] - Math.round(m[4]) <= 1 / 64 && m[5] - Math.round(m[5]) > -1 / 64 && m[5] - Math.round(m[5]) <= 1 / 64;
21227
21235
  let farFade = false;
21228
21236
  let shiftX = 0;
21229
21237
  let shiftY = 0;
21230
21238
  if (hq && !axisAligned) {
21231
21239
  const extentU = Math.hypot(m[0], m[1]) * spec.srcW;
21232
21240
  const extentV = Math.hypot(m[2], m[3]) * spec.srcH;
21233
- if (nearSourceExtent(extentU, spec.srcW) || nearSourceExtent(extentV, spec.srcH)) {
21241
+ const near = nearSourceExtent(extentU, spec.srcW) || nearSourceExtent(extentV, spec.srcH);
21242
+ if (!spec.wrap) {
21243
+ return resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel, near);
21244
+ } else if (near) {
21234
21245
  kernel = kernel === "hq-bicubic" ? "bicubic" : "bilinear";
21246
+ plainRotated = true;
21235
21247
  } else {
21236
21248
  farFade = true;
21237
21249
  if (spec.halfPixelOffset) {
@@ -21242,6 +21254,13 @@ function resampleImage(rgba, width, height, spec, surface) {
21242
21254
  }
21243
21255
  }
21244
21256
  }
21257
+ const integerBicubic = kernel === "bicubic" && (axisAligned || plainRotated);
21258
+ if (hq && axisAligned && !spec.wrap && !premultSource) {
21259
+ const phased = resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut);
21260
+ if (phased !== void 0) {
21261
+ return phased;
21262
+ }
21263
+ }
21245
21264
  if (hq && axisAligned) {
21246
21265
  const ox = m[0] * spec.srcX + m[4];
21247
21266
  m = [m[0], 0, 0, m[3], m[4] + mirroredOrigin(ox) - ox, m[5]];
@@ -21351,7 +21370,7 @@ function resampleImage(rgba, width, height, spec, surface) {
21351
21370
  for (let t = iv0; t <= iv1; t++) {
21352
21371
  wv.push(integerBicubic ? Math.round(fv.weight(t, cv) * 65536) / 65536 : fv.weight(t, cv));
21353
21372
  }
21354
- return blendSeparable(rgba, width, box, iu0, wu, iv0, wv, kernel === "bicubic", edge, integerBicubic);
21373
+ return blendSeparable(rgba, width, box, iu0, wu, iv0, wv, kernel === "bicubic", edge, integerBicubic, premultSource);
21355
21374
  };
21356
21375
  let [r, g, b, a] = sampleAt(u, v);
21357
21376
  if (farFade && !spec.wrap && a > 0) {
@@ -21375,6 +21394,12 @@ function resampleImage(rgba, width, height, spec, surface) {
21375
21394
  b = Math.trunc(b);
21376
21395
  a = Math.trunc(a);
21377
21396
  if (a <= 0) continue;
21397
+ } else if (premultSource) {
21398
+ r = Math.round(r);
21399
+ g = Math.round(g);
21400
+ b = Math.round(b);
21401
+ a = Math.round(a);
21402
+ if (a <= 0) continue;
21378
21403
  }
21379
21404
  const alpha = Math.min(255, a);
21380
21405
  const dst = (j * w + i) * 4;
@@ -21386,6 +21411,244 @@ function resampleImage(rgba, width, height, spec, surface) {
21386
21411
  }
21387
21412
  return { x: bx0, y: by0, w, h, rgba: out };
21388
21413
  }
21414
+ var HQ_PHASES = 128;
21415
+ function resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut) {
21416
+ const kernel = spec.kernel;
21417
+ const scaleU = m[0];
21418
+ const scaleV = m[3];
21419
+ if (!(scaleU >= 1 && scaleV >= 1) || spec.rightHalo) {
21420
+ return void 0;
21421
+ }
21422
+ const integral = (v) => Math.abs(v - Math.round(v)) < 1e-9;
21423
+ if (scaleU === 1 && scaleV === 1 && integral(m[4]) && integral(m[5])) {
21424
+ return void 0;
21425
+ }
21426
+ const shift = spec.halfPixelOffset ? 0.5 : 0;
21427
+ const left = m[0] * spec.srcX + m[4] - shift;
21428
+ const top = m[3] * spec.srcY + m[5] - shift;
21429
+ const right = left + m[0] * spec.srcW;
21430
+ const bottom = top + m[3] * spec.srcH;
21431
+ const xFirst = Math.ceil(left - COVERAGE_NUDGE_X);
21432
+ const xLast = Math.ceil(right - COVERAGE_NUDGE_X) - 1;
21433
+ const yFirst = Math.ceil(top - COVERAGE_NUDGE_Y);
21434
+ const yLast = Math.ceil(bottom - COVERAGE_NUDGE_Y) - 1;
21435
+ const cx0 = Math.max(0, xFirst);
21436
+ const cy0 = Math.max(0, yFirst);
21437
+ const cx1 = Math.min(surface.w - 1, xLast);
21438
+ const cy1 = Math.min(surface.h - 1, yLast);
21439
+ if (cx1 < cx0 || cy1 < cy0) {
21440
+ return null;
21441
+ }
21442
+ const w = cx1 - cx0 + 1;
21443
+ const h = cy1 - cy0 + 1;
21444
+ if (w * h > MAX_RESAMPLE_PIXELS) {
21445
+ return null;
21446
+ }
21447
+ const cubic = kernel === "hq-bicubic";
21448
+ const bin = cubic ? 0.5 : 1;
21449
+ const stepU = Math.round(65536 / scaleU);
21450
+ const stepV = Math.round(65536 / scaleV);
21451
+ const dx = Math.max(0, xFirst - left);
21452
+ const dy = Math.max(0, yFirst - top);
21453
+ const offsetU = dx > 1e-9 ? Math.round((1 - dx) * stepU) : 0;
21454
+ const offsetV = dy > 1e-9 ? Math.round(dy * stepV) : 0;
21455
+ const filterU = axisFilter(kernel, scaleU, false);
21456
+ const filterV = axisFilter(kernel, scaleV, false);
21457
+ const tapsFor = (filter, step, offset, origin, from, to) => {
21458
+ const taps = [];
21459
+ for (let k = from; k <= to; k++) {
21460
+ const phase = Math.floor((k * step + offset - 1) / (65536 / HQ_PHASES));
21461
+ const c = origin + (phase + bin) / HQ_PHASES;
21462
+ const first = Math.ceil(c - filter.radius);
21463
+ const last = Math.floor(c + filter.radius);
21464
+ const weights = [];
21465
+ for (let t = first; t <= last; t++) {
21466
+ weights.push(filter.weight(t, c));
21467
+ }
21468
+ taps.push({ first, weights });
21469
+ }
21470
+ return taps;
21471
+ };
21472
+ const colTaps = tapsFor(filterU, stepU, offsetU, spec.srcX, cx0 - xFirst, cx1 - xFirst);
21473
+ const rowTaps = tapsFor(filterV, stepV, offsetV, spec.srcY, cy0 - yFirst, cy1 - yFirst);
21474
+ let rowMin = Infinity;
21475
+ let rowMax = -Infinity;
21476
+ for (const t of rowTaps) {
21477
+ rowMin = Math.min(rowMin, t.first);
21478
+ rowMax = Math.max(rowMax, t.first + t.weights.length - 1);
21479
+ }
21480
+ rowMin = Math.max(0, rowMin);
21481
+ rowMax = Math.min(height - 1, rowMax);
21482
+ const rows = Math.max(0, rowMax - rowMin + 1);
21483
+ const inter = new Uint8Array(rows * w * 4);
21484
+ for (let r = 0; r < rows; r++) {
21485
+ const srcRow = (rowMin + r) * width;
21486
+ for (let i = 0; i < w; i++) {
21487
+ const t = colTaps[i];
21488
+ let pr = 0;
21489
+ let pg = 0;
21490
+ let pb = 0;
21491
+ let pa = 0;
21492
+ for (let q = 0; q < t.weights.length; q++) {
21493
+ const tx = t.first + q;
21494
+ if (tx < 0 || tx >= width) {
21495
+ continue;
21496
+ }
21497
+ const o = (srcRow + tx) * 4;
21498
+ const a = rgba[o + 3];
21499
+ if (a === 0) {
21500
+ continue;
21501
+ }
21502
+ const wq = t.weights[q];
21503
+ pr += wq * Math.round(rgba[o] * a / 255);
21504
+ pg += wq * Math.round(rgba[o + 1] * a / 255);
21505
+ pb += wq * Math.round(rgba[o + 2] * a / 255);
21506
+ pa += wq * a;
21507
+ }
21508
+ const alpha = Math.min(255, Math.max(0, Math.round(pa)));
21509
+ const d = (r * w + i) * 4;
21510
+ inter[d] = Math.min(alpha, Math.max(0, Math.round(pr)));
21511
+ inter[d + 1] = Math.min(alpha, Math.max(0, Math.round(pg)));
21512
+ inter[d + 2] = Math.min(alpha, Math.max(0, Math.round(pb)));
21513
+ inter[d + 3] = alpha;
21514
+ }
21515
+ }
21516
+ const out = new Uint8ClampedArray(w * h * 4);
21517
+ for (let j = 0; j < h; j++) {
21518
+ const t = rowTaps[j];
21519
+ for (let i = 0; i < w; i++) {
21520
+ let pr = 0;
21521
+ let pg = 0;
21522
+ let pb = 0;
21523
+ let pa = 0;
21524
+ for (let q = 0; q < t.weights.length; q++) {
21525
+ const ty = t.first + q - rowMin;
21526
+ if (ty < 0 || ty >= rows) {
21527
+ continue;
21528
+ }
21529
+ const o = (ty * w + i) * 4;
21530
+ const wq = t.weights[q];
21531
+ pr += wq * inter[o];
21532
+ pg += wq * inter[o + 1];
21533
+ pb += wq * inter[o + 2];
21534
+ pa += wq * inter[o + 3];
21535
+ }
21536
+ const alpha = Math.min(255, Math.max(0, Math.round(pa)));
21537
+ if (alpha === 0) {
21538
+ continue;
21539
+ }
21540
+ const d = (j * w + i) * 4;
21541
+ const k = premultOut ? 1 : 255 / alpha;
21542
+ out[d] = Math.min(alpha, Math.max(0, Math.round(pr))) * k;
21543
+ out[d + 1] = Math.min(alpha, Math.max(0, Math.round(pg))) * k;
21544
+ out[d + 2] = Math.min(alpha, Math.max(0, Math.round(pb))) * k;
21545
+ out[d + 3] = alpha;
21546
+ }
21547
+ }
21548
+ return { x: cx0, y: cy0, w, h, rgba: out, premultiplied: premultOut };
21549
+ }
21550
+ function resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel, near) {
21551
+ const pad = 2;
21552
+ let img;
21553
+ let pw;
21554
+ let ph;
21555
+ let a;
21556
+ let b;
21557
+ let c;
21558
+ let d;
21559
+ let ex;
21560
+ let ey;
21561
+ const half = spec.halfPixelOffset;
21562
+ if (near) {
21563
+ pw = width + 2 * pad;
21564
+ ph = height + 2 * pad;
21565
+ img = new Uint8ClampedArray(pw * ph * 4);
21566
+ for (let y = 0; y < height; y++) {
21567
+ for (let x = 0; x < width; x++) {
21568
+ const s = (y * width + x) * 4;
21569
+ const al = rgba[s + 3];
21570
+ const o = ((y + pad) * pw + x + pad) * 4;
21571
+ img[o] = Math.round(rgba[s] * al / 255);
21572
+ img[o + 1] = Math.round(rgba[s + 1] * al / 255);
21573
+ img[o + 2] = Math.round(rgba[s + 2] * al / 255);
21574
+ img[o + 3] = al;
21575
+ }
21576
+ }
21577
+ [a, b, c, d] = m;
21578
+ ex = m[4] - (half ? 0.5 : 0);
21579
+ ey = m[5] - (half ? 0.5 : 0);
21580
+ } else {
21581
+ const W = ceilExtent(Math.hypot(m[0], m[1]) * spec.srcW);
21582
+ const H = ceilExtent(Math.hypot(m[2], m[3]) * spec.srcH);
21583
+ const kx = W / spec.srcW;
21584
+ const ky = H / spec.srcH;
21585
+ const pre = resampleImage(rgba, width, height, {
21586
+ srcX: spec.srcX,
21587
+ srcY: spec.srcY,
21588
+ srcW: spec.srcW,
21589
+ srcH: spec.srcH,
21590
+ toDevice: [kx, 0, 0, ky, -spec.srcX * kx, -spec.srcY * ky],
21591
+ kernel,
21592
+ halfPixelOffset: false
21593
+ }, { w: W, h: H }, { premultOut: true });
21594
+ if (!pre) {
21595
+ return null;
21596
+ }
21597
+ if (!pre.premultiplied) {
21598
+ for (let i = 0; i < pre.rgba.length; i += 4) {
21599
+ const al = pre.rgba[i + 3];
21600
+ pre.rgba[i] = Math.round(pre.rgba[i] * al / 255);
21601
+ pre.rgba[i + 1] = Math.round(pre.rgba[i + 1] * al / 255);
21602
+ pre.rgba[i + 2] = Math.round(pre.rgba[i + 2] * al / 255);
21603
+ }
21604
+ }
21605
+ pw = W + 2 * pad;
21606
+ ph = H + 2 * pad;
21607
+ img = new Uint8ClampedArray(pw * ph * 4);
21608
+ for (let y = 0; y < pre.h; y++) {
21609
+ for (let x = 0; x < pre.w; x++) {
21610
+ const dx = x + pre.x;
21611
+ const dy = y + pre.y;
21612
+ if (dx < W && dy < H) {
21613
+ img.set(pre.rgba.subarray((y * pre.w + x) * 4, (y * pre.w + x) * 4 + 4), ((dy + pad) * pw + dx + pad) * 4);
21614
+ }
21615
+ }
21616
+ }
21617
+ a = m[0] / kx;
21618
+ b = m[1] / kx;
21619
+ c = m[2] / ky;
21620
+ d = m[3] / ky;
21621
+ const ox = m[0] * spec.srcX + m[2] * spec.srcY + m[4];
21622
+ const oy = m[1] * spec.srcX + m[3] * spec.srcY + m[5];
21623
+ ex = half ? ox - 0.5 + 0.5 * (a + c) : ox;
21624
+ ey = half ? oy - 0.5 + 0.5 * (b + d) : oy;
21625
+ }
21626
+ const block = resampleImage(img, pw, ph, {
21627
+ srcX: 0,
21628
+ srcY: 0,
21629
+ srcW: pw,
21630
+ srcH: ph,
21631
+ toDevice: [a, b, c, d, ex - a * pad - c * pad, ey - b * pad - d * pad],
21632
+ kernel: kernel === "hq-bicubic" ? "bicubic" : "bilinear",
21633
+ halfPixelOffset: false
21634
+ }, surface, { plainRotated: true, keepOrigin: true, premultSource: true });
21635
+ if (!block) {
21636
+ return block;
21637
+ }
21638
+ const corners = [
21639
+ [spec.srcX, spec.srcY],
21640
+ [spec.srcX + spec.srcW, spec.srcY],
21641
+ [spec.srcX + spec.srcW, spec.srcY + spec.srcH],
21642
+ [spec.srcX, spec.srcY + spec.srcH]
21643
+ ].flatMap(([u, v]) => [toPlusFix(m[0] * u + m[2] * v + m[4]), toPlusFix(m[1] * u + m[3] * v + m[5])]);
21644
+ const coverage = rasterizePlusFill([corners], false, false, half, { x: block.x, y: block.y, w: block.w, h: block.h });
21645
+ for (let i = 0; i < block.w * block.h; i++) {
21646
+ if (!coverage[i]) {
21647
+ block.rgba.fill(0, i * 4, i * 4 + 4);
21648
+ }
21649
+ }
21650
+ return block;
21651
+ }
21389
21652
  var FIX16 = 65536;
21390
21653
  function resampleNearest(rgba, width, height, spec, surface) {
21391
21654
  const m = spec.toDevice;
@@ -29999,7 +30262,7 @@ function squareExtension(width, dx, dy, scale = 1, height = width, matrix, whole
29999
30262
  const ly = (-matrix[1] * dx + matrix[0] * dy) / det;
30000
30263
  let l = Math.hypot(lx, ly);
30001
30264
  if (wholePixelNorm) {
30002
- l = norm(Math.floor((lx + slack) / 16) * 16, Math.floor((ly + slack) / 16) * 16);
30265
+ l = norm(Math.sign(lx) * Math.floor((Math.abs(lx) + slack) / 16) * 16, Math.sign(ly) * Math.floor((Math.abs(ly) + slack) / 16) * 16);
30003
30266
  if (l === 0) return [0, 0];
30004
30267
  }
30005
30268
  const q = width / 2 * scale / l;
@@ -30012,7 +30275,8 @@ function squareExtension(width, dx, dy, scale = 1, height = width, matrix, whole
30012
30275
  const lx = dx / ax;
30013
30276
  const ly = dy / ay;
30014
30277
  const cut = ax === 1 && ay === 1 ? 0 : slack;
30015
- const whole = norm(Math.floor((lx + cut) / 16) * 16, Math.floor((ly + cut) / 16) * 16);
30278
+ const unit = (v) => cut ? Math.sign(v) * Math.floor((Math.abs(v) + cut) / 16) * 16 : Math.floor(v / 16) * 16;
30279
+ const whole = norm(unit(lx), unit(ly));
30016
30280
  if (whole === 0) return [0, 0];
30017
30281
  return [round(lx / whole * r), round(ly * ay / ax / whole * r)];
30018
30282
  }
@@ -30230,6 +30494,11 @@ var Outliner = class {
30230
30494
  this.pts.push([p[0], p[1]]);
30231
30495
  if (curveJoin && !this.originalRoundJoinSides) {
30232
30496
  this.push(p, sb);
30497
+ if (cap === "flat" && Da !== Db && !(a.curveEnd && b.curveEnd)) {
30498
+ const before = this.pts.length;
30499
+ this.wedge(p, rayB, rayA, false, false, this.extremeTail(side === "L", Da, a));
30500
+ if (this.pts.length - before < 2) this.pts.length = before;
30501
+ }
30233
30502
  this.push(p, sa);
30234
30503
  this.pts.push([p[0], p[1]]);
30235
30504
  }
@@ -30763,9 +31032,8 @@ function penWidenOptions(rCtx, opts = {}) {
30763
31032
  const unrotated = Math.abs(matrix[1]) < 1e-6 && Math.abs(matrix[2]) < 1e-6;
30764
31033
  const scaled2 = !rCtx.wholeDevicePixels && unrotated && (Math.abs(Math.abs(matrix[0]) - 1) > 1e-6 || Math.abs(Math.abs(matrix[3]) - 1) > 1e-6);
30765
31034
  const uniform = scaled2 && !ellipse && state.penExtended && (flags & 15) !== 6;
30766
- const nibWidth = uniform ? Math.max(1, Math.floor(widthPx + 0.5)) : widthPx;
30767
31035
  return {
30768
- width: Math.round((ellipse ? state.penWidth * Math.abs(matrix[0]) : nibWidth) * 16),
31036
+ width: Math.round((ellipse ? state.penWidth * Math.abs(matrix[0]) : widthPx) * 16),
30769
31037
  ...ellipse ? { height: Math.round(state.penWidth * Math.abs(matrix[3]) * 16) } : {},
30770
31038
  cap: opts.roundPen || !state.penExtended || capBits === 0 ? "round" : capBits === 256 ? "square" : "flat",
30771
31039
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
@@ -30779,7 +31047,7 @@ function penWidenOptions(rCtx, opts = {}) {
30779
31047
  ...scaled2 && !dashes ? {
30780
31048
  cutToLogicalUnits: true,
30781
31049
  logicalScale: ellipse ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : Math.abs(matrix[0]),
30782
- // The pen rounds to whole pixels, but a square cap extends by half the unrounded width.
31050
+ // A square cap extends by half the unrounded width in FIX.
30783
31051
  ...uniform ? { capWidth: state.penWidth * Math.abs(matrix[0]) * 16 } : {}
30784
31052
  } : {}
30785
31053
  };
@@ -32094,11 +32362,10 @@ function handleRoundRect(rCtx, dataOff, recSize) {
32094
32362
  const cornerOnFrame = (fix, size, framedSize) => inset && size !== 0 ? Math.floor(Math.min(fix, size) * framedSize / size) : fix;
32095
32363
  let cw = cornerOnFrame(cornerFixW, Math.abs((r - l) * devM[0]) * 16, Math.abs(framed.exx));
32096
32364
  let ch = cornerOnFrame(cornerFixH, Math.abs((b - t) * devM[3]) * 16, Math.abs(framed.eyy));
32097
- if (!inset && rCtx.state.penStyle !== 6 && cornerW !== 0 && cornerH !== 0 && Math.abs(devM[1]) < 1e-9 && Math.abs(devM[2]) < 1e-9 && rCtx.state.penStyle !== 5 && !penIsCosmetic(rCtx) && rCtx.state.worldTransform.every((v, i) => v === [1, 0, 0, 1, 0, 0][i])) {
32098
- const fullW = (Math.abs(r - l) + 1) * Math.abs(devM[0]) * 16;
32099
- const fullH = (Math.abs(b - t) + 1) * Math.abs(devM[3]) * 16;
32100
- cw = Math.floor(Math.min(cornerFixW, fullW) * Math.abs(framed.exx) / fullW);
32101
- ch = Math.floor(Math.min(cornerFixH, fullH) * Math.abs(framed.eyy) / fullH);
32365
+ const drawBox = inset ? framed : curvedFixBox(rCtx, l, t, r, b, true);
32366
+ if (!inset && drawBox.exx !== unframed.exx && Math.abs(unframed.exx) > 0 && Math.abs(unframed.eyy) > 0 && cornerW !== 0 && cornerH !== 0) {
32367
+ cw = Math.floor(Math.min(cornerFixW, Math.abs(unframed.exx)) * Math.abs(drawBox.exx) / Math.abs(unframed.exx));
32368
+ ch = Math.floor(Math.min(cornerFixH, Math.abs(unframed.eyy)) * Math.abs(drawBox.eyy) / Math.abs(unframed.eyy));
32102
32369
  }
32103
32370
  const drawRoundRect = inset ? (c) => appendRoundRectPath(
32104
32371
  c,
@@ -32128,7 +32395,7 @@ function handleRoundRect(rCtx, dataOff, recSize) {
32128
32395
  }
32129
32396
  const raster = (box = framed) => roundRectRasterPath(box, cw, ch, clockwise, cornerW === 0 || cornerH === 0);
32130
32397
  if (inPath) {
32131
- const box = framed;
32398
+ const box = drawBox;
32132
32399
  if (cornerW === 0 || cornerH === 0) recordRectangle(rCtx, box, clockwise);
32133
32400
  else {
32134
32401
  recordBezierShape(rCtx, roundRectDeviceBeziers(box, cw, ch, clockwise), 8);
@@ -32141,7 +32408,7 @@ function handleRoundRect(rCtx, dataOff, recSize) {
32141
32408
  c.beginPath();
32142
32409
  drawRoundRect(c);
32143
32410
  },
32144
- raster: () => raster(inset ? framed : curvedFixBox(rCtx, l, t, r, b, true)),
32411
+ raster: () => raster(drawBox),
32145
32412
  roundPen: true,
32146
32413
  fill: true,
32147
32414
  stroke: true