emf-converter 4.8.8 → 4.8.10

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
@@ -15935,14 +15935,75 @@ function pathGradientColorAt(shape, x, y) {
15935
15935
  bestS = Math.max(0, alpha);
15936
15936
  bestU = alpha > 0 ? Math.min(1, Math.max(0, beta / alpha)) : 0;
15937
15937
  }
15938
- if (found < 0) {
15939
- return null;
15940
- }
15941
- let s = bestS;
15938
+ let s = found < 0 ? Infinity : bestS;
15942
15939
  if (shape.focus) {
15943
- const f = Math.min(0.999, Math.max(0, (shape.focus.x + shape.focus.y) / 2));
15944
- s = s <= f ? 0 : (s - f) / (1 - f);
15940
+ const fx = Math.min(1, Math.max(0, shape.focus.x));
15941
+ const fy = Math.min(1, Math.max(0, shape.focus.y));
15942
+ if (fx === fy) {
15943
+ s = s <= fx ? 0 : (s - fx) / (1 - fx);
15944
+ } else if (s > 0) {
15945
+ const dx = 1 - fx;
15946
+ const dy = 1 - fy;
15947
+ let distance = Infinity;
15948
+ let inFocus = false;
15949
+ for (let i = 0; i < n; i++) {
15950
+ const a = boundary[i];
15951
+ const b = boundary[(i + 1) % n];
15952
+ const ax = a.x - center.x;
15953
+ const ay = a.y - center.y;
15954
+ const ex = b.x - a.x;
15955
+ const ey = b.y - a.y;
15956
+ const cross = ax * ey - ay * ex;
15957
+ if (Math.abs(cross) < 1e-12) continue;
15958
+ if ((fx > 0 || Math.abs(px) < eps) && (fy > 0 || Math.abs(py) < eps)) {
15959
+ const x2 = fx > 0 ? px / fx : 0;
15960
+ const y2 = fy > 0 ? py / fy : 0;
15961
+ const alpha = (x2 * ey - y2 * ex) / cross;
15962
+ const beta = (ax * y2 - ay * x2) / cross;
15963
+ if (alpha >= -eps && alpha <= 1 + eps && beta >= -eps && beta <= alpha + eps) {
15964
+ inFocus = true;
15965
+ if (found < 0) found = i;
15966
+ }
15967
+ }
15968
+ const qa = cross * dx * dy;
15969
+ const qb = cross * (fx * dy + fy * dx) - px * ey * dy + py * ex * dx;
15970
+ const qc = cross * fx * fy - px * ey * fy + py * ex * fx;
15971
+ const disc = qb * qb - 4 * qa * qc;
15972
+ const roots = Math.abs(qa) < 1e-12 ? Math.abs(qb) > 1e-12 ? [-qc / qb] : [] : disc >= 0 ? [(-qb - Math.sqrt(disc)) / (2 * qa), (-qb + Math.sqrt(disc)) / (2 * qa)] : [];
15973
+ let hits = 0;
15974
+ let hitT = 0;
15975
+ let hitU = 0;
15976
+ for (const t of roots) {
15977
+ if (t < -eps || t > 1 + eps) continue;
15978
+ const sx = fx + dx * t;
15979
+ const sy = fy + dy * t;
15980
+ if (sy === 0 && sx > 0 && Math.abs(py) < eps && ey > 0 && Math.max(ay, ay + ey) > 0 && Math.abs(ex) > eps) {
15981
+ const u2 = (px / sx - ax) / ex;
15982
+ if (u2 >= -eps && u2 <= 1 + eps) {
15983
+ hits = 1;
15984
+ hitT = 0;
15985
+ hitU = Math.min(1, Math.max(0, u2));
15986
+ break;
15987
+ }
15988
+ }
15989
+ if (sx <= 0 || sy <= 0) continue;
15990
+ const u = Math.abs(ex) > Math.abs(ey) ? (px / sx - ax) / ex : (py / sy - ay) / ey;
15991
+ if (u >= -eps && u <= 1 + eps) {
15992
+ hits++;
15993
+ hitT = Math.max(0, t);
15994
+ hitU = Math.min(1, Math.max(0, u));
15995
+ }
15996
+ }
15997
+ if (hits === 1) {
15998
+ distance = hitT;
15999
+ found = i;
16000
+ bestU = hitU;
16001
+ }
16002
+ }
16003
+ s = inFocus ? 0 : Number.isFinite(distance) ? distance : s;
16004
+ }
15945
16005
  }
16006
+ if (found < 0 || !Number.isFinite(s)) return null;
15946
16007
  const pos = 1 - s;
15947
16008
  if (shape.preset && shape.preset.positions.length > 0) {
15948
16009
  const { positions, argb } = shape.preset;
@@ -16286,14 +16347,14 @@ function parseSerializableObject(view, dataOff, dataSize) {
16286
16347
  }
16287
16348
  const p = dataOff + 20;
16288
16349
  const i32 = (k, lo, hi) => clamp(view.getInt32(p + 4 * k, true), lo, hi);
16289
- const f323 = (k, lo, hi) => {
16350
+ const f324 = (k, lo, hi) => {
16290
16351
  const v = view.getFloat32(p + 4 * k, true);
16291
16352
  return Number.isFinite(v) ? clamp(v, lo, hi) : 0;
16292
16353
  };
16293
16354
  const need = (n) => size >= n;
16294
16355
  switch (kind) {
16295
16356
  case "blur":
16296
- return need(8) ? { kind, radius: f323(0, 0, 255), expandEdge: view.getUint32(p + 4, true) !== 0 } : null;
16357
+ return need(8) ? { kind, radius: f324(0, 0, 255), expandEdge: view.getUint32(p + 4, true) !== 0 } : null;
16297
16358
  case "brightnessContrast":
16298
16359
  return need(8) ? { kind, brightness: i32(0, -255, 255), contrast: i32(1, -100, 100) } : null;
16299
16360
  case "colorBalance":
@@ -16349,7 +16410,7 @@ function parseSerializableObject(view, dataOff, dataSize) {
16349
16410
  return { kind, areas };
16350
16411
  }
16351
16412
  case "sharpen":
16352
- return need(8) ? { kind, radius: f323(0, 0, 255), amount: f323(1, 0, 100) } : null;
16413
+ return need(8) ? { kind, radius: f324(0, 0, 255), amount: f324(1, 0, 100) } : null;
16353
16414
  case "tint":
16354
16415
  return need(8) ? { kind, hue: i32(0, -180, 180), amount: i32(1, -100, 100) } : null;
16355
16416
  }
@@ -17140,6 +17201,101 @@ function wrapBmpFile(bmpData, bmpRowStride, width, height, pixelDataSize) {
17140
17201
  return bmpFile;
17141
17202
  }
17142
17203
 
17204
+ // src/emf-plus-bezier.ts
17205
+ var f32 = Math.fround;
17206
+ function gdiplusFix(v) {
17207
+ return Math.floor(f32(f32(v) * 256 + 0.5)) + 15 >> 4;
17208
+ }
17209
+ function flattenBezierGdiplus(p, out, cull, parameters) {
17210
+ let minX = Infinity;
17211
+ let minY = Infinity;
17212
+ let maxX = -Infinity;
17213
+ let maxY = -Infinity;
17214
+ for (let i = 0; i < 8; i += 2) {
17215
+ minX = Math.min(minX, p[i]);
17216
+ maxX = Math.max(maxX, p[i]);
17217
+ minY = Math.min(minY, p[i + 1]);
17218
+ maxY = Math.max(maxY, p[i + 1]);
17219
+ }
17220
+ const left = minX - 16;
17221
+ const top = minY - 16;
17222
+ const X = [p[0] - left, p[2] - left, p[4] - left, p[6] - left];
17223
+ const Y = [p[1] - top, p[3] - top, p[5] - top, p[7] - top];
17224
+ const sar2 = (v, n) => Math.floor(v / 2 ** n);
17225
+ const ex = [X[0] * 1024, (X[3] - X[0]) * 1024, 3 * (X[1] - 2 * X[2] + X[3]) * 2048, 3 * (X[0] - 2 * X[1] + X[2]) * 2048];
17226
+ const ey = [Y[0] * 1024, (Y[3] - Y[0]) * 1024, 3 * (Y[1] - 2 * Y[2] + Y[3]) * 2048, 3 * (Y[0] - 2 * Y[1] + Y[2]) * 2048];
17227
+ let steps = 1;
17228
+ let shift = 0;
17229
+ const maxAbs = (a, b) => Math.abs(a) > Math.abs(b) ? Math.abs(a) : Math.abs(b);
17230
+ {
17231
+ for (let guard = 0; guard < 40; guard++) {
17232
+ const limit = 24576 * 2 ** shift;
17233
+ if (maxAbs(ex[2], ex[3]) <= limit && maxAbs(ey[2], ey[3]) <= limit) {
17234
+ break;
17235
+ }
17236
+ shift += 2;
17237
+ for (const e of [ex, ey]) {
17238
+ e[2] = sar2(e[2] + e[3], 1);
17239
+ e[1] = sar2(e[1] - sar2(e[2], shift), 1);
17240
+ }
17241
+ steps *= 2;
17242
+ }
17243
+ }
17244
+ for (const e of [ex, ey]) {
17245
+ e[0] *= 8;
17246
+ e[1] *= 8;
17247
+ const l = shift - 3;
17248
+ if (l >= 0) {
17249
+ e[2] = sar2(e[2], l);
17250
+ e[3] = sar2(e[3], l);
17251
+ } else {
17252
+ e[2] *= 2 ** -l;
17253
+ e[3] *= 2 ** -l;
17254
+ }
17255
+ }
17256
+ const step = (e) => {
17257
+ e[0] += e[1];
17258
+ const t2 = e[2];
17259
+ e[1] += t2;
17260
+ e[2] = t2 + t2 - e[3];
17261
+ e[3] = t2;
17262
+ };
17263
+ let dt = 1 / steps;
17264
+ let t = dt;
17265
+ step(ex);
17266
+ step(ey);
17267
+ steps--;
17268
+ for (let guard = 0; guard < 1 << 22; guard++) {
17269
+ out.push(sar2(ex[0] + 4096, 13) + left, sar2(ey[0] + 4096, 13) + top);
17270
+ parameters?.push(t);
17271
+ if (steps === 0) {
17272
+ return;
17273
+ }
17274
+ if (Math.max(maxAbs(ex[2], ex[3]), maxAbs(ey[2], ey[3])) > 196608) {
17275
+ for (const e of [ex, ey]) {
17276
+ e[2] = sar2(e[2] + e[3], 3);
17277
+ e[1] = sar2(e[1] - e[2], 1);
17278
+ e[3] = sar2(e[3], 2);
17279
+ }
17280
+ steps *= 2;
17281
+ dt /= 2;
17282
+ }
17283
+ while (steps % 2 === 0 && maxAbs(ex[3], 2 * ex[2] - ex[3]) <= 49152 && maxAbs(ey[3], 2 * ey[2] - ey[3]) <= 49152) {
17284
+ for (const e of [ex, ey]) {
17285
+ e[3] *= 4;
17286
+ e[1] = e[2] + 2 * e[1];
17287
+ e[2] = e[2] * 8 - e[3];
17288
+ }
17289
+ steps /= 2;
17290
+ dt *= 2;
17291
+ }
17292
+ steps--;
17293
+ t += dt;
17294
+ step(ex);
17295
+ step(ey);
17296
+ }
17297
+ }
17298
+
17143
17299
  // src/emf-clip-scanline.ts
17144
17300
  var FLATTEN_TOLERANCE2 = 0.05;
17145
17301
  var MAX_CURVE_SEGMENTS = 4096;
@@ -18117,17 +18273,16 @@ function flattenFirstFigure(points, types, colorAt) {
18117
18273
  break;
18118
18274
  }
18119
18275
  if (kind === 3 && k > 0 && k + 2 < points.length) {
18120
- const p0 = points[k - 1];
18121
- const p1 = points[k];
18122
- const p2 = points[k + 1];
18123
- const p3 = points[k + 2];
18276
+ const curve = points.slice(k - 1, k + 3).flatMap((p) => [gdiplusFix(p.x), gdiplusFix(p.y)]);
18277
+ outPts[outPts.length - 1] = { x: curve[0] / 16, y: curve[1] / 16 };
18124
18278
  const c0 = colorAt(k - 1);
18125
18279
  const c3 = colorAt(k + 2);
18126
18280
  const flat = [];
18127
- flattenCubic(p0, p1, p2, p3, flat);
18128
- for (const v of flat) {
18129
- outPts.push({ x: v.x, y: v.y });
18130
- outArgb.push(lerpArgb2(c0, c3, v.t));
18281
+ const parameters = [];
18282
+ flattenBezierGdiplus(curve, flat, void 0, parameters);
18283
+ for (let i = 0; i < parameters.length; i++) {
18284
+ outPts.push({ x: flat[i * 2] / 16, y: flat[i * 2 + 1] / 16 });
18285
+ outArgb.push(lerpArgb2(c0, c3, parameters[i]));
18131
18286
  }
18132
18287
  k += 2;
18133
18288
  if (types[k] & 128) {
@@ -18335,97 +18490,11 @@ function flatteningContext(target, device) {
18335
18490
  }
18336
18491
 
18337
18492
  // src/emf-plus-nominal-line.ts
18338
- var f32 = Math.fround;
18339
- function gdiplusFix(v) {
18340
- return Math.floor(f32(f32(v) * 256 + 0.5)) + 15 >> 4;
18341
- }
18342
- function flattenBezierGdiplus(p, out, cull) {
18343
- let minX = Infinity;
18344
- let minY = Infinity;
18345
- let maxX = -Infinity;
18346
- let maxY = -Infinity;
18347
- for (let i = 0; i < 8; i += 2) {
18348
- minX = Math.min(minX, p[i]);
18349
- maxX = Math.max(maxX, p[i]);
18350
- minY = Math.min(minY, p[i + 1]);
18351
- maxY = Math.max(maxY, p[i + 1]);
18352
- }
18353
- const left = minX - 16;
18354
- const top = minY - 16;
18355
- const X = [p[0] - left, p[2] - left, p[4] - left, p[6] - left];
18356
- const Y = [p[1] - top, p[3] - top, p[5] - top, p[7] - top];
18357
- const sar2 = (v, n) => Math.floor(v / 2 ** n);
18358
- const ex = [X[0] * 1024, (X[3] - X[0]) * 1024, 3 * (X[1] - 2 * X[2] + X[3]) * 2048, 3 * (X[0] - 2 * X[1] + X[2]) * 2048];
18359
- const ey = [Y[0] * 1024, (Y[3] - Y[0]) * 1024, 3 * (Y[1] - 2 * Y[2] + Y[3]) * 2048, 3 * (Y[0] - 2 * Y[1] + Y[2]) * 2048];
18360
- let steps = 1;
18361
- let shift = 0;
18362
- const maxAbs = (a, b) => Math.abs(a) > Math.abs(b) ? Math.abs(a) : Math.abs(b);
18363
- {
18364
- for (let guard = 0; guard < 40; guard++) {
18365
- const limit = 24576 * 2 ** shift;
18366
- if (maxAbs(ex[2], ex[3]) <= limit && maxAbs(ey[2], ey[3]) <= limit) {
18367
- break;
18368
- }
18369
- shift += 2;
18370
- for (const e of [ex, ey]) {
18371
- e[2] = sar2(e[2] + e[3], 1);
18372
- e[1] = sar2(e[1] - sar2(e[2], shift), 1);
18373
- }
18374
- steps *= 2;
18375
- }
18376
- }
18377
- for (const e of [ex, ey]) {
18378
- e[0] *= 8;
18379
- e[1] *= 8;
18380
- const l = shift - 3;
18381
- if (l >= 0) {
18382
- e[2] = sar2(e[2], l);
18383
- e[3] = sar2(e[3], l);
18384
- } else {
18385
- e[2] *= 2 ** -l;
18386
- e[3] *= 2 ** -l;
18387
- }
18388
- }
18389
- const step = (e) => {
18390
- e[0] += e[1];
18391
- const t = e[2];
18392
- e[1] += t;
18393
- e[2] = t + t - e[3];
18394
- e[3] = t;
18395
- };
18396
- step(ex);
18397
- step(ey);
18398
- steps--;
18399
- for (let guard = 0; guard < 1 << 22; guard++) {
18400
- out.push(sar2(ex[0] + 4096, 13) + left, sar2(ey[0] + 4096, 13) + top);
18401
- if (steps === 0) {
18402
- return;
18403
- }
18404
- if (Math.max(maxAbs(ex[2], ex[3]), maxAbs(ey[2], ey[3])) > 196608) {
18405
- for (const e of [ex, ey]) {
18406
- e[2] = sar2(e[2] + e[3], 3);
18407
- e[1] = sar2(e[1] - e[2], 1);
18408
- e[3] = sar2(e[3], 2);
18409
- }
18410
- steps *= 2;
18411
- }
18412
- while (steps % 2 === 0 && maxAbs(ex[3], 2 * ex[2] - ex[3]) <= 49152 && maxAbs(ey[3], 2 * ey[2] - ey[3]) <= 49152) {
18413
- for (const e of [ex, ey]) {
18414
- e[3] *= 4;
18415
- e[1] = e[2] + 2 * e[1];
18416
- e[2] = e[2] * 8 - e[3];
18417
- }
18418
- steps /= 2;
18419
- }
18420
- steps--;
18421
- step(ex);
18422
- step(ey);
18423
- }
18424
- }
18493
+ var f322 = Math.fround;
18425
18494
  function recordNominalFigures(buildPath, device, cull) {
18426
- const m = device.map((v) => f32(v));
18427
- const fx = (x, y) => gdiplusFix(f32(f32(f32(m[0] * f32(x)) + f32(m[2] * f32(y))) + m[4]));
18428
- const fy = (x, y) => gdiplusFix(f32(f32(f32(m[1] * f32(x)) + f32(m[3] * f32(y))) + m[5]));
18495
+ const m = device.map((v) => f322(v));
18496
+ const fx = (x, y) => gdiplusFix(f322(f322(f322(m[0] * f322(x)) + f322(m[2] * f322(y))) + m[4]));
18497
+ const fy = (x, y) => gdiplusFix(f322(f322(f322(m[1] * f322(x)) + f322(m[3] * f322(y))) + m[5]));
18429
18498
  const figures = [];
18430
18499
  let fig = null;
18431
18500
  let start = null;
@@ -18521,8 +18590,8 @@ function enumeratorBatches(pts) {
18521
18590
  return out;
18522
18591
  }
18523
18592
  function ddaSegment(ax, ay, bx, by, last, plot, clip) {
18524
- const fdx = f32(bx / 16 - ax / 16);
18525
- const fdy = f32(by / 16 - ay / 16);
18593
+ const fdx = f322(bx / 16 - ax / 16);
18594
+ const fdy = f322(by / 16 - ay / 16);
18526
18595
  if (fdx === 0 && fdy === 0) {
18527
18596
  return;
18528
18597
  }
@@ -18550,14 +18619,14 @@ function ddaSegment(ax, ay, bx, by, last, plot, clip) {
18550
18619
  let maj1 = xMajor ? bx : by;
18551
18620
  let min0 = xMajor ? ay : ax;
18552
18621
  let min1 = xMajor ? by : bx;
18553
- const slope = xMajor ? f32(f32(sign * ady) / adx) : f32(f32(sign * adx) / ady);
18622
+ const slope = xMajor ? f322(f322(sign * ady) / adx) : f322(f322(sign * adx) / ady);
18554
18623
  const dMaj = maj1 - maj0;
18555
18624
  const dMin = (min1 - min0) * sign;
18556
18625
  let frac0 = 0;
18557
18626
  let frac1 = 0;
18558
18627
  let e0 = 0;
18559
18628
  if (clip) {
18560
- const inv2 = slope === 0 ? 0 : f32(1 / slope);
18629
+ const inv2 = slope === 0 ? 0 : f322(1 / slope);
18561
18630
  const majLo = (xMajor ? clip.x : clip.y) * 16 - 8;
18562
18631
  const majHi = (xMajor ? clip.x + clip.w : clip.y + clip.h) * 16 - 8;
18563
18632
  const minLo = (xMajor ? clip.y : clip.x) * 16 - 8;
@@ -18567,19 +18636,19 @@ function ddaSegment(ax, ay, bx, by, last, plot, clip) {
18567
18636
  return;
18568
18637
  }
18569
18638
  if (maj0 < majLo) {
18570
- const v = f32(f32((majLo - maj0) * slope) + min0);
18639
+ const v = f322(f322((majLo - maj0) * slope) + min0);
18571
18640
  const fl = Math.floor(v);
18572
18641
  min0 = fl;
18573
18642
  maj0 = majLo;
18574
- frac0 = f32(v - fl);
18643
+ frac0 = f322(v - fl);
18575
18644
  }
18576
18645
  if (maj1 > majHi) {
18577
- const v = f32(f32((majHi - maj1) * slope) + min1);
18646
+ const v = f322(f322((majHi - maj1) * slope) + min1);
18578
18647
  const fl = Math.floor(v);
18579
18648
  last = true;
18580
18649
  min1 = fl;
18581
18650
  maj1 = majHi;
18582
- frac1 = f32(v - fl);
18651
+ frac1 = f322(v - fl);
18583
18652
  }
18584
18653
  }
18585
18654
  const lowIsStart = sign === 1;
@@ -18590,7 +18659,7 @@ function ddaSegment(ax, ay, bx, by, last, plot, clip) {
18590
18659
  return;
18591
18660
  }
18592
18661
  if (lo < minLo) {
18593
- const t = Math.floor(f32(f32(minLo - f32(lo + (lowIsStart ? frac0 : frac1))) * inv2));
18662
+ const t = Math.floor(f322(f322(minLo - f322(lo + (lowIsStart ? frac0 : frac1))) * inv2));
18594
18663
  if (lowIsStart) {
18595
18664
  maj0 += t;
18596
18665
  min0 = minLo;
@@ -18600,7 +18669,7 @@ function ddaSegment(ax, ay, bx, by, last, plot, clip) {
18600
18669
  }
18601
18670
  }
18602
18671
  if (hi > minHi) {
18603
- const t = Math.floor(f32(f32(minHi - f32(hi + (lowIsStart ? frac1 : frac0))) * inv2));
18672
+ const t = Math.floor(f322(f322(minHi - f322(hi + (lowIsStart ? frac1 : frac0))) * inv2));
18604
18673
  if (lowIsStart) {
18605
18674
  maj1 += t;
18606
18675
  min1 = minHi;
@@ -18615,7 +18684,7 @@ function ddaSegment(ax, ay, bx, by, last, plot, clip) {
18615
18684
  min1++;
18616
18685
  }
18617
18686
  if (frac0 !== 0) {
18618
- e0 = Math.floor(f32(f32(2 * dMaj * sign) * frac0));
18687
+ e0 = Math.floor(f322(f322(2 * dMaj * sign) * frac0));
18619
18688
  }
18620
18689
  }
18621
18690
  const diag = xMajor && dMaj === dMin;
@@ -19412,7 +19481,7 @@ function widenFigures(figures, pen) {
19412
19481
  var CAP_DATA_FILL_PATH = 1;
19413
19482
  var CAP_DATA_LINE_PATH = 2;
19414
19483
  var FLT_EPS = 11920928955078125e-23;
19415
- var f322 = Math.fround;
19484
+ var f323 = Math.fround;
19416
19485
  function capPathLength(points, types) {
19417
19486
  const n = points.length;
19418
19487
  if (n < 2) {
@@ -19423,11 +19492,11 @@ function capPathLength(points, types) {
19423
19492
  let min = 0;
19424
19493
  for (let i = 0; i < n; i++) {
19425
19494
  const p = points[i];
19426
- const dx = f322(prev.x - p.x);
19495
+ const dx = f323(prev.x - p.x);
19427
19496
  if (Math.abs(dx) >= FLT_EPS) {
19428
- const t = f322(-p.x / dx);
19429
- if (!(t < -FLT_EPS) && !(f322(t - 1) > FLT_EPS)) {
19430
- const y = f322(f322(f322(prev.y - p.y) * t) + p.y);
19497
+ const t = f323(-p.x / dx);
19498
+ if (!(t < -FLT_EPS) && !(f323(t - 1) > FLT_EPS)) {
19499
+ const y = f323(f323(f323(prev.y - p.y) * t) + p.y);
19431
19500
  min = Math.min(min, y);
19432
19501
  }
19433
19502
  }
@@ -19436,15 +19505,15 @@ function capPathLength(points, types) {
19436
19505
  return min < 0 ? -min : 0;
19437
19506
  }
19438
19507
  function arrowCapPath(width, height, middleInset, filled) {
19439
- const h = f322(height);
19440
- const w2 = f322(f322(width) * 0.5);
19508
+ const h = f323(height);
19509
+ const w2 = f323(f323(width) * 0.5);
19441
19510
  const points = [
19442
19511
  { x: w2, y: -h },
19443
19512
  { x: 0, y: 0 },
19444
19513
  { x: -w2, y: -h }
19445
19514
  ];
19446
19515
  if (filled && middleInset !== 0) {
19447
- points.push({ x: 0, y: f322(f322(middleInset) - h) });
19516
+ points.push({ x: 0, y: f323(f323(middleInset) - h) });
19448
19517
  }
19449
19518
  const types = new Uint8Array(points.length);
19450
19519
  types.fill(1);
@@ -19477,7 +19546,7 @@ function parseCustomLineCap(view, off, size) {
19477
19546
  kind: "plus-customlinecap",
19478
19547
  capType: 1,
19479
19548
  baseCap: 0,
19480
- baseInset: width !== 0 ? f322(height / width) : 0,
19549
+ baseInset: width !== 0 ? f323(height / width) : 0,
19481
19550
  strokeStartCap: u(16),
19482
19551
  strokeEndCap: u(20),
19483
19552
  strokeJoin: u(24),
@@ -19527,19 +19596,19 @@ function parseCustomLineCap(view, off, size) {
19527
19596
  };
19528
19597
  }
19529
19598
  function intersectCircleLine(c, r2, a, b) {
19530
- const vx = f322(b.x - a.x);
19531
- const vy = f322(b.y - a.y);
19532
- const len = Math.sqrt(f322(f322(vx * vx) + f322(vy * vy)));
19599
+ const vx = f323(b.x - a.x);
19600
+ const vy = f323(b.y - a.y);
19601
+ const len = Math.sqrt(f323(f323(vx * vx) + f323(vy * vy)));
19533
19602
  if (len < FLT_EPS) {
19534
19603
  return null;
19535
19604
  }
19536
- const inv2 = f322(1 / len);
19537
- const ux = f322(vx * inv2);
19538
- const uy = f322(vy * inv2);
19539
- const wx = f322(c.x - a.x);
19540
- const wy = f322(c.y - a.y);
19541
- const d2 = f322(f322(wy * wy) + f322(wx * wx));
19542
- const proj = f322(f322(wy * uy) + f322(wx * ux));
19605
+ const inv2 = f323(1 / len);
19606
+ const ux = f323(vx * inv2);
19607
+ const uy = f323(vy * inv2);
19608
+ const wx = f323(c.x - a.x);
19609
+ const wy = f323(c.y - a.y);
19610
+ const d2 = f323(f323(wy * wy) + f323(wx * wx));
19611
+ const proj = f323(f323(wy * uy) + f323(wx * ux));
19543
19612
  if (proj < FLT_EPS && d2 >= r2) {
19544
19613
  return null;
19545
19614
  }
@@ -19564,8 +19633,8 @@ function intersectCircleLine(c, r2, a, b) {
19564
19633
  if (t === null) {
19565
19634
  return null;
19566
19635
  }
19567
- const tf = f322(t);
19568
- return { x: f322(f322(tf * ux) + a.x), y: f322(f322(tf * uy) + a.y) };
19636
+ const tf = f323(t);
19637
+ return { x: f323(f323(tf * ux) + a.x), y: f323(f323(tf * uy) + a.y) };
19569
19638
  }
19570
19639
  function capGradient(pts, dropped, reverse, r2, t) {
19571
19640
  const n = pts.length;
@@ -19578,9 +19647,9 @@ function capGradient(pts, dropped, reverse, r2, t) {
19578
19647
  while (k < n) {
19579
19648
  const q = pts[at(k)];
19580
19649
  outside = at(k);
19581
- const dx = f322(q.x - p0.x);
19582
- const dy = f322(q.y - p0.y);
19583
- if (f322(f322(dx * dx) + f322(dy * dy)) > r2) {
19650
+ const dx = f323(q.x - p0.x);
19651
+ const dy = f323(q.y - p0.y);
19652
+ if (f323(f323(dx * dx) + f323(dy * dy)) > r2) {
19584
19653
  found = true;
19585
19654
  break;
19586
19655
  }
@@ -19594,31 +19663,31 @@ function capGradient(pts, dropped, reverse, r2, t) {
19594
19663
  }
19595
19664
  const inner = pts[cur];
19596
19665
  const hit = intersectCircleLine(p0, r2, pts[outside], inner) ?? { x: inner.x, y: inner.y };
19597
- let gx = f322(hit.x - p0.x);
19598
- let gy = f322(hit.y - p0.y);
19666
+ let gx = f323(hit.x - p0.x);
19667
+ let gy = f323(hit.y - p0.y);
19599
19668
  const len = Math.sqrt(gx * gx + gy * gy);
19600
19669
  if (len > FLT_EPS) {
19601
- gx = f322(gx / len);
19602
- gy = f322(gy / len);
19670
+ gx = f323(gx / len);
19671
+ gy = f323(gy / len);
19603
19672
  } else {
19604
19673
  gx = 0;
19605
19674
  gy = 0;
19606
19675
  }
19607
- const k1 = f322(1 - t);
19676
+ const k1 = f323(1 - t);
19608
19677
  pts[cur] = {
19609
- x: f322(f322(f322(p0.x - hit.x) * k1) + hit.x),
19610
- y: f322(f322(f322(p0.y - hit.y) * k1) + hit.y)
19678
+ x: f323(f323(f323(p0.x - hit.x) * k1) + hit.x),
19679
+ y: f323(f323(f323(p0.y - hit.y) * k1) + hit.y)
19611
19680
  };
19612
19681
  return { x: gx, y: gy };
19613
19682
  }
19614
19683
  function placeCapPath(path, origin, d, s) {
19615
- const ax = f322(d.y * s);
19616
- const ay = f322(-d.x * s);
19617
- const bx = f322(d.x * s);
19618
- const by = f322(d.y * s);
19684
+ const ax = f323(d.y * s);
19685
+ const ay = f323(-d.x * s);
19686
+ const bx = f323(d.x * s);
19687
+ const by = f323(d.y * s);
19619
19688
  const points = path.points.map((p) => ({
19620
- x: f322(f322(f322(ax * p.x) + f322(bx * p.y)) + origin.x),
19621
- y: f322(f322(f322(ay * p.x) + f322(by * p.y)) + origin.y)
19689
+ x: f323(f323(f323(ax * p.x) + f323(bx * p.y)) + origin.x),
19690
+ y: f323(f323(f323(ay * p.x) + f323(by * p.y)) + origin.y)
19622
19691
  }));
19623
19692
  return { ...path, points };
19624
19693
  }
@@ -19678,7 +19747,7 @@ function customCapGeometry(figures, width, start, end, options2 = {}) {
19678
19747
  if (!path || path.points.length === 0) {
19679
19748
  return;
19680
19749
  }
19681
- const ws = f322(cap.widthScale * width);
19750
+ const ws = f323(cap.widthScale * width);
19682
19751
  let length;
19683
19752
  let scale;
19684
19753
  if (fill) {
@@ -19688,9 +19757,9 @@ function customCapGeometry(figures, width, start, end, options2 = {}) {
19688
19757
  length = Math.abs(cap.strokeLength) < FLT_EPS ? 1 : cap.strokeLength;
19689
19758
  scale = ws;
19690
19759
  }
19691
- const t = fill && Math.abs(length) < FLT_EPS ? 0 : f322(cap.baseInset / length);
19692
- const r = f322(length * scale);
19693
- const g = capGradient(pts, dropped, atEnd, f322(r * r), t);
19760
+ const t = fill && Math.abs(length) < FLT_EPS ? 0 : f323(cap.baseInset / length);
19761
+ const r = f323(length * scale);
19762
+ const g = capGradient(pts, dropped, atEnd, f323(r * r), t);
19694
19763
  const dir = { x: -g.x, y: -g.y };
19695
19764
  const origin = atEnd ? last : first;
19696
19765
  if (fill) {
@@ -19778,7 +19847,7 @@ function parseEmfPlusPenObject(view, dataOff, recDataSize, textureCache, cacheKe
19778
19847
  o += 4;
19779
19848
  return v;
19780
19849
  };
19781
- const f323 = () => {
19850
+ const f324 = () => {
19782
19851
  if (o + 4 > end) {
19783
19852
  return void 0;
19784
19853
  }
@@ -19803,7 +19872,7 @@ function parseEmfPlusPenObject(view, dataOff, recDataSize, textureCache, cacheKe
19803
19872
  pen.lineJoin = u32();
19804
19873
  }
19805
19874
  if (penFlags & PEN_MITER_LIMIT) {
19806
- pen.miterLimit = f323();
19875
+ pen.miterLimit = f324();
19807
19876
  }
19808
19877
  if (penFlags & PEN_LINE_STYLE) {
19809
19878
  pen.dashStyle = u32() ?? 0;
@@ -19812,7 +19881,7 @@ function parseEmfPlusPenObject(view, dataOff, recDataSize, textureCache, cacheKe
19812
19881
  pen.dashCap = u32();
19813
19882
  }
19814
19883
  if (penFlags & PEN_DASHED_LINE_OFFSET) {
19815
- pen.dashOffset = f323();
19884
+ pen.dashOffset = f324();
19816
19885
  }
19817
19886
  if (penFlags & PEN_DASHED_LINE) {
19818
19887
  const n = u32() ?? 0;
@@ -27270,7 +27339,8 @@ var RasterRealizedFont = class {
27270
27339
  }
27271
27340
  };
27272
27341
  var RealizedFont = class {
27273
- constructor(ttf, ppem, ppemX, mode, syntheticBold, syntheticItalic, cellHeight = 0, stretchWidth = 0, gridFit = true) {
27342
+ constructor(ttf, ppem, ppemX, mode, syntheticBold, syntheticItalic, cellHeight = 0, stretchWidth = 0, gridFit = true, gdiPlus = false) {
27343
+ this.gdiPlus = gdiPlus;
27274
27344
  this.rotatedSize = null;
27275
27345
  this.rotOutlines = /* @__PURE__ */ new Map();
27276
27346
  this.outlines = /* @__PURE__ */ new Map();
@@ -27282,6 +27352,7 @@ var RealizedFont = class {
27282
27352
  this.ctOutlines = /* @__PURE__ */ new Map();
27283
27353
  this.ttf = ttf;
27284
27354
  this.gridFit = gridFit;
27355
+ this.fractionalOrigins = gdiPlus ? mode === "gray" ? "xy" : mode === "cleartype" ? "x" : void 0 : void 0;
27285
27356
  this.stretchWidth = ppemX !== ppem ? stretchWidth : 0;
27286
27357
  this.ppem = ppem;
27287
27358
  this.ppemX = ppemX;
@@ -27308,7 +27379,13 @@ var RealizedFont = class {
27308
27379
  this.underlineThickness = scale(ttf.underlineThickness);
27309
27380
  this.strikeoutPosition = scale(ttf.strikeoutPosition);
27310
27381
  this.strikeoutThickness = scale(ttf.strikeoutSize);
27311
- this.hinted = new HintedSize(ttf, ppemX, ppem, { version: 35, grayscale: mode !== "mono" }, gridFit);
27382
+ this.hinted = new HintedSize(
27383
+ ttf,
27384
+ ppemX,
27385
+ ppem,
27386
+ gdiPlus && mode === "gray" ? { version: 40, grayscale: true, clearType: true, compatibleWidths: false } : { version: 35, grayscale: mode !== "mono" },
27387
+ gridFit || gdiPlus && mode === "gray"
27388
+ );
27312
27389
  this.hdmx = ppemX === ppem ? ttf.hdmx.get(ppem) : void 0;
27313
27390
  }
27314
27391
  /** Glyph index for a character code (UTF-16 code unit or code point). */
@@ -27352,7 +27429,7 @@ var RealizedFont = class {
27352
27429
  return o;
27353
27430
  }
27354
27431
  const gi = index < this.ttf.numGlyphs ? index : NOTDEF;
27355
- this.ctSize ?? (this.ctSize = new HintedSize(this.ttf, this.ppemX, this.ppem, { version: 40, grayscale: false, clearType: true }));
27432
+ this.ctSize ?? (this.ctSize = new HintedSize(this.ttf, this.ppemX, this.ppem, { version: 40, grayscale: false, clearType: true, compatibleWidths: !this.gdiPlus }));
27356
27433
  const u = this.ctSize.hintGlyph(gi);
27357
27434
  const natural = this.ttf.hMetrics(gi).advance * this.ppemX / this.ttf.unitsPerEm;
27358
27435
  const k = !this.naturalWidths && natural > 0 ? this.advance(index) / natural : 1;
@@ -27402,8 +27479,8 @@ var RealizedFont = class {
27402
27479
  * `m` = [a, b, c, d] (device, y down: x' = a*x + c*y, y' = b*x + d*y,
27403
27480
  * applied to the hinted outline about the pen position).
27404
27481
  */
27405
- glyph(index, m, subX = 0) {
27406
- const key = (m ? `${index}|${m.map((v) => v.toFixed(6)).join(",")}` : String(index)) + (subX ? `@${subX}` : "");
27482
+ glyph(index, m, subX = 0, subY = 0) {
27483
+ const key = (m ? `${index}|${m.map((v) => v.toFixed(6)).join(",")}` : String(index)) + (subX || subY ? `@${subX},${subY}` : "");
27407
27484
  let g = this.glyphs.get(key);
27408
27485
  if (g) {
27409
27486
  return g;
@@ -27414,32 +27491,33 @@ var RealizedFont = class {
27414
27491
  const p = this.ppem;
27415
27492
  m = [Math.round(m[0] * p) / p, Math.round(m[1] * p) / p, Math.round(m[2] * p) / p, Math.round(m[3] * p) / p];
27416
27493
  }
27417
- let o = src;
27418
- if (this.syntheticItalic || m || subX) {
27419
- const n = src.xs.length;
27494
+ let o = this.mode === "cleartype" && !m && !this.syntheticItalic ? this.ctOutline(index) : src;
27495
+ if (this.syntheticItalic || m || subX || subY) {
27496
+ const base = o;
27497
+ const n = base.xs.length;
27420
27498
  const xs = new Float64Array(n);
27421
27499
  const ys = new Float64Array(n);
27422
27500
  for (let i = 0; i < n; i++) {
27423
- let x = src.xs[i];
27424
- const y = src.ys[i];
27501
+ let x = base.xs[i];
27502
+ const y = base.ys[i];
27425
27503
  if (this.syntheticItalic) {
27426
27504
  x += y * ITALIC_SHEAR;
27427
27505
  }
27428
27506
  if (m) {
27429
- xs[i] = Math.round(m[0] * x - m[2] * y);
27430
- ys[i] = Math.round(-(m[1] * x - m[3] * y));
27507
+ xs[i] = Math.round(m[0] * x - m[2] * y + subX);
27508
+ ys[i] = Math.round(-(m[1] * x - m[3] * y) - subY);
27431
27509
  } else {
27432
27510
  xs[i] = Math.round(x + subX);
27433
- ys[i] = y;
27511
+ ys[i] = y - subY;
27434
27512
  }
27435
27513
  }
27436
- o = { xs, ys, onCurve: src.onCurve, endPts: src.endPts };
27514
+ o = { xs, ys, onCurve: base.onCurve, endPts: base.endPts };
27437
27515
  }
27438
27516
  let bitmap;
27439
27517
  if (this.mode === "mono") {
27440
27518
  bitmap = rasterizeMono(o, dropoutMode(src.scanControl, src.scanType));
27441
27519
  } else if (this.mode === "cleartype") {
27442
- bitmap = rasterizeClearType(!m && !this.syntheticItalic ? this.ctOutline(index) : o);
27520
+ bitmap = rasterizeClearType(o, this.gdiPlus);
27443
27521
  } else {
27444
27522
  bitmap = rasterizeGray(o);
27445
27523
  }
@@ -27659,7 +27737,8 @@ var GdiFontCollection = class _GdiFontCollection {
27659
27737
  synthItalic,
27660
27738
  cellHeight,
27661
27739
  spec.width,
27662
- !spec.unhinted
27740
+ !spec.unhinted,
27741
+ spec.gdiPlus
27663
27742
  );
27664
27743
  tt2.naturalWidths = spec.quality === CLEARTYPE_NATURAL_QUALITY;
27665
27744
  return tt2;
@@ -27738,7 +27817,7 @@ function resolvePpem(font, height) {
27738
27817
  return ppem;
27739
27818
  }
27740
27819
  var CLEARTYPE_OVERSAMPLE = 6;
27741
- function rasterizeClearType(o) {
27820
+ function rasterizeClearType(o, truncate = false) {
27742
27821
  const S = CLEARTYPE_OVERSAMPLE / 3;
27743
27822
  const r = rasterizeSamples(o, CLEARTYPE_OVERSAMPLE, 1, 1);
27744
27823
  if (!r) {
@@ -27760,7 +27839,7 @@ function rasterizeClearType(o) {
27760
27839
  }
27761
27840
  for (let j = 0; j < n; j++) {
27762
27841
  const acc = (j > 0 ? sub[j - 1] : 0) + sub[j] + (j + 1 < n ? sub[j + 1] : 0);
27763
- data[y * n + j] = Math.round(255 * acc / (3 * S));
27842
+ data[y * n + j] = (truncate ? Math.floor : Math.round)(255 * acc / (3 * S));
27764
27843
  }
27765
27844
  }
27766
27845
  return { width, height, left: box.xMin, top: box.yMax, data, channels: 3 };
@@ -29050,18 +29129,19 @@ function floorDivision(a, b) {
29050
29129
  return Number(q);
29051
29130
  }
29052
29131
  var penCache = /* @__PURE__ */ new Map();
29053
- function penPolygon(width) {
29054
- const cached = penCache.get(width);
29132
+ function penPolygon(width, height = width) {
29133
+ const key = `${width},${height}`;
29134
+ const cached = penCache.get(key);
29055
29135
  if (cached) {
29056
29136
  return cached;
29057
29137
  }
29058
29138
  let pen;
29059
- if (width < HOBBY_LIMIT) {
29139
+ if (width === height && width < HOBBY_LIMIT) {
29060
29140
  const n = Math.min(6, Math.max(1, Math.floor(width / 16 + 0.5)));
29061
29141
  pen = HOBBY[n - 1];
29062
29142
  } else {
29063
29143
  const rx = Math.ceil(width / 2);
29064
- const ry = rx;
29144
+ const ry = Math.ceil(height / 2);
29065
29145
  const f = flattenBezierPath(ellipseBeziers(-rx, -ry, rx, ry));
29066
29146
  const half = [];
29067
29147
  for (let i = 0; i + 1 < f.length; i += 2) {
@@ -29073,13 +29153,15 @@ function penPolygon(width) {
29073
29153
  half.pop();
29074
29154
  pen = [...half, ...half.map((p) => [0 - p[0] || 0, 0 - p[1] || 0])];
29075
29155
  }
29076
- penCache.set(width, pen);
29156
+ penCache.set(key, pen);
29077
29157
  return pen;
29078
29158
  }
29079
- function drawVertices(pen, dx, dy) {
29159
+ function drawVertices(pen, dx, dy, width = 1, height = width) {
29080
29160
  const n = pen.length;
29081
29161
  const axisVertex = pen.some((q) => q[1] === 0);
29082
- const steep = Math.abs(dy) > 2 * Math.abs(dx) || Math.abs(dy) === 2 * Math.abs(dx) && axisVertex;
29162
+ const yMagnitude = Math.abs(dy) * (width === height ? 1 : width);
29163
+ const xMagnitude = Math.abs(dx) * (width === height ? 2 : height);
29164
+ const steep = yMagnitude > xMagnitude || yMagnitude === xMagnitude && axisVertex;
29083
29165
  const s = (steep ? dy < 0 : dx < 0 || dx === 0 && dy < 0) ? -1 : 1;
29084
29166
  let best = 0;
29085
29167
  let bestH = -Infinity;
@@ -29098,7 +29180,7 @@ function drawVertices(pen, dx, dy) {
29098
29180
  function halfPixel(v) {
29099
29181
  return Math.sign(v) * 8 * Math.floor((Math.abs(v) + 4) / 8);
29100
29182
  }
29101
- function perpendicularVectors(width, dx0, dy0) {
29183
+ function perpendicularVectors(width, dx0, dy0, height = width) {
29102
29184
  let dx = dx0;
29103
29185
  let dy = dy0;
29104
29186
  const flip = dx < 0 || dx === 0 && dy < 0;
@@ -29106,7 +29188,7 @@ function perpendicularVectors(width, dx0, dy0) {
29106
29188
  dx = -dx;
29107
29189
  dy = -dy;
29108
29190
  }
29109
- const pen = penPolygon(width);
29191
+ const pen = penPolygon(width, height);
29110
29192
  const n = pen.length;
29111
29193
  const nx = -dy;
29112
29194
  const ny = dx;
@@ -29145,8 +29227,8 @@ function perpendicularVectors(width, dx0, dy0) {
29145
29227
  const vx = rounded[0], vy = rounded[1];
29146
29228
  return { v: flip ? [-vx, -vy] : [vx, vy], ray: flip ? [-x, -y] : [x, y] };
29147
29229
  }
29148
- function squareExtension(width, dx, dy, scale = 1) {
29149
- const len = Math.hypot(dx, dy);
29230
+ function squareExtension(width, dx, dy, scale = 1, height = width) {
29231
+ const len = width === height ? Math.hypot(dx, dy) : Math.hypot(dx, dy * width / height);
29150
29232
  const r = width / 2 * scale;
29151
29233
  return [Math.floor(dx / len * r + 0.5), Math.floor(dy / len * r + 0.5)];
29152
29234
  }
@@ -29168,7 +29250,7 @@ var Outliner = class {
29168
29250
  this.opts = opts;
29169
29251
  this.out = out;
29170
29252
  this.pts = [];
29171
- this.pen = penPolygon(opts.width);
29253
+ this.pen = penPolygon(opts.width, opts.height);
29172
29254
  this.n = this.pen.length;
29173
29255
  this.rr = opts.cap === "round" && opts.join === "round";
29174
29256
  this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
@@ -29183,10 +29265,10 @@ var Outliner = class {
29183
29265
  const dx = dir ? dir[0] : b[0] - a[0];
29184
29266
  const dy = dir ? dir[1] : b[1] - a[1];
29185
29267
  const d = drawDir ?? [dx, dy];
29186
- const [L, R] = drawVertices(this.pen, d[0], d[1]);
29268
+ const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height);
29187
29269
  const perpendicular = curve && drawDir ? drawDir : [dx, dy];
29188
- const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1]);
29189
- return { dx, dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.width, perpendicular[0], perpendicular[1]), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
29270
+ const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height);
29271
+ 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 };
29190
29272
  }
29191
29273
  push(p, v) {
29192
29274
  this.pts.push([p[0] + v[0], p[1] + v[1]]);
@@ -29299,7 +29381,7 @@ var Outliner = class {
29299
29381
  const sv = this.capSide(s, from);
29300
29382
  const ev = this.capSide(s, to);
29301
29383
  if (cap === "square") {
29302
- const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale);
29384
+ const e0 = scale === 1 ? s.e : squareExtension(this.opts.width, s.pe[0], s.pe[1], scale, this.opts.height);
29303
29385
  const e = start ? [-e0[0], -e0[1]] : e0;
29304
29386
  this.push(p, [sv[0] + e[0], sv[1] + e[1]]);
29305
29387
  this.push(p, [ev[0] + e[0], ev[1] + e[1]]);
@@ -29347,7 +29429,7 @@ var Outliner = class {
29347
29429
  }
29348
29430
  }
29349
29431
  } else if (join === "miter") {
29350
- const m = miterPoint(sa, [a.dx, a.dy], sb, [b.dx, b.dy], width, miterLimit, side);
29432
+ const m = miterPoint(sa, [a.dx, a.dy], sb, [b.dx, b.dy], width, miterLimit, side, this.opts.height);
29351
29433
  if (m) {
29352
29434
  this.push(p, m);
29353
29435
  }
@@ -29603,7 +29685,7 @@ function widenPath(path, opts) {
29603
29685
  }
29604
29686
  return out;
29605
29687
  }
29606
- function miterPoint(sa, da, sb, db, width, limit, side) {
29688
+ function miterPoint(sa, da, sb, db, width, limit, side, height = width) {
29607
29689
  const den = da[0] * db[1] - da[1] * db[0];
29608
29690
  if (den === 0) {
29609
29691
  return null;
@@ -29616,7 +29698,8 @@ function miterPoint(sa, da, sb, db, width, limit, side) {
29616
29698
  const x = Math.sign(mx) * Math.floor(Math.abs(mx) + 0.5);
29617
29699
  const y = Math.sign(my) * Math.floor(Math.abs(my) + 0.5);
29618
29700
  const pixel = side === "L" ? Math.ceil : Math.floor;
29619
- if (Math.hypot(pixel(x / 16), pixel(y / 16)) > limit * width / 32) {
29701
+ const yDistance = height === width ? pixel(y / 16) : pixel(y / 16) * width / height;
29702
+ if (Math.hypot(pixel(x / 16), yDistance) > limit * width / 32) {
29620
29703
  return null;
29621
29704
  }
29622
29705
  return [x, y];
@@ -29798,8 +29881,10 @@ function penWidenOptions(rCtx, opts = {}) {
29798
29881
  const capBits = flags & 3840;
29799
29882
  const joinBits = flags & 61440;
29800
29883
  const dashes = state.penExtended ? geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
29884
+ 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;
29801
29885
  return {
29802
- width: Math.round(widthPx * 16),
29886
+ width: Math.round((ellipse ? state.penWidth * Math.abs(matrix[0]) : widthPx) * 16),
29887
+ ...ellipse ? { height: Math.round(state.penWidth * Math.abs(matrix[3]) * 16) } : {},
29803
29888
  cap: opts.roundPen || !state.penExtended || capBits === 0 ? "round" : capBits === 256 ? "square" : "flat",
29804
29889
  join: opts.roundPen ? "round" : opts.rectangle && !state.penExtended ? "miter" : !state.penExtended || joinBits === 0 ? "round" : joinBits === 4096 ? "bevel" : "miter",
29805
29890
  miterLimit: state.miterLimit ?? 10,
@@ -30314,7 +30399,7 @@ function pathGradientSampler(shape, wrap, device) {
30314
30399
  const bias = wrap === "clamp" ? CLAMP_EDGE_BIAS : 0;
30315
30400
  return (x0, y0, w, h, out) => {
30316
30401
  for (let j = 0; j < h; j++) {
30317
- const dy = y0 + j + bias;
30402
+ const dy = y0 + j;
30318
30403
  for (let i = 0; i < w; i++) {
30319
30404
  const dx = x0 + i + bias;
30320
30405
  let bx = inv2[0] * dx + inv2[2] * dy + inv2[4];
@@ -30323,6 +30408,7 @@ function pathGradientSampler(shape, wrap, device) {
30323
30408
  bx = foldIntoTile(bx, box.x, box.w, mirrorX, lagX);
30324
30409
  by = foldIntoTile(by, box.y, box.h, mirrorY, lagY);
30325
30410
  }
30411
+ if (wrap === "clamp" && by >= box.y + box.h) continue;
30326
30412
  const c = pathGradientColorAt(shape, bx, by);
30327
30413
  if (c === null) {
30328
30414
  continue;
@@ -33700,12 +33786,14 @@ function layoutGdiRun(font, run) {
33700
33786
  let down = baseDown;
33701
33787
  for (let i = 0; i < n; i++) {
33702
33788
  const origin = at(along, down);
33703
- const ox = font.gridFit ? Math.round(origin.x) : Math.floor(origin.x);
33704
- const subX = font.gridFit ? 0 : Math.round((origin.x - ox) * 64);
33705
- const oy = Math.round(origin.y);
33706
- origins.push({ x: ox + subX / 64, y: oy, along, down });
33789
+ const fractionalX = !font.gridFit || font.fractionalOrigins;
33790
+ const ox = fractionalX ? Math.floor(origin.x) : Math.round(origin.x);
33791
+ const subX = !fractionalX ? 0 : font.fractionalOrigins === "xy" ? Math.round((origin.x - ox) * 4) * 16 : Math.round((origin.x - ox) * 64);
33792
+ const oy = font.fractionalOrigins === "xy" ? Math.floor(origin.y) : Math.round(origin.y);
33793
+ const subY = font.fractionalOrigins === "xy" ? Math.round((origin.y - oy) * 4) * 16 : 0;
33794
+ origins.push({ x: ox + subX / 64, y: oy + subY / 64, along, down });
33707
33795
  if (!suppressC1Glyph(run, i)) {
33708
- const g = font.glyph(glyphs[i], gm, subX);
33796
+ const g = font.glyph(glyphs[i], gm, subX, subY);
33709
33797
  if (g.bitmap) {
33710
33798
  placed.push({ x: ox + g.bitmap.left, y: oy - g.bitmap.top, bitmap: g.bitmap });
33711
33799
  }
@@ -34067,9 +34155,20 @@ function compositeClearType(ctx, placed, color, x0, y0, w, h) {
34067
34155
  canvasDrawImage(ctx, layer.canvas, x0, y0, w, h);
34068
34156
  ctx.restore();
34069
34157
  }
34070
- function gdiTextCoverage(font, run) {
34071
- const { placed } = layoutGdiRun(font, run);
34072
- if (placed.length === 0) {
34158
+ function gdiTextCoverage(font, run, options2 = {}) {
34159
+ const { placed, total, startAlong, baseDown } = layoutGdiRun(font, run);
34160
+ const bars = [];
34161
+ if (options2.decorations && !run.matrix && total !== 0) {
34162
+ const x = Math.round(run.x + startAlong);
34163
+ const end = x + Math.round(total);
34164
+ const add = (position, thickness) => {
34165
+ const top = Math.round(run.y + baseDown) - position;
34166
+ bars.push({ left: Math.min(x, end), right: Math.max(x, end), top, bottom: top + Math.max(1, thickness) });
34167
+ };
34168
+ if (run.underline) add(font.underlinePosition, font.underlineThickness);
34169
+ if (run.strikeOut) add(font.strikeoutPosition, font.strikeoutThickness);
34170
+ }
34171
+ if (placed.length === 0 && bars.length === 0) {
34073
34172
  return null;
34074
34173
  }
34075
34174
  let x0 = Infinity;
@@ -34082,6 +34181,12 @@ function gdiTextCoverage(font, run) {
34082
34181
  x1 = Math.max(x1, p.x + p.bitmap.width);
34083
34182
  y1 = Math.max(y1, p.y + p.bitmap.height);
34084
34183
  }
34184
+ for (const bar of bars) {
34185
+ x0 = Math.min(x0, bar.left);
34186
+ y0 = Math.min(y0, bar.top);
34187
+ x1 = Math.max(x1, bar.right);
34188
+ y1 = Math.max(y1, bar.bottom);
34189
+ }
34085
34190
  const w = x1 - x0;
34086
34191
  const h = y1 - y0;
34087
34192
  if (w <= 0 || h <= 0 || w * h > 64 * 1024 * 1024) {
@@ -34089,7 +34194,7 @@ function gdiTextCoverage(font, run) {
34089
34194
  }
34090
34195
  const channels = placed.some((p) => p.bitmap.channels === 3) ? 3 : 1;
34091
34196
  const data = new Uint8ClampedArray(w * h * channels);
34092
- const full = font.mode === "mono" ? 1 : 16;
34197
+ const full = font.mode === "mono" ? 1 : options2.grayLevels ?? 16;
34093
34198
  for (const p of placed) {
34094
34199
  const b = p.bitmap;
34095
34200
  const bc = b.channels === 3 ? 3 : 1;
@@ -34103,6 +34208,11 @@ function gdiTextCoverage(font, run) {
34103
34208
  }
34104
34209
  }
34105
34210
  }
34211
+ for (const bar of bars) {
34212
+ for (let y = bar.top; y < bar.bottom; y++) {
34213
+ data.fill(255, ((y - y0) * w + bar.left - x0) * channels, ((y - y0) * w + bar.right - x0) * channels);
34214
+ }
34215
+ }
34106
34216
  return { x: x0, y: y0, width: w, height: h, channels, data };
34107
34217
  }
34108
34218
 
@@ -34360,7 +34470,7 @@ function handlePolyText(rCtx, offset, dataOff, recSize, wide) {
34360
34470
  dx = Array.from({ length: dxCount }, (_, j) => view.getInt32(offset + offDx + j * 4, true));
34361
34471
  if (!wide) dx = collapseAnsiDx(dx, ansi.byteLengths, pdy);
34362
34472
  }
34363
- drawTextCall(rCtx, x, y, codes, options2, rect, dx);
34473
+ drawTextCall(rCtx, x, y, codes, options2 | ETO_IGNORELANGUAGE, rect, dx);
34364
34474
  }
34365
34475
  return true;
34366
34476
  }
@@ -35711,99 +35821,294 @@ function handleEmfObjectRecord(rCtx, recType, dataOff, recSize) {
35711
35821
  }
35712
35822
  }
35713
35823
 
35714
- // src/emf-gdi-transform-handlers.ts
35715
- function extentsSettable(rCtx) {
35716
- return rCtx.mapMode === 7 || rCtx.mapMode === 8;
35824
+ // src/wmf-mapping.ts
35825
+ var MM_TEXT = 1;
35826
+ var MM_LOMETRIC = 2;
35827
+ var MM_HIMETRIC = 3;
35828
+ var MM_LOENGLISH = 4;
35829
+ var MM_HIENGLISH = 5;
35830
+ var MM_TWIPS = 6;
35831
+ var MM_ISOTROPIC = 7;
35832
+ var MM_ANISOTROPIC = 8;
35833
+ var DEVICE_DPI = 96;
35834
+ function cloneMapping(m) {
35835
+ return {
35836
+ ...m.dpi ? { dpi: { ...m.dpi } } : {},
35837
+ mode: m.mode,
35838
+ winOrg: { ...m.winOrg },
35839
+ winExt: { ...m.winExt },
35840
+ vpOrg: { ...m.vpOrg },
35841
+ vpExt: { ...m.vpExt }
35842
+ };
35717
35843
  }
35718
- function handleCoordinateRecord(rCtx, recType, dataOff, recSize) {
35719
- const { view } = rCtx;
35720
- switch (recType) {
35721
- case EMR_SETWINDOWEXTEX: {
35722
- if (recSize >= 16 && extentsSettable(rCtx)) {
35723
- const cx = view.getInt32(dataOff, true);
35724
- const cy = view.getInt32(dataOff + 4, true);
35725
- if (cx !== 0 && cy !== 0) {
35726
- rCtx.windowExt = { cx, cy };
35727
- activateGdiMappingMode(rCtx);
35728
- }
35729
- }
35730
- return true;
35731
- }
35732
- case EMR_SETWINDOWORGEX: {
35733
- if (recSize >= 16) {
35734
- rCtx.windowOrg.x = view.getInt32(dataOff, true);
35735
- rCtx.windowOrg.y = view.getInt32(dataOff + 4, true);
35736
- activateGdiMappingMode(rCtx);
35737
- }
35738
- return true;
35739
- }
35740
- case EMR_SETVIEWPORTEXTEX: {
35741
- if (recSize >= 16 && extentsSettable(rCtx)) {
35742
- const cx = view.getInt32(dataOff, true);
35743
- const cy = view.getInt32(dataOff + 4, true);
35744
- if (cx !== 0 && cy !== 0) {
35745
- rCtx.viewportExt = { cx, cy };
35746
- activateGdiMappingMode(rCtx);
35747
- }
35748
- }
35749
- return true;
35750
- }
35751
- case EMR_SETVIEWPORTORGEX: {
35752
- if (recSize >= 16) {
35753
- rCtx.viewportOrg.x = view.getInt32(dataOff, true);
35754
- rCtx.viewportOrg.y = view.getInt32(dataOff + 4, true);
35755
- activateGdiMappingMode(rCtx);
35756
- }
35757
- return true;
35758
- }
35759
- case EMR_SETMAPMODE: {
35760
- if (recSize >= 12) {
35761
- const mode = view.getUint32(dataOff, true);
35762
- if (mode >= 1 && mode <= 8) {
35763
- rCtx.mapMode = mode;
35764
- if (mode === 1) {
35765
- rCtx.windowExt = { cx: 1, cy: 1 };
35766
- rCtx.viewportExt = { cx: 1, cy: 1 };
35767
- }
35768
- if (mode === 1 || mode === 8 || mode === 7) {
35769
- activateGdiMappingMode(rCtx);
35770
- }
35771
- }
35772
- }
35773
- return true;
35774
- }
35775
- case EMR_SCALEVIEWPORTEXTEX: {
35776
- if (recSize >= 24 && extentsSettable(rCtx)) {
35777
- const xNum = view.getInt32(dataOff, true);
35778
- const xDenom = view.getInt32(dataOff + 4, true);
35779
- const yNum = view.getInt32(dataOff + 8, true);
35780
- const yDenom = view.getInt32(dataOff + 12, true);
35781
- if (xDenom !== 0) {
35782
- rCtx.viewportExt.cx = Math.round(rCtx.viewportExt.cx * xNum / xDenom);
35783
- }
35784
- if (yDenom !== 0) {
35785
- rCtx.viewportExt.cy = Math.round(rCtx.viewportExt.cy * yNum / yDenom);
35786
- }
35787
- activateGdiMappingMode(rCtx);
35788
- }
35789
- return true;
35790
- }
35791
- case EMR_SCALEWINDOWEXTEX: {
35792
- if (recSize >= 24 && extentsSettable(rCtx)) {
35793
- const xNum = view.getInt32(dataOff, true);
35794
- const xDenom = view.getInt32(dataOff + 4, true);
35795
- const yNum = view.getInt32(dataOff + 8, true);
35796
- const yDenom = view.getInt32(dataOff + 12, true);
35797
- if (xDenom !== 0) {
35798
- rCtx.windowExt.cx = Math.round(rCtx.windowExt.cx * xNum / xDenom);
35799
- }
35800
- if (yDenom !== 0) {
35801
- rCtx.windowExt.cy = Math.round(rCtx.windowExt.cy * yNum / yDenom);
35802
- }
35844
+ var METRIC_UNITS_PER_INCH = {
35845
+ [MM_LOMETRIC]: 254,
35846
+ [MM_HIMETRIC]: 2540,
35847
+ [MM_LOENGLISH]: 100,
35848
+ [MM_HIENGLISH]: 1e3,
35849
+ [MM_TWIPS]: 1440
35850
+ };
35851
+ function fixIsotropic(m) {
35852
+ if (m.mode !== MM_ISOTROPIC || !m.winExt.cx || !m.winExt.cy) {
35853
+ return;
35854
+ }
35855
+ const xdim = Math.abs(m.vpExt.cx / m.winExt.cx) / (m.dpi?.x ?? DEVICE_DPI);
35856
+ const ydim = Math.abs(m.vpExt.cy / m.winExt.cy) / (m.dpi?.y ?? DEVICE_DPI);
35857
+ if (xdim > ydim) {
35858
+ const min = m.vpExt.cx >= 0 ? 1 : -1;
35859
+ m.vpExt.cx = Math.floor(m.vpExt.cx * ydim / xdim + 0.5) || min;
35860
+ } else if (ydim > xdim) {
35861
+ const min = m.vpExt.cy >= 0 ? 1 : -1;
35862
+ m.vpExt.cy = Math.floor(m.vpExt.cy * xdim / ydim + 0.5) || min;
35863
+ }
35864
+ }
35865
+ function setMapMode(m, mode) {
35866
+ if (mode < MM_TEXT || mode > MM_ANISOTROPIC) {
35867
+ return;
35868
+ }
35869
+ const units = METRIC_UNITS_PER_INCH[mode === MM_ISOTROPIC ? MM_LOMETRIC : mode];
35870
+ if (mode === MM_TEXT) {
35871
+ m.winExt = { cx: 1, cy: 1 };
35872
+ m.vpExt = { cx: 1, cy: 1 };
35873
+ } else if (units !== void 0 && (mode !== MM_ISOTROPIC || m.mode !== MM_ISOTROPIC)) {
35874
+ m.winExt = { cx: units, cy: units };
35875
+ m.vpExt = { cx: m.dpi?.x ?? DEVICE_DPI, cy: -(m.dpi?.y ?? DEVICE_DPI) };
35876
+ }
35877
+ m.mode = mode;
35878
+ }
35879
+ function extentsSettable(m) {
35880
+ return m.mode === MM_ISOTROPIC || m.mode === MM_ANISOTROPIC;
35881
+ }
35882
+ function setWindowExt(m, cx, cy) {
35883
+ if (!extentsSettable(m) || cx === 0 || cy === 0) {
35884
+ return;
35885
+ }
35886
+ m.winExt = { cx, cy };
35887
+ fixIsotropic(m);
35888
+ }
35889
+ function setViewportExt(m, cx, cy) {
35890
+ if (!extentsSettable(m) || cx === 0 || cy === 0) {
35891
+ return;
35892
+ }
35893
+ m.vpExt = { cx, cy };
35894
+ fixIsotropic(m);
35895
+ }
35896
+ function scaled(v, num, den) {
35897
+ return Math.trunc(v * num / den);
35898
+ }
35899
+ function scaleWindowExt(m, xNum, xDen, yNum, yDen) {
35900
+ if (!extentsSettable(m) || !xDen || !yDen) {
35901
+ return;
35902
+ }
35903
+ const cx = scaled(m.winExt.cx, xNum, xDen);
35904
+ const cy = scaled(m.winExt.cy, yNum, yDen);
35905
+ if (cx === 0 || cy === 0) {
35906
+ return;
35907
+ }
35908
+ m.winExt = { cx, cy };
35909
+ fixIsotropic(m);
35910
+ }
35911
+ function scaleViewportExt(m, xNum, xDen, yNum, yDen) {
35912
+ if (!extentsSettable(m) || !xDen || !yDen) {
35913
+ return;
35914
+ }
35915
+ const cx = scaled(m.vpExt.cx, xNum, xDen);
35916
+ const cy = scaled(m.vpExt.cy, yNum, yDen);
35917
+ if (cx === 0 || cy === 0) {
35918
+ return;
35919
+ }
35920
+ m.vpExt = { cx, cy };
35921
+ fixIsotropic(m);
35922
+ }
35923
+ function applyWmfMapping(rCtx, m, kx, ky, mirrorWidth = 0) {
35924
+ rCtx.wmfLayoutRtl = mirrorWidth > 0;
35925
+ rCtx.useMappingMode = true;
35926
+ rCtx.windowOrg = { x: m.winOrg.x, y: m.winOrg.y };
35927
+ rCtx.windowExt = { cx: m.winExt.cx || 1, cy: m.winExt.cy || 1 };
35928
+ rCtx.viewportOrg = { x: m.vpOrg.x * kx, y: m.vpOrg.y * ky };
35929
+ rCtx.viewportExt = { cx: (m.vpExt.cx || 1) * kx, cy: (m.vpExt.cy || 1) * ky };
35930
+ if (mirrorWidth > 0) {
35931
+ rCtx.viewportOrg.x = mirrorWidth * kx - rCtx.viewportOrg.x;
35932
+ rCtx.viewportExt.cx = -rCtx.viewportExt.cx;
35933
+ }
35934
+ }
35935
+ function scanMappingRecords(view, start) {
35936
+ const out = {
35937
+ mode: null,
35938
+ winExt: null,
35939
+ vpExt: null
35940
+ };
35941
+ let off = start;
35942
+ let guard = 0;
35943
+ while (off + 6 <= view.byteLength && guard++ < 1e6) {
35944
+ const size = view.getUint32(off, true) * 2;
35945
+ const type = view.getUint16(off + 4, true);
35946
+ if (size < 6 || off + size > view.byteLength || type === 0) {
35947
+ break;
35948
+ }
35949
+ const d = off + 6;
35950
+ if (type === 259 && size >= 8 && out.mode === null) {
35951
+ out.mode = view.getUint16(d, true);
35952
+ } else if (type === 524 && size >= 10 && !out.winExt) {
35953
+ out.winExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
35954
+ } else if (type === 526 && size >= 10 && !out.vpExt) {
35955
+ out.vpExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
35956
+ }
35957
+ off += size;
35958
+ }
35959
+ return out;
35960
+ }
35961
+ function wmfPlayback(view, header, referenceDpi) {
35962
+ const valid = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : DEVICE_DPI;
35963
+ const dpi = { x: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.x), y: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.y) };
35964
+ const density = referenceDpi === void 0 ? {} : { dpi };
35965
+ const bw = header.boundsRight - header.boundsLeft;
35966
+ const bh = header.boundsBottom - header.boundsTop;
35967
+ if (header.placeable !== false) {
35968
+ const inch = header.unitsPerInch > 0 ? header.unitsPerInch : DEVICE_DPI;
35969
+ const width2 = Math.max(1, Math.round(Math.abs(bw) * dpi.x / inch));
35970
+ const height2 = Math.max(1, Math.round(Math.abs(bh) * dpi.y / inch));
35971
+ return {
35972
+ width: width2,
35973
+ height: height2,
35974
+ mapping: {
35975
+ ...density,
35976
+ mode: MM_ANISOTROPIC,
35977
+ winOrg: { x: header.boundsLeft, y: header.boundsTop },
35978
+ winExt: { cx: bw || 1, cy: bh || 1 },
35979
+ vpOrg: { x: 0, y: 0 },
35980
+ vpExt: { cx: width2, cy: height2 }
35981
+ }
35982
+ };
35983
+ }
35984
+ const scan = scanMappingRecords(view, header.headerSize);
35985
+ const scalable = scan.mode === MM_ISOTROPIC || scan.mode === MM_ANISOTROPIC;
35986
+ const ext = scalable && scan.vpExt ? scan.vpExt : scan.winExt;
35987
+ const width = ext ? Math.abs(ext.cx) : Math.abs(bw);
35988
+ const height = ext ? Math.abs(ext.cy) : Math.abs(bh);
35989
+ const w = Math.max(1, width || 1);
35990
+ const h = Math.max(1, height || 1);
35991
+ return {
35992
+ width: w,
35993
+ height: h,
35994
+ mapping: {
35995
+ ...density,
35996
+ mode: MM_ANISOTROPIC,
35997
+ winOrg: { x: 0, y: 0 },
35998
+ winExt: { cx: w, cy: h },
35999
+ vpOrg: { x: 0, y: 0 },
36000
+ vpExt: { cx: w, cy: h }
36001
+ }
36002
+ };
36003
+ }
36004
+
36005
+ // src/emf-gdi-transform-handlers.ts
36006
+ function emfDeviceDpi(view) {
36007
+ if (view.byteLength < 88 || view.getUint32(0, true) !== 1) {
36008
+ return void 0;
36009
+ }
36010
+ const devW = view.getInt32(72, true);
36011
+ const devH = view.getInt32(76, true);
36012
+ const mmW = view.getInt32(80, true);
36013
+ const mmH = view.getInt32(84, true);
36014
+ if (devW <= 0 || devH <= 0 || mmW <= 0 || mmH <= 0) {
36015
+ return void 0;
36016
+ }
36017
+ return { x: devW * 25.4 / mmW, y: devH * 25.4 / mmH };
36018
+ }
36019
+ function emfMapping(r) {
36020
+ const dpi = emfDeviceDpi(r.view);
36021
+ return {
36022
+ ...dpi ? { dpi } : {},
36023
+ mode: r.mapMode ?? MM_TEXT,
36024
+ winOrg: r.windowOrg,
36025
+ winExt: { ...r.windowExt },
36026
+ vpOrg: r.viewportOrg,
36027
+ vpExt: { ...r.viewportExt }
36028
+ };
36029
+ }
36030
+ function storeMapping(r, m) {
36031
+ r.mapMode = m.mode;
36032
+ r.windowExt = m.winExt;
36033
+ r.viewportExt = m.vpExt;
36034
+ }
36035
+ function setExtent(r, viewport, cx, cy) {
36036
+ const m = emfMapping(r);
36037
+ if (!extentsSettable(m) || cx === 0 || cy === 0) {
36038
+ return;
36039
+ }
36040
+ if (viewport) {
36041
+ m.vpExt = { cx, cy };
36042
+ } else {
36043
+ m.winExt = { cx, cy };
36044
+ }
36045
+ fixIsotropic(m);
36046
+ storeMapping(r, m);
36047
+ activateGdiMappingMode(r);
36048
+ }
36049
+ function scaleExtent(r, viewport, xNum, xDenom, yNum, yDenom) {
36050
+ const ext = viewport ? r.viewportExt : r.windowExt;
36051
+ const cx = xDenom !== 0 ? Math.round(ext.cx * xNum / xDenom) : ext.cx;
36052
+ const cy = yDenom !== 0 ? Math.round(ext.cy * yNum / yDenom) : ext.cy;
36053
+ setExtent(r, viewport, cx, cy);
36054
+ }
36055
+ function handleCoordinateRecord(rCtx, recType, dataOff, recSize) {
36056
+ const { view } = rCtx;
36057
+ switch (recType) {
36058
+ case EMR_SETWINDOWEXTEX: {
36059
+ if (recSize >= 16) {
36060
+ setExtent(rCtx, false, view.getInt32(dataOff, true), view.getInt32(dataOff + 4, true));
36061
+ }
36062
+ return true;
36063
+ }
36064
+ case EMR_SETWINDOWORGEX: {
36065
+ if (recSize >= 16) {
36066
+ rCtx.windowOrg.x = view.getInt32(dataOff, true);
36067
+ rCtx.windowOrg.y = view.getInt32(dataOff + 4, true);
36068
+ activateGdiMappingMode(rCtx);
36069
+ }
36070
+ return true;
36071
+ }
36072
+ case EMR_SETVIEWPORTEXTEX: {
36073
+ if (recSize >= 16) {
36074
+ setExtent(rCtx, true, view.getInt32(dataOff, true), view.getInt32(dataOff + 4, true));
36075
+ }
36076
+ return true;
36077
+ }
36078
+ case EMR_SETVIEWPORTORGEX: {
36079
+ if (recSize >= 16) {
36080
+ rCtx.viewportOrg.x = view.getInt32(dataOff, true);
36081
+ rCtx.viewportOrg.y = view.getInt32(dataOff + 4, true);
35803
36082
  activateGdiMappingMode(rCtx);
35804
36083
  }
35805
36084
  return true;
35806
36085
  }
36086
+ case EMR_SETMAPMODE: {
36087
+ if (recSize >= 12) {
36088
+ const mode = view.getUint32(dataOff, true);
36089
+ if (mode >= MM_TEXT && mode <= MM_ANISOTROPIC) {
36090
+ const m = emfMapping(rCtx);
36091
+ setMapMode(m, mode);
36092
+ storeMapping(rCtx, m);
36093
+ activateGdiMappingMode(rCtx);
36094
+ }
36095
+ }
36096
+ return true;
36097
+ }
36098
+ case EMR_SCALEVIEWPORTEXTEX:
36099
+ case EMR_SCALEWINDOWEXTEX: {
36100
+ if (recSize >= 24) {
36101
+ scaleExtent(
36102
+ rCtx,
36103
+ recType === EMR_SCALEVIEWPORTEXTEX,
36104
+ view.getInt32(dataOff, true),
36105
+ view.getInt32(dataOff + 4, true),
36106
+ view.getInt32(dataOff + 8, true),
36107
+ view.getInt32(dataOff + 12, true)
36108
+ );
36109
+ }
36110
+ return true;
36111
+ }
35807
36112
  default:
35808
36113
  return false;
35809
36114
  }
@@ -36792,24 +37097,22 @@ function rgbaToHex(c) {
36792
37097
  }
36793
37098
  return /^#[0-9a-f]{6}$/i.test(c) ? c : null;
36794
37099
  }
36795
- function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
37100
+ function realizePlusEngineFont(rCtx, font, paint, brushSampler2) {
36796
37101
  const fonts = rCtx.fonts;
36797
37102
  const color = typeof paint === "string" ? rgbaToHex(paint) : null;
36798
- const hintNow = rCtx.textRenderingHint ?? 0;
36799
- const graySmooth = hintNow === 3 || hintNow === 4 || hintNow === 5;
37103
+ const hint = rCtx.textRenderingHint ?? 0;
37104
+ const graySmooth = hint === 3 || hint === 4 || hint === 5;
36800
37105
  const solidViaCoverage = !!color && graySmooth && !isSvgContext(rCtx.ctx);
36801
37106
  const sampler = isSvgContext(rCtx.ctx) ? null : solidViaCoverage ? solidSampler(cssColorToArgb(paint) ?? 4278190080) : color ? null : brushSampler2;
36802
37107
  const unit = font.unit ?? 0;
36803
- if (!fonts || !color && !sampler || alignment !== 0 || unit !== 0 && unit !== 2) {
36804
- return false;
37108
+ if (!fonts || !color && !sampler || unit !== 0 && unit !== 2) {
37109
+ return null;
36805
37110
  }
36806
37111
  const m = plusWorldMatrix(rCtx);
36807
37112
  if (m[1] !== 0 || m[2] !== 0 || m[0] <= 0 || m[3] <= 0) {
36808
- return false;
37113
+ return null;
36809
37114
  }
36810
37115
  const emPx = font.emSize * m[3];
36811
- const hint = rCtx.textRenderingHint ?? 0;
36812
- const quality = HINT_QUALITY[hint] ?? NONANTIALIASED_QUALITY;
36813
37116
  const spec = {
36814
37117
  face: font.family,
36815
37118
  height: -Math.round(emPx),
@@ -36818,39 +37121,41 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
36818
37121
  italic: (font.flags & 2) !== 0,
36819
37122
  charSet: 1,
36820
37123
  pitchAndFamily: 0,
36821
- quality,
37124
+ quality: HINT_QUALITY[hint] ?? NONANTIALIASED_QUALITY,
36822
37125
  unhinted: hint === 2 || hint === 4,
36823
37126
  // AntiAlias ignores the font's gasp table (measured: Arial 16 px is
36824
37127
  // grayscale there, but single-bit under AntiAliasGridFit, as in GDI).
36825
- ignoreGasp: hint === 4
37128
+ ignoreGasp: hint === 4,
37129
+ gdiPlus: true
36826
37130
  };
36827
37131
  const realized = fonts.realize(spec, rCtx.fontFamilyMap);
36828
37132
  if (!realized) {
36829
- return false;
36830
- }
36831
- const ttf = realized.ttf;
36832
- const unhinted = spec.unhinted === true;
36833
- const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
36834
- const ascent = unhinted ? exactAscent : Math.ceil(exactAscent);
36835
- const x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
36836
- const y = m[3] * layoutY + m[5] + ascent;
36837
- const codes = [];
36838
- for (let i = 0; i < text.length; i++) {
36839
- codes.push(text.charCodeAt(i));
37133
+ return null;
36840
37134
  }
36841
- const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
36842
- const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
36843
- if ((!color || solidViaCoverage) && sampler) {
36844
- const cov = gdiTextCoverage(realized, {
36845
- codes,
36846
- glyphIndices: false,
36847
- x,
36848
- y,
36849
- dx,
36850
- dy: null,
36851
- textAlign: 24,
36852
- options: 0,
36853
- matrix: null});
37135
+ return {
37136
+ realized,
37137
+ emPx,
37138
+ m,
37139
+ unhinted: spec.unhinted === true,
37140
+ color,
37141
+ sampler,
37142
+ solidViaCoverage,
37143
+ underline: (font.flags & 4) !== 0,
37144
+ strikeOut: (font.flags & 8) !== 0
37145
+ };
37146
+ }
37147
+ function paintPlusEngineRun(rCtx, ef, run) {
37148
+ const base = {
37149
+ ...run,
37150
+ textAlign: 24,
37151
+ bkColor: "#ffffff",
37152
+ bkMode: 1,
37153
+ options: 0,
37154
+ rect: null,
37155
+ matrix: null
37156
+ };
37157
+ if ((!ef.color || ef.solidViaCoverage) && ef.sampler) {
37158
+ const cov = gdiTextCoverage(ef.realized, { ...base, underline: ef.underline, strikeOut: ef.strikeOut }, { decorations: true, grayLevels: 15 });
36854
37159
  if (!cov) {
36855
37160
  return true;
36856
37161
  }
@@ -36860,7 +37165,7 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
36860
37165
  }
36861
37166
  return compositeBrushCoverage(
36862
37167
  rCtx,
36863
- sampler,
37168
+ ef.sampler,
36864
37169
  { x: cov.x, y: cov.y, w: cov.width, h: cov.height },
36865
37170
  cov.data,
36866
37171
  cov.channels,
@@ -36868,25 +37173,83 @@ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, ali
36868
37173
  cov.channels === 3 ? gamma : 1
36869
37174
  );
36870
37175
  }
36871
- paintGdiTextRun(rCtx.ctx, realized, {
36872
- codes,
36873
- glyphIndices: false,
36874
- x,
36875
- y,
36876
- dx,
36877
- dy: null,
36878
- textAlign: 24,
36879
- textColor: color,
36880
- bkColor: "#ffffff",
36881
- bkMode: 1,
36882
- options: 0,
36883
- rect: null,
36884
- matrix: null,
36885
- underline: (font.flags & 4) !== 0,
36886
- strikeOut: (font.flags & 8) !== 0
36887
- }, rCtx.fontFamilyMap);
37176
+ paintGdiTextRun(
37177
+ rCtx.ctx,
37178
+ ef.realized,
37179
+ { ...base, textColor: ef.color, underline: ef.underline, strikeOut: ef.strikeOut },
37180
+ rCtx.fontFamilyMap
37181
+ );
36888
37182
  return true;
36889
37183
  }
37184
+ function drawPlusStringWithEngine(rCtx, font, text, layoutX, layoutY, paint, alignment, format, brushSampler2 = null) {
37185
+ if (alignment !== 0) {
37186
+ return false;
37187
+ }
37188
+ const ef = realizePlusEngineFont(rCtx, font, paint, brushSampler2);
37189
+ if (!ef) {
37190
+ return false;
37191
+ }
37192
+ const { realized, emPx, m, unhinted } = ef;
37193
+ const ttf = realized.ttf;
37194
+ const exactAscent = emPx * ttf.winAscent / ttf.unitsPerEm;
37195
+ const ascent = unhinted ? Math.round(exactAscent) : Math.ceil(exactAscent);
37196
+ let x = m[0] * layoutX + m[4] + emPx * (format?.leadingMargin ?? PLUS_LEADING_EM);
37197
+ if (!unhinted) x = Math.round(x);
37198
+ const y = m[3] * layoutY + m[5] + ascent;
37199
+ const codes = [];
37200
+ for (let i = 0; i < text.length; i++) {
37201
+ codes.push(text.charCodeAt(i));
37202
+ }
37203
+ const tracking = format?.tracking ?? PLUS_DEFAULT_TRACKING;
37204
+ const dx = unhinted ? codes.map((c) => realized.advance(realized.glyphIndex(c)) * tracking) : null;
37205
+ return paintPlusEngineRun(rCtx, ef, { codes, glyphIndices: false, x, y, dx, dy: null });
37206
+ }
37207
+ var DRIVER_STRING_CMAP_LOOKUP = 1;
37208
+ var DRIVER_STRING_VERTICAL = 2;
37209
+ var DRIVER_STRING_REALIZED_ADVANCE = 4;
37210
+ function drawPlusDriverString(rCtx, recFlags, brushVal, font, codes, positions, options2) {
37211
+ const cmap = (options2 & DRIVER_STRING_CMAP_LOOKUP) !== 0;
37212
+ const realizedAdvance = (options2 & DRIVER_STRING_REALIZED_ADVANCE) !== 0;
37213
+ if (!(options2 & DRIVER_STRING_VERTICAL)) {
37214
+ const paint = resolveBrushPaint(rCtx, recFlags, brushVal);
37215
+ const ef = realizePlusEngineFont(rCtx, font, paint, rCtx.fonts ? deviceBrushSampler(rCtx, recFlags, brushVal) : null);
37216
+ if (ef) {
37217
+ const { m } = ef;
37218
+ const dev = positions.map((p) => ({ x: m[0] * p.x + m[4], y: m[3] * p.y + m[5] }));
37219
+ const step = (axis) => dev.map((p, i) => i + 1 < dev.length ? dev[i + 1][axis] - p[axis] : 0);
37220
+ paintPlusEngineRun(rCtx, ef, {
37221
+ codes,
37222
+ glyphIndices: !cmap,
37223
+ x: dev[0].x,
37224
+ y: dev[0].y,
37225
+ dx: realizedAdvance ? null : step("x"),
37226
+ dy: realizedAdvance ? null : step("y")
37227
+ });
37228
+ return;
37229
+ }
37230
+ }
37231
+ if (!cmap) {
37232
+ return;
37233
+ }
37234
+ const { ctx } = rCtx;
37235
+ const bold = font.flags & 1 ? "bold " : "";
37236
+ const italic = font.flags & 2 ? "italic " : "";
37237
+ const family = mapFontFamily(font.family, rCtx.fontFamilyMap);
37238
+ const setFont = () => {
37239
+ ctx.font = `${italic}${bold}${font.emSize}px ${family}`;
37240
+ ctx.textBaseline = "alphabetic";
37241
+ ctx.textAlign = "left";
37242
+ };
37243
+ if (realizedAdvance) {
37244
+ setFont();
37245
+ fillPlusText(rCtx, recFlags, brushVal, String.fromCharCode(...codes), positions[0].x, positions[0].y, font.emSize);
37246
+ return;
37247
+ }
37248
+ for (let i = 0; i < codes.length; i++) {
37249
+ setFont();
37250
+ fillPlusText(rCtx, recFlags, brushVal, String.fromCharCode(codes[i]), positions[i].x, positions[i].y, font.emSize);
37251
+ }
37252
+ }
36890
37253
  function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataSize) {
36891
37254
  const { ctx, view, objectTable } = rCtx;
36892
37255
  switch (recType) {
@@ -36970,24 +37333,31 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
36970
37333
  case EMFPLUS_DRAWDRIVERSTRING: {
36971
37334
  if (recDataSize >= 16) {
36972
37335
  const brushVal = view.getUint32(dataOff, true);
37336
+ const options2 = view.getUint32(dataOff + 4, true);
37337
+ const matrixPresent = view.getUint32(dataOff + 8, true) !== 0;
36973
37338
  const glyphCount = view.getUint32(dataOff + 12, true);
36974
- const fontId = recFlags & 255;
36975
- const font = objectTable.get(fontId);
37339
+ const font = objectTable.get(recFlags & 255);
36976
37340
  const glyphsOff = dataOff + 16;
36977
37341
  const posOff = glyphsOff + glyphCount * 2;
36978
- const alignedPosOff = posOff + 3 & -4;
36979
- if (glyphCount > 0 && glyphCount < 1e5 && alignedPosOff + glyphCount * 8 <= dataOff + recDataSize && font && font.kind === "plus-font") {
36980
- const text = readUtf16LE(view, glyphsOff, glyphCount);
36981
- if (text.length > 0) {
36982
- const bold = font.flags & 1 ? "bold " : "";
36983
- const italic = font.flags & 2 ? "italic " : "";
36984
- const family = mapFontFamily(font.family, rCtx.fontFamilyMap);
36985
- ctx.font = `${italic}${bold}${font.emSize}px ${family}`;
36986
- ctx.textBaseline = "alphabetic";
36987
- ctx.textAlign = "left";
36988
- const gx = view.getFloat32(alignedPosOff, true);
36989
- const gy = view.getFloat32(alignedPosOff + 4, true);
36990
- fillPlusText(rCtx, recFlags, brushVal, text, gx, gy, font.emSize);
37342
+ const matrixOff = posOff + glyphCount * 8;
37343
+ if (glyphCount > 0 && glyphCount < 1e5 && matrixOff + (matrixPresent ? 24 : 0) <= dataOff + recDataSize && font && font.kind === "plus-font") {
37344
+ const codes = [];
37345
+ const positions = [];
37346
+ for (let i = 0; i < glyphCount; i++) {
37347
+ codes.push(view.getUint16(glyphsOff + i * 2, true));
37348
+ positions.push({ x: view.getFloat32(posOff + i * 8, true), y: view.getFloat32(posOff + i * 8 + 4, true) });
37349
+ }
37350
+ const world = rCtx.worldTransform;
37351
+ if (matrixPresent) {
37352
+ const xf = [0, 4, 8, 12, 16, 20].map((k) => view.getFloat32(matrixOff + k, true));
37353
+ if (xf.every(Number.isFinite)) {
37354
+ rCtx.worldTransform = mulMatrix(world, xf);
37355
+ }
37356
+ }
37357
+ try {
37358
+ drawPlusDriverString(rCtx, recFlags, brushVal, font, codes, positions, options2);
37359
+ } finally {
37360
+ rCtx.worldTransform = world;
36991
37361
  }
36992
37362
  }
36993
37363
  }
@@ -37766,7 +38136,7 @@ function parseEmfPlusRegionObject(view, off, maxLen) {
37766
38136
  }
37767
38137
  view.getUint32(off, true);
37768
38138
  const regionNodeCount = view.getUint32(off + 4, true);
37769
- if (regionNodeCount === 0 || regionNodeCount > 1e5) {
38139
+ if (regionNodeCount > 1e5) {
37770
38140
  return null;
37771
38141
  }
37772
38142
  const endOff = off + maxLen;
@@ -38282,187 +38652,6 @@ function extractEmbeddedEmf(view, start) {
38282
38652
  return out.buffer;
38283
38653
  }
38284
38654
 
38285
- // src/wmf-mapping.ts
38286
- var MM_TEXT = 1;
38287
- var MM_LOMETRIC = 2;
38288
- var MM_HIMETRIC = 3;
38289
- var MM_LOENGLISH = 4;
38290
- var MM_HIENGLISH = 5;
38291
- var MM_TWIPS = 6;
38292
- var MM_ISOTROPIC = 7;
38293
- var MM_ANISOTROPIC = 8;
38294
- var DEVICE_DPI = 96;
38295
- function cloneMapping(m) {
38296
- return {
38297
- ...m.dpi ? { dpi: { ...m.dpi } } : {},
38298
- mode: m.mode,
38299
- winOrg: { ...m.winOrg },
38300
- winExt: { ...m.winExt },
38301
- vpOrg: { ...m.vpOrg },
38302
- vpExt: { ...m.vpExt }
38303
- };
38304
- }
38305
- var METRIC_UNITS_PER_INCH = {
38306
- [MM_LOMETRIC]: 254,
38307
- [MM_HIMETRIC]: 2540,
38308
- [MM_LOENGLISH]: 100,
38309
- [MM_HIENGLISH]: 1e3,
38310
- [MM_TWIPS]: 1440
38311
- };
38312
- function fixIsotropic(m) {
38313
- if (m.mode !== MM_ISOTROPIC || !m.winExt.cx || !m.winExt.cy) {
38314
- return;
38315
- }
38316
- const xdim = Math.abs(m.vpExt.cx / m.winExt.cx) / (m.dpi?.x ?? DEVICE_DPI);
38317
- const ydim = Math.abs(m.vpExt.cy / m.winExt.cy) / (m.dpi?.y ?? DEVICE_DPI);
38318
- if (xdim > ydim) {
38319
- const min = m.vpExt.cx >= 0 ? 1 : -1;
38320
- m.vpExt.cx = Math.floor(m.vpExt.cx * ydim / xdim + 0.5) || min;
38321
- } else if (ydim > xdim) {
38322
- const min = m.vpExt.cy >= 0 ? 1 : -1;
38323
- m.vpExt.cy = Math.floor(m.vpExt.cy * xdim / ydim + 0.5) || min;
38324
- }
38325
- }
38326
- function setMapMode(m, mode) {
38327
- if (mode < MM_TEXT || mode > MM_ANISOTROPIC) {
38328
- return;
38329
- }
38330
- const units = METRIC_UNITS_PER_INCH[mode === MM_ISOTROPIC ? MM_LOMETRIC : mode];
38331
- if (mode === MM_TEXT) {
38332
- m.winExt = { cx: 1, cy: 1 };
38333
- m.vpExt = { cx: 1, cy: 1 };
38334
- } else if (units !== void 0 && (mode !== MM_ISOTROPIC || m.mode !== MM_ISOTROPIC)) {
38335
- m.winExt = { cx: units, cy: units };
38336
- m.vpExt = { cx: m.dpi?.x ?? DEVICE_DPI, cy: -(m.dpi?.y ?? DEVICE_DPI) };
38337
- }
38338
- m.mode = mode;
38339
- }
38340
- function extentsSettable2(m) {
38341
- return m.mode === MM_ISOTROPIC || m.mode === MM_ANISOTROPIC;
38342
- }
38343
- function setWindowExt(m, cx, cy) {
38344
- if (!extentsSettable2(m) || cx === 0 || cy === 0) {
38345
- return;
38346
- }
38347
- m.winExt = { cx, cy };
38348
- fixIsotropic(m);
38349
- }
38350
- function setViewportExt(m, cx, cy) {
38351
- if (!extentsSettable2(m) || cx === 0 || cy === 0) {
38352
- return;
38353
- }
38354
- m.vpExt = { cx, cy };
38355
- fixIsotropic(m);
38356
- }
38357
- function scaled(v, num, den) {
38358
- return Math.trunc(v * num / den);
38359
- }
38360
- function scaleWindowExt(m, xNum, xDen, yNum, yDen) {
38361
- if (!extentsSettable2(m) || !xDen || !yDen) {
38362
- return;
38363
- }
38364
- const cx = scaled(m.winExt.cx, xNum, xDen);
38365
- const cy = scaled(m.winExt.cy, yNum, yDen);
38366
- if (cx === 0 || cy === 0) {
38367
- return;
38368
- }
38369
- m.winExt = { cx, cy };
38370
- fixIsotropic(m);
38371
- }
38372
- function scaleViewportExt(m, xNum, xDen, yNum, yDen) {
38373
- if (!extentsSettable2(m) || !xDen || !yDen) {
38374
- return;
38375
- }
38376
- const cx = scaled(m.vpExt.cx, xNum, xDen);
38377
- const cy = scaled(m.vpExt.cy, yNum, yDen);
38378
- if (cx === 0 || cy === 0) {
38379
- return;
38380
- }
38381
- m.vpExt = { cx, cy };
38382
- fixIsotropic(m);
38383
- }
38384
- function applyWmfMapping(rCtx, m, kx, ky, mirrorWidth = 0) {
38385
- rCtx.wmfLayoutRtl = mirrorWidth > 0;
38386
- rCtx.useMappingMode = true;
38387
- rCtx.windowOrg = { x: m.winOrg.x, y: m.winOrg.y };
38388
- rCtx.windowExt = { cx: m.winExt.cx || 1, cy: m.winExt.cy || 1 };
38389
- rCtx.viewportOrg = { x: m.vpOrg.x * kx, y: m.vpOrg.y * ky };
38390
- rCtx.viewportExt = { cx: (m.vpExt.cx || 1) * kx, cy: (m.vpExt.cy || 1) * ky };
38391
- if (mirrorWidth > 0) {
38392
- rCtx.viewportOrg.x = mirrorWidth * kx - rCtx.viewportOrg.x;
38393
- rCtx.viewportExt.cx = -rCtx.viewportExt.cx;
38394
- }
38395
- }
38396
- function scanMappingRecords(view, start) {
38397
- const out = {
38398
- mode: null,
38399
- winExt: null,
38400
- vpExt: null
38401
- };
38402
- let off = start;
38403
- let guard = 0;
38404
- while (off + 6 <= view.byteLength && guard++ < 1e6) {
38405
- const size = view.getUint32(off, true) * 2;
38406
- const type = view.getUint16(off + 4, true);
38407
- if (size < 6 || off + size > view.byteLength || type === 0) {
38408
- break;
38409
- }
38410
- const d = off + 6;
38411
- if (type === 259 && size >= 8 && out.mode === null) {
38412
- out.mode = view.getUint16(d, true);
38413
- } else if (type === 524 && size >= 10 && !out.winExt) {
38414
- out.winExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
38415
- } else if (type === 526 && size >= 10 && !out.vpExt) {
38416
- out.vpExt = { cy: view.getInt16(d, true), cx: view.getInt16(d + 2, true) };
38417
- }
38418
- off += size;
38419
- }
38420
- return out;
38421
- }
38422
- function wmfPlayback(view, header, referenceDpi) {
38423
- const valid = (v) => typeof v === "number" && Number.isFinite(v) && v > 0 ? v : DEVICE_DPI;
38424
- const dpi = { x: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.x), y: valid(typeof referenceDpi === "number" ? referenceDpi : referenceDpi?.y) };
38425
- const density = referenceDpi === void 0 ? {} : { dpi };
38426
- const bw = header.boundsRight - header.boundsLeft;
38427
- const bh = header.boundsBottom - header.boundsTop;
38428
- if (header.placeable !== false) {
38429
- const inch = header.unitsPerInch > 0 ? header.unitsPerInch : DEVICE_DPI;
38430
- const width2 = Math.max(1, Math.round(Math.abs(bw) * dpi.x / inch));
38431
- const height2 = Math.max(1, Math.round(Math.abs(bh) * dpi.y / inch));
38432
- return {
38433
- width: width2,
38434
- height: height2,
38435
- mapping: {
38436
- ...density,
38437
- mode: MM_ANISOTROPIC,
38438
- winOrg: { x: header.boundsLeft, y: header.boundsTop },
38439
- winExt: { cx: bw || 1, cy: bh || 1 },
38440
- vpOrg: { x: 0, y: 0 },
38441
- vpExt: { cx: width2, cy: height2 }
38442
- }
38443
- };
38444
- }
38445
- const scan = scanMappingRecords(view, header.headerSize);
38446
- const scalable = scan.mode === MM_ISOTROPIC || scan.mode === MM_ANISOTROPIC;
38447
- const ext = scalable && scan.vpExt ? scan.vpExt : scan.winExt;
38448
- const width = ext ? Math.abs(ext.cx) : Math.abs(bw);
38449
- const height = ext ? Math.abs(ext.cy) : Math.abs(bh);
38450
- const w = Math.max(1, width || 1);
38451
- const h = Math.max(1, height || 1);
38452
- return {
38453
- width: w,
38454
- height: h,
38455
- mapping: {
38456
- ...density,
38457
- mode: MM_ANISOTROPIC,
38458
- winOrg: { x: 0, y: 0 },
38459
- winExt: { cx: w, cy: h },
38460
- vpOrg: { x: 0, y: 0 },
38461
- vpExt: { cx: w, cy: h }
38462
- }
38463
- };
38464
- }
38465
-
38466
38655
  // src/wmf-emf-bridge.ts
38467
38656
  var EmfRecordWriter = class {
38468
38657
  constructor(type, capacity = 64) {