emf-converter 4.17.0 → 4.18.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/README.md +4 -4
- package/THIRD_PARTY_NOTICES +31 -4
- package/dist/browser.js +1783 -391
- package/dist/browser.mjs +1783 -391
- package/dist/index.js +1783 -391
- package/dist/index.mjs +1783 -391
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -10445,12 +10445,12 @@ function cmykPlanesToRgba(planes, width, height, ycck) {
|
|
|
10445
10445
|
const fracOf = FRAC_OF;
|
|
10446
10446
|
const strides = [N * N * N * 3, N * N * 3, N * 3, 3];
|
|
10447
10447
|
const out = new Uint8Array(width * height * 4);
|
|
10448
|
-
const
|
|
10448
|
+
const fix2 = (x) => Math.floor(x * 65536 + 0.5);
|
|
10449
10449
|
const half = 1 << 15;
|
|
10450
|
-
const crR =
|
|
10451
|
-
const cbB =
|
|
10452
|
-
const crG = -
|
|
10453
|
-
const cbG = -
|
|
10450
|
+
const crR = fix2(1.402);
|
|
10451
|
+
const cbB = fix2(1.772);
|
|
10452
|
+
const crG = -fix2(0.71414);
|
|
10453
|
+
const cbG = -fix2(0.34414);
|
|
10454
10454
|
const inks = [0, 0, 0, 0];
|
|
10455
10455
|
const frac = [0, 0, 0, 0];
|
|
10456
10456
|
const order = [0, 1, 2, 3];
|
|
@@ -11361,12 +11361,12 @@ function convertPlanes({ width, height, planes: full, ids, adobe }, colorTransfo
|
|
|
11361
11361
|
}
|
|
11362
11362
|
} else {
|
|
11363
11363
|
const clamp2 = (v) => v < 0 ? 0 : v > 255 ? 255 : v;
|
|
11364
|
-
const
|
|
11364
|
+
const fix2 = (x) => Math.floor(x * 65536 + 0.5);
|
|
11365
11365
|
const half = 1 << 15;
|
|
11366
|
-
const crR =
|
|
11367
|
-
const cbB =
|
|
11368
|
-
const crG = -
|
|
11369
|
-
const cbG = -
|
|
11366
|
+
const crR = fix2(1.402);
|
|
11367
|
+
const cbB = fix2(1.772);
|
|
11368
|
+
const crG = -fix2(0.71414);
|
|
11369
|
+
const cbG = -fix2(0.34414);
|
|
11370
11370
|
for (let i = 0; i < width * height; i++) {
|
|
11371
11371
|
const y = full[0][i];
|
|
11372
11372
|
const cb = full[1][i] - 128;
|
|
@@ -12333,7 +12333,7 @@ function flattenBezierPath(pts) {
|
|
|
12333
12333
|
}
|
|
12334
12334
|
return out;
|
|
12335
12335
|
}
|
|
12336
|
-
function roundRectCorners(l, t, r, b, cw, ch, compatible = false, clockwise = false) {
|
|
12336
|
+
function roundRectCorners(l, t, r, b, cw, ch, compatible = false, clockwise = false, floorH = false) {
|
|
12337
12337
|
const w = r - l;
|
|
12338
12338
|
const h = b - t;
|
|
12339
12339
|
let ew = Math.min(Math.abs(cw), w);
|
|
@@ -12346,7 +12346,7 @@ function roundRectCorners(l, t, r, b, cw, ch, compatible = false, clockwise = fa
|
|
|
12346
12346
|
const topX = compatible ? Math.round(r - ew / 2) : Math.floor(r - ew / 2);
|
|
12347
12347
|
const hx = r - topX;
|
|
12348
12348
|
const verticalControl = clockwise ? Math.ceil(KAPPA * hy) : Math.floor(KAPPA * hy);
|
|
12349
|
-
const horizontalControl = Math.ceil(KAPPA * hx);
|
|
12349
|
+
const horizontalControl = floorH ? Math.floor(KAPPA * hx) : Math.ceil(KAPPA * hx);
|
|
12350
12350
|
const q = [r, t + hy, r, t + hy - verticalControl, r - hx + horizontalControl, t, topX, t];
|
|
12351
12351
|
const mx = (x) => l + r - x;
|
|
12352
12352
|
const my = (y) => t + b - y;
|
|
@@ -12473,8 +12473,8 @@ var POLYGON_NODES = (() => {
|
|
|
12473
12473
|
const cos = [];
|
|
12474
12474
|
const sin = [];
|
|
12475
12475
|
for (let k = 0; k <= 129; k++) {
|
|
12476
|
-
cos.push(Math.cos(k * TRIG_STEP));
|
|
12477
|
-
sin.push(Math.sin(k * TRIG_STEP));
|
|
12476
|
+
cos.push(Math.fround(Math.cos(k * TRIG_STEP)));
|
|
12477
|
+
sin.push(Math.fround(Math.sin(k * TRIG_STEP)));
|
|
12478
12478
|
}
|
|
12479
12479
|
for (let k = 0; k <= 128; k += 32) {
|
|
12480
12480
|
cos[k] = [1, 0, -1, 0, 1][k / 32];
|
|
@@ -12487,7 +12487,7 @@ function polygonTrig(angle) {
|
|
|
12487
12487
|
if (b < 0) {
|
|
12488
12488
|
b += 2 * Math.PI;
|
|
12489
12489
|
}
|
|
12490
|
-
const x = b / TRIG_STEP;
|
|
12490
|
+
const x = Math.fround(b / TRIG_STEP);
|
|
12491
12491
|
const i = Math.min(127, Math.floor(x));
|
|
12492
12492
|
const f = x - i;
|
|
12493
12493
|
return [
|
|
@@ -12507,16 +12507,38 @@ function approximateArcAngle(x, y) {
|
|
|
12507
12507
|
if (ax === 0 && ay === 0) {
|
|
12508
12508
|
return 0;
|
|
12509
12509
|
}
|
|
12510
|
-
const a = ay <= ax ? interpolatedAtan(ay / ax) : Math.PI / 2 - interpolatedAtan(ax / ay);
|
|
12510
|
+
const a = ay <= ax ? interpolatedAtan(Math.fround(ay / ax)) : Math.PI / 2 - interpolatedAtan(Math.fround(ax / ay));
|
|
12511
12511
|
if (x >= 0) {
|
|
12512
12512
|
return y >= 0 ? a : 2 * Math.PI - a;
|
|
12513
12513
|
}
|
|
12514
12514
|
return y >= 0 ? Math.PI - a : Math.PI + a;
|
|
12515
12515
|
}
|
|
12516
|
-
function unitPiece(from, to, small) {
|
|
12516
|
+
function unitPiece(from, to, small, radius = Infinity) {
|
|
12517
12517
|
const trig = small ? (a) => [Math.cos(a), Math.sin(a)] : polygonTrig;
|
|
12518
12518
|
const p0 = trig(from);
|
|
12519
12519
|
const p3 = trig(to);
|
|
12520
|
+
if (small && 6e-8 * radius / Math.abs(Math.sin(to - from)) > 0.5) {
|
|
12521
|
+
const f = Math.fround;
|
|
12522
|
+
const q0 = [f(p0[0]), f(p0[1])];
|
|
12523
|
+
const q3 = [f(p3[0]), f(p3[1])];
|
|
12524
|
+
const det32 = f(f(q0[0] * q3[1]) - f(q0[1] * q3[0]));
|
|
12525
|
+
if (det32 !== 0) {
|
|
12526
|
+
const X = [f(f(q3[1] - q0[1]) / det32), f(f(q0[0] - q3[0]) / det32)];
|
|
12527
|
+
const c = f(polygonTrig(Math.abs(to - from) / 2)[0]);
|
|
12528
|
+
const kappa = f(f(f(4 / 3) * c) / f(1 + c));
|
|
12529
|
+
return {
|
|
12530
|
+
start: p0,
|
|
12531
|
+
ctrl: [
|
|
12532
|
+
f(q0[0] + f(kappa * f(X[0] - q0[0]))),
|
|
12533
|
+
f(q0[1] + f(kappa * f(X[1] - q0[1]))),
|
|
12534
|
+
f(q3[0] + f(kappa * f(X[0] - q3[0]))),
|
|
12535
|
+
f(q3[1] + f(kappa * f(X[1] - q3[1]))),
|
|
12536
|
+
p3[0],
|
|
12537
|
+
p3[1]
|
|
12538
|
+
]
|
|
12539
|
+
};
|
|
12540
|
+
}
|
|
12541
|
+
}
|
|
12520
12542
|
const det = p0[0] * p3[1] - p0[1] * p3[0];
|
|
12521
12543
|
let ctrl;
|
|
12522
12544
|
if (Math.abs(det) < 1e-12) {
|
|
@@ -12536,7 +12558,7 @@ function unitPiece(from, to, small) {
|
|
|
12536
12558
|
}
|
|
12537
12559
|
return { start: p0, ctrl };
|
|
12538
12560
|
}
|
|
12539
|
-
function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise, halfX = false, framed = false) {
|
|
12561
|
+
function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise, halfX = false, framed = false, mirrorX = false) {
|
|
12540
12562
|
const w = r - l;
|
|
12541
12563
|
const h = b - t;
|
|
12542
12564
|
const Q = Math.PI / 2;
|
|
@@ -12549,16 +12571,21 @@ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise, halfX = false, framed
|
|
|
12549
12571
|
const angle = (x, y) => approximateArcAngle((x - tcx) / (w / 2 || 1), -(y - tcy) / (h / 2 || 1));
|
|
12550
12572
|
const a0 = angle(xs, ys);
|
|
12551
12573
|
let a1 = angle(xe, ye);
|
|
12552
|
-
const
|
|
12574
|
+
const mirrored = (a2) => clockwise ? (2 * Math.PI - a2) % (2 * Math.PI) : a2;
|
|
12575
|
+
const small = a1 !== a0 && Math.abs(mirrored(a1) - mirrored(a0)) <= SMALL_SWEEP;
|
|
12553
12576
|
const s = clockwise ? -1 : 1;
|
|
12554
12577
|
if (s > 0) {
|
|
12555
12578
|
while (a1 <= a0) a1 += 2 * Math.PI;
|
|
12556
12579
|
} else {
|
|
12557
12580
|
while (a1 >= a0) a1 -= 2 * Math.PI;
|
|
12558
12581
|
}
|
|
12559
|
-
const
|
|
12560
|
-
const
|
|
12561
|
-
|
|
12582
|
+
const axis = (r2, c) => Math.fround(r2 * Math.fround(c));
|
|
12583
|
+
const px = (u, v) => mirrorX ? (
|
|
12584
|
+
// The mirrored circle sits on the same centre but its horizontal radius rounds down (native playback, 144 arcs under a mirrored x).
|
|
12585
|
+
Math.round(cx - axis(Math.floor(w / 2), u))
|
|
12586
|
+
) : clockwise && halfX ? Math.ceil(cx + axis(rx, u) + 0.5 - v) : Math.round(cx + axis(rx, u) + (halfX ? 1 + v : 0));
|
|
12587
|
+
const py = (v) => Math.round(cy - axis(ry, v));
|
|
12588
|
+
const eb = mirrorX ? axisBox(r, t, l, b) : axisBox(l, t, r, b);
|
|
12562
12589
|
if (halfX) eb.halfX = true;
|
|
12563
12590
|
const E = ellipseBeziersBox(eb);
|
|
12564
12591
|
if (clockwise) {
|
|
@@ -12594,7 +12621,7 @@ function arcBeziers(l, t, r, b, xs, ys, xe, ye, clockwise, halfX = false, framed
|
|
|
12594
12621
|
continue;
|
|
12595
12622
|
}
|
|
12596
12623
|
const e = s > 0 ? Math.min(next, a1) : Math.max(next, a1);
|
|
12597
|
-
const piece = unitPiece(a, e, small);
|
|
12624
|
+
const piece = unitPiece(a, e, small, Math.max(rx, ry));
|
|
12598
12625
|
for (let i = 0; i < 6; i += 2) {
|
|
12599
12626
|
out.push(px(piece.ctrl[i], piece.ctrl[i + 1]), py(piece.ctrl[i + 1]));
|
|
12600
12627
|
}
|
|
@@ -16262,6 +16289,21 @@ function decodeBmpFile(bytes) {
|
|
|
16262
16289
|
return image ? { kind: "rgba", data: image.data, width: image.width, height: image.height } : null;
|
|
16263
16290
|
}
|
|
16264
16291
|
|
|
16292
|
+
// src/float32-down.ts
|
|
16293
|
+
var float32 = new Float32Array(1);
|
|
16294
|
+
var float32Bits = new Uint32Array(float32.buffer);
|
|
16295
|
+
function down32(x) {
|
|
16296
|
+
const r = Math.fround(x);
|
|
16297
|
+
if (r <= x || Number.isNaN(r)) return r;
|
|
16298
|
+
if (r === 0) {
|
|
16299
|
+
float32Bits[0] = 2147483649;
|
|
16300
|
+
return float32[0];
|
|
16301
|
+
}
|
|
16302
|
+
float32[0] = r;
|
|
16303
|
+
float32Bits[0] += r > 0 ? -1 : 1;
|
|
16304
|
+
return float32[0];
|
|
16305
|
+
}
|
|
16306
|
+
|
|
16265
16307
|
// src/emf-plus-linear-ramp.ts
|
|
16266
16308
|
var GAMMA = 2.2;
|
|
16267
16309
|
function linearRampIntervals(pointCount, rect) {
|
|
@@ -16537,30 +16579,76 @@ function pathGradientQuantum(boundary, matrix = IDENTITY) {
|
|
|
16537
16579
|
let x1 = -Infinity;
|
|
16538
16580
|
let y1 = -Infinity;
|
|
16539
16581
|
for (const p of boundary) {
|
|
16540
|
-
|
|
16541
|
-
|
|
16542
|
-
|
|
16543
|
-
|
|
16544
|
-
x1 = Math.max(x1, x);
|
|
16545
|
-
y1 = Math.max(y1, y);
|
|
16582
|
+
x0 = Math.min(x0, p.x);
|
|
16583
|
+
y0 = Math.min(y0, p.y);
|
|
16584
|
+
x1 = Math.max(x1, p.x);
|
|
16585
|
+
y1 = Math.max(y1, p.y);
|
|
16546
16586
|
}
|
|
16547
|
-
const
|
|
16587
|
+
const w = x1 - x0;
|
|
16588
|
+
const h = y1 - y0;
|
|
16589
|
+
const first = Math.hypot(matrix[0] * w + matrix[2] * h, matrix[1] * w + matrix[3] * h);
|
|
16590
|
+
const second = Math.hypot(matrix[0] * w - matrix[2] * h, matrix[1] * w - matrix[3] * h);
|
|
16591
|
+
const steps = Math.ceil(first + second);
|
|
16548
16592
|
return Number.isFinite(steps) && steps > 0 ? steps : 0;
|
|
16549
16593
|
}
|
|
16594
|
+
var TIE_LEVEL = 1e-9;
|
|
16550
16595
|
var TIE_EPSILON = 1e-7;
|
|
16596
|
+
function pathGradientRatio(shape, x, y, focusPoint) {
|
|
16597
|
+
const report = { s: NaN };
|
|
16598
|
+
return pathGradientColorAt(shape, x, y, focusPoint, 0, report) === null ? null : report.s;
|
|
16599
|
+
}
|
|
16551
16600
|
function quantisedPathArgb(surround, centre, t, quantum) {
|
|
16552
16601
|
const scaled2 = t * quantum;
|
|
16553
16602
|
const tie = Math.abs(scaled2 - Math.floor(scaled2) - 0.5) < TIE_EPSILON;
|
|
16554
|
-
|
|
16555
|
-
|
|
16603
|
+
return quantisedStepArgb(surround, centre, tie ? scaled2 : Math.floor(scaled2 + 0.5), quantum, t < 0.5);
|
|
16604
|
+
}
|
|
16605
|
+
function roundTowards(v, target) {
|
|
16606
|
+
const floor = Math.floor(v);
|
|
16607
|
+
const fraction = v - floor;
|
|
16608
|
+
if (Math.abs(fraction - 0.5) < TIE_LEVEL) return target > v ? floor + 1 : floor;
|
|
16609
|
+
return fraction > 0.5 ? floor + 1 : floor;
|
|
16610
|
+
}
|
|
16611
|
+
var centreWeightTables = /* @__PURE__ */ new Map();
|
|
16612
|
+
function centreWeight(quantum, j) {
|
|
16613
|
+
let table2 = centreWeightTables.get(quantum);
|
|
16614
|
+
if (!table2) {
|
|
16615
|
+
table2 = new Float64Array(quantum + 1);
|
|
16616
|
+
const step = down32(1 / quantum);
|
|
16617
|
+
let w = 0;
|
|
16618
|
+
for (let i = 1; i <= quantum; i++) {
|
|
16619
|
+
w = down32(w + step);
|
|
16620
|
+
table2[i] = w;
|
|
16621
|
+
}
|
|
16622
|
+
if (centreWeightTables.size > 64) centreWeightTables.clear();
|
|
16623
|
+
centreWeightTables.set(quantum, table2);
|
|
16624
|
+
}
|
|
16625
|
+
return table2[j];
|
|
16626
|
+
}
|
|
16627
|
+
function centreWeightArgb(surround, centre, k, quantum) {
|
|
16628
|
+
const w = centreWeight(quantum, quantum - k);
|
|
16629
|
+
const aS = surround >>> 24 & 255;
|
|
16630
|
+
const aC = centre >>> 24 & 255;
|
|
16631
|
+
const level2 = (s, c) => roundTowards(c + (s - c) * w, c);
|
|
16632
|
+
const alpha = level2(aS, aC);
|
|
16633
|
+
if (alpha <= 0) return 0;
|
|
16634
|
+
const ch = (shift) => {
|
|
16635
|
+
const p = level2((surround >>> shift & 255) * aS / 255, (centre >>> shift & 255) * aC / 255);
|
|
16636
|
+
return Math.min(255, Math.max(0, Math.round(p * 255 / alpha)));
|
|
16637
|
+
};
|
|
16638
|
+
return (alpha << 24 | ch(16) << 16 | ch(8) << 8 | ch(0)) >>> 0;
|
|
16639
|
+
}
|
|
16640
|
+
function quantisedStepArgb(surround, centre, k, quantum, fromBoundary) {
|
|
16641
|
+
if (Number.isInteger(k)) return centreWeightArgb(surround, centre, k, quantum);
|
|
16556
16642
|
const w = (fromBoundary ? k : quantum - k) / quantum;
|
|
16557
16643
|
const aS = surround >>> 24 & 255;
|
|
16558
16644
|
const aC = centre >>> 24 & 255;
|
|
16559
16645
|
const mix2 = (s, c) => fromBoundary ? s + (c - s) * w : c + (s - c) * w;
|
|
16560
|
-
const
|
|
16646
|
+
const whole = Number.isInteger(k);
|
|
16647
|
+
const level2 = (s, c) => whole ? roundTowards(mix2(s, c), c) : Math.floor(mix2(s, c) + 0.5);
|
|
16648
|
+
const alpha = level2(aS, aC);
|
|
16561
16649
|
if (alpha <= 0) return 0;
|
|
16562
16650
|
const ch = (shift) => {
|
|
16563
|
-
const p =
|
|
16651
|
+
const p = level2((surround >>> shift & 255) * aS / 255, (centre >>> shift & 255) * aC / 255);
|
|
16564
16652
|
return Math.min(255, Math.max(0, Math.round(p * 255 / alpha)));
|
|
16565
16653
|
};
|
|
16566
16654
|
return (alpha << 24 | ch(16) << 16 | ch(8) << 8 | ch(0)) >>> 0;
|
|
@@ -16570,6 +16658,24 @@ function quantisedPosition(pos, quantum) {
|
|
|
16570
16658
|
const tie = Math.abs(scaled2 - Math.floor(scaled2) - 0.5) < TIE_EPSILON;
|
|
16571
16659
|
return (tie ? scaled2 : Math.floor(scaled2 + 0.5)) / quantum;
|
|
16572
16660
|
}
|
|
16661
|
+
function pathGradientStepColor(shape, k, quantum) {
|
|
16662
|
+
const pos = k / quantum;
|
|
16663
|
+
if (shape.preset && shape.preset.positions.length > 0) {
|
|
16664
|
+
const { positions, argb } = shape.preset;
|
|
16665
|
+
if (pos <= positions[0]) return argb[0];
|
|
16666
|
+
for (let i = 1; i < positions.length; i++) {
|
|
16667
|
+
if (pos <= positions[i]) {
|
|
16668
|
+
const span = positions[i] - positions[i - 1];
|
|
16669
|
+
return lerpArgb(argb[i - 1], argb[i], span > 0 ? (pos - positions[i - 1]) / span : 1);
|
|
16670
|
+
}
|
|
16671
|
+
}
|
|
16672
|
+
return argb[positions.length - 1];
|
|
16673
|
+
}
|
|
16674
|
+
const surround = shape.boundaryArgb[0] ?? shape.centerArgb;
|
|
16675
|
+
if (!shape.blend) return quantisedStepArgb(surround, shape.centerArgb, k, quantum, k * 2 < quantum);
|
|
16676
|
+
const t = Math.min(1, Math.max(0, piecewise2(shape.blend.positions, shape.blend.factors, pos)));
|
|
16677
|
+
return surround >>> 24 !== shape.centerArgb >>> 24 ? lerpUniformPathArgb(surround, shape.centerArgb, t) : lerpArgb(surround, shape.centerArgb, t);
|
|
16678
|
+
}
|
|
16573
16679
|
function piecewise2(xs, ys, x) {
|
|
16574
16680
|
const n = Math.min(xs.length, ys.length);
|
|
16575
16681
|
if (n === 0) {
|
|
@@ -16604,7 +16710,7 @@ function stopColorAt(stops, t) {
|
|
|
16604
16710
|
}
|
|
16605
16711
|
return stops[stops.length - 1].argb;
|
|
16606
16712
|
}
|
|
16607
|
-
function pathGradientColorAt(shape, x, y, focusPoint, quantum) {
|
|
16713
|
+
function pathGradientColorAt(shape, x, y, focusPoint, quantum, report) {
|
|
16608
16714
|
const { center, boundary, boundaryArgb } = shape;
|
|
16609
16715
|
const n = boundary.length;
|
|
16610
16716
|
const px = x - center.x;
|
|
@@ -16710,6 +16816,7 @@ function pathGradientColorAt(shape, x, y, focusPoint, quantum) {
|
|
|
16710
16816
|
}
|
|
16711
16817
|
}
|
|
16712
16818
|
if (found < 0 || !Number.isFinite(s)) return null;
|
|
16819
|
+
if (report) report.s = s;
|
|
16713
16820
|
const exactPos = 1 - s;
|
|
16714
16821
|
const pos = quantum && quantum > 0 ? quantisedPosition(exactPos, quantum) : exactPos;
|
|
16715
16822
|
if (shape.preset && shape.preset.positions.length > 0) {
|
|
@@ -17306,19 +17413,31 @@ function applyTint(src, hue, amount) {
|
|
|
17306
17413
|
var TINT_FULL = 254;
|
|
17307
17414
|
function applyRedEyeCorrection(src, width, height, areas) {
|
|
17308
17415
|
const out = new Uint8ClampedArray(src);
|
|
17309
|
-
const carry = { x: 0, y: 0 };
|
|
17416
|
+
const carry = { x: 0, y: 0, set: false };
|
|
17310
17417
|
for (const a of areas) {
|
|
17311
17418
|
correctRedEyeArea(out, width, clamp(a.left, 0, width), clamp(a.top, 0, height), clamp(a.right, 0, width), clamp(a.bottom, 0, height), carry);
|
|
17312
17419
|
}
|
|
17313
17420
|
return out;
|
|
17314
17421
|
}
|
|
17315
17422
|
var RED_EYE_SECTORS = 60;
|
|
17316
|
-
var
|
|
17317
|
-
|
|
17318
|
-
|
|
17423
|
+
var RED_EYE_LEGACY = {
|
|
17424
|
+
blueWeight: 0.225,
|
|
17425
|
+
pureWeight: 1 / 1.225,
|
|
17426
|
+
carry: 0.81
|
|
17427
|
+
};
|
|
17428
|
+
var RED_EYE_CENTRE_SECTOR = 15;
|
|
17429
|
+
var RED_EYE_BLUE_WEIGHT = 2 / 9;
|
|
17430
|
+
var RED_EYE_PURE_WEIGHT = 1;
|
|
17431
|
+
var RED_EYE_CARRY = 1;
|
|
17432
|
+
function redEyeLuma(g, b) {
|
|
17433
|
+
return Math.floor((9 * g + 2 * b + 5) / 11);
|
|
17434
|
+
}
|
|
17319
17435
|
var RED_EYE_GREEN_SHARE = 5 / 16;
|
|
17320
|
-
var RED_EYE_SPREAD_STEPS = [
|
|
17436
|
+
var RED_EYE_SPREAD_STEPS = [25, 40, 80];
|
|
17321
17437
|
var RED_EYE_STRENGTHS = [0.25, 0.5, 0.661, 0.75];
|
|
17438
|
+
var RED_EYE_HIGHLIGHT_RISE = 40;
|
|
17439
|
+
var RED_EYE_FALLBACK_SLOPE = 0.33;
|
|
17440
|
+
var RED_EYE_HIGHLIGHT_REST = 5;
|
|
17322
17441
|
function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
17323
17442
|
const w = x1 - x0;
|
|
17324
17443
|
const h = y1 - y0;
|
|
@@ -17328,9 +17447,19 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
|
17328
17447
|
}
|
|
17329
17448
|
const redness = new Float64Array(count);
|
|
17330
17449
|
const dark = new Float64Array(count);
|
|
17450
|
+
const lumas = new Int32Array(count);
|
|
17331
17451
|
let sx = 0;
|
|
17332
17452
|
let sy = 0;
|
|
17333
17453
|
let sw = 0;
|
|
17454
|
+
let sxL = 0;
|
|
17455
|
+
let syL = 0;
|
|
17456
|
+
let swL = 0;
|
|
17457
|
+
let redCount = 0;
|
|
17458
|
+
let sx32 = 0;
|
|
17459
|
+
let sy32 = 0;
|
|
17460
|
+
let sw32 = 0;
|
|
17461
|
+
let firstRed = -1;
|
|
17462
|
+
let uniformRed = true;
|
|
17334
17463
|
for (let y = 0; y < h; y++) {
|
|
17335
17464
|
for (let x = 0; x < w; x++) {
|
|
17336
17465
|
const i = ((y0 + y) * stride + x0 + x) * 4;
|
|
@@ -17340,24 +17469,53 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
|
17340
17469
|
const k = y * w + x;
|
|
17341
17470
|
const d = g + RED_EYE_BLUE_WEIGHT * b;
|
|
17342
17471
|
dark[k] = d;
|
|
17472
|
+
const dL = g + RED_EYE_LEGACY.blueWeight * b;
|
|
17473
|
+
const luma = redEyeLuma(g, b);
|
|
17474
|
+
lumas[k] = luma;
|
|
17343
17475
|
const v = r - Math.max(g, b);
|
|
17344
17476
|
if (v > 0) {
|
|
17345
17477
|
redness[k] = v;
|
|
17346
|
-
const weight =
|
|
17478
|
+
const weight = luma >= 1 ? v / luma : RED_EYE_PURE_WEIGHT;
|
|
17347
17479
|
sx += weight * (x + 0.5);
|
|
17348
17480
|
sy += weight * (y + 0.5);
|
|
17349
17481
|
sw += weight;
|
|
17482
|
+
redCount++;
|
|
17483
|
+
const weight32 = Math.fround(weight);
|
|
17484
|
+
sx32 = Math.fround(sx32 + Math.fround(weight32 * Math.fround(x + 0.5)));
|
|
17485
|
+
sy32 = Math.fround(sy32 + Math.fround(weight32 * Math.fround(y + 0.5)));
|
|
17486
|
+
sw32 = Math.fround(sw32 + weight32);
|
|
17487
|
+
const triple = r << 16 | g << 8 | b;
|
|
17488
|
+
if (firstRed < 0) {
|
|
17489
|
+
firstRed = triple;
|
|
17490
|
+
} else if (triple !== firstRed) {
|
|
17491
|
+
uniformRed = false;
|
|
17492
|
+
}
|
|
17493
|
+
const weightL = dL >= 1 ? v / dL : RED_EYE_LEGACY.pureWeight;
|
|
17494
|
+
sxL += weightL * (x + 0.5);
|
|
17495
|
+
syL += weightL * (y + 0.5);
|
|
17496
|
+
swL += weightL;
|
|
17350
17497
|
}
|
|
17351
17498
|
}
|
|
17352
17499
|
}
|
|
17353
17500
|
if (sw === 0) {
|
|
17354
17501
|
return;
|
|
17355
17502
|
}
|
|
17356
|
-
|
|
17357
|
-
|
|
17503
|
+
const snap2 = (v) => Math.round(v * 1e9) / 1e9;
|
|
17504
|
+
const lumaCx = snap2((sx + (carry.set ? carry.x - 0.5 : 0) * RED_EYE_CARRY) / sw);
|
|
17505
|
+
const lumaCy = snap2((sy + (carry.set ? carry.y - 0.5 : 0) * RED_EYE_CARRY) / sw);
|
|
17506
|
+
const onPixelCentre = (v) => Number.isInteger(snap2(v - 0.5));
|
|
17507
|
+
const symmetric = redCount > 1 && (onPixelCentre(lumaCx) || onPixelCentre(lumaCy));
|
|
17508
|
+
const exactCentre = (c, sum32) => !onPixelCentre(c) || Math.fround(sum32 / sw32) === c;
|
|
17509
|
+
const exactSymmetric = symmetric && !uniformRed && !carry.set && exactCentre(lumaCx, sx32) && exactCentre(lumaCy, sy32);
|
|
17510
|
+
const legacyWeights = symmetric && !exactSymmetric;
|
|
17511
|
+
let cx = legacyWeights ? (sxL + RED_EYE_LEGACY.carry * (carry.set ? carry.x : 0)) / swL : lumaCx;
|
|
17512
|
+
let cy = legacyWeights ? (syL + RED_EYE_LEGACY.carry * (carry.set ? carry.y : 0)) / swL : lumaCy;
|
|
17358
17513
|
carry.x = x0 + cx;
|
|
17359
17514
|
carry.y = y0 + cy;
|
|
17360
|
-
|
|
17515
|
+
carry.set = true;
|
|
17516
|
+
let fellBack = false;
|
|
17517
|
+
if (Math.hypot(cx - w / 2, cy - h / 2) >= (w + h) / 6) {
|
|
17518
|
+
fellBack = true;
|
|
17361
17519
|
cx = w / 2;
|
|
17362
17520
|
cy = h / 2;
|
|
17363
17521
|
}
|
|
@@ -17369,10 +17527,17 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
|
17369
17527
|
if (!(radius > 0)) {
|
|
17370
17528
|
return;
|
|
17371
17529
|
}
|
|
17372
|
-
const sorted =
|
|
17373
|
-
const
|
|
17530
|
+
const sorted = Int32Array.from(lumas).sort();
|
|
17531
|
+
const p70 = sorted[Math.floor(0.7 * count)];
|
|
17532
|
+
const spread = p70 - sorted[Math.floor(0.3 * count)];
|
|
17533
|
+
const brightest = sorted[count - 1];
|
|
17534
|
+
const second = count > 1 ? sorted[count - 2] : -1;
|
|
17535
|
+
let highlight = -1;
|
|
17536
|
+
if (brightest > second && brightest - p70 >= RED_EYE_HIGHLIGHT_RISE) {
|
|
17537
|
+
highlight = lumas.indexOf(brightest);
|
|
17538
|
+
}
|
|
17374
17539
|
let level2 = 0;
|
|
17375
|
-
while (level2 < RED_EYE_SPREAD_STEPS.length && spread
|
|
17540
|
+
while (level2 < RED_EYE_SPREAD_STEPS.length && spread > RED_EYE_SPREAD_STEPS[level2]) {
|
|
17376
17541
|
level2++;
|
|
17377
17542
|
}
|
|
17378
17543
|
const strength = RED_EYE_STRENGTHS[level2];
|
|
@@ -17393,7 +17558,7 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
|
17393
17558
|
if (angle < 0) {
|
|
17394
17559
|
angle += 360;
|
|
17395
17560
|
}
|
|
17396
|
-
const s = Math.min(RED_EYE_SECTORS - 1, Math.floor(angle / 6));
|
|
17561
|
+
const s = dx === 0 && dy === 0 ? RED_EYE_CENTRE_SECTOR : dy === 0 ? 0 : Math.min(RED_EYE_SECTORS - 1, Math.floor(angle / 6));
|
|
17397
17562
|
sector[k] = s;
|
|
17398
17563
|
if (d < radius) {
|
|
17399
17564
|
sectorSum[s] += redness[k];
|
|
@@ -17415,8 +17580,13 @@ function correctRedEyeArea(out, stride, x0, y0, x1, y1, carry) {
|
|
|
17415
17580
|
const ratio = meanDark > 0 ? dark[k] / meanDark : 1;
|
|
17416
17581
|
const u = distance[k] / radius;
|
|
17417
17582
|
const darknessFalloff = ratio < 2 ? 0.5 * (1 - ratio) ** 2 : 0;
|
|
17418
|
-
const falloff = Math.max(strength * (1 - u) * (1 - u), darknessFalloff);
|
|
17419
|
-
|
|
17583
|
+
const falloff = Math.max(strength * (1 - u) * (1 - u), darknessFalloff, fellBack ? RED_EYE_FALLBACK_SLOPE * (1 - u) : 0);
|
|
17584
|
+
let rest = (1 - falloff) * mean;
|
|
17585
|
+
if (highlight >= 0) {
|
|
17586
|
+
const hdx = x - highlight % w;
|
|
17587
|
+
const hdy = y - Math.floor(highlight / w);
|
|
17588
|
+
rest = Math.min(rest, RED_EYE_HIGHLIGHT_REST * (hdx * hdx + hdy * hdy));
|
|
17589
|
+
}
|
|
17420
17590
|
if (rest >= v) {
|
|
17421
17591
|
continue;
|
|
17422
17592
|
}
|
|
@@ -19636,13 +19806,13 @@ function recordDeviceFigures(buildPath, device) {
|
|
|
19636
19806
|
const f = fig;
|
|
19637
19807
|
f.curved = true;
|
|
19638
19808
|
const n = f.pts.length;
|
|
19639
|
-
const
|
|
19640
|
-
const p0x =
|
|
19641
|
-
const p0y =
|
|
19809
|
+
const fix2 = (v) => toPlusFix(v);
|
|
19810
|
+
const p0x = fix2(f.pts[n - 2]);
|
|
19811
|
+
const p0y = fix2(f.pts[n - 1]);
|
|
19642
19812
|
f.pts[n - 2] = p0x / 16;
|
|
19643
19813
|
f.pts[n - 1] = p0y / 16;
|
|
19644
19814
|
const out = [];
|
|
19645
|
-
const ctrl = [p0x, p0y,
|
|
19815
|
+
const ctrl = [p0x, p0y, fix2(dx(c1x, c1y)), fix2(dy(c1x, c1y)), fix2(dx(c2x, c2y)), fix2(dy(c2x, c2y)), fix2(dx(x, y)), fix2(dy(x, y))];
|
|
19646
19816
|
flattenBezierGdiplus(ctrl, out);
|
|
19647
19817
|
for (const v of out) {
|
|
19648
19818
|
f.pts.push(v / 16);
|
|
@@ -19916,7 +20086,7 @@ function frame(a, b) {
|
|
|
19916
20086
|
const uy = (b.y - a.y) / len;
|
|
19917
20087
|
return { ux, uy, nx: -uy, ny: ux };
|
|
19918
20088
|
}
|
|
19919
|
-
function joinPoints(p, f1, f2, o, pen) {
|
|
20089
|
+
function joinPoints(p, f1, f2, o, pen, meetInside = false) {
|
|
19920
20090
|
const a = { x: p.x + f1.nx * o, y: p.y + f1.ny * o };
|
|
19921
20091
|
const b = { x: p.x + f2.nx * o, y: p.y + f2.ny * o };
|
|
19922
20092
|
if (o === 0) {
|
|
@@ -19928,6 +20098,11 @@ function joinPoints(p, f1, f2, o, pen) {
|
|
|
19928
20098
|
}
|
|
19929
20099
|
const outer = cross * o < 0;
|
|
19930
20100
|
if (!outer) {
|
|
20101
|
+
if (meetInside) {
|
|
20102
|
+
const den2 = f1.ux * f2.uy - f1.uy * f2.ux;
|
|
20103
|
+
const t2 = ((b.x - a.x) * f2.uy - (b.y - a.y) * f2.ux) / den2;
|
|
20104
|
+
return [{ x: a.x + f1.ux * t2, y: a.y + f1.uy * t2 }];
|
|
20105
|
+
}
|
|
19931
20106
|
return [a, b];
|
|
19932
20107
|
}
|
|
19933
20108
|
if (pen.join === 2) {
|
|
@@ -19995,7 +20170,7 @@ function sidePoints(pts, closed, o, pen) {
|
|
|
19995
20170
|
const inIdx = i - 1 >= 0 ? i - 1 : closed ? segs2 - 1 : -1;
|
|
19996
20171
|
const outIdx = i < segs2 ? i : -1;
|
|
19997
20172
|
if (inIdx >= 0 && outIdx >= 0) {
|
|
19998
|
-
out.push(...joinPoints(pts[i], frames[inIdx], frames[outIdx], o, pen));
|
|
20173
|
+
out.push(...joinPoints(pts[i], frames[inIdx], frames[outIdx], o, pen, closed && !!pen.compound));
|
|
19999
20174
|
} else {
|
|
20000
20175
|
const f = frames[outIdx >= 0 ? outIdx : inIdx];
|
|
20001
20176
|
out.push({ x: pts[i].x + f.nx * o, y: pts[i].y + f.ny * o });
|
|
@@ -20102,6 +20277,50 @@ function signedArea(pts) {
|
|
|
20102
20277
|
}
|
|
20103
20278
|
return a / 2;
|
|
20104
20279
|
}
|
|
20280
|
+
function insidePolygon(pts, q) {
|
|
20281
|
+
let inside = false;
|
|
20282
|
+
for (let i = 0, j = pts.length - 1; i < pts.length; j = i++) {
|
|
20283
|
+
const a = pts[i];
|
|
20284
|
+
const b = pts[j];
|
|
20285
|
+
if (a.y > q.y !== b.y > q.y && q.x < (b.x - a.x) * (q.y - a.y) / (b.y - a.y) + a.x) {
|
|
20286
|
+
inside = !inside;
|
|
20287
|
+
}
|
|
20288
|
+
}
|
|
20289
|
+
return inside;
|
|
20290
|
+
}
|
|
20291
|
+
function insetCollapses(pts, d) {
|
|
20292
|
+
const sign = signedArea(pts) > 0 ? 1 : -1;
|
|
20293
|
+
const n = pts.length;
|
|
20294
|
+
const frames = Array.from({ length: n }, (_, i) => frame(pts[i], pts[(i + 1) % n]));
|
|
20295
|
+
const moved = pts.map((v, i) => {
|
|
20296
|
+
const f1 = frames[(i + n - 1) % n];
|
|
20297
|
+
const f2 = frames[i];
|
|
20298
|
+
const n1x = f1.nx * sign, n1y = f1.ny * sign, n2x = f2.nx * sign, n2y = f2.ny * sign;
|
|
20299
|
+
const k = 1 + n1x * n2x + n1y * n2y;
|
|
20300
|
+
return k < 1e-9 ? { x: v.x + n1x * d, y: v.y + n1y * d } : { x: v.x + (n1x + n2x) * d / k, y: v.y + (n1y + n2y) * d / k };
|
|
20301
|
+
});
|
|
20302
|
+
return Math.sign(signedArea(moved)) !== sign || moved.some((q) => !insidePolygon(pts, q));
|
|
20303
|
+
}
|
|
20304
|
+
function innerBoundary(pts, d, pen) {
|
|
20305
|
+
const sign = signedArea(pts) > 0 ? 1 : -1;
|
|
20306
|
+
const n = pts.length;
|
|
20307
|
+
const frames = Array.from({ length: n }, (_, i) => frame(pts[i], pts[(i + 1) % n]));
|
|
20308
|
+
const out = [];
|
|
20309
|
+
for (let i = 0; i < n; i++) {
|
|
20310
|
+
const f1 = frames[(i + n - 1) % n];
|
|
20311
|
+
const f2 = frames[i];
|
|
20312
|
+
const o = sign * d;
|
|
20313
|
+
const cross = f1.ux * f2.uy - f1.uy * f2.ux;
|
|
20314
|
+
if (cross * o < 0) {
|
|
20315
|
+
out.push(...joinPoints(pts[i], f1, f2, o, pen));
|
|
20316
|
+
} else {
|
|
20317
|
+
const n1x = f1.nx * sign, n1y = f1.ny * sign, n2x = f2.nx * sign, n2y = f2.ny * sign;
|
|
20318
|
+
const k = 1 + n1x * n2x + n1y * n2y;
|
|
20319
|
+
out.push(k < 1e-9 ? { x: pts[i].x + n1x * d, y: pts[i].y + n1y * d } : { x: pts[i].x + (n1x + n2x) * d / k, y: pts[i].y + (n1y + n2y) * d / k });
|
|
20320
|
+
}
|
|
20321
|
+
}
|
|
20322
|
+
return out;
|
|
20323
|
+
}
|
|
20105
20324
|
function widenFigures(figures, pen) {
|
|
20106
20325
|
const polys = [];
|
|
20107
20326
|
const h = pen.half;
|
|
@@ -20113,6 +20332,13 @@ function widenFigures(figures, pen) {
|
|
|
20113
20332
|
const closed = fig.closed && pts.length > 2;
|
|
20114
20333
|
let lo = -h;
|
|
20115
20334
|
let hi = h;
|
|
20335
|
+
if (pen.inset && closed && !pen.dash && !pen.compound) {
|
|
20336
|
+
polys.push(pts.slice());
|
|
20337
|
+
if (!insetCollapses(pts, 2 * h)) {
|
|
20338
|
+
polys.push(innerBoundary(pts, 2 * h, pen).reverse());
|
|
20339
|
+
}
|
|
20340
|
+
continue;
|
|
20341
|
+
}
|
|
20116
20342
|
if (pen.inset && closed) {
|
|
20117
20343
|
if (signedArea(pts) > 0) {
|
|
20118
20344
|
lo = 0;
|
|
@@ -21022,6 +21248,106 @@ async function preDecodeMetafileCaches(view, depth = 0) {
|
|
|
21022
21248
|
};
|
|
21023
21249
|
}
|
|
21024
21250
|
|
|
21251
|
+
// src/emf-plus-hq-cubic-weights.ts
|
|
21252
|
+
var HQ_CUBIC_HALF_TABLE = [
|
|
21253
|
+
[-1675, 5953, 56660, 6337, -1739],
|
|
21254
|
+
[-1612, 5575, 56650, 6727, -1804],
|
|
21255
|
+
[-1550, 5203, 56630, 7123, -1870],
|
|
21256
|
+
[-1489, 4837, 56600, 7525, -1937],
|
|
21257
|
+
[-1429, 4477, 56561, 7931, -2004],
|
|
21258
|
+
[-1371, 4125, 56510, 8345, -2073],
|
|
21259
|
+
[-1313, 3777, 56451, 8763, -2142],
|
|
21260
|
+
[-1257, 3437, 56381, 9187, -2212],
|
|
21261
|
+
[-1202, 3103, 56301, 9617, -2283],
|
|
21262
|
+
[-1148, 2775, 56211, 10053, -2355],
|
|
21263
|
+
[-1095, 2453, 56112, 10493, -2427],
|
|
21264
|
+
[-1044, 2139, 56002, 10939, -2500],
|
|
21265
|
+
[-993, 1829, 55884, 11389, -2573],
|
|
21266
|
+
[-945, 1529, 55754, 11845, -2647],
|
|
21267
|
+
[-897, 1233, 55616, 12305, -2721],
|
|
21268
|
+
[-851, 945, 55467, 12771, -2796],
|
|
21269
|
+
[-806, 663, 55309, 13241, -2871],
|
|
21270
|
+
[-762, 387, 55142, 13715, -2946],
|
|
21271
|
+
[-720, 119, 54964, 14195, -3022],
|
|
21272
|
+
[-679, -143, 54778, 14677, -3097],
|
|
21273
|
+
[-639, -399, 54582, 15165, -3173],
|
|
21274
|
+
[-600, -649, 54377, 15657, -3249],
|
|
21275
|
+
[-563, -891, 54162, 16153, -3325],
|
|
21276
|
+
[-528, -1125, 53937, 16653, -3401],
|
|
21277
|
+
[-493, -1355, 53705, 17155, -3476],
|
|
21278
|
+
[-460, -1577, 53462, 17663, -3552],
|
|
21279
|
+
[-429, -1791, 53210, 18173, -3627],
|
|
21280
|
+
[-398, -2001, 52950, 18687, -3702],
|
|
21281
|
+
[-369, -2203, 52681, 19203, -3776],
|
|
21282
|
+
[-341, -2399, 52403, 19723, -3850],
|
|
21283
|
+
[-315, -2587, 52116, 20245, -3923],
|
|
21284
|
+
[-289, -2771, 51821, 20771, -3996],
|
|
21285
|
+
[-265, -2947, 51517, 21299, -4068],
|
|
21286
|
+
[-243, -3115, 51204, 21829, -4139],
|
|
21287
|
+
[-221, -3279, 50884, 22361, -4209],
|
|
21288
|
+
[-201, -3435, 50554, 22897, -4279],
|
|
21289
|
+
[-182, -3585, 50217, 23433, -4347],
|
|
21290
|
+
[-164, -3729, 49872, 23971, -4414],
|
|
21291
|
+
[-147, -3867, 49518, 24513, -4481],
|
|
21292
|
+
[-131, -3999, 49158, 25053, -4545],
|
|
21293
|
+
[-117, -4123, 48788, 25597, -4609],
|
|
21294
|
+
[-103, -4243, 48412, 26141, -4671],
|
|
21295
|
+
[-90, -4357, 48029, 26685, -4731],
|
|
21296
|
+
[-79, -4463, 47637, 27231, -4790],
|
|
21297
|
+
[-68, -4565, 47239, 27777, -4847],
|
|
21298
|
+
[-59, -4659, 46833, 28323, -4902],
|
|
21299
|
+
[-50, -4749, 46421, 28869, -4955],
|
|
21300
|
+
[-42, -4833, 46002, 29415, -5006],
|
|
21301
|
+
[-35, -4911, 45576, 29961, -5055],
|
|
21302
|
+
[-29, -4983, 45143, 30507, -5102],
|
|
21303
|
+
[-24, -5049, 44704, 31051, -5146],
|
|
21304
|
+
[-19, -5111, 44259, 31595, -5188],
|
|
21305
|
+
[-15, -5167, 43807, 32139, -5228],
|
|
21306
|
+
[-11, -5219, 43351, 32679, -5264],
|
|
21307
|
+
[-8, -5265, 42888, 33219, -5298],
|
|
21308
|
+
[-6, -5305, 42419, 33757, -5329],
|
|
21309
|
+
[-4, -5341, 41944, 34295, -5358],
|
|
21310
|
+
[-3, -5371, 41464, 34829, -5383],
|
|
21311
|
+
[-2, -5397, 40980, 35359, -5404],
|
|
21312
|
+
[-1, -5419, 40490, 35889, -5423],
|
|
21313
|
+
[0, -5437, 39996, 36415, -5438],
|
|
21314
|
+
[0, -5449, 39497, 36937, -5449],
|
|
21315
|
+
[0, -5457, 38993, 37457, -5457],
|
|
21316
|
+
[0, -5461, 38485, 37973, -5461]
|
|
21317
|
+
];
|
|
21318
|
+
function hqCubicBinWeights(bin) {
|
|
21319
|
+
if (bin < 64) {
|
|
21320
|
+
return { first: -2, weights: HQ_CUBIC_HALF_TABLE[bin] };
|
|
21321
|
+
}
|
|
21322
|
+
return { first: -1, weights: HQ_CUBIC_HALF_TABLE[127 - bin].slice().reverse() };
|
|
21323
|
+
}
|
|
21324
|
+
var HQ_CUBIC_CDF = (() => {
|
|
21325
|
+
const cdf = new Int32Array(512).fill(Number.NaN);
|
|
21326
|
+
for (let bin = 0; bin < 128; bin++) {
|
|
21327
|
+
const { first, weights } = hqCubicBinWeights(bin);
|
|
21328
|
+
let acc = -32768;
|
|
21329
|
+
for (let i = 0; i <= 5; i++) {
|
|
21330
|
+
const m = 128 * (first + i) - 64 - bin - 1;
|
|
21331
|
+
if (m >= -256 && m <= 255) {
|
|
21332
|
+
cdf[m + 256] = acc;
|
|
21333
|
+
}
|
|
21334
|
+
if (i < 5) {
|
|
21335
|
+
acc += weights[i];
|
|
21336
|
+
}
|
|
21337
|
+
}
|
|
21338
|
+
}
|
|
21339
|
+
return cdf;
|
|
21340
|
+
})();
|
|
21341
|
+
function hqCubicCdf(m) {
|
|
21342
|
+
if (m < -256) {
|
|
21343
|
+
return -32768;
|
|
21344
|
+
}
|
|
21345
|
+
if (m > 255) {
|
|
21346
|
+
return 32768;
|
|
21347
|
+
}
|
|
21348
|
+
return HQ_CUBIC_CDF[m + 256];
|
|
21349
|
+
}
|
|
21350
|
+
|
|
21025
21351
|
// src/emf-plus-image-resample.ts
|
|
21026
21352
|
var INTERPOLATION_KERNELS = {
|
|
21027
21353
|
0: "bilinear",
|
|
@@ -21074,6 +21400,20 @@ function snapToDeviceGrid(spec) {
|
|
|
21074
21400
|
const [a, b, c, d] = m;
|
|
21075
21401
|
return [a, b, c, d, ox - a * spec.srcX - c * spec.srcY, oy - b * spec.srcX - d * spec.srcY];
|
|
21076
21402
|
}
|
|
21403
|
+
function snapOriginKeepCorners(spec) {
|
|
21404
|
+
const m = spec.toDevice;
|
|
21405
|
+
const map = (u, v) => [m[0] * u + m[2] * v + m[4], m[1] * u + m[3] * v + m[5]];
|
|
21406
|
+
const [rx, ry] = map(spec.srcX, spec.srcY);
|
|
21407
|
+
const ox = Math.round(rx * SUBPIXEL_GRID) / SUBPIXEL_GRID;
|
|
21408
|
+
const oy = Math.round(ry * SUBPIXEL_GRID) / SUBPIXEL_GRID;
|
|
21409
|
+
const [ux, uy] = map(spec.srcX + spec.srcW, spec.srcY);
|
|
21410
|
+
const [vx, vy] = map(spec.srcX, spec.srcY + spec.srcH);
|
|
21411
|
+
const a = (ux - ox) / spec.srcW;
|
|
21412
|
+
const b = (uy - oy) / spec.srcW;
|
|
21413
|
+
const c = (vx - ox) / spec.srcH;
|
|
21414
|
+
const d = (vy - oy) / spec.srcH;
|
|
21415
|
+
return [a, b, c, d, ox - a * spec.srcX - c * spec.srcY, oy - b * spec.srcX - d * spec.srcY];
|
|
21416
|
+
}
|
|
21077
21417
|
function cubicKernel(t, a) {
|
|
21078
21418
|
const x = Math.abs(t);
|
|
21079
21419
|
if (x < 1) {
|
|
@@ -21100,18 +21440,6 @@ function cubicIntegral(t, a) {
|
|
|
21100
21440
|
}
|
|
21101
21441
|
return Math.sign(t) * v;
|
|
21102
21442
|
}
|
|
21103
|
-
var FAR_FADE = [1, 1, 0.985, 0.95, 0.91, 0.85, 0.8, 0.745, 0.69, 0.63, 0.56, 0.5, 0.43, 0.35, 0.28, 0.22, 0.16, 0.11, 0.065, 0.03, 0];
|
|
21104
|
-
function fadeAt(d, bilinear) {
|
|
21105
|
-
if (d >= 1) {
|
|
21106
|
-
return 0;
|
|
21107
|
-
}
|
|
21108
|
-
if (bilinear) {
|
|
21109
|
-
return 1 - Math.max(0, d);
|
|
21110
|
-
}
|
|
21111
|
-
const x = Math.max(0, d) * 20;
|
|
21112
|
-
const i = Math.floor(x);
|
|
21113
|
-
return FAR_FADE[i] + (FAR_FADE[i + 1] - FAR_FADE[i]) * (x - i);
|
|
21114
|
-
}
|
|
21115
21443
|
function ceilExtent(len) {
|
|
21116
21444
|
return Math.ceil(len * (1 - 15e-8));
|
|
21117
21445
|
}
|
|
@@ -21119,6 +21447,17 @@ function nearSourceExtent(deviceLen, srcLen) {
|
|
|
21119
21447
|
const d = ceilExtent(deviceLen) - srcLen;
|
|
21120
21448
|
return d >= -1 && d <= 1;
|
|
21121
21449
|
}
|
|
21450
|
+
function unitCopyOffset(t, other, spec) {
|
|
21451
|
+
const f = t - Math.round(t);
|
|
21452
|
+
if (f > -1 / 64 + 1e-9) {
|
|
21453
|
+
return f <= 1 / 64 + 1e-9;
|
|
21454
|
+
}
|
|
21455
|
+
if (Math.abs(f + 1 / 64) > 1e-9 || !isPowerOfTwo(spec.srcW) || !isPowerOfTwo(spec.srcH)) {
|
|
21456
|
+
return false;
|
|
21457
|
+
}
|
|
21458
|
+
const g = (other - Math.round(other)) * 128;
|
|
21459
|
+
return spec.srcW * spec.srcH * Math.max(spec.srcW, spec.srcH) <= 256 || Math.abs(g - Math.round(g)) < 1e-9;
|
|
21460
|
+
}
|
|
21122
21461
|
var BICUBIC_A = -0.5;
|
|
21123
21462
|
var HQ_BICUBIC_A = -1;
|
|
21124
21463
|
function axisFilter(kernel, scale, copy) {
|
|
@@ -21238,6 +21577,9 @@ function resampleImage(rgba, width, height, spec, surface, options2 = {}) {
|
|
|
21238
21577
|
}
|
|
21239
21578
|
return resampleImage(grown, width + 1, height, { ...spec, rightHalo: void 0 }, surface);
|
|
21240
21579
|
}
|
|
21580
|
+
if (spec.wrap === "clamp" && (spec.clampArgb ?? 0) >>> 24 === 0 && (spec.kernel === "hq-bicubic" || spec.kernel === "hq-bilinear")) {
|
|
21581
|
+
return resampleImage(rgba, width, height, { ...spec, wrap: void 0, clampArgb: void 0 }, surface, options2);
|
|
21582
|
+
}
|
|
21241
21583
|
if (spec.kernel === "nearest" && !spec.wrap) {
|
|
21242
21584
|
return resampleNearest(rgba, width, height, spec, surface);
|
|
21243
21585
|
}
|
|
@@ -21248,32 +21590,21 @@ function resampleImage(rgba, width, height, spec, surface, options2 = {}) {
|
|
|
21248
21590
|
m = [m[0], 0, 0, m[3], m[4], m[5]];
|
|
21249
21591
|
}
|
|
21250
21592
|
const axisAligned = m[1] === 0 && m[2] === 0;
|
|
21593
|
+
if (hq && !axisAligned && !keepOrigin) {
|
|
21594
|
+
m = snapOriginKeepCorners(spec);
|
|
21595
|
+
}
|
|
21251
21596
|
let plainRotated = plainRotatedPass;
|
|
21252
|
-
const unitBicubicCopy = kernel === "bicubic" && axisAligned && !spec.halfPixelOffset && m[0] === 1 && m[3] === 1 &&
|
|
21253
|
-
let farFade = false;
|
|
21597
|
+
const unitBicubicCopy = kernel === "bicubic" && axisAligned && !spec.halfPixelOffset && m[0] === 1 && m[3] === 1 && unitCopyOffset(m[4], m[5], spec) && unitCopyOffset(m[5], m[4], spec);
|
|
21254
21598
|
let shiftX = 0;
|
|
21255
21599
|
let shiftY = 0;
|
|
21256
21600
|
if (hq && !axisAligned) {
|
|
21257
21601
|
const extentU = Math.hypot(m[0], m[1]) * spec.srcW;
|
|
21258
21602
|
const extentV = Math.hypot(m[2], m[3]) * spec.srcH;
|
|
21259
21603
|
const near = nearSourceExtent(extentU, spec.srcW) || nearSourceExtent(extentV, spec.srcH);
|
|
21260
|
-
|
|
21261
|
-
return resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel, near);
|
|
21262
|
-
} else if (near) {
|
|
21263
|
-
kernel = kernel === "hq-bicubic" ? "bicubic" : "bilinear";
|
|
21264
|
-
plainRotated = true;
|
|
21265
|
-
} else {
|
|
21266
|
-
farFade = true;
|
|
21267
|
-
if (spec.halfPixelOffset) {
|
|
21268
|
-
const lu = Math.hypot(m[0], m[1]);
|
|
21269
|
-
const lv = Math.hypot(m[2], m[3]);
|
|
21270
|
-
shiftX = 0.5 * m[0] / lu + 0.5 * m[2] / lv;
|
|
21271
|
-
shiftY = 0.5 * m[1] / lu + 0.5 * m[3] / lv;
|
|
21272
|
-
}
|
|
21273
|
-
}
|
|
21604
|
+
return resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel, near);
|
|
21274
21605
|
}
|
|
21275
21606
|
const integerBicubic = kernel === "bicubic" && (axisAligned || plainRotated);
|
|
21276
|
-
if (hq && axisAligned && !
|
|
21607
|
+
if (hq && axisAligned && !premultSource) {
|
|
21277
21608
|
const phased = resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut);
|
|
21278
21609
|
if (phased !== void 0) {
|
|
21279
21610
|
return phased;
|
|
@@ -21334,8 +21665,8 @@ function resampleImage(rgba, width, height, spec, surface, options2 = {}) {
|
|
|
21334
21665
|
const vMax = spec.srcY + spec.srcH;
|
|
21335
21666
|
const wu = [];
|
|
21336
21667
|
const wv = [];
|
|
21337
|
-
|
|
21338
|
-
|
|
21668
|
+
Math.hypot(inv2[0], inv2[2]);
|
|
21669
|
+
Math.hypot(inv2[1], inv2[3]);
|
|
21339
21670
|
const c = spec.clampArgb ?? 0;
|
|
21340
21671
|
const edge = {
|
|
21341
21672
|
wrap: spec.wrap,
|
|
@@ -21391,18 +21722,6 @@ function resampleImage(rgba, width, height, spec, surface, options2 = {}) {
|
|
|
21391
21722
|
return blendSeparable(rgba, width, box, iu0, wu, iv0, wv, kernel === "bicubic", edge, integerBicubic, premultSource);
|
|
21392
21723
|
};
|
|
21393
21724
|
let [r, g, b, a] = sampleAt(u, v);
|
|
21394
|
-
if (farFade && !spec.wrap && a > 0) {
|
|
21395
|
-
const du = (uMax - u) / gradU;
|
|
21396
|
-
const dv = (vMax - v) / gradV;
|
|
21397
|
-
const k = 1 - (du < 1 ? fadeAt(du, kernel === "hq-bilinear") * (sampleAt(uMax, v)[3] / a) : 0) - (dv < 1 ? fadeAt(dv, kernel === "hq-bilinear") * (sampleAt(u, vMax)[3] / a) : 0);
|
|
21398
|
-
if (k < 1) {
|
|
21399
|
-
const f = Math.max(0, k);
|
|
21400
|
-
r *= f;
|
|
21401
|
-
g *= f;
|
|
21402
|
-
b *= f;
|
|
21403
|
-
a *= f;
|
|
21404
|
-
}
|
|
21405
|
-
}
|
|
21406
21725
|
if (a <= 0) {
|
|
21407
21726
|
continue;
|
|
21408
21727
|
}
|
|
@@ -21430,21 +21749,74 @@ function resampleImage(rgba, width, height, spec, surface, options2 = {}) {
|
|
|
21430
21749
|
return { x: bx0, y: by0, w, h, rgba: out };
|
|
21431
21750
|
}
|
|
21432
21751
|
var HQ_PHASES = 128;
|
|
21752
|
+
function isPowerOfTwo(v) {
|
|
21753
|
+
return Number.isInteger(v) && v > 0 && (v & v - 1) === 0;
|
|
21754
|
+
}
|
|
21755
|
+
function mirroredUnitIsExact(spec) {
|
|
21756
|
+
return !spec.pointsForm || isPowerOfTwo(spec.srcW) && isPowerOfTwo(spec.srcH);
|
|
21757
|
+
}
|
|
21758
|
+
function mirroredBias(spec, scale, fractionalEdge) {
|
|
21759
|
+
if (mirroredUnitIsExact(spec)) {
|
|
21760
|
+
return scale === 1 ? -(fractionalEdge ? 2 : 1) * 65536 + (spec.kernel === "hq-bicubic" ? 1 : 0) : 0;
|
|
21761
|
+
}
|
|
21762
|
+
return scale <= 1 ? 1 : 0;
|
|
21763
|
+
}
|
|
21764
|
+
function hqStep(scale) {
|
|
21765
|
+
return Math.round(65536 / scale);
|
|
21766
|
+
}
|
|
21767
|
+
function hqTentCdf(j) {
|
|
21768
|
+
if (j <= -128) {
|
|
21769
|
+
return -32768;
|
|
21770
|
+
}
|
|
21771
|
+
if (j >= 128) {
|
|
21772
|
+
return 32768;
|
|
21773
|
+
}
|
|
21774
|
+
return j < 0 ? -(512 * -j - 2 * j * j) : 512 * j - 2 * j * j;
|
|
21775
|
+
}
|
|
21776
|
+
function hqReductionTaps(cubic, scale, step, position, origin, from, to) {
|
|
21777
|
+
const taps = [];
|
|
21778
|
+
const s = Math.fround(scale);
|
|
21779
|
+
const radius = (cubic ? 2 : 1) * (step / 65536) + 1;
|
|
21780
|
+
for (let k = from; k <= to; k++) {
|
|
21781
|
+
const p = position(k);
|
|
21782
|
+
const centre = origin + p / 65536;
|
|
21783
|
+
const first = Math.ceil(centre - radius);
|
|
21784
|
+
const last = Math.floor(centre + radius);
|
|
21785
|
+
const weights = [];
|
|
21786
|
+
let prev = Number.NaN;
|
|
21787
|
+
for (let t = first; t <= last + 1; t++) {
|
|
21788
|
+
const q = 128 * s * (t - 0.5 - origin - p / 65536);
|
|
21789
|
+
const edge = Math.floor(q);
|
|
21790
|
+
const cdf = cubic ? hqCubicCdf(edge) : hqTentCdf(edge);
|
|
21791
|
+
if (t > first) {
|
|
21792
|
+
weights.push((cdf - prev) / 65536);
|
|
21793
|
+
}
|
|
21794
|
+
prev = cdf;
|
|
21795
|
+
}
|
|
21796
|
+
taps.push({ first, weights });
|
|
21797
|
+
}
|
|
21798
|
+
return taps;
|
|
21799
|
+
}
|
|
21433
21800
|
function resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut) {
|
|
21434
21801
|
const kernel = spec.kernel;
|
|
21435
|
-
const
|
|
21802
|
+
const mirrorU = m[0] < 0;
|
|
21803
|
+
const scaleU = Math.abs(m[0]);
|
|
21436
21804
|
const scaleV = m[3];
|
|
21437
|
-
if (!(scaleU
|
|
21805
|
+
if (!(scaleU > 0 && scaleV > 0) || spec.rightHalo) {
|
|
21438
21806
|
return void 0;
|
|
21439
21807
|
}
|
|
21440
21808
|
const integral = (v) => Math.abs(v - Math.round(v)) < 1e-9;
|
|
21441
|
-
if (scaleU === 1 && scaleV === 1 && integral(m[4]) && integral(m[5])) {
|
|
21809
|
+
if (scaleU === 1 && scaleV === 1 && !mirrorU && integral(m[4]) && integral(m[5])) {
|
|
21442
21810
|
return void 0;
|
|
21443
21811
|
}
|
|
21812
|
+
const unitMirror = mirrorU && scaleU === 1;
|
|
21444
21813
|
const shift = spec.halfPixelOffset ? 0.5 : 0;
|
|
21445
|
-
const
|
|
21814
|
+
const edge0 = m[0] * spec.srcX + m[4] - shift;
|
|
21815
|
+
const edge1 = edge0 + m[0] * spec.srcW;
|
|
21816
|
+
const rawLeft = spec.toDevice[0] * (spec.srcX + spec.srcW) + spec.toDevice[4] - shift;
|
|
21817
|
+
const left = mirrorU ? Math.round(rawLeft * SUBPIXEL_GRID) / SUBPIXEL_GRID : Math.min(edge0, edge1);
|
|
21446
21818
|
const top = m[3] * spec.srcY + m[5] - shift;
|
|
21447
|
-
const right = left +
|
|
21819
|
+
const right = mirrorU ? left + scaleU * spec.srcW : Math.max(edge0, edge1);
|
|
21448
21820
|
const bottom = top + m[3] * spec.srcH;
|
|
21449
21821
|
const xFirst = Math.ceil(left - COVERAGE_NUDGE_X);
|
|
21450
21822
|
const xLast = Math.ceil(right - COVERAGE_NUDGE_X) - 1;
|
|
@@ -21464,43 +21836,86 @@ function resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut
|
|
|
21464
21836
|
}
|
|
21465
21837
|
const cubic = kernel === "hq-bicubic";
|
|
21466
21838
|
const bin = cubic ? 0.5 : 1;
|
|
21467
|
-
const stepU =
|
|
21468
|
-
const stepV =
|
|
21469
|
-
const
|
|
21839
|
+
const stepU = hqStep(scaleU);
|
|
21840
|
+
const stepV = hqStep(scaleV);
|
|
21841
|
+
const rawLeftEdge = mirrorU ? rawLeft : spec.toDevice[0] * spec.srcX + spec.toDevice[4] - shift;
|
|
21842
|
+
const dxRaw = xFirst - rawLeftEdge;
|
|
21843
|
+
const dx = dxRaw < 1e-5 ? 0 : dxRaw;
|
|
21470
21844
|
const dy = Math.max(0, yFirst - top);
|
|
21471
|
-
|
|
21845
|
+
if (mirrorU && (spec.halfPixelOffset || !integral(spec.srcX) || !integral(spec.srcW))) {
|
|
21846
|
+
return void 0;
|
|
21847
|
+
}
|
|
21848
|
+
const mirroredPixels = xLast - xFirst + 1 + dx;
|
|
21849
|
+
const offsetU = !mirrorU && dx > 1e-9 ? Math.round((1 - dx) * stepU) : 0;
|
|
21472
21850
|
const offsetV = dy > 1e-9 ? Math.round(dy * stepV) : 0;
|
|
21473
21851
|
const filterU = axisFilter(kernel, scaleU, false);
|
|
21474
21852
|
const filterV = axisFilter(kernel, scaleV, false);
|
|
21475
|
-
const tapsFor = (filter, step, offset, origin, from, to) => {
|
|
21853
|
+
const tapsFor = (filter, step, offset, origin, from, to, scale, mirror2 = false) => {
|
|
21476
21854
|
const taps = [];
|
|
21855
|
+
const farBias = ((step & step - 1) === 0 ? 0 : Math.round(spec.srcW / 170)) + (mirror2 ? mirroredBias(spec, scale, dx > 1e-9) : 0);
|
|
21856
|
+
const position = (k) => mirror2 ? Math.round((mirroredPixels - k) * step) + farBias : k * step + offset;
|
|
21857
|
+
if (mirror2 && unitMirror && dx <= 1e-9 && mirroredUnitIsExact(spec)) {
|
|
21858
|
+
for (let k = from; k <= to; k++) {
|
|
21859
|
+
taps.push({ first: Math.round(origin + position(k) / 65536), weights: [1] });
|
|
21860
|
+
}
|
|
21861
|
+
return taps;
|
|
21862
|
+
}
|
|
21863
|
+
const originBins = origin * HQ_PHASES;
|
|
21864
|
+
const wholeBins = Math.abs(originBins - Math.round(originBins)) < 1e-6;
|
|
21865
|
+
if (scale < 1 && wholeBins) {
|
|
21866
|
+
return hqReductionTaps(cubic, scale, step, position, origin, from, to);
|
|
21867
|
+
}
|
|
21868
|
+
const tabulated = cubic && wholeBins;
|
|
21477
21869
|
for (let k = from; k <= to; k++) {
|
|
21478
|
-
const phase = Math.floor((k
|
|
21479
|
-
|
|
21480
|
-
|
|
21481
|
-
|
|
21870
|
+
const phase = Math.floor((position(k) - 1) / (65536 / HQ_PHASES));
|
|
21871
|
+
if (tabulated) {
|
|
21872
|
+
const total = Math.round(originBins) + phase;
|
|
21873
|
+
const bins = hqCubicBinWeights((total % HQ_PHASES + HQ_PHASES) % HQ_PHASES);
|
|
21874
|
+
taps.push({
|
|
21875
|
+
first: Math.floor(total / HQ_PHASES) + bins.first,
|
|
21876
|
+
weights: bins.weights.map((w2) => w2 / 65536)
|
|
21877
|
+
});
|
|
21878
|
+
continue;
|
|
21879
|
+
}
|
|
21880
|
+
const c2 = origin + (phase + bin) / HQ_PHASES;
|
|
21881
|
+
const first = Math.ceil(c2 - filter.radius);
|
|
21882
|
+
const last = Math.floor(c2 + filter.radius);
|
|
21482
21883
|
const weights = [];
|
|
21483
21884
|
for (let t = first; t <= last; t++) {
|
|
21484
|
-
weights.push(filter.weight(t,
|
|
21885
|
+
weights.push(filter.weight(t, c2));
|
|
21485
21886
|
}
|
|
21486
21887
|
taps.push({ first, weights });
|
|
21487
21888
|
}
|
|
21488
21889
|
return taps;
|
|
21489
21890
|
};
|
|
21490
|
-
const colTaps = tapsFor(filterU, stepU, offsetU, spec.srcX, cx0 - xFirst, cx1 - xFirst);
|
|
21491
|
-
const rowTaps = tapsFor(filterV, stepV, offsetV, spec.srcY, cy0 - yFirst, cy1 - yFirst);
|
|
21891
|
+
const colTaps = tapsFor(filterU, stepU, offsetU, spec.srcX, cx0 - xFirst, cx1 - xFirst, scaleU, mirrorU);
|
|
21892
|
+
const rowTaps = tapsFor(filterV, stepV, offsetV, spec.srcY, cy0 - yFirst, cy1 - yFirst, scaleV);
|
|
21492
21893
|
let rowMin = Infinity;
|
|
21493
21894
|
let rowMax = -Infinity;
|
|
21494
21895
|
for (const t of rowTaps) {
|
|
21495
21896
|
rowMin = Math.min(rowMin, t.first);
|
|
21496
21897
|
rowMax = Math.max(rowMax, t.first + t.weights.length - 1);
|
|
21497
21898
|
}
|
|
21498
|
-
|
|
21499
|
-
|
|
21899
|
+
const c = spec.clampArgb ?? 0;
|
|
21900
|
+
const edge = spec.wrap ? {
|
|
21901
|
+
wrap: spec.wrap,
|
|
21902
|
+
clamp: [c >>> 16 & 255, c >>> 8 & 255, c & 255, c >>> 24 & 255],
|
|
21903
|
+
mirrorX: spec.wrap === "tile-flip-x" || spec.wrap === "tile-flip-xy",
|
|
21904
|
+
mirrorY: spec.wrap === "tile-flip-y" || spec.wrap === "tile-flip-xy"
|
|
21905
|
+
} : null;
|
|
21906
|
+
if (!edge) {
|
|
21907
|
+
rowMin = Math.max(0, rowMin);
|
|
21908
|
+
rowMax = Math.min(height - 1, rowMax);
|
|
21909
|
+
}
|
|
21500
21910
|
const rows = Math.max(0, rowMax - rowMin + 1);
|
|
21911
|
+
const rowMargin = edge || Math.abs(scaleV - 1) < 1e-9 ? Infinity : Math.ceil((cubic ? 2 : 1) / Math.min(1, scaleV));
|
|
21501
21912
|
const inter = new Uint8Array(rows * w * 4);
|
|
21502
21913
|
for (let r = 0; r < rows; r++) {
|
|
21503
|
-
const
|
|
21914
|
+
const rowTexel = edge ? wrapTap(rowMin + r, 0, height, edge.mirrorY, edge) : rowMin + r;
|
|
21915
|
+
if (rowTexel === OUTSIDE_TRANSPARENT || rowTexel < spec.srcY - rowMargin || rowTexel > spec.srcY + spec.srcH + rowMargin - 1) {
|
|
21916
|
+
continue;
|
|
21917
|
+
}
|
|
21918
|
+
const srcRow = rowTexel * width;
|
|
21504
21919
|
for (let i = 0; i < w; i++) {
|
|
21505
21920
|
const t = colTaps[i];
|
|
21506
21921
|
let pr = 0;
|
|
@@ -21508,19 +21923,30 @@ function resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut
|
|
|
21508
21923
|
let pb = 0;
|
|
21509
21924
|
let pa = 0;
|
|
21510
21925
|
for (let q = 0; q < t.weights.length; q++) {
|
|
21511
|
-
|
|
21512
|
-
|
|
21926
|
+
let tx = t.first + q;
|
|
21927
|
+
let px = rgba;
|
|
21928
|
+
let o = 0;
|
|
21929
|
+
if (edge) {
|
|
21930
|
+
tx = wrapTap(tx, 0, width, edge.mirrorX, edge);
|
|
21931
|
+
if (tx === OUTSIDE_TRANSPARENT) {
|
|
21932
|
+
continue;
|
|
21933
|
+
}
|
|
21934
|
+
} else if (tx < 0 || tx >= width) {
|
|
21513
21935
|
continue;
|
|
21514
21936
|
}
|
|
21515
|
-
|
|
21516
|
-
|
|
21937
|
+
if (tx === OUTSIDE_CLAMP || rowTexel === OUTSIDE_CLAMP) {
|
|
21938
|
+
px = edge?.clamp ?? [0, 0, 0, 0];
|
|
21939
|
+
} else {
|
|
21940
|
+
o = (srcRow + tx) * 4;
|
|
21941
|
+
}
|
|
21942
|
+
const a = px[o + 3];
|
|
21517
21943
|
if (a === 0) {
|
|
21518
21944
|
continue;
|
|
21519
21945
|
}
|
|
21520
21946
|
const wq = t.weights[q];
|
|
21521
|
-
pr += wq * Math.round(
|
|
21522
|
-
pg += wq * Math.round(
|
|
21523
|
-
pb += wq * Math.round(
|
|
21947
|
+
pr += wq * Math.round(px[o] * a / 255);
|
|
21948
|
+
pg += wq * Math.round(px[o + 1] * a / 255);
|
|
21949
|
+
pb += wq * Math.round(px[o + 2] * a / 255);
|
|
21524
21950
|
pa += wq * a;
|
|
21525
21951
|
}
|
|
21526
21952
|
const alpha = Math.min(255, Math.max(0, Math.round(pa)));
|
|
@@ -21566,7 +21992,7 @@ function resampleHqAxisAligned(rgba, width, height, spec, surface, m, premultOut
|
|
|
21566
21992
|
return { x: cx0, y: cy0, w, h, rgba: out, premultiplied: premultOut };
|
|
21567
21993
|
}
|
|
21568
21994
|
function resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel, near) {
|
|
21569
|
-
const pad = 2;
|
|
21995
|
+
const pad = spec.wrap ? 0 : 2;
|
|
21570
21996
|
let img;
|
|
21571
21997
|
let pw;
|
|
21572
21998
|
let ph;
|
|
@@ -21607,7 +22033,9 @@ function resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel,
|
|
|
21607
22033
|
srcH: spec.srcH,
|
|
21608
22034
|
toDevice: [kx, 0, 0, ky, -spec.srcX * kx, -spec.srcY * ky],
|
|
21609
22035
|
kernel,
|
|
21610
|
-
halfPixelOffset: false
|
|
22036
|
+
halfPixelOffset: false,
|
|
22037
|
+
wrap: spec.wrap,
|
|
22038
|
+
clampArgb: spec.clampArgb
|
|
21611
22039
|
}, { w: W, h: H }, { premultOut: true });
|
|
21612
22040
|
if (!pre) {
|
|
21613
22041
|
return null;
|
|
@@ -21648,7 +22076,9 @@ function resampleRotatedTwoStage(rgba, width, height, spec, surface, m, kernel,
|
|
|
21648
22076
|
srcH: ph,
|
|
21649
22077
|
toDevice: [a, b, c, d, ex - a * pad - c * pad, ey - b * pad - d * pad],
|
|
21650
22078
|
kernel: kernel === "hq-bicubic" ? "bicubic" : "bilinear",
|
|
21651
|
-
halfPixelOffset: false
|
|
22079
|
+
halfPixelOffset: false,
|
|
22080
|
+
wrap: spec.wrap,
|
|
22081
|
+
clampArgb: spec.clampArgb
|
|
21652
22082
|
}, surface, { plainRotated: true, keepOrigin: true, premultSource: true });
|
|
21653
22083
|
if (!block) {
|
|
21654
22084
|
return block;
|
|
@@ -23772,21 +24202,21 @@ function popState(rCtx, stackId) {
|
|
|
23772
24202
|
if (idx !== void 0 && idx < rCtx.saveStack.length) {
|
|
23773
24203
|
const saved = rCtx.saveStack[idx];
|
|
23774
24204
|
rCtx.worldTransform = [...saved.transform];
|
|
23775
|
-
const
|
|
23776
|
-
if (
|
|
23777
|
-
rCtx.clipRegion =
|
|
23778
|
-
rCtx.antiAlias =
|
|
23779
|
-
rCtx.interpolationMode =
|
|
23780
|
-
rCtx.pixelOffsetMode =
|
|
23781
|
-
rCtx.textRenderingHint =
|
|
23782
|
-
rCtx.pageUnit =
|
|
23783
|
-
rCtx.pageScale =
|
|
24205
|
+
const snap2 = saved.snapshot;
|
|
24206
|
+
if (snap2) {
|
|
24207
|
+
rCtx.clipRegion = snap2.clipRegion;
|
|
24208
|
+
rCtx.antiAlias = snap2.antiAlias;
|
|
24209
|
+
rCtx.interpolationMode = snap2.interpolationMode;
|
|
24210
|
+
rCtx.pixelOffsetMode = snap2.pixelOffsetMode;
|
|
24211
|
+
rCtx.textRenderingHint = snap2.textRenderingHint;
|
|
24212
|
+
rCtx.pageUnit = snap2.pageUnit;
|
|
24213
|
+
rCtx.pageScale = snap2.pageScale;
|
|
23784
24214
|
const ext = plusExt(rCtx);
|
|
23785
24215
|
const { multiFormatSkip, pendingEffect } = ext;
|
|
23786
24216
|
for (const key of Object.keys(ext)) {
|
|
23787
24217
|
delete ext[key];
|
|
23788
24218
|
}
|
|
23789
|
-
Object.assign(ext,
|
|
24219
|
+
Object.assign(ext, snap2.ext, { multiFormatSkip, pendingEffect });
|
|
23790
24220
|
}
|
|
23791
24221
|
rCtx.saveStack.length = idx;
|
|
23792
24222
|
const newMap = /* @__PURE__ */ new Map();
|
|
@@ -23796,7 +24226,7 @@ function popState(rCtx, stackId) {
|
|
|
23796
24226
|
}
|
|
23797
24227
|
}
|
|
23798
24228
|
rCtx.saveIdMap = newMap;
|
|
23799
|
-
if (
|
|
24229
|
+
if (snap2) {
|
|
23800
24230
|
reapplyPlusClip(rCtx);
|
|
23801
24231
|
}
|
|
23802
24232
|
}
|
|
@@ -25265,6 +25695,7 @@ function defaultGS() {
|
|
|
25265
25695
|
deltaShift: 3,
|
|
25266
25696
|
instructControl: 0,
|
|
25267
25697
|
scanControl: false,
|
|
25698
|
+
scanSet: false,
|
|
25268
25699
|
scanType: 0,
|
|
25269
25700
|
gep0: 1,
|
|
25270
25701
|
gep1: 1,
|
|
@@ -25277,6 +25708,13 @@ function defaultGS() {
|
|
|
25277
25708
|
var HintError = class extends Error {
|
|
25278
25709
|
};
|
|
25279
25710
|
var MAX_INSTRUCTIONS = 1e6;
|
|
25711
|
+
var SIZE_TWEAK_BODIES = [
|
|
25712
|
+
// MPPEM GTEQ SWAP MPPEM LTEQ AND IF SHPIX ELSE POP POP EIF
|
|
25713
|
+
[75, 83, 35, 75, 81, 90, 88, 56, 27, 33, 33, 89],
|
|
25714
|
+
// MPPEM EQ IF SHPIX ELSE POP POP EIF
|
|
25715
|
+
[75, 84, 88, 56, 27, 33, 33, 89]
|
|
25716
|
+
];
|
|
25717
|
+
var DEFAULT_DROPOUT_PPEM = 32;
|
|
25280
25718
|
var HintedSize = class _HintedSize {
|
|
25281
25719
|
constructor(font, ppemX, ppemY, env, hinting = true) {
|
|
25282
25720
|
this.fdefs = [];
|
|
@@ -25293,6 +25731,8 @@ var HintedSize = class _HintedSize {
|
|
|
25293
25731
|
this.callFrames = [];
|
|
25294
25732
|
/** The glyph program being run belongs to a composite glyph. */
|
|
25295
25733
|
this.inComposite = false;
|
|
25734
|
+
/** IUP[y] has run in the current glyph program. */
|
|
25735
|
+
this.iupy = false;
|
|
25296
25736
|
this.count = 0;
|
|
25297
25737
|
this.font = font;
|
|
25298
25738
|
this.env = env;
|
|
@@ -25360,7 +25800,7 @@ var HintedSize = class _HintedSize {
|
|
|
25360
25800
|
}
|
|
25361
25801
|
/** The scan-conversion mode prep left, used when a glyph program doesn't set its own. */
|
|
25362
25802
|
get defaultScan() {
|
|
25363
|
-
return { scanControl: this.gs0.scanControl, scanType: this.gs0.scanType };
|
|
25803
|
+
return { scanControl: this.gs0.scanControl, scanSet: this.gs0.scanSet, scanType: this.gs0.scanType };
|
|
25364
25804
|
}
|
|
25365
25805
|
// -----------------------------------------------------------------------
|
|
25366
25806
|
// Glyph loading
|
|
@@ -25388,6 +25828,7 @@ var HintedSize = class _HintedSize {
|
|
|
25388
25828
|
advance: pp2x - pp1x,
|
|
25389
25829
|
linearAdvance: mulFix(advance, this.xScale),
|
|
25390
25830
|
scanControl: res2.scanControl,
|
|
25831
|
+
scanSet: res2.scanSet,
|
|
25391
25832
|
scanType: res2.scanType
|
|
25392
25833
|
};
|
|
25393
25834
|
}
|
|
@@ -25452,7 +25893,7 @@ var HintedSize = class _HintedSize {
|
|
|
25452
25893
|
let lastScan = scan;
|
|
25453
25894
|
for (const comp of glyph.components) {
|
|
25454
25895
|
const sub = this.loadRecursive(comp.glyphIndex, depth + 1);
|
|
25455
|
-
lastScan = { scanControl: sub.scanControl, scanType: sub.scanType };
|
|
25896
|
+
lastScan = { scanControl: sub.scanControl, scanSet: sub.scanSet, scanType: sub.scanType };
|
|
25456
25897
|
const z = sub.zone;
|
|
25457
25898
|
const m = z.n - 4;
|
|
25458
25899
|
if (comp.flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO)) {
|
|
@@ -25588,12 +26029,13 @@ var HintedSize = class _HintedSize {
|
|
|
25588
26029
|
this.pts = zone;
|
|
25589
26030
|
this.zp0 = this.zp1 = this.zp2 = zone;
|
|
25590
26031
|
this.stack = [];
|
|
26032
|
+
this.iupy = false;
|
|
25591
26033
|
this.computeFuncs();
|
|
25592
26034
|
try {
|
|
25593
26035
|
this.execute(instructions);
|
|
25594
26036
|
} catch {
|
|
25595
26037
|
}
|
|
25596
|
-
return { zone, scanControl: this.gs.scanControl, scanType: this.gs.scanType };
|
|
26038
|
+
return { zone, scanControl: this.gs.scanControl, scanSet: this.gs.scanSet, scanType: this.gs.scanType };
|
|
25597
26039
|
}
|
|
25598
26040
|
// -----------------------------------------------------------------------
|
|
25599
26041
|
// Vector / projection machinery
|
|
@@ -25693,14 +26135,21 @@ var HintedSize = class _HintedSize {
|
|
|
25693
26135
|
}
|
|
25694
26136
|
/**
|
|
25695
26137
|
* Backward-compatible ClearType reads storage 22 (TypeMan Talk
|
|
25696
|
-
* DStroke/IStroke)
|
|
25697
|
-
*
|
|
25698
|
-
*
|
|
26138
|
+
* DStroke/IStroke) and 24 (spacing functions) as 0 inside the functions
|
|
26139
|
+
* whose signatures Microsoft documents, which bypasses them, and storage
|
|
26140
|
+
* 8 (VacuFormRound) as 0 wherever it is read: the Monotype fonts store
|
|
26141
|
+
* there whether the size is small (`MPPEM <= limit`) and, when it is,
|
|
26142
|
+
* run a block of corner-squaring ALIGNRP and SHPIX calls after the IUPs
|
|
26143
|
+
* that native ClearType never runs (Arial and Times New Roman bowls at
|
|
26144
|
+
* 9 to 17 ppem; 2,890 to 3,059 of 3,720 size-sheet captures exact).
|
|
25699
26145
|
*/
|
|
25700
26146
|
ctBypassStorage(i) {
|
|
25701
26147
|
if (!this.ctCompat() || i !== 22 && i !== 24 && i !== 8) {
|
|
25702
26148
|
return false;
|
|
25703
26149
|
}
|
|
26150
|
+
if (i === 8) {
|
|
26151
|
+
return true;
|
|
26152
|
+
}
|
|
25704
26153
|
const frame2 = this.callFrames[this.callFrames.length - 1];
|
|
25705
26154
|
if (!frame2) {
|
|
25706
26155
|
return false;
|
|
@@ -25711,10 +26160,7 @@ var HintedSize = class _HintedSize {
|
|
|
25711
26160
|
if (i === 22) {
|
|
25712
26161
|
return at([176, 22, 67, 88]);
|
|
25713
26162
|
}
|
|
25714
|
-
|
|
25715
|
-
return at([1, 176, 24, 67, 88]) || at([1, 24, 176, 24, 67, 88]);
|
|
25716
|
-
}
|
|
25717
|
-
return at([69, 35, 70, 96, 32, 176, 38]);
|
|
26163
|
+
return at([1, 176, 24, 67, 88]) || at([1, 24, 176, 24, 67, 88]);
|
|
25718
26164
|
}
|
|
25719
26165
|
/** True when the projection vector points (mostly) along x, ClearType's direction. */
|
|
25720
26166
|
ctDirection() {
|
|
@@ -25884,6 +26330,27 @@ var HintedSize = class _HintedSize {
|
|
|
25884
26330
|
this.stack.push(v | 0);
|
|
25885
26331
|
}
|
|
25886
26332
|
/** Returns the length of the instruction at `ip` (for skipping). */
|
|
26333
|
+
/**
|
|
26334
|
+
* True for the two generic per-size tweak helpers of Monotype-hinted fonts
|
|
26335
|
+
* (Arial, Times New Roman, Tahoma), whose whole body is `MPPEM >= lo and
|
|
26336
|
+
* MPPEM <= hi: SHPIX` or `MPPEM == ppem: SHPIX`. Native ClearType ignores
|
|
26337
|
+
* the x shifts they issue; the mode-selected variants (the same body behind
|
|
26338
|
+
* `RS 2` / `EQ`), inline shifts and every other function are applied. Measured on
|
|
26339
|
+
* private fonts (`shpix-*.ttf`): any other body, such as extra bytes before
|
|
26340
|
+
* or after the helper, strict comparisons or a missing ELSE branch, is
|
|
26341
|
+
* applied, and the function number does not matter.
|
|
26342
|
+
*/
|
|
26343
|
+
static isSizeTweak(def) {
|
|
26344
|
+
if (def.sizeTweak === void 0) {
|
|
26345
|
+
const n = def.end - def.start;
|
|
26346
|
+
def.sizeTweak = SIZE_TWEAK_BODIES.some((body) => body.length === n && body.every((b, i) => def.code[def.start + i] === b));
|
|
26347
|
+
}
|
|
26348
|
+
return def.sizeTweak;
|
|
26349
|
+
}
|
|
26350
|
+
inSizeTweak() {
|
|
26351
|
+
const frame2 = this.callFrames[this.callFrames.length - 1];
|
|
26352
|
+
return !!frame2 && _HintedSize.isSizeTweak(frame2.def);
|
|
26353
|
+
}
|
|
25887
26354
|
static insLength(code, ip) {
|
|
25888
26355
|
const op = code[ip];
|
|
25889
26356
|
if (op === 64) {
|
|
@@ -25903,6 +26370,7 @@ var HintedSize = class _HintedSize {
|
|
|
25903
26370
|
execute(code) {
|
|
25904
26371
|
const calls = [];
|
|
25905
26372
|
this.callFrames = calls;
|
|
26373
|
+
this.count = 0;
|
|
25906
26374
|
let ip = 0;
|
|
25907
26375
|
let cur = code;
|
|
25908
26376
|
while (true) {
|
|
@@ -26350,7 +26818,7 @@ var HintedSize = class _HintedSize {
|
|
|
26350
26818
|
while (gs.loop > 0) {
|
|
26351
26819
|
const p = this.pop();
|
|
26352
26820
|
if (p >= 0 && p < this.zp2.n) {
|
|
26353
|
-
const keep = !this.ctCompat() || this.inComposite || gs.fvx === 0 && (this.zp2.tags[p] & TOUCH_Y) !== 0;
|
|
26821
|
+
const keep = !this.ctCompat() || this.inComposite || gs.fvx === 0 && (this.zp2.tags[p] & TOUCH_Y) !== 0 || gs.fvx !== 0 && !this.env.grayscale && !this.inSizeTweak();
|
|
26354
26822
|
if (keep) {
|
|
26355
26823
|
this.moveZp2(p, dx, dy, true);
|
|
26356
26824
|
}
|
|
@@ -26382,7 +26850,7 @@ var HintedSize = class _HintedSize {
|
|
|
26382
26850
|
this.zp1.curY[p] - this.zp0.curY[gs.rp0]
|
|
26383
26851
|
);
|
|
26384
26852
|
let target = d;
|
|
26385
|
-
if (this.ctCompat() && gs.gep0 !== 0 && gs.gep1 !== 0) {
|
|
26853
|
+
if (this.ctCompat() && this.ctDirection() && gs.gep0 !== 0 && gs.gep1 !== 0) {
|
|
26386
26854
|
const org = this.dualProjectOrus(
|
|
26387
26855
|
this.zp1.orusX[p] - this.zp0.orusX[gs.rp0],
|
|
26388
26856
|
this.zp1.orusY[p] - this.zp0.orusY[gs.rp0]
|
|
@@ -26675,6 +27143,7 @@ var HintedSize = class _HintedSize {
|
|
|
26675
27143
|
case 133: {
|
|
26676
27144
|
const v = this.pop();
|
|
26677
27145
|
const a = v & 255;
|
|
27146
|
+
gs.scanSet = true;
|
|
26678
27147
|
if (a === 255) {
|
|
26679
27148
|
gs.scanControl = true;
|
|
26680
27149
|
return true;
|
|
@@ -26685,10 +27154,10 @@ var HintedSize = class _HintedSize {
|
|
|
26685
27154
|
}
|
|
26686
27155
|
if (v & 256 && this.ppem <= a) gs.scanControl = true;
|
|
26687
27156
|
if (v & 512 && this.env.rotated) gs.scanControl = true;
|
|
26688
|
-
if (v & 1024 && this.stretched) gs.scanControl = true;
|
|
27157
|
+
if (v & 1024 && (this.stretched || this.env.reportStretched)) gs.scanControl = true;
|
|
26689
27158
|
if (v & 2048 && this.ppem > a) gs.scanControl = false;
|
|
26690
27159
|
if (v & 4096 && this.env.rotated) gs.scanControl = false;
|
|
26691
|
-
if (v & 8192 && this.stretched) gs.scanControl = false;
|
|
27160
|
+
if (v & 8192 && (this.stretched || this.env.reportStretched)) gs.scanControl = false;
|
|
26692
27161
|
return true;
|
|
26693
27162
|
}
|
|
26694
27163
|
case 134:
|
|
@@ -26700,7 +27169,7 @@ var HintedSize = class _HintedSize {
|
|
|
26700
27169
|
let k = 0;
|
|
26701
27170
|
if (sel & 1) k = this.env.version;
|
|
26702
27171
|
if (sel & 2 && this.env.rotated) k |= 1 << 8;
|
|
26703
|
-
if (sel & 4 && this.stretched) k |= 1 << 9;
|
|
27172
|
+
if (sel & 4 && (this.stretched || this.env.reportStretched)) k |= 1 << 9;
|
|
26704
27173
|
if (sel & 32 && this.env.grayscale) k |= 1 << 12;
|
|
26705
27174
|
if (sel & 64 && this.env.clearType) k |= 1 << 13;
|
|
26706
27175
|
if (sel & 128 && this.env.clearType && this.env.compatibleWidths !== false) k |= 1 << 14;
|
|
@@ -27002,6 +27471,7 @@ var HintedSize = class _HintedSize {
|
|
|
27002
27471
|
return this.dualProject(mulFix(dx, this.xScale), mulFix(dy, this.yScale));
|
|
27003
27472
|
}
|
|
27004
27473
|
insIUP(xAxis) {
|
|
27474
|
+
if (!xAxis) this.iupy = true;
|
|
27005
27475
|
const z = this.pts;
|
|
27006
27476
|
const mask = xAxis ? TOUCH_X : TOUCH_Y;
|
|
27007
27477
|
const orgs = xAxis ? z.orgX : z.orgY;
|
|
@@ -27133,7 +27603,7 @@ var HintedSize = class _HintedSize {
|
|
|
27133
27603
|
let s = (b & 15) - 8;
|
|
27134
27604
|
if (s >= 0) s++;
|
|
27135
27605
|
s *= 1 << 6 - this.gs.deltaShift;
|
|
27136
|
-
if (this.ctCompat() && !(this.gs.fvx === 0 && (this.zp0.tags[a] & TOUCH_Y) !== 0)) {
|
|
27606
|
+
if (this.ctCompat() && (this.iupy || !(this.gs.fvx === 0 && (this.zp0.tags[a] & TOUCH_Y) !== 0))) {
|
|
27137
27607
|
continue;
|
|
27138
27608
|
}
|
|
27139
27609
|
this.move(this.zp0, a, s);
|
|
@@ -27812,7 +28282,7 @@ function monoBox(o) {
|
|
|
27812
28282
|
}
|
|
27813
28283
|
return { xMin, xMax, yMin, yMax };
|
|
27814
28284
|
}
|
|
27815
|
-
function rasterizeMono(o, dropout, fixedBox) {
|
|
28285
|
+
function rasterizeMono(o, dropout, fixedBox, stubOvershoot = true) {
|
|
27816
28286
|
const box = fixedBox ?? monoBox(o);
|
|
27817
28287
|
if (!box) {
|
|
27818
28288
|
return null;
|
|
@@ -27868,10 +28338,10 @@ function rasterizeMono(o, dropout, fixedBox) {
|
|
|
27868
28338
|
break;
|
|
27869
28339
|
case 1:
|
|
27870
28340
|
case 5:
|
|
27871
|
-
if (left.next === right && left.height <= 0 && !(left.flags & OVERSHOOT_TOP && x2 - x1 >= r.half)) {
|
|
28341
|
+
if (left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= r.half)) {
|
|
27872
28342
|
return;
|
|
27873
28343
|
}
|
|
27874
|
-
if (right.next === left && left.start === y && !(left.flags & OVERSHOOT_BOTTOM && x2 - x1 >= r.half)) {
|
|
28344
|
+
if (right.next === left && left.start === y && !(stubOvershoot && left.flags & OVERSHOOT_BOTTOM && x2 - x1 >= r.half)) {
|
|
27875
28345
|
return;
|
|
27876
28346
|
}
|
|
27877
28347
|
pxl = mode === 1 ? e2 : r.floorPub(Math.floor((x1 + x2 + Math.floor(P * 63 / 64)) / 2));
|
|
@@ -27927,10 +28397,10 @@ function rasterizeMono(o, dropout, fixedBox) {
|
|
|
27927
28397
|
break;
|
|
27928
28398
|
case 1:
|
|
27929
28399
|
case 5:
|
|
27930
|
-
if (left.next === right && left.height <= 0 && !(left.flags & OVERSHOOT_TOP && x2 - x1 >= h.half)) {
|
|
28400
|
+
if (left.next === right && left.height <= 0 && !(stubOvershoot && left.flags & OVERSHOOT_TOP && x2 - x1 >= h.half)) {
|
|
27931
28401
|
return;
|
|
27932
28402
|
}
|
|
27933
|
-
if (right.next === left && left.start === col && !(left.flags & OVERSHOOT_BOTTOM && x2 - x1 >= h.half)) {
|
|
28403
|
+
if (right.next === left && left.start === col && !(stubOvershoot && left.flags & OVERSHOOT_BOTTOM && x2 - x1 >= h.half)) {
|
|
27934
28404
|
return;
|
|
27935
28405
|
}
|
|
27936
28406
|
pxl = mode === 1 ? e2 : h.floorPub(Math.floor((x1 + x2 + Math.floor(P * 63 / 64)) / 2));
|
|
@@ -27956,7 +28426,7 @@ function rasterizeMono(o, dropout, fixedBox) {
|
|
|
27956
28426
|
return { width, height, left: box.xMin, top: box.yMax, data };
|
|
27957
28427
|
}
|
|
27958
28428
|
var GRAY_OVERSAMPLE = 4;
|
|
27959
|
-
function rasterizeSamples(o, kx, ky, padX = 0) {
|
|
28429
|
+
function rasterizeSamples(o, kx, ky, padX = 0, dropout = 2, stubOvershoot = true) {
|
|
27960
28430
|
const n = o.xs.length;
|
|
27961
28431
|
if (n === 0) {
|
|
27962
28432
|
return null;
|
|
@@ -27985,10 +28455,10 @@ function rasterizeSamples(o, kx, ky, padX = 0) {
|
|
|
27985
28455
|
onCurve: o.onCurve,
|
|
27986
28456
|
endPts: o.endPts
|
|
27987
28457
|
};
|
|
27988
|
-
const hi = rasterizeMono(big,
|
|
28458
|
+
const hi = rasterizeMono(big, dropout, { xMin: box.xMin * kx, xMax: box.xMax * kx, yMin: box.yMin * ky, yMax: box.yMax * ky }, stubOvershoot);
|
|
27989
28459
|
return hi ? { box, hi } : null;
|
|
27990
28460
|
}
|
|
27991
|
-
function rasterizeGray(o) {
|
|
28461
|
+
function rasterizeGray(o, dropout = 2) {
|
|
27992
28462
|
const n = o.xs.length;
|
|
27993
28463
|
if (n === 0) {
|
|
27994
28464
|
return null;
|
|
@@ -28018,7 +28488,7 @@ function rasterizeGray(o) {
|
|
|
28018
28488
|
onCurve: o.onCurve,
|
|
28019
28489
|
endPts: o.endPts
|
|
28020
28490
|
};
|
|
28021
|
-
const hi = rasterizeMono(big,
|
|
28491
|
+
const hi = rasterizeMono(big, dropout, { xMin: box.xMin * k, xMax: box.xMax * k, yMin: box.yMin * k, yMax: box.yMax * k }, false);
|
|
28022
28492
|
if (!hi) {
|
|
28023
28493
|
return null;
|
|
28024
28494
|
}
|
|
@@ -28076,7 +28546,8 @@ function slantRows(b) {
|
|
|
28076
28546
|
}
|
|
28077
28547
|
return { ...b, width, data };
|
|
28078
28548
|
}
|
|
28079
|
-
var RASTER_STRETCH_COST = [0, 0, 120, 150, 250, 250];
|
|
28549
|
+
var RASTER_STRETCH_COST = [0, 0, 120, 150, 250, 250, 1150, 1280, 1840];
|
|
28550
|
+
var RASTER_MAX_X_SCALE = 5;
|
|
28080
28551
|
function unitOf(f) {
|
|
28081
28552
|
return Math.max(1, f.pixHeight - f.internalLeading);
|
|
28082
28553
|
}
|
|
@@ -28499,8 +28970,7 @@ var RealizedFont = class {
|
|
|
28499
28970
|
const skew = m && !(Math.abs(m[1]) < 1e-9 && Math.abs(m[2]) < 1e-9) && !(Math.abs(m[0]) < 1e-9 && Math.abs(m[3]) < 1e-9);
|
|
28500
28971
|
const src = skew ? this.rotatedOutline(index) : this.outline(index);
|
|
28501
28972
|
if (skew && m) {
|
|
28502
|
-
|
|
28503
|
-
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];
|
|
28973
|
+
m = roundedRotationMatrix(m, this.ppem);
|
|
28504
28974
|
}
|
|
28505
28975
|
let o = this.mode === "cleartype" && !m && !this.syntheticItalic ? this.ctOutline(index) : src;
|
|
28506
28976
|
if (this.syntheticItalic || m || subX || subY) {
|
|
@@ -28526,11 +28996,12 @@ var RealizedFont = class {
|
|
|
28526
28996
|
}
|
|
28527
28997
|
let bitmap;
|
|
28528
28998
|
if (this.mode === "mono") {
|
|
28529
|
-
bitmap = rasterizeMono(o, dropoutMode(src.scanControl, src.scanType));
|
|
28999
|
+
bitmap = rasterizeMono(o, dropoutMode(src.scanSet ? src.scanControl : this.ppem <= DEFAULT_DROPOUT_PPEM, src.scanType));
|
|
28530
29000
|
} else if (this.mode === "cleartype") {
|
|
28531
|
-
|
|
29001
|
+
const dropout = src.scanSet ? dropoutMode(src.scanControl, src.scanType) : 2;
|
|
29002
|
+
bitmap = rasterizeClearType(o, this.gdiPlus, this.gdiPlus ? clearTypeSpread(this.ttf) : void 0, dropout);
|
|
28532
29003
|
} else {
|
|
28533
|
-
bitmap = rasterizeGray(o);
|
|
29004
|
+
bitmap = rasterizeGray(o, src.scanSet ? dropoutMode(src.scanControl, src.scanType) : 2);
|
|
28534
29005
|
}
|
|
28535
29006
|
if (bitmap && this.syntheticBold) {
|
|
28536
29007
|
bitmap = embolden(bitmap, this.mode === "mono" ? 1 : 16);
|
|
@@ -28540,6 +29011,19 @@ var RealizedFont = class {
|
|
|
28540
29011
|
return g;
|
|
28541
29012
|
}
|
|
28542
29013
|
};
|
|
29014
|
+
function roundedRotationMatrix(m, ppem) {
|
|
29015
|
+
const isRotation = Math.abs(m[0] - m[3]) < 1e-6 && Math.abs(m[1] + m[2]) < 1e-6;
|
|
29016
|
+
if (isRotation && ppem > 0) {
|
|
29017
|
+
const major = ppem * Math.max(Math.abs(m[0]), Math.abs(m[1]));
|
|
29018
|
+
const target = Math.round(major);
|
|
29019
|
+
if (target >= 1) {
|
|
29020
|
+
const k = target / major;
|
|
29021
|
+
return [m[0] * k, m[1] * k, m[2] * k, m[3] * k];
|
|
29022
|
+
}
|
|
29023
|
+
}
|
|
29024
|
+
const p = ppem;
|
|
29025
|
+
return [Math.round(m[0] * p) / p, Math.round(m[1] * p) / p, Math.round(m[2] * p) / p, Math.round(m[3] * p) / p];
|
|
29026
|
+
}
|
|
28543
29027
|
function embolden(b, full) {
|
|
28544
29028
|
const w = b.width + 1;
|
|
28545
29029
|
const data = new Uint8Array(w * b.height);
|
|
@@ -28638,8 +29122,9 @@ var GdiFontCollection = class _GdiFontCollection {
|
|
|
28638
29122
|
* heights for a negative lfHeight and cell heights for a positive one.
|
|
28639
29123
|
* The cost model is fitted to GetTextMetrics over lfHeight -60..60 for
|
|
28640
29124
|
* MS Sans Serif, MS Serif, Courier, Small Fonts, System and Terminal
|
|
28641
|
-
* (98% exact): 150 per pixel too small; 290 plus
|
|
28642
|
-
* a stretch cost by factor (120, 150, 250, 250 for 2x..5x
|
|
29125
|
+
* (98% exact): 150 per pixel too small; 290 plus 340 per pixel too big;
|
|
29126
|
+
* a stretch cost by factor (120, 150, 250, 250 for 2x..5x and 1,150,
|
|
29127
|
+
* 1,280 and 1,840 for 6x..8x, the largest GDI uses) plus 100 per
|
|
28643
29128
|
* extra factor divided by the face's character height (small faces
|
|
28644
29129
|
* stretch less readily); ties go to the smaller stretch, then to the
|
|
28645
29130
|
* 96 dpi face. A weight mismatch costs 3 per 10 units (so Terminal's
|
|
@@ -28659,9 +29144,9 @@ var GdiFontCollection = class _GdiFontCollection {
|
|
|
28659
29144
|
let bestCost = Infinity;
|
|
28660
29145
|
for (const f of pool) {
|
|
28661
29146
|
const unit = height < 0 ? unitOf(f) : f.pixHeight;
|
|
28662
|
-
for (let n = 1; n
|
|
29147
|
+
for (let n = 1; n < RASTER_STRETCH_COST.length; n++) {
|
|
28663
29148
|
const d = unit * n - target;
|
|
28664
|
-
const cost = (d < 0 ? -d * 150 : d > 0 ? 290 + d *
|
|
29149
|
+
const cost = (d < 0 ? -d * 150 : d > 0 ? 290 + d * 340 : 0) + RASTER_STRETCH_COST[n] + (n > 1 ? 100 * (n - 1) / unitOf(f) : 0) + Math.abs(f.weight - weight) * 3 / 10 + n * 0.01 + (f.vertRes === 96 ? 0 : 1e-3);
|
|
28665
29150
|
if (cost < bestCost) {
|
|
28666
29151
|
bestCost = cost;
|
|
28667
29152
|
best = { face: f, scale: n };
|
|
@@ -28677,7 +29162,7 @@ var GdiFontCollection = class _GdiFontCollection {
|
|
|
28677
29162
|
return null;
|
|
28678
29163
|
}
|
|
28679
29164
|
const { face, scale } = pick;
|
|
28680
|
-
const scaleX = spec.width > 0 && face.avgWidth > 0 ? Math.max(1, Math.ceil(spec.width / face.avgWidth - 0.5)) : scale;
|
|
29165
|
+
const scaleX = spec.width > 0 && face.avgWidth > 0 ? Math.max(1, Math.ceil(spec.width / face.avgWidth - 0.5)) : Math.min(scale, RASTER_MAX_X_SCALE);
|
|
28681
29166
|
return new RasterRealizedFont(face, scale, weight >= 600 && face.weight < 600, scaleX, spec.italic && !face.italic);
|
|
28682
29167
|
}
|
|
28683
29168
|
/**
|
|
@@ -28828,9 +29313,15 @@ function resolvePpem(font, height) {
|
|
|
28828
29313
|
return ppem;
|
|
28829
29314
|
}
|
|
28830
29315
|
var CLEARTYPE_OVERSAMPLE = 6;
|
|
28831
|
-
function
|
|
29316
|
+
function clearTypeSpread(ttf) {
|
|
29317
|
+
if (ttf.family.toLowerCase() !== "courier new") {
|
|
29318
|
+
return void 0;
|
|
29319
|
+
}
|
|
29320
|
+
return { left: 1, right: ttf.weightClass >= 600 ? 1 : 2 };
|
|
29321
|
+
}
|
|
29322
|
+
function rasterizeClearType(o, truncate = false, spread, dropout = 2) {
|
|
28832
29323
|
const S = CLEARTYPE_OVERSAMPLE / 3;
|
|
28833
|
-
const r = rasterizeSamples(o, CLEARTYPE_OVERSAMPLE, 1, 1);
|
|
29324
|
+
const r = rasterizeSamples(o, CLEARTYPE_OVERSAMPLE, 1, 1, dropout, false);
|
|
28834
29325
|
if (!r) {
|
|
28835
29326
|
return null;
|
|
28836
29327
|
}
|
|
@@ -28844,12 +29335,23 @@ function rasterizeClearType(o, truncate = false) {
|
|
|
28844
29335
|
sub.fill(0);
|
|
28845
29336
|
const row2 = y * hi.width;
|
|
28846
29337
|
for (let x = 0; x < hi.width; x++) {
|
|
28847
|
-
|
|
29338
|
+
let on = hi.data[row2 + x] !== 0;
|
|
29339
|
+
if (spread && !on) {
|
|
29340
|
+
for (let k = x - spread.right; k <= x + spread.left && !on; k++) {
|
|
29341
|
+
on = k >= 0 && k < hi.width && hi.data[row2 + k] !== 0;
|
|
29342
|
+
}
|
|
29343
|
+
}
|
|
29344
|
+
if (on) {
|
|
28848
29345
|
sub[Math.floor(x / S)] += 1;
|
|
28849
29346
|
}
|
|
28850
29347
|
}
|
|
28851
29348
|
for (let j = 0; j < n; j++) {
|
|
28852
|
-
const
|
|
29349
|
+
const before = j > 0 ? sub[j - 1] : 0;
|
|
29350
|
+
const after = j + 1 < n ? sub[j + 1] : 0;
|
|
29351
|
+
let acc = before + sub[j] + after;
|
|
29352
|
+
if (spread && acc === 1 && sub[j] === 0 && (j % 3 === 0 && before === 1 || (j + 1) % 3 === 0 && after === 1)) {
|
|
29353
|
+
acc = 0;
|
|
29354
|
+
}
|
|
28853
29355
|
data[y * n + j] = (truncate ? Math.floor : Math.round)(255 * acc / (3 * S));
|
|
28854
29356
|
}
|
|
28855
29357
|
}
|
|
@@ -30168,22 +30670,27 @@ function penPolygon(width, height = width) {
|
|
|
30168
30670
|
return pen;
|
|
30169
30671
|
}
|
|
30170
30672
|
var matrixPenCache = /* @__PURE__ */ new Map();
|
|
30673
|
+
function halfVectorComponent(v) {
|
|
30674
|
+
return Math.sign(v) * Math.floor(Math.abs(v) + 0.75);
|
|
30675
|
+
}
|
|
30171
30676
|
function penPolygonMatrix(width, m) {
|
|
30172
30677
|
const key = `${width},${m.join(",")}`;
|
|
30173
30678
|
const cached = matrixPenCache.get(key);
|
|
30174
30679
|
if (cached) {
|
|
30175
30680
|
return cached;
|
|
30176
30681
|
}
|
|
30177
|
-
const
|
|
30682
|
+
const scale = Math.hypot(m[0], m[1]);
|
|
30683
|
+
if (Math.abs(Math.hypot(m[2], m[3]) - scale) < 1e-4 * scale && Math.abs(m[0] * m[2] + m[1] * m[3]) < 1e-4 * scale * scale && width * scale < HOBBY_LIMIT) {
|
|
30684
|
+
const digital = penPolygon(Math.round(width * scale));
|
|
30685
|
+
matrixPenCache.set(key, digital);
|
|
30686
|
+
return digital;
|
|
30687
|
+
}
|
|
30688
|
+
const h = width / 2;
|
|
30178
30689
|
const mirror2 = m[0] * m[3] - m[1] * m[2] < 0 ? -1 : 1;
|
|
30179
|
-
const
|
|
30180
|
-
const
|
|
30181
|
-
|
|
30182
|
-
|
|
30183
|
-
const y = bez[i + 1] * mirror2;
|
|
30184
|
-
dev.push(Math.round(m[0] * x + m[2] * y), Math.round(m[1] * x + m[3] * y));
|
|
30185
|
-
}
|
|
30186
|
-
const f = flattenBezierPath(dev);
|
|
30690
|
+
const hx = [halfVectorComponent(m[0] * h), halfVectorComponent(m[1] * h)];
|
|
30691
|
+
const hy = [mirror2 * halfVectorComponent(m[2] * h), mirror2 * halfVectorComponent(m[3] * h)];
|
|
30692
|
+
const box = ellipseBeziersBox({ ax: -hx[0] - hy[0], ay: -hx[1] - hy[1], exx: 2 * hx[0], exy: 2 * hx[1], eyx: 2 * hy[0], eyy: 2 * hy[1] });
|
|
30693
|
+
const f = flattenBezierPath(box.slice(0, 14));
|
|
30187
30694
|
const half = [];
|
|
30188
30695
|
for (let i = 0; i + 1 < f.length; i += 2) {
|
|
30189
30696
|
half.push([f[i], f[i + 1]]);
|
|
@@ -30255,9 +30762,10 @@ function perpendicularVectors(width, dx0, dy0, height = width, matrixPen) {
|
|
|
30255
30762
|
const den = 2 * (bh - hB + (bh - hS));
|
|
30256
30763
|
const w = den === 0 ? 0 : (hB - hS) / den;
|
|
30257
30764
|
const x = D[0] + (B[0] - D[0]) * w, y = D[1] + (B[1] - D[1]) * w;
|
|
30258
|
-
const signs = [dx === 0 ? 0 : Math.sign(dy), Math.sign(dx)];
|
|
30259
|
-
const firstEdge = best === 0 && hP >= hN;
|
|
30260
30765
|
const num = hB - hS;
|
|
30766
|
+
const sign = (c) => Math.sign(den === 0 ? D[c] : D[c] * den + (B[c] - D[c]) * num);
|
|
30767
|
+
const signs = matrixPen ? [sign(0) !== 0 ? -sign(0) : dx === 0 ? 0 : Math.sign(dy), sign(1) !== 0 ? sign(1) : Math.sign(dx)] : [dx === 0 ? 0 : Math.sign(dy), Math.sign(dx)];
|
|
30768
|
+
const firstEdge = matrixPen ? best < n / 2 : best === 0 && hP >= hN;
|
|
30261
30769
|
const rounded = [0, 1].map((c) => {
|
|
30262
30770
|
const bias2 = signs[c] + 2 * oddEdgeAdjustment(Math.abs(B[c] - D[c]) % 2 === 1, firstEdge);
|
|
30263
30771
|
if (den === 0) {
|
|
@@ -30284,7 +30792,8 @@ function squareExtension(width, dx, dy, scale = 1, height = width, matrix, whole
|
|
|
30284
30792
|
if (l === 0) return [0, 0];
|
|
30285
30793
|
}
|
|
30286
30794
|
const q = width / 2 * scale / l;
|
|
30287
|
-
|
|
30795
|
+
const round2 = symmetric ? (v) => Math.sign(v) * Math.floor(Math.abs(v) + 0.5) : (v) => Math.floor(v + 0.5);
|
|
30796
|
+
return [round2((matrix[0] * lx + matrix[2] * ly) * q), round2((matrix[1] * lx + matrix[3] * ly) * q)];
|
|
30288
30797
|
}
|
|
30289
30798
|
const [ax, ay] = typeof logicalScale === "number" ? [logicalScale, logicalScale] : logicalScale;
|
|
30290
30799
|
const r = width / 2 * scale;
|
|
@@ -30338,7 +30847,8 @@ var Outliner = class {
|
|
|
30338
30847
|
const [L, R] = drawVertices(this.pen, d[0], d[1], this.opts.width, this.opts.height, nibMatrix);
|
|
30339
30848
|
const perpendicular = curve && drawDir ? drawDir : [dx, dy];
|
|
30340
30849
|
const vectors = perpendicularVectors(this.opts.width, perpendicular[0], perpendicular[1], this.opts.height, nibMatrix ? this.pen : void 0);
|
|
30341
|
-
|
|
30850
|
+
const reversed = !!drawDir && dx * drawDir[0] + dy * drawDir[1] < 0;
|
|
30851
|
+
return { dx, dy, tx: reversed ? drawDir[0] : dx, ty: reversed ? drawDir[1] : dy, L, R, v: vectors.v, vRaw: vectors.ray, e: squareExtension(this.opts.capWidth ?? this.opts.width, perpendicular[0], perpendicular[1], 1, this.opts.height ?? this.opts.capWidth, nibMatrix, !!(this.opts.wholePixelDashVectors || this.opts.cutToLogicalUnits), void 0, this.opts.logicalScale), pe: [perpendicular[0], perpendicular[1]], curveEnd: !!drawDir, role: drawDir?.[2] ?? 3, tangentLength: drawDir ? drawDir[0] * drawDir[0] + drawDir[1] * drawDir[1] : 0, curve };
|
|
30342
30852
|
}
|
|
30343
30853
|
push(p, v) {
|
|
30344
30854
|
this.pts.push([p[0] + v[0], p[1] + v[1]]);
|
|
@@ -30451,7 +30961,7 @@ var Outliner = class {
|
|
|
30451
30961
|
const sv = this.capSide(s, from);
|
|
30452
30962
|
const ev = this.capSide(s, to);
|
|
30453
30963
|
if (cap === "square") {
|
|
30454
|
-
const e0 = scale === 1 || s.curveEnd ? s.e :
|
|
30964
|
+
const e0 = scale === 1 || s.curveEnd ? s.e : this.scaledExtension(s, scale);
|
|
30455
30965
|
const e = start ? [-e0[0], -e0[1]] : e0;
|
|
30456
30966
|
this.push(p, [sv[0] + e[0], sv[1] + e[1]]);
|
|
30457
30967
|
this.push(p, [ev[0] + e[0], ev[1] + e[1]]);
|
|
@@ -30460,6 +30970,23 @@ var Outliner = class {
|
|
|
30460
30970
|
this.push(p, ev);
|
|
30461
30971
|
}
|
|
30462
30972
|
}
|
|
30973
|
+
/**
|
|
30974
|
+
* The square-cap extension of a dash end that GDI scales by its real over whole-pixel length. At one logical unit per device pixel the
|
|
30975
|
+
* extension is the vector component times (half the width over the whole-pixel length), a float32 product of a float32 ratio, rounded
|
|
30976
|
+
* half away from zero; ties of the exact product (110.5, 3.5, 57.5, -62.5) fall where that single-precision value puts them.
|
|
30977
|
+
*/
|
|
30978
|
+
scaledExtension(s, scale) {
|
|
30979
|
+
const o = this.opts;
|
|
30980
|
+
if (o.wholePixelDashVectors && !o.matrix && !o.dashMetric && (o.height === void 0 || o.height === o.width)) {
|
|
30981
|
+
const length = norm(Math.floor(s.pe[0] / 16), Math.floor(s.pe[1] / 16)) * 16;
|
|
30982
|
+
if (length > 0) {
|
|
30983
|
+
const ratio = Math.fround(o.width / 2 / length);
|
|
30984
|
+
const component = (v) => Math.sign(v) * Math.floor(Math.fround(Math.abs(v) * ratio) + 0.5);
|
|
30985
|
+
return [component(s.pe[0]), component(s.pe[1])];
|
|
30986
|
+
}
|
|
30987
|
+
}
|
|
30988
|
+
return squareExtension(o.width, s.pe[0], s.pe[1], scale, o.height, o.deviceNib ? o.matrix : void 0, false, !!o.wholePixelDashVectors);
|
|
30989
|
+
}
|
|
30463
30990
|
/**
|
|
30464
30991
|
* The join at `p` on `side`, coming along `a` and leaving along `b` in
|
|
30465
30992
|
* outline order (for the left side, walked backwards, `a` is the later
|
|
@@ -30503,7 +31030,7 @@ var Outliner = class {
|
|
|
30503
31030
|
}
|
|
30504
31031
|
}
|
|
30505
31032
|
} else if (join === "miter") {
|
|
30506
|
-
const m = miterPoint(sa, [a.dx, a.dy], sb, [b.dx, b.dy], width, miterLimit, side, this.opts.height);
|
|
31033
|
+
const m = miterPoint(sa, [a.dx, a.dy], sb, [b.dx, b.dy], width, miterLimit, side, this.opts.height, this.opts.deviceNib ? this.opts.matrix : void 0);
|
|
30507
31034
|
if (m) {
|
|
30508
31035
|
this.push(p, m);
|
|
30509
31036
|
}
|
|
@@ -30577,7 +31104,7 @@ var Outliner = class {
|
|
|
30577
31104
|
for (let i = 0; i + 1 < segs2.length; i++) {
|
|
30578
31105
|
const s = segs2[i];
|
|
30579
31106
|
const t = segs2[i + 1];
|
|
30580
|
-
const tr = turnSign(s.
|
|
31107
|
+
const tr = turnSign(s.tx, s.ty, t.tx, t.ty);
|
|
30581
31108
|
if (tr === 0) {
|
|
30582
31109
|
this.push(P[i + 1], this.joinSide(s, "R"));
|
|
30583
31110
|
} else {
|
|
@@ -30588,7 +31115,7 @@ var Outliner = class {
|
|
|
30588
31115
|
for (let i = segs2.length - 1; i > 0; i--) {
|
|
30589
31116
|
const s = segs2[i];
|
|
30590
31117
|
const t = segs2[i - 1];
|
|
30591
|
-
const tr = turnSign(t.
|
|
31118
|
+
const tr = turnSign(t.tx, t.ty, s.tx, s.ty);
|
|
30592
31119
|
if (tr === 0) {
|
|
30593
31120
|
this.push(P[i], this.joinSide(s, "L"));
|
|
30594
31121
|
} else {
|
|
@@ -30608,7 +31135,7 @@ var Outliner = class {
|
|
|
30608
31135
|
const i = j % m;
|
|
30609
31136
|
const s = segs2[(i + m - 1) % m];
|
|
30610
31137
|
const t = segs2[i];
|
|
30611
|
-
const tr = turnSign(s.
|
|
31138
|
+
const tr = turnSign(s.tx, s.ty, t.tx, t.ty);
|
|
30612
31139
|
if (tr === 0) {
|
|
30613
31140
|
this.push(P[i], this.joinSide(s, "R"));
|
|
30614
31141
|
} else {
|
|
@@ -30620,7 +31147,7 @@ var Outliner = class {
|
|
|
30620
31147
|
const i = (m - j) % m;
|
|
30621
31148
|
const s = segs2[i];
|
|
30622
31149
|
const t = segs2[(i + m - 1) % m];
|
|
30623
|
-
const tr = turnSign(t.
|
|
31150
|
+
const tr = turnSign(t.tx, t.ty, s.tx, s.ty);
|
|
30624
31151
|
if (tr === 0) {
|
|
30625
31152
|
this.push(P[i], this.joinSide(s, "L"));
|
|
30626
31153
|
} else {
|
|
@@ -30640,6 +31167,14 @@ var Outliner = class {
|
|
|
30640
31167
|
this.flush();
|
|
30641
31168
|
}
|
|
30642
31169
|
};
|
|
31170
|
+
function nearestUnit(v) {
|
|
31171
|
+
return Math.sign(v) * Math.floor((Math.abs(v) + 8) / 16) * 16;
|
|
31172
|
+
}
|
|
31173
|
+
function cutCoordinate(x0, d, t, len) {
|
|
31174
|
+
const offset = Math.abs(d) * (t / len);
|
|
31175
|
+
const v = Math.fround(x0 + (d < 0 ? -offset : offset));
|
|
31176
|
+
return d < 0 ? Math.ceil(v - 0.5) : Math.floor(v + 0.5);
|
|
31177
|
+
}
|
|
30643
31178
|
function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors, metric, matrix) {
|
|
30644
31179
|
const out = [];
|
|
30645
31180
|
const dashes = [];
|
|
@@ -30662,7 +31197,7 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
|
|
|
30662
31197
|
const dir = [x1 - x0, y1 - y0];
|
|
30663
31198
|
const det = matrix ? matrix[0] * matrix[3] - matrix[1] * matrix[2] : 1;
|
|
30664
31199
|
const real = matrix ? Math.hypot((matrix[3] * dir[0] - matrix[2] * dir[1]) / det, (-matrix[1] * dir[0] + matrix[0] * dir[1]) / det) : metric ? Math.hypot(dir[0] / metric[0], dir[1] / metric[1]) : norm(dir[0], dir[1]);
|
|
30665
|
-
const len = metric
|
|
31200
|
+
const len = metric ? norm(nearestUnit(dir[0] / metric[0]), nearestUnit(dir[1] / metric[1])) : matrix ? norm(nearestUnit((matrix[3] * dir[0] - matrix[2] * dir[1]) / det), nearestUnit((-matrix[1] * dir[0] + matrix[0] * dir[1]) / det)) : wholePixelVectors ? norm(Math.floor(dir[0] / 16), Math.floor(dir[1] / 16)) * 16 : norm(dir[0], dir[1]);
|
|
30666
31201
|
if (len === 0) {
|
|
30667
31202
|
if (on && cur) {
|
|
30668
31203
|
cur.pts.push(P[i + 1]);
|
|
@@ -30675,7 +31210,7 @@ function dashPieces(P, tangents, curveFlags, pattern, shorten, wholePixelVectors
|
|
|
30675
31210
|
let t = 0;
|
|
30676
31211
|
while (len - t > left || left === 0 && on) {
|
|
30677
31212
|
t += left;
|
|
30678
|
-
const q = [
|
|
31213
|
+
const q = [cutCoordinate(x0, dir[0], t, len), cutCoordinate(y0, dir[1], t, len)];
|
|
30679
31214
|
if (on && cur) {
|
|
30680
31215
|
cur.pts.push(q);
|
|
30681
31216
|
cur.dirs.push(dir);
|
|
@@ -30732,7 +31267,7 @@ function widenInLogicalSpace(path, opts, m) {
|
|
|
30732
31267
|
});
|
|
30733
31268
|
}
|
|
30734
31269
|
function widenPath(path, opts) {
|
|
30735
|
-
if (opts.matrix && !
|
|
31270
|
+
if (opts.matrix && !opts.deviceNib) {
|
|
30736
31271
|
return widenInLogicalSpace(path, opts, opts.matrix);
|
|
30737
31272
|
}
|
|
30738
31273
|
const out = [];
|
|
@@ -30786,7 +31321,7 @@ function widenPath(path, opts) {
|
|
|
30786
31321
|
}
|
|
30787
31322
|
return out;
|
|
30788
31323
|
}
|
|
30789
|
-
function miterPoint(sa, da, sb, db, width, limit, side, height = width) {
|
|
31324
|
+
function miterPoint(sa, da, sb, db, width, limit, side, height = width, matrix) {
|
|
30790
31325
|
const den = da[0] * db[1] - da[1] * db[0];
|
|
30791
31326
|
if (den === 0) {
|
|
30792
31327
|
return null;
|
|
@@ -30799,6 +31334,12 @@ function miterPoint(sa, da, sb, db, width, limit, side, height = width) {
|
|
|
30799
31334
|
const x = Math.sign(mx) * Math.floor(Math.abs(mx) + 0.5);
|
|
30800
31335
|
const y = Math.sign(my) * Math.floor(Math.abs(my) + 0.5);
|
|
30801
31336
|
const pixel = side === "L" ? Math.ceil : Math.floor;
|
|
31337
|
+
if (matrix) {
|
|
31338
|
+
const det = matrix[0] * matrix[3] - matrix[1] * matrix[2];
|
|
31339
|
+
const lx = (matrix[3] * x - matrix[2] * y) / det;
|
|
31340
|
+
const ly = (-matrix[1] * x + matrix[0] * y) / det;
|
|
31341
|
+
return Math.hypot(Math.round(lx / 16), Math.round(ly / 16)) > limit * width / 32 ? null : [x, y];
|
|
31342
|
+
}
|
|
30802
31343
|
const yDistance = height === width ? pixel(y / 16) : pixel(y / 16) * width / height;
|
|
30803
31344
|
if (Math.hypot(pixel(x / 16), yDistance) > limit * width / 32) {
|
|
30804
31345
|
return null;
|
|
@@ -30882,9 +31423,12 @@ function boxFrame(box) {
|
|
|
30882
31423
|
const h = Math.round(Math.hypot(box.eyx, box.eyy));
|
|
30883
31424
|
return { l: 0, t: 0, r: w, b: h };
|
|
30884
31425
|
}
|
|
30885
|
-
function roundRectDeviceBeziers(box, cw, ch,
|
|
31426
|
+
function roundRectDeviceBeziers(box, cw, ch, recordedClockwise = false, compatible = false) {
|
|
30886
31427
|
const f = boxFrame(box);
|
|
30887
|
-
const
|
|
31428
|
+
const mirrorX = isAxisBox(box) && box.exx < 0;
|
|
31429
|
+
const mirrorY = isAxisBox(box) && box.eyy < 0;
|
|
31430
|
+
const clockwise = recordedClockwise !== mirrorY;
|
|
31431
|
+
const q = roundRectCorners(f.l, f.t, f.r, f.b, cw, ch, compatible, clockwise, mirrorX);
|
|
30888
31432
|
const map = frameMapper(box, f.l, f.t, f.r - f.l, f.b - f.t);
|
|
30889
31433
|
const pts = [];
|
|
30890
31434
|
for (let i = 0; i < q.length; i += 2) {
|
|
@@ -30936,6 +31480,11 @@ function roundRectDeviceBeziers(box, cw, ch, clockwise = false, compatible = fal
|
|
|
30936
31480
|
set(15, null, f.b - hy);
|
|
30937
31481
|
}
|
|
30938
31482
|
}
|
|
31483
|
+
if (mirrorX) {
|
|
31484
|
+
for (let i = 0; i < pts.length; i += 2) {
|
|
31485
|
+
pts[i] = f.l + f.r - pts[i];
|
|
31486
|
+
}
|
|
31487
|
+
}
|
|
30939
31488
|
return pts;
|
|
30940
31489
|
}
|
|
30941
31490
|
function roundRectRasterPath(box, cw, ch, clockwise = false, rectangle = false, compatible = false) {
|
|
@@ -30949,7 +31498,7 @@ function roundRectRasterPath(box, cw, ch, clockwise = false, rectangle = false,
|
|
|
30949
31498
|
path.closeFigure();
|
|
30950
31499
|
return path;
|
|
30951
31500
|
}
|
|
30952
|
-
function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPath()) {
|
|
31501
|
+
function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPath(), mirror2) {
|
|
30953
31502
|
const f = boxFrame(box);
|
|
30954
31503
|
const map = frameMapper(box, f.l, f.t, f.r - f.l, f.b - f.t);
|
|
30955
31504
|
let sx = s[0];
|
|
@@ -30971,12 +31520,19 @@ function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPat
|
|
|
30971
31520
|
if (det < 0) {
|
|
30972
31521
|
cw = !cw;
|
|
30973
31522
|
}
|
|
31523
|
+
} else if (mirror2) {
|
|
31524
|
+
cw = clockwise !== mirror2.y;
|
|
31525
|
+
if (mirror2.x) {
|
|
31526
|
+
sx = f.l + f.r - sx;
|
|
31527
|
+
ex = f.l + f.r - ex;
|
|
31528
|
+
}
|
|
30974
31529
|
} else {
|
|
30975
31530
|
if (box.exx < 0 !== box.eyy < 0) {
|
|
30976
31531
|
cw = !cw;
|
|
30977
31532
|
}
|
|
30978
31533
|
}
|
|
30979
|
-
const
|
|
31534
|
+
const mirrorX = !!mirror2?.x && isAxisBox(box);
|
|
31535
|
+
const bz = arcBeziers(f.l, f.t, f.r, f.b, sx, sy, ex, ey, cw, !!box.halfX, !!box.framed, mirrorX);
|
|
30980
31536
|
const pts = [];
|
|
30981
31537
|
for (let i = 0; i < bz.length; i += 2) {
|
|
30982
31538
|
pts.push(...map(bz[i], bz[i + 1]));
|
|
@@ -30990,7 +31546,7 @@ function arcRasterPath(box, s, e, clockwise, kind, from, path = new GdiRasterPat
|
|
|
30990
31546
|
if (kind === "pie") {
|
|
30991
31547
|
const w = f.r - f.l;
|
|
30992
31548
|
const h = f.b - f.t;
|
|
30993
|
-
const [cx, cy] = map(f.l + Math.ceil(w / 2) + (box.halfX ? 1 : 0), f.t + Math.ceil(h / 2));
|
|
31549
|
+
const [cx, cy] = map(f.l + Math.ceil(w / 2) + (box.halfX && !mirrorX ? 1 : 0), f.t + Math.ceil(h / 2));
|
|
30994
31550
|
path.lineTo(cx, cy);
|
|
30995
31551
|
}
|
|
30996
31552
|
if (kind === "pie" || kind === "chord") {
|
|
@@ -31031,8 +31587,10 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
31031
31587
|
const rotatedOrSheared = Math.abs(matrix[1]) >= 1e-6 || Math.abs(matrix[2]) >= 1e-6;
|
|
31032
31588
|
const quarterTurn = Math.abs(matrix[0]) < 1e-9 && Math.abs(matrix[3]) < 1e-9;
|
|
31033
31589
|
const general = !rCtx.wholeDevicePixels && rotatedOrSheared && !quarterTurn && Math.abs(det) > 1e-9 && state.penWidth * Math.sqrt(Math.abs(det)) * 16 >= 1;
|
|
31034
|
-
const
|
|
31035
|
-
const
|
|
31590
|
+
const unrotated = Math.abs(matrix[1]) < 1e-6 && Math.abs(matrix[2]) < 1e-6;
|
|
31591
|
+
const scaled2 = !rCtx.wholeDevicePixels && unrotated && (Math.abs(Math.abs(matrix[0]) - 1) > 1e-6 || Math.abs(Math.abs(matrix[3]) - 1) > 1e-6);
|
|
31592
|
+
const dashes = state.penExtended ? ellipse || general || scaled2 ? geometricStyle(flags, state.penWidth, state.penUserStyle, 1) : geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
|
|
31593
|
+
const dashMetric = (ellipse || scaled2) && !general && dashes ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : void 0;
|
|
31036
31594
|
if (general) {
|
|
31037
31595
|
return {
|
|
31038
31596
|
width: Math.round(state.penWidth * 16),
|
|
@@ -31047,8 +31605,6 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
31047
31605
|
cutToLogicalUnits: !dashes
|
|
31048
31606
|
};
|
|
31049
31607
|
}
|
|
31050
|
-
const unrotated = Math.abs(matrix[1]) < 1e-6 && Math.abs(matrix[2]) < 1e-6;
|
|
31051
|
-
const scaled2 = !rCtx.wholeDevicePixels && unrotated && (Math.abs(Math.abs(matrix[0]) - 1) > 1e-6 || Math.abs(Math.abs(matrix[3]) - 1) > 1e-6);
|
|
31052
31608
|
const uniform = scaled2 && !ellipse && state.penExtended && (flags & 15) !== 6;
|
|
31053
31609
|
return {
|
|
31054
31610
|
width: Math.round((ellipse ? state.penWidth * Math.abs(matrix[0]) : widthPx) * 16),
|
|
@@ -31062,7 +31618,7 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
31062
31618
|
// One logical unit per device pixel, unrotated: GDI measures dash
|
|
31063
31619
|
// segments in whole pixels.
|
|
31064
31620
|
wholePixelDashVectors: Math.abs(matrix[0] - 1) < 1e-6 && Math.abs(matrix[3] - 1) < 1e-6 && Math.abs(matrix[1]) < 1e-6 && Math.abs(matrix[2]) < 1e-6,
|
|
31065
|
-
...scaled2
|
|
31621
|
+
...scaled2 ? {
|
|
31066
31622
|
cutToLogicalUnits: true,
|
|
31067
31623
|
logicalScale: ellipse ? [Math.abs(matrix[0]), Math.abs(matrix[3])] : Math.abs(matrix[0]),
|
|
31068
31624
|
// A square cap extends by half the unrounded width in FIX.
|
|
@@ -31495,6 +32051,406 @@ function withoutOutline(spans, path) {
|
|
|
31495
32051
|
return out;
|
|
31496
32052
|
}
|
|
31497
32053
|
|
|
32054
|
+
// src/emf-plus-path-gradient-copies.ts
|
|
32055
|
+
var fix = (v) => Math.floor(v * 16 + 0.5) / 16;
|
|
32056
|
+
var TIE = 1e-6;
|
|
32057
|
+
var STRIP_TIE = 5e-3;
|
|
32058
|
+
var CONTAINMENT_TIE = 5e-4;
|
|
32059
|
+
var SLANTED_NEAR = 5e-6;
|
|
32060
|
+
var CEIL_EPSILON = 1e-9;
|
|
32061
|
+
function prepareCopies(shape, full, steps) {
|
|
32062
|
+
const n = shape.boundary.length;
|
|
32063
|
+
if (n < 3 || steps <= 0) return null;
|
|
32064
|
+
const isotropic = !shape.focus || Math.abs(shape.focus.x - shape.focus.y) <= 1e-9;
|
|
32065
|
+
const focus = shape.focus && isotropic ? Math.min(1, Math.max(0, shape.focus.x)) : 0;
|
|
32066
|
+
const vx = new Float64Array(n);
|
|
32067
|
+
const vy = new Float64Array(n);
|
|
32068
|
+
for (let i = 0; i < n; i++) {
|
|
32069
|
+
const p = shape.boundary[i];
|
|
32070
|
+
vx[i] = fix(full[0] * p.x + full[2] * p.y + full[4]);
|
|
32071
|
+
vy[i] = fix(full[1] * p.x + full[3] * p.y + full[5]);
|
|
32072
|
+
}
|
|
32073
|
+
const c = shape.center;
|
|
32074
|
+
const cx = fix(full[0] * c.x + full[2] * c.y + full[4]);
|
|
32075
|
+
const cy = fix(full[1] * c.x + full[3] * c.y + full[5]);
|
|
32076
|
+
const anisotropic = isotropic ? null : {
|
|
32077
|
+
...shape,
|
|
32078
|
+
boundary: Array.from(vx, (x, i) => ({ x, y: vy[i] })),
|
|
32079
|
+
center: { x: cx, y: cy },
|
|
32080
|
+
boundaryArgb: shape.boundaryArgb,
|
|
32081
|
+
blend: null,
|
|
32082
|
+
preset: null,
|
|
32083
|
+
transform: null
|
|
32084
|
+
};
|
|
32085
|
+
let degenerate = false;
|
|
32086
|
+
for (let i = 0; i < n; i++) {
|
|
32087
|
+
const j = (i + 1) % n;
|
|
32088
|
+
if ((vx[i] - cx) * (vy[j] - cy) - (vy[i] - cy) * (vx[j] - cx) === 0) degenerate = true;
|
|
32089
|
+
}
|
|
32090
|
+
return { cx, cy, vx, vy, steps, focus, anisotropic, degenerate };
|
|
32091
|
+
}
|
|
32092
|
+
function floatCopyIndex(g, edge, dx, dy) {
|
|
32093
|
+
const n = g.vx.length;
|
|
32094
|
+
const ax = g.vx[edge] - g.cx;
|
|
32095
|
+
const ay = g.vy[edge] - g.cy;
|
|
32096
|
+
const ex = g.vx[(edge + 1) % n] - g.vx[edge];
|
|
32097
|
+
const ey = g.vy[(edge + 1) % n] - g.vy[edge];
|
|
32098
|
+
const denominator = down32(down32(ex * dy) - down32(ey * dx));
|
|
32099
|
+
if (denominator === 0) return null;
|
|
32100
|
+
const u = down32(down32(down32(ay * dx) - down32(ax * dy)) / denominator);
|
|
32101
|
+
const bx = down32(ax + down32(u * ex));
|
|
32102
|
+
const by = down32(ay + down32(u * ey));
|
|
32103
|
+
const useX = Math.abs(bx) >= Math.abs(by);
|
|
32104
|
+
const boundary = useX ? bx : by;
|
|
32105
|
+
if (boundary === 0) return null;
|
|
32106
|
+
const r = Math.abs(down32((useX ? dx : dy) / boundary));
|
|
32107
|
+
return Math.max(0, Math.floor(down32(down32(g.steps * r) + 0.5)));
|
|
32108
|
+
}
|
|
32109
|
+
function focusCopyIndex(g, edge, px, py) {
|
|
32110
|
+
const n = g.vx.length;
|
|
32111
|
+
const dx = px - g.cx;
|
|
32112
|
+
const dy = py - g.cy;
|
|
32113
|
+
const f = Math.fround(g.focus);
|
|
32114
|
+
const j = (edge + 1) % n;
|
|
32115
|
+
const ax = g.vx[edge] - g.cx;
|
|
32116
|
+
const ay = g.vy[edge] - g.cy;
|
|
32117
|
+
const ex = g.vx[j] - g.vx[edge];
|
|
32118
|
+
const ey = g.vy[j] - g.vy[edge];
|
|
32119
|
+
const denominator = down32(down32(ex * dy) - down32(ey * dx));
|
|
32120
|
+
if (denominator === 0) return null;
|
|
32121
|
+
const u = down32(down32(down32(ay * dx) - down32(ax * dy)) / denominator);
|
|
32122
|
+
const bx = down32(ax + down32(u * ex));
|
|
32123
|
+
const by = down32(ay + down32(u * ey));
|
|
32124
|
+
const useX = Math.abs(bx) >= Math.abs(by);
|
|
32125
|
+
const b = useX ? bx : by;
|
|
32126
|
+
if (b === 0) return null;
|
|
32127
|
+
const c = useX ? g.cx : g.cy;
|
|
32128
|
+
const p = useX ? px : py;
|
|
32129
|
+
const outer = down32(c + b);
|
|
32130
|
+
const scaled2 = (c0, v) => down32(c0 + down32(f * (v - c0)));
|
|
32131
|
+
const f0x = scaled2(g.cx, g.vx[edge]);
|
|
32132
|
+
const f0y = scaled2(g.cy, g.vy[edge]);
|
|
32133
|
+
const f1x = scaled2(g.cx, g.vx[j]);
|
|
32134
|
+
const f1y = scaled2(g.cy, g.vy[j]);
|
|
32135
|
+
const fax = down32(f0x - g.cx);
|
|
32136
|
+
const fay = down32(f0y - g.cy);
|
|
32137
|
+
const fex = down32(f1x - f0x);
|
|
32138
|
+
const fey = down32(f1y - f0y);
|
|
32139
|
+
const focusDenominator = down32(down32(fex * dy) - down32(fey * dx));
|
|
32140
|
+
if (focusDenominator === 0) return null;
|
|
32141
|
+
const fu = down32(down32(down32(fay * dx) - down32(fax * dy)) / focusDenominator);
|
|
32142
|
+
const inner = down32((useX ? f0x : f0y) + down32(fu * (useX ? fex : fey)));
|
|
32143
|
+
const span = Math.fround(outer - inner);
|
|
32144
|
+
if (span === 0) return null;
|
|
32145
|
+
const t = down32(Math.fround(p - inner) / span);
|
|
32146
|
+
const position = Math.fround(down32(g.steps * t) + 0.5);
|
|
32147
|
+
if (ex !== 0 && ey !== 0) {
|
|
32148
|
+
const ulp = (v) => 2 ** (Math.floor(Math.log2(Math.abs(v) || 1)) - 23);
|
|
32149
|
+
const slack = g.steps * (ulp(inner) + ulp(outer)) / Math.abs(span);
|
|
32150
|
+
const short = Math.ceil(position) - position;
|
|
32151
|
+
if (short > 0 && short <= slack) return null;
|
|
32152
|
+
}
|
|
32153
|
+
return Math.max(0, Math.floor(position));
|
|
32154
|
+
}
|
|
32155
|
+
function tieSide(g, edge, dx, dy, q, focus = 0) {
|
|
32156
|
+
const n = g.vx.length;
|
|
32157
|
+
const ex = g.vx[(edge + 1) % n] - g.vx[edge];
|
|
32158
|
+
const ey = g.vy[(edge + 1) % n] - g.vy[edge];
|
|
32159
|
+
if (ex === 0 && ey === 0) return null;
|
|
32160
|
+
const adx = Math.abs(dx);
|
|
32161
|
+
const ady = Math.abs(dy);
|
|
32162
|
+
let odd = g.steps;
|
|
32163
|
+
while (odd % 2 === 0) odd /= 2;
|
|
32164
|
+
const fractional = (2 * q + 1) % odd !== 0;
|
|
32165
|
+
const axisAligned = ex === 0 || ey === 0;
|
|
32166
|
+
const alike = axisAligned ? ex === 0 ? adx <= ady : ady <= adx : Math.abs(ex) === Math.abs(ey) || Math.abs(ex) > Math.abs(ey) === adx > ady;
|
|
32167
|
+
if (!alike) return axisAligned ? fractional : null;
|
|
32168
|
+
const forward = ex > 0 || ex === 0 && ey > 0;
|
|
32169
|
+
if (!forward) return focus > 0 && !axisAligned ? null : fractional;
|
|
32170
|
+
if (dx * ex + dy * ey < 0) return fractional || !edgeParameterIsBinary(g, edge, dx, dy, q);
|
|
32171
|
+
return fractional && adx === ady;
|
|
32172
|
+
}
|
|
32173
|
+
function gcd(a, b) {
|
|
32174
|
+
while (b) [a, b] = [b, a % b];
|
|
32175
|
+
return a;
|
|
32176
|
+
}
|
|
32177
|
+
function edgeParameterIsBinary(g, edge, dx, dy, q) {
|
|
32178
|
+
const n = g.vx.length;
|
|
32179
|
+
const k = 16;
|
|
32180
|
+
const ex = Math.round((g.vx[(edge + 1) % n] - g.vx[edge]) * k);
|
|
32181
|
+
const ey = Math.round((g.vy[(edge + 1) % n] - g.vy[edge]) * k);
|
|
32182
|
+
const ax = Math.round((g.vx[edge] - g.cx) * k);
|
|
32183
|
+
const ay = Math.round((g.vy[edge] - g.cy) * k);
|
|
32184
|
+
const S = 2 * q + 1;
|
|
32185
|
+
const D = 2 * g.steps;
|
|
32186
|
+
const P = Math.round(dx * k) * ex + Math.round(dy * k) * ey;
|
|
32187
|
+
const A = ax * ex + ay * ey;
|
|
32188
|
+
const numerator = P * D - A * S;
|
|
32189
|
+
const denominator = (ex * ex + ey * ey) * S;
|
|
32190
|
+
if (!Number.isSafeInteger(numerator) || !Number.isSafeInteger(denominator)) return false;
|
|
32191
|
+
if (numerator === 0) return true;
|
|
32192
|
+
let d = Math.abs(denominator / gcd(Math.abs(numerator), Math.abs(denominator)));
|
|
32193
|
+
while (d % 2 === 0) d /= 2;
|
|
32194
|
+
return d === 1;
|
|
32195
|
+
}
|
|
32196
|
+
function insideCopy(g, scale, px, py, scaleY = scale) {
|
|
32197
|
+
const n = g.vx.length;
|
|
32198
|
+
let xl = Infinity;
|
|
32199
|
+
let xr = -Infinity;
|
|
32200
|
+
let ax = g.cx + (g.vx[n - 1] - g.cx) * scale;
|
|
32201
|
+
let ay = g.cy + (g.vy[n - 1] - g.cy) * scaleY;
|
|
32202
|
+
for (let i = 0; i < n; i++) {
|
|
32203
|
+
const bx = g.cx + (g.vx[i] - g.cx) * scale;
|
|
32204
|
+
const by = g.cy + (g.vy[i] - g.cy) * scaleY;
|
|
32205
|
+
if (ay <= py && by > py || by <= py && ay > py) {
|
|
32206
|
+
const x = ax + (py - ay) / (by - ay) * (bx - ax);
|
|
32207
|
+
if (x < xl) xl = x;
|
|
32208
|
+
if (x > xr) xr = x;
|
|
32209
|
+
}
|
|
32210
|
+
ax = bx;
|
|
32211
|
+
ay = by;
|
|
32212
|
+
}
|
|
32213
|
+
return xl !== Infinity && px >= Math.ceil(xl - CEIL_EPSILON) && px < Math.ceil(xr - CEIL_EPSILON);
|
|
32214
|
+
}
|
|
32215
|
+
function edgeAt(g, scaleX, scaleY, px, py) {
|
|
32216
|
+
const n = g.vx.length;
|
|
32217
|
+
const near = 1e-6;
|
|
32218
|
+
let hit = null;
|
|
32219
|
+
let vertexRow = false;
|
|
32220
|
+
for (let i = 0; i < n; i++) {
|
|
32221
|
+
const j = (i + 1) % n;
|
|
32222
|
+
const ax = g.cx + (g.vx[i] - g.cx) * scaleX;
|
|
32223
|
+
const ay = g.cy + (g.vy[i] - g.cy) * scaleY;
|
|
32224
|
+
const bx = g.cx + (g.vx[j] - g.cx) * scaleX;
|
|
32225
|
+
const by = g.cy + (g.vy[j] - g.cy) * scaleY;
|
|
32226
|
+
if (Math.abs(ax - bx) < near && Math.abs(px - ax) < near && py >= Math.min(ay, by) - near && py <= Math.max(ay, by) + near) return { kind: "vertical", edge: i };
|
|
32227
|
+
if (Math.abs(ay - by) < near && Math.abs(py - ay) < near && px >= Math.min(ax, bx) - near && px <= Math.max(ax, bx) + near) return { kind: "horizontal", edge: i };
|
|
32228
|
+
if (Math.abs(ay - py) < near) vertexRow = true;
|
|
32229
|
+
const length = Math.hypot(bx - ax, by - ay);
|
|
32230
|
+
if (length < near) continue;
|
|
32231
|
+
const across = ((px - ax) * (by - ay) - (py - ay) * (bx - ax)) / length;
|
|
32232
|
+
const along = ((px - ax) * (bx - ax) + (py - ay) * (by - ay)) / (length * length);
|
|
32233
|
+
if (Math.abs(across) < SLANTED_NEAR && along >= -near && along <= 1 + near) hit = { kind: "slanted", edge: i };
|
|
32234
|
+
}
|
|
32235
|
+
return hit ?? (vertexRow ? { kind: "slanted", edge: -1 } : null);
|
|
32236
|
+
}
|
|
32237
|
+
function focusedEdgeStep(g, px, py) {
|
|
32238
|
+
const focus = g.anisotropic.focus;
|
|
32239
|
+
const full = 1 - 1e-9;
|
|
32240
|
+
if (focus.x < full && focus.y < full) return void 0;
|
|
32241
|
+
const n = g.vx.length;
|
|
32242
|
+
let onEdge = false;
|
|
32243
|
+
for (let i = 0; i < n && !onEdge; i++) {
|
|
32244
|
+
const j = (i + 1) % n;
|
|
32245
|
+
const near = 1e-6;
|
|
32246
|
+
if (focus.x >= full && Math.abs(g.vx[i] - g.vx[j]) < near && Math.abs(px - g.vx[i]) < near && py >= Math.min(g.vy[i], g.vy[j]) - near && py <= Math.max(g.vy[i], g.vy[j]) + near) onEdge = true;
|
|
32247
|
+
if (focus.y >= full && Math.abs(g.vy[i] - g.vy[j]) < near && Math.abs(py - g.vy[i]) < near && px >= Math.min(g.vx[i], g.vx[j]) - near && px <= Math.max(g.vx[i], g.vx[j]) + near) onEdge = true;
|
|
32248
|
+
}
|
|
32249
|
+
if (!onEdge) return void 0;
|
|
32250
|
+
const fx = Math.min(1, Math.max(0, focus.x));
|
|
32251
|
+
const fy = Math.min(1, Math.max(0, focus.y));
|
|
32252
|
+
for (let m = 0; m <= g.steps; m++) {
|
|
32253
|
+
const along = m === g.steps ? 1 : (m + 0.5) / g.steps;
|
|
32254
|
+
if (insideCopy(g, fx + (1 - fx) * along, px, py, fy + (1 - fy) * along)) return g.steps - m;
|
|
32255
|
+
}
|
|
32256
|
+
return null;
|
|
32257
|
+
}
|
|
32258
|
+
function anisotropicTieStep(g, q, tie, dx, dy, px, py) {
|
|
32259
|
+
const focus = g.anisotropic.focus;
|
|
32260
|
+
const along = (tie + 0.5) / g.steps;
|
|
32261
|
+
const fx = Math.min(1, Math.max(0, focus.x));
|
|
32262
|
+
const fy = Math.min(1, Math.max(0, focus.y));
|
|
32263
|
+
const scaleX = fx + (1 - fx) * along;
|
|
32264
|
+
const scaleY = fy + (1 - fy) * along;
|
|
32265
|
+
const hit = edgeAt(g, scaleX, scaleY, px, py);
|
|
32266
|
+
const half = g.steps - tie - 0.5;
|
|
32267
|
+
if (hit?.kind === "slanted") return half;
|
|
32268
|
+
if (hit === null && Math.abs(q - tie) >= CONTAINMENT_TIE) return half;
|
|
32269
|
+
if (hit === null) return g.steps - tie - (insideCopy(g, scaleX, px, py, scaleY) ? 0 : 1);
|
|
32270
|
+
let odd = g.steps;
|
|
32271
|
+
while (odd % 2 === 0) odd /= 2;
|
|
32272
|
+
const fractional = (2 * tie + 1) % odd !== 0;
|
|
32273
|
+
const vertical = hit.kind === "vertical";
|
|
32274
|
+
if (vertical ? Math.abs(dx) > Math.abs(dy) : Math.abs(dy) > Math.abs(dx)) return g.steps - tie - (fractional ? 0 : 1);
|
|
32275
|
+
const n = g.vx.length;
|
|
32276
|
+
const ex = g.vx[(hit.edge + 1) % n] - g.vx[hit.edge];
|
|
32277
|
+
const ey = g.vy[(hit.edge + 1) % n] - g.vy[hit.edge];
|
|
32278
|
+
if (!(ex > 0 || ex === 0 && ey > 0)) return g.steps - tie - (fractional ? 0 : 1);
|
|
32279
|
+
if (dx * ex + dy * ey >= 0) return g.steps - tie - (fractional && Math.abs(dx) === Math.abs(dy) ? 0 : 1);
|
|
32280
|
+
const ax = g.cx + (g.vx[hit.edge] - g.cx) * scaleX;
|
|
32281
|
+
const ay = g.cy + (g.vy[hit.edge] - g.cy) * scaleY;
|
|
32282
|
+
const u = vertical ? (py - ay) / (ey * scaleY) : (px - ax) / (ex * scaleX);
|
|
32283
|
+
const scaled2 = u * 2 ** 24;
|
|
32284
|
+
const binary = Math.abs(scaled2 - Math.round(scaled2)) < 1e-4;
|
|
32285
|
+
return g.steps - tie - (fractional || !binary ? 0 : 1);
|
|
32286
|
+
}
|
|
32287
|
+
function copiesStepAt(g, px, py, nudge = 0) {
|
|
32288
|
+
const n = g.vx.length;
|
|
32289
|
+
let s = -1;
|
|
32290
|
+
let edge = -1;
|
|
32291
|
+
const dx = px - g.cx;
|
|
32292
|
+
const dy = py - g.cy;
|
|
32293
|
+
for (let i = 0; i < n; i++) {
|
|
32294
|
+
const ax = g.vx[i] - g.cx;
|
|
32295
|
+
const ay = g.vy[i] - g.cy;
|
|
32296
|
+
const ex = g.vx[(i + 1) % n] - g.vx[i];
|
|
32297
|
+
const ey = g.vy[(i + 1) % n] - g.vy[i];
|
|
32298
|
+
const det = ax * ey - ay * ex;
|
|
32299
|
+
if (Math.abs(det) < 1e-12) continue;
|
|
32300
|
+
const alpha = (dx * ey - dy * ex) / det;
|
|
32301
|
+
const beta = (ax * dy - ay * dx) / det;
|
|
32302
|
+
if (alpha < -1e-9 || beta < -1e-9 || beta > alpha + 1e-9 || alpha > 1 + 1e-9) continue;
|
|
32303
|
+
s = alpha;
|
|
32304
|
+
edge = i;
|
|
32305
|
+
}
|
|
32306
|
+
if (g.anisotropic) {
|
|
32307
|
+
const edge2 = s > 1 - 1e-9;
|
|
32308
|
+
const column2 = focusedEdgeStep(g, px, py);
|
|
32309
|
+
if (column2 !== void 0) return column2;
|
|
32310
|
+
const ratio = pathGradientRatio(g.anisotropic, px + nudge, py, { x: px, y: py });
|
|
32311
|
+
if (ratio === null) return null;
|
|
32312
|
+
if (edge2) return Math.max(0, g.steps * (1 - ratio));
|
|
32313
|
+
s = ratio;
|
|
32314
|
+
}
|
|
32315
|
+
if (s < 0) return null;
|
|
32316
|
+
if (g.degenerate && !insideCopy(g, 1, px, py)) return null;
|
|
32317
|
+
if (!g.anisotropic && g.focus === 0 && edge >= 0) {
|
|
32318
|
+
const m2 = floatCopyIndex(g, edge, dx, dy);
|
|
32319
|
+
if (m2 !== null) {
|
|
32320
|
+
if (m2 >= g.steps && !insideCopy(g, 1, px, py)) return null;
|
|
32321
|
+
return g.steps - Math.min(m2, g.steps);
|
|
32322
|
+
}
|
|
32323
|
+
}
|
|
32324
|
+
if (!g.anisotropic && g.focus > 0 && g.focus < 1 && edge >= 0 && !(px === g.cx && py === g.cy)) {
|
|
32325
|
+
const m2 = focusCopyIndex(g, edge, px, py);
|
|
32326
|
+
if (m2 !== null) {
|
|
32327
|
+
if (m2 >= g.steps && !insideCopy(g, 1, px, py)) return null;
|
|
32328
|
+
return g.steps - Math.min(m2, g.steps);
|
|
32329
|
+
}
|
|
32330
|
+
}
|
|
32331
|
+
const f = g.focus;
|
|
32332
|
+
const q = s <= f ? 0 : (s - f) / (1 - f) * g.steps - 0.5;
|
|
32333
|
+
if (q > 0 && Math.abs(q - Math.round(q)) < (g.anisotropic ? STRIP_TIE : TIE)) {
|
|
32334
|
+
const tie = Math.round(q);
|
|
32335
|
+
if (g.anisotropic) return anisotropicTieStep(g, q, tie, dx, dy, px, py);
|
|
32336
|
+
const decided = edge >= 0 ? tieSide(g, edge, dx, dy, tie, f) : null;
|
|
32337
|
+
if (decided !== null) return g.steps - tie - (decided ? 0 : 1);
|
|
32338
|
+
return g.steps - tie - 0.5;
|
|
32339
|
+
}
|
|
32340
|
+
const m = Math.max(0, Math.ceil(q));
|
|
32341
|
+
if (m >= g.steps && !insideCopy(g, 1, px, py)) return null;
|
|
32342
|
+
return g.steps - Math.min(m, g.steps);
|
|
32343
|
+
}
|
|
32344
|
+
|
|
32345
|
+
// src/emf-plus-path-gradient-vertices.ts
|
|
32346
|
+
var FRACTION_BITS = 16;
|
|
32347
|
+
var ONE = 2 ** FRACTION_BITS;
|
|
32348
|
+
var CEIL_EPSILON2 = 1e-9;
|
|
32349
|
+
var snap = (v) => Math.ceil(v * 16 - 1e-9) / 16;
|
|
32350
|
+
function premultiplied2(argb) {
|
|
32351
|
+
const a = argb >>> 24;
|
|
32352
|
+
return [a, (argb >>> 16 & 255) * a / 255, (argb >>> 8 & 255) * a / 255, (argb & 255) * a / 255];
|
|
32353
|
+
}
|
|
32354
|
+
function prepareVertexGradient(shape, full) {
|
|
32355
|
+
const n = shape.boundary.length;
|
|
32356
|
+
if (n < 3 || shape.preset || shape.blend || shape.boundaryArgb.length < n) {
|
|
32357
|
+
return null;
|
|
32358
|
+
}
|
|
32359
|
+
if (shape.boundaryArgb.every((color) => color === shape.boundaryArgb[0])) {
|
|
32360
|
+
return null;
|
|
32361
|
+
}
|
|
32362
|
+
const vx = new Float64Array(n);
|
|
32363
|
+
const vy = new Float64Array(n);
|
|
32364
|
+
const vc = new Float64Array(n * 4);
|
|
32365
|
+
for (let i = 0; i < n; i++) {
|
|
32366
|
+
const p = shape.boundary[i];
|
|
32367
|
+
vx[i] = snap(full[0] * p.x + full[2] * p.y + full[4]);
|
|
32368
|
+
vy[i] = snap(full[1] * p.x + full[3] * p.y + full[5]);
|
|
32369
|
+
vc.set(premultiplied2(shape.boundaryArgb[i]), i * 4);
|
|
32370
|
+
}
|
|
32371
|
+
const c = shape.center;
|
|
32372
|
+
return {
|
|
32373
|
+
cx: snap(full[0] * c.x + full[2] * c.y + full[4]),
|
|
32374
|
+
cy: snap(full[1] * c.x + full[3] * c.y + full[5]),
|
|
32375
|
+
vx,
|
|
32376
|
+
vy,
|
|
32377
|
+
vc,
|
|
32378
|
+
cc: premultiplied2(shape.centerArgb)
|
|
32379
|
+
};
|
|
32380
|
+
}
|
|
32381
|
+
function edgeChannel(ax, ay, bx, by, ca, cb, x, y) {
|
|
32382
|
+
const dx = bx - ax;
|
|
32383
|
+
const dy = by - ay;
|
|
32384
|
+
let t = 0;
|
|
32385
|
+
if (Math.abs(dx) > Math.abs(dy)) {
|
|
32386
|
+
const steps = Math.trunc(Math.abs(dx));
|
|
32387
|
+
if (steps > 0) t = Math.abs(x - Math.floor(ax)) / steps;
|
|
32388
|
+
} else {
|
|
32389
|
+
const steps = Math.trunc(Math.abs(dy));
|
|
32390
|
+
if (steps > 0) t = Math.abs(y - Math.floor(ay)) / steps;
|
|
32391
|
+
}
|
|
32392
|
+
return Math.trunc((ca + (cb - ca) * t) * ONE);
|
|
32393
|
+
}
|
|
32394
|
+
function vertexGradientColorAt(g, px, py) {
|
|
32395
|
+
const n = g.vx.length;
|
|
32396
|
+
let result = null;
|
|
32397
|
+
const tx = [0, 0, 0];
|
|
32398
|
+
const ty = [0, 0, 0];
|
|
32399
|
+
const out = [0, 0, 0, 0];
|
|
32400
|
+
for (let f = 0; f < n; f++) {
|
|
32401
|
+
const f1 = (f + 1) % n;
|
|
32402
|
+
tx[0] = g.cx;
|
|
32403
|
+
tx[1] = g.vx[f];
|
|
32404
|
+
tx[2] = g.vx[f1];
|
|
32405
|
+
ty[0] = g.cy;
|
|
32406
|
+
ty[1] = g.vy[f];
|
|
32407
|
+
ty[2] = g.vy[f1];
|
|
32408
|
+
let left = -1;
|
|
32409
|
+
let right = -1;
|
|
32410
|
+
let xl = Infinity;
|
|
32411
|
+
let xr = -Infinity;
|
|
32412
|
+
for (let i = 0; i < 3; i++) {
|
|
32413
|
+
const j = (i + 1) % 3;
|
|
32414
|
+
const ay = ty[i];
|
|
32415
|
+
const by = ty[j];
|
|
32416
|
+
if (!(ay <= py && by > py || by <= py && ay > py)) continue;
|
|
32417
|
+
const x = tx[i] + (py - ay) / (by - ay) * (tx[j] - tx[i]);
|
|
32418
|
+
if (x < xl) {
|
|
32419
|
+
xl = x;
|
|
32420
|
+
left = i;
|
|
32421
|
+
}
|
|
32422
|
+
if (x > xr) {
|
|
32423
|
+
xr = x;
|
|
32424
|
+
right = i;
|
|
32425
|
+
}
|
|
32426
|
+
}
|
|
32427
|
+
if (left < 0 || right < 0 || left === right) continue;
|
|
32428
|
+
const xs = Math.ceil(xl - CEIL_EPSILON2);
|
|
32429
|
+
const xe = Math.ceil(xr - CEIL_EPSILON2);
|
|
32430
|
+
if (px < xs || px >= xe) continue;
|
|
32431
|
+
const li = left;
|
|
32432
|
+
const lj = (left + 1) % 3;
|
|
32433
|
+
const ri = right;
|
|
32434
|
+
const rj = (right + 1) % 3;
|
|
32435
|
+
for (let q = 0; q < 4; q++) {
|
|
32436
|
+
const colors = [g.cc[q], g.vc[f * 4 + q], g.vc[f1 * 4 + q]];
|
|
32437
|
+
const cL = edgeChannel(tx[li], ty[li], tx[lj], ty[lj], colors[li], colors[lj], xs, py);
|
|
32438
|
+
const cR = edgeChannel(tx[ri], ty[ri], tx[rj], ty[rj], colors[ri], colors[rj], xe, py);
|
|
32439
|
+
const step = Math.floor((cR - cL) / (xe - xs));
|
|
32440
|
+
const v = cL + step * (px - xs);
|
|
32441
|
+
out[q] = Math.max(0, Math.min(255, Math.floor((v + ONE / 2) / ONE)));
|
|
32442
|
+
}
|
|
32443
|
+
const alpha = out[0];
|
|
32444
|
+
if (alpha === 0) {
|
|
32445
|
+
result = 0;
|
|
32446
|
+
continue;
|
|
32447
|
+
}
|
|
32448
|
+
const ch = (premult) => Math.min(255, Math.round(premult * 255 / alpha));
|
|
32449
|
+
result = (alpha << 24 | ch(out[1]) << 16 | ch(out[2]) << 8 | ch(out[3])) >>> 0;
|
|
32450
|
+
}
|
|
32451
|
+
return result;
|
|
32452
|
+
}
|
|
32453
|
+
|
|
31498
32454
|
// src/emf-plus-exact-fill.ts
|
|
31499
32455
|
var IDENTITY4 = [1, 0, 0, 1, 0, 0];
|
|
31500
32456
|
var MAX_EXACT_PIXELS = 16 * 1024 * 1024;
|
|
@@ -31573,17 +32529,110 @@ function pixelAligned(boundary, m) {
|
|
|
31573
32529
|
}
|
|
31574
32530
|
return [x0, y0, x1, y1].every((v) => Math.abs(v - Math.round(v)) < 1e-6);
|
|
31575
32531
|
}
|
|
31576
|
-
|
|
32532
|
+
var TILE_WEIGHT_STEPS = 2048;
|
|
32533
|
+
function tileIndex(i, n, mirror2) {
|
|
32534
|
+
if (!mirror2) {
|
|
32535
|
+
return (i % n + n) % n;
|
|
32536
|
+
}
|
|
32537
|
+
const m = (i % (2 * n) + 2 * n) % (2 * n);
|
|
32538
|
+
return m < n ? m : 2 * n - 1 - m;
|
|
32539
|
+
}
|
|
32540
|
+
function fractionalTileSampler(shape, wrap, full) {
|
|
32541
|
+
if (Math.abs(full[1]) > 1e-9 || Math.abs(full[2]) > 1e-9 || full[0] <= 0 || full[3] <= 0) return null;
|
|
32542
|
+
if (!shape.boundaryArgb.every((color) => color === shape.boundaryArgb[0])) return null;
|
|
32543
|
+
let x0 = Infinity;
|
|
32544
|
+
let y0 = Infinity;
|
|
32545
|
+
let x1 = -Infinity;
|
|
32546
|
+
let y1 = -Infinity;
|
|
32547
|
+
for (const point of shape.boundary) {
|
|
32548
|
+
const x = full[0] * point.x + full[4];
|
|
32549
|
+
const y = full[3] * point.y + full[5];
|
|
32550
|
+
x0 = Math.min(x0, x);
|
|
32551
|
+
y0 = Math.min(y0, y);
|
|
32552
|
+
x1 = Math.max(x1, x);
|
|
32553
|
+
y1 = Math.max(y1, y);
|
|
32554
|
+
}
|
|
32555
|
+
const round = (v) => Math.floor(v + 0.5);
|
|
32556
|
+
const width = round(x1) - round(x0);
|
|
32557
|
+
const height = round(y1) - round(y0);
|
|
32558
|
+
if (!(x1 > x0) || !(y1 > y0) || width < 1 || height < 1 || width * height > 4 * 1024 * 1024) return null;
|
|
32559
|
+
const kx = width / (x1 - x0);
|
|
32560
|
+
const ky = height / (y1 - y0);
|
|
32561
|
+
const toTile = (point) => ({
|
|
32562
|
+
x: (full[0] * point.x + full[4] - x0) * kx,
|
|
32563
|
+
y: (full[3] * point.y + full[5] - y0) * ky
|
|
32564
|
+
});
|
|
32565
|
+
const inner = pathGradientSampler({
|
|
32566
|
+
...shape,
|
|
32567
|
+
boundary: shape.boundary.map(toTile),
|
|
32568
|
+
center: toTile(shape.center),
|
|
32569
|
+
transform: null
|
|
32570
|
+
}, "clamp", IDENTITY4, false);
|
|
32571
|
+
if (!inner) return null;
|
|
32572
|
+
const mirrorX = wrap === "tile-flip-x" || wrap === "tile-flip-xy";
|
|
32573
|
+
const mirrorY = wrap === "tile-flip-y" || wrap === "tile-flip-xy";
|
|
32574
|
+
let texels = null;
|
|
32575
|
+
const texel = () => {
|
|
32576
|
+
if (texels) return texels;
|
|
32577
|
+
const rgba = new Uint8ClampedArray(width * height * 4);
|
|
32578
|
+
inner(0, 0, width, height, rgba);
|
|
32579
|
+
texels = new Float64Array(width * height * 4);
|
|
32580
|
+
for (let i = 0; i < width * height; i++) {
|
|
32581
|
+
const a = rgba[i * 4 + 3];
|
|
32582
|
+
texels[i * 4] = rgba[i * 4] * a / 255;
|
|
32583
|
+
texels[i * 4 + 1] = rgba[i * 4 + 1] * a / 255;
|
|
32584
|
+
texels[i * 4 + 2] = rgba[i * 4 + 2] * a / 255;
|
|
32585
|
+
texels[i * 4 + 3] = a;
|
|
32586
|
+
}
|
|
32587
|
+
return texels;
|
|
32588
|
+
};
|
|
32589
|
+
return (px, py, w, h, out) => {
|
|
32590
|
+
const t = texel();
|
|
32591
|
+
for (let j = 0; j < h; j++) {
|
|
32592
|
+
const v = ky * (py + j - y0);
|
|
32593
|
+
const iv = Math.floor(v);
|
|
32594
|
+
const wy = Math.floor((v - iv) * TILE_WEIGHT_STEPS + 0.5) / TILE_WEIGHT_STEPS;
|
|
32595
|
+
const r0 = tileIndex(iv, height, mirrorY) * width;
|
|
32596
|
+
const r1 = tileIndex(iv + 1, height, mirrorY) * width;
|
|
32597
|
+
for (let i = 0; i < w; i++) {
|
|
32598
|
+
const u = kx * (px + i - x0);
|
|
32599
|
+
const iu = Math.floor(u);
|
|
32600
|
+
const wx = Math.floor((u - iu) * TILE_WEIGHT_STEPS + 0.5) / TILE_WEIGHT_STEPS;
|
|
32601
|
+
const c0 = tileIndex(iu, width, mirrorX);
|
|
32602
|
+
const c1 = tileIndex(iu + 1, width, mirrorX);
|
|
32603
|
+
const o = (j * w + i) * 4;
|
|
32604
|
+
const sample2 = (k) => (1 - wx) * (1 - wy) * t[(r0 + c0) * 4 + k] + wx * (1 - wy) * t[(r0 + c1) * 4 + k] + (1 - wx) * wy * t[(r1 + c0) * 4 + k] + wx * wy * t[(r1 + c1) * 4 + k];
|
|
32605
|
+
const coverage = sample2(3);
|
|
32606
|
+
const alpha = Math.floor(coverage + 0.5);
|
|
32607
|
+
if (alpha <= 0) {
|
|
32608
|
+
out[o] = out[o + 1] = out[o + 2] = out[o + 3] = 0;
|
|
32609
|
+
continue;
|
|
32610
|
+
}
|
|
32611
|
+
const scale = coverage >= 255 ? 1 : 255 / coverage;
|
|
32612
|
+
out[o] = Math.min(255, Math.floor(sample2(0) * scale + 0.5));
|
|
32613
|
+
out[o + 1] = Math.min(255, Math.floor(sample2(1) * scale + 0.5));
|
|
32614
|
+
out[o + 2] = Math.min(255, Math.floor(sample2(2) * scale + 0.5));
|
|
32615
|
+
out[o + 3] = alpha;
|
|
32616
|
+
}
|
|
32617
|
+
}
|
|
32618
|
+
};
|
|
32619
|
+
}
|
|
32620
|
+
function pathGradientSampler(shape, wrap, device, strictOutside = true) {
|
|
31577
32621
|
const box = boundaryBox2(shape.boundary);
|
|
31578
32622
|
const full = mulMatrix(device, shape.transform ?? IDENTITY4);
|
|
31579
32623
|
const inv2 = invertAffine(full);
|
|
31580
32624
|
if (!box || !inv2) {
|
|
31581
32625
|
return null;
|
|
31582
32626
|
}
|
|
31583
|
-
|
|
32627
|
+
if (wrap !== "clamp" && !pixelAligned(shape.boundary, full)) {
|
|
32628
|
+
const tiled = fractionalTileSampler(shape, wrap, full);
|
|
32629
|
+
if (tiled) return tiled;
|
|
32630
|
+
}
|
|
31584
32631
|
const uniformSurround = shape.boundaryArgb.every((color) => color === shape.boundaryArgb[0]);
|
|
31585
|
-
const smooth = !uniformSurround && !shape.preset ||
|
|
32632
|
+
const smooth = !uniformSurround && !shape.preset || wrap !== "clamp" && !pixelAligned(shape.boundary, full);
|
|
31586
32633
|
const quantum = smooth ? 0 : pathGradientQuantum(shape.boundary, full);
|
|
32634
|
+
const vertexGradient = wrap === "clamp" || pixelAligned(shape.boundary, full) ? prepareVertexGradient(shape, full) : null;
|
|
32635
|
+
const copies = quantum > 0 ? prepareCopies(shape, full, quantum) : null;
|
|
31587
32636
|
const pxX = Math.hypot(full[0], full[1]);
|
|
31588
32637
|
const pxY = Math.hypot(full[2], full[3]);
|
|
31589
32638
|
const lagX = pxX > 0 ? 1 / pxX : 0;
|
|
@@ -31604,7 +32653,25 @@ function pathGradientSampler(shape, wrap, device) {
|
|
|
31604
32653
|
}
|
|
31605
32654
|
if (wrap === "clamp" && by >= box.y + box.h) continue;
|
|
31606
32655
|
const focusPoint = bias ? { x: bx - inv2[0] * bias, y: by - inv2[1] * bias } : void 0;
|
|
31607
|
-
|
|
32656
|
+
let c = null;
|
|
32657
|
+
let decided = false;
|
|
32658
|
+
if (vertexGradient || copies) {
|
|
32659
|
+
const fx = wrap === "clamp" ? x0 + i : full[0] * bx + full[2] * by + full[4];
|
|
32660
|
+
const fy = wrap === "clamp" ? dy : full[1] * bx + full[3] * by + full[5];
|
|
32661
|
+
const rx = Math.round(fx);
|
|
32662
|
+
const ry = Math.round(fy);
|
|
32663
|
+
if (Math.abs(fx - rx) < 1e-6 && Math.abs(fy - ry) < 1e-6) {
|
|
32664
|
+
if (vertexGradient) {
|
|
32665
|
+
c = vertexGradientColorAt(vertexGradient, rx, ry);
|
|
32666
|
+
if (c === null && strictOutside) decided = true;
|
|
32667
|
+
} else if (copies) {
|
|
32668
|
+
const step = copiesStepAt(copies, rx, ry, bias);
|
|
32669
|
+
if (step !== null) c = pathGradientStepColor(shape, step, quantum);
|
|
32670
|
+
else if (strictOutside && !copies.anisotropic) decided = true;
|
|
32671
|
+
}
|
|
32672
|
+
}
|
|
32673
|
+
}
|
|
32674
|
+
if (c === null && !decided) c = pathGradientColorAt(shape, bx, by, focusPoint, quantum);
|
|
31608
32675
|
if (c === null) {
|
|
31609
32676
|
continue;
|
|
31610
32677
|
}
|
|
@@ -32205,6 +33272,23 @@ function handleLineTo(rCtx, dataOff, recSize) {
|
|
|
32205
33272
|
}
|
|
32206
33273
|
return true;
|
|
32207
33274
|
}
|
|
33275
|
+
function cosmeticRectangleBox(rCtx, box) {
|
|
33276
|
+
const { state } = rCtx;
|
|
33277
|
+
if (rCtx.inPath || state.penStyle === 5 || state.penStyle === 6 || box.exy !== 0 || box.eyx !== 0 || box.exx === 0 || box.eyy === 0 || !penIsCosmetic(rCtx)) {
|
|
33278
|
+
return box;
|
|
33279
|
+
}
|
|
33280
|
+
const ax = Math.ceil(box.ax / 16) * 16;
|
|
33281
|
+
const ay = Math.ceil(box.ay / 16) * 16;
|
|
33282
|
+
return { ...box, ax, ay, exx: Math.ceil((box.ax + box.exx) / 16) * 16 - ax, eyy: Math.ceil((box.ay + box.eyy) / 16) * 16 - ay };
|
|
33283
|
+
}
|
|
33284
|
+
function devicePositiveBox(box) {
|
|
33285
|
+
if (!isAxisBox(box) || box.exx >= 0 && box.eyy >= 0) {
|
|
33286
|
+
return box;
|
|
33287
|
+
}
|
|
33288
|
+
const ax = box.exx < 0 ? box.ax + box.exx : box.ax;
|
|
33289
|
+
const ay = box.eyy < 0 ? box.ay + box.eyy : box.ay;
|
|
33290
|
+
return { ...box, ax, ay, exx: Math.abs(box.exx), eyy: Math.abs(box.eyy) };
|
|
33291
|
+
}
|
|
32208
33292
|
function handleRectangle(rCtx, dataOff, recSize) {
|
|
32209
33293
|
const { ctx, view, state, inPath } = rCtx;
|
|
32210
33294
|
if (recSize >= 24) {
|
|
@@ -32212,7 +33296,7 @@ function handleRectangle(rCtx, dataOff, recSize) {
|
|
|
32212
33296
|
const t = view.getInt32(dataOff + 4, true);
|
|
32213
33297
|
const r = view.getInt32(dataOff + 8, true);
|
|
32214
33298
|
const b = view.getInt32(dataOff + 12, true);
|
|
32215
|
-
const unframed = uprightFixBox(rCtx, l, t, r, b);
|
|
33299
|
+
const unframed = cosmeticRectangleBox(rCtx, uprightFixBox(rCtx, l, t, r, b));
|
|
32216
33300
|
const inset = insideFrameInset(rCtx, unframed, true, rCtx.state.arcDirection === 2);
|
|
32217
33301
|
const box = inset ? insetFixBox(unframed, inset) : unframed;
|
|
32218
33302
|
const clockwise = rCtx.state.arcDirection === 2;
|
|
@@ -32267,7 +33351,7 @@ function handleRectangle(rCtx, dataOff, recSize) {
|
|
|
32267
33351
|
c.beginPath();
|
|
32268
33352
|
c.rect(x, y, w, h);
|
|
32269
33353
|
},
|
|
32270
|
-
raster: () => rectRasterPath(box, clockwise),
|
|
33354
|
+
raster: () => rectRasterPath(devicePositiveBox(box), clockwise),
|
|
32271
33355
|
rectangle: true,
|
|
32272
33356
|
fill: true,
|
|
32273
33357
|
stroke: true,
|
|
@@ -32377,7 +33461,7 @@ function handleRoundRect(rCtx, dataOff, recSize) {
|
|
|
32377
33461
|
const devM = gdiDeviceMatrix(rCtx);
|
|
32378
33462
|
const cornerFixW = inset ? Math.abs(cornerW * devM[0]) * 16 : fixExtent(rCtx, cornerW, 0);
|
|
32379
33463
|
const cornerFixH = inset ? Math.abs(cornerH * devM[3]) * 16 : fixExtent(rCtx, cornerH, 1);
|
|
32380
|
-
const cornerOnFrame = (
|
|
33464
|
+
const cornerOnFrame = (fix2, size, framedSize) => inset && size !== 0 ? Math.floor(Math.min(fix2, size) * framedSize / size) : fix2;
|
|
32381
33465
|
let cw = cornerOnFrame(cornerFixW, Math.abs((r - l) * devM[0]) * 16, Math.abs(framed.exx));
|
|
32382
33466
|
let ch = cornerOnFrame(cornerFixH, Math.abs((b - t) * devM[3]) * 16, Math.abs(framed.eyy));
|
|
32383
33467
|
const drawBox = inset ? framed : curvedFixBox(rCtx, l, t, r, b, true);
|
|
@@ -32441,18 +33525,21 @@ function curvedFixBox(rCtx, l, t, r, b, upright = false) {
|
|
|
32441
33525
|
return box;
|
|
32442
33526
|
}
|
|
32443
33527
|
const m = gdiDeviceMatrix(rCtx);
|
|
32444
|
-
if (
|
|
33528
|
+
if (m[1] !== 0 || m[2] !== 0) {
|
|
32445
33529
|
return box;
|
|
32446
33530
|
}
|
|
33531
|
+
const whole = box.ax % 16 === 0 && box.ay % 16 === 0 && box.exx % 16 === 0 && box.eyy % 16 === 0;
|
|
33532
|
+
const gx = whole ? 4 : 0;
|
|
33533
|
+
const gy = gx;
|
|
32447
33534
|
const sx = box.exx < 0 ? -1 : 1;
|
|
32448
33535
|
const sy = box.eyy < 0 ? -1 : 1;
|
|
32449
33536
|
return {
|
|
32450
|
-
ax: box.ax -
|
|
32451
|
-
ay: box.ay -
|
|
32452
|
-
exx: box.exx +
|
|
33537
|
+
ax: box.ax - gx * sx,
|
|
33538
|
+
ay: box.ay - gy * sy,
|
|
33539
|
+
exx: box.exx + 2 * gx * sx,
|
|
32453
33540
|
exy: 0,
|
|
32454
33541
|
eyx: 0,
|
|
32455
|
-
eyy: box.eyy +
|
|
33542
|
+
eyy: box.eyy + 2 * gy * sy
|
|
32456
33543
|
};
|
|
32457
33544
|
}
|
|
32458
33545
|
function handleEllipse(rCtx, dataOff, recSize) {
|
|
@@ -32548,34 +33635,41 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
32548
33635
|
}
|
|
32549
33636
|
};
|
|
32550
33637
|
const kind = isArcTo ? "arcto" : recType === EMR_PIE ? "pie" : recType === EMR_CHORD ? "chord" : "arc";
|
|
33638
|
+
const radialOnBox = (box, x, y) => {
|
|
33639
|
+
const wl = r - l;
|
|
33640
|
+
const hl = b - t;
|
|
33641
|
+
if (wl === 0 || hl === 0) {
|
|
33642
|
+
return fixPoint(rCtx, x, y);
|
|
33643
|
+
}
|
|
33644
|
+
const u = (x - l) / wl;
|
|
33645
|
+
const v = (y - t) / hl;
|
|
33646
|
+
return [box.ax + box.exx * u + box.eyx * v, box.ay + box.exy * u + box.eyy * v];
|
|
33647
|
+
};
|
|
32551
33648
|
const devM = gdiDeviceMatrix(rCtx);
|
|
32552
|
-
const
|
|
32553
|
-
const
|
|
32554
|
-
|
|
32555
|
-
|
|
32556
|
-
|
|
32557
|
-
const [
|
|
32558
|
-
|
|
32559
|
-
|
|
32560
|
-
|
|
32561
|
-
|
|
32562
|
-
|
|
33649
|
+
const mapFlips = devM[0] * devM[3] - devM[1] * devM[2] < 0;
|
|
33650
|
+
const axisMap2 = devM[1] === 0 && devM[2] === 0;
|
|
33651
|
+
const rasterArgs = (immediate = false) => {
|
|
33652
|
+
const box = inset ? framed : immediate && needsFill ? curvedFixBox(rCtx, l, t, r, b) : unframed;
|
|
33653
|
+
const boxFlips = box.exx * box.eyy - box.exy * box.eyx < 0;
|
|
33654
|
+
const mirror2 = axisMap2 && isAxisBox(box) ? { x: devM[0] < 0, y: devM[3] < 0 } : void 0;
|
|
33655
|
+
return {
|
|
33656
|
+
box,
|
|
33657
|
+
mirror: mirror2,
|
|
33658
|
+
clockwise: mirror2 ? clockwise : clockwise !== (mapFlips !== boxFlips),
|
|
33659
|
+
s: radialOnBox(box, startX, startY),
|
|
33660
|
+
// Device FIX rounding can separate distinct radial points on the
|
|
33661
|
+
// same logical ray. Preserve their proven endpoint identity.
|
|
33662
|
+
e: fullEllipse ? radialOnBox(box, startX, startY) : radialOnBox(box, endX, endY),
|
|
33663
|
+
from: currentFix(rCtx)
|
|
33664
|
+
};
|
|
32563
33665
|
};
|
|
32564
|
-
const rasterArgs = (immediate = false) => ({
|
|
32565
|
-
box: inset ? framed : immediate && needsFill ? curvedFixBox(rCtx, l, t, r, b) : unframed,
|
|
32566
|
-
s: radialOnBox(fixPoint(rCtx, startX, startY), rawFix(startX, startY)),
|
|
32567
|
-
// Device FIX rounding can separate distinct radial points on the
|
|
32568
|
-
// same logical ray. Preserve their proven endpoint identity.
|
|
32569
|
-
e: fullEllipse ? radialOnBox(fixPoint(rCtx, startX, startY), rawFix(startX, startY)) : radialOnBox(fixPoint(rCtx, endX, endY), rawFix(endX, endY)),
|
|
32570
|
-
from: currentFix(rCtx)
|
|
32571
|
-
});
|
|
32572
33666
|
if (inPath) {
|
|
32573
33667
|
if (isArcTo) {
|
|
32574
33668
|
continueFigure(rCtx);
|
|
32575
33669
|
}
|
|
32576
33670
|
build(gdiPathRecorder(rCtx));
|
|
32577
33671
|
const a = rasterArgs();
|
|
32578
|
-
arcRasterPath(a.box, a.s, a.e, clockwise, kind, a.from, rasterPathOf(rCtx));
|
|
33672
|
+
arcRasterPath(a.box, a.s, a.e, a.clockwise, kind, a.from, rasterPathOf(rCtx), a.mirror);
|
|
32579
33673
|
if (needsFill) {
|
|
32580
33674
|
rasterPathOf(rCtx).closeFigure();
|
|
32581
33675
|
}
|
|
@@ -32589,7 +33683,7 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
32589
33683
|
},
|
|
32590
33684
|
raster: () => {
|
|
32591
33685
|
const a = rasterArgs(true);
|
|
32592
|
-
return arcRasterPath(a.box, a.s, a.e, clockwise, kind, a.from).path;
|
|
33686
|
+
return arcRasterPath(a.box, a.s, a.e, a.clockwise, kind, a.from, void 0, a.mirror).path;
|
|
32593
33687
|
},
|
|
32594
33688
|
fill: needsFill,
|
|
32595
33689
|
stroke: true
|
|
@@ -32597,7 +33691,7 @@ function handleArcFamily(rCtx, recType, dataOff, recSize) {
|
|
|
32597
33691
|
}
|
|
32598
33692
|
if (isArcTo) {
|
|
32599
33693
|
const a = rasterArgs();
|
|
32600
|
-
const end = arcRasterPath(a.box, a.s, a.e, clockwise, "arc").end;
|
|
33694
|
+
const end = arcRasterPath(a.box, a.s, a.e, a.clockwise, "arc", void 0, void 0, a.mirror).end;
|
|
32601
33695
|
const dx = Math.floor(end[0] / 16);
|
|
32602
33696
|
const dy = Math.floor(end[1] / 16);
|
|
32603
33697
|
const inv2 = invertAffine(gdiDeviceMatrix(rCtx));
|
|
@@ -32719,6 +33813,21 @@ function handleEmfGdiShapeRecord(rCtx, recType, dataOff, recSize) {
|
|
|
32719
33813
|
}
|
|
32720
33814
|
}
|
|
32721
33815
|
|
|
33816
|
+
// src/emf-gdi-chroma-tie-data.ts
|
|
33817
|
+
var CHROMA_TIE_FLIPS = {
|
|
33818
|
+
"40,0": [374, 506, 1076, 1078, 1142, 1526, 1910, 2294, 2678, 3446, 5750, 5806, 5818, 5830, 5842, 5854, 5866, 5902, 5938, 6324, 7256, 7484, 7868, 8636, 8792, 8996, 9020, 9404, 9788, 10556, 11904, 12112, 12136, 12160, 12172, 12184, 12208, 12220, 12244, 12256, 12268, 12666, 13190, 13598, 15338, 18246, 18540, 18750, 19940, 21272, 21476, 21680, 21759, 21884, 24100, 24882, 27364, 27614, 28022, 30442, 30534, 30900, 31062, 32478, 32482, 33673, 36394, 36984, 37242, 37404, 40380, 41256, 41541, 42688, 42736, 42784, 43188, 46651, 48193, 49126, 49530, 49668, 50268, 53877, 54849, 55404, 55476, 58319, 61818, 62257, 66538, 67026, 67236, 67398, 67716, 69373, 71370, 73392, 73872, 77949, 78325, 79054, 80143, 80400, 85086, 85632, 86184, 86370, 86394, 88496, 91974, 98682, 98820, 98868, 99054, 102841, 104262, 104628, 110970, 111628, 115656, 116574, 116916, 119216, 119334, 119968, 123396, 127812, 128579, 129366, 129493, 129738, 134784, 134878, 140880, 142861, 143671, 146590, 147484, 150855, 151211, 153414, 153922, 154543, 155567, 157776, 159826, 160168, 160910, 162313, 165787, 166068, 169642, 171408, 171882, 172510, 174117, 174926, 176025, 176170, 176928, 177636, 177718, 177990, 178356, 181268, 184330, 184354, 184390, 184402, 184414, 184426, 184438, 184462, 184498, 184514, 185282, 185666, 186434, 186818, 188354, 189491, 190278, 190672, 190696, 190732, 190756, 190768, 190804, 190840, 191624, 192776, 193160, 193952, 194615, 194782, 194948, 195080, 195464, 195848, 196010],
|
|
33819
|
+
"40,20": [1345, 13655, 16768, 19051, 22461, 23888, 29071, 34630, 40955, 41856, 43128, 47160, 47377, 47934, 47976, 48106, 48607, 49476, 59008, 59116, 59372, 65851, 69045, 69721, 71741, 74531, 85884, 89225, 89899, 91692, 93843, 94915, 95071, 95968, 97561, 100356, 101005, 102444, 109699, 116446, 117163, 118538, 119501, 133219, 136360, 137042, 137929, 138173, 143164, 145012, 145555, 146068, 156036, 158160, 160630, 161047, 174146, 175587, 176339, 177137],
|
|
33820
|
+
"50,20": [3435, 4690, 7934, 11527, 21838, 22211, 24980, 32745, 35495, 36570, 38851, 41578, 43128, 49195, 57142, 72649, 73084, 81747, 89022, 89826, 93145, 94307, 96679, 99174, 99185, 102486, 103896, 109861, 110110, 112698, 116081, 130842, 133613, 137784, 139643, 142939, 143358, 143734, 143834, 152125, 158072, 170378, 170422, 174146, 175547, 177966, 180424, 182339, 190180, 192424, 196256],
|
|
33821
|
+
"-40,0": [5816, 9911, 17137, 17332, 18078, 19903, 25108, 39517, 46996, 54208, 54890, 55254, 59753, 61616, 73287, 73927, 77843, 90139, 93011, 94263, 96552, 99873, 104370, 115822, 116256, 119156, 122178, 125065, 125455, 127853, 133264, 133614, 136585, 141275, 148914, 149785, 153213, 156483, 167561, 171079, 171826, 183498, 184714, 185541, 186397, 190359, 194533],
|
|
33822
|
+
"100,0": [458, 506, 543, 845, 1142, 1274, 1526, 2294, 5074, 5750, 5782, 5806, 5818, 5830, 5854, 5866, 5902, 5926, 5938, 6800, 7100, 7256, 7484, 7616, 7868, 8384, 8636, 8792, 8996, 9020, 9152, 9404, 10328, 10556, 11324, 11416, 11904, 12092, 12112, 12136, 12160, 12184, 12208, 12244, 12256, 12268, 12546, 13142, 13370, 13502, 13598, 14522, 15338, 16670, 17320, 18246, 19484, 19712, 19940, 20864, 21068, 21272, 21476, 21680, 21884, 23710, 24882, 25615, 25874, 26054, 26282, 27002, 27206, 27614, 28022, 30004, 30442, 30780, 30883, 31062, 31176, 31224, 31434, 33073, 36480, 36984, 37122, 37242, 37404, 37566, 37776, 39326, 39686, 40862, 42346, 42688, 42784, 43746, 43908, 45308, 45543, 45668, 46232, 46959, 48210, 48250, 48322, 48380, 49030, 49078, 49126, 49248, 49530, 49668, 50088, 52485, 54592, 54688, 55030, 55343, 55404, 55476, 55590, 56010, 58009, 59324, 59888, 60522, 60592, 60628, 60894, 60934, 60958, 61372, 61746, 61932, 62118, 62352, 62617, 66410, 66970, 67276, 67324, 67348, 67398, 67716, 67902, 68088, 68274, 68460, 73240, 73340, 73618, 73666, 73690, 73872, 74430, 75097, 77750, 79094, 79618, 79686, 80052, 80400, 80690, 81053, 84630, 85308, 85632, 86184, 86370, 86394, 86742, 86928, 89565, 91974, 92478, 92526, 92898, 93084, 97548, 97782, 98610, 98682, 98820, 98868, 99426, 99612, 100368, 103704, 104124, 104262, 104628, 104952, 105162, 105210, 105396, 105768, 106117, 107011, 110614, 110686, 110712, 110970, 111040, 111294, 111504, 111738, 111924, 112828, 113676, 114388, 115341, 115393, 116574, 116916, 116956, 116992, 117636, 117846, 122298, 122464, 122968, 123266, 123298, 123334, 123650, 123724, 123978, 124188, 125029, 125924, 128054, 128514, 129238, 129262, 129286, 129310, 129366, 129640, 129712, 130196, 134784, 136054, 136080, 136538, 137182, 141253, 141946, 142018, 142292, 142396, 143060, 143828, 145207, 145667, 145693, 146155, 147484, 147922, 148226, 148264, 148288, 148312, 148392, 148634, 148738, 149402, 152235, 153414, 153874, 153922, 154264, 154568, 155106, 155744, 156104, 156308, 156512, 156716, 156858, 158768, 159360, 159826, 160168, 160216, 160264, 160606, 160910, 161020, 162086, 162242, 162398, 162446, 162650, 165540, 166068, 166168, 166558, 167252, 168584, 171720, 171882, 172510, 172948, 174926, 175538, 176306, 177852, 177990, 178356, 181064, 181268, 181676, 181997, 182648, 183008, 183936, 184330, 184354, 184390, 184402, 184414, 184438, 184462, 184514, 185194, 185282, 185632, 185666, 186434, 188354, 189758, 189890, 190278, 190410, 190672, 190684, 190696, 190732, 190768, 190804, 190816, 190840, 191624, 191926, 192776, 193160, 193802, 193952, 195080, 195165, 195332, 195464, 195692, 195848],
|
|
33823
|
+
"-100,0": [8492, 8494, 18577, 69397, 74091, 76386, 76390, 120219, 122518, 127206, 127210, 173433, 182718, 188113, 188115, 188117],
|
|
33824
|
+
"20,0": [374, 758, 1142, 1526, 2294, 2678, 4598, 5782, 5806, 5818, 5830, 5842, 5878, 5926, 5938, 6857, 7100, 7256, 7484, 7868, 8144, 8636, 9020, 9404, 10556, 11324, 11904, 12092, 12112, 12136, 12160, 12184, 12208, 12232, 12244, 12256, 12268, 12408, 15256, 15338, 16012, 19736, 22402, 24192, 24490, 24720, 30900, 31062, 33949, 36540, 37242, 43461, 45209, 45343, 47763, 49530, 50829, 51159, 52932, 54027, 54376, 55056, 55110, 55476, 59280, 59784, 60294, 61056, 61170, 65557, 65771, 67398, 71574, 73872, 78008, 79686, 80052, 83615, 86184, 86370, 88236, 88957, 90159, 90896, 90972, 91188, 92340, 92657, 93560, 94764, 95047, 95257, 95760, 98682, 98796, 102636, 103746, 104262, 104628, 108240, 110418, 110970, 113753, 116916, 121939, 122283, 122285, 123481, 126166, 126786, 127848, 128811, 129546, 133194, 137205, 139249, 140100, 140104, 143450, 143585, 144257, 148826, 153414, 157182, 159486, 160495, 160975, 161749, 164341, 166068, 166168, 168189, 169944, 171030, 171630, 173895, 175302, 175860, 176838, 178356, 184104, 184330, 184342, 184354, 184366, 184390, 184402, 184414, 184426, 184438, 184462, 184474, 184486, 184514, 185282, 185666, 185765, 187202, 188354, 188776, 190038, 190672, 190696, 190732, 190768, 190792, 190804, 190816, 190840, 191302, 191624, 192392, 192776, 193160, 194369, 194696, 195003, 195464, 195848],
|
|
33825
|
+
"70,0": [254, 458, 1142, 1274, 1526, 2246, 2294, 2348, 2450, 2654, 2858, 3062, 4598, 5750, 5782, 5806, 5830, 5842, 5854, 5866, 5902, 5926, 5938, 6300, 7100, 7256, 7484, 7616, 7868, 8384, 8636, 8792, 8996, 9020, 9404, 9470, 9497, 9788, 10328, 10556, 11021, 11324, 11416, 11904, 12092, 12112, 12136, 12184, 12244, 12256, 12268, 12546, 13370, 13598, 15134, 15338, 16670, 18540, 19532, 19712, 19940, 21068, 21272, 21476, 21884, 24192, 24720, 24841, 26282, 27410, 27614, 28180, 29026, 30004, 30442, 30534, 30900, 31062, 31224, 31434, 34160, 35373, 36480, 36984, 37242, 37404, 37566, 39890, 42688, 42784, 46640, 48380, 49030, 49078, 49126, 49248, 49530, 49668, 50088, 50659, 54592, 54664, 54688, 55476, 55590, 56010, 60766, 60958, 60982, 61372, 61560, 61746, 61932, 62617, 65226, 67348, 67398, 67716, 68088, 68274, 69492, 69557, 70194, 73107, 73578, 73714, 74244, 75841, 76888, 79686, 80400, 83650, 84127, 84200, 86184, 86370, 86394, 86742, 86845, 86928, 88496, 90155, 90522, 90549, 91974, 92478, 92526, 92898, 93084, 94736, 95937, 96873, 97782, 98682, 98820, 98868, 103659, 104262, 104628, 104952, 105162, 105210, 105396, 107075, 108234, 110686, 110712, 110970, 111294, 111504, 111628, 111738, 116332, 116574, 116916, 116992, 117636, 121933, 122621, 122968, 123024, 123334, 123396, 127016, 127044, 129262, 129286, 129310, 129366, 129712, 134394, 134784, 136054, 136080, 140378, 142018, 142292, 144762, 145335, 145710, 147484, 147922, 148226, 148312, 148392, 150262, 153414, 153874, 153922, 154568, 155744, 159360, 159826, 160168, 160216, 160264, 160606, 160910, 161076, 162242, 162446, 162650, 163690, 164494, 166068, 166168, 166558, 166606, 167252, 167848, 168584, 170886, 171648, 171882, 172510, 172948, 174722, 174926, 176306, 177852, 177990, 178356, 181064, 181268, 183008, 184330, 184354, 184390, 184402, 184414, 184426, 184438, 184462, 184498, 184514, 185194, 185282, 185632, 185666, 185714, 186434, 187202, 189033, 189051, 189758, 189890, 190278, 190672, 190696, 190732, 190792, 190804, 190816, 190840, 191624, 192776, 193160, 193952, 195464, 195563, 195692, 195848],
|
|
33826
|
+
"0,30": [1721, 4912, 17621, 23134, 24625, 24929, 33960, 36358, 38321, 38379, 40933, 42823, 43299, 45130, 45943, 49299, 52890, 53885, 57288, 57436, 59699, 61699, 64420, 65176, 65236, 72099, 72211, 72381, 83500, 85501, 88189, 89169, 92103, 93701, 95610, 95681, 108288, 108606, 114622, 117231, 119626, 123617, 127534, 133819, 136508, 136984, 139544, 143792, 145778, 147469, 149239, 153446, 153562, 154152, 159126, 166024, 175800, 176759, 180377, 181528, 182453, 183108, 192812],
|
|
33827
|
+
"0,-50": [1993, 2566, 7118, 7355, 11339, 12468, 15355, 19766, 19939, 26761, 31589, 32405, 35291, 38652, 41997, 50880, 52335, 53022, 53093, 55240, 72257, 72491, 75259, 75267, 80408, 83070, 83658, 83938, 85802, 86633, 90942, 99179, 101706, 102357, 106183, 108569, 117985, 120676, 140059, 141222, 143338, 147505, 147553, 150898, 152640, 156175, 156373, 156839, 158346, 159040, 163988, 171036, 176002, 179175, 179438, 192876, 194345, 194768, 194848],
|
|
33828
|
+
"0,60": [2079, 10520, 24043, 34818, 38212, 39257, 41632, 41905, 48383, 50923, 58894, 59675, 61206, 64816, 65028, 66919, 71898, 77171, 77667, 82511, 82591, 90280, 94741, 98446, 99892, 99982, 103615, 105816, 111088, 115141, 115170, 126478, 127086, 129937, 130463, 131475, 133798, 134795, 134807, 136638, 138053, 139328, 140657, 143569, 145200, 146837, 147691, 147766, 149712, 151474, 168315, 171698, 173961, 177231, 182638, 184786, 185640, 188116, 192273, 196154]
|
|
33829
|
+
};
|
|
33830
|
+
|
|
32722
33831
|
// src/emf-gdi-illuminant-data.ts
|
|
32723
33832
|
var ILLUMINANT_CUBE_DATA = {
|
|
32724
33833
|
1: "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",
|
|
@@ -32900,7 +34009,33 @@ function adjustChroma(r, g, b, scale, angle) {
|
|
|
32900
34009
|
}
|
|
32901
34010
|
return out;
|
|
32902
34011
|
}
|
|
32903
|
-
|
|
34012
|
+
var chromaTieTables = /* @__PURE__ */ new Map();
|
|
34013
|
+
function chromaTieTable(ca) {
|
|
34014
|
+
if (ca.illuminant !== 0 && ca.illuminant !== 6) return null;
|
|
34015
|
+
const key = `${ca.colorfulness},${ca.redGreenTint}`;
|
|
34016
|
+
let table2 = chromaTieTables.get(key);
|
|
34017
|
+
if (table2 === void 0) {
|
|
34018
|
+
const flips = CHROMA_TIE_FLIPS[key];
|
|
34019
|
+
table2 = null;
|
|
34020
|
+
if (flips) {
|
|
34021
|
+
table2 = new Int8Array(32768 * 3);
|
|
34022
|
+
for (const f of flips) table2[f >> 1] = f & 1 ? 1 : -1;
|
|
34023
|
+
}
|
|
34024
|
+
chromaTieTables.set(key, table2);
|
|
34025
|
+
}
|
|
34026
|
+
return table2;
|
|
34027
|
+
}
|
|
34028
|
+
function paletteEntry(v) {
|
|
34029
|
+
const n = Math.round(v * 31 / 255);
|
|
34030
|
+
return PALETTE[n] === v ? n : -1;
|
|
34031
|
+
}
|
|
34032
|
+
function tieIndex(c) {
|
|
34033
|
+
const r = paletteEntry(c[0]);
|
|
34034
|
+
const g = paletteEntry(c[1]);
|
|
34035
|
+
const b = paletteEntry(c[2]);
|
|
34036
|
+
return r < 0 || g < 0 || b < 0 ? -1 : (r * 32 + g) * 32 + b;
|
|
34037
|
+
}
|
|
34038
|
+
function colorAdjustmentMapper(ca, options2) {
|
|
32904
34039
|
const illuminant = illuminantCube(ca.illuminant);
|
|
32905
34040
|
const matrix = ILLUMINANT_MATRICES[ca.illuminant];
|
|
32906
34041
|
const gammas = [ca.redGamma / 1e4, ca.greenGamma / 1e4, ca.blueGamma / 1e4];
|
|
@@ -32913,6 +34048,7 @@ function colorAdjustmentMapper(ca) {
|
|
|
32913
34048
|
const angle = TINT_RADIANS * ca.redGreenTint / 100;
|
|
32914
34049
|
const log = (ca.flags & CA_LOG_FILTER) !== 0;
|
|
32915
34050
|
const negative = (ca.flags & CA_NEGATIVE) !== 0;
|
|
34051
|
+
const ties = chroma && options2?.chromaTies !== false ? chromaTieTable(ca) : null;
|
|
32916
34052
|
const curve = (value, channel) => {
|
|
32917
34053
|
let v = 255 * (clamp255(value) / 255) ** gammas[channel];
|
|
32918
34054
|
v = (v - black) / span * 255;
|
|
@@ -32932,6 +34068,7 @@ function colorAdjustmentMapper(ca) {
|
|
|
32932
34068
|
return (rgb2) => {
|
|
32933
34069
|
let c = [rgb2 >> 16 & 255, rgb2 >> 8 & 255, rgb2 & 255];
|
|
32934
34070
|
if (chroma) {
|
|
34071
|
+
const tie = ties ? tieIndex(c) : -1;
|
|
32935
34072
|
c = c.map(exactPaletteLevel);
|
|
32936
34073
|
if (matrix) {
|
|
32937
34074
|
const [r, g, b] = c;
|
|
@@ -32939,6 +34076,7 @@ function colorAdjustmentMapper(ca) {
|
|
|
32939
34076
|
}
|
|
32940
34077
|
c = adjustChroma(c[0], c[1], c[2], scale, angle);
|
|
32941
34078
|
c = c.map(roundHalfUp);
|
|
34079
|
+
if (ties && tie >= 0) c = c.map((v, k) => v + ties[tie * 3 + k]);
|
|
32942
34080
|
} else if (illuminant) {
|
|
32943
34081
|
const mapped = lookupIlluminant(illuminant, c[0] / 255, c[1] / 255, c[2] / 255);
|
|
32944
34082
|
c = [mapped[0] * 255, mapped[1] * 255, mapped[2] * 255];
|
|
@@ -33022,6 +34160,50 @@ function ditherQuantize(v, threshold) {
|
|
|
33022
34160
|
return paletteLevel(n < 0 ? 0 : n > 31 ? 31 : n);
|
|
33023
34161
|
}
|
|
33024
34162
|
|
|
34163
|
+
// src/emf-gdi-halftone-branch.ts
|
|
34164
|
+
function halftoneColorKey(r, g, b) {
|
|
34165
|
+
return b === r ? 16777216 | b >> 2 << 8 | g >> 2 : b | g << 8 | r << 16;
|
|
34166
|
+
}
|
|
34167
|
+
function halftoneBranch(rgb2, w, h) {
|
|
34168
|
+
if (w <= 0 || h <= 0) return "replicate";
|
|
34169
|
+
const n = w * h;
|
|
34170
|
+
if (n <= 2304) return "replicate";
|
|
34171
|
+
const keyAt = (i) => halftoneColorKey(rgb2[i * 3], rgb2[i * 3 + 1], rgb2[i * 3 + 2]);
|
|
34172
|
+
const seen = /* @__PURE__ */ new Set();
|
|
34173
|
+
if (n > 16384) {
|
|
34174
|
+
for (let y = 0; y < h; y += 6) {
|
|
34175
|
+
for (let x = 0; x < w; x++) seen.add(keyAt(y * w + x));
|
|
34176
|
+
if (seen.size >= 20) return "filter";
|
|
34177
|
+
}
|
|
34178
|
+
return "replicate";
|
|
34179
|
+
}
|
|
34180
|
+
const rows = Math.floor(2304 / w) + 1;
|
|
34181
|
+
if (h < rows) return "replicate";
|
|
34182
|
+
const exact = h === rows;
|
|
34183
|
+
const limit = exact ? 289 + Math.floor((rows * w - 2304) / 8) : 145 + Math.floor((rows * w - 2304) / 16);
|
|
34184
|
+
let colors = 0;
|
|
34185
|
+
let duplicateRows = 0;
|
|
34186
|
+
let coloredPixels = 0;
|
|
34187
|
+
let gaveUp = false;
|
|
34188
|
+
for (let y = 0; y < h; y++) {
|
|
34189
|
+
let added = 0;
|
|
34190
|
+
for (let x = 0; x < w; x++) {
|
|
34191
|
+
const key = keyAt(y * w + x);
|
|
34192
|
+
if (!seen.has(key)) {
|
|
34193
|
+
seen.add(key);
|
|
34194
|
+
added++;
|
|
34195
|
+
}
|
|
34196
|
+
}
|
|
34197
|
+
colors += added;
|
|
34198
|
+
if (!gaveUp && colors >= limit) return "filter";
|
|
34199
|
+
if (added === 0) duplicateRows++;
|
|
34200
|
+
else coloredPixels += w;
|
|
34201
|
+
if (colors >= 20 && coloredPixels > 2304 && !(exact && gaveUp)) return "filter";
|
|
34202
|
+
if (exact ? colors + duplicateRows * w >= limit - 1 : colors + (duplicateRows + 1) * w >= n - 2305 + limit) gaveUp = true;
|
|
34203
|
+
}
|
|
34204
|
+
return "replicate";
|
|
34205
|
+
}
|
|
34206
|
+
|
|
33025
34207
|
// src/emf-gdi-stretch.ts
|
|
33026
34208
|
var BLACKONWHITE = 1;
|
|
33027
34209
|
var WHITEONBLACK = 2;
|
|
@@ -33154,119 +34336,24 @@ function halftoneReduceTaps(srcLen, dstLen, reverse) {
|
|
|
33154
34336
|
if (reverse) taps.reverse();
|
|
33155
34337
|
return taps;
|
|
33156
34338
|
}
|
|
33157
|
-
var ENLARGE_INNER = [
|
|
33158
|
-
1e3,
|
|
33159
|
-
992.47,
|
|
33160
|
-
984.9399,
|
|
33161
|
-
977.4099,
|
|
33162
|
-
969.8798,
|
|
33163
|
-
962.3498,
|
|
33164
|
-
954.8198,
|
|
33165
|
-
947.2897,
|
|
33166
|
-
939.7597,
|
|
33167
|
-
932.2296,
|
|
33168
|
-
924.6996,
|
|
33169
|
-
917.1695,
|
|
33170
|
-
909.6395,
|
|
33171
|
-
902.1095,
|
|
33172
|
-
894.5665,
|
|
33173
|
-
886.8087,
|
|
33174
|
-
879.045,
|
|
33175
|
-
871.2813,
|
|
33176
|
-
863.4349,
|
|
33177
|
-
855.5885,
|
|
33178
|
-
847.7421,
|
|
33179
|
-
839.8269,
|
|
33180
|
-
831.9046,
|
|
33181
|
-
823.912,
|
|
33182
|
-
815.9193,
|
|
33183
|
-
807.9266,
|
|
33184
|
-
799.847,
|
|
33185
|
-
791.7283,
|
|
33186
|
-
783.6096,
|
|
33187
|
-
775.449,
|
|
33188
|
-
767.3204,
|
|
33189
|
-
758.9233,
|
|
33190
|
-
750.5263,
|
|
33191
|
-
742.4271,
|
|
33192
|
-
734.0547,
|
|
33193
|
-
725.6823,
|
|
33194
|
-
717.232,
|
|
33195
|
-
708.7675,
|
|
33196
|
-
700.2393,
|
|
33197
|
-
691.7111,
|
|
33198
|
-
683.0734,
|
|
33199
|
-
674.4357,
|
|
33200
|
-
665.7105,
|
|
33201
|
-
656.9854,
|
|
33202
|
-
648.2603,
|
|
33203
|
-
639.3747,
|
|
33204
|
-
630.4873,
|
|
33205
|
-
621.5157,
|
|
33206
|
-
612.5442
|
|
33207
|
-
];
|
|
33208
|
-
var ENLARGE_OUTER = [
|
|
33209
|
-
375.1388,
|
|
33210
|
-
364.2093,
|
|
33211
|
-
353.2797,
|
|
33212
|
-
342.4714,
|
|
33213
|
-
331.7615,
|
|
33214
|
-
321.1462,
|
|
33215
|
-
310.6456,
|
|
33216
|
-
300.2252,
|
|
33217
|
-
289.9229,
|
|
33218
|
-
279.7227,
|
|
33219
|
-
269.6439,
|
|
33220
|
-
259.6535,
|
|
33221
|
-
249.7825,
|
|
33222
|
-
240.0362,
|
|
33223
|
-
230.3856,
|
|
33224
|
-
220.8799,
|
|
33225
|
-
211.4594,
|
|
33226
|
-
202.1844,
|
|
33227
|
-
192.9996,
|
|
33228
|
-
183.9679,
|
|
33229
|
-
175.1064,
|
|
33230
|
-
166.2864,
|
|
33231
|
-
157.6436,
|
|
33232
|
-
149.1447,
|
|
33233
|
-
140.7609,
|
|
33234
|
-
132.5474,
|
|
33235
|
-
124.4802,
|
|
33236
|
-
116.5636,
|
|
33237
|
-
108.778,
|
|
33238
|
-
101.1602,
|
|
33239
|
-
93.7098,
|
|
33240
|
-
86.4419,
|
|
33241
|
-
79.3251,
|
|
33242
|
-
72.4091,
|
|
33243
|
-
65.6853,
|
|
33244
|
-
59.1472,
|
|
33245
|
-
52.812,
|
|
33246
|
-
46.6978,
|
|
33247
|
-
40.8001,
|
|
33248
|
-
35.1449,
|
|
33249
|
-
29.7494,
|
|
33250
|
-
24.6096,
|
|
33251
|
-
19.7977,
|
|
33252
|
-
15.2801,
|
|
33253
|
-
11.1442,
|
|
33254
|
-
7.3916,
|
|
33255
|
-
4.1415,
|
|
33256
|
-
1.4039,
|
|
33257
|
-
0
|
|
33258
|
-
];
|
|
33259
|
-
var ENLARGE_HALF = 500.0106;
|
|
33260
|
-
var ENLARGE_KNOTS = 96;
|
|
33261
34339
|
function enlargeKernel(u) {
|
|
33262
34340
|
if (u >= 1) return 0;
|
|
33263
|
-
|
|
33264
|
-
|
|
33265
|
-
|
|
33266
|
-
const i = Math.min(table2.length - 2, Math.floor(edge + 1e-9));
|
|
33267
|
-
return table2[i] + (table2[i + 1] - table2[i]) * (edge - i);
|
|
34341
|
+
const x = 1 - u;
|
|
34342
|
+
if (Math.abs(u - 0.5) < 1e-9) return x;
|
|
34343
|
+
return Math.pow(x, u < 0.5 ? Math.SQRT1_2 : Math.SQRT2);
|
|
33268
34344
|
}
|
|
33269
34345
|
function halftoneEnlargeTaps(src, dst) {
|
|
34346
|
+
return halftoneEnlargeCumulative(src, dst).map((row2) => {
|
|
34347
|
+
let prev = 0;
|
|
34348
|
+
return row2.map(([j, cum], i) => {
|
|
34349
|
+
const c = i === row2.length - 1 ? 8192 : Math.ceil(cum - 1e-7);
|
|
34350
|
+
const share = c - prev;
|
|
34351
|
+
prev = c;
|
|
34352
|
+
return [j, share / 8192];
|
|
34353
|
+
});
|
|
34354
|
+
});
|
|
34355
|
+
}
|
|
34356
|
+
function halftoneEnlargeCumulative(src, dst) {
|
|
33270
34357
|
const ratio = dst / src;
|
|
33271
34358
|
const reach = Math.ceil(ratio) - 1;
|
|
33272
34359
|
const fir = [];
|
|
@@ -33287,7 +34374,7 @@ function halftoneEnlargeTaps(src, dst) {
|
|
|
33287
34374
|
}
|
|
33288
34375
|
cover.push(run);
|
|
33289
34376
|
}
|
|
33290
|
-
const
|
|
34377
|
+
const rows = [];
|
|
33291
34378
|
for (let x = 0; x < dst; x++) {
|
|
33292
34379
|
const weights = /* @__PURE__ */ new Map();
|
|
33293
34380
|
for (let k = -reach; k <= reach; k++) {
|
|
@@ -33298,18 +34385,13 @@ function halftoneEnlargeTaps(src, dst) {
|
|
|
33298
34385
|
}
|
|
33299
34386
|
}
|
|
33300
34387
|
const sorted = [...weights.entries()].sort((a, b) => a[0] - b[0]);
|
|
33301
|
-
let prev = 0;
|
|
33302
34388
|
let cum = 0;
|
|
33303
|
-
|
|
33304
|
-
|
|
33305
|
-
|
|
33306
|
-
|
|
33307
|
-
row2.push([sorted[i][0], (c - prev) / 8192]);
|
|
33308
|
-
prev = c;
|
|
33309
|
-
}
|
|
33310
|
-
taps.push(row2);
|
|
34389
|
+
rows.push(sorted.map(([j, v]) => {
|
|
34390
|
+
cum += v * 8192;
|
|
34391
|
+
return [j, cum];
|
|
34392
|
+
}));
|
|
33311
34393
|
}
|
|
33312
|
-
return
|
|
34394
|
+
return rows;
|
|
33313
34395
|
}
|
|
33314
34396
|
function ditherPixels(px, w, h, dither, flipX, flipY, phaseX, phaseY) {
|
|
33315
34397
|
for (let y = 0; y < h; y++) {
|
|
@@ -33386,6 +34468,20 @@ function halftoneDespeckle(px, w, h) {
|
|
|
33386
34468
|
}
|
|
33387
34469
|
}
|
|
33388
34470
|
}
|
|
34471
|
+
function halftoneSharpen(px, w, h) {
|
|
34472
|
+
const src = px.slice();
|
|
34473
|
+
const at = (x, y, c) => src[(Math.max(0, Math.min(h - 1, y)) * w + Math.max(0, Math.min(w - 1, x))) * 3 + c];
|
|
34474
|
+
for (let y = 0; y < h; y++) {
|
|
34475
|
+
for (let x = 0; x < w; x++) {
|
|
34476
|
+
for (let c = 0; c < 3; c++) {
|
|
34477
|
+
const v = at(x, y, c);
|
|
34478
|
+
const sum = at(x - 1, y, c) + at(x + 1, y, c) + at(x, y - 1, c) + at(x, y + 1, c);
|
|
34479
|
+
const out = v + Math.floor((4 * v - sum) / 8);
|
|
34480
|
+
px[(y * w + x) * 3 + c] = out < 0 ? 0 : out > 255 ? 255 : out;
|
|
34481
|
+
}
|
|
34482
|
+
}
|
|
34483
|
+
}
|
|
34484
|
+
}
|
|
33389
34485
|
function halftonePairDespeckle(px, w, h, rows) {
|
|
33390
34486
|
const n = rows ? w : h;
|
|
33391
34487
|
const at = (k, side) => (rows ? side * w + k : k * w + side) * 3;
|
|
@@ -33448,6 +34544,239 @@ function halftoneReduceBoth(rect, sw, sh, dw, dh, flipX, flipY) {
|
|
|
33448
34544
|
}
|
|
33449
34545
|
return out;
|
|
33450
34546
|
}
|
|
34547
|
+
function halftoneReduceOneAxis(rect, sw, sh, dw, dh, flipX, flipY) {
|
|
34548
|
+
const vertical = dh < sh;
|
|
34549
|
+
const taps = vertical ? halftoneReduceTaps(sh, dh, flipY) : halftoneReduceTaps(sw, dw, flipX);
|
|
34550
|
+
const reduced = new Float64Array(dw * dh * 3);
|
|
34551
|
+
for (let y = 0; y < dh; y++) {
|
|
34552
|
+
for (let x = 0; x < dw; x++) {
|
|
34553
|
+
const run = vertical ? taps[y] : taps[x];
|
|
34554
|
+
const keep = vertical ? flipX ? dw - 1 - x : x : flipY ? dh - 1 - y : y;
|
|
34555
|
+
let total = 0;
|
|
34556
|
+
for (const [, w] of run) total += w;
|
|
34557
|
+
for (let c = 0; c < 3; c++) {
|
|
34558
|
+
let sum = 0;
|
|
34559
|
+
for (const [k, w] of run) sum += rect[((vertical ? k : keep) * sw + (vertical ? keep : k)) * 3 + c] * w;
|
|
34560
|
+
reduced[(y * dw + x) * 3 + c] = sum / total;
|
|
34561
|
+
}
|
|
34562
|
+
}
|
|
34563
|
+
}
|
|
34564
|
+
const out = new Int32Array(dw * dh * 3);
|
|
34565
|
+
const at = (x, y, c) => reduced[(Math.max(0, Math.min(dh - 1, y)) * dw + Math.max(0, Math.min(dw - 1, x))) * 3 + c];
|
|
34566
|
+
for (let y = 0; y < dh; y++) {
|
|
34567
|
+
for (let x = 0; x < dw; x++) {
|
|
34568
|
+
for (let c = 0; c < 3; c++) {
|
|
34569
|
+
const v = at(x, y, c);
|
|
34570
|
+
const sum = vertical ? at(x, y - 1, c) + at(x, y + 1, c) : at(x - 1, y, c) + at(x + 1, y, c);
|
|
34571
|
+
out[(y * dw + x) * 3 + c] = Math.max(0, Math.min(255, Math.floor(v + (2 * v - sum) / 4)));
|
|
34572
|
+
}
|
|
34573
|
+
}
|
|
34574
|
+
}
|
|
34575
|
+
return out;
|
|
34576
|
+
}
|
|
34577
|
+
var FILTER_WEIGHTS = {
|
|
34578
|
+
1: [[5, 22, 5, 32]],
|
|
34579
|
+
2: [[4, 12, 0, 16], [0, 12, 4, 16]],
|
|
34580
|
+
3: [[6, 10, 0, 16], [1, 14, 1, 16], [0, 10, 6, 16]],
|
|
34581
|
+
4: [[6, 10, 0, 16], [3, 12, 1, 16], [1, 12, 3, 16], [0, 10, 6, 16]],
|
|
34582
|
+
5: [[13, 19, 0, 32], [6, 25, 1, 32], [3, 26, 3, 32], [1, 25, 6, 32], [0, 19, 13, 32]]
|
|
34583
|
+
};
|
|
34584
|
+
function filterAxisTaps(src, dst) {
|
|
34585
|
+
const factor = dst / src;
|
|
34586
|
+
if (factor === 2) {
|
|
34587
|
+
const rows = FILTER_WEIGHTS[2].map(([a, b, c]) => [a * 512, b * 512, c * 512]);
|
|
34588
|
+
return Array.from({ length: dst }, (_, i) => {
|
|
34589
|
+
const k = Math.floor(i / 2);
|
|
34590
|
+
const [a, b, c] = rows[i % 2];
|
|
34591
|
+
return [[Math.max(0, k - 1), a], [k, b], [Math.min(src - 1, k + 1), c]];
|
|
34592
|
+
});
|
|
34593
|
+
}
|
|
34594
|
+
return halftoneEnlargeTaps(src, dst).map((row2) => row2.map(([j, v]) => [j, Math.round(v * 8192)]));
|
|
34595
|
+
}
|
|
34596
|
+
function halftoneFilterOneAxis(rgb2, w, h, W, H, below) {
|
|
34597
|
+
const horizontal = W > w;
|
|
34598
|
+
const n = horizontal ? w : h;
|
|
34599
|
+
const sharp = new Int32Array(rgb2.length);
|
|
34600
|
+
const at = (x, y, c) => y >= h && below ? below[Math.max(0, Math.min(w - 1, x)) * 3 + c] : rgb2[(Math.max(0, Math.min(h - 1, y)) * w + Math.max(0, Math.min(w - 1, x))) * 3 + c];
|
|
34601
|
+
for (let y = 0; y < h; y++) {
|
|
34602
|
+
for (let x = 0; x < w; x++) {
|
|
34603
|
+
for (let c = 0; c < 3; c++) {
|
|
34604
|
+
const v = at(x, y, c);
|
|
34605
|
+
const sum = horizontal ? at(x - 1, y, c) + at(x + 1, y, c) : at(x, y - 1, c) + at(x, y + 1, c);
|
|
34606
|
+
const out2 = v + Math.floor((2 * v - sum) / 4);
|
|
34607
|
+
sharp[(y * w + x) * 3 + c] = out2 < 0 ? 0 : out2 > 255 ? 255 : out2;
|
|
34608
|
+
}
|
|
34609
|
+
}
|
|
34610
|
+
}
|
|
34611
|
+
const taps = filterAxisTaps(n, horizontal ? W : H);
|
|
34612
|
+
const out = new Int32Array(W * H * 3);
|
|
34613
|
+
for (let y = 0; y < H; y++) {
|
|
34614
|
+
for (let x = 0; x < W; x++) {
|
|
34615
|
+
for (let c = 0; c < 3; c++) {
|
|
34616
|
+
let sum = 0;
|
|
34617
|
+
if (horizontal) for (const [j, weight] of taps[x]) sum += weight * sharp[(y * w + j) * 3 + c];
|
|
34618
|
+
else for (const [j, weight] of taps[y]) sum += weight * sharp[(j * w + x) * 3 + c];
|
|
34619
|
+
out[(y * W + x) * 3 + c] = Math.floor((sum + 4096) / 8192);
|
|
34620
|
+
}
|
|
34621
|
+
}
|
|
34622
|
+
}
|
|
34623
|
+
return out;
|
|
34624
|
+
}
|
|
34625
|
+
function filterRuns(src, dst) {
|
|
34626
|
+
const k = Array.from({ length: dst }, (_, i) => halftoneNearest(i, src, dst));
|
|
34627
|
+
const length = /* @__PURE__ */ new Map();
|
|
34628
|
+
for (const v of k) length.set(v, (length.get(v) ?? 0) + 1);
|
|
34629
|
+
const placed = /* @__PURE__ */ new Map();
|
|
34630
|
+
return k.map((v) => {
|
|
34631
|
+
const p = placed.get(v) ?? 0;
|
|
34632
|
+
placed.set(v, p + 1);
|
|
34633
|
+
return { k: v, weights: FILTER_WEIGHTS[length.get(v)][p] };
|
|
34634
|
+
});
|
|
34635
|
+
}
|
|
34636
|
+
function halftoneFilterSupported(w, h, W, H) {
|
|
34637
|
+
return w > 0 && h > 0 && W >= w && H >= h && (W > w || H > h);
|
|
34638
|
+
}
|
|
34639
|
+
function ditherFilteredSource(rect, SW, SH, W, H, dither, flipY) {
|
|
34640
|
+
if (W > 5 * SW || H > 5 * SH) {
|
|
34641
|
+
const further = new Int32Array((SH + 1) * SW * 3);
|
|
34642
|
+
further.set(rect);
|
|
34643
|
+
further.set(rect.subarray((SH - 1) * SW * 3), SH * SW * 3);
|
|
34644
|
+
ditherPixels(
|
|
34645
|
+
further,
|
|
34646
|
+
SW,
|
|
34647
|
+
SH + 1,
|
|
34648
|
+
dither,
|
|
34649
|
+
false,
|
|
34650
|
+
false,
|
|
34651
|
+
void 0,
|
|
34652
|
+
Int32Array.from({ length: SH + 1 }, (_, j) => flipY ? H - 1 - j : j)
|
|
34653
|
+
);
|
|
34654
|
+
return further;
|
|
34655
|
+
}
|
|
34656
|
+
const extended = new Int32Array((SH + 4) * SW * 3);
|
|
34657
|
+
extended.set(rect.subarray(0, SW * 3), 0);
|
|
34658
|
+
extended.set(rect.subarray(0, SW * 3), SW * 3);
|
|
34659
|
+
extended.set(rect, 2 * SW * 3);
|
|
34660
|
+
extended.set(rect.subarray((SH - 1) * SW * 3), (SH + 2) * SW * 3);
|
|
34661
|
+
extended.set(rect.subarray((SH - 1) * SW * 3), (SH + 3) * SW * 3);
|
|
34662
|
+
ditherPixels(
|
|
34663
|
+
extended,
|
|
34664
|
+
SW,
|
|
34665
|
+
SH + 4,
|
|
34666
|
+
{ startX: dither.startX, startY: (dither.startY + (flipY ? 63 : 2)) % 65 },
|
|
34667
|
+
false,
|
|
34668
|
+
false,
|
|
34669
|
+
void 0,
|
|
34670
|
+
Int32Array.from({ length: SH + 4 }, (_, e) => flipY ? H - e + 1 : e - 2)
|
|
34671
|
+
);
|
|
34672
|
+
return extended;
|
|
34673
|
+
}
|
|
34674
|
+
function halftoneFilterEnlarge(rgb2, w, h, W, H, extended) {
|
|
34675
|
+
if (W === w || H === h) return halftoneFilterOneAxis(rgb2, w, h, W, H, extended && extended.length === (h + 1) * w * 3 ? extended.subarray(h * w * 3) : void 0);
|
|
34676
|
+
const clamp2 = (v) => v < 0 ? 0 : v > 255 ? 255 : v;
|
|
34677
|
+
const general = W > 5 * w || H > 5 * h;
|
|
34678
|
+
const out = new Int32Array(W * H * 3);
|
|
34679
|
+
if (general) {
|
|
34680
|
+
const sharp2 = rgb2.slice();
|
|
34681
|
+
if (extended) {
|
|
34682
|
+
const at2 = (x, y, c) => extended[(Math.max(0, Math.min(h, y)) * w + Math.max(0, Math.min(w - 1, x))) * 3 + c];
|
|
34683
|
+
for (let y = 0; y < h; y++) {
|
|
34684
|
+
for (let x = 0; x < w; x++) {
|
|
34685
|
+
for (let c = 0; c < 3; c++) {
|
|
34686
|
+
const v = at2(x, y, c);
|
|
34687
|
+
const sum = at2(x - 1, y, c) + at2(x + 1, y, c) + at2(x, y - 1, c) + at2(x, y + 1, c);
|
|
34688
|
+
sharp2[(y * w + x) * 3 + c] = clamp2(v + Math.floor((4 * v - sum) / 8));
|
|
34689
|
+
}
|
|
34690
|
+
}
|
|
34691
|
+
}
|
|
34692
|
+
} else {
|
|
34693
|
+
halftoneSharpen(sharp2, w, h);
|
|
34694
|
+
}
|
|
34695
|
+
const xt = filterAxisTaps(w, W);
|
|
34696
|
+
const yt = filterAxisTaps(h, H);
|
|
34697
|
+
const middle2 = new Int32Array(W * h * 3);
|
|
34698
|
+
for (let y = 0; y < h; y++) {
|
|
34699
|
+
for (let x = 0; x < W; x++) {
|
|
34700
|
+
for (let c = 0; c < 3; c++) {
|
|
34701
|
+
let sum = 0;
|
|
34702
|
+
for (const [j, weight] of xt[x]) sum += weight * sharp2[(y * w + j) * 3 + c];
|
|
34703
|
+
middle2[(y * W + x) * 3 + c] = Math.floor((sum + 4096) / 8192);
|
|
34704
|
+
}
|
|
34705
|
+
}
|
|
34706
|
+
}
|
|
34707
|
+
for (let y = 0; y < H; y++) {
|
|
34708
|
+
for (let x = 0; x < W; x++) {
|
|
34709
|
+
for (let c = 0; c < 3; c++) {
|
|
34710
|
+
let sum = 0;
|
|
34711
|
+
for (const [j, weight] of yt[y]) sum += weight * middle2[(j * W + x) * 3 + c];
|
|
34712
|
+
out[(y * W + x) * 3 + c] = clamp2(Math.floor((sum + 4096) / 8192));
|
|
34713
|
+
}
|
|
34714
|
+
}
|
|
34715
|
+
}
|
|
34716
|
+
return out;
|
|
34717
|
+
}
|
|
34718
|
+
const rows = h + 2;
|
|
34719
|
+
const sharp = new Int32Array(w * rows * 3);
|
|
34720
|
+
let padded;
|
|
34721
|
+
if (extended && extended.length === (h + 4) * w * 3) padded = extended;
|
|
34722
|
+
else {
|
|
34723
|
+
padded = new Int32Array(w * (h + 4) * 3);
|
|
34724
|
+
if (extended && extended.length === rows * w * 3) {
|
|
34725
|
+
padded.set(extended.subarray(w * 3, 2 * w * 3), 0);
|
|
34726
|
+
padded.set(extended, w * 3);
|
|
34727
|
+
padded.set(extended.subarray(h * w * 3, (h + 1) * w * 3), (h + 3) * w * 3);
|
|
34728
|
+
} else {
|
|
34729
|
+
padded.set(rgb2.subarray(0, w * 3), 0);
|
|
34730
|
+
padded.set(rgb2.subarray(0, w * 3), w * 3);
|
|
34731
|
+
padded.set(rgb2, 2 * w * 3);
|
|
34732
|
+
padded.set(rgb2.subarray((h - 1) * w * 3), (h + 2) * w * 3);
|
|
34733
|
+
padded.set(rgb2.subarray((h - 1) * w * 3), (h + 3) * w * 3);
|
|
34734
|
+
}
|
|
34735
|
+
}
|
|
34736
|
+
const source = padded;
|
|
34737
|
+
const at = (x, y, c) => source[((y + 1) * w + Math.max(0, Math.min(w - 1, x))) * 3 + c];
|
|
34738
|
+
for (let y = 0; y < rows; y++) {
|
|
34739
|
+
for (let x = 0; x < w; x++) {
|
|
34740
|
+
for (let c = 0; c < 3; c++) {
|
|
34741
|
+
const v = at(x, y, c);
|
|
34742
|
+
const sum = at(x - 1, y, c) + at(x + 1, y, c) + at(x, y - 1, c) + at(x, y + 1, c);
|
|
34743
|
+
sharp[(y * w + x) * 3 + c] = clamp2(v + Math.floor((4 * v - sum) / 8));
|
|
34744
|
+
}
|
|
34745
|
+
}
|
|
34746
|
+
}
|
|
34747
|
+
const xr = filterRuns(w, W);
|
|
34748
|
+
const yr = filterRuns(h, H);
|
|
34749
|
+
const middle = new Int32Array(w * 3);
|
|
34750
|
+
for (let y = 0; y < H; y++) {
|
|
34751
|
+
const near = yr[y].k + 1;
|
|
34752
|
+
const [a, b, c, total] = yr[y].weights;
|
|
34753
|
+
const before = (near - 1) * w * 3;
|
|
34754
|
+
const here = near * w * 3;
|
|
34755
|
+
const after = (near + 1) * w * 3;
|
|
34756
|
+
for (let i = 0; i < w * 3; i++) {
|
|
34757
|
+
middle[i] = Math.floor((a * sharp[before + i] + b * sharp[here + i] + c * sharp[after + i] + total / 2) / total);
|
|
34758
|
+
}
|
|
34759
|
+
for (let x = 0; x < W; x++) {
|
|
34760
|
+
const k = xr[x].k;
|
|
34761
|
+
const [a2, b2, c2, total2] = xr[x].weights;
|
|
34762
|
+
const left = Math.max(0, k - 1);
|
|
34763
|
+
const right = Math.min(w - 1, k + 1);
|
|
34764
|
+
for (let c3 = 0; c3 < 3; c3++) {
|
|
34765
|
+
out[(y * W + x) * 3 + c3] = Math.floor((a2 * middle[left * 3 + c3] + b2 * middle[k * 3 + c3] + c2 * middle[right * 3 + c3] + total2 / 2) / total2);
|
|
34766
|
+
}
|
|
34767
|
+
}
|
|
34768
|
+
}
|
|
34769
|
+
return out;
|
|
34770
|
+
}
|
|
34771
|
+
function halftoneMixedEngine(rect, SW, SH, W, H) {
|
|
34772
|
+
const halved = W > SW && H * 2 <= SH || H > SH && W * 2 <= SW;
|
|
34773
|
+
const cap = H < SH && 3 * H + 2 <= 2 * SH || W < SW && 3 * W + 2 <= 2 * SW;
|
|
34774
|
+
if (halved || cap) return "reduced";
|
|
34775
|
+
const small = SW * SH <= 2304;
|
|
34776
|
+
if (!small && halftoneBranch(rect, SW, SH) === "filter") return "reduced";
|
|
34777
|
+
if (W * H < SW * SH) return small ? "despeckled" : "reduced";
|
|
34778
|
+
return "nearest";
|
|
34779
|
+
}
|
|
33451
34780
|
function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSampling = false, directDib = false, dither, curves) {
|
|
33452
34781
|
const W = Math.max(0, Math.round(Math.abs(dw)));
|
|
33453
34782
|
const H = Math.max(0, Math.round(Math.abs(dh)));
|
|
@@ -33492,14 +34821,76 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
|
|
|
33492
34821
|
const reducing = W < SW && H < SH;
|
|
33493
34822
|
const mixed = W > SW && H < SH || W < SW && H > SH;
|
|
33494
34823
|
const dithered = !!dither && !!adjust && !adjustAfterSampling;
|
|
33495
|
-
const
|
|
33496
|
-
const
|
|
33497
|
-
|
|
34824
|
+
const mixedPlain = mixed && (!adjust || adjustAfterSampling || dithered);
|
|
34825
|
+
const engine = mixedPlain ? halftoneMixedEngine(rect, SW, SH, W, H) : "nearest";
|
|
34826
|
+
const nearestMixed = mixedPlain && engine === "nearest" && (W < SW && W * 2 > SW || H < SH && H * 2 > SH);
|
|
34827
|
+
const nativeMixed = mixedPlain && engine !== "nearest";
|
|
34828
|
+
const despeckles = SW * SH <= 2304 || SW * SH > 16384;
|
|
34829
|
+
const oneAxisReduce = W < SW && H === SH || H < SH && W === SW;
|
|
34830
|
+
const reduceDespeckle = (reducing || oneAxisReduce) && despeckles && !directDib && !(W < SW && 3 * W + 2 <= 2 * SW) && !(H < SH && 3 * H + 2 <= 2 * SH) && (SW * SH <= 2304 || halftoneBranch(rect, SW, SH) === "replicate");
|
|
34831
|
+
if (oneAxisReduce && (!adjust || adjustAfterSampling || dithered)) {
|
|
34832
|
+
if (reduceDespeckle) halftoneDespeckle(rect, SW, SH);
|
|
34833
|
+
const reduced = halftoneReduceOneAxis(rect, SW, SH, W, H, flipX, flipY);
|
|
34834
|
+
if (dithered) {
|
|
34835
|
+
ditherPixels(reduced, W, H, dither);
|
|
34836
|
+
adjust(reduced);
|
|
34837
|
+
if (curves) curves(reduced);
|
|
34838
|
+
} else if (adjust) adjust(reduced);
|
|
34839
|
+
for (let i = 0, o = 0; i < W * H; i++, o += 3) {
|
|
34840
|
+
data[i * 4] = reduced[o];
|
|
34841
|
+
data[i * 4 + 1] = reduced[o + 1];
|
|
34842
|
+
data[i * 4 + 2] = reduced[o + 2];
|
|
34843
|
+
data[i * 4 + 3] = 255;
|
|
34844
|
+
}
|
|
34845
|
+
return { width: W, height: H, data };
|
|
34846
|
+
}
|
|
34847
|
+
if (enlarging && halftoneFilterSupported(SW, SH, W, H) && (!adjust || adjustAfterSampling || dithered) && halftoneBranch(rect, SW, SH) === "filter") {
|
|
34848
|
+
let extended;
|
|
34849
|
+
let source = rect;
|
|
34850
|
+
if (dithered) {
|
|
34851
|
+
if (W === SW || H === SH) {
|
|
34852
|
+
if (H > SH) {
|
|
34853
|
+
extended = new Int32Array((SH + 1) * SW * 3);
|
|
34854
|
+
extended.set(rect);
|
|
34855
|
+
extended.set(rect.subarray((SH - 1) * SW * 3), SH * SW * 3);
|
|
34856
|
+
ditherPixels(extended, SW, SH + 1, dither, false, false, void 0, Int32Array.from({ length: SH + 1 }, (_, j) => flipY ? H - 1 - j : j));
|
|
34857
|
+
adjust(extended);
|
|
34858
|
+
source = extended.subarray(0, SW * SH * 3);
|
|
34859
|
+
} else {
|
|
34860
|
+
source = rect.slice();
|
|
34861
|
+
ditherPixels(source, SW, SH, dither, false, false, void 0, Int32Array.from({ length: SH }, (_, j) => flipY ? H - 1 - j : j));
|
|
34862
|
+
adjust(source);
|
|
34863
|
+
}
|
|
34864
|
+
} else {
|
|
34865
|
+
extended = ditherFilteredSource(rect, SW, SH, W, H, dither, flipY);
|
|
34866
|
+
adjust(extended);
|
|
34867
|
+
}
|
|
34868
|
+
}
|
|
34869
|
+
const filtered = halftoneFilterEnlarge(source, SW, SH, W, H, extended);
|
|
34870
|
+
if (flipX || flipY) {
|
|
34871
|
+
const mirror2 = filtered.slice();
|
|
34872
|
+
for (let y = 0; y < H; y++) {
|
|
34873
|
+
for (let x = 0; x < W; x++) {
|
|
34874
|
+
const from = ((flipY ? H - 1 - y : y) * W + (flipX ? W - 1 - x : x)) * 3;
|
|
34875
|
+
filtered.set(mirror2.subarray(from, from + 3), (y * W + x) * 3);
|
|
34876
|
+
}
|
|
34877
|
+
}
|
|
34878
|
+
}
|
|
34879
|
+
if (adjust && adjustAfterSampling) adjust(filtered);
|
|
34880
|
+
if (curves && dithered) curves(filtered);
|
|
34881
|
+
for (let i = 0, o = 0; i < W * H; i++, o += 3) {
|
|
34882
|
+
data[i * 4] = filtered[o];
|
|
34883
|
+
data[i * 4 + 1] = filtered[o + 1];
|
|
34884
|
+
data[i * 4 + 2] = filtered[o + 2];
|
|
34885
|
+
data[i * 4 + 3] = 255;
|
|
34886
|
+
}
|
|
34887
|
+
return { width: W, height: H, data };
|
|
34888
|
+
}
|
|
34889
|
+
if (((enlarging || nearestMixed || engine === "despeckled") && despeckles || reducing && reduceDespeckle) && !directDib && !pairRows && !pairColumns) {
|
|
33498
34890
|
halftoneDespeckle(rect, SW, SH);
|
|
33499
34891
|
}
|
|
33500
|
-
const
|
|
33501
|
-
const
|
|
33502
|
-
const extendRow = ditherAtSource && nativeMixed && W < SW && H > SH && !flipY;
|
|
34892
|
+
const ditherAtSource = dithered && (W >= SW && H >= SH || nativeMixed && W * H >= SW * SH);
|
|
34893
|
+
const extendRow = ditherAtSource && nativeMixed && W < SW && H > SH;
|
|
33503
34894
|
if (extendRow) {
|
|
33504
34895
|
const bigger = new Int32Array((SH + 1) * SW * 3);
|
|
33505
34896
|
bigger.set(rect);
|
|
@@ -33515,7 +34906,7 @@ function stretchHalftone(src, sx, sy, sw, sh, dw, dh, adjust, adjustAfterSamplin
|
|
|
33515
34906
|
false,
|
|
33516
34907
|
false,
|
|
33517
34908
|
void 0,
|
|
33518
|
-
flipY ? Int32Array.from({ length: SH }, (_, j) => H - 1 - j) : void 0
|
|
34909
|
+
flipY ? Int32Array.from({ length: extendRow ? SH + 1 : SH }, (_, j) => H - 1 - j) : void 0
|
|
33519
34910
|
);
|
|
33520
34911
|
}
|
|
33521
34912
|
if (adjust && !adjustAfterSampling && (!dithered || ditherAtSource)) {
|
|
@@ -36620,9 +38011,9 @@ function handlePolyDraw(rCtx, offset, dataOff, recSize, pointSize) {
|
|
|
36620
38011
|
ensureOpen();
|
|
36621
38012
|
const pts = [0, 1, 2].map((k) => readPt(i + k));
|
|
36622
38013
|
const dev = pts.map(([x, y]) => gmapPoint(rCtx, x, y));
|
|
36623
|
-
const
|
|
38014
|
+
const fix2 = pts.map(([x, y]) => fixPoint(rCtx, x, y));
|
|
36624
38015
|
canvas?.bezierCurveTo(dev[0].x, dev[0].y, dev[1].x, dev[1].y, dev[2].x, dev[2].y);
|
|
36625
|
-
raster?.bezierTo(
|
|
38016
|
+
raster?.bezierTo(fix2[0][0], fix2[0][1], fix2[1][0], fix2[1][1], fix2[2][0], fix2[2][1]);
|
|
36626
38017
|
i += 2;
|
|
36627
38018
|
} else {
|
|
36628
38019
|
continue;
|
|
@@ -38021,22 +39412,22 @@ function strokeGdiplus(rCtx, pen, nib, sampler, buildPath, device, size, mode, c
|
|
|
38021
39412
|
const m = frame2.toDevice;
|
|
38022
39413
|
return poly.flatMap((p) => [toPlusFix(m[0] * p.x + m[2] * p.y + m[4]), toPlusFix(m[1] * p.x + m[3] * p.y + m[5])]);
|
|
38023
39414
|
};
|
|
38024
|
-
let
|
|
39415
|
+
let fix2;
|
|
38025
39416
|
if (hasCustomCap(pen)) {
|
|
38026
|
-
|
|
39417
|
+
fix2 = customCapOutline(figures, width, devicePen, pen).map(toFix);
|
|
38027
39418
|
} else if (width <= NOMINAL_PEN_MAX && !devicePen.dash && !(((pen.startCap ?? 0) | (pen.endCap ?? 0) | (pen.dashCap ?? 0)) & 240)) {
|
|
38028
39419
|
return strokeNominal(rCtx, pen, sampler, buildPath, device, size, antialias, closedFigure);
|
|
38029
39420
|
} else {
|
|
38030
|
-
|
|
39421
|
+
fix2 = widenFigures(figures, devicePen).map(toFix);
|
|
38031
39422
|
}
|
|
38032
|
-
const box = figuresBox(
|
|
39423
|
+
const box = figuresBox(fix2, size);
|
|
38033
39424
|
if (!box) {
|
|
38034
39425
|
return true;
|
|
38035
39426
|
}
|
|
38036
39427
|
if (box.w * box.h > 16e6) {
|
|
38037
39428
|
return false;
|
|
38038
39429
|
}
|
|
38039
|
-
const coverage = rasterizePlusFill(
|
|
39430
|
+
const coverage = rasterizePlusFill(fix2, false, antialias, isHalfPixelOffset(rCtx.pixelOffsetMode ?? 0), box);
|
|
38040
39431
|
return compositeBrushCoverage(rCtx, sampler, box, coverage, 1, true);
|
|
38041
39432
|
}
|
|
38042
39433
|
function strokeNominal(rCtx, pen, sampler, buildPath, device, size, antialias, closedFigure) {
|
|
@@ -38171,7 +39562,7 @@ function deviceQuad(wt, s, pts) {
|
|
|
38171
39562
|
}
|
|
38172
39563
|
return out;
|
|
38173
39564
|
}
|
|
38174
|
-
function imageResampleSpec(rCtx, dataOff, isMetafile, toWorld) {
|
|
39565
|
+
function imageResampleSpec(rCtx, dataOff, isMetafile, toWorld, points) {
|
|
38175
39566
|
const { view } = rCtx;
|
|
38176
39567
|
const kernel = resampleKernelFor(rCtx.interpolationMode ?? 0);
|
|
38177
39568
|
if (isMetafile || view.getUint32(dataOff + 4, true) !== UNIT_PIXEL2) {
|
|
@@ -38192,10 +39583,11 @@ function imageResampleSpec(rCtx, dataOff, isMetafile, toWorld) {
|
|
|
38192
39583
|
toDevice: mulMatrix(plusWorldMatrix(rCtx), toWorld(srcX, srcY, srcW, srcH)),
|
|
38193
39584
|
kernel,
|
|
38194
39585
|
halfPixelOffset: isHalfPixelOffset(rCtx.pixelOffsetMode ?? 0),
|
|
39586
|
+
...points ? { pointsForm: true } : {},
|
|
38195
39587
|
...imageAttributesWrap(rCtx, view.getUint32(dataOff, true))
|
|
38196
39588
|
};
|
|
38197
39589
|
}
|
|
38198
|
-
function drawOrDeferImage(rCtx, imgObj, dataOff, dx, dy, dw, dh, toWorld, effect = null) {
|
|
39590
|
+
function drawOrDeferImage(rCtx, imgObj, dataOff, dx, dy, dw, dh, toWorld, effect = null, points = false) {
|
|
38199
39591
|
if (!imgObj.data) {
|
|
38200
39592
|
return;
|
|
38201
39593
|
}
|
|
@@ -38208,7 +39600,7 @@ function drawOrDeferImage(rCtx, imgObj, dataOff, dx, dy, dw, dh, toWorld, effect
|
|
|
38208
39600
|
dh,
|
|
38209
39601
|
transform: plusWorldMatrix(rCtx),
|
|
38210
39602
|
isMetafile,
|
|
38211
|
-
resample: imageResampleSpec(rCtx, dataOff, isMetafile, toWorld)
|
|
39603
|
+
resample: imageResampleSpec(rCtx, dataOff, isMetafile, toWorld, points)
|
|
38212
39604
|
};
|
|
38213
39605
|
const { view } = rCtx;
|
|
38214
39606
|
const source = {
|
|
@@ -38677,7 +40069,7 @@ function handleEmfPlusTextImageRecord(rCtx, recType, recFlags, dataOff, recDataS
|
|
|
38677
40069
|
const c = (p3x - p1x) / sh;
|
|
38678
40070
|
const d = (p3y - p1y) / sh;
|
|
38679
40071
|
return [a, b, c, d, p1x - a * sx - c * sy, p1y - b * sx - d * sy];
|
|
38680
|
-
}, effect);
|
|
40072
|
+
}, effect, true);
|
|
38681
40073
|
} else {
|
|
38682
40074
|
imgObj && imgObj.kind === "plus-image" && imgObj.data;
|
|
38683
40075
|
}
|
|
@@ -40886,15 +42278,15 @@ function compatBox(p, l, t, r, b, opts = {}) {
|
|
|
40886
42278
|
return box;
|
|
40887
42279
|
}
|
|
40888
42280
|
function fixBoxOf(box, cornerExact, keepInverted = false) {
|
|
40889
|
-
const
|
|
42281
|
+
const fix2 = keepInverted ? axisBox(box.x0, box.y0, box.x1, box.y1) : axisBox(box.x0, box.y0, Math.max(box.x0, box.x1), Math.max(box.y0, box.y1));
|
|
40890
42282
|
if (box.halfX) {
|
|
40891
|
-
|
|
40892
|
-
|
|
42283
|
+
fix2.halfX = true;
|
|
42284
|
+
fix2.halfXCompat = true;
|
|
40893
42285
|
}
|
|
40894
42286
|
if (cornerExact) {
|
|
40895
|
-
|
|
42287
|
+
fix2.cornerExact = cornerExact;
|
|
40896
42288
|
}
|
|
40897
|
-
return
|
|
42289
|
+
return fix2;
|
|
40898
42290
|
}
|
|
40899
42291
|
function canvasRect(box) {
|
|
40900
42292
|
return { x: box.x0 / 16, y: box.y0 / 16, w: Math.max(0, box.x1 - box.x0) / 16, h: Math.max(0, box.y1 - box.y0) / 16 };
|