TOPVERSE_Official/.output/server/chunks/loadSVG.mjs

1657 lines
60 KiB
JavaScript

import { y as forceGet, a1 as Loader, a3 as FileLoader, ap as Matrix3, aY as ShapeUtils, aZ as Box2, h as Vector2, a_ as Shape, a$ as Path, g as BufferGeometry, I as Float32BufferAttribute, av as increaseLoadingCount, aw as decreaseLoadingCount, ay as handleProgress, b0 as ShapePath, V as Vector3 } from './app/_nuxt/model-9bf70e2c.mjs';
import 'vue';
import 'vue/server-renderer';
class SVGLoader extends Loader {
constructor(manager) {
super(manager);
this.defaultDPI = 90;
this.defaultUnit = "px";
}
load(url, onLoad, onProgress, onError) {
const scope = this;
const loader2 = new FileLoader(scope.manager);
loader2.setPath(scope.path);
loader2.setRequestHeader(scope.requestHeader);
loader2.setWithCredentials(scope.withCredentials);
loader2.load(url, function(text) {
try {
onLoad(scope.parse(text));
} catch (e) {
if (onError) {
onError(e);
} else {
console.error(e);
}
scope.manager.itemError(url);
}
}, onProgress, onError);
}
parse(text) {
const scope = this;
function parseNode(node, style) {
if (node.nodeType !== 1)
return;
const transform = getNodeTransform(node);
let isDefsNode = false;
let path = null;
switch (node.nodeName) {
case "svg":
break;
case "style":
parseCSSStylesheet(node);
break;
case "g":
style = parseStyle(node, style);
break;
case "path":
style = parseStyle(node, style);
if (node.hasAttribute("d"))
path = parsePathNode(node);
break;
case "rect":
style = parseStyle(node, style);
path = parseRectNode(node);
break;
case "polygon":
style = parseStyle(node, style);
path = parsePolygonNode(node);
break;
case "polyline":
style = parseStyle(node, style);
path = parsePolylineNode(node);
break;
case "circle":
style = parseStyle(node, style);
path = parseCircleNode(node);
break;
case "ellipse":
style = parseStyle(node, style);
path = parseEllipseNode(node);
break;
case "line":
style = parseStyle(node, style);
path = parseLineNode(node);
break;
case "defs":
isDefsNode = true;
break;
case "use":
style = parseStyle(node, style);
const href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href") || "";
const usedNodeId = href.substring(1);
const usedNode = node.viewportElement.getElementById(usedNodeId);
if (usedNode) {
parseNode(usedNode, style);
} else {
console.warn("SVGLoader: 'use node' references non-existent node id: " + usedNodeId);
}
break;
}
if (path) {
if (style.fill !== void 0 && style.fill !== "none") {
path.color.setStyle(style.fill);
}
transformPath(path, currentTransform);
paths.push(path);
path.userData = { node, style };
}
const childNodes = node.childNodes;
for (let i = 0; i < childNodes.length; i++) {
const node2 = childNodes[i];
if (isDefsNode && node2.nodeName !== "style" && node2.nodeName !== "defs") {
continue;
}
parseNode(node2, style);
}
if (transform) {
transformStack.pop();
if (transformStack.length > 0) {
currentTransform.copy(transformStack[transformStack.length - 1]);
} else {
currentTransform.identity();
}
}
}
function parsePathNode(node) {
const path = new ShapePath();
const point = new Vector2();
const control = new Vector2();
const firstPoint = new Vector2();
let isFirstPoint = true;
let doSetFirstPoint = false;
const d = node.getAttribute("d");
const commands = d.match(/[a-df-z][^a-df-z]*/ig);
for (let i = 0, l = commands.length; i < l; i++) {
const command = commands[i];
const type = command.charAt(0);
const data2 = command.slice(1).trim();
if (isFirstPoint === true) {
doSetFirstPoint = true;
isFirstPoint = false;
}
let numbers;
switch (type) {
case "M":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 2) {
point.x = numbers[j + 0];
point.y = numbers[j + 1];
control.x = point.x;
control.y = point.y;
if (j === 0) {
path.moveTo(point.x, point.y);
} else {
path.lineTo(point.x, point.y);
}
if (j === 0)
firstPoint.copy(point);
}
break;
case "H":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j++) {
point.x = numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "V":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j++) {
point.y = numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "L":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 2) {
point.x = numbers[j + 0];
point.y = numbers[j + 1];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "C":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 6) {
path.bezierCurveTo(numbers[j + 0], numbers[j + 1], numbers[j + 2], numbers[j + 3], numbers[j + 4], numbers[j + 5]);
control.x = numbers[j + 2];
control.y = numbers[j + 3];
point.x = numbers[j + 4];
point.y = numbers[j + 5];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "S":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 4) {
path.bezierCurveTo(getReflection(point.x, control.x), getReflection(point.y, control.y), numbers[j + 0], numbers[j + 1], numbers[j + 2], numbers[j + 3]);
control.x = numbers[j + 0];
control.y = numbers[j + 1];
point.x = numbers[j + 2];
point.y = numbers[j + 3];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "Q":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 4) {
path.quadraticCurveTo(numbers[j + 0], numbers[j + 1], numbers[j + 2], numbers[j + 3]);
control.x = numbers[j + 0];
control.y = numbers[j + 1];
point.x = numbers[j + 2];
point.y = numbers[j + 3];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "T":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 2) {
const rx = getReflection(point.x, control.x);
const ry = getReflection(point.y, control.y);
path.quadraticCurveTo(rx, ry, numbers[j + 0], numbers[j + 1]);
control.x = rx;
control.y = ry;
point.x = numbers[j + 0];
point.y = numbers[j + 1];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "A":
numbers = parseFloats(data2, [3, 4], 7);
for (let j = 0, jl = numbers.length; j < jl; j += 7) {
if (numbers[j + 5] == point.x && numbers[j + 6] == point.y)
continue;
const start = point.clone();
point.x = numbers[j + 5];
point.y = numbers[j + 6];
control.x = point.x;
control.y = point.y;
parseArcCommand(path, numbers[j], numbers[j + 1], numbers[j + 2], numbers[j + 3], numbers[j + 4], start, point);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "m":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 2) {
point.x += numbers[j + 0];
point.y += numbers[j + 1];
control.x = point.x;
control.y = point.y;
if (j === 0) {
path.moveTo(point.x, point.y);
} else {
path.lineTo(point.x, point.y);
}
if (j === 0)
firstPoint.copy(point);
}
break;
case "h":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j++) {
point.x += numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "v":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j++) {
point.y += numbers[j];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "l":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 2) {
point.x += numbers[j + 0];
point.y += numbers[j + 1];
control.x = point.x;
control.y = point.y;
path.lineTo(point.x, point.y);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "c":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 6) {
path.bezierCurveTo(point.x + numbers[j + 0], point.y + numbers[j + 1], point.x + numbers[j + 2], point.y + numbers[j + 3], point.x + numbers[j + 4], point.y + numbers[j + 5]);
control.x = point.x + numbers[j + 2];
control.y = point.y + numbers[j + 3];
point.x += numbers[j + 4];
point.y += numbers[j + 5];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "s":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 4) {
path.bezierCurveTo(getReflection(point.x, control.x), getReflection(point.y, control.y), point.x + numbers[j + 0], point.y + numbers[j + 1], point.x + numbers[j + 2], point.y + numbers[j + 3]);
control.x = point.x + numbers[j + 0];
control.y = point.y + numbers[j + 1];
point.x += numbers[j + 2];
point.y += numbers[j + 3];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "q":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 4) {
path.quadraticCurveTo(point.x + numbers[j + 0], point.y + numbers[j + 1], point.x + numbers[j + 2], point.y + numbers[j + 3]);
control.x = point.x + numbers[j + 0];
control.y = point.y + numbers[j + 1];
point.x += numbers[j + 2];
point.y += numbers[j + 3];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "t":
numbers = parseFloats(data2);
for (let j = 0, jl = numbers.length; j < jl; j += 2) {
const rx = getReflection(point.x, control.x);
const ry = getReflection(point.y, control.y);
path.quadraticCurveTo(rx, ry, point.x + numbers[j + 0], point.y + numbers[j + 1]);
control.x = rx;
control.y = ry;
point.x = point.x + numbers[j + 0];
point.y = point.y + numbers[j + 1];
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "a":
numbers = parseFloats(data2, [3, 4], 7);
for (let j = 0, jl = numbers.length; j < jl; j += 7) {
if (numbers[j + 5] == 0 && numbers[j + 6] == 0)
continue;
const start = point.clone();
point.x += numbers[j + 5];
point.y += numbers[j + 6];
control.x = point.x;
control.y = point.y;
parseArcCommand(path, numbers[j], numbers[j + 1], numbers[j + 2], numbers[j + 3], numbers[j + 4], start, point);
if (j === 0 && doSetFirstPoint === true)
firstPoint.copy(point);
}
break;
case "Z":
case "z":
path.currentPath.autoClose = true;
if (path.currentPath.curves.length > 0) {
point.copy(firstPoint);
path.currentPath.currentPoint.copy(point);
isFirstPoint = true;
}
break;
default:
console.warn(command);
}
doSetFirstPoint = false;
}
return path;
}
function parseCSSStylesheet(node) {
if (!node.sheet || !node.sheet.cssRules || !node.sheet.cssRules.length)
return;
for (let i = 0; i < node.sheet.cssRules.length; i++) {
const stylesheet = node.sheet.cssRules[i];
if (stylesheet.type !== 1)
continue;
const selectorList = stylesheet.selectorText.split(/,/gm).filter(Boolean).map((i2) => i2.trim());
for (let j = 0; j < selectorList.length; j++) {
const definitions = Object.fromEntries(Object.entries(stylesheet.style).filter(([, v]) => v !== ""));
stylesheets[selectorList[j]] = Object.assign(stylesheets[selectorList[j]] || {}, definitions);
}
}
}
function parseArcCommand(path, rx, ry, x_axis_rotation, large_arc_flag, sweep_flag, start, end) {
if (rx == 0 || ry == 0) {
path.lineTo(end.x, end.y);
return;
}
x_axis_rotation = x_axis_rotation * Math.PI / 180;
rx = Math.abs(rx);
ry = Math.abs(ry);
const dx2 = (start.x - end.x) / 2;
const dy2 = (start.y - end.y) / 2;
const x1p = Math.cos(x_axis_rotation) * dx2 + Math.sin(x_axis_rotation) * dy2;
const y1p = -Math.sin(x_axis_rotation) * dx2 + Math.cos(x_axis_rotation) * dy2;
let rxs = rx * rx;
let rys = ry * ry;
const x1ps = x1p * x1p;
const y1ps = y1p * y1p;
const cr = x1ps / rxs + y1ps / rys;
if (cr > 1) {
const s = Math.sqrt(cr);
rx = s * rx;
ry = s * ry;
rxs = rx * rx;
rys = ry * ry;
}
const dq = rxs * y1ps + rys * x1ps;
const pq = (rxs * rys - dq) / dq;
let q = Math.sqrt(Math.max(0, pq));
if (large_arc_flag === sweep_flag)
q = -q;
const cxp = q * rx * y1p / ry;
const cyp = -q * ry * x1p / rx;
const cx = Math.cos(x_axis_rotation) * cxp - Math.sin(x_axis_rotation) * cyp + (start.x + end.x) / 2;
const cy = Math.sin(x_axis_rotation) * cxp + Math.cos(x_axis_rotation) * cyp + (start.y + end.y) / 2;
const theta = svgAngle(1, 0, (x1p - cxp) / rx, (y1p - cyp) / ry);
const delta = svgAngle((x1p - cxp) / rx, (y1p - cyp) / ry, (-x1p - cxp) / rx, (-y1p - cyp) / ry) % (Math.PI * 2);
path.currentPath.absellipse(cx, cy, rx, ry, theta, theta + delta, sweep_flag === 0, x_axis_rotation);
}
function svgAngle(ux, uy, vx, vy) {
const dot = ux * vx + uy * vy;
const len = Math.sqrt(ux * ux + uy * uy) * Math.sqrt(vx * vx + vy * vy);
let ang = Math.acos(Math.max(-1, Math.min(1, dot / len)));
if (ux * vy - uy * vx < 0)
ang = -ang;
return ang;
}
function parseRectNode(node) {
const x = parseFloatWithUnits(node.getAttribute("x") || 0);
const y = parseFloatWithUnits(node.getAttribute("y") || 0);
const rx = parseFloatWithUnits(node.getAttribute("rx") || node.getAttribute("ry") || 0);
const ry = parseFloatWithUnits(node.getAttribute("ry") || node.getAttribute("rx") || 0);
const w = parseFloatWithUnits(node.getAttribute("width"));
const h = parseFloatWithUnits(node.getAttribute("height"));
const bci = 1 - 0.551915024494;
const path = new ShapePath();
path.moveTo(x + rx, y);
path.lineTo(x + w - rx, y);
if (rx !== 0 || ry !== 0) {
path.bezierCurveTo(x + w - rx * bci, y, x + w, y + ry * bci, x + w, y + ry);
}
path.lineTo(x + w, y + h - ry);
if (rx !== 0 || ry !== 0) {
path.bezierCurveTo(x + w, y + h - ry * bci, x + w - rx * bci, y + h, x + w - rx, y + h);
}
path.lineTo(x + rx, y + h);
if (rx !== 0 || ry !== 0) {
path.bezierCurveTo(x + rx * bci, y + h, x, y + h - ry * bci, x, y + h - ry);
}
path.lineTo(x, y + ry);
if (rx !== 0 || ry !== 0) {
path.bezierCurveTo(x, y + ry * bci, x + rx * bci, y, x + rx, y);
}
return path;
}
function parsePolygonNode(node) {
function iterator(match, a, b) {
const x = parseFloatWithUnits(a);
const y = parseFloatWithUnits(b);
if (index === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
index++;
}
const regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
const path = new ShapePath();
let index = 0;
node.getAttribute("points").replace(regex, iterator);
path.currentPath.autoClose = true;
return path;
}
function parsePolylineNode(node) {
function iterator(match, a, b) {
const x = parseFloatWithUnits(a);
const y = parseFloatWithUnits(b);
if (index === 0) {
path.moveTo(x, y);
} else {
path.lineTo(x, y);
}
index++;
}
const regex = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
const path = new ShapePath();
let index = 0;
node.getAttribute("points").replace(regex, iterator);
path.currentPath.autoClose = false;
return path;
}
function parseCircleNode(node) {
const x = parseFloatWithUnits(node.getAttribute("cx") || 0);
const y = parseFloatWithUnits(node.getAttribute("cy") || 0);
const r = parseFloatWithUnits(node.getAttribute("r") || 0);
const subpath = new Path();
subpath.absarc(x, y, r, 0, Math.PI * 2);
const path = new ShapePath();
path.subPaths.push(subpath);
return path;
}
function parseEllipseNode(node) {
const x = parseFloatWithUnits(node.getAttribute("cx") || 0);
const y = parseFloatWithUnits(node.getAttribute("cy") || 0);
const rx = parseFloatWithUnits(node.getAttribute("rx") || 0);
const ry = parseFloatWithUnits(node.getAttribute("ry") || 0);
const subpath = new Path();
subpath.absellipse(x, y, rx, ry, 0, Math.PI * 2);
const path = new ShapePath();
path.subPaths.push(subpath);
return path;
}
function parseLineNode(node) {
const x1 = parseFloatWithUnits(node.getAttribute("x1") || 0);
const y1 = parseFloatWithUnits(node.getAttribute("y1") || 0);
const x2 = parseFloatWithUnits(node.getAttribute("x2") || 0);
const y2 = parseFloatWithUnits(node.getAttribute("y2") || 0);
const path = new ShapePath();
path.moveTo(x1, y1);
path.lineTo(x2, y2);
path.currentPath.autoClose = false;
return path;
}
function parseStyle(node, style) {
style = Object.assign({}, style);
let stylesheetStyles = {};
if (node.hasAttribute("class")) {
const classSelectors = node.getAttribute("class").split(/\s/).filter(Boolean).map((i) => i.trim());
for (let i = 0; i < classSelectors.length; i++) {
stylesheetStyles = Object.assign(stylesheetStyles, stylesheets["." + classSelectors[i]]);
}
}
if (node.hasAttribute("id")) {
stylesheetStyles = Object.assign(stylesheetStyles, stylesheets["#" + node.getAttribute("id")]);
}
function addStyle(svgName, jsName, adjustFunction) {
if (adjustFunction === void 0)
adjustFunction = function copy(v) {
if (v.startsWith("url"))
console.warn("SVGLoader: url access in attributes is not implemented.");
return v;
};
if (node.hasAttribute(svgName))
style[jsName] = adjustFunction(node.getAttribute(svgName));
if (stylesheetStyles[svgName])
style[jsName] = adjustFunction(stylesheetStyles[svgName]);
if (node.style && node.style[svgName] !== "")
style[jsName] = adjustFunction(node.style[svgName]);
}
function clamp(v) {
return Math.max(0, Math.min(1, parseFloatWithUnits(v)));
}
function positive(v) {
return Math.max(0, parseFloatWithUnits(v));
}
addStyle("fill", "fill");
addStyle("fill-opacity", "fillOpacity", clamp);
addStyle("fill-rule", "fillRule");
addStyle("opacity", "opacity", clamp);
addStyle("stroke", "stroke");
addStyle("stroke-opacity", "strokeOpacity", clamp);
addStyle("stroke-width", "strokeWidth", positive);
addStyle("stroke-linejoin", "strokeLineJoin");
addStyle("stroke-linecap", "strokeLineCap");
addStyle("stroke-miterlimit", "strokeMiterLimit", positive);
addStyle("visibility", "visibility");
return style;
}
function getReflection(a, b) {
return a - (b - a);
}
function parseFloats(input, flags, stride) {
if (typeof input !== "string") {
throw new TypeError("Invalid input: " + typeof input);
}
const RE = {
SEPARATOR: /[ \t\r\n\,.\-+]/,
WHITESPACE: /[ \t\r\n]/,
DIGIT: /[\d]/,
SIGN: /[-+]/,
POINT: /\./,
COMMA: /,/,
EXP: /e/i,
FLAGS: /[01]/
};
const SEP = 0;
const INT = 1;
const FLOAT = 2;
const EXP = 3;
let state = SEP;
let seenComma = true;
let number = "", exponent = "";
const result = [];
function throwSyntaxError(current2, i, partial) {
const error = new SyntaxError('Unexpected character "' + current2 + '" at index ' + i + ".");
error.partial = partial;
throw error;
}
function newNumber() {
if (number !== "") {
if (exponent === "")
result.push(Number(number));
else
result.push(Number(number) * Math.pow(10, Number(exponent)));
}
number = "";
exponent = "";
}
let current;
const length = input.length;
for (let i = 0; i < length; i++) {
current = input[i];
if (Array.isArray(flags) && flags.includes(result.length % stride) && RE.FLAGS.test(current)) {
state = INT;
number = current;
newNumber();
continue;
}
if (state === SEP) {
if (RE.WHITESPACE.test(current)) {
continue;
}
if (RE.DIGIT.test(current) || RE.SIGN.test(current)) {
state = INT;
number = current;
continue;
}
if (RE.POINT.test(current)) {
state = FLOAT;
number = current;
continue;
}
if (RE.COMMA.test(current)) {
if (seenComma) {
throwSyntaxError(current, i, result);
}
seenComma = true;
}
}
if (state === INT) {
if (RE.DIGIT.test(current)) {
number += current;
continue;
}
if (RE.POINT.test(current)) {
number += current;
state = FLOAT;
continue;
}
if (RE.EXP.test(current)) {
state = EXP;
continue;
}
if (RE.SIGN.test(current) && number.length === 1 && RE.SIGN.test(number[0])) {
throwSyntaxError(current, i, result);
}
}
if (state === FLOAT) {
if (RE.DIGIT.test(current)) {
number += current;
continue;
}
if (RE.EXP.test(current)) {
state = EXP;
continue;
}
if (RE.POINT.test(current) && number[number.length - 1] === ".") {
throwSyntaxError(current, i, result);
}
}
if (state === EXP) {
if (RE.DIGIT.test(current)) {
exponent += current;
continue;
}
if (RE.SIGN.test(current)) {
if (exponent === "") {
exponent += current;
continue;
}
if (exponent.length === 1 && RE.SIGN.test(exponent)) {
throwSyntaxError(current, i, result);
}
}
}
if (RE.WHITESPACE.test(current)) {
newNumber();
state = SEP;
seenComma = false;
} else if (RE.COMMA.test(current)) {
newNumber();
state = SEP;
seenComma = true;
} else if (RE.SIGN.test(current)) {
newNumber();
state = INT;
number = current;
} else if (RE.POINT.test(current)) {
newNumber();
state = FLOAT;
number = current;
} else {
throwSyntaxError(current, i, result);
}
}
newNumber();
return result;
}
const units = ["mm", "cm", "in", "pt", "pc", "px"];
const unitConversion = {
"mm": {
"mm": 1,
"cm": 0.1,
"in": 1 / 25.4,
"pt": 72 / 25.4,
"pc": 6 / 25.4,
"px": -1
},
"cm": {
"mm": 10,
"cm": 1,
"in": 1 / 2.54,
"pt": 72 / 2.54,
"pc": 6 / 2.54,
"px": -1
},
"in": {
"mm": 25.4,
"cm": 2.54,
"in": 1,
"pt": 72,
"pc": 6,
"px": -1
},
"pt": {
"mm": 25.4 / 72,
"cm": 2.54 / 72,
"in": 1 / 72,
"pt": 1,
"pc": 6 / 72,
"px": -1
},
"pc": {
"mm": 25.4 / 6,
"cm": 2.54 / 6,
"in": 1 / 6,
"pt": 72 / 6,
"pc": 1,
"px": -1
},
"px": {
"px": 1
}
};
function parseFloatWithUnits(string) {
let theUnit = "px";
if (typeof string === "string" || string instanceof String) {
for (let i = 0, n = units.length; i < n; i++) {
const u = units[i];
if (string.endsWith(u)) {
theUnit = u;
string = string.substring(0, string.length - u.length);
break;
}
}
}
let scale = void 0;
if (theUnit === "px" && scope.defaultUnit !== "px") {
scale = unitConversion["in"][scope.defaultUnit] / scope.defaultDPI;
} else {
scale = unitConversion[theUnit][scope.defaultUnit];
if (scale < 0) {
scale = unitConversion[theUnit]["in"] * scope.defaultDPI;
}
}
return scale * parseFloat(string);
}
function getNodeTransform(node) {
if (!(node.hasAttribute("transform") || node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y")))) {
return null;
}
const transform = parseNodeTransform(node);
if (transformStack.length > 0) {
transform.premultiply(transformStack[transformStack.length - 1]);
}
currentTransform.copy(transform);
transformStack.push(transform);
return transform;
}
function parseNodeTransform(node) {
const transform = new Matrix3();
const currentTransform2 = tempTransform0;
if (node.nodeName === "use" && (node.hasAttribute("x") || node.hasAttribute("y"))) {
const tx = parseFloatWithUnits(node.getAttribute("x"));
const ty = parseFloatWithUnits(node.getAttribute("y"));
transform.translate(tx, ty);
}
if (node.hasAttribute("transform")) {
const transformsTexts = node.getAttribute("transform").split(")");
for (let tIndex = transformsTexts.length - 1; tIndex >= 0; tIndex--) {
const transformText = transformsTexts[tIndex].trim();
if (transformText === "")
continue;
const openParPos = transformText.indexOf("(");
const closeParPos = transformText.length;
if (openParPos > 0 && openParPos < closeParPos) {
const transformType = transformText.slice(0, openParPos);
const array = parseFloats(transformText.slice(openParPos + 1));
currentTransform2.identity();
switch (transformType) {
case "translate":
if (array.length >= 1) {
const tx = array[0];
let ty = tx;
if (array.length >= 2) {
ty = array[1];
}
currentTransform2.translate(tx, ty);
}
break;
case "rotate":
if (array.length >= 1) {
let angle = 0;
let cx = 0;
let cy = 0;
angle = -array[0] * Math.PI / 180;
if (array.length >= 3) {
cx = array[1];
cy = array[2];
}
tempTransform1.identity().translate(-cx, -cy);
tempTransform2.identity().rotate(angle);
tempTransform3.multiplyMatrices(tempTransform2, tempTransform1);
tempTransform1.identity().translate(cx, cy);
currentTransform2.multiplyMatrices(tempTransform1, tempTransform3);
}
break;
case "scale":
if (array.length >= 1) {
const scaleX = array[0];
let scaleY = scaleX;
if (array.length >= 2) {
scaleY = array[1];
}
currentTransform2.scale(scaleX, scaleY);
}
break;
case "skewX":
if (array.length === 1) {
currentTransform2.set(1, Math.tan(array[0] * Math.PI / 180), 0, 0, 1, 0, 0, 0, 1);
}
break;
case "skewY":
if (array.length === 1) {
currentTransform2.set(1, 0, 0, Math.tan(array[0] * Math.PI / 180), 1, 0, 0, 0, 1);
}
break;
case "matrix":
if (array.length === 6) {
currentTransform2.set(array[0], array[2], array[4], array[1], array[3], array[5], 0, 0, 1);
}
break;
}
}
transform.premultiply(currentTransform2);
}
}
return transform;
}
function transformPath(path, m) {
function transfVec2(v2) {
tempV3.set(v2.x, v2.y, 1).applyMatrix3(m);
v2.set(tempV3.x, tempV3.y);
}
const isRotated = isTransformRotated(m);
const subPaths = path.subPaths;
for (let i = 0, n = subPaths.length; i < n; i++) {
const subPath = subPaths[i];
const curves = subPath.curves;
for (let j = 0; j < curves.length; j++) {
const curve = curves[j];
if (curve.isLineCurve) {
transfVec2(curve.v1);
transfVec2(curve.v2);
} else if (curve.isCubicBezierCurve) {
transfVec2(curve.v0);
transfVec2(curve.v1);
transfVec2(curve.v2);
transfVec2(curve.v3);
} else if (curve.isQuadraticBezierCurve) {
transfVec2(curve.v0);
transfVec2(curve.v1);
transfVec2(curve.v2);
} else if (curve.isEllipseCurve) {
if (isRotated) {
console.warn("SVGLoader: Elliptic arc or ellipse rotation or skewing is not implemented.");
}
tempV2.set(curve.aX, curve.aY);
transfVec2(tempV2);
curve.aX = tempV2.x;
curve.aY = tempV2.y;
curve.xRadius *= getTransformScaleX(m);
curve.yRadius *= getTransformScaleY(m);
}
}
}
}
function isTransformRotated(m) {
return m.elements[1] !== 0 || m.elements[3] !== 0;
}
function getTransformScaleX(m) {
const te = m.elements;
return Math.sqrt(te[0] * te[0] + te[1] * te[1]);
}
function getTransformScaleY(m) {
const te = m.elements;
return Math.sqrt(te[3] * te[3] + te[4] * te[4]);
}
const paths = [];
const stylesheets = {};
const transformStack = [];
const tempTransform0 = new Matrix3();
const tempTransform1 = new Matrix3();
const tempTransform2 = new Matrix3();
const tempTransform3 = new Matrix3();
const tempV2 = new Vector2();
const tempV3 = new Vector3();
const currentTransform = new Matrix3();
const xml = new DOMParser().parseFromString(text, "image/svg+xml");
parseNode(xml.documentElement, {
fill: "#000",
fillOpacity: 1,
strokeOpacity: 1,
strokeWidth: 1,
strokeLineJoin: "miter",
strokeLineCap: "butt",
strokeMiterLimit: 4
});
const data = { paths, xml: xml.documentElement };
return data;
}
static createShapes(shapePath) {
const BIGNUMBER = 999999999;
const IntersectionLocationType = {
ORIGIN: 0,
DESTINATION: 1,
BETWEEN: 2,
LEFT: 3,
RIGHT: 4,
BEHIND: 5,
BEYOND: 6
};
const classifyResult = {
loc: IntersectionLocationType.ORIGIN,
t: 0
};
function findEdgeIntersection(a0, a1, b0, b1) {
const x1 = a0.x;
const x2 = a1.x;
const x3 = b0.x;
const x4 = b1.x;
const y1 = a0.y;
const y2 = a1.y;
const y3 = b0.y;
const y4 = b1.y;
const nom1 = (x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3);
const nom2 = (x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3);
const denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
const t1 = nom1 / denom;
const t2 = nom2 / denom;
if (denom === 0 && nom1 !== 0 || t1 <= 0 || t1 >= 1 || t2 < 0 || t2 > 1) {
return null;
} else if (nom1 === 0 && denom === 0) {
for (let i = 0; i < 2; i++) {
classifyPoint(i === 0 ? b0 : b1, a0, a1);
if (classifyResult.loc == IntersectionLocationType.ORIGIN) {
const point = i === 0 ? b0 : b1;
return { x: point.x, y: point.y, t: classifyResult.t };
} else if (classifyResult.loc == IntersectionLocationType.BETWEEN) {
const x = +(x1 + classifyResult.t * (x2 - x1)).toPrecision(10);
const y = +(y1 + classifyResult.t * (y2 - y1)).toPrecision(10);
return { x, y, t: classifyResult.t };
}
}
return null;
} else {
for (let i = 0; i < 2; i++) {
classifyPoint(i === 0 ? b0 : b1, a0, a1);
if (classifyResult.loc == IntersectionLocationType.ORIGIN) {
const point = i === 0 ? b0 : b1;
return { x: point.x, y: point.y, t: classifyResult.t };
}
}
const x = +(x1 + t1 * (x2 - x1)).toPrecision(10);
const y = +(y1 + t1 * (y2 - y1)).toPrecision(10);
return { x, y, t: t1 };
}
}
function classifyPoint(p, edgeStart, edgeEnd) {
const ax = edgeEnd.x - edgeStart.x;
const ay = edgeEnd.y - edgeStart.y;
const bx = p.x - edgeStart.x;
const by = p.y - edgeStart.y;
const sa = ax * by - bx * ay;
if (p.x === edgeStart.x && p.y === edgeStart.y) {
classifyResult.loc = IntersectionLocationType.ORIGIN;
classifyResult.t = 0;
return;
}
if (p.x === edgeEnd.x && p.y === edgeEnd.y) {
classifyResult.loc = IntersectionLocationType.DESTINATION;
classifyResult.t = 1;
return;
}
if (sa < -Number.EPSILON) {
classifyResult.loc = IntersectionLocationType.LEFT;
return;
}
if (sa > Number.EPSILON) {
classifyResult.loc = IntersectionLocationType.RIGHT;
return;
}
if (ax * bx < 0 || ay * by < 0) {
classifyResult.loc = IntersectionLocationType.BEHIND;
return;
}
if (Math.sqrt(ax * ax + ay * ay) < Math.sqrt(bx * bx + by * by)) {
classifyResult.loc = IntersectionLocationType.BEYOND;
return;
}
let t;
if (ax !== 0) {
t = bx / ax;
} else {
t = by / ay;
}
classifyResult.loc = IntersectionLocationType.BETWEEN;
classifyResult.t = t;
}
function getIntersections(path1, path2) {
const intersectionsRaw = [];
const intersections = [];
for (let index = 1; index < path1.length; index++) {
const path1EdgeStart = path1[index - 1];
const path1EdgeEnd = path1[index];
for (let index2 = 1; index2 < path2.length; index2++) {
const path2EdgeStart = path2[index2 - 1];
const path2EdgeEnd = path2[index2];
const intersection = findEdgeIntersection(path1EdgeStart, path1EdgeEnd, path2EdgeStart, path2EdgeEnd);
if (intersection !== null && intersectionsRaw.find((i) => i.t <= intersection.t + Number.EPSILON && i.t >= intersection.t - Number.EPSILON) === void 0) {
intersectionsRaw.push(intersection);
intersections.push(new Vector2(intersection.x, intersection.y));
}
}
}
return intersections;
}
function getScanlineIntersections(scanline, boundingBox, paths) {
const center = new Vector2();
boundingBox.getCenter(center);
const allIntersections = [];
paths.forEach((path) => {
if (path.boundingBox.containsPoint(center)) {
const intersections = getIntersections(scanline, path.points);
intersections.forEach((p) => {
allIntersections.push({ identifier: path.identifier, isCW: path.isCW, point: p });
});
}
});
allIntersections.sort((i1, i2) => {
return i1.point.x - i2.point.x;
});
return allIntersections;
}
function isHoleTo(simplePath, allPaths, scanlineMinX2, scanlineMaxX2, _fillRule) {
if (_fillRule === null || _fillRule === void 0 || _fillRule === "") {
_fillRule = "nonzero";
}
const centerBoundingBox = new Vector2();
simplePath.boundingBox.getCenter(centerBoundingBox);
const scanline = [new Vector2(scanlineMinX2, centerBoundingBox.y), new Vector2(scanlineMaxX2, centerBoundingBox.y)];
const scanlineIntersections = getScanlineIntersections(scanline, simplePath.boundingBox, allPaths);
scanlineIntersections.sort((i1, i2) => {
return i1.point.x - i2.point.x;
});
const baseIntersections = [];
const otherIntersections = [];
scanlineIntersections.forEach((i2) => {
if (i2.identifier === simplePath.identifier) {
baseIntersections.push(i2);
} else {
otherIntersections.push(i2);
}
});
const firstXOfPath = baseIntersections[0].point.x;
const stack = [];
let i = 0;
while (i < otherIntersections.length && otherIntersections[i].point.x < firstXOfPath) {
if (stack.length > 0 && stack[stack.length - 1] === otherIntersections[i].identifier) {
stack.pop();
} else {
stack.push(otherIntersections[i].identifier);
}
i++;
}
stack.push(simplePath.identifier);
if (_fillRule === "evenodd") {
const isHole = stack.length % 2 === 0 ? true : false;
const isHoleFor = stack[stack.length - 2];
return { identifier: simplePath.identifier, isHole, for: isHoleFor };
} else if (_fillRule === "nonzero") {
let isHole = true;
let isHoleFor = null;
let lastCWValue = null;
for (let i2 = 0; i2 < stack.length; i2++) {
const identifier2 = stack[i2];
if (isHole) {
lastCWValue = allPaths[identifier2].isCW;
isHole = false;
isHoleFor = identifier2;
} else if (lastCWValue !== allPaths[identifier2].isCW) {
lastCWValue = allPaths[identifier2].isCW;
isHole = true;
}
}
return { identifier: simplePath.identifier, isHole, for: isHoleFor };
} else {
console.warn('fill-rule: "' + _fillRule + '" is currently not implemented.');
}
}
let identifier = 0;
let scanlineMinX = BIGNUMBER;
let scanlineMaxX = -BIGNUMBER;
let simplePaths = shapePath.subPaths.map((p) => {
const points = p.getPoints();
let maxY = -BIGNUMBER;
let minY = BIGNUMBER;
let maxX = -BIGNUMBER;
let minX = BIGNUMBER;
for (let i = 0; i < points.length; i++) {
const p2 = points[i];
if (p2.y > maxY) {
maxY = p2.y;
}
if (p2.y < minY) {
minY = p2.y;
}
if (p2.x > maxX) {
maxX = p2.x;
}
if (p2.x < minX) {
minX = p2.x;
}
}
if (scanlineMaxX <= maxX) {
scanlineMaxX = maxX + 1;
}
if (scanlineMinX >= minX) {
scanlineMinX = minX - 1;
}
return { curves: p.curves, points, isCW: ShapeUtils.isClockWise(points), identifier: identifier++, boundingBox: new Box2(new Vector2(minX, minY), new Vector2(maxX, maxY)) };
});
simplePaths = simplePaths.filter((sp) => sp.points.length > 1);
const isAHole = simplePaths.map((p) => isHoleTo(p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData.style.fillRule));
const shapesToReturn = [];
simplePaths.forEach((p) => {
const amIAHole = isAHole[p.identifier];
if (!amIAHole.isHole) {
const shape = new Shape();
shape.curves = p.curves;
const holes = isAHole.filter((h) => h.isHole && h.for === p.identifier);
holes.forEach((h) => {
const hole = simplePaths[h.identifier];
const path = new Path();
path.curves = hole.curves;
shape.holes.push(path);
});
shapesToReturn.push(shape);
}
});
return shapesToReturn;
}
static getStrokeStyle(width, color, lineJoin, lineCap, miterLimit) {
width = width !== void 0 ? width : 1;
color = color !== void 0 ? color : "#000";
lineJoin = lineJoin !== void 0 ? lineJoin : "miter";
lineCap = lineCap !== void 0 ? lineCap : "butt";
miterLimit = miterLimit !== void 0 ? miterLimit : 4;
return {
strokeColor: color,
strokeWidth: width,
strokeLineJoin: lineJoin,
strokeLineCap: lineCap,
strokeMiterLimit: miterLimit
};
}
static pointsToStroke(points, style, arcDivisions, minDistance) {
const vertices = [];
const normals = [];
const uvs = [];
if (SVGLoader.pointsToStrokeWithBuffers(points, style, arcDivisions, minDistance, vertices, normals, uvs) === 0) {
return null;
}
const geometry = new BufferGeometry();
geometry.setAttribute("position", new Float32BufferAttribute(vertices, 3));
geometry.setAttribute("normal", new Float32BufferAttribute(normals, 3));
geometry.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
return geometry;
}
static pointsToStrokeWithBuffers(points, style, arcDivisions, minDistance, vertices, normals, uvs, vertexOffset) {
const tempV2_1 = new Vector2();
const tempV2_2 = new Vector2();
const tempV2_3 = new Vector2();
const tempV2_4 = new Vector2();
const tempV2_5 = new Vector2();
const tempV2_6 = new Vector2();
const tempV2_7 = new Vector2();
const lastPointL = new Vector2();
const lastPointR = new Vector2();
const point0L = new Vector2();
const point0R = new Vector2();
const currentPointL = new Vector2();
const currentPointR = new Vector2();
const nextPointL = new Vector2();
const nextPointR = new Vector2();
const innerPoint = new Vector2();
const outerPoint = new Vector2();
arcDivisions = arcDivisions !== void 0 ? arcDivisions : 12;
minDistance = minDistance !== void 0 ? minDistance : 1e-3;
vertexOffset = vertexOffset !== void 0 ? vertexOffset : 0;
points = removeDuplicatedPoints(points);
const numPoints = points.length;
if (numPoints < 2)
return 0;
const isClosed = points[0].equals(points[numPoints - 1]);
let currentPoint;
let previousPoint = points[0];
let nextPoint;
const strokeWidth2 = style.strokeWidth / 2;
const deltaU = 1 / (numPoints - 1);
let u0 = 0, u1;
let innerSideModified;
let joinIsOnLeftSide;
let isMiter;
let initialJoinIsOnLeftSide = false;
let numVertices = 0;
let currentCoordinate = vertexOffset * 3;
let currentCoordinateUV = vertexOffset * 2;
getNormal(points[0], points[1], tempV2_1).multiplyScalar(strokeWidth2);
lastPointL.copy(points[0]).sub(tempV2_1);
lastPointR.copy(points[0]).add(tempV2_1);
point0L.copy(lastPointL);
point0R.copy(lastPointR);
for (let iPoint = 1; iPoint < numPoints; iPoint++) {
currentPoint = points[iPoint];
if (iPoint === numPoints - 1) {
if (isClosed) {
nextPoint = points[1];
} else
nextPoint = void 0;
} else {
nextPoint = points[iPoint + 1];
}
const normal1 = tempV2_1;
getNormal(previousPoint, currentPoint, normal1);
tempV2_3.copy(normal1).multiplyScalar(strokeWidth2);
currentPointL.copy(currentPoint).sub(tempV2_3);
currentPointR.copy(currentPoint).add(tempV2_3);
u1 = u0 + deltaU;
innerSideModified = false;
if (nextPoint !== void 0) {
getNormal(currentPoint, nextPoint, tempV2_2);
tempV2_3.copy(tempV2_2).multiplyScalar(strokeWidth2);
nextPointL.copy(currentPoint).sub(tempV2_3);
nextPointR.copy(currentPoint).add(tempV2_3);
joinIsOnLeftSide = true;
tempV2_3.subVectors(nextPoint, previousPoint);
if (normal1.dot(tempV2_3) < 0) {
joinIsOnLeftSide = false;
}
if (iPoint === 1)
initialJoinIsOnLeftSide = joinIsOnLeftSide;
tempV2_3.subVectors(nextPoint, currentPoint);
tempV2_3.normalize();
const dot = Math.abs(normal1.dot(tempV2_3));
if (dot !== 0) {
const miterSide = strokeWidth2 / dot;
tempV2_3.multiplyScalar(-miterSide);
tempV2_4.subVectors(currentPoint, previousPoint);
tempV2_5.copy(tempV2_4).setLength(miterSide).add(tempV2_3);
innerPoint.copy(tempV2_5).negate();
const miterLength2 = tempV2_5.length();
const segmentLengthPrev = tempV2_4.length();
tempV2_4.divideScalar(segmentLengthPrev);
tempV2_6.subVectors(nextPoint, currentPoint);
const segmentLengthNext = tempV2_6.length();
tempV2_6.divideScalar(segmentLengthNext);
if (tempV2_4.dot(innerPoint) < segmentLengthPrev && tempV2_6.dot(innerPoint) < segmentLengthNext) {
innerSideModified = true;
}
outerPoint.copy(tempV2_5).add(currentPoint);
innerPoint.add(currentPoint);
isMiter = false;
if (innerSideModified) {
if (joinIsOnLeftSide) {
nextPointR.copy(innerPoint);
currentPointR.copy(innerPoint);
} else {
nextPointL.copy(innerPoint);
currentPointL.copy(innerPoint);
}
} else {
makeSegmentTriangles();
}
switch (style.strokeLineJoin) {
case "bevel":
makeSegmentWithBevelJoin(joinIsOnLeftSide, innerSideModified, u1);
break;
case "round":
createSegmentTrianglesWithMiddleSection(joinIsOnLeftSide, innerSideModified);
if (joinIsOnLeftSide) {
makeCircularSector(currentPoint, currentPointL, nextPointL, u1, 0);
} else {
makeCircularSector(currentPoint, nextPointR, currentPointR, u1, 1);
}
break;
case "miter":
case "miter-clip":
default:
const miterFraction = strokeWidth2 * style.strokeMiterLimit / miterLength2;
if (miterFraction < 1) {
if (style.strokeLineJoin !== "miter-clip") {
makeSegmentWithBevelJoin(joinIsOnLeftSide, innerSideModified, u1);
break;
} else {
createSegmentTrianglesWithMiddleSection(joinIsOnLeftSide, innerSideModified);
if (joinIsOnLeftSide) {
tempV2_6.subVectors(outerPoint, currentPointL).multiplyScalar(miterFraction).add(currentPointL);
tempV2_7.subVectors(outerPoint, nextPointL).multiplyScalar(miterFraction).add(nextPointL);
addVertex(currentPointL, u1, 0);
addVertex(tempV2_6, u1, 0);
addVertex(currentPoint, u1, 0.5);
addVertex(currentPoint, u1, 0.5);
addVertex(tempV2_6, u1, 0);
addVertex(tempV2_7, u1, 0);
addVertex(currentPoint, u1, 0.5);
addVertex(tempV2_7, u1, 0);
addVertex(nextPointL, u1, 0);
} else {
tempV2_6.subVectors(outerPoint, currentPointR).multiplyScalar(miterFraction).add(currentPointR);
tempV2_7.subVectors(outerPoint, nextPointR).multiplyScalar(miterFraction).add(nextPointR);
addVertex(currentPointR, u1, 1);
addVertex(tempV2_6, u1, 1);
addVertex(currentPoint, u1, 0.5);
addVertex(currentPoint, u1, 0.5);
addVertex(tempV2_6, u1, 1);
addVertex(tempV2_7, u1, 1);
addVertex(currentPoint, u1, 0.5);
addVertex(tempV2_7, u1, 1);
addVertex(nextPointR, u1, 1);
}
}
} else {
if (innerSideModified) {
if (joinIsOnLeftSide) {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(outerPoint, u1, 0);
addVertex(lastPointR, u0, 1);
addVertex(outerPoint, u1, 0);
addVertex(innerPoint, u1, 1);
} else {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(outerPoint, u1, 1);
addVertex(lastPointL, u0, 0);
addVertex(innerPoint, u1, 0);
addVertex(outerPoint, u1, 1);
}
if (joinIsOnLeftSide) {
nextPointL.copy(outerPoint);
} else {
nextPointR.copy(outerPoint);
}
} else {
if (joinIsOnLeftSide) {
addVertex(currentPointL, u1, 0);
addVertex(outerPoint, u1, 0);
addVertex(currentPoint, u1, 0.5);
addVertex(currentPoint, u1, 0.5);
addVertex(outerPoint, u1, 0);
addVertex(nextPointL, u1, 0);
} else {
addVertex(currentPointR, u1, 1);
addVertex(outerPoint, u1, 1);
addVertex(currentPoint, u1, 0.5);
addVertex(currentPoint, u1, 0.5);
addVertex(outerPoint, u1, 1);
addVertex(nextPointR, u1, 1);
}
}
isMiter = true;
}
break;
}
} else {
makeSegmentTriangles();
}
} else {
makeSegmentTriangles();
}
if (!isClosed && iPoint === numPoints - 1) {
addCapGeometry(points[0], point0L, point0R, joinIsOnLeftSide, true, u0);
}
u0 = u1;
previousPoint = currentPoint;
lastPointL.copy(nextPointL);
lastPointR.copy(nextPointR);
}
if (!isClosed) {
addCapGeometry(currentPoint, currentPointL, currentPointR, joinIsOnLeftSide, false, u1);
} else if (innerSideModified && vertices) {
let lastOuter = outerPoint;
let lastInner = innerPoint;
if (initialJoinIsOnLeftSide !== joinIsOnLeftSide) {
lastOuter = innerPoint;
lastInner = outerPoint;
}
if (joinIsOnLeftSide) {
if (isMiter || initialJoinIsOnLeftSide) {
lastInner.toArray(vertices, 0 * 3);
lastInner.toArray(vertices, 3 * 3);
if (isMiter) {
lastOuter.toArray(vertices, 1 * 3);
}
}
} else {
if (isMiter || !initialJoinIsOnLeftSide) {
lastInner.toArray(vertices, 1 * 3);
lastInner.toArray(vertices, 3 * 3);
if (isMiter) {
lastOuter.toArray(vertices, 0 * 3);
}
}
}
}
return numVertices;
function getNormal(p1, p2, result) {
result.subVectors(p2, p1);
return result.set(-result.y, result.x).normalize();
}
function addVertex(position, u, v) {
if (vertices) {
vertices[currentCoordinate] = position.x;
vertices[currentCoordinate + 1] = position.y;
vertices[currentCoordinate + 2] = 0;
if (normals) {
normals[currentCoordinate] = 0;
normals[currentCoordinate + 1] = 0;
normals[currentCoordinate + 2] = 1;
}
currentCoordinate += 3;
if (uvs) {
uvs[currentCoordinateUV] = u;
uvs[currentCoordinateUV + 1] = v;
currentCoordinateUV += 2;
}
}
numVertices += 3;
}
function makeCircularSector(center, p1, p2, u, v) {
tempV2_1.copy(p1).sub(center).normalize();
tempV2_2.copy(p2).sub(center).normalize();
let angle = Math.PI;
const dot = tempV2_1.dot(tempV2_2);
if (Math.abs(dot) < 1)
angle = Math.abs(Math.acos(dot));
angle /= arcDivisions;
tempV2_3.copy(p1);
for (let i = 0, il = arcDivisions - 1; i < il; i++) {
tempV2_4.copy(tempV2_3).rotateAround(center, angle);
addVertex(tempV2_3, u, v);
addVertex(tempV2_4, u, v);
addVertex(center, u, 0.5);
tempV2_3.copy(tempV2_4);
}
addVertex(tempV2_4, u, v);
addVertex(p2, u, v);
addVertex(center, u, 0.5);
}
function makeSegmentTriangles() {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(currentPointL, u1, 0);
addVertex(lastPointR, u0, 1);
addVertex(currentPointL, u1, 1);
addVertex(currentPointR, u1, 0);
}
function makeSegmentWithBevelJoin(joinIsOnLeftSide2, innerSideModified2, u) {
if (innerSideModified2) {
if (joinIsOnLeftSide2) {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(currentPointL, u1, 0);
addVertex(lastPointR, u0, 1);
addVertex(currentPointL, u1, 0);
addVertex(innerPoint, u1, 1);
addVertex(currentPointL, u, 0);
addVertex(nextPointL, u, 0);
addVertex(innerPoint, u, 0.5);
} else {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(currentPointR, u1, 1);
addVertex(lastPointL, u0, 0);
addVertex(innerPoint, u1, 0);
addVertex(currentPointR, u1, 1);
addVertex(currentPointR, u, 1);
addVertex(nextPointR, u, 0);
addVertex(innerPoint, u, 0.5);
}
} else {
if (joinIsOnLeftSide2) {
addVertex(currentPointL, u, 0);
addVertex(nextPointL, u, 0);
addVertex(currentPoint, u, 0.5);
} else {
addVertex(currentPointR, u, 1);
addVertex(nextPointR, u, 0);
addVertex(currentPoint, u, 0.5);
}
}
}
function createSegmentTrianglesWithMiddleSection(joinIsOnLeftSide2, innerSideModified2) {
if (innerSideModified2) {
if (joinIsOnLeftSide2) {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(currentPointL, u1, 0);
addVertex(lastPointR, u0, 1);
addVertex(currentPointL, u1, 0);
addVertex(innerPoint, u1, 1);
addVertex(currentPointL, u0, 0);
addVertex(currentPoint, u1, 0.5);
addVertex(innerPoint, u1, 1);
addVertex(currentPoint, u1, 0.5);
addVertex(nextPointL, u0, 0);
addVertex(innerPoint, u1, 1);
} else {
addVertex(lastPointR, u0, 1);
addVertex(lastPointL, u0, 0);
addVertex(currentPointR, u1, 1);
addVertex(lastPointL, u0, 0);
addVertex(innerPoint, u1, 0);
addVertex(currentPointR, u1, 1);
addVertex(currentPointR, u0, 1);
addVertex(innerPoint, u1, 0);
addVertex(currentPoint, u1, 0.5);
addVertex(currentPoint, u1, 0.5);
addVertex(innerPoint, u1, 0);
addVertex(nextPointR, u0, 1);
}
}
}
function addCapGeometry(center, p1, p2, joinIsOnLeftSide2, start, u) {
switch (style.strokeLineCap) {
case "round":
if (start) {
makeCircularSector(center, p2, p1, u, 0.5);
} else {
makeCircularSector(center, p1, p2, u, 0.5);
}
break;
case "square":
if (start) {
tempV2_1.subVectors(p1, center);
tempV2_2.set(tempV2_1.y, -tempV2_1.x);
tempV2_3.addVectors(tempV2_1, tempV2_2).add(center);
tempV2_4.subVectors(tempV2_2, tempV2_1).add(center);
if (joinIsOnLeftSide2) {
tempV2_3.toArray(vertices, 1 * 3);
tempV2_4.toArray(vertices, 0 * 3);
tempV2_4.toArray(vertices, 3 * 3);
} else {
tempV2_3.toArray(vertices, 1 * 3);
tempV2_3.toArray(vertices, 3 * 3);
tempV2_4.toArray(vertices, 0 * 3);
}
} else {
tempV2_1.subVectors(p2, center);
tempV2_2.set(tempV2_1.y, -tempV2_1.x);
tempV2_3.addVectors(tempV2_1, tempV2_2).add(center);
tempV2_4.subVectors(tempV2_2, tempV2_1).add(center);
const vl = vertices.length;
if (joinIsOnLeftSide2) {
tempV2_3.toArray(vertices, vl - 1 * 3);
tempV2_4.toArray(vertices, vl - 2 * 3);
tempV2_4.toArray(vertices, vl - 4 * 3);
} else {
tempV2_3.toArray(vertices, vl - 2 * 3);
tempV2_4.toArray(vertices, vl - 1 * 3);
tempV2_4.toArray(vertices, vl - 4 * 3);
}
}
break;
}
}
function removeDuplicatedPoints(points2) {
let dupPoints = false;
for (let i = 1, n = points2.length - 1; i < n; i++) {
if (points2[i].distanceTo(points2[i + 1]) < minDistance) {
dupPoints = true;
break;
}
}
if (!dupPoints)
return points2;
const newPoints = [];
newPoints.push(points2[0]);
for (let i = 1, n = points2.length - 1; i < n; i++) {
if (points2[i].distanceTo(points2[i + 1]) >= minDistance) {
newPoints.push(points2[i]);
}
}
newPoints.push(points2[points2.length - 1]);
return newPoints;
}
}
}
const cache = /* @__PURE__ */ new Map();
const loader = new SVGLoader();
var loadSVG = (url) => forceGet(cache, url, () => new Promise((resolve, reject) => {
increaseLoadingCount();
loader.load(url, (svg) => {
decreaseLoadingCount();
resolve(Object.freeze(svg));
}, handleProgress, () => {
decreaseLoadingCount();
reject();
});
}));
export { loadSVG as default };
//# sourceMappingURL=loadSVG.mjs.map