three-stdlib 2.29.8 → 2.29.9
Sign up to get free protection for your applications and to get access to all the features.
- package/loaders/SVGLoader.cjs +158 -50
- package/loaders/SVGLoader.cjs.map +1 -1
- package/loaders/SVGLoader.js +158 -50
- package/loaders/SVGLoader.js.map +1 -1
- package/package.json +1 -1
package/loaders/SVGLoader.cjs
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
3
3
|
const THREE = require("three");
|
4
|
+
const COLOR_SPACE_SVG = "srgb";
|
4
5
|
class SVGLoader extends THREE.Loader {
|
5
6
|
constructor(manager) {
|
6
7
|
super(manager);
|
@@ -37,10 +38,11 @@ class SVGLoader extends THREE.Loader {
|
|
37
38
|
if (node.nodeType !== 1)
|
38
39
|
return;
|
39
40
|
const transform = getNodeTransform(node);
|
40
|
-
let
|
41
|
+
let isDefsNode = false;
|
41
42
|
let path = null;
|
42
43
|
switch (node.nodeName) {
|
43
44
|
case "svg":
|
45
|
+
style = parseStyle(node, style);
|
44
46
|
break;
|
45
47
|
case "style":
|
46
48
|
parseCSSStylesheet(node);
|
@@ -78,14 +80,12 @@ class SVGLoader extends THREE.Loader {
|
|
78
80
|
path = parseLineNode(node);
|
79
81
|
break;
|
80
82
|
case "defs":
|
81
|
-
|
82
|
-
break;
|
83
|
-
case "mask":
|
84
|
-
traverseChildNodes = false;
|
83
|
+
isDefsNode = true;
|
85
84
|
break;
|
86
85
|
case "use":
|
87
86
|
style = parseStyle(node, style);
|
88
|
-
const
|
87
|
+
const href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href") || "";
|
88
|
+
const usedNodeId = href.substring(1);
|
89
89
|
const usedNode = node.viewportElement.getElementById(usedNodeId);
|
90
90
|
if (usedNode) {
|
91
91
|
parseNode(usedNode, style);
|
@@ -96,17 +96,19 @@ class SVGLoader extends THREE.Loader {
|
|
96
96
|
}
|
97
97
|
if (path) {
|
98
98
|
if (style.fill !== void 0 && style.fill !== "none") {
|
99
|
-
path.color.setStyle(style.fill);
|
99
|
+
path.color.setStyle(style.fill, COLOR_SPACE_SVG);
|
100
100
|
}
|
101
101
|
transformPath(path, currentTransform);
|
102
102
|
paths.push(path);
|
103
103
|
path.userData = { node, style };
|
104
104
|
}
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
105
|
+
const childNodes = node.childNodes;
|
106
|
+
for (let i = 0; i < childNodes.length; i++) {
|
107
|
+
const node2 = childNodes[i];
|
108
|
+
if (isDefsNode && node2.nodeName !== "style" && node2.nodeName !== "defs") {
|
109
|
+
continue;
|
109
110
|
}
|
111
|
+
parseNode(node2, style);
|
110
112
|
}
|
111
113
|
if (transform) {
|
112
114
|
transformStack.pop();
|
@@ -125,11 +127,13 @@ class SVGLoader extends THREE.Loader {
|
|
125
127
|
let isFirstPoint = true;
|
126
128
|
let doSetFirstPoint = false;
|
127
129
|
const d = node.getAttribute("d");
|
130
|
+
if (d === "" || d === "none")
|
131
|
+
return null;
|
128
132
|
const commands = d.match(/[a-df-z][^a-df-z]*/gi);
|
129
133
|
for (let i = 0, l = commands.length; i < l; i++) {
|
130
134
|
const command = commands[i];
|
131
135
|
const type = command.charAt(0);
|
132
|
-
const data2 = command.
|
136
|
+
const data2 = command.slice(1).trim();
|
133
137
|
if (isFirstPoint === true) {
|
134
138
|
doSetFirstPoint = true;
|
135
139
|
isFirstPoint = false;
|
@@ -442,7 +446,8 @@ class SVGLoader extends THREE.Loader {
|
|
442
446
|
continue;
|
443
447
|
const selectorList = stylesheet.selectorText.split(/,/gm).filter(Boolean).map((i2) => i2.trim());
|
444
448
|
for (let j = 0; j < selectorList.length; j++) {
|
445
|
-
|
449
|
+
const definitions = Object.fromEntries(Object.entries(stylesheet.style).filter(([, v]) => v !== ""));
|
450
|
+
stylesheets[selectorList[j]] = Object.assign(stylesheets[selectorList[j]] || {}, definitions);
|
446
451
|
}
|
447
452
|
}
|
448
453
|
}
|
@@ -530,7 +535,7 @@ class SVGLoader extends THREE.Loader {
|
|
530
535
|
}
|
531
536
|
index++;
|
532
537
|
}
|
533
|
-
const regex = /(
|
538
|
+
const regex = /([+-]?\d*\.?\d+(?:e[+-]?\d+)?)(?:,|\s)([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/g;
|
534
539
|
const path = new THREE.ShapePath();
|
535
540
|
let index = 0;
|
536
541
|
node.getAttribute("points").replace(regex, iterator);
|
@@ -548,7 +553,7 @@ class SVGLoader extends THREE.Loader {
|
|
548
553
|
}
|
549
554
|
index++;
|
550
555
|
}
|
551
|
-
const regex = /(
|
556
|
+
const regex = /([+-]?\d*\.?\d+(?:e[+-]?\d+)?)(?:,|\s)([+-]?\d*\.?\d+(?:e[+-]?\d+)?)/g;
|
552
557
|
const path = new THREE.ShapePath();
|
553
558
|
let index = 0;
|
554
559
|
node.getAttribute("points").replace(regex, iterator);
|
@@ -600,13 +605,12 @@ class SVGLoader extends THREE.Loader {
|
|
600
605
|
stylesheetStyles = Object.assign(stylesheetStyles, stylesheets["#" + node.getAttribute("id")]);
|
601
606
|
}
|
602
607
|
function addStyle(svgName, jsName, adjustFunction) {
|
603
|
-
if (adjustFunction === void 0)
|
608
|
+
if (adjustFunction === void 0)
|
604
609
|
adjustFunction = function copy(v) {
|
605
610
|
if (v.startsWith("url"))
|
606
611
|
console.warn("SVGLoader: url access in attributes is not implemented.");
|
607
612
|
return v;
|
608
613
|
};
|
609
|
-
}
|
610
614
|
if (node.hasAttribute(svgName))
|
611
615
|
style[jsName] = adjustFunction(node.getAttribute(svgName));
|
612
616
|
if (stylesheetStyles[svgName])
|
@@ -871,14 +875,14 @@ class SVGLoader extends THREE.Loader {
|
|
871
875
|
const openParPos = transformText.indexOf("(");
|
872
876
|
const closeParPos = transformText.length;
|
873
877
|
if (openParPos > 0 && openParPos < closeParPos) {
|
874
|
-
const transformType = transformText.
|
875
|
-
const array = parseFloats(transformText.
|
878
|
+
const transformType = transformText.slice(0, openParPos);
|
879
|
+
const array = parseFloats(transformText.slice(openParPos + 1));
|
876
880
|
currentTransform2.identity();
|
877
881
|
switch (transformType) {
|
878
882
|
case "translate":
|
879
883
|
if (array.length >= 1) {
|
880
884
|
const tx = array[0];
|
881
|
-
let ty =
|
885
|
+
let ty = 0;
|
882
886
|
if (array.length >= 2) {
|
883
887
|
ty = array[1];
|
884
888
|
}
|
@@ -890,15 +894,15 @@ class SVGLoader extends THREE.Loader {
|
|
890
894
|
let angle = 0;
|
891
895
|
let cx = 0;
|
892
896
|
let cy = 0;
|
893
|
-
angle =
|
897
|
+
angle = array[0] * Math.PI / 180;
|
894
898
|
if (array.length >= 3) {
|
895
899
|
cx = array[1];
|
896
900
|
cy = array[2];
|
897
901
|
}
|
898
|
-
tempTransform1.
|
899
|
-
tempTransform2.
|
902
|
+
tempTransform1.makeTranslation(-cx, -cy);
|
903
|
+
tempTransform2.makeRotation(angle);
|
900
904
|
tempTransform3.multiplyMatrices(tempTransform2, tempTransform1);
|
901
|
-
tempTransform1.
|
905
|
+
tempTransform1.makeTranslation(cx, cy);
|
902
906
|
currentTransform2.multiplyMatrices(tempTransform1, tempTransform3);
|
903
907
|
}
|
904
908
|
break;
|
@@ -939,7 +943,55 @@ class SVGLoader extends THREE.Loader {
|
|
939
943
|
tempV3.set(v2.x, v2.y, 1).applyMatrix3(m);
|
940
944
|
v2.set(tempV3.x, tempV3.y);
|
941
945
|
}
|
942
|
-
|
946
|
+
function transfEllipseGeneric(curve) {
|
947
|
+
const a = curve.xRadius;
|
948
|
+
const b = curve.yRadius;
|
949
|
+
const cosTheta = Math.cos(curve.aRotation);
|
950
|
+
const sinTheta = Math.sin(curve.aRotation);
|
951
|
+
const v1 = new THREE.Vector3(a * cosTheta, a * sinTheta, 0);
|
952
|
+
const v2 = new THREE.Vector3(-b * sinTheta, b * cosTheta, 0);
|
953
|
+
const f1 = v1.applyMatrix3(m);
|
954
|
+
const f2 = v2.applyMatrix3(m);
|
955
|
+
const mF = tempTransform0.set(f1.x, f2.x, 0, f1.y, f2.y, 0, 0, 0, 1);
|
956
|
+
const mFInv = tempTransform1.copy(mF).invert();
|
957
|
+
const mFInvT = tempTransform2.copy(mFInv).transpose();
|
958
|
+
const mQ = mFInvT.multiply(mFInv);
|
959
|
+
const mQe = mQ.elements;
|
960
|
+
const ed = eigenDecomposition(mQe[0], mQe[1], mQe[4]);
|
961
|
+
const rt1sqrt = Math.sqrt(ed.rt1);
|
962
|
+
const rt2sqrt = Math.sqrt(ed.rt2);
|
963
|
+
curve.xRadius = 1 / rt1sqrt;
|
964
|
+
curve.yRadius = 1 / rt2sqrt;
|
965
|
+
curve.aRotation = Math.atan2(ed.sn, ed.cs);
|
966
|
+
const isFullEllipse = (curve.aEndAngle - curve.aStartAngle) % (2 * Math.PI) < Number.EPSILON;
|
967
|
+
if (!isFullEllipse) {
|
968
|
+
const mDsqrt = tempTransform1.set(rt1sqrt, 0, 0, 0, rt2sqrt, 0, 0, 0, 1);
|
969
|
+
const mRT = tempTransform2.set(ed.cs, ed.sn, 0, -ed.sn, ed.cs, 0, 0, 0, 1);
|
970
|
+
const mDRF = mDsqrt.multiply(mRT).multiply(mF);
|
971
|
+
const transformAngle = (phi) => {
|
972
|
+
const { x: cosR, y: sinR } = new THREE.Vector3(Math.cos(phi), Math.sin(phi), 0).applyMatrix3(mDRF);
|
973
|
+
return Math.atan2(sinR, cosR);
|
974
|
+
};
|
975
|
+
curve.aStartAngle = transformAngle(curve.aStartAngle);
|
976
|
+
curve.aEndAngle = transformAngle(curve.aEndAngle);
|
977
|
+
if (isTransformFlipped(m)) {
|
978
|
+
curve.aClockwise = !curve.aClockwise;
|
979
|
+
}
|
980
|
+
}
|
981
|
+
}
|
982
|
+
function transfEllipseNoSkew(curve) {
|
983
|
+
const sx = getTransformScaleX(m);
|
984
|
+
const sy = getTransformScaleY(m);
|
985
|
+
curve.xRadius *= sx;
|
986
|
+
curve.yRadius *= sy;
|
987
|
+
const theta = sx > Number.EPSILON ? Math.atan2(m.elements[1], m.elements[0]) : Math.atan2(-m.elements[3], m.elements[4]);
|
988
|
+
curve.aRotation += theta;
|
989
|
+
if (isTransformFlipped(m)) {
|
990
|
+
curve.aStartAngle *= -1;
|
991
|
+
curve.aEndAngle *= -1;
|
992
|
+
curve.aClockwise = !curve.aClockwise;
|
993
|
+
}
|
994
|
+
}
|
943
995
|
const subPaths = path.subPaths;
|
944
996
|
for (let i = 0, n = subPaths.length; i < n; i++) {
|
945
997
|
const subPath = subPaths[i];
|
@@ -959,21 +1011,31 @@ class SVGLoader extends THREE.Loader {
|
|
959
1011
|
transfVec2(curve.v1);
|
960
1012
|
transfVec2(curve.v2);
|
961
1013
|
} else if (curve.isEllipseCurve) {
|
962
|
-
if (isRotated) {
|
963
|
-
console.warn("SVGLoader: Elliptic arc or ellipse rotation or skewing is not implemented.");
|
964
|
-
}
|
965
1014
|
tempV2.set(curve.aX, curve.aY);
|
966
1015
|
transfVec2(tempV2);
|
967
1016
|
curve.aX = tempV2.x;
|
968
1017
|
curve.aY = tempV2.y;
|
969
|
-
|
970
|
-
|
1018
|
+
if (isTransformSkewed(m)) {
|
1019
|
+
transfEllipseGeneric(curve);
|
1020
|
+
} else {
|
1021
|
+
transfEllipseNoSkew(curve);
|
1022
|
+
}
|
971
1023
|
}
|
972
1024
|
}
|
973
1025
|
}
|
974
1026
|
}
|
975
|
-
function
|
976
|
-
|
1027
|
+
function isTransformFlipped(m) {
|
1028
|
+
const te = m.elements;
|
1029
|
+
return te[0] * te[4] - te[1] * te[3] < 0;
|
1030
|
+
}
|
1031
|
+
function isTransformSkewed(m) {
|
1032
|
+
const te = m.elements;
|
1033
|
+
const basisDot = te[0] * te[3] + te[1] * te[4];
|
1034
|
+
if (basisDot === 0)
|
1035
|
+
return false;
|
1036
|
+
const sx = getTransformScaleX(m);
|
1037
|
+
const sy = getTransformScaleY(m);
|
1038
|
+
return Math.abs(basisDot / (sx * sy)) > Number.EPSILON;
|
977
1039
|
}
|
978
1040
|
function getTransformScaleX(m) {
|
979
1041
|
const te = m.elements;
|
@@ -983,6 +1045,45 @@ class SVGLoader extends THREE.Loader {
|
|
983
1045
|
const te = m.elements;
|
984
1046
|
return Math.sqrt(te[3] * te[3] + te[4] * te[4]);
|
985
1047
|
}
|
1048
|
+
function eigenDecomposition(A, B, C) {
|
1049
|
+
let rt1, rt2, cs, sn, t;
|
1050
|
+
const sm = A + C;
|
1051
|
+
const df = A - C;
|
1052
|
+
const rt = Math.sqrt(df * df + 4 * B * B);
|
1053
|
+
if (sm > 0) {
|
1054
|
+
rt1 = 0.5 * (sm + rt);
|
1055
|
+
t = 1 / rt1;
|
1056
|
+
rt2 = A * t * C - B * t * B;
|
1057
|
+
} else if (sm < 0) {
|
1058
|
+
rt2 = 0.5 * (sm - rt);
|
1059
|
+
} else {
|
1060
|
+
rt1 = 0.5 * rt;
|
1061
|
+
rt2 = -0.5 * rt;
|
1062
|
+
}
|
1063
|
+
if (df > 0) {
|
1064
|
+
cs = df + rt;
|
1065
|
+
} else {
|
1066
|
+
cs = df - rt;
|
1067
|
+
}
|
1068
|
+
if (Math.abs(cs) > 2 * Math.abs(B)) {
|
1069
|
+
t = -2 * B / cs;
|
1070
|
+
sn = 1 / Math.sqrt(1 + t * t);
|
1071
|
+
cs = t * sn;
|
1072
|
+
} else if (Math.abs(B) === 0) {
|
1073
|
+
cs = 1;
|
1074
|
+
sn = 0;
|
1075
|
+
} else {
|
1076
|
+
t = -0.5 * cs / B;
|
1077
|
+
cs = 1 / Math.sqrt(1 + t * t);
|
1078
|
+
sn = t * cs;
|
1079
|
+
}
|
1080
|
+
if (df > 0) {
|
1081
|
+
t = cs;
|
1082
|
+
cs = -sn;
|
1083
|
+
sn = t;
|
1084
|
+
}
|
1085
|
+
return { rt1, rt2, cs, sn };
|
1086
|
+
}
|
986
1087
|
const paths = [];
|
987
1088
|
const stylesheets = {};
|
988
1089
|
const transformStack = [];
|
@@ -1182,13 +1283,13 @@ class SVGLoader extends THREE.Loader {
|
|
1182
1283
|
let isHoleFor = null;
|
1183
1284
|
let lastCWValue = null;
|
1184
1285
|
for (let i2 = 0; i2 < stack.length; i2++) {
|
1185
|
-
const
|
1286
|
+
const identifier = stack[i2];
|
1186
1287
|
if (isHole) {
|
1187
|
-
lastCWValue = allPaths[
|
1288
|
+
lastCWValue = allPaths[identifier].isCW;
|
1188
1289
|
isHole = false;
|
1189
|
-
isHoleFor =
|
1190
|
-
} else if (lastCWValue !== allPaths[
|
1191
|
-
lastCWValue = allPaths[
|
1290
|
+
isHoleFor = identifier;
|
1291
|
+
} else if (lastCWValue !== allPaths[identifier].isCW) {
|
1292
|
+
lastCWValue = allPaths[identifier].isCW;
|
1192
1293
|
isHole = true;
|
1193
1294
|
}
|
1194
1295
|
}
|
@@ -1197,7 +1298,6 @@ class SVGLoader extends THREE.Loader {
|
|
1197
1298
|
console.warn('fill-rule: "' + _fillRule + '" is currently not implemented.');
|
1198
1299
|
}
|
1199
1300
|
}
|
1200
|
-
let identifier = 0;
|
1201
1301
|
let scanlineMinX = BIGNUMBER;
|
1202
1302
|
let scanlineMaxX = -BIGNUMBER;
|
1203
1303
|
let simplePaths = shapePath.subPaths.map((p) => {
|
@@ -1231,13 +1331,22 @@ class SVGLoader extends THREE.Loader {
|
|
1231
1331
|
curves: p.curves,
|
1232
1332
|
points,
|
1233
1333
|
isCW: THREE.ShapeUtils.isClockWise(points),
|
1234
|
-
identifier:
|
1334
|
+
identifier: -1,
|
1235
1335
|
boundingBox: new THREE.Box2(new THREE.Vector2(minX, minY), new THREE.Vector2(maxX, maxY))
|
1236
1336
|
};
|
1237
1337
|
});
|
1238
1338
|
simplePaths = simplePaths.filter((sp) => sp.points.length > 1);
|
1339
|
+
for (let identifier = 0; identifier < simplePaths.length; identifier++) {
|
1340
|
+
simplePaths[identifier].identifier = identifier;
|
1341
|
+
}
|
1239
1342
|
const isAHole = simplePaths.map(
|
1240
|
-
(p) => isHoleTo(
|
1343
|
+
(p) => isHoleTo(
|
1344
|
+
p,
|
1345
|
+
simplePaths,
|
1346
|
+
scanlineMinX,
|
1347
|
+
scanlineMaxX,
|
1348
|
+
shapePath.userData ? shapePath.userData.style.fillRule : void 0
|
1349
|
+
)
|
1241
1350
|
);
|
1242
1351
|
const shapesToReturn = [];
|
1243
1352
|
simplePaths.forEach((p) => {
|
@@ -1333,9 +1442,8 @@ class SVGLoader extends THREE.Loader {
|
|
1333
1442
|
if (iPoint === numPoints - 1) {
|
1334
1443
|
if (isClosed) {
|
1335
1444
|
nextPoint = points[1];
|
1336
|
-
} else
|
1445
|
+
} else
|
1337
1446
|
nextPoint = void 0;
|
1338
|
-
}
|
1339
1447
|
} else {
|
1340
1448
|
nextPoint = points[iPoint + 1];
|
1341
1449
|
}
|
@@ -1361,7 +1469,7 @@ class SVGLoader extends THREE.Loader {
|
|
1361
1469
|
tempV2_3.subVectors(nextPoint, currentPoint);
|
1362
1470
|
tempV2_3.normalize();
|
1363
1471
|
const dot = Math.abs(normal1.dot(tempV2_3));
|
1364
|
-
if (dot
|
1472
|
+
if (dot > Number.EPSILON) {
|
1365
1473
|
const miterSide = strokeWidth2 / dot;
|
1366
1474
|
tempV2_3.multiplyScalar(-miterSide);
|
1367
1475
|
tempV2_4.subVectors(currentPoint, previousPoint);
|
@@ -1571,8 +1679,8 @@ class SVGLoader extends THREE.Loader {
|
|
1571
1679
|
addVertex(lastPointL, u0, 0);
|
1572
1680
|
addVertex(currentPointL, u1, 0);
|
1573
1681
|
addVertex(lastPointR, u0, 1);
|
1574
|
-
addVertex(currentPointL, u1,
|
1575
|
-
addVertex(currentPointR, u1,
|
1682
|
+
addVertex(currentPointL, u1, 0);
|
1683
|
+
addVertex(currentPointR, u1, 1);
|
1576
1684
|
}
|
1577
1685
|
function makeSegmentWithBevelJoin(joinIsOnLeftSide2, innerSideModified2, u) {
|
1578
1686
|
if (innerSideModified2) {
|
@@ -1594,8 +1702,8 @@ class SVGLoader extends THREE.Loader {
|
|
1594
1702
|
addVertex(innerPoint, u1, 0);
|
1595
1703
|
addVertex(currentPointR, u1, 1);
|
1596
1704
|
addVertex(currentPointR, u, 1);
|
1597
|
-
addVertex(
|
1598
|
-
addVertex(
|
1705
|
+
addVertex(innerPoint, u, 0);
|
1706
|
+
addVertex(nextPointR, u, 1);
|
1599
1707
|
}
|
1600
1708
|
} else {
|
1601
1709
|
if (joinIsOnLeftSide2) {
|
@@ -1661,7 +1769,7 @@ class SVGLoader extends THREE.Loader {
|
|
1661
1769
|
tempV2_4.toArray(vertices, 3 * 3);
|
1662
1770
|
} else {
|
1663
1771
|
tempV2_3.toArray(vertices, 1 * 3);
|
1664
|
-
tempV2_3.toArray(vertices, 3 * 3);
|
1772
|
+
uvs[3 * 2 + 1] === 1 ? tempV2_4.toArray(vertices, 3 * 3) : tempV2_3.toArray(vertices, 3 * 3);
|
1665
1773
|
tempV2_4.toArray(vertices, 0 * 3);
|
1666
1774
|
}
|
1667
1775
|
} else {
|
@@ -1675,8 +1783,8 @@ class SVGLoader extends THREE.Loader {
|
|
1675
1783
|
tempV2_4.toArray(vertices, vl - 2 * 3);
|
1676
1784
|
tempV2_4.toArray(vertices, vl - 4 * 3);
|
1677
1785
|
} else {
|
1678
|
-
|
1679
|
-
|
1786
|
+
tempV2_4.toArray(vertices, vl - 2 * 3);
|
1787
|
+
tempV2_3.toArray(vertices, vl - 1 * 3);
|
1680
1788
|
tempV2_4.toArray(vertices, vl - 4 * 3);
|
1681
1789
|
}
|
1682
1790
|
}
|