@vvfx/lottie2ir 0.0.1-beta.10 → 0.0.1-beta.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Description: Lottie to Animation IR converter
4
4
  * Author: Ant Group CO., Ltd.
5
5
  * Contributors: 澄弈
6
- * Version: v0.0.1-beta.10
6
+ * Version: v0.0.1-beta.12
7
7
  */
8
8
 
9
9
  'use strict';
@@ -232,41 +232,6 @@ function resolveLottieAssetPath(asset) {
232
232
  });
233
233
  }
234
234
 
235
- function resolveDiagnosticAction(code) {
236
- switch(code){
237
- case 'invalid-stretch-ratio':
238
- case 'separated-position-fallback':
239
- case 'animated-anchor-fallback':
240
- case 'animated-gradient-fallback':
241
- case 'missing-font':
242
- return 'approximated';
243
- case 'missing-image-asset':
244
- case 'unsupported-mask':
245
- case 'unsupported-track-matte':
246
- case 'unsupported-shape-feature':
247
- case 'unsupported-shape-type':
248
- case 'missing-text-data':
249
- return 'dropped';
250
- case 'unsupported-layer-type':
251
- return 'unsupported';
252
- }
253
- }
254
- /** Creates a source-scoped warning for a normalized, approximated, or dropped Lottie feature. */ function createLottieDiagnostic(options) {
255
- var _ref;
256
- var _options_featureKinds;
257
- return _extends({
258
- code: "LOTTIE_" + options.code.replaceAll('-', '_').toUpperCase(),
259
- severity: 'warning',
260
- action: resolveDiagnosticAction(options.code),
261
- path: '$.layers'
262
- }, options.layerInd != null && {
263
- sourceId: String(options.layerInd)
264
- }, {
265
- feature: (_ref = (_options_featureKinds = options.featureKinds) == null ? void 0 : _options_featureKinds.join(',')) != null ? _ref : options.code,
266
- message: options.message
267
- });
268
- }
269
-
270
235
  function isFiniteNumber(value) {
271
236
  return typeof value === 'number' && Number.isFinite(value);
272
237
  }
@@ -509,6 +474,257 @@ function mergeSeparatedPosition(pRecord) {
509
474
  };
510
475
  }
511
476
 
477
+ function hasAnimatedAnchor(layer) {
478
+ var property = getPropertyRecord(layer, 'a');
479
+ return property != null && isKeyframedProperty(property);
480
+ }
481
+ function toStaticAnchor(layer) {
482
+ var _ref;
483
+ var _property_keyframes_;
484
+ var property = toAnimatedProperty(getPropertyRecord(layer, 'a'), readVector3);
485
+ if (property == null || property.type === 'static') {
486
+ return property;
487
+ }
488
+ return {
489
+ type: 'static',
490
+ value: (_ref = (_property_keyframes_ = property.keyframes[0]) == null ? void 0 : _property_keyframes_.value) != null ? _ref : [
491
+ 0,
492
+ 0,
493
+ 0
494
+ ]
495
+ };
496
+ }
497
+ function readVector3(value) {
498
+ var _values_, _values_1, _values_2;
499
+ var values = toFiniteNumberArray(value);
500
+ if (values == null) {
501
+ return undefined;
502
+ }
503
+ return [
504
+ (_values_ = values[0]) != null ? _values_ : 0,
505
+ (_values_1 = values[1]) != null ? _values_1 : 0,
506
+ (_values_2 = values[2]) != null ? _values_2 : 0
507
+ ];
508
+ }
509
+ function readSpatialTangent(value) {
510
+ var values = toFiniteNumberArray(value);
511
+ if ((values == null ? void 0 : values.length) === 2) {
512
+ return [
513
+ values[0],
514
+ values[1]
515
+ ];
516
+ }
517
+ if ((values == null ? void 0 : values.length) === 3) {
518
+ return [
519
+ values[0],
520
+ values[1],
521
+ values[2]
522
+ ];
523
+ }
524
+ return undefined;
525
+ }
526
+ function readScaleVector(value) {
527
+ var _values_, _values_1, _values_2;
528
+ var _toFiniteNumberArray;
529
+ var values = (_toFiniteNumberArray = toFiniteNumberArray(value)) == null ? void 0 : _toFiniteNumberArray.map(function(item) {
530
+ return item / 100;
531
+ });
532
+ if (values == null) {
533
+ return undefined;
534
+ }
535
+ return [
536
+ (_values_ = values[0]) != null ? _values_ : 1,
537
+ (_values_1 = values[1]) != null ? _values_1 : 1,
538
+ (_values_2 = values[2]) != null ? _values_2 : 1
539
+ ];
540
+ }
541
+ function readOpacityNumber(value) {
542
+ var valueNumber = toFirstNumber(value);
543
+ return valueNumber != null ? valueNumber / 100 : undefined;
544
+ }
545
+ function getPropertyRecord(layer, key) {
546
+ var ks = asRecord(layer.ks);
547
+ var property = asRecord(ks == null ? void 0 : ks[key]);
548
+ if (property == null || !('k' in property)) {
549
+ return undefined;
550
+ }
551
+ return property;
552
+ }
553
+ function readBezierHandle(value) {
554
+ var record = asRecord(value);
555
+ var x = toFirstNumber(record == null ? void 0 : record['x']);
556
+ var y = toFirstNumber(record == null ? void 0 : record['y']);
557
+ if (x == null || y == null) {
558
+ return undefined;
559
+ }
560
+ return {
561
+ x: x,
562
+ y: y
563
+ };
564
+ }
565
+ function readKeyframes(property, reader) {
566
+ var rawKeyframes = property['k'];
567
+ if (!Array.isArray(rawKeyframes)) {
568
+ return undefined;
569
+ }
570
+ var keyframes = [];
571
+ var previousEndValue;
572
+ // Lottie stores segment tangents on the start keyframe; IR assigns them to their endpoints.
573
+ var pendingInTangent;
574
+ var pendingSpatialIn;
575
+ for(var _iterator = _create_for_of_iterator_helper_loose(rawKeyframes), _step; !(_step = _iterator()).done;){
576
+ var rawKeyframe = _step.value;
577
+ var keyframeRecord = asRecord(rawKeyframe);
578
+ var t = keyframeRecord == null ? void 0 : keyframeRecord['t'];
579
+ if (!isFiniteNumber(t)) {
580
+ continue;
581
+ }
582
+ // Terminal keyframes inherit the preceding `e` value.
583
+ var value = reader(keyframeRecord == null ? void 0 : keyframeRecord['s']);
584
+ if (value == null) {
585
+ if (previousEndValue != null) {
586
+ value = previousEndValue;
587
+ } else {
588
+ continue;
589
+ }
590
+ }
591
+ var endValue = reader(keyframeRecord == null ? void 0 : keyframeRecord['e']);
592
+ previousEndValue = endValue != null ? endValue : value;
593
+ var recordInTangent = readBezierHandle(keyframeRecord == null ? void 0 : keyframeRecord['i']);
594
+ var outTangent = readBezierHandle(keyframeRecord == null ? void 0 : keyframeRecord['o']);
595
+ var spatialOut = readSpatialTangent(keyframeRecord == null ? void 0 : keyframeRecord['to']);
596
+ var recordSpatialIn = readSpatialTangent(keyframeRecord == null ? void 0 : keyframeRecord['ti']);
597
+ var inTangent = pendingInTangent;
598
+ var spatialIn = pendingSpatialIn;
599
+ keyframes.push(_extends({
600
+ frame: t,
601
+ value: value
602
+ }, endValue != null && {
603
+ endValue: endValue
604
+ }, (keyframeRecord == null ? void 0 : keyframeRecord['h']) === 1 && {
605
+ hold: true
606
+ }, inTangent != null && {
607
+ inTangent: inTangent
608
+ }, outTangent != null && {
609
+ outTangent: outTangent
610
+ }, spatialOut != null && {
611
+ spatialOut: spatialOut
612
+ }, spatialIn != null && {
613
+ spatialIn: spatialIn
614
+ }));
615
+ // Incoming tangents belong to the next IR keyframe.
616
+ pendingInTangent = recordInTangent;
617
+ pendingSpatialIn = recordSpatialIn;
618
+ }
619
+ return keyframes.length > 0 ? keyframes : undefined;
620
+ }
621
+ function toAnimatedProperty(property, reader) {
622
+ if (property == null) {
623
+ return undefined;
624
+ }
625
+ if (isKeyframedProperty(property)) {
626
+ var _ref;
627
+ var _keyframes_;
628
+ var keyframes = readKeyframes(property, reader);
629
+ if (keyframes != null && keyframes.length >= 2) {
630
+ return {
631
+ type: 'keyframed',
632
+ keyframes: keyframes
633
+ };
634
+ }
635
+ var staticValue = (_ref = keyframes == null ? void 0 : (_keyframes_ = keyframes[0]) == null ? void 0 : _keyframes_.value) != null ? _ref : reader(property['k']);
636
+ return staticValue != null ? {
637
+ type: 'static',
638
+ value: staticValue
639
+ } : undefined;
640
+ }
641
+ var value = reader(property['k']);
642
+ return value != null ? {
643
+ type: 'static',
644
+ value: value
645
+ } : undefined;
646
+ }
647
+ /**
648
+ * Converts Lottie transform properties and keyframes to IR units and tangent ownership.
649
+ *
650
+ * Scale and opacity percentages become normalized factors. Animated anchors use their first keyframe because IR anchors
651
+ * are static.
652
+ */ function convertLottieTransform(layer) {
653
+ var _getPropertyRecord;
654
+ var transform = {};
655
+ var anchor = toStaticAnchor(layer);
656
+ var positionProperty = getPropertyRecord(layer, 'p');
657
+ var position = toAnimatedProperty(positionProperty, readVector3);
658
+ var scale = toAnimatedProperty(getPropertyRecord(layer, 's'), readScaleVector);
659
+ var rotationZ = toAnimatedProperty((_getPropertyRecord = getPropertyRecord(layer, 'rz')) != null ? _getPropertyRecord : getPropertyRecord(layer, 'r'), toFirstNumber);
660
+ var rotationX = toAnimatedProperty(getPropertyRecord(layer, 'rx'), toFirstNumber);
661
+ var rotationY = toAnimatedProperty(getPropertyRecord(layer, 'ry'), toFirstNumber);
662
+ var opacity = toAnimatedProperty(getPropertyRecord(layer, 'o'), readOpacityNumber);
663
+ if (anchor != null) {
664
+ transform.anchor = anchor;
665
+ }
666
+ if (position != null) {
667
+ transform.position = position;
668
+ }
669
+ if (scale != null) {
670
+ transform.scale = scale;
671
+ }
672
+ if (rotationX != null || rotationY != null || rotationZ != null) {
673
+ var rotation = {};
674
+ if (rotationX != null) {
675
+ rotation.x = rotationX;
676
+ }
677
+ if (rotationY != null) {
678
+ rotation.y = rotationY;
679
+ }
680
+ if (rotationZ != null) {
681
+ rotation.z = rotationZ;
682
+ }
683
+ transform.rotation = rotation;
684
+ }
685
+ if (opacity != null) {
686
+ transform.opacity = opacity;
687
+ }
688
+ return transform;
689
+ }
690
+
691
+ function resolveDiagnosticAction(code) {
692
+ switch(code){
693
+ case 'invalid-stretch-ratio':
694
+ case 'separated-position-fallback':
695
+ case 'animated-anchor-fallback':
696
+ case 'animated-gradient-fallback':
697
+ case 'duplicate-layer-index':
698
+ case 'unsupported-text-glyphs':
699
+ case 'missing-font':
700
+ return 'approximated';
701
+ case 'missing-image-asset':
702
+ case 'unsupported-mask':
703
+ case 'unsupported-track-matte':
704
+ case 'unsupported-shape-feature':
705
+ case 'unsupported-shape-type':
706
+ case 'missing-text-data':
707
+ return 'dropped';
708
+ case 'unsupported-layer-type':
709
+ return 'unsupported';
710
+ }
711
+ }
712
+ /** Creates a source-scoped warning for a normalized, approximated, or dropped Lottie feature. */ function createLottieDiagnostic(options) {
713
+ var _ref;
714
+ var _options_featureKinds;
715
+ return _extends({
716
+ code: "LOTTIE_" + options.code.replaceAll('-', '_').toUpperCase(),
717
+ severity: 'warning',
718
+ action: resolveDiagnosticAction(options.code),
719
+ path: '$.layers'
720
+ }, options.layerInd != null && {
721
+ sourceId: String(options.layerInd)
722
+ }, {
723
+ feature: (_ref = (_options_featureKinds = options.featureKinds) == null ? void 0 : _options_featureKinds.join(',')) != null ? _ref : options.code,
724
+ message: options.message
725
+ });
726
+ }
727
+
512
728
  function hasFullStaticOpacity(mask) {
513
729
  var opacity = mask['o'];
514
730
  if (opacity == null) {
@@ -606,9 +822,10 @@ function collectMaskPathIssues(mask) {
606
822
  'open-mask-path'
607
823
  ];
608
824
  }
609
- /** Converts one supported authored Mask and reports features that prevent conversion. */ function convertLottieMask(maskInfo) {
825
+ /** Converts the ordered authored Mask stack and reports features that prevent conversion. */ function convertLottieMasks(maskInfo) {
610
826
  if (!Array.isArray(maskInfo)) {
611
827
  return {
828
+ masks: [],
612
829
  unsupportedFeatures: [
613
830
  'invalid-mask-data'
614
831
  ]
@@ -622,6 +839,7 @@ function collectMaskPathIssues(mask) {
622
839
  });
623
840
  if (activeMasks.length === 0) {
624
841
  return {
842
+ masks: [],
625
843
  unsupportedFeatures: hasInvalidEntry ? [
626
844
  'invalid-mask-data'
627
845
  ] : []
@@ -631,9 +849,6 @@ function collectMaskPathIssues(mask) {
631
849
  if (hasInvalidEntry) {
632
850
  features.add('invalid-mask-data');
633
851
  }
634
- if (activeMasks.length > 1) {
635
- features.add('multiple-active-masks');
636
- }
637
852
  for(var _iterator = _create_for_of_iterator_helper_loose(activeMasks), _step; !(_step = _iterator()).done;){
638
853
  var mask = _step.value;
639
854
  if (!isSupportedLottieMaskMode(mask['mode'])) {
@@ -648,20 +863,36 @@ function collectMaskPathIssues(mask) {
648
863
  }
649
864
  }
650
865
  var unsupportedFeatures = Array.from(features).sort();
651
- if (unsupportedFeatures.length > 0 || activeMasks.length !== 1) {
866
+ if (unsupportedFeatures.length > 0) {
652
867
  return {
868
+ masks: [],
653
869
  unsupportedFeatures: unsupportedFeatures
654
870
  };
655
871
  }
656
- var mask1 = activeMasks[0];
657
- var pathData = resolveMaskPathData(mask1);
658
- var mode = mapLottieMaskMode(mask1['mode']);
872
+ var masks = [];
873
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(activeMasks), _step2; !(_step2 = _iterator2()).done;){
874
+ var mask1 = _step2.value;
875
+ var converted = convertMaskEntry(mask1);
876
+ if (converted == null) {
877
+ return {
878
+ masks: [],
879
+ unsupportedFeatures: [
880
+ 'invalid-mask-data'
881
+ ]
882
+ };
883
+ }
884
+ masks.push(converted);
885
+ }
886
+ return {
887
+ masks: masks,
888
+ unsupportedFeatures: []
889
+ };
890
+ }
891
+ function convertMaskEntry(mask) {
892
+ var pathData = resolveMaskPathData(mask);
893
+ var mode = mapLottieMaskMode(mask['mode']);
659
894
  if (pathData == null || mode == null) {
660
- return {
661
- unsupportedFeatures: [
662
- 'invalid-mask-data'
663
- ]
664
- };
895
+ return undefined;
665
896
  }
666
897
  var vertices = pathData['v'];
667
898
  var relativeInTangents = pathData['i'];
@@ -690,15 +921,12 @@ function collectMaskPathIssues(mask) {
690
921
  outTangents: outTangents,
691
922
  closed: true
692
923
  };
693
- return {
694
- mask: _extends({
695
- path: path,
696
- mode: mode
697
- }, mask1['inv'] === true && {
698
- inverted: true
699
- }),
700
- unsupportedFeatures: []
701
- };
924
+ return _extends({
925
+ path: path,
926
+ mode: mode
927
+ }, mask['inv'] === true && {
928
+ inverted: true
929
+ });
702
930
  }
703
931
 
704
932
  /** Stable diagnostic labels for unsupported Lottie shape operators. */ var SHAPE_FEATURE_LABELS = {
@@ -1308,18 +1536,195 @@ function buildCustomShapeData(shPaths, fills, strokes, transform) {
1308
1536
  strokes: strokes,
1309
1537
  position: position
1310
1538
  };
1311
- return shapeData;
1312
- }
1313
-
1314
- /** Returns the first Text Document keyframe used for static text conversion. */ function parseLottieTextDocument(layer) {
1315
- var _asRecord;
1316
- if (layer.ty !== 5 || layer.t == null) {
1539
+ return shapeData;
1540
+ }
1541
+
1542
+ /** Returns the first Text Document keyframe used for static text conversion. */ function parseLottieTextDocument(layer) {
1543
+ var _asRecord;
1544
+ if (layer.ty !== 5 || layer.t == null) {
1545
+ return undefined;
1546
+ }
1547
+ var textData = asRecord(layer.t);
1548
+ var documentData = asRecord(textData == null ? void 0 : textData['d']);
1549
+ var keyframes = documentData == null ? void 0 : documentData['k'];
1550
+ return Array.isArray(keyframes) ? asRecord((_asRecord = asRecord(keyframes[0])) == null ? void 0 : _asRecord['s']) : undefined;
1551
+ }
1552
+
1553
+ function isFiniteColor(value) {
1554
+ return Array.isArray(value) && value.every(function(channel) {
1555
+ return typeof channel === 'number' && Number.isFinite(channel);
1556
+ });
1557
+ }
1558
+ function collectOutlinePaths(items) {
1559
+ var paths = [];
1560
+ for(var _iterator = _create_for_of_iterator_helper_loose(items), _step; !(_step = _iterator()).done;){
1561
+ var item = _step.value;
1562
+ if (item.hd === true) {
1563
+ continue;
1564
+ }
1565
+ if (item.ty === 'gr') {
1566
+ var _paths;
1567
+ var _item_it;
1568
+ var nested = collectOutlinePaths((_item_it = item.it) != null ? _item_it : []);
1569
+ if (nested == null) {
1570
+ return undefined;
1571
+ }
1572
+ (_paths = paths).push.apply(_paths, [].concat(nested));
1573
+ } else if (item.ty === 'sh' && item.ks.a !== 1) {
1574
+ paths.push(item);
1575
+ } else {
1576
+ return undefined;
1577
+ }
1578
+ }
1579
+ return paths;
1580
+ }
1581
+ /** Embedded glyph paths use 100-unit font coordinates, independent of the exported font size. */ function convertLottieTextGlyphs(layer, fonts, chars) {
1582
+ var _loop = function() {
1583
+ var _step_value = _step.value, lineIndex = _step_value[0], line = _step_value[1];
1584
+ var glyphs = Array.from(line, function(character) {
1585
+ return chars.find(function(glyph) {
1586
+ return glyph.ch === character && glyph.fFamily === font.fFamily && glyph.style === font.fStyle;
1587
+ });
1588
+ });
1589
+ if (glyphs.some(function(glyph) {
1590
+ return glyph == null;
1591
+ })) {
1592
+ return {
1593
+ v: undefined
1594
+ };
1595
+ }
1596
+ // Trailing spaces advance the pen but do not participate in Lottie's alignment width.
1597
+ var trimmedLength = Array.from(line.replace(/ +$/, '')).length;
1598
+ var width = glyphs.slice(0, trimmedLength).reduce(function(sum, glyph) {
1599
+ var _ref;
1600
+ return sum + ((_ref = glyph == null ? void 0 : glyph.w) != null ? _ref : 0) * scale + tracking;
1601
+ }, 0) - (trimmedLength > 0 ? tracking : 0);
1602
+ var x = document['j'] === 1 ? -width : document['j'] === 2 ? -width / 2 : 0;
1603
+ var y = lineIndex * lineHeight + (lineIndex > 0 ? 1 : 0) - baselineShift;
1604
+ for(var _iterator = _create_for_of_iterator_helper_loose(glyphs), _step1; !(_step1 = _iterator()).done;){
1605
+ var glyph = _step1.value;
1606
+ if (glyph == null) {
1607
+ return {
1608
+ v: undefined
1609
+ };
1610
+ }
1611
+ if ('shapes' in glyph.data) {
1612
+ var _loop = function() {
1613
+ var shape = _step2.value;
1614
+ if (shape.primitiveType !== animationIr.IRShapePrimitiveType.Custom) {
1615
+ return {
1616
+ v: undefined
1617
+ };
1618
+ }
1619
+ for(var _iterator = _create_for_of_iterator_helper_loose(shape.customPaths), _step; !(_step = _iterator()).done;){
1620
+ var path = _step.value;
1621
+ paths.push({
1622
+ closed: path.closed,
1623
+ points: path.points.map(function(point) {
1624
+ return {
1625
+ x: (point.x + shape.position[0]) * scale + x,
1626
+ y: (point.y + shape.position[1]) * scale + y
1627
+ };
1628
+ }),
1629
+ inTangents: path.inTangents.map(function(point) {
1630
+ return {
1631
+ x: point.x * scale,
1632
+ y: point.y * scale
1633
+ };
1634
+ }),
1635
+ outTangents: path.outTangents.map(function(point) {
1636
+ return {
1637
+ x: point.x * scale,
1638
+ y: point.y * scale
1639
+ };
1640
+ })
1641
+ });
1642
+ }
1643
+ };
1644
+ var outlinePaths = collectOutlinePaths(glyph.data.shapes);
1645
+ if (outlinePaths == null) {
1646
+ return {
1647
+ v: undefined
1648
+ };
1649
+ }
1650
+ var converted = convertLottieShapes([
1651
+ {
1652
+ ty: 'gr',
1653
+ it: outlinePaths
1654
+ },
1655
+ {
1656
+ ty: 'fl',
1657
+ c: {
1658
+ a: 0,
1659
+ k: fillColor
1660
+ },
1661
+ o: {
1662
+ a: 0,
1663
+ k: 100
1664
+ },
1665
+ r: 1
1666
+ }
1667
+ ]);
1668
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(converted.shapes), _step2; !(_step2 = _iterator1()).done;){
1669
+ var _ret = _loop();
1670
+ if (_type_of(_ret) === "object") return {
1671
+ v: _ret.v
1672
+ };
1673
+ }
1674
+ } else if (glyph.ch.trim() !== '') {
1675
+ return {
1676
+ v: undefined
1677
+ };
1678
+ }
1679
+ x += glyph.w * scale + tracking;
1680
+ }
1681
+ };
1682
+ var _color_, _color_1, _color_2;
1683
+ var document = parseLottieTextDocument(layer);
1684
+ var font = fonts.find(function(item) {
1685
+ return item.fName === (document == null ? void 0 : document['f']);
1686
+ });
1687
+ if (document == null || font == null || typeof document['t'] !== 'string' || document['sz'] != null || document['ps'] != null || toFiniteNumber(document['sw'], 0) !== 0) {
1317
1688
  return undefined;
1318
1689
  }
1319
- var textData = asRecord(layer.t);
1320
- var documentData = asRecord(textData == null ? void 0 : textData['d']);
1321
- var keyframes = documentData == null ? void 0 : documentData['k'];
1322
- return Array.isArray(keyframes) ? asRecord((_asRecord = asRecord(keyframes[0])) == null ? void 0 : _asRecord['s']) : undefined;
1690
+ var color = document['fc'];
1691
+ if (!isFiniteColor(color)) {
1692
+ return undefined;
1693
+ }
1694
+ var fillColor = [
1695
+ (_color_ = color[0]) != null ? _color_ : 0,
1696
+ (_color_1 = color[1]) != null ? _color_1 : 0,
1697
+ (_color_2 = color[2]) != null ? _color_2 : 0,
1698
+ 1
1699
+ ];
1700
+ var fontSize = toFiniteNumber(document['s'], 16);
1701
+ var scale = fontSize / 100;
1702
+ var tracking = toFiniteNumber(document['tr'], 0) * fontSize / 1000;
1703
+ var lineHeight = toFiniteNumber(document['lh'], fontSize);
1704
+ var baselineShift = toFiniteNumber(document['ls'], 0);
1705
+ var paths = [];
1706
+ var lines = document['t'].replace(/\r\n?/g, '\n').split('\n');
1707
+ for(var _iterator = _create_for_of_iterator_helper_loose(lines.entries()), _step; !(_step = _iterator()).done;){
1708
+ var _ret = _loop();
1709
+ if (_type_of(_ret) === "object") return _ret.v;
1710
+ }
1711
+ return paths.length === 0 ? [] : [
1712
+ {
1713
+ primitiveType: animationIr.IRShapePrimitiveType.Custom,
1714
+ customPaths: paths,
1715
+ position: [
1716
+ 0,
1717
+ 0
1718
+ ],
1719
+ fills: [
1720
+ {
1721
+ type: animationIr.IRPaintType.Solid,
1722
+ color: fillColor
1723
+ }
1724
+ ],
1725
+ strokes: []
1726
+ }
1727
+ ];
1323
1728
  }
1324
1729
 
1325
1730
  var textWeightType = {
@@ -1513,230 +1918,25 @@ function readNamedFontWeight(value) {
1513
1918
  return undefined;
1514
1919
  }
1515
1920
 
1516
- function hasAnimatedAnchor(layer) {
1517
- var property = getPropertyRecord(layer, 'a');
1518
- return property != null && isKeyframedProperty(property);
1519
- }
1520
- function toStaticAnchor(layer) {
1521
- var _ref;
1522
- var _property_keyframes_;
1523
- var property = toAnimatedProperty(getPropertyRecord(layer, 'a'), readVector3);
1524
- if (property == null || property.type === 'static') {
1525
- return property;
1526
- }
1527
- return {
1528
- type: 'static',
1529
- value: (_ref = (_property_keyframes_ = property.keyframes[0]) == null ? void 0 : _property_keyframes_.value) != null ? _ref : [
1530
- 0,
1531
- 0,
1532
- 0
1533
- ]
1534
- };
1535
- }
1536
- function readVector3(value) {
1537
- var _values_, _values_1, _values_2;
1538
- var values = toFiniteNumberArray(value);
1539
- if (values == null) {
1540
- return undefined;
1541
- }
1542
- return [
1543
- (_values_ = values[0]) != null ? _values_ : 0,
1544
- (_values_1 = values[1]) != null ? _values_1 : 0,
1545
- (_values_2 = values[2]) != null ? _values_2 : 0
1546
- ];
1547
- }
1548
- function readSpatialTangent(value) {
1549
- var values = toFiniteNumberArray(value);
1550
- if ((values == null ? void 0 : values.length) === 2) {
1551
- return [
1552
- values[0],
1553
- values[1]
1554
- ];
1555
- }
1556
- if ((values == null ? void 0 : values.length) === 3) {
1557
- return [
1558
- values[0],
1559
- values[1],
1560
- values[2]
1561
- ];
1562
- }
1563
- return undefined;
1564
- }
1565
- function readScaleVector(value) {
1566
- var _values_, _values_1, _values_2;
1567
- var _toFiniteNumberArray;
1568
- var values = (_toFiniteNumberArray = toFiniteNumberArray(value)) == null ? void 0 : _toFiniteNumberArray.map(function(item) {
1569
- return item / 100;
1570
- });
1571
- if (values == null) {
1572
- return undefined;
1573
- }
1574
- return [
1575
- (_values_ = values[0]) != null ? _values_ : 1,
1576
- (_values_1 = values[1]) != null ? _values_1 : 1,
1577
- (_values_2 = values[2]) != null ? _values_2 : 1
1578
- ];
1579
- }
1580
- function readOpacityNumber(value) {
1581
- var valueNumber = toFirstNumber(value);
1582
- return valueNumber != null ? valueNumber / 100 : undefined;
1583
- }
1584
- function getPropertyRecord(layer, key) {
1585
- var ks = asRecord(layer.ks);
1586
- var property = asRecord(ks == null ? void 0 : ks[key]);
1587
- if (property == null || !('k' in property)) {
1588
- return undefined;
1589
- }
1590
- return property;
1591
- }
1592
- function readBezierHandle(value) {
1593
- var record = asRecord(value);
1594
- var x = toFirstNumber(record == null ? void 0 : record['x']);
1595
- var y = toFirstNumber(record == null ? void 0 : record['y']);
1596
- if (x == null || y == null) {
1597
- return undefined;
1598
- }
1599
- return {
1600
- x: x,
1601
- y: y
1602
- };
1603
- }
1604
- function readKeyframes(property, reader) {
1605
- var rawKeyframes = property['k'];
1606
- if (!Array.isArray(rawKeyframes)) {
1607
- return undefined;
1608
- }
1609
- var keyframes = [];
1610
- var previousEndValue;
1611
- // Lottie stores segment tangents on the start keyframe; IR assigns them to their endpoints.
1612
- var pendingInTangent;
1613
- var pendingSpatialIn;
1614
- for(var _iterator = _create_for_of_iterator_helper_loose(rawKeyframes), _step; !(_step = _iterator()).done;){
1615
- var rawKeyframe = _step.value;
1616
- var keyframeRecord = asRecord(rawKeyframe);
1617
- var t = keyframeRecord == null ? void 0 : keyframeRecord['t'];
1618
- if (!isFiniteNumber(t)) {
1619
- continue;
1620
- }
1621
- // Terminal keyframes inherit the preceding `e` value.
1622
- var value = reader(keyframeRecord == null ? void 0 : keyframeRecord['s']);
1623
- if (value == null) {
1624
- if (previousEndValue != null) {
1625
- value = previousEndValue;
1626
- } else {
1627
- continue;
1628
- }
1629
- }
1630
- var endValue = reader(keyframeRecord == null ? void 0 : keyframeRecord['e']);
1631
- previousEndValue = endValue != null ? endValue : value;
1632
- var recordInTangent = readBezierHandle(keyframeRecord == null ? void 0 : keyframeRecord['i']);
1633
- var outTangent = readBezierHandle(keyframeRecord == null ? void 0 : keyframeRecord['o']);
1634
- var spatialOut = readSpatialTangent(keyframeRecord == null ? void 0 : keyframeRecord['to']);
1635
- var recordSpatialIn = readSpatialTangent(keyframeRecord == null ? void 0 : keyframeRecord['ti']);
1636
- var inTangent = pendingInTangent;
1637
- var spatialIn = pendingSpatialIn;
1638
- keyframes.push(_extends({
1639
- frame: t,
1640
- value: value
1641
- }, endValue != null && {
1642
- endValue: endValue
1643
- }, (keyframeRecord == null ? void 0 : keyframeRecord['h']) === 1 && {
1644
- hold: true
1645
- }, inTangent != null && {
1646
- inTangent: inTangent
1647
- }, outTangent != null && {
1648
- outTangent: outTangent
1649
- }, spatialOut != null && {
1650
- spatialOut: spatialOut
1651
- }, spatialIn != null && {
1652
- spatialIn: spatialIn
1653
- }));
1654
- // Incoming tangents belong to the next IR keyframe.
1655
- pendingInTangent = recordInTangent;
1656
- pendingSpatialIn = recordSpatialIn;
1657
- }
1658
- return keyframes.length > 0 ? keyframes : undefined;
1659
- }
1660
- function toAnimatedProperty(property, reader) {
1661
- if (property == null) {
1662
- return undefined;
1663
- }
1664
- if (isKeyframedProperty(property)) {
1665
- var _ref;
1666
- var _keyframes_;
1667
- var keyframes = readKeyframes(property, reader);
1668
- if (keyframes != null && keyframes.length >= 2) {
1669
- return {
1670
- type: 'keyframed',
1671
- keyframes: keyframes
1672
- };
1673
- }
1674
- var staticValue = (_ref = keyframes == null ? void 0 : (_keyframes_ = keyframes[0]) == null ? void 0 : _keyframes_.value) != null ? _ref : reader(property['k']);
1675
- return staticValue != null ? {
1676
- type: 'static',
1677
- value: staticValue
1678
- } : undefined;
1679
- }
1680
- var value = reader(property['k']);
1681
- return value != null ? {
1682
- type: 'static',
1683
- value: value
1684
- } : undefined;
1685
- }
1686
- /**
1687
- * Converts Lottie transform properties and keyframes to IR units and tangent ownership.
1688
- *
1689
- * Scale and opacity percentages become normalized factors. Animated anchors use their first keyframe because IR anchors
1690
- * are static.
1691
- */ function convertLottieTransform(layer) {
1692
- var _getPropertyRecord;
1693
- var transform = {};
1694
- var anchor = toStaticAnchor(layer);
1695
- var positionProperty = getPropertyRecord(layer, 'p');
1696
- var position = toAnimatedProperty(positionProperty, readVector3);
1697
- var scale = toAnimatedProperty(getPropertyRecord(layer, 's'), readScaleVector);
1698
- var rotationZ = toAnimatedProperty((_getPropertyRecord = getPropertyRecord(layer, 'rz')) != null ? _getPropertyRecord : getPropertyRecord(layer, 'r'), toFirstNumber);
1699
- var rotationX = toAnimatedProperty(getPropertyRecord(layer, 'rx'), toFirstNumber);
1700
- var rotationY = toAnimatedProperty(getPropertyRecord(layer, 'ry'), toFirstNumber);
1701
- var opacity = toAnimatedProperty(getPropertyRecord(layer, 'o'), readOpacityNumber);
1702
- if (anchor != null) {
1703
- transform.anchor = anchor;
1704
- }
1705
- if (position != null) {
1706
- transform.position = position;
1707
- }
1708
- if (scale != null) {
1709
- transform.scale = scale;
1710
- }
1711
- if (rotationX != null || rotationY != null || rotationZ != null) {
1712
- var rotation = {};
1713
- if (rotationX != null) {
1714
- rotation.x = rotationX;
1715
- }
1716
- if (rotationY != null) {
1717
- rotation.y = rotationY;
1718
- }
1719
- if (rotationZ != null) {
1720
- rotation.z = rotationZ;
1721
- }
1722
- transform.rotation = rotation;
1723
- }
1724
- if (opacity != null) {
1725
- transform.opacity = opacity;
1726
- }
1727
- return transform;
1728
- }
1729
-
1730
1921
  /**
1731
1922
  * Lowers one supported Lottie Layer after its parent, matte, and precomposition references have been resolved.
1732
1923
  *
1733
1924
  * Fidelity limitations are returned with the converted Layer for Scene-level diagnostic assembly.
1734
1925
  */ function convertLottieLayer(options) {
1735
- var _ref;
1926
+ var _options_chars, _ref;
1736
1927
  var layer = options.layer, asset = options.asset, id = options.id;
1737
1928
  var layerRecord = layer;
1738
- var type = mapLottieLayerTypeToIR(layer);
1929
+ var hasGlyphs = layer.ty === 5 && options.chars != null && options.chars.length > 0;
1930
+ var glyphShapes = hasGlyphs ? convertLottieTextGlyphs(layer, options.fonts, (_options_chars = options.chars) != null ? _options_chars : []) : undefined;
1931
+ var type = glyphShapes != null ? 'shape' : mapLottieLayerTypeToIR(layer);
1739
1932
  var diagnostics = [];
1933
+ if (hasGlyphs && glyphShapes == null) {
1934
+ diagnostics.push(createLottieDiagnostic({
1935
+ code: 'unsupported-text-glyphs',
1936
+ message: "Text layer '" + layer.nm + "' has missing or unsupported glyph outlines; using font-based text instead.",
1937
+ layerInd: layer.ind
1938
+ }));
1939
+ }
1740
1940
  var solidLayerColor = type === 'solid' ? convertSolidColor(layer) : undefined;
1741
1941
  var parentLayerId = options.parentLayerId;
1742
1942
  var shapeLayer = layer.ty === 4 ? layer : undefined;
@@ -1819,7 +2019,7 @@ function toAnimatedProperty(property, reader) {
1819
2019
  content: textConversion.content
1820
2020
  }, type === 'shape' && {
1821
2021
  content: {
1822
- shapes: (_ref = shapeConversion == null ? void 0 : shapeConversion.shapes) != null ? _ref : []
2022
+ shapes: (_ref = glyphShapes != null ? glyphShapes : shapeConversion == null ? void 0 : shapeConversion.shapes) != null ? _ref : []
1823
2023
  }
1824
2024
  }, type === 'precomp' && options.precompCompositionId != null && {
1825
2025
  content: {
@@ -1829,8 +2029,9 @@ function toAnimatedProperty(property, reader) {
1829
2029
  }
1830
2030
  }, {
1831
2031
  transform: transform,
1832
- blendMode: mapLottieBlendMode(layerRecord['bm']),
1833
- mask: maskConversion.mask
2032
+ blendMode: mapLottieBlendMode(layerRecord['bm'])
2033
+ }, maskConversion.masks.length > 0 && {
2034
+ masks: maskConversion.masks
1834
2035
  });
1835
2036
  var localBounds = computeLottieLocalBounds(convertedLayer, layer, asset, textConversion == null ? void 0 : textConversion.localBounds);
1836
2037
  if (localBounds != null) {
@@ -1939,9 +2140,10 @@ function convertSolidColor(layer) {
1939
2140
  /** Analyzes authored masks; precomposition clipping remains in `content.clipToBounds`. */ function convertLayerMask(layer) {
1940
2141
  var layerRecord = layer;
1941
2142
  if (layerRecord['hasMask'] === true && layerRecord['masksProperties'] != null) {
1942
- return convertLottieMask(layerRecord['masksProperties']);
2143
+ return convertLottieMasks(layerRecord['masksProperties']);
1943
2144
  }
1944
2145
  return {
2146
+ masks: [],
1945
2147
  unsupportedFeatures: []
1946
2148
  };
1947
2149
  }
@@ -2153,8 +2355,25 @@ function resolveLayerMattes(layers, contextByLayerIndex, diagnostics) {
2153
2355
  sourceLayer: layerForTransform
2154
2356
  });
2155
2357
  }
2358
+ }, _loop1 = function() {
2359
+ var context = _step2.value;
2360
+ var _collectParents = collectParents(context, new Set()), parents = _collectParents.parents, ambiguous = _collectParents.ambiguous;
2361
+ var childIn = Math.max(inPoint, toFiniteNumber(context.sourceLayer.ip, 0));
2362
+ var childOut = Math.min(outPoint, toFiniteNumber(context.sourceLayer.op, 0));
2363
+ // Lottie evaluates ancestor transforms even when their own content is inactive.
2364
+ var needsIndependentLifetime = childOut > childIn && parents.some(function(parent) {
2365
+ return childIn < toFiniteNumber(parent.sourceLayer.ip, 0) || childOut > toFiniteNumber(parent.sourceLayer.op, 0);
2366
+ });
2367
+ if (ambiguous || needsIndependentLifetime) {
2368
+ context.parentTransformLayers = parents.map(function(parent) {
2369
+ return parent.sourceLayer;
2370
+ });
2371
+ } else {
2372
+ var _parents_;
2373
+ context.parentLayerId = (_parents_ = parents[0]) == null ? void 0 : _parents_.layerId;
2374
+ }
2156
2375
  };
2157
- var layers = param.layers, assetById = param.assetById, fonts = param.fonts;
2376
+ var layers = param.layers, assetById = param.assetById, fonts = param.fonts, inPoint = param.inPoint, outPoint = param.outPoint;
2158
2377
  var contexts = [];
2159
2378
  var contextByLayerIndex = new Map();
2160
2379
  var diagnostics = [];
@@ -2169,16 +2388,53 @@ function resolveLayerMattes(layers, contextByLayerIndex, diagnostics) {
2169
2388
  };
2170
2389
  // Lottie lists topmost layers first; IR uses back-to-front painter order.
2171
2390
  for(var layerIndex = layers.length - 1; layerIndex >= 0; layerIndex--)_loop(layerIndex);
2172
- for(var _iterator = _create_for_of_iterator_helper_loose(contexts), _step; !(_step = _iterator()).done;){
2391
+ var contextsByIndex = new Map();
2392
+ for(var _iterator = _create_for_of_iterator_helper_loose(contexts.toReversed()), _step; !(_step = _iterator()).done;){
2173
2393
  var context = _step.value;
2174
- var parentInd = context.sourceLayer['parent'];
2175
- if (typeof parentInd === 'number') {
2176
- var parentContext = contextByLayerIndex.get(parentInd);
2177
- if (parentContext != null) {
2178
- context.parentLayerId = parentContext.layerId;
2179
- }
2394
+ var index = context.sourceLayer.ind;
2395
+ if (typeof index === 'number') {
2396
+ var _contextsByIndex_get;
2397
+ var matches = (_contextsByIndex_get = contextsByIndex.get(index)) != null ? _contextsByIndex_get : [];
2398
+ matches.push(context);
2399
+ contextsByIndex.set(index, matches);
2400
+ }
2401
+ }
2402
+ for(var _iterator1 = _create_for_of_iterator_helper_loose(contextsByIndex), _step1; !(_step1 = _iterator1()).done;){
2403
+ var _step_value = _step1.value, index1 = _step_value[0], matches1 = _step_value[1];
2404
+ if (matches1.length > 1) {
2405
+ diagnostics.push(createLottieDiagnostic({
2406
+ code: 'duplicate-layer-index',
2407
+ message: "Layer index " + index1 + " is duplicated; parent transforms follow lottie-web's source-order hierarchy.",
2408
+ layerInd: index1
2409
+ }));
2180
2410
  }
2181
2411
  }
2412
+ var collectParents = function collectParents1(context, ancestors) {
2413
+ var _contextsByIndex_get;
2414
+ if (ancestors.has(context)) {
2415
+ throw new TypeError('Cyclic Lottie parent references cannot be converted.');
2416
+ }
2417
+ var parentIndex = context.sourceLayer.parent;
2418
+ var matches = typeof parentIndex === 'number' ? (_contextsByIndex_get = contextsByIndex.get(parentIndex)) != null ? _contextsByIndex_get : [] : [];
2419
+ var parents = [];
2420
+ var ambiguous = matches.length > 1;
2421
+ ancestors.add(context);
2422
+ for(var _iterator = _create_for_of_iterator_helper_loose(matches), _step; !(_step = _iterator()).done;){
2423
+ var parent = _step.value;
2424
+ var _parents;
2425
+ var inherited = collectParents(parent, ancestors);
2426
+ (_parents = parents).push.apply(_parents, [].concat([
2427
+ parent
2428
+ ], inherited.parents));
2429
+ ambiguous || (ambiguous = inherited.ambiguous);
2430
+ }
2431
+ ancestors.delete(context);
2432
+ return {
2433
+ parents: parents,
2434
+ ambiguous: ambiguous
2435
+ };
2436
+ };
2437
+ for(var _iterator2 = _create_for_of_iterator_helper_loose(contexts), _step2; !(_step2 = _iterator2()).done;)_loop1();
2182
2438
  resolveLayerMattes(layers, contextByLayerIndex, diagnostics);
2183
2439
  return {
2184
2440
  contexts: contexts,
@@ -2245,27 +2501,55 @@ function buildIRCompositionFromIRLayers(layers, options) {
2245
2501
  var parsed = parseLottieLayerStack({
2246
2502
  layers: compositionLayers,
2247
2503
  assetById: assetById,
2248
- fonts: fonts
2504
+ fonts: fonts,
2505
+ inPoint: compositionInPoint,
2506
+ outPoint: compositionOutPoint
2249
2507
  });
2250
2508
  var convertedLayers = [];
2251
2509
  (_diagnostics = diagnostics).push.apply(_diagnostics, [].concat(parsed.diagnostics));
2252
2510
  for(var _iterator = _create_for_of_iterator_helper_loose(parsed.contexts), _step; !(_step = _iterator()).done;){
2253
2511
  var context = _step.value;
2254
2512
  var _diagnostics1;
2513
+ var _ref;
2514
+ var _context_parentTransformLayers;
2255
2515
  var refId = 'refId' in context.sourceLayer ? context.sourceLayer.refId : undefined;
2256
2516
  var precompCompositionId = refId != null ? compositionIdByAssetId.get(String(refId)) : undefined;
2517
+ var parentLayerId = context.parentLayerId;
2518
+ // Private null layers retain ancestor transforms independently of visible
2519
+ // content lifetimes and preserve source-order multiplication for duplicate indices.
2520
+ for(var _iterator1 = _create_for_of_iterator_helper_loose((_ref = (_context_parentTransformLayers = context.parentTransformLayers) == null ? void 0 : _context_parentTransformLayers.toReversed()) != null ? _ref : []), _step1; !(_step1 = _iterator1()).done;){
2521
+ var parent = _step1.value;
2522
+ var transform = convertLottieTransform(parent);
2523
+ var id = createId();
2524
+ delete transform.opacity;
2525
+ convertedLayers.push(_extends({
2526
+ id: id,
2527
+ type: 'null',
2528
+ time: {
2529
+ inFrame: compositionInPoint,
2530
+ outFrame: compositionOutPoint
2531
+ },
2532
+ visible: true,
2533
+ transform: transform
2534
+ }, parentLayerId != null && {
2535
+ parentId: parentLayerId
2536
+ }));
2537
+ parentLayerId = id;
2538
+ }
2257
2539
  var converted = convertLottieLayer({
2258
2540
  layer: context.sourceLayer,
2259
2541
  asset: context.asset,
2260
2542
  id: context.layerId,
2261
- parentLayerId: context.parentLayerId,
2543
+ parentLayerId: parentLayerId,
2262
2544
  matte: context.matte,
2263
2545
  compositionRange: {
2264
2546
  inPoint: compositionInPoint,
2265
2547
  outPoint: compositionOutPoint
2266
2548
  },
2267
2549
  precompCompositionId: precompCompositionId,
2268
- fontAssetIdByName: fontRegistry.assetIdByFontName
2550
+ fontAssetIdByName: fontRegistry.assetIdByFontName,
2551
+ fonts: fonts,
2552
+ chars: json.chars
2269
2553
  });
2270
2554
  (_diagnostics1 = diagnostics).push.apply(_diagnostics1, [].concat(converted.diagnostics));
2271
2555
  convertedLayers.push(converted.layer);
@@ -11273,7 +11557,7 @@ Object.defineProperties(JSZip, staticAccessors);
11273
11557
  * @throws `LottieConverterError` when the archive is invalid or contains no JSON file.
11274
11558
  */ function extractLottieFromZip(zipData) {
11275
11559
  return _async_to_generator(function() {
11276
- var zip, error, resourcePaths, jsonPath, file, mimeType, json, dirPath, resources;
11560
+ var zip, error, resourceEntries, jsonEntry, file, mimeType, json, dirPath, resources;
11277
11561
  return _ts_generator(this, function(_state) {
11278
11562
  switch(_state.label){
11279
11563
  case 0:
@@ -11299,34 +11583,34 @@ Object.defineProperties(JSZip, staticAccessors);
11299
11583
  cause: _instanceof(error, Error) ? error.message : String(error)
11300
11584
  });
11301
11585
  case 3:
11302
- resourcePaths = [];
11586
+ resourceEntries = [];
11303
11587
  for(var relativePath in zip.files){
11304
11588
  file = zip.files[relativePath];
11305
11589
  mimeType = resolveZipResourceMimeType(relativePath);
11306
11590
  if (!file.dir && mimeType != null && !relativePath.includes('_MACOSX')) {
11307
- resourcePaths.push({
11591
+ resourceEntries.push({
11308
11592
  file: file,
11309
11593
  mimeType: mimeType
11310
11594
  });
11311
11595
  }
11312
11596
  if (!file.dir && /\.json$/i.test(relativePath) && !relativePath.includes('_MACOSX')) {
11313
- jsonPath = file;
11597
+ jsonEntry = file;
11314
11598
  }
11315
11599
  }
11316
- if (jsonPath == null) {
11600
+ if (jsonEntry == null) {
11317
11601
  throw new LottieConverterError(LOTTIE_CONVERTER_ERROR_CODES.ZIP_JSON_NOT_FOUND, 'No JSON file was found in the ZIP archive.');
11318
11602
  }
11319
11603
  return [
11320
11604
  4,
11321
- jsonPath.async('string')
11605
+ jsonEntry.async('string')
11322
11606
  ];
11323
11607
  case 4:
11324
11608
  json = _state.sent();
11325
- dirPath = jsonPath.name.split('/').slice(0, -1).join('/');
11609
+ dirPath = jsonEntry.name.split('/').slice(0, -1).join('/');
11326
11610
  resources = {};
11327
11611
  return [
11328
11612
  4,
11329
- Promise.all(resourcePaths.map(function(param) {
11613
+ Promise.all(resourceEntries.map(function(param) {
11330
11614
  var file = param.file, mimeType = param.mimeType;
11331
11615
  return _async_to_generator(function() {
11332
11616
  var buffer, uint8Array, binary, i, base64;