@pixerate/editor 0.99.0 → 0.101.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/THIRD_PARTY_NOTICES.md +4 -0
- package/dist/animation-editor/index.cjs +39 -39
- package/dist/animation-editor/index.d.cts +1 -1
- package/dist/animation-editor/index.d.ts +1 -1
- package/dist/animation-editor/index.js +1 -1
- package/dist/{chunk-YGZNGDIT.js → chunk-63EFQCT5.js} +807 -73
- package/dist/chunk-63EFQCT5.js.map +1 -0
- package/dist/{chunk-JF5PXN7W.cjs → chunk-KANRAHTL.cjs} +838 -104
- package/dist/chunk-KANRAHTL.cjs.map +1 -0
- package/dist/image-editor/index.cjs +321 -165
- package/dist/image-editor/index.cjs.map +1 -1
- package/dist/image-editor/index.d.cts +70 -11
- package/dist/image-editor/index.d.ts +70 -11
- package/dist/image-editor/index.js +165 -9
- package/dist/image-editor/index.js.map +1 -1
- package/dist/{svg-C9r284x8.d.cts → svg-Bj1MQFh6.d.cts} +395 -2
- package/dist/{svg-MVKBqwD4.d.ts → svg-vme0PLNo.d.ts} +395 -2
- package/dist/vector/index.cjs +1352 -584
- package/dist/vector/index.cjs.map +1 -1
- package/dist/vector/index.d.cts +302 -197
- package/dist/vector/index.d.ts +302 -197
- package/dist/vector/index.js +854 -86
- package/dist/vector/index.js.map +1 -1
- package/package.json +1 -1
- package/skills/pixerate-vector/SKILL.md +52 -2
- package/skills/pixerate-vector/references/commands.md +21 -0
- package/dist/chunk-JF5PXN7W.cjs.map +0 -1
- package/dist/chunk-YGZNGDIT.js.map +0 -1
|
@@ -75,6 +75,25 @@ var VECTOR_GRADIENT_SPREADS = ["pad", "reflect", "repeat"];
|
|
|
75
75
|
var VECTOR_GRADIENT_INTERPOLATIONS = ["srgb", "linear", "oklab"];
|
|
76
76
|
var VECTOR_STROKE_GRADIENT_MODES = ["within", "along", "across"];
|
|
77
77
|
var VECTOR_ARROWHEADS = ["triangle", "arrow", "open", "circle", "square", "bar"];
|
|
78
|
+
var VECTOR_BLEND_MODES = [
|
|
79
|
+
"normal",
|
|
80
|
+
"darken",
|
|
81
|
+
"multiply",
|
|
82
|
+
"color-burn",
|
|
83
|
+
"lighten",
|
|
84
|
+
"screen",
|
|
85
|
+
"color-dodge",
|
|
86
|
+
"linear-dodge",
|
|
87
|
+
"overlay",
|
|
88
|
+
"soft-light",
|
|
89
|
+
"hard-light",
|
|
90
|
+
"difference",
|
|
91
|
+
"exclusion",
|
|
92
|
+
"hue",
|
|
93
|
+
"saturation",
|
|
94
|
+
"color",
|
|
95
|
+
"luminosity"
|
|
96
|
+
];
|
|
78
97
|
var VECTOR_BLEND_SPACINGS = ["steps", "distance", "smoothColor"];
|
|
79
98
|
var VECTOR_TOOLS = [
|
|
80
99
|
"select",
|
|
@@ -100,6 +119,7 @@ var VECTOR_TRANSFORM_HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w", "rot
|
|
|
100
119
|
var VECTOR_PATHFINDER_OPERATIONS = ["divide", "trim", "merge", "crop", "outline", "minusBack"];
|
|
101
120
|
var VECTOR_EFFECT_TYPES = ["trim", "roundCorners", "puckerBloat", "twist", "zigzag", "wiggle", "offset", "merge", "repeater", "envelope"];
|
|
102
121
|
var VECTOR_MERGE_MODES = ["merge", "add", "subtract", "intersect", "exclude"];
|
|
122
|
+
var VECTOR_FILTER_TYPES = ["dropShadow", "innerShadow", "outerGlow", "innerGlow", "layerBlur", "feather"];
|
|
103
123
|
|
|
104
124
|
// src/vector/gradient.ts
|
|
105
125
|
var clamp = (v2, lo, hi) => Math.min(hi, Math.max(lo, v2));
|
|
@@ -1255,8 +1275,8 @@ function removeWidthPoints(points, indices) {
|
|
|
1255
1275
|
}
|
|
1256
1276
|
function ease(u, e) {
|
|
1257
1277
|
const x = Math.min(Math.max(u, 0), 1);
|
|
1258
|
-
const
|
|
1259
|
-
return x + (
|
|
1278
|
+
const round3 = Math.sqrt(Math.max(0, 1 - (1 - x) * (1 - x)));
|
|
1279
|
+
return x + (round3 - x) * Math.min(Math.max(e, 0), 1);
|
|
1260
1280
|
}
|
|
1261
1281
|
function taperWaveFactor(t, taper, wave) {
|
|
1262
1282
|
let k = 1;
|
|
@@ -1880,6 +1900,278 @@ function vectorStrokeReach(style) {
|
|
|
1880
1900
|
return reach;
|
|
1881
1901
|
}
|
|
1882
1902
|
|
|
1903
|
+
// src/vector/paintLayers.ts
|
|
1904
|
+
var VECTOR_STROKE_SETTING_KEYS = [
|
|
1905
|
+
"strokeWidth",
|
|
1906
|
+
"strokeLinecap",
|
|
1907
|
+
"strokeLinejoin",
|
|
1908
|
+
"strokeDasharray",
|
|
1909
|
+
"strokeAlign",
|
|
1910
|
+
"startArrow",
|
|
1911
|
+
"endArrow",
|
|
1912
|
+
"arrowAlign",
|
|
1913
|
+
"startArrowScale",
|
|
1914
|
+
"endArrowScale",
|
|
1915
|
+
"strokeWidthProfile"
|
|
1916
|
+
];
|
|
1917
|
+
var VECTOR_BLEND_MODE_LABELS = {
|
|
1918
|
+
normal: "Normal",
|
|
1919
|
+
darken: "Darken",
|
|
1920
|
+
multiply: "Multiply",
|
|
1921
|
+
"color-burn": "Color Burn",
|
|
1922
|
+
lighten: "Lighten",
|
|
1923
|
+
screen: "Screen",
|
|
1924
|
+
"color-dodge": "Color Dodge",
|
|
1925
|
+
"linear-dodge": "Linear Dodge (Add)",
|
|
1926
|
+
overlay: "Overlay",
|
|
1927
|
+
"soft-light": "Soft Light",
|
|
1928
|
+
"hard-light": "Hard Light",
|
|
1929
|
+
difference: "Difference",
|
|
1930
|
+
exclusion: "Exclusion",
|
|
1931
|
+
hue: "Hue",
|
|
1932
|
+
saturation: "Saturation",
|
|
1933
|
+
color: "Color",
|
|
1934
|
+
luminosity: "Luminosity"
|
|
1935
|
+
};
|
|
1936
|
+
function isVectorBlendMode(value) {
|
|
1937
|
+
return typeof value === "string" && VECTOR_BLEND_MODES.includes(value);
|
|
1938
|
+
}
|
|
1939
|
+
function vectorBlendModeCss(mode) {
|
|
1940
|
+
if (!mode || mode === "normal" || !isVectorBlendMode(mode)) return void 0;
|
|
1941
|
+
return mode === "linear-dodge" ? "plus-lighter" : mode;
|
|
1942
|
+
}
|
|
1943
|
+
function vectorBlendModeFromCss(value) {
|
|
1944
|
+
const v2 = (value ?? "").trim().toLowerCase();
|
|
1945
|
+
if (v2 === "plus-lighter") return "linear-dodge";
|
|
1946
|
+
return isVectorBlendMode(v2) ? v2 : null;
|
|
1947
|
+
}
|
|
1948
|
+
var draws = (paint) => {
|
|
1949
|
+
if (paint === void 0 || paint === null) return false;
|
|
1950
|
+
if (typeof paint === "string") {
|
|
1951
|
+
const p = paint.trim().toLowerCase();
|
|
1952
|
+
return p !== "" && p !== "none" && p !== "transparent";
|
|
1953
|
+
}
|
|
1954
|
+
return true;
|
|
1955
|
+
};
|
|
1956
|
+
function isPlainVectorPaintLayer(layer) {
|
|
1957
|
+
return (layer.opacity ?? 1) >= 1 && (layer.blendMode ?? "normal") === "normal" && layer.visible !== false && (layer.kind ?? "paint") === "paint";
|
|
1958
|
+
}
|
|
1959
|
+
function isDrawnVectorPaintLayer(layer) {
|
|
1960
|
+
return layer.visible !== false && (layer.kind ?? "paint") === "paint" && draws(layer.paint) && (layer.opacity ?? 1) > 0;
|
|
1961
|
+
}
|
|
1962
|
+
function vectorFills(style) {
|
|
1963
|
+
if (Array.isArray(style.fills)) return style.fills;
|
|
1964
|
+
return draws(style.fill) ? [{ paint: style.fill }] : [];
|
|
1965
|
+
}
|
|
1966
|
+
function vectorStrokeSettings(style) {
|
|
1967
|
+
const out = {};
|
|
1968
|
+
for (const key of VECTOR_STROKE_SETTING_KEYS) {
|
|
1969
|
+
const v2 = style[key];
|
|
1970
|
+
if (v2 !== void 0 && v2 !== null) out[key] = v2;
|
|
1971
|
+
}
|
|
1972
|
+
return out;
|
|
1973
|
+
}
|
|
1974
|
+
function vectorStrokes(style) {
|
|
1975
|
+
if (Array.isArray(style.strokes)) return style.strokes;
|
|
1976
|
+
return draws(style.stroke) ? [{ paint: style.stroke, ...vectorStrokeSettings(style) }] : [];
|
|
1977
|
+
}
|
|
1978
|
+
function hasVectorPaintStacks(style) {
|
|
1979
|
+
return Array.isArray(style.fills) || Array.isArray(style.strokes);
|
|
1980
|
+
}
|
|
1981
|
+
function withVectorFills(node, fills) {
|
|
1982
|
+
const next = { ...node };
|
|
1983
|
+
if (fills.length === 0 || fills.length === 1 && isPlainVectorPaintLayer(fills[0])) {
|
|
1984
|
+
delete next.fills;
|
|
1985
|
+
next.fill = fills[0]?.paint ?? null;
|
|
1986
|
+
return next;
|
|
1987
|
+
}
|
|
1988
|
+
next.fills = fills.map((l) => ({ ...l }));
|
|
1989
|
+
next.fill = fills[fills.length - 1].paint;
|
|
1990
|
+
return next;
|
|
1991
|
+
}
|
|
1992
|
+
function withVectorStrokes(node, strokes) {
|
|
1993
|
+
const next = { ...node };
|
|
1994
|
+
if (strokes.length === 0) {
|
|
1995
|
+
delete next.strokes;
|
|
1996
|
+
next.stroke = null;
|
|
1997
|
+
return next;
|
|
1998
|
+
}
|
|
1999
|
+
const top = strokes[strokes.length - 1];
|
|
2000
|
+
for (const key of VECTOR_STROKE_SETTING_KEYS) delete next[key];
|
|
2001
|
+
Object.assign(next, vectorStrokeSettings(top));
|
|
2002
|
+
next.stroke = top.paint;
|
|
2003
|
+
if (strokes.length === 1 && isPlainVectorPaintLayer(top)) delete next.strokes;
|
|
2004
|
+
else next.strokes = strokes.map((l) => ({ ...l }));
|
|
2005
|
+
return next;
|
|
2006
|
+
}
|
|
2007
|
+
var json = (v2) => JSON.stringify(v2 ?? null);
|
|
2008
|
+
function strokeShorthandDiff(node, top) {
|
|
2009
|
+
const out = [];
|
|
2010
|
+
if (json(node.stroke) !== json(top?.paint)) out.push("stroke");
|
|
2011
|
+
for (const key of VECTOR_STROKE_SETTING_KEYS) if (json(node[key]) !== json(top?.[key])) out.push(key);
|
|
2012
|
+
return out;
|
|
2013
|
+
}
|
|
2014
|
+
var checked = /* @__PURE__ */ new WeakSet();
|
|
2015
|
+
function normalizeVectorPaintStacks(node, prefer = "shorthand") {
|
|
2016
|
+
if (!hasVectorPaintStacks(node)) {
|
|
2017
|
+
if (!("fills" in node) && !("strokes" in node)) return node;
|
|
2018
|
+
const next2 = { ...node };
|
|
2019
|
+
delete next2.fills;
|
|
2020
|
+
delete next2.strokes;
|
|
2021
|
+
return next2;
|
|
2022
|
+
}
|
|
2023
|
+
if (checked.has(node)) return node;
|
|
2024
|
+
let next = node;
|
|
2025
|
+
if (Array.isArray(node.fills)) {
|
|
2026
|
+
let fills = node.fills;
|
|
2027
|
+
const top = fills[fills.length - 1];
|
|
2028
|
+
if (prefer === "shorthand" && json(node.fill) !== json(top?.paint)) {
|
|
2029
|
+
if (!draws(node.fill)) fills = [];
|
|
2030
|
+
else fills = top ? [...fills.slice(0, -1), { ...top, paint: node.fill }] : [{ paint: node.fill }];
|
|
2031
|
+
}
|
|
2032
|
+
next = withVectorFills(next, fills);
|
|
2033
|
+
}
|
|
2034
|
+
if (Array.isArray(node.strokes)) {
|
|
2035
|
+
let strokes = node.strokes;
|
|
2036
|
+
const top = strokes[strokes.length - 1];
|
|
2037
|
+
const diff = prefer === "shorthand" ? strokeShorthandDiff(node, top) : [];
|
|
2038
|
+
if (diff.length) {
|
|
2039
|
+
if (diff.includes("stroke") && !draws(node.stroke)) strokes = [];
|
|
2040
|
+
else {
|
|
2041
|
+
const layer = top ? { ...top } : { paint: node.stroke ?? null };
|
|
2042
|
+
for (const key of diff) {
|
|
2043
|
+
if (key === "stroke") layer.paint = node.stroke ?? null;
|
|
2044
|
+
else if (node[key] === void 0 || node[key] === null) delete layer[key];
|
|
2045
|
+
else layer[key] = node[key];
|
|
2046
|
+
}
|
|
2047
|
+
strokes = top ? [...strokes.slice(0, -1), layer] : [layer];
|
|
2048
|
+
}
|
|
2049
|
+
}
|
|
2050
|
+
next = withVectorStrokes(next, strokes);
|
|
2051
|
+
}
|
|
2052
|
+
const keys = ["fill", "fills", "stroke", "strokes", ...VECTOR_STROKE_SETTING_KEYS];
|
|
2053
|
+
const same2 = keys.every((k) => k in next === k in node && json(next[k]) === json(node[k]));
|
|
2054
|
+
const out = same2 ? node : next;
|
|
2055
|
+
checked.add(out);
|
|
2056
|
+
return out;
|
|
2057
|
+
}
|
|
2058
|
+
function sanitizePaint(value) {
|
|
2059
|
+
if (value === null || value === void 0) return null;
|
|
2060
|
+
if (typeof value === "string") return value;
|
|
2061
|
+
return sanitizeVectorGradient(value);
|
|
2062
|
+
}
|
|
2063
|
+
function sanitizeLayerBase(raw) {
|
|
2064
|
+
const out = { paint: sanitizePaint(raw.paint) };
|
|
2065
|
+
if (typeof raw.opacity === "number" && Number.isFinite(raw.opacity) && raw.opacity < 1) out.opacity = Math.max(0, raw.opacity);
|
|
2066
|
+
if (isVectorBlendMode(raw.blendMode) && raw.blendMode !== "normal") out.blendMode = raw.blendMode;
|
|
2067
|
+
if (raw.visible === false) out.visible = false;
|
|
2068
|
+
return out;
|
|
2069
|
+
}
|
|
2070
|
+
function sanitizeVectorFills(value) {
|
|
2071
|
+
if (!Array.isArray(value)) return [];
|
|
2072
|
+
return value.filter((l) => !!l && typeof l === "object").map(sanitizeLayerBase);
|
|
2073
|
+
}
|
|
2074
|
+
var ARROW_ALIGNS = ["extend", "tip"];
|
|
2075
|
+
function sanitizeVectorStrokeSettings(raw) {
|
|
2076
|
+
const out = {};
|
|
2077
|
+
const num2 = (v2) => typeof v2 === "number" && Number.isFinite(v2) ? v2 : void 0;
|
|
2078
|
+
const width = num2(raw.strokeWidth);
|
|
2079
|
+
if (width !== void 0 && width >= 0) out.strokeWidth = width;
|
|
2080
|
+
if (raw.strokeLinecap === "butt" || raw.strokeLinecap === "round" || raw.strokeLinecap === "square") out.strokeLinecap = raw.strokeLinecap;
|
|
2081
|
+
if (raw.strokeLinejoin === "miter" || raw.strokeLinejoin === "round" || raw.strokeLinejoin === "bevel") out.strokeLinejoin = raw.strokeLinejoin;
|
|
2082
|
+
if (Array.isArray(raw.strokeDasharray)) {
|
|
2083
|
+
const dash = raw.strokeDasharray.filter((n) => typeof n === "number" && Number.isFinite(n) && n >= 0);
|
|
2084
|
+
if (dash.length && dash.some((n) => n > 0)) out.strokeDasharray = dash;
|
|
2085
|
+
}
|
|
2086
|
+
if (raw.strokeAlign === "center" || raw.strokeAlign === "inside" || raw.strokeAlign === "outside") out.strokeAlign = raw.strokeAlign;
|
|
2087
|
+
for (const key of ["startArrow", "endArrow"]) if (VECTOR_ARROWHEADS.includes(raw[key])) out[key] = raw[key];
|
|
2088
|
+
if (ARROW_ALIGNS.includes(raw.arrowAlign)) out.arrowAlign = raw.arrowAlign;
|
|
2089
|
+
for (const key of ["startArrowScale", "endArrowScale"]) {
|
|
2090
|
+
const n = num2(raw[key]);
|
|
2091
|
+
if (n !== void 0 && n > 0) out[key] = n;
|
|
2092
|
+
}
|
|
2093
|
+
if (Array.isArray(raw.strokeWidthProfile)) {
|
|
2094
|
+
const p = sanitizeWidthProfile(raw.strokeWidthProfile);
|
|
2095
|
+
if (p.length) out.strokeWidthProfile = p;
|
|
2096
|
+
}
|
|
2097
|
+
return out;
|
|
2098
|
+
}
|
|
2099
|
+
function sanitizeVectorStrokes(value) {
|
|
2100
|
+
if (!Array.isArray(value)) return [];
|
|
2101
|
+
return value.filter((l) => !!l && typeof l === "object").map((raw) => {
|
|
2102
|
+
if (raw.kind !== void 0 && raw.kind !== "paint") return { ...raw };
|
|
2103
|
+
return { ...sanitizeLayerBase(raw), ...sanitizeVectorStrokeSettings(raw) };
|
|
2104
|
+
});
|
|
2105
|
+
}
|
|
2106
|
+
var layerNodeCache = /* @__PURE__ */ new WeakMap();
|
|
2107
|
+
function vectorPaintLayerNodes(node) {
|
|
2108
|
+
const hit = layerNodeCache.get(node);
|
|
2109
|
+
if (hit) return hit;
|
|
2110
|
+
const { fills: _f, strokes: _s, ...base } = node;
|
|
2111
|
+
const plain2 = { ...base };
|
|
2112
|
+
for (const key of VECTOR_STROKE_SETTING_KEYS) delete plain2[key];
|
|
2113
|
+
const out = [];
|
|
2114
|
+
vectorFills(node).forEach((layer, index) => {
|
|
2115
|
+
out.push({ kind: "fill", index, layer, node: { ...plain2, fill: layer.paint, stroke: null }, drawn: isDrawnVectorPaintLayer(layer) });
|
|
2116
|
+
});
|
|
2117
|
+
vectorStrokes(node).forEach((layer, index) => {
|
|
2118
|
+
const settings = (layer.kind ?? "paint") === "paint" ? vectorStrokeSettings(layer) : {};
|
|
2119
|
+
out.push({ kind: "stroke", index, layer, node: { ...plain2, fill: null, ...settings, stroke: layer.paint }, drawn: isDrawnVectorPaintLayer(layer) });
|
|
2120
|
+
});
|
|
2121
|
+
layerNodeCache.set(node, out);
|
|
2122
|
+
return out;
|
|
2123
|
+
}
|
|
2124
|
+
function needsVectorPaintLayers(node) {
|
|
2125
|
+
if (!hasVectorPaintStacks(node)) return false;
|
|
2126
|
+
const fills = vectorFills(node);
|
|
2127
|
+
const strokes = vectorStrokes(node);
|
|
2128
|
+
return fills.length > 1 || strokes.length > 1 || fills.some((l) => !isPlainVectorPaintLayer(l)) || strokes.some((l) => !isPlainVectorPaintLayer(l));
|
|
2129
|
+
}
|
|
2130
|
+
function vectorStrokeStackReach(node) {
|
|
2131
|
+
let reach = 0;
|
|
2132
|
+
for (const l of vectorPaintLayerNodes(node)) if (l.kind === "stroke" && l.drawn) reach = Math.max(reach, vectorStrokeReach(l.node));
|
|
2133
|
+
return reach;
|
|
2134
|
+
}
|
|
2135
|
+
function hitTestVectorPaintLayer(node, path, p, tolerance = 0) {
|
|
2136
|
+
if (!path.length) return null;
|
|
2137
|
+
const layers = vectorPaintLayerNodes(node);
|
|
2138
|
+
for (let i = layers.length - 1; i >= 0; i--) {
|
|
2139
|
+
const l = layers[i];
|
|
2140
|
+
if (!l.drawn) continue;
|
|
2141
|
+
if (l.kind === "stroke") {
|
|
2142
|
+
if ((l.node.strokeWidth ?? 1) > 0 && hitTestVectorStroke(path, p, l.node, tolerance)) return { kind: "stroke", index: l.index };
|
|
2143
|
+
} else if (pointInBezierPath(path, [p.x, p.y], node.fillRule ?? "nonzero")) return { kind: "fill", index: l.index };
|
|
2144
|
+
}
|
|
2145
|
+
return null;
|
|
2146
|
+
}
|
|
2147
|
+
function hitTestVectorPaintStack(node, path, p, tolerance = 0) {
|
|
2148
|
+
if (hitTestVectorPaintLayer(node, path, p, tolerance)) return true;
|
|
2149
|
+
if (vectorPaintLayerNodes(node).some((l) => l.kind === "stroke" && l.drawn)) return false;
|
|
2150
|
+
return distanceToBezierPath(path, [p.x, p.y]) <= tolerance;
|
|
2151
|
+
}
|
|
2152
|
+
function vectorStacksHaveGradient(style) {
|
|
2153
|
+
return [...style.fills ?? [], ...style.strokes ?? []].some((l) => isVectorGradient(l.paint));
|
|
2154
|
+
}
|
|
2155
|
+
function newVectorStrokeLayer(node, patch = {}) {
|
|
2156
|
+
const top = vectorStrokes(node).at(-1);
|
|
2157
|
+
const settings = top && (top.kind ?? "paint") === "paint" ? vectorStrokeSettings(top) : { strokeWidth: node.strokeWidth ?? 1 };
|
|
2158
|
+
return { paint: "#000000", ...settings, ...patch };
|
|
2159
|
+
}
|
|
2160
|
+
function vectorTargetPaint(style, target, layer = null) {
|
|
2161
|
+
if (layer === null) return style[target];
|
|
2162
|
+
const stack = target === "fill" ? vectorFills(style) : vectorStrokes(style);
|
|
2163
|
+
return stack[layer] ? stack[layer].paint : style[target];
|
|
2164
|
+
}
|
|
2165
|
+
function withVectorTargetPaint(node, target, layer, paint) {
|
|
2166
|
+
const stack = target === "fill" ? vectorFills(node) : vectorStrokes(node);
|
|
2167
|
+
if (layer === null || !stack[layer]) {
|
|
2168
|
+
if (!stack.length) return { ...node, [target]: paint };
|
|
2169
|
+
layer = stack.length - 1;
|
|
2170
|
+
}
|
|
2171
|
+
const next = stack.map((l, i) => i === layer ? { ...l, paint } : l);
|
|
2172
|
+
return target === "fill" ? withVectorFills(node, next) : withVectorStrokes(node, next);
|
|
2173
|
+
}
|
|
2174
|
+
|
|
1883
2175
|
// src/vector/pathMap.ts
|
|
1884
2176
|
var MAX_PIECES = 1 << 20;
|
|
1885
2177
|
var MAX_DEPTH = 6;
|
|
@@ -2616,6 +2908,9 @@ function shapeNode(shape, id) {
|
|
|
2616
2908
|
locked: _l,
|
|
2617
2909
|
visible: _v,
|
|
2618
2910
|
opacity: _o,
|
|
2911
|
+
// The node's own blend mode and filters stay on the node, not on each shape it draws.
|
|
2912
|
+
blendMode: _bm,
|
|
2913
|
+
filters: _fl,
|
|
2619
2914
|
...style
|
|
2620
2915
|
} = shape.source;
|
|
2621
2916
|
return { ...style, id, type: "path", subpaths: bezierToSubpaths(shape.path), ...shape.opacity < 1 ? { opacity: shape.opacity } : {} };
|
|
@@ -2627,7 +2922,9 @@ function placement(node) {
|
|
|
2627
2922
|
...node.visible === false ? { visible: false } : {},
|
|
2628
2923
|
...node.locked ? { locked: true } : {},
|
|
2629
2924
|
...node.blendStep ? { blendStep: true } : {},
|
|
2630
|
-
...node.booleanOperation ? { booleanOperation: node.booleanOperation } : {}
|
|
2925
|
+
...node.booleanOperation ? { booleanOperation: node.booleanOperation } : {},
|
|
2926
|
+
...node.blendMode ? { blendMode: node.blendMode } : {},
|
|
2927
|
+
...node.filters?.length ? { filters: node.filters } : {}
|
|
2631
2928
|
};
|
|
2632
2929
|
}
|
|
2633
2930
|
function vectorAppearanceNodes(node) {
|
|
@@ -2942,10 +3239,7 @@ function hitTestVectorNode(node, p, tolerance = 0, parent = IDENTITY_MATRIX, opt
|
|
|
2942
3239
|
}
|
|
2943
3240
|
const path = vectorPathWorldBezier(node, parent);
|
|
2944
3241
|
if (path.length === 0) return false;
|
|
2945
|
-
|
|
2946
|
-
if (hasPaint(node.fill) && pointInBezierPath(path, point, node.fillRule ?? "nonzero")) return true;
|
|
2947
|
-
if (hasPaint(node.stroke)) return hitTestVectorStroke(path, p, node, tolerance);
|
|
2948
|
-
return distanceToBezierPath(path, point) <= tolerance;
|
|
3242
|
+
return hitTestVectorPaintStack(node, path, p, tolerance);
|
|
2949
3243
|
}
|
|
2950
3244
|
function vectorStrokeOutline(node, parent = IDENTITY_MATRIX) {
|
|
2951
3245
|
if (!hasPaint(node.stroke) || !((node.strokeWidth ?? 1) > 0)) return [];
|
|
@@ -2995,13 +3289,21 @@ function bakeIntoGeometry(node, m) {
|
|
|
2995
3289
|
return { ...group, children, blend: { ...group.blend, spine: moved } };
|
|
2996
3290
|
}
|
|
2997
3291
|
const path = node;
|
|
2998
|
-
const
|
|
3292
|
+
const flips = m[0] * m[3] - m[1] * m[2] < 0;
|
|
3293
|
+
const mirrored = flips && path.strokeWidthProfile?.length;
|
|
3294
|
+
const layer = (l) => ({
|
|
3295
|
+
...l,
|
|
3296
|
+
...isVectorGradient(l.paint) ? { paint: transformVectorPaint(l.paint, m) } : {},
|
|
3297
|
+
...flips && l.strokeWidthProfile?.length ? { strokeWidthProfile: mirrorWidthProfile(l.strokeWidthProfile) } : {}
|
|
3298
|
+
});
|
|
2999
3299
|
return {
|
|
3000
3300
|
...path,
|
|
3001
3301
|
...mirrored ? { strokeWidthProfile: mirrorWidthProfile(path.strokeWidthProfile) } : {},
|
|
3002
3302
|
// Gradients in the node's own space move with its geometry.
|
|
3003
3303
|
...isVectorGradient(path.fill) ? { fill: transformVectorPaint(path.fill, m) } : {},
|
|
3004
3304
|
...isVectorGradient(path.stroke) ? { stroke: transformVectorPaint(path.stroke, m) } : {},
|
|
3305
|
+
...Array.isArray(path.fills) ? { fills: path.fills.map(layer) } : {},
|
|
3306
|
+
...Array.isArray(path.strokes) ? { strokes: path.strokes.map(layer) } : {},
|
|
3005
3307
|
subpaths: path.subpaths.map((sp) => ({
|
|
3006
3308
|
closed: sp.closed,
|
|
3007
3309
|
anchors: sp.anchors.map((a) => mapAnchor(a, m))
|
|
@@ -4267,6 +4569,201 @@ function evaluateVectorPathKeyframes(keyframes, time, options = {}) {
|
|
|
4267
4569
|
return morph.at(u);
|
|
4268
4570
|
}
|
|
4269
4571
|
|
|
4572
|
+
// src/vector/filters.ts
|
|
4573
|
+
var VECTOR_FILTER_DEFAULTS = {
|
|
4574
|
+
dropShadow: { color: "#000000", opacity: 0.25, offsetX: 0, offsetY: 4, blur: 4, spread: 0 },
|
|
4575
|
+
innerShadow: { color: "#000000", opacity: 0.25, offsetX: 0, offsetY: 4, blur: 4, spread: 0 },
|
|
4576
|
+
outerGlow: { color: "#ffffbe", opacity: 0.75, blur: 10, spread: 0 },
|
|
4577
|
+
innerGlow: { color: "#ffffbe", opacity: 0.75, blur: 10, spread: 0 },
|
|
4578
|
+
layerBlur: { radius: 4 },
|
|
4579
|
+
feather: { radius: 8 }
|
|
4580
|
+
};
|
|
4581
|
+
var VECTOR_FILTER_LABELS = {
|
|
4582
|
+
dropShadow: "Drop Shadow",
|
|
4583
|
+
innerShadow: "Inner Shadow",
|
|
4584
|
+
outerGlow: "Outer Glow",
|
|
4585
|
+
innerGlow: "Inner Glow",
|
|
4586
|
+
layerBlur: "Layer Blur",
|
|
4587
|
+
feather: "Feather"
|
|
4588
|
+
};
|
|
4589
|
+
var SHADOW_SPECS = [
|
|
4590
|
+
{ key: "color", label: "Color", kind: "color" },
|
|
4591
|
+
{ key: "opacity", label: "Opacity", kind: "number", min: 0, max: 1, step: 0.01, slider: true },
|
|
4592
|
+
{ key: "offsetX", label: "X", kind: "number", min: -1e3, max: 1e3, step: 1 },
|
|
4593
|
+
{ key: "offsetY", label: "Y", kind: "number", min: -1e3, max: 1e3, step: 1 },
|
|
4594
|
+
{ key: "blur", label: "Blur", kind: "number", min: 0, max: 500, step: 1 },
|
|
4595
|
+
{ key: "spread", label: "Spread", kind: "number", min: 0, max: 500, step: 1 }
|
|
4596
|
+
];
|
|
4597
|
+
var GLOW_SPECS = SHADOW_SPECS.filter((s) => s.key !== "offsetX" && s.key !== "offsetY");
|
|
4598
|
+
var VECTOR_FILTER_PARAM_SPECS = {
|
|
4599
|
+
dropShadow: SHADOW_SPECS,
|
|
4600
|
+
innerShadow: SHADOW_SPECS.map((s) => s.key === "spread" ? { ...s, label: "Choke" } : s),
|
|
4601
|
+
outerGlow: GLOW_SPECS,
|
|
4602
|
+
innerGlow: GLOW_SPECS.map((s) => s.key === "spread" ? { ...s, label: "Choke" } : s),
|
|
4603
|
+
layerBlur: [{ key: "radius", label: "Radius", kind: "number", min: 0, max: 500, step: 1, slider: true }],
|
|
4604
|
+
feather: [{ key: "radius", label: "Radius", kind: "number", min: 0, max: 500, step: 1, slider: true }]
|
|
4605
|
+
};
|
|
4606
|
+
function isVectorFilterType(value) {
|
|
4607
|
+
return typeof value === "string" && VECTOR_FILTER_TYPES.includes(value);
|
|
4608
|
+
}
|
|
4609
|
+
function normalizeVectorFilterParams(type, params, base) {
|
|
4610
|
+
if (!isVectorFilterType(type)) return null;
|
|
4611
|
+
const out = { ...VECTOR_FILTER_DEFAULTS[type], ...base ?? {} };
|
|
4612
|
+
for (const spec of VECTOR_FILTER_PARAM_SPECS[type]) {
|
|
4613
|
+
const v2 = params?.[spec.key];
|
|
4614
|
+
if (v2 === void 0) continue;
|
|
4615
|
+
if (spec.kind === "number" && typeof v2 === "number" && Number.isFinite(v2)) out[spec.key] = Math.min(spec.max ?? Infinity, Math.max(spec.min ?? -Infinity, v2));
|
|
4616
|
+
else if (spec.kind === "color" && typeof v2 === "string" && v2.trim()) out[spec.key] = v2.trim();
|
|
4617
|
+
}
|
|
4618
|
+
return out;
|
|
4619
|
+
}
|
|
4620
|
+
function vectorFilterParamKeys(type) {
|
|
4621
|
+
return VECTOR_FILTER_PARAM_SPECS[type].map((s) => s.key);
|
|
4622
|
+
}
|
|
4623
|
+
function createVectorFilter(type, id, params) {
|
|
4624
|
+
const p = normalizeVectorFilterParams(type, params);
|
|
4625
|
+
return p ? { id, type, params: p } : null;
|
|
4626
|
+
}
|
|
4627
|
+
function sanitizeVectorFilters(value) {
|
|
4628
|
+
if (!Array.isArray(value)) return [];
|
|
4629
|
+
const out = [];
|
|
4630
|
+
const used = /* @__PURE__ */ new Set();
|
|
4631
|
+
for (const raw of value) {
|
|
4632
|
+
if (!raw || typeof raw !== "object") continue;
|
|
4633
|
+
const r = raw;
|
|
4634
|
+
if (!isVectorFilterType(r.type)) continue;
|
|
4635
|
+
let id = typeof r.id === "string" && r.id && !used.has(r.id) ? r.id : "";
|
|
4636
|
+
for (let k = out.length + 1; !id; k++) if (!used.has(`filter${k}`)) id = `filter${k}`;
|
|
4637
|
+
used.add(id);
|
|
4638
|
+
const filter = createVectorFilter(r.type, id, r.params ?? {});
|
|
4639
|
+
out.push(r.enabled === false ? { ...filter, enabled: false } : filter);
|
|
4640
|
+
}
|
|
4641
|
+
return out;
|
|
4642
|
+
}
|
|
4643
|
+
function activeVectorFilters(node) {
|
|
4644
|
+
return (node.filters ?? []).filter((f) => {
|
|
4645
|
+
if (f.enabled === false || !isVectorFilterType(f.type)) return false;
|
|
4646
|
+
if (f.type === "layerBlur" || f.type === "feather") return f.params.radius > 0;
|
|
4647
|
+
return f.params.opacity > 0;
|
|
4648
|
+
});
|
|
4649
|
+
}
|
|
4650
|
+
function vectorFilterReach(filters) {
|
|
4651
|
+
let outer = 0;
|
|
4652
|
+
let blur = 0;
|
|
4653
|
+
for (const f of filters) {
|
|
4654
|
+
switch (f.type) {
|
|
4655
|
+
case "dropShadow":
|
|
4656
|
+
case "innerShadow":
|
|
4657
|
+
outer = Math.max(outer, Math.max(Math.abs(f.params.offsetX), Math.abs(f.params.offsetY)) + f.params.blur * 1.5 + f.params.spread);
|
|
4658
|
+
break;
|
|
4659
|
+
case "outerGlow":
|
|
4660
|
+
case "innerGlow":
|
|
4661
|
+
outer = Math.max(outer, f.params.blur * 1.5 + f.params.spread);
|
|
4662
|
+
break;
|
|
4663
|
+
case "layerBlur":
|
|
4664
|
+
blur += f.params.radius * 1.5;
|
|
4665
|
+
break;
|
|
4666
|
+
}
|
|
4667
|
+
}
|
|
4668
|
+
return outer + blur;
|
|
4669
|
+
}
|
|
4670
|
+
var round = (n) => Math.round(n * 1e3) / 1e3;
|
|
4671
|
+
var fe = (tag, attrs, children) => ({ tag, attrs, ...children ? { children } : {} });
|
|
4672
|
+
function vectorFilterSvg(filters, id, bounds) {
|
|
4673
|
+
const active = filters.filter((f) => activeVectorFilters({ filters: [f] }).length);
|
|
4674
|
+
if (!active.length || !bounds) return null;
|
|
4675
|
+
const primitives = [];
|
|
4676
|
+
let body = "SourceGraphic";
|
|
4677
|
+
let n = 0;
|
|
4678
|
+
const name = (part) => `${part}${n}`;
|
|
4679
|
+
for (const f of active) {
|
|
4680
|
+
if (f.type !== "innerShadow" && f.type !== "innerGlow") continue;
|
|
4681
|
+
n++;
|
|
4682
|
+
const p = f.params;
|
|
4683
|
+
primitives.push(fe("feComponentTransfer", { in: "SourceAlpha", result: name("inv") }, [fe("feFuncA", { type: "table", tableValues: "1 0" })]));
|
|
4684
|
+
let last = name("inv");
|
|
4685
|
+
if (f.type === "innerShadow" && (f.params.offsetX || f.params.offsetY)) {
|
|
4686
|
+
primitives.push(fe("feOffset", { in: last, dx: round(f.params.offsetX), dy: round(f.params.offsetY), result: name("off") }));
|
|
4687
|
+
last = name("off");
|
|
4688
|
+
}
|
|
4689
|
+
if (p.spread > 0) {
|
|
4690
|
+
primitives.push(fe("feMorphology", { in: last, operator: "dilate", radius: round(p.spread), result: name("grow") }));
|
|
4691
|
+
last = name("grow");
|
|
4692
|
+
}
|
|
4693
|
+
if (p.blur > 0) {
|
|
4694
|
+
primitives.push(fe("feGaussianBlur", { in: last, stdDeviation: round(p.blur / 2), result: name("blur") }));
|
|
4695
|
+
last = name("blur");
|
|
4696
|
+
}
|
|
4697
|
+
primitives.push(fe("feFlood", { "flood-color": p.color, "flood-opacity": round(p.opacity), result: name("color") }));
|
|
4698
|
+
primitives.push(fe("feComposite", { in: name("color"), in2: last, operator: "in", result: name("tint") }));
|
|
4699
|
+
primitives.push(fe("feComposite", { in: name("tint"), in2: "SourceAlpha", operator: "in", result: name("inner") }));
|
|
4700
|
+
primitives.push(fe("feComposite", { in: name("inner"), in2: body, operator: "over", result: name("body") }));
|
|
4701
|
+
body = name("body");
|
|
4702
|
+
}
|
|
4703
|
+
for (const f of active) {
|
|
4704
|
+
if (f.type !== "feather") continue;
|
|
4705
|
+
n++;
|
|
4706
|
+
const r = f.params.radius;
|
|
4707
|
+
primitives.push(fe("feMorphology", { in: "SourceAlpha", operator: "erode", radius: round(r / 2), result: name("core") }));
|
|
4708
|
+
primitives.push(fe("feGaussianBlur", { in: name("core"), stdDeviation: round(r / 4), result: name("fade") }));
|
|
4709
|
+
primitives.push(fe("feComposite", { in: body, in2: name("fade"), operator: "in", result: name("body") }));
|
|
4710
|
+
body = name("body");
|
|
4711
|
+
}
|
|
4712
|
+
const under = [];
|
|
4713
|
+
for (const f of active) {
|
|
4714
|
+
if (f.type !== "dropShadow" && f.type !== "outerGlow") continue;
|
|
4715
|
+
n++;
|
|
4716
|
+
const p = f.params;
|
|
4717
|
+
let last = "SourceAlpha";
|
|
4718
|
+
if (p.spread > 0) {
|
|
4719
|
+
primitives.push(fe("feMorphology", { in: last, operator: "dilate", radius: round(p.spread), result: name("grow") }));
|
|
4720
|
+
last = name("grow");
|
|
4721
|
+
}
|
|
4722
|
+
if (p.blur > 0) {
|
|
4723
|
+
primitives.push(fe("feGaussianBlur", { in: last, stdDeviation: round(p.blur / 2), result: name("blur") }));
|
|
4724
|
+
last = name("blur");
|
|
4725
|
+
}
|
|
4726
|
+
if (f.type === "dropShadow" && (f.params.offsetX || f.params.offsetY)) {
|
|
4727
|
+
primitives.push(fe("feOffset", { in: last, dx: round(f.params.offsetX), dy: round(f.params.offsetY), result: name("off") }));
|
|
4728
|
+
last = name("off");
|
|
4729
|
+
}
|
|
4730
|
+
primitives.push(fe("feFlood", { "flood-color": p.color, "flood-opacity": round(p.opacity), result: name("color") }));
|
|
4731
|
+
primitives.push(fe("feComposite", { in: name("color"), in2: last, operator: "in", result: name("shadow") }));
|
|
4732
|
+
under.push(name("shadow"));
|
|
4733
|
+
}
|
|
4734
|
+
if (under.length) {
|
|
4735
|
+
n++;
|
|
4736
|
+
primitives.push(fe("feMerge", { result: name("merged") }, [...under, body].map((i) => fe("feMergeNode", { in: i }))));
|
|
4737
|
+
body = name("merged");
|
|
4738
|
+
}
|
|
4739
|
+
for (const f of active) {
|
|
4740
|
+
if (f.type !== "layerBlur") continue;
|
|
4741
|
+
n++;
|
|
4742
|
+
primitives.push(fe("feGaussianBlur", { in: body, stdDeviation: round(f.params.radius / 2), result: name("body") }));
|
|
4743
|
+
body = name("body");
|
|
4744
|
+
}
|
|
4745
|
+
const lastResult = primitives[primitives.length - 1]?.attrs.result;
|
|
4746
|
+
if (lastResult !== body) primitives.push(fe("feMerge", {}, [fe("feMergeNode", { in: body })]));
|
|
4747
|
+
const pad = vectorFilterReach(active) + 2;
|
|
4748
|
+
return {
|
|
4749
|
+
id,
|
|
4750
|
+
x: round(bounds.x - pad),
|
|
4751
|
+
y: round(bounds.y - pad),
|
|
4752
|
+
width: round(bounds.width + 2 * pad),
|
|
4753
|
+
height: round(bounds.height + 2 * pad),
|
|
4754
|
+
primitives
|
|
4755
|
+
};
|
|
4756
|
+
}
|
|
4757
|
+
var escapeAttr = (value) => value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
4758
|
+
function primitiveMarkup(p) {
|
|
4759
|
+
const attrs = Object.entries(p.attrs).map(([k, v2]) => ` ${k}="${escapeAttr(String(v2))}"`).join("");
|
|
4760
|
+
return p.children?.length ? `<${p.tag}${attrs}>${p.children.map(primitiveMarkup).join("")}</${p.tag}>` : `<${p.tag}${attrs}/>`;
|
|
4761
|
+
}
|
|
4762
|
+
function vectorFilterMarkup(filter, extra = "") {
|
|
4763
|
+
return `<filter id="${escapeAttr(filter.id)}" filterUnits="userSpaceOnUse" x="${filter.x}" y="${filter.y}" width="${filter.width}" height="${filter.height}" color-interpolation-filters="sRGB"${extra}>${filter.primitives.map(primitiveMarkup).join("")}</filter>`;
|
|
4764
|
+
}
|
|
4765
|
+
var VECTOR_FILTER_MENU = VECTOR_FILTER_TYPES.map((type) => ({ type, label: VECTOR_FILTER_LABELS[type] }));
|
|
4766
|
+
|
|
4270
4767
|
// src/vector/gradientStroke.ts
|
|
4271
4768
|
var SHARP = 1.25;
|
|
4272
4769
|
var TOLERANCE = 0.2;
|
|
@@ -4450,7 +4947,7 @@ function applyVectorCornersAttribute(subpaths, value) {
|
|
|
4450
4947
|
}
|
|
4451
4948
|
return subpaths;
|
|
4452
4949
|
}
|
|
4453
|
-
var
|
|
4950
|
+
var escapeAttr2 = (value) => value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">");
|
|
4454
4951
|
function vectorPathLocalBounds(node) {
|
|
4455
4952
|
const b = bezierPathBounds(subpathsToBezier(node.subpaths));
|
|
4456
4953
|
return b ? { x: b.minX, y: b.minY, width: b.maxX - b.minX, height: b.maxY - b.minY } : null;
|
|
@@ -4506,6 +5003,26 @@ function computeStrokeSvgParts(node, clipId, precision) {
|
|
|
4506
5003
|
heads: parts.heads.map((h) => bezierPathToSvg(h.path, { precision }))
|
|
4507
5004
|
};
|
|
4508
5005
|
}
|
|
5006
|
+
function vectorNodeLocalPaintBounds(node) {
|
|
5007
|
+
const drawn = expandVectorAppearance(node);
|
|
5008
|
+
const reach = (n) => n.type === "path" ? vectorStrokeStackReach(n) : Math.max(0, ...n.children.map(reach));
|
|
5009
|
+
let b;
|
|
5010
|
+
if (drawn.type === "path") b = vectorPathLocalBounds(drawn);
|
|
5011
|
+
else b = unionBounds(drawn.children.filter((c) => c.visible !== false).map((c) => vectorNodeBounds(c, IDENTITY_MATRIX)));
|
|
5012
|
+
if (!b) return null;
|
|
5013
|
+
const pad = reach(drawn);
|
|
5014
|
+
return { x: b.x - pad, y: b.y - pad, width: b.width + 2 * pad, height: b.height + 2 * pad };
|
|
5015
|
+
}
|
|
5016
|
+
var filterCache = /* @__PURE__ */ new WeakMap();
|
|
5017
|
+
function vectorNodeFilterSvg(node, id) {
|
|
5018
|
+
if (!node.filters?.length) return null;
|
|
5019
|
+
const hit = filterCache.get(node);
|
|
5020
|
+
if (hit && hit.id === id) return hit.filter;
|
|
5021
|
+
const active = activeVectorFilters(node);
|
|
5022
|
+
const filter = active.length ? vectorFilterSvg(active, id, vectorNodeLocalPaintBounds(node)) : null;
|
|
5023
|
+
filterCache.set(node, { id, filter });
|
|
5024
|
+
return filter;
|
|
5025
|
+
}
|
|
4509
5026
|
function widthProfileToAttribute(points, precision = 4) {
|
|
4510
5027
|
return points.map((p) => [p.t, p.left, p.right].map((n) => formatNumber(n, precision)).join(",")).join(";");
|
|
4511
5028
|
}
|
|
@@ -4521,16 +5038,16 @@ function widthProfileFromAttribute(value) {
|
|
|
4521
5038
|
var round2 = (n) => Math.round(n * 100) / 100;
|
|
4522
5039
|
function gradientMarkup(def, extra = "") {
|
|
4523
5040
|
const tag = def.type === "radial" ? "radialGradient" : "linearGradient";
|
|
4524
|
-
const attrs = Object.entries(def.attrs).map(([k, v2]) => ` ${k}="${
|
|
4525
|
-
const stops = def.stops.map((s) => `<stop offset="${s.offset}" stop-color="${
|
|
4526
|
-
return `<${tag} id="${
|
|
5041
|
+
const attrs = Object.entries(def.attrs).map(([k, v2]) => ` ${k}="${escapeAttr2(String(v2))}"`).join("");
|
|
5042
|
+
const stops = def.stops.map((s) => `<stop offset="${s.offset}" stop-color="${escapeAttr2(s.stopColor)}"${s.stopOpacity !== void 0 ? ` stop-opacity="${s.stopOpacity}"` : ""}/>`).join("");
|
|
5043
|
+
return `<${tag} id="${escapeAttr2(def.id)}"${attrs}${extra}>${stops}</${tag}>`;
|
|
4527
5044
|
}
|
|
4528
5045
|
function paintDefMarkup(def, gradient) {
|
|
4529
|
-
const extra = gradient ? ` data-vector-gradient="${
|
|
5046
|
+
const extra = gradient ? ` data-vector-gradient="${escapeAttr2(JSON.stringify(gradient))}"` : "";
|
|
4530
5047
|
if (def.type !== "pattern") return gradientMarkup(def, extra);
|
|
4531
|
-
const attrs = Object.entries(def.attrs).map(([k, v2]) => ` ${k}="${
|
|
4532
|
-
const inner = def.gradients.map((g) => gradientMarkup(g)).join("") + def.tiles.map((t) => `<path d="${t.d}" fill="${
|
|
4533
|
-
return `<pattern id="${
|
|
5048
|
+
const attrs = Object.entries(def.attrs).map(([k, v2]) => ` ${k}="${escapeAttr2(String(v2))}"`).join("");
|
|
5049
|
+
const inner = def.gradients.map((g) => gradientMarkup(g)).join("") + def.tiles.map((t) => `<path d="${t.d}" fill="${escapeAttr2(t.fill)}"/>`).join("");
|
|
5050
|
+
return `<pattern id="${escapeAttr2(def.id)}"${attrs}${extra}>${inner}</pattern>`;
|
|
4534
5051
|
}
|
|
4535
5052
|
var paintMarkup = (paint, defs) => defs.map((d, i) => paintDefMarkup(d, i === 0 && isVectorGradient(paint) ? paint : void 0));
|
|
4536
5053
|
function blendFromAttribute(value, m) {
|
|
@@ -4569,25 +5086,113 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
4569
5086
|
const num2 = (n) => formatNumber(n, precision);
|
|
4570
5087
|
const indent = (depth) => pretty ? " ".repeat(depth) : "";
|
|
4571
5088
|
const common = (node) => {
|
|
4572
|
-
let out2 = ` id="${
|
|
5089
|
+
let out2 = ` id="${escapeAttr2(node.id)}"`;
|
|
4573
5090
|
if (node.transform) out2 += ` transform="matrix(${node.transform.map((n) => formatNumber(n, 6)).join(" ")})"`;
|
|
4574
5091
|
if (node.opacity !== void 0 && node.opacity < 1) out2 += ` opacity="${num2(node.opacity)}"`;
|
|
4575
5092
|
if (node.visible === false) out2 += ` display="none"`;
|
|
4576
5093
|
if (node.blendStep) out2 += ` data-vector-blend-step=""`;
|
|
4577
|
-
if (node.type === "group" && node.blend) out2 += ` data-vector-blend="${
|
|
5094
|
+
if (node.type === "group" && node.blend) out2 += ` data-vector-blend="${escapeAttr2(JSON.stringify(node.blend))}"`;
|
|
4578
5095
|
if (node.booleanOperation) out2 += ` data-vector-boolean-operation="${node.booleanOperation}"`;
|
|
5096
|
+
const blend = vectorBlendModeCss(node.blendMode);
|
|
5097
|
+
if (blend) out2 += ` style="mix-blend-mode:${blend}"`;
|
|
5098
|
+
if (node.filters?.length) {
|
|
5099
|
+
const filter = vectorNodeFilterSvg(node, `${prefix}filter-${node.id}`);
|
|
5100
|
+
const data = ` data-vector-filters="${escapeAttr2(JSON.stringify(node.filters))}"`;
|
|
5101
|
+
if (filter) {
|
|
5102
|
+
defs.push(vectorFilterMarkup(filter, data));
|
|
5103
|
+
out2 += ` filter="url(#${escapeAttr2(filter.id)})"`;
|
|
5104
|
+
} else out2 += data;
|
|
5105
|
+
}
|
|
4579
5106
|
return out2;
|
|
4580
5107
|
};
|
|
5108
|
+
const layerAttrs = (layer) => {
|
|
5109
|
+
let out2 = "";
|
|
5110
|
+
if (layer.opacity !== void 0 && layer.opacity < 1) out2 += ` opacity="${num2(layer.opacity)}"`;
|
|
5111
|
+
const blend = vectorBlendModeCss(layer.blendMode);
|
|
5112
|
+
if (blend) out2 += ` style="mix-blend-mode:${blend}"`;
|
|
5113
|
+
return out2;
|
|
5114
|
+
};
|
|
5115
|
+
const strokePartLines = (node, parts, strokeValue, d, lineAttrs, depth) => {
|
|
5116
|
+
const out2 = [];
|
|
5117
|
+
if (options.strokes === "outline") {
|
|
5118
|
+
const area = bezierPathToSvg(vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
|
|
5119
|
+
out2.push(`${indent(depth)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr2(strokeValue)}"/>`);
|
|
5120
|
+
return out2;
|
|
5121
|
+
}
|
|
5122
|
+
let clip = "";
|
|
5123
|
+
if (parts.clip) {
|
|
5124
|
+
const rule = node.fillRule === "evenodd" ? "evenodd" : "nonzero";
|
|
5125
|
+
const id = escapeAttr2(parts.clip.id);
|
|
5126
|
+
if (parts.clip.kind === "clip") {
|
|
5127
|
+
defs.push(`<clipPath id="${id}"><path d="${d}" clip-rule="${rule}"/></clipPath>`);
|
|
5128
|
+
clip = ` clip-path="url(#${id})"`;
|
|
5129
|
+
} else {
|
|
5130
|
+
const b = parts.clip.bounds;
|
|
5131
|
+
const box = `x="${num2(b.x)}" y="${num2(b.y)}" width="${num2(b.width)}" height="${num2(b.height)}"`;
|
|
5132
|
+
defs.push(`<mask id="${id}" maskUnits="userSpaceOnUse" ${box}><rect ${box} fill="#fff"/><path d="${d}" fill="#000" fill-rule="${rule}"/></mask>`);
|
|
5133
|
+
clip = ` mask="url(#${id})"`;
|
|
5134
|
+
}
|
|
5135
|
+
}
|
|
5136
|
+
if (parts.outline !== void 0) out2.push(`${indent(depth)}<path data-vector-part="stroke-outline" d="${parts.outline}" fill="${escapeAttr2(strokeValue)}"${clip}/>`);
|
|
5137
|
+
else out2.push(`${indent(depth)}<path data-vector-part="stroke" d="${parts.d}" fill="none"${lineAttrs(parts.width)}${clip}/>`);
|
|
5138
|
+
for (const h2 of parts.heads) out2.push(`${indent(depth)}<path data-vector-part="head" d="${h2}" fill="${escapeAttr2(strokeValue)}"/>`);
|
|
5139
|
+
return out2;
|
|
5140
|
+
};
|
|
5141
|
+
const lineAttrsOf = (node, strokeValue) => (width) => {
|
|
5142
|
+
let out2 = ` stroke="${escapeAttr2(strokeValue)}" stroke-width="${num2(width)}"`;
|
|
5143
|
+
if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
|
|
5144
|
+
if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
|
|
5145
|
+
if (node.strokeDasharray?.length) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
|
|
5146
|
+
return out2;
|
|
5147
|
+
};
|
|
5148
|
+
const liveCorners = (node) => {
|
|
5149
|
+
const corners = vectorCornersAttribute(node.subpaths, precision);
|
|
5150
|
+
return corners ? ` data-vector-d="${bezierPathToSvg(subpathsToBezier(node.subpaths, { corners: false }), { precision })}" data-vector-corners="${corners}"` : "";
|
|
5151
|
+
};
|
|
5152
|
+
const emitStacked = (node, depth) => {
|
|
5153
|
+
const d = vectorPathData(node, precision);
|
|
5154
|
+
const rule = node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : "";
|
|
5155
|
+
let data = ` data-vector-path="" data-vector-fills="${escapeAttr2(JSON.stringify(vectorFills(node)))}" data-vector-strokes="${escapeAttr2(JSON.stringify(vectorStrokes(node)))}"`;
|
|
5156
|
+
if (node.fillRule === "evenodd") data += ` data-vector-fill-rule="evenodd"`;
|
|
5157
|
+
lines.push(`${indent(depth)}<g${common(node)}${data}>`);
|
|
5158
|
+
const layers = vectorPaintLayerNodes(node).filter((l) => l.drawn);
|
|
5159
|
+
let geometry = liveCorners(node);
|
|
5160
|
+
if (!layers.some((l) => l.kind === "fill")) {
|
|
5161
|
+
lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}" fill="none"${rule}${geometry}/>`);
|
|
5162
|
+
geometry = "";
|
|
5163
|
+
}
|
|
5164
|
+
for (const l of layers) {
|
|
5165
|
+
const id = `${prefix}${l.kind}-${node.id}-${l.index}`;
|
|
5166
|
+
const paint = vectorPaintToSvg(l.layer.paint, id, { node: l.node, precision, ...l.kind === "stroke" ? { role: "stroke" } : {} });
|
|
5167
|
+
defs.push(...paintMarkup(l.layer.paint, paint.defs));
|
|
5168
|
+
const attrs = ` data-vector-layer="${l.index}"${layerAttrs(l.layer)}`;
|
|
5169
|
+
if (l.kind === "fill") {
|
|
5170
|
+
lines.push(`${indent(depth + 1)}<path data-vector-part="fill"${attrs} d="${d}" fill="${escapeAttr2(paint.value)}"${rule}${geometry}/>`);
|
|
5171
|
+
geometry = "";
|
|
5172
|
+
continue;
|
|
5173
|
+
}
|
|
5174
|
+
const lineAttrs = lineAttrsOf(l.node, paint.value);
|
|
5175
|
+
const parts = vectorStrokeSvgParts(l.node, `${prefix}clip-${node.id}-${l.index}`, precision);
|
|
5176
|
+
if (!parts) {
|
|
5177
|
+
lines.push(`${indent(depth + 1)}<path data-vector-part="stroke"${attrs} d="${d}" fill="none"${lineAttrs(l.node.strokeWidth ?? 1)}/>`);
|
|
5178
|
+
continue;
|
|
5179
|
+
}
|
|
5180
|
+
lines.push(`${indent(depth + 1)}<g data-vector-part="stroke-layer"${attrs}>`);
|
|
5181
|
+
lines.push(...strokePartLines(l.node, parts, paint.value, d, lineAttrs, depth + 2));
|
|
5182
|
+
lines.push(`${indent(depth + 1)}</g>`);
|
|
5183
|
+
}
|
|
5184
|
+
lines.push(`${indent(depth)}</g>`);
|
|
5185
|
+
};
|
|
4581
5186
|
const emit2 = (node, depth) => {
|
|
4582
5187
|
if (node.visible === false && !options.includeHidden) return;
|
|
4583
5188
|
const wrappers = options.wrap?.[node.id] ?? [];
|
|
4584
5189
|
wrappers.forEach((w2, i) => {
|
|
4585
|
-
let attrs = w2.id !== void 0 ? ` id="${
|
|
4586
|
-
if (w2.transform) attrs += ` transform="${
|
|
5190
|
+
let attrs = w2.id !== void 0 ? ` id="${escapeAttr2(w2.id)}"` : "";
|
|
5191
|
+
if (w2.transform) attrs += ` transform="${escapeAttr2(w2.transform)}"`;
|
|
4587
5192
|
if (w2.clip) {
|
|
4588
5193
|
const shape = Object.entries(w2.clip.attrs).map(([k, v2]) => ` ${k}="${formatNumber(v2, 4)}"`).join("");
|
|
4589
|
-
defs.push(`<clipPath id="${
|
|
4590
|
-
attrs += ` clip-path="url(#${
|
|
5194
|
+
defs.push(`<clipPath id="${escapeAttr2(w2.clip.id)}" clipPathUnits="objectBoundingBox"><${w2.clip.shape}${w2.clip.shapeId !== void 0 ? ` id="${escapeAttr2(w2.clip.shapeId)}"` : ""}${shape}/></clipPath>`);
|
|
5195
|
+
attrs += ` clip-path="url(#${escapeAttr2(w2.clip.id)})"`;
|
|
4591
5196
|
}
|
|
4592
5197
|
lines.push(`${indent(depth + i)}<g${attrs}>`);
|
|
4593
5198
|
});
|
|
@@ -4601,13 +5206,13 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
4601
5206
|
...node.effects?.length ? { effects: node.effects } : {},
|
|
4602
5207
|
...node.type === "group" && node.liveBoolean ? { liveBoolean: node.liveBoolean } : {}
|
|
4603
5208
|
};
|
|
4604
|
-
lines.push(`${indent(depth)}<g${common(node)} data-vector-live="${
|
|
5209
|
+
lines.push(`${indent(depth)}<g${common(node)} data-vector-live="${escapeAttr2(JSON.stringify(live2))}">`);
|
|
4605
5210
|
lines.push(`${indent(depth + 1)}<g data-vector-part="appearance">`);
|
|
4606
5211
|
for (const shape of vectorAppearanceNodes(node)) emit2(shape, depth + 2);
|
|
4607
5212
|
lines.push(`${indent(depth + 1)}</g>`);
|
|
4608
5213
|
lines.push(`${indent(depth + 1)}<g data-vector-part="source" display="none">`);
|
|
4609
5214
|
if (node.type === "path") {
|
|
4610
|
-
const { effects: _e, transform: _t, opacity: _o, visible: _v, booleanOperation: _b, blendStep: _s, ...source } = node;
|
|
5215
|
+
const { effects: _e, transform: _t, opacity: _o, visible: _v, booleanOperation: _b, blendStep: _s, blendMode: _bm, filters: _f, ...source } = node;
|
|
4611
5216
|
emit2({ ...source, id: `${node.id}~src` }, depth + 2);
|
|
4612
5217
|
} else for (const child of node.children) emit2(child, depth + 2);
|
|
4613
5218
|
lines.push(`${indent(depth + 1)}</g>`);
|
|
@@ -4620,20 +5225,17 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
4620
5225
|
lines.push(`${indent(depth)}</g>`);
|
|
4621
5226
|
return;
|
|
4622
5227
|
}
|
|
5228
|
+
if (needsVectorPaintLayers(node)) {
|
|
5229
|
+
emitStacked(node, depth);
|
|
5230
|
+
return;
|
|
5231
|
+
}
|
|
4623
5232
|
const fill = vectorPaintToSvg(node.fill, `${prefix}fill-${node.id}`, { node, precision });
|
|
4624
5233
|
const stroke = vectorPaintToSvg(node.stroke, `${prefix}stroke-${node.id}`, { node, role: "stroke", precision });
|
|
4625
5234
|
defs.push(...paintMarkup(node.fill, fill.defs), ...paintMarkup(node.stroke, stroke.defs));
|
|
4626
5235
|
const d = vectorPathData(node, precision);
|
|
4627
|
-
const
|
|
4628
|
-
const
|
|
4629
|
-
const
|
|
4630
|
-
const lineAttrs = (width) => {
|
|
4631
|
-
let out2 = ` stroke="${escapeAttr(stroke.value)}" stroke-width="${num2(width)}"`;
|
|
4632
|
-
if (node.strokeLinecap && node.strokeLinecap !== "butt") out2 += ` stroke-linecap="${node.strokeLinecap}"`;
|
|
4633
|
-
if (node.strokeLinejoin && node.strokeLinejoin !== "miter") out2 += ` stroke-linejoin="${node.strokeLinejoin}"`;
|
|
4634
|
-
if (node.strokeDasharray?.length) out2 += ` stroke-dasharray="${node.strokeDasharray.map(num2).join(" ")}"`;
|
|
4635
|
-
return out2;
|
|
4636
|
-
};
|
|
5236
|
+
const live = liveCorners(node);
|
|
5237
|
+
const fillAttrs = ` fill="${escapeAttr2(fill.value)}"${node.fillRule === "evenodd" ? ` fill-rule="evenodd"` : ""}`;
|
|
5238
|
+
const lineAttrs = lineAttrsOf(node, stroke.value);
|
|
4637
5239
|
const parts = stroke.value !== "none" ? vectorStrokeSvgParts(node, `${prefix}clip-${node.id}`, precision) : void 0;
|
|
4638
5240
|
if (!parts) {
|
|
4639
5241
|
lines.push(`${indent(depth)}<path${common(node)} d="${d}"${fillAttrs}${stroke.value !== "none" ? lineAttrs(node.strokeWidth ?? 1) : ""}${live}/>`);
|
|
@@ -4655,28 +5257,7 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
4655
5257
|
}
|
|
4656
5258
|
lines.push(`${indent(depth)}<g${common(node)}${data}>`);
|
|
4657
5259
|
lines.push(`${indent(depth + 1)}<path data-vector-part="fill" d="${d}"${fillAttrs}${live}/>`);
|
|
4658
|
-
|
|
4659
|
-
const area = bezierPathToSvg(vectorStrokeOutlinePath(subpathsToBezier(node.subpaths), node), { precision });
|
|
4660
|
-
lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${area}" fill="${escapeAttr(stroke.value)}"/>`);
|
|
4661
|
-
} else {
|
|
4662
|
-
let clip = "";
|
|
4663
|
-
if (parts.clip) {
|
|
4664
|
-
const rule = node.fillRule === "evenodd" ? "evenodd" : "nonzero";
|
|
4665
|
-
const id = escapeAttr(parts.clip.id);
|
|
4666
|
-
if (parts.clip.kind === "clip") {
|
|
4667
|
-
defs.push(`<clipPath id="${id}"><path d="${d}" clip-rule="${rule}"/></clipPath>`);
|
|
4668
|
-
clip = ` clip-path="url(#${id})"`;
|
|
4669
|
-
} else {
|
|
4670
|
-
const b = parts.clip.bounds;
|
|
4671
|
-
const box = `x="${num2(b.x)}" y="${num2(b.y)}" width="${num2(b.width)}" height="${num2(b.height)}"`;
|
|
4672
|
-
defs.push(`<mask id="${id}" maskUnits="userSpaceOnUse" ${box}><rect ${box} fill="#fff"/><path d="${d}" fill="#000" fill-rule="${rule}"/></mask>`);
|
|
4673
|
-
clip = ` mask="url(#${id})"`;
|
|
4674
|
-
}
|
|
4675
|
-
}
|
|
4676
|
-
if (parts.outline !== void 0) lines.push(`${indent(depth + 1)}<path data-vector-part="stroke-outline" d="${parts.outline}" fill="${escapeAttr(stroke.value)}"${clip}/>`);
|
|
4677
|
-
else lines.push(`${indent(depth + 1)}<path data-vector-part="stroke" d="${parts.d}" fill="none"${lineAttrs(parts.width)}${clip}/>`);
|
|
4678
|
-
for (const h2 of parts.heads) lines.push(`${indent(depth + 1)}<path data-vector-part="head" d="${h2}" fill="${escapeAttr(stroke.value)}"/>`);
|
|
4679
|
-
}
|
|
5260
|
+
lines.push(...strokePartLines(node, parts, stroke.value, d, lineAttrs, depth + 1));
|
|
4680
5261
|
lines.push(`${indent(depth)}</g>`);
|
|
4681
5262
|
};
|
|
4682
5263
|
for (const node of doc.nodes) emit2(node, 1);
|
|
@@ -4686,7 +5267,7 @@ function vectorDocumentToSvg(doc, options = {}) {
|
|
|
4686
5267
|
const out = [`<svg xmlns="http://www.w3.org/2000/svg" width="${w}" height="${h}" viewBox="0 0 ${w} ${h}">`];
|
|
4687
5268
|
if (defs.length) out.push(`${indent(1)}<defs>${defs.join("")}</defs>`);
|
|
4688
5269
|
if (doc.background && options.background !== false && hasPaint(doc.background)) {
|
|
4689
|
-
out.push(`${indent(1)}<rect width="${w}" height="${h}" fill="${
|
|
5270
|
+
out.push(`${indent(1)}<rect width="${w}" height="${h}" fill="${escapeAttr2(doc.background)}"/>`);
|
|
4690
5271
|
}
|
|
4691
5272
|
out.push(...lines, "</svg>");
|
|
4692
5273
|
return out.join(nl);
|
|
@@ -4777,10 +5358,15 @@ var STYLE_KEYS2 = {
|
|
|
4777
5358
|
"stroke-linecap": "strokeLinecap",
|
|
4778
5359
|
"stroke-linejoin": "strokeLinejoin",
|
|
4779
5360
|
"stroke-dasharray": "strokeDasharray",
|
|
4780
|
-
"fill-rule": "fillRule"
|
|
5361
|
+
"fill-rule": "fillRule",
|
|
5362
|
+
"fill-opacity": "fillOpacity",
|
|
5363
|
+
"stroke-opacity": "strokeOpacity",
|
|
5364
|
+
"mix-blend-mode": "mixBlendMode",
|
|
5365
|
+
filter: "filter"
|
|
4781
5366
|
};
|
|
4782
5367
|
function readStyle(el, parent) {
|
|
4783
|
-
const
|
|
5368
|
+
const { mixBlendMode: _m, filter: _f, ...inherited } = parent;
|
|
5369
|
+
const out = { ...inherited };
|
|
4784
5370
|
for (const [attr, key] of Object.entries(STYLE_KEYS2)) if (el.attrs[attr] !== void 0) out[key] = el.attrs[attr].trim();
|
|
4785
5371
|
for (const decl of (el.attrs.style ?? "").split(";")) {
|
|
4786
5372
|
const i = decl.indexOf(":");
|
|
@@ -4816,6 +5402,45 @@ function collectGradients(el, raw) {
|
|
|
4816
5402
|
if (PAINT_SERVERS.has(el.name) && el.attrs.id) raw.set(el.attrs.id, el);
|
|
4817
5403
|
for (const c of el.children) collectGradients(c, raw);
|
|
4818
5404
|
}
|
|
5405
|
+
function collectFilters(el, raw) {
|
|
5406
|
+
if (el.name === "filter" && el.attrs.id) raw.set(el.attrs.id, el);
|
|
5407
|
+
for (const c of el.children) collectFilters(c, raw);
|
|
5408
|
+
}
|
|
5409
|
+
function filtersFromElement(el) {
|
|
5410
|
+
const own = el.attrs["data-vector-filters"];
|
|
5411
|
+
if (own !== void 0) {
|
|
5412
|
+
try {
|
|
5413
|
+
return sanitizeVectorFilters(JSON.parse(own));
|
|
5414
|
+
} catch {
|
|
5415
|
+
return [];
|
|
5416
|
+
}
|
|
5417
|
+
}
|
|
5418
|
+
const prims = el.children.filter((c) => c.name.startsWith("fe"));
|
|
5419
|
+
const out = [];
|
|
5420
|
+
for (const p of prims) {
|
|
5421
|
+
const std = numberList(p.attrs.stdDeviation)[0] ?? 0;
|
|
5422
|
+
if (p.name === "feDropShadow") {
|
|
5423
|
+
const style = Object.fromEntries(
|
|
5424
|
+
(p.attrs.style ?? "").split(";").map((d) => d.split(":").map((x) => x.trim())).filter((d) => d.length === 2)
|
|
5425
|
+
);
|
|
5426
|
+
const opacity = parseFloat(style["flood-opacity"] ?? p.attrs["flood-opacity"] ?? "1");
|
|
5427
|
+
out.push({
|
|
5428
|
+
type: "dropShadow",
|
|
5429
|
+
params: {
|
|
5430
|
+
color: style["flood-color"] ?? p.attrs["flood-color"] ?? "#000000",
|
|
5431
|
+
opacity: Number.isFinite(opacity) ? opacity : 1,
|
|
5432
|
+
offsetX: length(p.attrs.dx, 2),
|
|
5433
|
+
offsetY: length(p.attrs.dy, 2),
|
|
5434
|
+
blur: std * 2,
|
|
5435
|
+
spread: 0
|
|
5436
|
+
}
|
|
5437
|
+
});
|
|
5438
|
+
} else if (p.name === "feGaussianBlur" && prims.length === 1 && (p.attrs.in === void 0 || p.attrs.in === "SourceGraphic")) {
|
|
5439
|
+
out.push({ type: "layerBlur", params: { radius: std * 2 } });
|
|
5440
|
+
} else return [];
|
|
5441
|
+
}
|
|
5442
|
+
return sanitizeVectorFilters(out);
|
|
5443
|
+
}
|
|
4819
5444
|
function gradientFromAttribute(value) {
|
|
4820
5445
|
if (!value) return null;
|
|
4821
5446
|
try {
|
|
@@ -4913,6 +5538,13 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
4913
5538
|
};
|
|
4914
5539
|
const rawGradients = /* @__PURE__ */ new Map();
|
|
4915
5540
|
collectGradients(root, rawGradients);
|
|
5541
|
+
const rawFilters = /* @__PURE__ */ new Map();
|
|
5542
|
+
collectFilters(root, rawFilters);
|
|
5543
|
+
const filtersOf = (value) => {
|
|
5544
|
+
const url = /^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec((value ?? "").trim());
|
|
5545
|
+
const el = url ? rawFilters.get(url[1]) : void 0;
|
|
5546
|
+
return el ? filtersFromElement(el) : [];
|
|
5547
|
+
};
|
|
4916
5548
|
const paint = (value) => {
|
|
4917
5549
|
const v2 = value.trim();
|
|
4918
5550
|
const url = /^url\(\s*['"]?#([^'")\s]+)['"]?\s*\)/.exec(v2);
|
|
@@ -4979,8 +5611,55 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
4979
5611
|
if (m === IDENTITY_MATRIX) return node;
|
|
4980
5612
|
const next = transformVectorNode(node, m);
|
|
4981
5613
|
const strokeScale = Math.sqrt(Math.abs(m[0] * m[3] - m[1] * m[2]));
|
|
4982
|
-
if (
|
|
4983
|
-
|
|
5614
|
+
if (strokeScale > 0 && Math.abs(strokeScale - 1) > 1e-9) {
|
|
5615
|
+
if (hasPaint(next.stroke)) next.strokeWidth = (next.strokeWidth ?? 1) * strokeScale;
|
|
5616
|
+
if (Array.isArray(next.strokes)) next.strokes = next.strokes.map((l) => (l.kind ?? "paint") === "paint" ? { ...l, strokeWidth: (l.strokeWidth ?? 1) * strokeScale } : l);
|
|
5617
|
+
}
|
|
5618
|
+
return normalizeVectorPaintStacks(next, "stack");
|
|
5619
|
+
};
|
|
5620
|
+
const withOpacities = (node, s) => {
|
|
5621
|
+
let out = node;
|
|
5622
|
+
const fo = s.fillOpacity !== void 0 ? fraction(s.fillOpacity, 1) : 1;
|
|
5623
|
+
const so = s.strokeOpacity !== void 0 ? fraction(s.strokeOpacity, 1) : 1;
|
|
5624
|
+
if (fo < 1 && hasPaint(out.fill)) out = withVectorFills(out, [{ paint: out.fill, opacity: Math.max(0, fo) }]);
|
|
5625
|
+
if (so < 1 && hasPaint(out.stroke)) out = withVectorStrokes(out, vectorStrokes(out).map((l) => ({ ...l, opacity: Math.max(0, so) })));
|
|
5626
|
+
return out;
|
|
5627
|
+
};
|
|
5628
|
+
const stackedPath = (g, _style, m, meta) => {
|
|
5629
|
+
const fillEl = g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === "fill");
|
|
5630
|
+
const subpaths = fillEl ? shapeOf(fillEl) : null;
|
|
5631
|
+
if (!subpaths?.length) return null;
|
|
5632
|
+
const parse = (v2) => {
|
|
5633
|
+
try {
|
|
5634
|
+
return v2 ? JSON.parse(v2) : [];
|
|
5635
|
+
} catch {
|
|
5636
|
+
return [];
|
|
5637
|
+
}
|
|
5638
|
+
};
|
|
5639
|
+
let node = { id: idFor(g), type: "path", ...meta, subpaths, fill: null, stroke: null };
|
|
5640
|
+
if (g.attrs["data-vector-fill-rule"] === "evenodd") node.fillRule = "evenodd";
|
|
5641
|
+
node = withVectorFills(node, sanitizeVectorFills(parse(g.attrs["data-vector-fills"])));
|
|
5642
|
+
node = withVectorStrokes(node, sanitizeVectorStrokes(parse(g.attrs["data-vector-strokes"])));
|
|
5643
|
+
return placed(node, m);
|
|
5644
|
+
};
|
|
5645
|
+
const mergeStacked = (nodes2) => {
|
|
5646
|
+
const out = [];
|
|
5647
|
+
const key = (n) => JSON.stringify([n.subpaths, n.transform ?? null, n.opacity ?? 1, n.visible !== false, n.filters ?? null, n.blendMode ?? "normal", n.fillRule ?? "nonzero", n.booleanOperation ?? null]);
|
|
5648
|
+
for (const n of nodes2) {
|
|
5649
|
+
const prev = out[out.length - 1];
|
|
5650
|
+
if (prev?.type === "path" && n.type === "path" && key(prev) === key(n)) {
|
|
5651
|
+
const fills = vectorFills(n);
|
|
5652
|
+
const strokesBefore = vectorStrokes(prev);
|
|
5653
|
+
if (!(fills.length && strokesBefore.length)) {
|
|
5654
|
+
let merged = withVectorFills(prev, [...vectorFills(prev), ...fills]);
|
|
5655
|
+
merged = withVectorStrokes(merged, [...strokesBefore, ...vectorStrokes(n)]);
|
|
5656
|
+
out[out.length - 1] = merged;
|
|
5657
|
+
continue;
|
|
5658
|
+
}
|
|
5659
|
+
}
|
|
5660
|
+
out.push(n);
|
|
5661
|
+
}
|
|
5662
|
+
return out;
|
|
4984
5663
|
};
|
|
4985
5664
|
const mergedPath = (g, style, m, meta) => {
|
|
4986
5665
|
const part = (name) => g.children.find((c) => c.name === "path" && c.attrs["data-vector-part"] === name);
|
|
@@ -5063,10 +5742,14 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
5063
5742
|
const s = readStyle(child, style);
|
|
5064
5743
|
const opacity = child.attrs.opacity !== void 0 ? parseFloat(child.attrs.opacity) : void 0;
|
|
5065
5744
|
const hidden = child.attrs.display === "none" || child.attrs.visibility === "hidden";
|
|
5745
|
+
const blendMode = vectorBlendModeFromCss(s.mixBlendMode);
|
|
5746
|
+
const filters = filtersOf(s.filter);
|
|
5066
5747
|
const meta = {
|
|
5067
5748
|
...child.attrs["inkscape:label"] || child.attrs["data-name"] ? { name: child.attrs["inkscape:label"] ?? child.attrs["data-name"] } : {},
|
|
5068
5749
|
...opacity !== void 0 && Number.isFinite(opacity) && opacity < 1 ? { opacity } : {},
|
|
5069
|
-
...hidden ? { visible: false } : {}
|
|
5750
|
+
...hidden ? { visible: false } : {},
|
|
5751
|
+
...blendMode && blendMode !== "normal" ? { blendMode } : {},
|
|
5752
|
+
...filters.length ? { filters } : {}
|
|
5070
5753
|
};
|
|
5071
5754
|
if (child.attrs["data-vector-blend-step"] !== void 0) continue;
|
|
5072
5755
|
const operation = child.attrs["data-vector-boolean-operation"];
|
|
@@ -5076,6 +5759,11 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
5076
5759
|
if (node2) out.push(node2);
|
|
5077
5760
|
continue;
|
|
5078
5761
|
}
|
|
5762
|
+
if (child.name === "g" && child.attrs["data-vector-path"] !== void 0 && child.attrs["data-vector-fills"] !== void 0) {
|
|
5763
|
+
const node2 = stackedPath(child, s, m, meta);
|
|
5764
|
+
if (node2) out.push(node2);
|
|
5765
|
+
continue;
|
|
5766
|
+
}
|
|
5079
5767
|
if (child.name === "g" && child.attrs["data-vector-path"] !== void 0) {
|
|
5080
5768
|
const node2 = mergedPath(child, s, m, meta);
|
|
5081
5769
|
if (node2) out.push(node2);
|
|
@@ -5093,20 +5781,23 @@ function parseVectorSvg(svg, options = {}) {
|
|
|
5093
5781
|
const subpaths = shapeOf(child);
|
|
5094
5782
|
if (!subpaths || !subpaths.length) continue;
|
|
5095
5783
|
const node = placed(
|
|
5096
|
-
|
|
5097
|
-
|
|
5098
|
-
|
|
5099
|
-
|
|
5100
|
-
|
|
5101
|
-
|
|
5102
|
-
|
|
5103
|
-
|
|
5104
|
-
|
|
5784
|
+
withOpacities(
|
|
5785
|
+
{
|
|
5786
|
+
id: idFor(child),
|
|
5787
|
+
type: "path",
|
|
5788
|
+
...meta,
|
|
5789
|
+
subpaths,
|
|
5790
|
+
fill: child.name === "line" ? null : paint(s.fill),
|
|
5791
|
+
stroke: paint(s.stroke),
|
|
5792
|
+
...strokeStyle(s)
|
|
5793
|
+
},
|
|
5794
|
+
s
|
|
5795
|
+
),
|
|
5105
5796
|
m
|
|
5106
5797
|
);
|
|
5107
5798
|
out.push(node);
|
|
5108
5799
|
}
|
|
5109
|
-
return out;
|
|
5800
|
+
return options.mergeStackedShapes ? mergeStacked(out) : out;
|
|
5110
5801
|
};
|
|
5111
5802
|
const nodes = visit(root, readStyle(root, { fill: "#000", stroke: "none", strokeWidth: "" }), rootMatrix);
|
|
5112
5803
|
return { width, height, nodes };
|
|
@@ -5119,12 +5810,14 @@ export {
|
|
|
5119
5810
|
VECTOR_GRADIENT_INTERPOLATIONS,
|
|
5120
5811
|
VECTOR_STROKE_GRADIENT_MODES,
|
|
5121
5812
|
VECTOR_ARROWHEADS,
|
|
5813
|
+
VECTOR_BLEND_MODES,
|
|
5122
5814
|
VECTOR_BLEND_SPACINGS,
|
|
5123
5815
|
VECTOR_TOOLS,
|
|
5124
5816
|
VECTOR_TRANSFORM_HANDLES,
|
|
5125
5817
|
VECTOR_PATHFINDER_OPERATIONS,
|
|
5126
5818
|
VECTOR_EFFECT_TYPES,
|
|
5127
5819
|
VECTOR_MERGE_MODES,
|
|
5820
|
+
VECTOR_FILTER_TYPES,
|
|
5128
5821
|
isVectorGradient,
|
|
5129
5822
|
parseVectorColor,
|
|
5130
5823
|
VECTOR_GRADIENT_MIN_STOPS,
|
|
@@ -5223,6 +5916,32 @@ export {
|
|
|
5223
5916
|
vectorStrokeOutlinePath,
|
|
5224
5917
|
hitTestVectorStroke,
|
|
5225
5918
|
vectorStrokeReach,
|
|
5919
|
+
VECTOR_STROKE_SETTING_KEYS,
|
|
5920
|
+
VECTOR_BLEND_MODE_LABELS,
|
|
5921
|
+
isVectorBlendMode,
|
|
5922
|
+
vectorBlendModeCss,
|
|
5923
|
+
vectorBlendModeFromCss,
|
|
5924
|
+
isPlainVectorPaintLayer,
|
|
5925
|
+
isDrawnVectorPaintLayer,
|
|
5926
|
+
vectorFills,
|
|
5927
|
+
vectorStrokeSettings,
|
|
5928
|
+
vectorStrokes,
|
|
5929
|
+
hasVectorPaintStacks,
|
|
5930
|
+
withVectorFills,
|
|
5931
|
+
withVectorStrokes,
|
|
5932
|
+
normalizeVectorPaintStacks,
|
|
5933
|
+
sanitizeVectorFills,
|
|
5934
|
+
sanitizeVectorStrokeSettings,
|
|
5935
|
+
sanitizeVectorStrokes,
|
|
5936
|
+
vectorPaintLayerNodes,
|
|
5937
|
+
needsVectorPaintLayers,
|
|
5938
|
+
vectorStrokeStackReach,
|
|
5939
|
+
hitTestVectorPaintLayer,
|
|
5940
|
+
hitTestVectorPaintStack,
|
|
5941
|
+
vectorStacksHaveGradient,
|
|
5942
|
+
newVectorStrokeLayer,
|
|
5943
|
+
vectorTargetPaint,
|
|
5944
|
+
withVectorTargetPaint,
|
|
5226
5945
|
effectPathLength,
|
|
5227
5946
|
effectPathVertexCount,
|
|
5228
5947
|
trimIntervals,
|
|
@@ -5331,16 +6050,31 @@ export {
|
|
|
5331
6050
|
createVectorMorph,
|
|
5332
6051
|
interpolateVectorPaths,
|
|
5333
6052
|
evaluateVectorPathKeyframes,
|
|
6053
|
+
VECTOR_FILTER_DEFAULTS,
|
|
6054
|
+
VECTOR_FILTER_LABELS,
|
|
6055
|
+
VECTOR_FILTER_PARAM_SPECS,
|
|
6056
|
+
isVectorFilterType,
|
|
6057
|
+
normalizeVectorFilterParams,
|
|
6058
|
+
vectorFilterParamKeys,
|
|
6059
|
+
createVectorFilter,
|
|
6060
|
+
sanitizeVectorFilters,
|
|
6061
|
+
activeVectorFilters,
|
|
6062
|
+
vectorFilterReach,
|
|
6063
|
+
vectorFilterSvg,
|
|
6064
|
+
vectorFilterMarkup,
|
|
6065
|
+
VECTOR_FILTER_MENU,
|
|
5334
6066
|
vectorStrokeGradientDefs,
|
|
5335
6067
|
vectorCornersAttribute,
|
|
5336
6068
|
applyVectorCornersAttribute,
|
|
5337
6069
|
vectorPathLocalBounds,
|
|
5338
6070
|
vectorPaintToSvg,
|
|
5339
6071
|
vectorStrokeSvgParts,
|
|
6072
|
+
vectorNodeLocalPaintBounds,
|
|
6073
|
+
vectorNodeFilterSvg,
|
|
5340
6074
|
widthProfileToAttribute,
|
|
5341
6075
|
widthProfileFromAttribute,
|
|
5342
6076
|
vectorDocumentToSvg,
|
|
5343
6077
|
parseSvgTransform,
|
|
5344
6078
|
parseVectorSvg
|
|
5345
6079
|
};
|
|
5346
|
-
//# sourceMappingURL=chunk-
|
|
6080
|
+
//# sourceMappingURL=chunk-63EFQCT5.js.map
|