emf-converter 4.4.6 → 4.4.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +73 -29
- package/dist/browser.mjs +73 -29
- package/dist/index.js +73 -29
- package/dist/index.mjs +73 -29
- package/package.json +1 -1
package/dist/browser.js
CHANGED
|
@@ -11333,7 +11333,7 @@ var GdiRasterPath = class {
|
|
|
11333
11333
|
/** Appends every figure of `other`. */
|
|
11334
11334
|
append(other) {
|
|
11335
11335
|
for (const f of other.figures) {
|
|
11336
|
-
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents) });
|
|
11336
|
+
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents), roundWiden: f.roundWiden });
|
|
11337
11337
|
}
|
|
11338
11338
|
for (let i = 0; i < other.getPath.types.length; i++) {
|
|
11339
11339
|
this.log(other.getPath.pts[2 * i], other.getPath.pts[2 * i + 1], other.getPath.types[i]);
|
|
@@ -15763,11 +15763,11 @@ function mirror(p, n) {
|
|
|
15763
15763
|
}
|
|
15764
15764
|
return p;
|
|
15765
15765
|
}
|
|
15766
|
-
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
15766
|
+
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical = false, edgeWidth = w, edgeHeight = h) {
|
|
15767
15767
|
const k = blurKernel(radius);
|
|
15768
15768
|
const taps = (k.length - 1) / 2;
|
|
15769
|
-
const horizontalIndex =
|
|
15770
|
-
const verticalIndex =
|
|
15769
|
+
const horizontalIndex = taps >= edgeWidth ? (x) => Math.max(0, Math.min(w - 1, x)) : (x) => mirror(x, w);
|
|
15770
|
+
const verticalIndex = taps >= edgeHeight ? (y) => Math.max(0, Math.min(h - 1, y)) : (y) => mirror(y, h);
|
|
15771
15771
|
const out = new Float64Array(w * h * 4);
|
|
15772
15772
|
for (let y = 0; y < h; y++) {
|
|
15773
15773
|
const row = y * w * 4;
|
|
@@ -15793,7 +15793,7 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15793
15793
|
}
|
|
15794
15794
|
if (taps > 0 && vRow >= 0 && vRow < h) {
|
|
15795
15795
|
const horizontal = out.slice();
|
|
15796
|
-
const endRow = Math.min(h, vRow +
|
|
15796
|
+
const endRow = fullVertical ? h : Math.min(h, vRow + Math.ceil(h / w));
|
|
15797
15797
|
for (let row = vRow; row < endRow; row++) {
|
|
15798
15798
|
const col = new Float64Array(w * 4);
|
|
15799
15799
|
for (let j = -taps; j <= taps; j++) {
|
|
@@ -15811,14 +15811,46 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15811
15811
|
}
|
|
15812
15812
|
return out;
|
|
15813
15813
|
}
|
|
15814
|
+
function blurReduction(radius) {
|
|
15815
|
+
return radius < 20 ? 1 : radius < 40 ? 2 : radius <= 80 ? 4 : radius < 160 ? 8 : 16;
|
|
15816
|
+
}
|
|
15817
|
+
function effectBlur(src, width, height, radius) {
|
|
15818
|
+
const factor = blurReduction(radius);
|
|
15819
|
+
if (factor === 1 || (width < 4 || height < 4) && (width % factor !== 0 || height % factor !== 0)) {
|
|
15820
|
+
return gdipBlur(src, width, height, radius);
|
|
15821
|
+
}
|
|
15822
|
+
const w = Math.ceil(width / factor);
|
|
15823
|
+
const h = Math.ceil(height / factor);
|
|
15824
|
+
const reduced = new Uint8ClampedArray(w * h * 4);
|
|
15825
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
15826
|
+
const x1 = Math.min(width, (x + 1) * factor), y1 = Math.min(height, (y + 1) * factor);
|
|
15827
|
+
const count = (x1 - x * factor) * (y1 - y * factor);
|
|
15828
|
+
for (let c = 0; c < 4; c++) {
|
|
15829
|
+
let sum = 0;
|
|
15830
|
+
for (let yy = y * factor; yy < y1; yy++) for (let xx = x * factor; xx < x1; xx++) sum += src[(yy * width + xx) * 4 + c];
|
|
15831
|
+
reduced[(y * w + x) * 4 + c] = Math.floor(sum / count);
|
|
15832
|
+
}
|
|
15833
|
+
}
|
|
15834
|
+
const filtered = gdipBlur(reduced, w, h, radius / factor, 0, false, true, Math.floor(width / factor), Math.floor(height / factor));
|
|
15835
|
+
for (let i = 0; i < filtered.length; i++) filtered[i] = Math.round(filtered[i]);
|
|
15836
|
+
const out = new Float64Array(src.length);
|
|
15837
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
15838
|
+
const px = clamp((x + 0.5) / factor - 0.5, 0, w - 1), py = clamp((y + 0.5) / factor - 0.5, 0, h - 1);
|
|
15839
|
+
const ix = Math.floor(px), iy = Math.floor(py), fx = px - ix, fy = py - iy;
|
|
15840
|
+
const a = (iy * w + ix) * 4, b = (iy * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15841
|
+
const d = (Math.min(h - 1, iy + 1) * w + ix) * 4, e = (Math.min(h - 1, iy + 1) * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15842
|
+
for (let c = 0; c < 4; c++) out[(y * width + x) * 4 + c] = Math.round((1 - fy) * ((1 - fx) * filtered[a + c] + fx * filtered[b + c]) + fy * ((1 - fx) * filtered[d + c] + fx * filtered[e + c]));
|
|
15843
|
+
}
|
|
15844
|
+
return out;
|
|
15845
|
+
}
|
|
15814
15846
|
function applyBlur(src, w, h, radius) {
|
|
15815
|
-
return Uint8ClampedArray.from(
|
|
15847
|
+
return Uint8ClampedArray.from(effectBlur(src, w, h, radius), Math.round);
|
|
15816
15848
|
}
|
|
15817
15849
|
function sharpenGain(_radius, amount) {
|
|
15818
15850
|
return roundHalfDown(64 * amount / (250 - 2 * amount)) / 64;
|
|
15819
15851
|
}
|
|
15820
15852
|
function applySharpen(src, w, h, radius, amount) {
|
|
15821
|
-
const blurred =
|
|
15853
|
+
const blurred = effectBlur(src, w, h, radius);
|
|
15822
15854
|
const gain = sharpenGain(radius, amount);
|
|
15823
15855
|
const out = new Uint8ClampedArray(src);
|
|
15824
15856
|
for (let i = 0; i < src.length; i += 4) {
|
|
@@ -28073,7 +28105,8 @@ var Outliner = class {
|
|
|
28073
28105
|
this.pen = penPolygon(opts.width);
|
|
28074
28106
|
this.n = this.pen.length;
|
|
28075
28107
|
this.rr = opts.cap === "round" && opts.join === "round";
|
|
28076
|
-
this.
|
|
28108
|
+
this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
|
|
28109
|
+
this.roundJoinSides = !!opts.roundCurveJoins || this.originalRoundJoinSides;
|
|
28077
28110
|
this.maxX = Math.max(...this.pen.map((q) => Math.abs(q[0])));
|
|
28078
28111
|
}
|
|
28079
28112
|
/**
|
|
@@ -28086,7 +28119,8 @@ var Outliner = class {
|
|
|
28086
28119
|
const dy = dir ? dir[1] : b[1] - a[1];
|
|
28087
28120
|
const d = drawDir ?? [dx, dy];
|
|
28088
28121
|
const [L, R] = drawVertices(this.pen, d[0], d[1]);
|
|
28089
|
-
|
|
28122
|
+
const perpendicular = this.opts.roundCurveJoins && drawDir ? drawDir : [dx, dy];
|
|
28123
|
+
return { dx, dy, L, R, v: flatVector(this.opts.width, perpendicular[0], perpendicular[1]), e: squareExtension(this.opts.width, dx, dy), curveEnd: !!drawDir };
|
|
28090
28124
|
}
|
|
28091
28125
|
push(p, v) {
|
|
28092
28126
|
this.pts.push([p[0] + v[0], p[1] + v[1]]);
|
|
@@ -28205,12 +28239,17 @@ var Outliner = class {
|
|
|
28205
28239
|
* segment).
|
|
28206
28240
|
*/
|
|
28207
28241
|
join(p, a, b, side, outer) {
|
|
28208
|
-
const {
|
|
28209
|
-
const
|
|
28210
|
-
|
|
28242
|
+
const { cap, width, miterLimit } = this.opts;
|
|
28243
|
+
const join = this.opts.roundCurveJoins ? "round" : this.opts.join;
|
|
28244
|
+
let sa = this.joinSide(a, side);
|
|
28245
|
+
let sb = this.joinSide(b, side);
|
|
28246
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides && a.curveEnd && b.curveEnd) {
|
|
28247
|
+
sa = side === "R" ? a.v : [-a.v[0], -a.v[1]];
|
|
28248
|
+
sb = side === "R" ? b.v : [-b.v[0], -b.v[1]];
|
|
28249
|
+
}
|
|
28211
28250
|
const Da = side === "R" ? a.R : a.L;
|
|
28212
28251
|
const Db = side === "R" ? b.R : b.L;
|
|
28213
|
-
if (this.roundJoinSides && Da === Db) {
|
|
28252
|
+
if (this.roundJoinSides && (Da === Db || this.opts.roundCurveJoins && sa[0] === sb[0] && sa[1] === sb[1])) {
|
|
28214
28253
|
this.push(p, sa);
|
|
28215
28254
|
return;
|
|
28216
28255
|
}
|
|
@@ -28234,7 +28273,12 @@ var Outliner = class {
|
|
|
28234
28273
|
}
|
|
28235
28274
|
} else {
|
|
28236
28275
|
this.pts.push([p[0], p[1]]);
|
|
28237
|
-
if (
|
|
28276
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides) {
|
|
28277
|
+
this.push(p, sb);
|
|
28278
|
+
this.push(p, sa);
|
|
28279
|
+
this.pts.push([p[0], p[1]]);
|
|
28280
|
+
}
|
|
28281
|
+
if (join === "round" && cap === "flat" && !this.opts.roundCurveJoins) {
|
|
28238
28282
|
this.push(p, sb);
|
|
28239
28283
|
this.wedge(p, sb, sa, false, false);
|
|
28240
28284
|
this.push(p, sa);
|
|
@@ -28404,9 +28448,9 @@ function dashPieces(P, tangents, pattern, shorten) {
|
|
|
28404
28448
|
}
|
|
28405
28449
|
function widenPath(path, opts) {
|
|
28406
28450
|
const out = [];
|
|
28407
|
-
const outliner = new Outliner(opts, out);
|
|
28408
28451
|
const dashed = !!opts.dashes && opts.dashes.length > 0;
|
|
28409
28452
|
for (const fig of path.figures) {
|
|
28453
|
+
const outliner = new Outliner(fig.roundWiden ? { ...opts, roundCurveJoins: true } : opts, out);
|
|
28410
28454
|
let P = [];
|
|
28411
28455
|
const dirs = [];
|
|
28412
28456
|
for (let i = 0; i + 1 < fig.pts.length; i += 2) {
|
|
@@ -28518,6 +28562,7 @@ function ellipseRasterPath(box, clockwise = false) {
|
|
|
28518
28562
|
const path = new GdiRasterPath();
|
|
28519
28563
|
path.addBeziers(ellipseBeziersBox(box, clockwise), true);
|
|
28520
28564
|
path.closeFigure();
|
|
28565
|
+
path.figures[0].roundWiden = true;
|
|
28521
28566
|
return path;
|
|
28522
28567
|
}
|
|
28523
28568
|
function frameMapper(box, l, t, w, h) {
|
|
@@ -28637,7 +28682,7 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
28637
28682
|
const { state } = rCtx;
|
|
28638
28683
|
const flags = state.penFlags ?? state.penStyle;
|
|
28639
28684
|
const matrix = gdiDeviceMatrix(rCtx);
|
|
28640
|
-
const widthPx =
|
|
28685
|
+
const widthPx = rCtx.wholeDevicePixels && (flags & 15) === 6 ? state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) : penDeviceWidth(rCtx);
|
|
28641
28686
|
const capBits = flags & 3840;
|
|
28642
28687
|
const joinBits = flags & 61440;
|
|
28643
28688
|
const dashes = state.penExtended ? geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
|
|
@@ -33507,6 +33552,7 @@ function flattenBracketPath(rCtx) {
|
|
|
33507
33552
|
}
|
|
33508
33553
|
for (const f of rCtx.rasterPath.figures) {
|
|
33509
33554
|
delete f.tangents;
|
|
33555
|
+
delete f.roundWiden;
|
|
33510
33556
|
}
|
|
33511
33557
|
syncPathCmds(rCtx);
|
|
33512
33558
|
}
|
|
@@ -37534,19 +37580,12 @@ function compatBox(p, l, t, r, b, opts = {}) {
|
|
|
37534
37580
|
if (w > 1) {
|
|
37535
37581
|
const matrix = gdiDeviceMatrix(p.rCtx);
|
|
37536
37582
|
const rawWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) / p.kx;
|
|
37537
|
-
|
|
37538
|
-
|
|
37539
|
-
|
|
37540
|
-
|
|
37541
|
-
|
|
37542
|
-
|
|
37543
|
-
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37544
|
-
return box;
|
|
37545
|
-
}
|
|
37546
|
-
box.x0 += Math.round(Math.floor(w / 2) * ux);
|
|
37547
|
-
box.y0 += Math.round(Math.floor(w / 2) * uy);
|
|
37548
|
-
box.x1 -= Math.round(Math.floor((w - 1) / 2) * ux);
|
|
37549
|
-
box.y1 -= Math.round(Math.floor((w - 1) / 2) * uy);
|
|
37583
|
+
box.x1 += Math.round(ux);
|
|
37584
|
+
box.y1 += Math.round(uy);
|
|
37585
|
+
box.x0 += Math.round(rawWidth * ux / 2);
|
|
37586
|
+
box.y0 += Math.round(rawWidth * uy / 2);
|
|
37587
|
+
box.x1 -= Math.round(rawWidth * ux / 2);
|
|
37588
|
+
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37550
37589
|
}
|
|
37551
37590
|
}
|
|
37552
37591
|
return box;
|
|
@@ -37610,6 +37649,11 @@ function compatCorner(p, w, h, box) {
|
|
|
37610
37649
|
const ch = Math.round(Math.abs(h * m[3]) * 16);
|
|
37611
37650
|
const ux = 16 * p.kx;
|
|
37612
37651
|
const uy = 16 * p.ky;
|
|
37652
|
+
if ((p.rCtx.state.penStyle & 15) === PS_INSIDEFRAME && !penIsCosmetic(p.rCtx)) {
|
|
37653
|
+
const penWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) * 16;
|
|
37654
|
+
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37655
|
+
return [Math.min(cw, width + penWidth) * width / (width + penWidth), Math.min(ch, height + penWidth) * height / (height + penWidth)];
|
|
37656
|
+
}
|
|
37613
37657
|
if (!penIsNull(p) && penIsCosmetic(p.rCtx)) {
|
|
37614
37658
|
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37615
37659
|
return [Math.min(cw, width + ux) * width / (width + ux), Math.min(ch, height + uy) * height / (height + uy)];
|
package/dist/browser.mjs
CHANGED
|
@@ -11331,7 +11331,7 @@ var GdiRasterPath = class {
|
|
|
11331
11331
|
/** Appends every figure of `other`. */
|
|
11332
11332
|
append(other) {
|
|
11333
11333
|
for (const f of other.figures) {
|
|
11334
|
-
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents) });
|
|
11334
|
+
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents), roundWiden: f.roundWiden });
|
|
11335
11335
|
}
|
|
11336
11336
|
for (let i = 0; i < other.getPath.types.length; i++) {
|
|
11337
11337
|
this.log(other.getPath.pts[2 * i], other.getPath.pts[2 * i + 1], other.getPath.types[i]);
|
|
@@ -15761,11 +15761,11 @@ function mirror(p, n) {
|
|
|
15761
15761
|
}
|
|
15762
15762
|
return p;
|
|
15763
15763
|
}
|
|
15764
|
-
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
15764
|
+
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical = false, edgeWidth = w, edgeHeight = h) {
|
|
15765
15765
|
const k = blurKernel(radius);
|
|
15766
15766
|
const taps = (k.length - 1) / 2;
|
|
15767
|
-
const horizontalIndex =
|
|
15768
|
-
const verticalIndex =
|
|
15767
|
+
const horizontalIndex = taps >= edgeWidth ? (x) => Math.max(0, Math.min(w - 1, x)) : (x) => mirror(x, w);
|
|
15768
|
+
const verticalIndex = taps >= edgeHeight ? (y) => Math.max(0, Math.min(h - 1, y)) : (y) => mirror(y, h);
|
|
15769
15769
|
const out = new Float64Array(w * h * 4);
|
|
15770
15770
|
for (let y = 0; y < h; y++) {
|
|
15771
15771
|
const row = y * w * 4;
|
|
@@ -15791,7 +15791,7 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15791
15791
|
}
|
|
15792
15792
|
if (taps > 0 && vRow >= 0 && vRow < h) {
|
|
15793
15793
|
const horizontal = out.slice();
|
|
15794
|
-
const endRow = Math.min(h, vRow +
|
|
15794
|
+
const endRow = fullVertical ? h : Math.min(h, vRow + Math.ceil(h / w));
|
|
15795
15795
|
for (let row = vRow; row < endRow; row++) {
|
|
15796
15796
|
const col = new Float64Array(w * 4);
|
|
15797
15797
|
for (let j = -taps; j <= taps; j++) {
|
|
@@ -15809,14 +15809,46 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15809
15809
|
}
|
|
15810
15810
|
return out;
|
|
15811
15811
|
}
|
|
15812
|
+
function blurReduction(radius) {
|
|
15813
|
+
return radius < 20 ? 1 : radius < 40 ? 2 : radius <= 80 ? 4 : radius < 160 ? 8 : 16;
|
|
15814
|
+
}
|
|
15815
|
+
function effectBlur(src, width, height, radius) {
|
|
15816
|
+
const factor = blurReduction(radius);
|
|
15817
|
+
if (factor === 1 || (width < 4 || height < 4) && (width % factor !== 0 || height % factor !== 0)) {
|
|
15818
|
+
return gdipBlur(src, width, height, radius);
|
|
15819
|
+
}
|
|
15820
|
+
const w = Math.ceil(width / factor);
|
|
15821
|
+
const h = Math.ceil(height / factor);
|
|
15822
|
+
const reduced = new Uint8ClampedArray(w * h * 4);
|
|
15823
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
15824
|
+
const x1 = Math.min(width, (x + 1) * factor), y1 = Math.min(height, (y + 1) * factor);
|
|
15825
|
+
const count = (x1 - x * factor) * (y1 - y * factor);
|
|
15826
|
+
for (let c = 0; c < 4; c++) {
|
|
15827
|
+
let sum = 0;
|
|
15828
|
+
for (let yy = y * factor; yy < y1; yy++) for (let xx = x * factor; xx < x1; xx++) sum += src[(yy * width + xx) * 4 + c];
|
|
15829
|
+
reduced[(y * w + x) * 4 + c] = Math.floor(sum / count);
|
|
15830
|
+
}
|
|
15831
|
+
}
|
|
15832
|
+
const filtered = gdipBlur(reduced, w, h, radius / factor, 0, false, true, Math.floor(width / factor), Math.floor(height / factor));
|
|
15833
|
+
for (let i = 0; i < filtered.length; i++) filtered[i] = Math.round(filtered[i]);
|
|
15834
|
+
const out = new Float64Array(src.length);
|
|
15835
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
15836
|
+
const px = clamp((x + 0.5) / factor - 0.5, 0, w - 1), py = clamp((y + 0.5) / factor - 0.5, 0, h - 1);
|
|
15837
|
+
const ix = Math.floor(px), iy = Math.floor(py), fx = px - ix, fy = py - iy;
|
|
15838
|
+
const a = (iy * w + ix) * 4, b = (iy * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15839
|
+
const d = (Math.min(h - 1, iy + 1) * w + ix) * 4, e = (Math.min(h - 1, iy + 1) * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15840
|
+
for (let c = 0; c < 4; c++) out[(y * width + x) * 4 + c] = Math.round((1 - fy) * ((1 - fx) * filtered[a + c] + fx * filtered[b + c]) + fy * ((1 - fx) * filtered[d + c] + fx * filtered[e + c]));
|
|
15841
|
+
}
|
|
15842
|
+
return out;
|
|
15843
|
+
}
|
|
15812
15844
|
function applyBlur(src, w, h, radius) {
|
|
15813
|
-
return Uint8ClampedArray.from(
|
|
15845
|
+
return Uint8ClampedArray.from(effectBlur(src, w, h, radius), Math.round);
|
|
15814
15846
|
}
|
|
15815
15847
|
function sharpenGain(_radius, amount) {
|
|
15816
15848
|
return roundHalfDown(64 * amount / (250 - 2 * amount)) / 64;
|
|
15817
15849
|
}
|
|
15818
15850
|
function applySharpen(src, w, h, radius, amount) {
|
|
15819
|
-
const blurred =
|
|
15851
|
+
const blurred = effectBlur(src, w, h, radius);
|
|
15820
15852
|
const gain = sharpenGain(radius, amount);
|
|
15821
15853
|
const out = new Uint8ClampedArray(src);
|
|
15822
15854
|
for (let i = 0; i < src.length; i += 4) {
|
|
@@ -28071,7 +28103,8 @@ var Outliner = class {
|
|
|
28071
28103
|
this.pen = penPolygon(opts.width);
|
|
28072
28104
|
this.n = this.pen.length;
|
|
28073
28105
|
this.rr = opts.cap === "round" && opts.join === "round";
|
|
28074
|
-
this.
|
|
28106
|
+
this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
|
|
28107
|
+
this.roundJoinSides = !!opts.roundCurveJoins || this.originalRoundJoinSides;
|
|
28075
28108
|
this.maxX = Math.max(...this.pen.map((q) => Math.abs(q[0])));
|
|
28076
28109
|
}
|
|
28077
28110
|
/**
|
|
@@ -28084,7 +28117,8 @@ var Outliner = class {
|
|
|
28084
28117
|
const dy = dir ? dir[1] : b[1] - a[1];
|
|
28085
28118
|
const d = drawDir ?? [dx, dy];
|
|
28086
28119
|
const [L, R] = drawVertices(this.pen, d[0], d[1]);
|
|
28087
|
-
|
|
28120
|
+
const perpendicular = this.opts.roundCurveJoins && drawDir ? drawDir : [dx, dy];
|
|
28121
|
+
return { dx, dy, L, R, v: flatVector(this.opts.width, perpendicular[0], perpendicular[1]), e: squareExtension(this.opts.width, dx, dy), curveEnd: !!drawDir };
|
|
28088
28122
|
}
|
|
28089
28123
|
push(p, v) {
|
|
28090
28124
|
this.pts.push([p[0] + v[0], p[1] + v[1]]);
|
|
@@ -28203,12 +28237,17 @@ var Outliner = class {
|
|
|
28203
28237
|
* segment).
|
|
28204
28238
|
*/
|
|
28205
28239
|
join(p, a, b, side, outer) {
|
|
28206
|
-
const {
|
|
28207
|
-
const
|
|
28208
|
-
|
|
28240
|
+
const { cap, width, miterLimit } = this.opts;
|
|
28241
|
+
const join = this.opts.roundCurveJoins ? "round" : this.opts.join;
|
|
28242
|
+
let sa = this.joinSide(a, side);
|
|
28243
|
+
let sb = this.joinSide(b, side);
|
|
28244
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides && a.curveEnd && b.curveEnd) {
|
|
28245
|
+
sa = side === "R" ? a.v : [-a.v[0], -a.v[1]];
|
|
28246
|
+
sb = side === "R" ? b.v : [-b.v[0], -b.v[1]];
|
|
28247
|
+
}
|
|
28209
28248
|
const Da = side === "R" ? a.R : a.L;
|
|
28210
28249
|
const Db = side === "R" ? b.R : b.L;
|
|
28211
|
-
if (this.roundJoinSides && Da === Db) {
|
|
28250
|
+
if (this.roundJoinSides && (Da === Db || this.opts.roundCurveJoins && sa[0] === sb[0] && sa[1] === sb[1])) {
|
|
28212
28251
|
this.push(p, sa);
|
|
28213
28252
|
return;
|
|
28214
28253
|
}
|
|
@@ -28232,7 +28271,12 @@ var Outliner = class {
|
|
|
28232
28271
|
}
|
|
28233
28272
|
} else {
|
|
28234
28273
|
this.pts.push([p[0], p[1]]);
|
|
28235
|
-
if (
|
|
28274
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides) {
|
|
28275
|
+
this.push(p, sb);
|
|
28276
|
+
this.push(p, sa);
|
|
28277
|
+
this.pts.push([p[0], p[1]]);
|
|
28278
|
+
}
|
|
28279
|
+
if (join === "round" && cap === "flat" && !this.opts.roundCurveJoins) {
|
|
28236
28280
|
this.push(p, sb);
|
|
28237
28281
|
this.wedge(p, sb, sa, false, false);
|
|
28238
28282
|
this.push(p, sa);
|
|
@@ -28402,9 +28446,9 @@ function dashPieces(P, tangents, pattern, shorten) {
|
|
|
28402
28446
|
}
|
|
28403
28447
|
function widenPath(path, opts) {
|
|
28404
28448
|
const out = [];
|
|
28405
|
-
const outliner = new Outliner(opts, out);
|
|
28406
28449
|
const dashed = !!opts.dashes && opts.dashes.length > 0;
|
|
28407
28450
|
for (const fig of path.figures) {
|
|
28451
|
+
const outliner = new Outliner(fig.roundWiden ? { ...opts, roundCurveJoins: true } : opts, out);
|
|
28408
28452
|
let P = [];
|
|
28409
28453
|
const dirs = [];
|
|
28410
28454
|
for (let i = 0; i + 1 < fig.pts.length; i += 2) {
|
|
@@ -28516,6 +28560,7 @@ function ellipseRasterPath(box, clockwise = false) {
|
|
|
28516
28560
|
const path = new GdiRasterPath();
|
|
28517
28561
|
path.addBeziers(ellipseBeziersBox(box, clockwise), true);
|
|
28518
28562
|
path.closeFigure();
|
|
28563
|
+
path.figures[0].roundWiden = true;
|
|
28519
28564
|
return path;
|
|
28520
28565
|
}
|
|
28521
28566
|
function frameMapper(box, l, t, w, h) {
|
|
@@ -28635,7 +28680,7 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
28635
28680
|
const { state } = rCtx;
|
|
28636
28681
|
const flags = state.penFlags ?? state.penStyle;
|
|
28637
28682
|
const matrix = gdiDeviceMatrix(rCtx);
|
|
28638
|
-
const widthPx =
|
|
28683
|
+
const widthPx = rCtx.wholeDevicePixels && (flags & 15) === 6 ? state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) : penDeviceWidth(rCtx);
|
|
28639
28684
|
const capBits = flags & 3840;
|
|
28640
28685
|
const joinBits = flags & 61440;
|
|
28641
28686
|
const dashes = state.penExtended ? geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
|
|
@@ -33505,6 +33550,7 @@ function flattenBracketPath(rCtx) {
|
|
|
33505
33550
|
}
|
|
33506
33551
|
for (const f of rCtx.rasterPath.figures) {
|
|
33507
33552
|
delete f.tangents;
|
|
33553
|
+
delete f.roundWiden;
|
|
33508
33554
|
}
|
|
33509
33555
|
syncPathCmds(rCtx);
|
|
33510
33556
|
}
|
|
@@ -37532,19 +37578,12 @@ function compatBox(p, l, t, r, b, opts = {}) {
|
|
|
37532
37578
|
if (w > 1) {
|
|
37533
37579
|
const matrix = gdiDeviceMatrix(p.rCtx);
|
|
37534
37580
|
const rawWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) / p.kx;
|
|
37535
|
-
|
|
37536
|
-
|
|
37537
|
-
|
|
37538
|
-
|
|
37539
|
-
|
|
37540
|
-
|
|
37541
|
-
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37542
|
-
return box;
|
|
37543
|
-
}
|
|
37544
|
-
box.x0 += Math.round(Math.floor(w / 2) * ux);
|
|
37545
|
-
box.y0 += Math.round(Math.floor(w / 2) * uy);
|
|
37546
|
-
box.x1 -= Math.round(Math.floor((w - 1) / 2) * ux);
|
|
37547
|
-
box.y1 -= Math.round(Math.floor((w - 1) / 2) * uy);
|
|
37581
|
+
box.x1 += Math.round(ux);
|
|
37582
|
+
box.y1 += Math.round(uy);
|
|
37583
|
+
box.x0 += Math.round(rawWidth * ux / 2);
|
|
37584
|
+
box.y0 += Math.round(rawWidth * uy / 2);
|
|
37585
|
+
box.x1 -= Math.round(rawWidth * ux / 2);
|
|
37586
|
+
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37548
37587
|
}
|
|
37549
37588
|
}
|
|
37550
37589
|
return box;
|
|
@@ -37608,6 +37647,11 @@ function compatCorner(p, w, h, box) {
|
|
|
37608
37647
|
const ch = Math.round(Math.abs(h * m[3]) * 16);
|
|
37609
37648
|
const ux = 16 * p.kx;
|
|
37610
37649
|
const uy = 16 * p.ky;
|
|
37650
|
+
if ((p.rCtx.state.penStyle & 15) === PS_INSIDEFRAME && !penIsCosmetic(p.rCtx)) {
|
|
37651
|
+
const penWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) * 16;
|
|
37652
|
+
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37653
|
+
return [Math.min(cw, width + penWidth) * width / (width + penWidth), Math.min(ch, height + penWidth) * height / (height + penWidth)];
|
|
37654
|
+
}
|
|
37611
37655
|
if (!penIsNull(p) && penIsCosmetic(p.rCtx)) {
|
|
37612
37656
|
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37613
37657
|
return [Math.min(cw, width + ux) * width / (width + ux), Math.min(ch, height + uy) * height / (height + uy)];
|
package/dist/index.js
CHANGED
|
@@ -11334,7 +11334,7 @@ var GdiRasterPath = class {
|
|
|
11334
11334
|
/** Appends every figure of `other`. */
|
|
11335
11335
|
append(other) {
|
|
11336
11336
|
for (const f of other.figures) {
|
|
11337
|
-
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents) });
|
|
11337
|
+
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents), roundWiden: f.roundWiden });
|
|
11338
11338
|
}
|
|
11339
11339
|
for (let i = 0; i < other.getPath.types.length; i++) {
|
|
11340
11340
|
this.log(other.getPath.pts[2 * i], other.getPath.pts[2 * i + 1], other.getPath.types[i]);
|
|
@@ -15764,11 +15764,11 @@ function mirror(p, n) {
|
|
|
15764
15764
|
}
|
|
15765
15765
|
return p;
|
|
15766
15766
|
}
|
|
15767
|
-
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
15767
|
+
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical = false, edgeWidth = w, edgeHeight = h) {
|
|
15768
15768
|
const k = blurKernel(radius);
|
|
15769
15769
|
const taps = (k.length - 1) / 2;
|
|
15770
|
-
const horizontalIndex =
|
|
15771
|
-
const verticalIndex =
|
|
15770
|
+
const horizontalIndex = taps >= edgeWidth ? (x) => Math.max(0, Math.min(w - 1, x)) : (x) => mirror(x, w);
|
|
15771
|
+
const verticalIndex = taps >= edgeHeight ? (y) => Math.max(0, Math.min(h - 1, y)) : (y) => mirror(y, h);
|
|
15772
15772
|
const out = new Float64Array(w * h * 4);
|
|
15773
15773
|
for (let y = 0; y < h; y++) {
|
|
15774
15774
|
const row = y * w * 4;
|
|
@@ -15794,7 +15794,7 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15794
15794
|
}
|
|
15795
15795
|
if (taps > 0 && vRow >= 0 && vRow < h) {
|
|
15796
15796
|
const horizontal = out.slice();
|
|
15797
|
-
const endRow = Math.min(h, vRow +
|
|
15797
|
+
const endRow = fullVertical ? h : Math.min(h, vRow + Math.ceil(h / w));
|
|
15798
15798
|
for (let row = vRow; row < endRow; row++) {
|
|
15799
15799
|
const col = new Float64Array(w * 4);
|
|
15800
15800
|
for (let j = -taps; j <= taps; j++) {
|
|
@@ -15812,14 +15812,46 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15812
15812
|
}
|
|
15813
15813
|
return out;
|
|
15814
15814
|
}
|
|
15815
|
+
function blurReduction(radius) {
|
|
15816
|
+
return radius < 20 ? 1 : radius < 40 ? 2 : radius <= 80 ? 4 : radius < 160 ? 8 : 16;
|
|
15817
|
+
}
|
|
15818
|
+
function effectBlur(src, width, height, radius) {
|
|
15819
|
+
const factor = blurReduction(radius);
|
|
15820
|
+
if (factor === 1 || (width < 4 || height < 4) && (width % factor !== 0 || height % factor !== 0)) {
|
|
15821
|
+
return gdipBlur(src, width, height, radius);
|
|
15822
|
+
}
|
|
15823
|
+
const w = Math.ceil(width / factor);
|
|
15824
|
+
const h = Math.ceil(height / factor);
|
|
15825
|
+
const reduced = new Uint8ClampedArray(w * h * 4);
|
|
15826
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
15827
|
+
const x1 = Math.min(width, (x + 1) * factor), y1 = Math.min(height, (y + 1) * factor);
|
|
15828
|
+
const count = (x1 - x * factor) * (y1 - y * factor);
|
|
15829
|
+
for (let c = 0; c < 4; c++) {
|
|
15830
|
+
let sum = 0;
|
|
15831
|
+
for (let yy = y * factor; yy < y1; yy++) for (let xx = x * factor; xx < x1; xx++) sum += src[(yy * width + xx) * 4 + c];
|
|
15832
|
+
reduced[(y * w + x) * 4 + c] = Math.floor(sum / count);
|
|
15833
|
+
}
|
|
15834
|
+
}
|
|
15835
|
+
const filtered = gdipBlur(reduced, w, h, radius / factor, 0, false, true, Math.floor(width / factor), Math.floor(height / factor));
|
|
15836
|
+
for (let i = 0; i < filtered.length; i++) filtered[i] = Math.round(filtered[i]);
|
|
15837
|
+
const out = new Float64Array(src.length);
|
|
15838
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
15839
|
+
const px = clamp((x + 0.5) / factor - 0.5, 0, w - 1), py = clamp((y + 0.5) / factor - 0.5, 0, h - 1);
|
|
15840
|
+
const ix = Math.floor(px), iy = Math.floor(py), fx = px - ix, fy = py - iy;
|
|
15841
|
+
const a = (iy * w + ix) * 4, b = (iy * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15842
|
+
const d = (Math.min(h - 1, iy + 1) * w + ix) * 4, e = (Math.min(h - 1, iy + 1) * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15843
|
+
for (let c = 0; c < 4; c++) out[(y * width + x) * 4 + c] = Math.round((1 - fy) * ((1 - fx) * filtered[a + c] + fx * filtered[b + c]) + fy * ((1 - fx) * filtered[d + c] + fx * filtered[e + c]));
|
|
15844
|
+
}
|
|
15845
|
+
return out;
|
|
15846
|
+
}
|
|
15815
15847
|
function applyBlur(src, w, h, radius) {
|
|
15816
|
-
return Uint8ClampedArray.from(
|
|
15848
|
+
return Uint8ClampedArray.from(effectBlur(src, w, h, radius), Math.round);
|
|
15817
15849
|
}
|
|
15818
15850
|
function sharpenGain(_radius, amount) {
|
|
15819
15851
|
return roundHalfDown(64 * amount / (250 - 2 * amount)) / 64;
|
|
15820
15852
|
}
|
|
15821
15853
|
function applySharpen(src, w, h, radius, amount) {
|
|
15822
|
-
const blurred =
|
|
15854
|
+
const blurred = effectBlur(src, w, h, radius);
|
|
15823
15855
|
const gain = sharpenGain(radius, amount);
|
|
15824
15856
|
const out = new Uint8ClampedArray(src);
|
|
15825
15857
|
for (let i = 0; i < src.length; i += 4) {
|
|
@@ -28074,7 +28106,8 @@ var Outliner = class {
|
|
|
28074
28106
|
this.pen = penPolygon(opts.width);
|
|
28075
28107
|
this.n = this.pen.length;
|
|
28076
28108
|
this.rr = opts.cap === "round" && opts.join === "round";
|
|
28077
|
-
this.
|
|
28109
|
+
this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
|
|
28110
|
+
this.roundJoinSides = !!opts.roundCurveJoins || this.originalRoundJoinSides;
|
|
28078
28111
|
this.maxX = Math.max(...this.pen.map((q) => Math.abs(q[0])));
|
|
28079
28112
|
}
|
|
28080
28113
|
/**
|
|
@@ -28087,7 +28120,8 @@ var Outliner = class {
|
|
|
28087
28120
|
const dy = dir ? dir[1] : b[1] - a[1];
|
|
28088
28121
|
const d = drawDir ?? [dx, dy];
|
|
28089
28122
|
const [L, R] = drawVertices(this.pen, d[0], d[1]);
|
|
28090
|
-
|
|
28123
|
+
const perpendicular = this.opts.roundCurveJoins && drawDir ? drawDir : [dx, dy];
|
|
28124
|
+
return { dx, dy, L, R, v: flatVector(this.opts.width, perpendicular[0], perpendicular[1]), e: squareExtension(this.opts.width, dx, dy), curveEnd: !!drawDir };
|
|
28091
28125
|
}
|
|
28092
28126
|
push(p, v) {
|
|
28093
28127
|
this.pts.push([p[0] + v[0], p[1] + v[1]]);
|
|
@@ -28206,12 +28240,17 @@ var Outliner = class {
|
|
|
28206
28240
|
* segment).
|
|
28207
28241
|
*/
|
|
28208
28242
|
join(p, a, b, side, outer) {
|
|
28209
|
-
const {
|
|
28210
|
-
const
|
|
28211
|
-
|
|
28243
|
+
const { cap, width, miterLimit } = this.opts;
|
|
28244
|
+
const join = this.opts.roundCurveJoins ? "round" : this.opts.join;
|
|
28245
|
+
let sa = this.joinSide(a, side);
|
|
28246
|
+
let sb = this.joinSide(b, side);
|
|
28247
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides && a.curveEnd && b.curveEnd) {
|
|
28248
|
+
sa = side === "R" ? a.v : [-a.v[0], -a.v[1]];
|
|
28249
|
+
sb = side === "R" ? b.v : [-b.v[0], -b.v[1]];
|
|
28250
|
+
}
|
|
28212
28251
|
const Da = side === "R" ? a.R : a.L;
|
|
28213
28252
|
const Db = side === "R" ? b.R : b.L;
|
|
28214
|
-
if (this.roundJoinSides && Da === Db) {
|
|
28253
|
+
if (this.roundJoinSides && (Da === Db || this.opts.roundCurveJoins && sa[0] === sb[0] && sa[1] === sb[1])) {
|
|
28215
28254
|
this.push(p, sa);
|
|
28216
28255
|
return;
|
|
28217
28256
|
}
|
|
@@ -28235,7 +28274,12 @@ var Outliner = class {
|
|
|
28235
28274
|
}
|
|
28236
28275
|
} else {
|
|
28237
28276
|
this.pts.push([p[0], p[1]]);
|
|
28238
|
-
if (
|
|
28277
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides) {
|
|
28278
|
+
this.push(p, sb);
|
|
28279
|
+
this.push(p, sa);
|
|
28280
|
+
this.pts.push([p[0], p[1]]);
|
|
28281
|
+
}
|
|
28282
|
+
if (join === "round" && cap === "flat" && !this.opts.roundCurveJoins) {
|
|
28239
28283
|
this.push(p, sb);
|
|
28240
28284
|
this.wedge(p, sb, sa, false, false);
|
|
28241
28285
|
this.push(p, sa);
|
|
@@ -28405,9 +28449,9 @@ function dashPieces(P, tangents, pattern, shorten) {
|
|
|
28405
28449
|
}
|
|
28406
28450
|
function widenPath(path, opts) {
|
|
28407
28451
|
const out = [];
|
|
28408
|
-
const outliner = new Outliner(opts, out);
|
|
28409
28452
|
const dashed = !!opts.dashes && opts.dashes.length > 0;
|
|
28410
28453
|
for (const fig of path.figures) {
|
|
28454
|
+
const outliner = new Outliner(fig.roundWiden ? { ...opts, roundCurveJoins: true } : opts, out);
|
|
28411
28455
|
let P = [];
|
|
28412
28456
|
const dirs = [];
|
|
28413
28457
|
for (let i = 0; i + 1 < fig.pts.length; i += 2) {
|
|
@@ -28519,6 +28563,7 @@ function ellipseRasterPath(box, clockwise = false) {
|
|
|
28519
28563
|
const path = new GdiRasterPath();
|
|
28520
28564
|
path.addBeziers(ellipseBeziersBox(box, clockwise), true);
|
|
28521
28565
|
path.closeFigure();
|
|
28566
|
+
path.figures[0].roundWiden = true;
|
|
28522
28567
|
return path;
|
|
28523
28568
|
}
|
|
28524
28569
|
function frameMapper(box, l, t, w, h) {
|
|
@@ -28638,7 +28683,7 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
28638
28683
|
const { state } = rCtx;
|
|
28639
28684
|
const flags = state.penFlags ?? state.penStyle;
|
|
28640
28685
|
const matrix = gdiDeviceMatrix(rCtx);
|
|
28641
|
-
const widthPx =
|
|
28686
|
+
const widthPx = rCtx.wholeDevicePixels && (flags & 15) === 6 ? state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) : penDeviceWidth(rCtx);
|
|
28642
28687
|
const capBits = flags & 3840;
|
|
28643
28688
|
const joinBits = flags & 61440;
|
|
28644
28689
|
const dashes = state.penExtended ? geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
|
|
@@ -33508,6 +33553,7 @@ function flattenBracketPath(rCtx) {
|
|
|
33508
33553
|
}
|
|
33509
33554
|
for (const f of rCtx.rasterPath.figures) {
|
|
33510
33555
|
delete f.tangents;
|
|
33556
|
+
delete f.roundWiden;
|
|
33511
33557
|
}
|
|
33512
33558
|
syncPathCmds(rCtx);
|
|
33513
33559
|
}
|
|
@@ -37535,19 +37581,12 @@ function compatBox(p, l, t, r, b, opts = {}) {
|
|
|
37535
37581
|
if (w > 1) {
|
|
37536
37582
|
const matrix = gdiDeviceMatrix(p.rCtx);
|
|
37537
37583
|
const rawWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) / p.kx;
|
|
37538
|
-
|
|
37539
|
-
|
|
37540
|
-
|
|
37541
|
-
|
|
37542
|
-
|
|
37543
|
-
|
|
37544
|
-
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37545
|
-
return box;
|
|
37546
|
-
}
|
|
37547
|
-
box.x0 += Math.round(Math.floor(w / 2) * ux);
|
|
37548
|
-
box.y0 += Math.round(Math.floor(w / 2) * uy);
|
|
37549
|
-
box.x1 -= Math.round(Math.floor((w - 1) / 2) * ux);
|
|
37550
|
-
box.y1 -= Math.round(Math.floor((w - 1) / 2) * uy);
|
|
37584
|
+
box.x1 += Math.round(ux);
|
|
37585
|
+
box.y1 += Math.round(uy);
|
|
37586
|
+
box.x0 += Math.round(rawWidth * ux / 2);
|
|
37587
|
+
box.y0 += Math.round(rawWidth * uy / 2);
|
|
37588
|
+
box.x1 -= Math.round(rawWidth * ux / 2);
|
|
37589
|
+
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37551
37590
|
}
|
|
37552
37591
|
}
|
|
37553
37592
|
return box;
|
|
@@ -37611,6 +37650,11 @@ function compatCorner(p, w, h, box) {
|
|
|
37611
37650
|
const ch = Math.round(Math.abs(h * m[3]) * 16);
|
|
37612
37651
|
const ux = 16 * p.kx;
|
|
37613
37652
|
const uy = 16 * p.ky;
|
|
37653
|
+
if ((p.rCtx.state.penStyle & 15) === PS_INSIDEFRAME && !penIsCosmetic(p.rCtx)) {
|
|
37654
|
+
const penWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) * 16;
|
|
37655
|
+
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37656
|
+
return [Math.min(cw, width + penWidth) * width / (width + penWidth), Math.min(ch, height + penWidth) * height / (height + penWidth)];
|
|
37657
|
+
}
|
|
37614
37658
|
if (!penIsNull(p) && penIsCosmetic(p.rCtx)) {
|
|
37615
37659
|
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37616
37660
|
return [Math.min(cw, width + ux) * width / (width + ux), Math.min(ch, height + uy) * height / (height + uy)];
|
package/dist/index.mjs
CHANGED
|
@@ -11332,7 +11332,7 @@ var GdiRasterPath = class {
|
|
|
11332
11332
|
/** Appends every figure of `other`. */
|
|
11333
11333
|
append(other) {
|
|
11334
11334
|
for (const f of other.figures) {
|
|
11335
|
-
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents) });
|
|
11335
|
+
this.figures.push({ pts: f.pts.slice(), closed: f.closed, tangents: f.tangents && new Map(f.tangents), roundWiden: f.roundWiden });
|
|
11336
11336
|
}
|
|
11337
11337
|
for (let i = 0; i < other.getPath.types.length; i++) {
|
|
11338
11338
|
this.log(other.getPath.pts[2 * i], other.getPath.pts[2 * i + 1], other.getPath.types[i]);
|
|
@@ -15762,11 +15762,11 @@ function mirror(p, n) {
|
|
|
15762
15762
|
}
|
|
15763
15763
|
return p;
|
|
15764
15764
|
}
|
|
15765
|
-
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
15765
|
+
function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false, fullVertical = false, edgeWidth = w, edgeHeight = h) {
|
|
15766
15766
|
const k = blurKernel(radius);
|
|
15767
15767
|
const taps = (k.length - 1) / 2;
|
|
15768
|
-
const horizontalIndex =
|
|
15769
|
-
const verticalIndex =
|
|
15768
|
+
const horizontalIndex = taps >= edgeWidth ? (x) => Math.max(0, Math.min(w - 1, x)) : (x) => mirror(x, w);
|
|
15769
|
+
const verticalIndex = taps >= edgeHeight ? (y) => Math.max(0, Math.min(h - 1, y)) : (y) => mirror(y, h);
|
|
15770
15770
|
const out = new Float64Array(w * h * 4);
|
|
15771
15771
|
for (let y = 0; y < h; y++) {
|
|
15772
15772
|
const row = y * w * 4;
|
|
@@ -15792,7 +15792,7 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15792
15792
|
}
|
|
15793
15793
|
if (taps > 0 && vRow >= 0 && vRow < h) {
|
|
15794
15794
|
const horizontal = out.slice();
|
|
15795
|
-
const endRow = Math.min(h, vRow +
|
|
15795
|
+
const endRow = fullVertical ? h : Math.min(h, vRow + Math.ceil(h / w));
|
|
15796
15796
|
for (let row = vRow; row < endRow; row++) {
|
|
15797
15797
|
const col = new Float64Array(w * 4);
|
|
15798
15798
|
for (let j = -taps; j <= taps; j++) {
|
|
@@ -15810,14 +15810,46 @@ function gdipBlur(src, w, h, radius, vRow = 0, vZeroAbove = false) {
|
|
|
15810
15810
|
}
|
|
15811
15811
|
return out;
|
|
15812
15812
|
}
|
|
15813
|
+
function blurReduction(radius) {
|
|
15814
|
+
return radius < 20 ? 1 : radius < 40 ? 2 : radius <= 80 ? 4 : radius < 160 ? 8 : 16;
|
|
15815
|
+
}
|
|
15816
|
+
function effectBlur(src, width, height, radius) {
|
|
15817
|
+
const factor = blurReduction(radius);
|
|
15818
|
+
if (factor === 1 || (width < 4 || height < 4) && (width % factor !== 0 || height % factor !== 0)) {
|
|
15819
|
+
return gdipBlur(src, width, height, radius);
|
|
15820
|
+
}
|
|
15821
|
+
const w = Math.ceil(width / factor);
|
|
15822
|
+
const h = Math.ceil(height / factor);
|
|
15823
|
+
const reduced = new Uint8ClampedArray(w * h * 4);
|
|
15824
|
+
for (let y = 0; y < h; y++) for (let x = 0; x < w; x++) {
|
|
15825
|
+
const x1 = Math.min(width, (x + 1) * factor), y1 = Math.min(height, (y + 1) * factor);
|
|
15826
|
+
const count = (x1 - x * factor) * (y1 - y * factor);
|
|
15827
|
+
for (let c = 0; c < 4; c++) {
|
|
15828
|
+
let sum = 0;
|
|
15829
|
+
for (let yy = y * factor; yy < y1; yy++) for (let xx = x * factor; xx < x1; xx++) sum += src[(yy * width + xx) * 4 + c];
|
|
15830
|
+
reduced[(y * w + x) * 4 + c] = Math.floor(sum / count);
|
|
15831
|
+
}
|
|
15832
|
+
}
|
|
15833
|
+
const filtered = gdipBlur(reduced, w, h, radius / factor, 0, false, true, Math.floor(width / factor), Math.floor(height / factor));
|
|
15834
|
+
for (let i = 0; i < filtered.length; i++) filtered[i] = Math.round(filtered[i]);
|
|
15835
|
+
const out = new Float64Array(src.length);
|
|
15836
|
+
for (let y = 0; y < height; y++) for (let x = 0; x < width; x++) {
|
|
15837
|
+
const px = clamp((x + 0.5) / factor - 0.5, 0, w - 1), py = clamp((y + 0.5) / factor - 0.5, 0, h - 1);
|
|
15838
|
+
const ix = Math.floor(px), iy = Math.floor(py), fx = px - ix, fy = py - iy;
|
|
15839
|
+
const a = (iy * w + ix) * 4, b = (iy * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15840
|
+
const d = (Math.min(h - 1, iy + 1) * w + ix) * 4, e = (Math.min(h - 1, iy + 1) * w + Math.min(w - 1, ix + 1)) * 4;
|
|
15841
|
+
for (let c = 0; c < 4; c++) out[(y * width + x) * 4 + c] = Math.round((1 - fy) * ((1 - fx) * filtered[a + c] + fx * filtered[b + c]) + fy * ((1 - fx) * filtered[d + c] + fx * filtered[e + c]));
|
|
15842
|
+
}
|
|
15843
|
+
return out;
|
|
15844
|
+
}
|
|
15813
15845
|
function applyBlur(src, w, h, radius) {
|
|
15814
|
-
return Uint8ClampedArray.from(
|
|
15846
|
+
return Uint8ClampedArray.from(effectBlur(src, w, h, radius), Math.round);
|
|
15815
15847
|
}
|
|
15816
15848
|
function sharpenGain(_radius, amount) {
|
|
15817
15849
|
return roundHalfDown(64 * amount / (250 - 2 * amount)) / 64;
|
|
15818
15850
|
}
|
|
15819
15851
|
function applySharpen(src, w, h, radius, amount) {
|
|
15820
|
-
const blurred =
|
|
15852
|
+
const blurred = effectBlur(src, w, h, radius);
|
|
15821
15853
|
const gain = sharpenGain(radius, amount);
|
|
15822
15854
|
const out = new Uint8ClampedArray(src);
|
|
15823
15855
|
for (let i = 0; i < src.length; i += 4) {
|
|
@@ -28072,7 +28104,8 @@ var Outliner = class {
|
|
|
28072
28104
|
this.pen = penPolygon(opts.width);
|
|
28073
28105
|
this.n = this.pen.length;
|
|
28074
28106
|
this.rr = opts.cap === "round" && opts.join === "round";
|
|
28075
|
-
this.
|
|
28107
|
+
this.originalRoundJoinSides = opts.join === "round" && opts.cap !== "flat";
|
|
28108
|
+
this.roundJoinSides = !!opts.roundCurveJoins || this.originalRoundJoinSides;
|
|
28076
28109
|
this.maxX = Math.max(...this.pen.map((q) => Math.abs(q[0])));
|
|
28077
28110
|
}
|
|
28078
28111
|
/**
|
|
@@ -28085,7 +28118,8 @@ var Outliner = class {
|
|
|
28085
28118
|
const dy = dir ? dir[1] : b[1] - a[1];
|
|
28086
28119
|
const d = drawDir ?? [dx, dy];
|
|
28087
28120
|
const [L, R] = drawVertices(this.pen, d[0], d[1]);
|
|
28088
|
-
|
|
28121
|
+
const perpendicular = this.opts.roundCurveJoins && drawDir ? drawDir : [dx, dy];
|
|
28122
|
+
return { dx, dy, L, R, v: flatVector(this.opts.width, perpendicular[0], perpendicular[1]), e: squareExtension(this.opts.width, dx, dy), curveEnd: !!drawDir };
|
|
28089
28123
|
}
|
|
28090
28124
|
push(p, v) {
|
|
28091
28125
|
this.pts.push([p[0] + v[0], p[1] + v[1]]);
|
|
@@ -28204,12 +28238,17 @@ var Outliner = class {
|
|
|
28204
28238
|
* segment).
|
|
28205
28239
|
*/
|
|
28206
28240
|
join(p, a, b, side, outer) {
|
|
28207
|
-
const {
|
|
28208
|
-
const
|
|
28209
|
-
|
|
28241
|
+
const { cap, width, miterLimit } = this.opts;
|
|
28242
|
+
const join = this.opts.roundCurveJoins ? "round" : this.opts.join;
|
|
28243
|
+
let sa = this.joinSide(a, side);
|
|
28244
|
+
let sb = this.joinSide(b, side);
|
|
28245
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides && a.curveEnd && b.curveEnd) {
|
|
28246
|
+
sa = side === "R" ? a.v : [-a.v[0], -a.v[1]];
|
|
28247
|
+
sb = side === "R" ? b.v : [-b.v[0], -b.v[1]];
|
|
28248
|
+
}
|
|
28210
28249
|
const Da = side === "R" ? a.R : a.L;
|
|
28211
28250
|
const Db = side === "R" ? b.R : b.L;
|
|
28212
|
-
if (this.roundJoinSides && Da === Db) {
|
|
28251
|
+
if (this.roundJoinSides && (Da === Db || this.opts.roundCurveJoins && sa[0] === sb[0] && sa[1] === sb[1])) {
|
|
28213
28252
|
this.push(p, sa);
|
|
28214
28253
|
return;
|
|
28215
28254
|
}
|
|
@@ -28233,7 +28272,12 @@ var Outliner = class {
|
|
|
28233
28272
|
}
|
|
28234
28273
|
} else {
|
|
28235
28274
|
this.pts.push([p[0], p[1]]);
|
|
28236
|
-
if (
|
|
28275
|
+
if (this.opts.roundCurveJoins && !this.originalRoundJoinSides) {
|
|
28276
|
+
this.push(p, sb);
|
|
28277
|
+
this.push(p, sa);
|
|
28278
|
+
this.pts.push([p[0], p[1]]);
|
|
28279
|
+
}
|
|
28280
|
+
if (join === "round" && cap === "flat" && !this.opts.roundCurveJoins) {
|
|
28237
28281
|
this.push(p, sb);
|
|
28238
28282
|
this.wedge(p, sb, sa, false, false);
|
|
28239
28283
|
this.push(p, sa);
|
|
@@ -28403,9 +28447,9 @@ function dashPieces(P, tangents, pattern, shorten) {
|
|
|
28403
28447
|
}
|
|
28404
28448
|
function widenPath(path, opts) {
|
|
28405
28449
|
const out = [];
|
|
28406
|
-
const outliner = new Outliner(opts, out);
|
|
28407
28450
|
const dashed = !!opts.dashes && opts.dashes.length > 0;
|
|
28408
28451
|
for (const fig of path.figures) {
|
|
28452
|
+
const outliner = new Outliner(fig.roundWiden ? { ...opts, roundCurveJoins: true } : opts, out);
|
|
28409
28453
|
let P = [];
|
|
28410
28454
|
const dirs = [];
|
|
28411
28455
|
for (let i = 0; i + 1 < fig.pts.length; i += 2) {
|
|
@@ -28517,6 +28561,7 @@ function ellipseRasterPath(box, clockwise = false) {
|
|
|
28517
28561
|
const path = new GdiRasterPath();
|
|
28518
28562
|
path.addBeziers(ellipseBeziersBox(box, clockwise), true);
|
|
28519
28563
|
path.closeFigure();
|
|
28564
|
+
path.figures[0].roundWiden = true;
|
|
28520
28565
|
return path;
|
|
28521
28566
|
}
|
|
28522
28567
|
function frameMapper(box, l, t, w, h) {
|
|
@@ -28636,7 +28681,7 @@ function penWidenOptions(rCtx, opts = {}) {
|
|
|
28636
28681
|
const { state } = rCtx;
|
|
28637
28682
|
const flags = state.penFlags ?? state.penStyle;
|
|
28638
28683
|
const matrix = gdiDeviceMatrix(rCtx);
|
|
28639
|
-
const widthPx =
|
|
28684
|
+
const widthPx = rCtx.wholeDevicePixels && (flags & 15) === 6 ? state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) : penDeviceWidth(rCtx);
|
|
28640
28685
|
const capBits = flags & 3840;
|
|
28641
28686
|
const joinBits = flags & 61440;
|
|
28642
28687
|
const dashes = state.penExtended ? geometricStyle(flags, widthPx, state.penUserStyle, widthPx / (state.penWidth || 1)) : null;
|
|
@@ -33506,6 +33551,7 @@ function flattenBracketPath(rCtx) {
|
|
|
33506
33551
|
}
|
|
33507
33552
|
for (const f of rCtx.rasterPath.figures) {
|
|
33508
33553
|
delete f.tangents;
|
|
33554
|
+
delete f.roundWiden;
|
|
33509
33555
|
}
|
|
33510
33556
|
syncPathCmds(rCtx);
|
|
33511
33557
|
}
|
|
@@ -37533,19 +37579,12 @@ function compatBox(p, l, t, r, b, opts = {}) {
|
|
|
37533
37579
|
if (w > 1) {
|
|
37534
37580
|
const matrix = gdiDeviceMatrix(p.rCtx);
|
|
37535
37581
|
const rawWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(matrix[0] * matrix[3] - matrix[1] * matrix[2])) / p.kx;
|
|
37536
|
-
|
|
37537
|
-
|
|
37538
|
-
|
|
37539
|
-
|
|
37540
|
-
|
|
37541
|
-
|
|
37542
|
-
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37543
|
-
return box;
|
|
37544
|
-
}
|
|
37545
|
-
box.x0 += Math.round(Math.floor(w / 2) * ux);
|
|
37546
|
-
box.y0 += Math.round(Math.floor(w / 2) * uy);
|
|
37547
|
-
box.x1 -= Math.round(Math.floor((w - 1) / 2) * ux);
|
|
37548
|
-
box.y1 -= Math.round(Math.floor((w - 1) / 2) * uy);
|
|
37582
|
+
box.x1 += Math.round(ux);
|
|
37583
|
+
box.y1 += Math.round(uy);
|
|
37584
|
+
box.x0 += Math.round(rawWidth * ux / 2);
|
|
37585
|
+
box.y0 += Math.round(rawWidth * uy / 2);
|
|
37586
|
+
box.x1 -= Math.round(rawWidth * ux / 2);
|
|
37587
|
+
box.y1 -= Math.round(rawWidth * uy / 2);
|
|
37549
37588
|
}
|
|
37550
37589
|
}
|
|
37551
37590
|
return box;
|
|
@@ -37609,6 +37648,11 @@ function compatCorner(p, w, h, box) {
|
|
|
37609
37648
|
const ch = Math.round(Math.abs(h * m[3]) * 16);
|
|
37610
37649
|
const ux = 16 * p.kx;
|
|
37611
37650
|
const uy = 16 * p.ky;
|
|
37651
|
+
if ((p.rCtx.state.penStyle & 15) === PS_INSIDEFRAME && !penIsCosmetic(p.rCtx)) {
|
|
37652
|
+
const penWidth = p.rCtx.state.penWidth * Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2])) * 16;
|
|
37653
|
+
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37654
|
+
return [Math.min(cw, width + penWidth) * width / (width + penWidth), Math.min(ch, height + penWidth) * height / (height + penWidth)];
|
|
37655
|
+
}
|
|
37612
37656
|
if (!penIsNull(p) && penIsCosmetic(p.rCtx)) {
|
|
37613
37657
|
const width = box.x1 - box.x0, height = box.y1 - box.y0;
|
|
37614
37658
|
return [Math.min(cw, width + ux) * width / (width + ux), Math.min(ch, height + uy) * height / (height + uy)];
|