three-stdlib 2.29.8 → 2.29.9

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.
@@ -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 traverseChildNodes = true;
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
- traverseChildNodes = false;
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 usedNodeId = node.href.baseVal.substring(1);
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
- if (traverseChildNodes) {
106
- const nodes = node.childNodes;
107
- for (let i = 0; i < nodes.length; i++) {
108
- parseNode(nodes[i], style);
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.substr(1).trim();
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
- stylesheets[selectorList[j]] = Object.assign(stylesheets[selectorList[j]] || {}, stylesheet.style);
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 = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
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 = /(-?[\d\.?]+)[,|\s](-?[\d\.?]+)/g;
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.substr(0, openParPos);
875
- const array = parseFloats(transformText.substr(openParPos + 1, closeParPos - openParPos - 1));
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 = tx;
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 = -array[0] * Math.PI / 180;
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.identity().translate(-cx, -cy);
899
- tempTransform2.identity().rotate(angle);
902
+ tempTransform1.makeTranslation(-cx, -cy);
903
+ tempTransform2.makeRotation(angle);
900
904
  tempTransform3.multiplyMatrices(tempTransform2, tempTransform1);
901
- tempTransform1.identity().translate(cx, cy);
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
- const isRotated = isTransformRotated(m);
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
- curve.xRadius *= getTransformScaleX(m);
970
- curve.yRadius *= getTransformScaleY(m);
1018
+ if (isTransformSkewed(m)) {
1019
+ transfEllipseGeneric(curve);
1020
+ } else {
1021
+ transfEllipseNoSkew(curve);
1022
+ }
971
1023
  }
972
1024
  }
973
1025
  }
974
1026
  }
975
- function isTransformRotated(m) {
976
- return m.elements[1] !== 0 || m.elements[3] !== 0;
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 identifier2 = stack[i2];
1286
+ const identifier = stack[i2];
1186
1287
  if (isHole) {
1187
- lastCWValue = allPaths[identifier2].isCW;
1288
+ lastCWValue = allPaths[identifier].isCW;
1188
1289
  isHole = false;
1189
- isHoleFor = identifier2;
1190
- } else if (lastCWValue !== allPaths[identifier2].isCW) {
1191
- lastCWValue = allPaths[identifier2].isCW;
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: 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(p, simplePaths, scanlineMinX, scanlineMaxX, shapePath.userData.style.fillRule)
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 !== 0) {
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, 1);
1575
- addVertex(currentPointR, u1, 0);
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(nextPointR, u, 0);
1598
- addVertex(innerPoint, u, 0.5);
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
- tempV2_3.toArray(vertices, vl - 2 * 3);
1679
- tempV2_4.toArray(vertices, vl - 1 * 3);
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
  }