@vvfx/ge-ir 0.0.1-beta.5 → 0.0.1-beta.6

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: Galacean Effects and animation IR bidirectional conversion package
4
4
  * Author: Ant Group CO., Ltd.
5
5
  * Contributors: 澄弈
6
- * Version: v0.0.1-beta.5
6
+ * Version: v0.0.1-beta.6
7
7
  */
8
8
 
9
9
  'use strict';
@@ -62,6 +62,92 @@ function _create_for_of_iterator_helper_loose(o, allowArrayLike) {
62
62
  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
63
63
  }
64
64
 
65
+ /** Read GE layer passthrough data. */ function getEffectsLayerSpecific(ir, layer) {
66
+ var _layer_specific;
67
+ return ir.source === 'effects' ? (_layer_specific = layer.specific) == null ? void 0 : _layer_specific.effects : undefined;
68
+ }
69
+ /** Read GE composition passthrough data. */ function getEffectsCompositionSpecific(ir) {
70
+ var _ir_specific;
71
+ return ir.source === 'effects' ? (_ir_specific = ir.specific) == null ? void 0 : _ir_specific.effects : undefined;
72
+ }
73
+ var EFFECTS_ANIMATION_SPECIFIC_KEYS = [
74
+ 'positionOverLifetime',
75
+ 'rotationOverLifetime',
76
+ 'sizeOverLifetime',
77
+ 'colorOverLifetime'
78
+ ];
79
+ var KEYS_BY_INVALIDATION_TARGET = {
80
+ position: [
81
+ 'positionOverLifetime'
82
+ ],
83
+ rotation: [
84
+ 'rotationOverLifetime',
85
+ 'sourceHierarchy'
86
+ ],
87
+ scale: [
88
+ 'sizeOverLifetime',
89
+ 'sourceHierarchy'
90
+ ],
91
+ color: [
92
+ 'colorOverLifetime'
93
+ ],
94
+ opacity: [
95
+ 'colorOverLifetime'
96
+ ],
97
+ anchor: [
98
+ 'sourceHierarchy'
99
+ ],
100
+ mask: [
101
+ 'mask'
102
+ ],
103
+ precomp: [
104
+ 'precompRefId',
105
+ 'precompContent'
106
+ ]
107
+ };
108
+ /**
109
+ * Remove raw GE values that would otherwise shadow an edited normalized field.
110
+ * Empty `effects` and `specific` containers are pruned so serialization stays clean.
111
+ */ function invalidateEffectsLayerSpecific(layer, target) {
112
+ var _layer_specific;
113
+ var effects = (_layer_specific = layer.specific) == null ? void 0 : _layer_specific.effects;
114
+ if (effects == null) {
115
+ return [];
116
+ }
117
+ var removed = [];
118
+ for(var _iterator = _create_for_of_iterator_helper_loose(KEYS_BY_INVALIDATION_TARGET[target]), _step; !(_step = _iterator()).done;){
119
+ var key = _step.value;
120
+ if (key in effects) {
121
+ delete effects[key];
122
+ removed.push(key);
123
+ }
124
+ }
125
+ if (Object.keys(effects).length === 0 && layer.specific != null) {
126
+ delete layer.specific.effects;
127
+ }
128
+ if (layer.specific != null && Object.keys(layer.specific).length === 0) {
129
+ delete layer.specific;
130
+ }
131
+ return removed;
132
+ }
133
+ /** Whether invalidating opacity would also discard a GE color animation. */ function hasEffectsColorAnimationPassthrough(layer) {
134
+ var _layer_specific_effects, _layer_specific;
135
+ var color = (_layer_specific = layer.specific) == null ? void 0 : (_layer_specific_effects = _layer_specific.effects) == null ? void 0 : _layer_specific_effects.colorOverLifetime;
136
+ if (color == null) {
137
+ return false;
138
+ }
139
+ return Object.keys(color).some(function(channelKey) {
140
+ return channelKey !== 'opacity';
141
+ });
142
+ }
143
+ /** Whether the layer retains any raw GE animation payload. */ function hasEffectsAnimationPassthrough(layer) {
144
+ var _layer_specific;
145
+ var effects = (_layer_specific = layer.specific) == null ? void 0 : _layer_specific.effects;
146
+ return effects != null && EFFECTS_ANIMATION_SPECIFIC_KEYS.some(function(key) {
147
+ return effects[key] != null;
148
+ });
149
+ }
150
+
65
151
  var DEFAULT_CAMERA_Z = 8;
66
152
  var DEFAULT_CAMERA_FOV = 60;
67
153
  var DEFAULT_CLIP_MODE = 1;
@@ -1195,36 +1281,29 @@ function getScalarValue(keyframe, dimensionIndex) {
1195
1281
  for(var i = 0; i < keyframes.length; i++){
1196
1282
  var _kf_outTangent, _kf_inTangent;
1197
1283
  var kf = keyframes[i];
1198
- var normalizedT = normalizeTime(kf.t, timeContext.startFrame, timeContext.endFrame);
1284
+ var normalizedT = normalizeTime(kf.frame, timeContext.startFrame, timeContext.endFrame);
1199
1285
  timingCurvePoints.push({
1200
1286
  t: normalizedT,
1201
1287
  outTangent: (_kf_outTangent = kf.outTangent) != null ? _kf_outTangent : DEFAULT_OUT_TANGENT,
1202
1288
  inTangent: (_kf_inTangent = kf.inTangent) != null ? _kf_inTangent : DEFAULT_IN_TANGENT
1203
1289
  });
1204
1290
  if (i < keyframes.length - 1) {
1205
- var _kf_value, _kf_endValue, _nextKf_value, _startPos_, _startPos_1, _stitchEnd_, _stitchEnd_1;
1291
+ var _kf_value, _ref, _kf_endValue, _startPos_, _startPos_1, _segmentEnd_, _segmentEnd_1;
1206
1292
  var nextKf = keyframes[i + 1];
1207
1293
  var startPos = (_kf_value = kf.value) != null ? _kf_value : [
1208
1294
  0,
1209
1295
  0,
1210
1296
  0
1211
1297
  ];
1212
- // Lottie segment end value: kf.endValue is authoritative; falls back to kf.value (mirrors master's `e ?? s`).
1213
- // nextKf.value is only used later in the path-fixup pass to stitch adjacent segments.
1214
- var segmentEnd = kf.hold === true ? startPos : (_kf_endValue = kf.endValue) != null ? _kf_endValue : startPos;
1215
- var stitchEnd = kf.hold === true ? startPos : (_nextKf_value = nextKf.value) != null ? _nextKf_value : [
1216
- 0,
1217
- 0,
1218
- 0
1219
- ];
1298
+ var segmentEnd = kf.hold === true ? startPos : (_ref = (_kf_endValue = kf.endValue) != null ? _kf_endValue : nextKf.value) != null ? _ref : startPos;
1220
1299
  pathPoints.push([
1221
1300
  [
1222
1301
  (_startPos_ = startPos[0]) != null ? _startPos_ : 0,
1223
1302
  (_startPos_1 = startPos[1]) != null ? _startPos_1 : 0
1224
1303
  ],
1225
1304
  [
1226
- (_stitchEnd_ = stitchEnd[0]) != null ? _stitchEnd_ : 0,
1227
- (_stitchEnd_1 = stitchEnd[1]) != null ? _stitchEnd_1 : 0
1305
+ (_segmentEnd_ = segmentEnd[0]) != null ? _segmentEnd_ : 0,
1306
+ (_segmentEnd_1 = segmentEnd[1]) != null ? _segmentEnd_1 : 0
1228
1307
  ]
1229
1308
  ]);
1230
1309
  // Spatial control points (per IRKeyframe convention): outgoing CP from
@@ -1243,11 +1322,11 @@ function getScalarValue(keyframe, dimensionIndex) {
1243
1322
  (_nextKf_spatialIn_1 = nextKf.spatialIn[1]) != null ? _nextKf_spatialIn_1 : 0
1244
1323
  ];
1245
1324
  } else {
1246
- var _startPos_2, _startPos_3, _segmentEnd_, _segmentEnd_1;
1325
+ var _startPos_2, _startPos_3, _segmentEnd_2, _segmentEnd_3;
1247
1326
  var sx = (_startPos_2 = startPos[0]) != null ? _startPos_2 : 0;
1248
1327
  var sy = (_startPos_3 = startPos[1]) != null ? _startPos_3 : 0;
1249
- var ex = (_segmentEnd_ = segmentEnd[0]) != null ? _segmentEnd_ : 0;
1250
- var ey = (_segmentEnd_1 = segmentEnd[1]) != null ? _segmentEnd_1 : 0;
1328
+ var ex = (_segmentEnd_2 = segmentEnd[0]) != null ? _segmentEnd_2 : 0;
1329
+ var ey = (_segmentEnd_3 = segmentEnd[1]) != null ? _segmentEnd_3 : 0;
1251
1330
  toPoint = [
1252
1331
  -sx / 3 + ex / 3,
1253
1332
  -sy / 3 + ey / 3
@@ -1263,10 +1342,6 @@ function getScalarValue(keyframe, dimensionIndex) {
1263
1342
  ]);
1264
1343
  }
1265
1344
  }
1266
- // Fix up path points: adjacent segments should share endpoints
1267
- for(var i1 = 0; i1 < pathPoints.length - 1; i1++){
1268
- pathPoints[i1][1] = pathPoints[i1 + 1][0];
1269
- }
1270
1345
  // Prepend a static segment if the first keyframe doesn't start at t=0.
1271
1346
  // The bridge segment runs synthetic-at-t=0 → original-kf[0]; for it to be a
1272
1347
  // flat hold the END-side tangent (which `buildPositionTimingCurves` reads as
@@ -1275,7 +1350,7 @@ function getScalarValue(keyframe, dimensionIndex) {
1275
1350
  // the IR convention leaves a first-kf inTangent undefined, or whatever the
1276
1351
  // producer set as a no-op).
1277
1352
  if (timingCurvePoints.length > 0 && timingCurvePoints[0].t > 0) {
1278
- var _ref, _ref1;
1353
+ var _ref1, _ref2;
1279
1354
  var _pathPoints_, _pathPoints_1;
1280
1355
  timingCurvePoints[0].inTangent = {
1281
1356
  x: 1,
@@ -1293,11 +1368,11 @@ function getScalarValue(keyframe, dimensionIndex) {
1293
1368
  }
1294
1369
  });
1295
1370
  pathPoints.unshift([
1296
- (_ref = (_pathPoints_ = pathPoints[0]) == null ? void 0 : _pathPoints_[0]) != null ? _ref : [
1371
+ (_ref1 = (_pathPoints_ = pathPoints[0]) == null ? void 0 : _pathPoints_[0]) != null ? _ref1 : [
1297
1372
  0,
1298
1373
  0
1299
1374
  ],
1300
- (_ref1 = (_pathPoints_1 = pathPoints[0]) == null ? void 0 : _pathPoints_1[0]) != null ? _ref1 : [
1375
+ (_ref2 = (_pathPoints_1 = pathPoints[0]) == null ? void 0 : _pathPoints_1[0]) != null ? _ref2 : [
1301
1376
  0,
1302
1377
  0
1303
1378
  ]
@@ -1374,10 +1449,13 @@ function buildCurveForDimension(keyframes, timeContext, dimensionIndex) {
1374
1449
  var _kf_outTangent, _nextKf_inTangent;
1375
1450
  var kf = keyframes[i];
1376
1451
  var nextKf = keyframes[i + 1];
1377
- var t0 = normalizeTime(kf.t, timeContext.startFrame, timeContext.endFrame);
1378
- var t1 = normalizeTime(nextKf.t, timeContext.startFrame, timeContext.endFrame);
1452
+ var t0 = normalizeTime(kf.frame, timeContext.startFrame, timeContext.endFrame);
1453
+ var t1 = normalizeTime(nextKf.frame, timeContext.startFrame, timeContext.endFrame);
1379
1454
  var v0 = getScalarValue(kf, dimensionIndex);
1380
- var v1 = kf.hold === true ? v0 : getScalarValue(nextKf, dimensionIndex);
1455
+ var endKeyframe = kf.endValue != null ? _extends({}, kf, {
1456
+ value: kf.endValue
1457
+ }) : nextKf;
1458
+ var v1 = kf.hold === true ? v0 : getScalarValue(endKeyframe, dimensionIndex);
1381
1459
  var outHandle = kf.hold === true ? {
1382
1460
  x: 0,
1383
1461
  y: 0
@@ -1484,20 +1562,11 @@ function buildPositionTimingCurves(points) {
1484
1562
  }
1485
1563
 
1486
1564
  /**
1487
- * True when the layer's parent only inherits transform — visibility and
1488
- * lifetime are independent of the parent's window.
1489
- *
1490
- * Reads `IRLayerReference.linkKind` directly. Producers that don't set the
1491
- * field (e.g. dsl2ge) effectively get `false` here, which is the correct
1492
- * default for "full" parent containment.
1493
- *
1494
- * Lottie's parser sets `linkKind: 'transform-only'` when a child's parent
1495
- * relationship comes from `layer.parent` rather than precomp expansion;
1496
- * `applyPostProcess` consumes this to decide whether to advance the parent's
1497
- * activation track when the child starts earlier.
1498
- */ function isTransformOnlyParentLink(layer) {
1565
+ * True when the child lifetime is independent of its transform parent's
1566
+ * clipping window. An omitted lifetimeMode keeps the legacy clipped default.
1567
+ */ function hasIndependentParentLifetime(layer) {
1499
1568
  var _layer_parent;
1500
- return ((_layer_parent = layer.parent) == null ? void 0 : _layer_parent.linkKind) === 'transform-only';
1569
+ return ((_layer_parent = layer.parent) == null ? void 0 : _layer_parent.lifetimeMode) === 'independent';
1501
1570
  }
1502
1571
 
1503
1572
  /**
@@ -1505,18 +1574,19 @@ function buildPositionTimingCurves(points) {
1505
1574
  * the time-stretch and offset semantics from `IRTimeContext`.
1506
1575
  *
1507
1576
  * dsl-source IRs leave `stretch` and `offsetFrame` undefined, in which case
1508
- * this collapses to `delay = startFrame / fr` and
1577
+ * this collapses to `delay = (startFrame - compositionInPoint) / fr` and
1509
1578
  * `duration = (endFrame - startFrame) / fr` — exactly what dsl2ge used to
1510
1579
  * compute inline.
1511
1580
  *
1512
1581
  * Zero/negative durations are clamped to a 0.0001 epsilon so GE keeps the
1513
1582
  * activation track alive for the (degenerate) layer.
1514
- */ function computeLayerTiming(layer, frameRate) {
1583
+ */ function computeLayerTiming(layer, frameRate, compositionInPoint) {
1584
+ if (compositionInPoint === void 0) compositionInPoint = 0;
1515
1585
  var _time_stretch, _time_offsetFrame;
1516
1586
  var time = layer.time;
1517
1587
  var stretch = (_time_stretch = time.stretch) != null ? _time_stretch : 1;
1518
1588
  var offsetFrame = (_time_offsetFrame = time.offsetFrame) != null ? _time_offsetFrame : 0;
1519
- var delay = roundNumber((offsetFrame + time.startFrame * stretch) / frameRate, 4);
1589
+ var delay = roundNumber((offsetFrame + time.startFrame * stretch - compositionInPoint) / frameRate, 4);
1520
1590
  var rawDuration = (time.endFrame - time.startFrame) * stretch / frameRate;
1521
1591
  var layerDuration = rawDuration > 0 ? roundNumber(rawDuration, 4) : 0.0001;
1522
1592
  return {
@@ -1528,37 +1598,29 @@ function buildPositionTimingCurves(points) {
1528
1598
  function computeStaticPosition(layer, ctx, anchorOffsetX, anchorOffsetY) {
1529
1599
  if (anchorOffsetX === void 0) anchorOffsetX = 0;
1530
1600
  if (anchorOffsetY === void 0) anchorOffsetY = 0;
1531
- var _transform_position;
1601
+ var _transform_position, _transform_position1, _transform_position_keyframes_, _transform_position2;
1532
1602
  var transform = layer.transform;
1533
- if (transform == null ? void 0 : (_transform_position = transform.position) == null ? void 0 : _transform_position.keyframed) {
1603
+ if ((transform == null ? void 0 : (_transform_position = transform.position) == null ? void 0 : _transform_position.keyframed) === true && transform.position.keyframes.length !== 1) {
1534
1604
  return convert2dTo3dPoint(ctx.width / 2 + anchorOffsetX, ctx.height / 2 + anchorOffsetY, 0, ctx.width, ctx.height);
1535
1605
  }
1536
1606
  var isNullType = layer.type === 'null' || layer.type === 'precomp';
1537
- if ((transform == null ? void 0 : transform.position) != null && Array.isArray(transform.position.value)) {
1607
+ var positionValue = (transform == null ? void 0 : (_transform_position1 = transform.position) == null ? void 0 : _transform_position1.keyframed) === true ? (_transform_position_keyframes_ = transform.position.keyframes[0]) == null ? void 0 : _transform_position_keyframes_.value : transform == null ? void 0 : (_transform_position2 = transform.position) == null ? void 0 : _transform_position2.value;
1608
+ if (Array.isArray(positionValue)) {
1538
1609
  var _pos_, _pos_1, _pos_2;
1539
- var pos = transform.position.value;
1610
+ var pos = positionValue;
1540
1611
  return convert2dTo3dPoint(((_pos_ = pos[0]) != null ? _pos_ : 0) + anchorOffsetX, ((_pos_1 = pos[1]) != null ? _pos_1 : 0) + anchorOffsetY, isNullType ? 0 : (_pos_2 = pos[2]) != null ? _pos_2 : 0, ctx.width, ctx.height);
1541
1612
  }
1542
1613
  return convert2dTo3dPoint(ctx.width / 2 + anchorOffsetX, ctx.height / 2 + anchorOffsetY, 0, ctx.width, ctx.height);
1543
1614
  }
1544
1615
  function getStaticAnchor(layer) {
1545
- var _layer_transform;
1546
- var anchor = (_layer_transform = layer.transform) == null ? void 0 : _layer_transform.anchor;
1547
- if (anchor != null && !anchor.keyframed && Array.isArray(anchor.value) && anchor.value.length >= 2) {
1616
+ var _layer_transform_anchor, _layer_transform;
1617
+ var value = (_layer_transform = layer.transform) == null ? void 0 : (_layer_transform_anchor = _layer_transform.anchor) == null ? void 0 : _layer_transform_anchor.value;
1618
+ if (Array.isArray(value) && value.length >= 2) {
1548
1619
  return [
1549
- anchor.value[0],
1550
- anchor.value[1]
1620
+ value[0],
1621
+ value[1]
1551
1622
  ];
1552
1623
  }
1553
- if ((anchor == null ? void 0 : anchor.keyframed) && anchor.keyframes != null && anchor.keyframes.length > 0) {
1554
- var firstVal = anchor.keyframes[0].value;
1555
- if (Array.isArray(firstVal) && firstVal.length >= 2) {
1556
- return [
1557
- firstVal[0],
1558
- firstVal[1]
1559
- ];
1560
- }
1561
- }
1562
1624
  return [
1563
1625
  0,
1564
1626
  0
@@ -1566,15 +1628,21 @@ function getStaticAnchor(layer) {
1566
1628
  }
1567
1629
  function getStaticScaleFromIR(layer) {
1568
1630
  var _value_, _value_1;
1569
- var _layer_transform;
1631
+ var _layer_transform, _scale_keyframes_;
1570
1632
  var scale = (_layer_transform = layer.transform) == null ? void 0 : _layer_transform.scale;
1571
- if (scale == null || scale.keyframed) {
1633
+ if (scale == null) {
1634
+ return [
1635
+ 1,
1636
+ 1
1637
+ ];
1638
+ }
1639
+ if (scale.keyframed && scale.keyframes.length !== 1) {
1572
1640
  return [
1573
1641
  1,
1574
1642
  1
1575
1643
  ];
1576
1644
  }
1577
- var value = scale.value;
1645
+ var value = scale.keyframed ? (_scale_keyframes_ = scale.keyframes[0]) == null ? void 0 : _scale_keyframes_.value : scale.value;
1578
1646
  if (!Array.isArray(value)) {
1579
1647
  return [
1580
1648
  1,
@@ -1586,14 +1654,15 @@ function getStaticScaleFromIR(layer) {
1586
1654
  (_value_1 = value[1]) != null ? _value_1 : 1
1587
1655
  ];
1588
1656
  }
1589
- function applyScalePositionAdjust(position, layer, layerWidth, layerHeight, ratio) {
1657
+ function applyScalePositionAdjust(position, layer, bounds, ratio) {
1590
1658
  var staticScale = getStaticScaleFromIR(layer);
1591
- if (staticScale[0] === 1 && staticScale[1] === 1 || layerWidth <= 0 || layerHeight <= 0) {
1659
+ var x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
1660
+ if (staticScale[0] === 1 && staticScale[1] === 1 || width <= 0 || height <= 0) {
1592
1661
  return position;
1593
1662
  }
1594
1663
  var anchor = getStaticAnchor(layer);
1595
- var anchorDiffX = anchor[0] - layerWidth / 2;
1596
- var anchorDiffY = anchor[1] - layerHeight / 2;
1664
+ var anchorDiffX = anchor[0] - (x + width / 2);
1665
+ var anchorDiffY = anchor[1] - (y + height / 2);
1597
1666
  if (Math.abs(anchorDiffX) <= 0.5 && Math.abs(anchorDiffY) <= 0.5) {
1598
1667
  return position;
1599
1668
  }
@@ -1603,43 +1672,46 @@ function applyScalePositionAdjust(position, layer, layerWidth, layerHeight, rati
1603
1672
  position[2]
1604
1673
  ];
1605
1674
  }
1606
- function computeAnchorInfo(layer, layerWidth, layerHeight) {
1675
+ function computeAnchorInfo(layer, bounds) {
1607
1676
  var anchor = getStaticAnchor(layer);
1677
+ var x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
1678
+ var localAnchorX = anchor[0] - x;
1679
+ var localAnchorY = anchor[1] - y;
1608
1680
  var anchorScaleX = 0.5;
1609
1681
  var anchorScaleY = 0.5;
1610
1682
  var anchorOffsetX = 0;
1611
1683
  var anchorOffsetY = 0;
1612
- if (layerWidth > 0 && layerHeight > 0) {
1613
- anchorScaleX = anchor[0] / layerWidth;
1614
- anchorScaleY = anchor[1] / layerHeight;
1615
- anchorOffsetX = -(anchor[0] - layerWidth / 2);
1616
- anchorOffsetY = -(anchor[1] - layerHeight / 2);
1684
+ if (width > 0 && height > 0) {
1685
+ anchorScaleX = localAnchorX / width;
1686
+ anchorScaleY = localAnchorY / height;
1687
+ anchorOffsetX = -(localAnchorX - width / 2);
1688
+ anchorOffsetY = -(localAnchorY - height / 2);
1617
1689
  }
1618
- if (layer.type === 'text' && layer.text != null && layerWidth > 0 && layerHeight > 0) {
1690
+ if (layer.type === 'text' && layer.text != null && width > 0 && height > 0) {
1619
1691
  if (layer.text.anchorAdjust === true) {
1620
1692
  if (layer.text.textAlign === 'left') {
1621
- anchorOffsetX = -(anchor[0] - layerWidth / 2);
1622
- anchorScaleX = anchor[0] / layerWidth - 0.5;
1693
+ anchorOffsetX = -(localAnchorX - width / 2);
1694
+ anchorScaleX = localAnchorX / width - 0.5;
1623
1695
  }
1624
1696
  if (layer.text.textAlign === 'center') {
1625
- anchorOffsetX = -anchor[0];
1626
- anchorScaleX = anchor[0] / layerWidth + 0.5;
1697
+ anchorOffsetX = -localAnchorX;
1698
+ anchorScaleX = localAnchorX / width + 0.5;
1627
1699
  }
1628
1700
  if (layer.text.textAlign === 'right') {
1629
- anchorOffsetX = -(anchor[0] + layerWidth / 2);
1630
- anchorScaleX = anchor[0] / layerWidth + 1.5;
1701
+ anchorOffsetX = -(localAnchorX + width / 2);
1702
+ anchorScaleX = localAnchorX / width + 1.5;
1631
1703
  }
1632
1704
  // GE renders glyphs in the lower half of the quad, so offset by half the
1633
1705
  // layer height to align the visible text center with Lottie's anchor.
1634
- var textHeight = layerHeight / 2;
1635
- anchorOffsetY = -(anchor[1] + textHeight);
1636
- anchorScaleY = -anchor[1] / textHeight;
1706
+ var textHeight = height / 2;
1707
+ anchorOffsetY = -(localAnchorY + textHeight);
1708
+ anchorScaleY = -localAnchorY / textHeight;
1637
1709
  }
1638
1710
  }
1639
1711
  var isSpriteForAnchor = layer.type === 'image' || layer.type === 'solid';
1640
1712
  var staticRotationZ = getStaticRotationZ(layer);
1641
1713
  var hasStaticRotation = staticRotationZ != null;
1642
- if (isSpriteForAnchor && hasStaticRotation && isTransformOnlyParentLink(layer) && (anchorOffsetX !== 0 || anchorOffsetY !== 0)) {
1714
+ if (isSpriteForAnchor && hasStaticRotation && hasIndependentParentLifetime(layer) && (anchorOffsetX !== 0 || anchorOffsetY !== 0)) {
1643
1715
  var rotValue = staticRotationZ != null ? staticRotationZ : 0;
1644
1716
  if (rotValue !== 0) {
1645
1717
  var rad = rotValue * Math.PI / 180;
@@ -1659,15 +1731,10 @@ function computeAnchorInfo(layer, layerWidth, layerHeight) {
1659
1731
  };
1660
1732
  }
1661
1733
  function getStaticRotationZ(layer) {
1662
- var _layer_transform, _layer_transform_separatedRotation, _layer_transform1;
1663
- var rotation = (_layer_transform = layer.transform) == null ? void 0 : _layer_transform.rotation;
1664
- if (rotation != null && !rotation.keyframed && Array.isArray(rotation.value)) {
1665
- var _rotation_value_;
1666
- return (_rotation_value_ = rotation.value[2]) != null ? _rotation_value_ : 0;
1667
- }
1668
- var separatedRotationZ = (_layer_transform1 = layer.transform) == null ? void 0 : (_layer_transform_separatedRotation = _layer_transform1.separatedRotation) == null ? void 0 : _layer_transform_separatedRotation.z;
1669
- if (separatedRotationZ != null && !separatedRotationZ.keyframed && typeof separatedRotationZ.value === 'number') {
1670
- return separatedRotationZ.value;
1734
+ var _layer_transform_rotation, _layer_transform;
1735
+ var rotationZ = (_layer_transform = layer.transform) == null ? void 0 : (_layer_transform_rotation = _layer_transform.rotation) == null ? void 0 : _layer_transform_rotation.z;
1736
+ if (rotationZ != null && !rotationZ.keyframed && typeof rotationZ.value === 'number') {
1737
+ return rotationZ.value;
1671
1738
  }
1672
1739
  return undefined;
1673
1740
  }
@@ -1678,86 +1745,20 @@ function getTimeContext(layer) {
1678
1745
  };
1679
1746
  }
1680
1747
 
1681
- function readGE2IRMetadata(ir, layer) {
1682
- if (ir.source !== 'ge') {
1683
- return undefined;
1684
- }
1685
- var metadata = layer.metadata;
1686
- if (metadata == null) {
1687
- return undefined;
1688
- }
1689
- var namespaced = metadata['ge2ir'];
1690
- if (isRecord$4(namespaced)) {
1691
- return namespaced;
1692
- }
1693
- var legacy = readLegacyGE2IRMetadata(metadata);
1694
- return Object.keys(legacy).length > 0 ? legacy : undefined;
1695
- }
1696
- function readLegacyGE2IRMetadata(metadata) {
1697
- var legacy = {};
1698
- var positionOverLifetime = metadata['positionOverLifetime'];
1699
- var rotationOverLifetime = metadata['rotationOverLifetime'];
1700
- var sizeOverLifetime = metadata['sizeOverLifetime'];
1701
- var colorOverLifetime = metadata['colorOverLifetime'];
1702
- var geComponentId = metadata['geComponentId'];
1703
- var geMask = metadata['geMask'];
1704
- var precompRefId = metadata['precompRefId'];
1705
- var precompContent = metadata['precompContent'];
1706
- if (isRecord$4(positionOverLifetime)) {
1707
- legacy.positionOverLifetime = positionOverLifetime;
1708
- }
1709
- if (isRecord$4(rotationOverLifetime)) {
1710
- legacy.rotationOverLifetime = rotationOverLifetime;
1711
- }
1712
- if (isRecord$4(sizeOverLifetime)) {
1713
- legacy.sizeOverLifetime = sizeOverLifetime;
1714
- }
1715
- if (isRecord$4(colorOverLifetime)) {
1716
- legacy.colorOverLifetime = colorOverLifetime;
1717
- }
1718
- if (typeof geComponentId === 'string') {
1719
- legacy.geComponentId = geComponentId;
1720
- }
1721
- if (isRecord$4(geMask)) {
1722
- legacy.geMask = geMask;
1723
- }
1724
- if (typeof precompRefId === 'string') {
1725
- legacy.precompRefId = precompRefId;
1726
- }
1727
- if (isRecord$4(precompContent)) {
1728
- legacy.precompContent = precompContent;
1729
- }
1730
- return legacy;
1731
- }
1732
- function readGE2IRCompositionMetadata(ir) {
1733
- if (ir.source !== 'ge') {
1734
- return undefined;
1735
- }
1736
- var metadata = ir.metadata;
1737
- if (metadata == null) {
1738
- return undefined;
1739
- }
1740
- var namespaced = metadata['ge2ir'];
1741
- return isRecord$4(namespaced) ? namespaced : undefined;
1742
- }
1743
- function isRecord$4(value) {
1744
- return value != null && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && !Array.isArray(value);
1745
- }
1746
-
1747
1748
  function buildTransformAnimation(layer, ctx) {
1748
1749
  var transform = layer.transform;
1749
1750
  if (transform == null) {
1750
1751
  return {};
1751
1752
  }
1752
1753
  var timeContext = getTimeContext(layer);
1753
- // Passthrough: ge2ir stores raw animation data in metadata to bypass the
1754
+ // Passthrough: ge2ir stores raw animation data in specific.effects to bypass the
1754
1755
  // IR keyframe conversion pipeline. Raw GE data is used verbatim when
1755
1756
  // available; otherwise the standard IR → GE conversion runs.
1756
- var ge2irMetadata = readGE2IRMetadata(ctx.ir, layer);
1757
- var passthroughPosition = ge2irMetadata == null ? void 0 : ge2irMetadata.positionOverLifetime;
1758
- var passthroughRotation = ge2irMetadata == null ? void 0 : ge2irMetadata.rotationOverLifetime;
1759
- var passthroughSize = ge2irMetadata == null ? void 0 : ge2irMetadata.sizeOverLifetime;
1760
- var positionOverLifetime = passthroughPosition != null ? passthroughPosition : buildPositionAnim(transform, timeContext, ctx);
1757
+ var effectsSpecific = getEffectsLayerSpecific(ctx.ir, layer);
1758
+ var passthroughPosition = effectsSpecific == null ? void 0 : effectsSpecific.positionOverLifetime;
1759
+ var passthroughRotation = effectsSpecific == null ? void 0 : effectsSpecific.rotationOverLifetime;
1760
+ var passthroughSize = effectsSpecific == null ? void 0 : effectsSpecific.sizeOverLifetime;
1761
+ var positionOverLifetime = passthroughPosition != null ? passthroughPosition : buildPositionAnim(layer, transform, timeContext, ctx);
1761
1762
  var rotationOverLifetime = passthroughRotation != null ? passthroughRotation : buildRotationAnim(transform, timeContext);
1762
1763
  var sizeOverLifetime = passthroughSize != null ? passthroughSize : buildSizeAnim(transform, timeContext);
1763
1764
  return {
@@ -1766,11 +1767,13 @@ function buildTransformAnimation(layer, ctx) {
1766
1767
  sizeOverLifetime: sizeOverLifetime
1767
1768
  };
1768
1769
  }
1769
- function buildPositionAnim(transform, timeContext, ctx) {
1770
+ function buildPositionAnim(layer, transform, timeContext, ctx) {
1770
1771
  var _posResult_curves_;
1772
+ var _posResult_pathPoints_;
1771
1773
  if (transform.position == null || !transform.position.keyframed) {
1772
1774
  return undefined;
1773
1775
  }
1776
+ assertContiguousPositionSegments(transform.position, layer);
1774
1777
  var posResult = irPositionKeyframesToGE(transform.position, timeContext);
1775
1778
  if (posResult == null) {
1776
1779
  return undefined;
@@ -1778,28 +1781,28 @@ function buildPositionAnim(transform, timeContext, ctx) {
1778
1781
  var pathPoints = [];
1779
1782
  var controlPoints = [];
1780
1783
  var useKeyframeMode = shouldUseKeyframeMode(transform.position);
1781
- for(var _iterator = _create_for_of_iterator_helper_loose(posResult.pathPoints), _step; !(_step = _iterator()).done;){
1782
- var pp = _step.value;
1783
- var point3d = convert2dTo3dPoint(pp[0][0], pp[0][1], 0, ctx.width, ctx.height);
1784
+ var firstPathPoint = (_posResult_pathPoints_ = posResult.pathPoints[0]) == null ? void 0 : _posResult_pathPoints_[0];
1785
+ if (firstPathPoint != null) {
1786
+ var point3d = convert2dTo3dPoint(firstPathPoint[0], firstPathPoint[1], 0, ctx.width, ctx.height);
1784
1787
  pathPoints.push(point3d);
1785
1788
  }
1786
- if (posResult.pathPoints.length > 0) {
1787
- var lastPp = posResult.pathPoints[posResult.pathPoints.length - 1];
1788
- var lastPoint3d = convert2dTo3dPoint(lastPp[1][0], lastPp[1][1], 0, ctx.width, ctx.height);
1789
- pathPoints.push(lastPoint3d);
1789
+ for(var _iterator = _create_for_of_iterator_helper_loose(posResult.pathPoints), _step; !(_step = _iterator()).done;){
1790
+ var pathPoint = _step.value;
1791
+ var endPoint3d = convert2dTo3dPoint(pathPoint[1][0], pathPoint[1][1], 0, ctx.width, ctx.height);
1792
+ pathPoints.push(endPoint3d);
1790
1793
  }
1791
1794
  for(var i = 0; i < posResult.controlPoints.length; i++){
1792
1795
  var cp = posResult.controlPoints[i];
1793
- var pp1 = posResult.pathPoints[i];
1796
+ var pp = posResult.pathPoints[i];
1794
1797
  if (useKeyframeMode) {
1795
- var dx = pp1[1][0] - pp1[0][0];
1796
- var dy = pp1[1][1] - pp1[0][1];
1797
- var cp1 = convert2dTo3dPoint(dx / 3 + pp1[0][0], dy / 3 + pp1[0][1], 0, ctx.width, ctx.height);
1798
- var cp2 = convert2dTo3dPoint(-dx / 3 + pp1[1][0], -dy / 3 + pp1[1][1], 0, ctx.width, ctx.height);
1798
+ var dx = pp[1][0] - pp[0][0];
1799
+ var dy = pp[1][1] - pp[0][1];
1800
+ var cp1 = convert2dTo3dPoint(dx / 3 + pp[0][0], dy / 3 + pp[0][1], 0, ctx.width, ctx.height);
1801
+ var cp2 = convert2dTo3dPoint(-dx / 3 + pp[1][0], -dy / 3 + pp[1][1], 0, ctx.width, ctx.height);
1799
1802
  controlPoints.push(cp1, cp2);
1800
1803
  } else {
1801
- var cp11 = convert2dTo3dPoint(cp[0][0] + pp1[0][0], cp[0][1] + pp1[0][1], 0, ctx.width, ctx.height);
1802
- var cp21 = convert2dTo3dPoint(cp[1][0] + pp1[1][0], cp[1][1] + pp1[1][1], 0, ctx.width, ctx.height);
1804
+ var cp11 = convert2dTo3dPoint(cp[0][0] + pp[0][0], cp[0][1] + pp[0][1], 0, ctx.width, ctx.height);
1805
+ var cp21 = convert2dTo3dPoint(cp[1][0] + pp[1][0], cp[1][1] + pp[1][1], 0, ctx.width, ctx.height);
1803
1806
  controlPoints.push(cp11, cp21);
1804
1807
  }
1805
1808
  }
@@ -1838,112 +1841,39 @@ function buildPositionAnim(transform, timeContext, ctx) {
1838
1841
  ]
1839
1842
  };
1840
1843
  }
1844
+ function assertContiguousPositionSegments(position, layer) {
1845
+ var _loop = function(index) {
1846
+ var segmentEnd = position.keyframes[index].endValue;
1847
+ var nextStart = position.keyframes[index + 1].value;
1848
+ if (segmentEnd == null) {
1849
+ return "continue";
1850
+ }
1851
+ var isContiguous = segmentEnd.every(function(value, dimension) {
1852
+ return Math.abs(value - nextStart[dimension]) <= 1e-6;
1853
+ });
1854
+ if (!isContiguous) {
1855
+ throw new Error("[ge-ir] Layer '" + layer.name + "' has a discontiguous position segment at keyframe " + index + "; " + 'GE path animation cannot preserve a segment endValue that differs from the next keyframe value.');
1856
+ }
1857
+ };
1858
+ for(var index = 0; index < position.keyframes.length - 1; index++)_loop(index);
1859
+ }
1841
1860
  function buildRotationAnim(transform, timeContext) {
1842
1861
  var result = {};
1843
- var hasZ = false;
1844
- var hasX = false;
1845
- var hasY = false;
1846
1862
  var rotation = transform.rotation;
1847
- if (rotation != null) {
1848
- if (rotation.keyframed) {
1849
- var _curves_, _curves_1, _curves_2;
1850
- var curves = irVectorKeyframesToGE(rotation, timeContext);
1851
- if (curves != null && axisHasRotationValue(rotation, 0) && ((_curves_ = curves[0]) == null ? void 0 : _curves_.length)) {
1852
- result['x'] = [
1853
- ValueType.BEZIER_CURVE,
1854
- curves[0]
1855
- ];
1856
- hasX = true;
1857
- }
1858
- if (curves != null && axisHasRotationValue(rotation, 1) && ((_curves_1 = curves[1]) == null ? void 0 : _curves_1.length)) {
1859
- result['y'] = [
1860
- ValueType.BEZIER_CURVE,
1861
- curves[1]
1862
- ];
1863
- hasY = true;
1864
- }
1865
- if (curves != null && axisHasRotationValue(rotation, 2) && ((_curves_2 = curves[2]) == null ? void 0 : _curves_2.length)) {
1866
- result['z'] = [
1867
- ValueType.BEZIER_CURVE,
1868
- curves[2]
1869
- ];
1870
- hasZ = true;
1871
- }
1872
- } else if (rotation.value != null) {
1873
- var _rotation_value = rotation.value, tmp = _rotation_value[0], x = tmp === void 0 ? 0 : tmp, tmp1 = _rotation_value[1], y = tmp1 === void 0 ? 0 : tmp1, tmp2 = _rotation_value[2], z = tmp2 === void 0 ? 0 : tmp2;
1874
- if (Math.abs(x) > 0.0001) {
1875
- result['x'] = [
1876
- ValueType.CONSTANT,
1877
- x
1878
- ];
1879
- hasX = true;
1880
- }
1881
- if (Math.abs(y) > 0.0001) {
1882
- result['y'] = [
1883
- ValueType.CONSTANT,
1884
- y
1885
- ];
1886
- hasY = true;
1887
- }
1888
- if (Math.abs(z) > 0.0001) {
1889
- result['z'] = [
1890
- ValueType.CONSTANT,
1891
- z
1892
- ];
1893
- hasZ = true;
1894
- }
1895
- }
1896
- } else {
1897
- var _separated_x, _separated_x1, _separated_y, _separated_y1, _separated_z, _separated_z1;
1898
- var separated = transform.separatedRotation;
1899
- if (separated == null ? void 0 : (_separated_x = separated.x) == null ? void 0 : _separated_x.keyframed) {
1900
- var curves1 = irScalarKeyframesToGE(separated.x, timeContext);
1901
- if (curves1 != null) {
1902
- result['x'] = [
1903
- ValueType.BEZIER_CURVE,
1904
- curves1[0]
1905
- ];
1906
- hasX = true;
1907
- }
1908
- } else if ((separated == null ? void 0 : (_separated_x1 = separated.x) == null ? void 0 : _separated_x1.value) != null && separated.x.value !== 0) {
1909
- result['x'] = [
1910
- ValueType.CONSTANT,
1911
- separated.x.value
1912
- ];
1913
- hasX = true;
1914
- }
1915
- if (separated == null ? void 0 : (_separated_y = separated.y) == null ? void 0 : _separated_y.keyframed) {
1916
- var curves2 = irScalarKeyframesToGE(separated.y, timeContext);
1917
- if (curves2 != null) {
1918
- result['y'] = [
1919
- ValueType.BEZIER_CURVE,
1920
- curves2[0]
1921
- ];
1922
- hasY = true;
1923
- }
1924
- } else if ((separated == null ? void 0 : (_separated_y1 = separated.y) == null ? void 0 : _separated_y1.value) != null && separated.y.value !== 0) {
1925
- result['y'] = [
1926
- ValueType.CONSTANT,
1927
- separated.y.value
1928
- ];
1929
- hasY = true;
1930
- }
1931
- if (separated == null ? void 0 : (_separated_z = separated.z) == null ? void 0 : _separated_z.keyframed) {
1932
- var curves3 = irScalarKeyframesToGE(separated.z, timeContext);
1933
- if (curves3 != null) {
1934
- result['z'] = [
1935
- ValueType.BEZIER_CURVE,
1936
- curves3[0]
1937
- ];
1938
- hasZ = true;
1939
- }
1940
- } else if ((separated == null ? void 0 : (_separated_z1 = separated.z) == null ? void 0 : _separated_z1.value) != null && separated.z.value !== 0) {
1941
- result['z'] = [
1942
- ValueType.CONSTANT,
1943
- separated.z.value
1944
- ];
1945
- hasZ = true;
1946
- }
1863
+ var x = buildRotationAxis(rotation == null ? void 0 : rotation.x, timeContext);
1864
+ var y = buildRotationAxis(rotation == null ? void 0 : rotation.y, timeContext);
1865
+ var z = buildRotationAxis(rotation == null ? void 0 : rotation.z, timeContext);
1866
+ var hasX = x != null;
1867
+ var hasY = y != null;
1868
+ var hasZ = z != null;
1869
+ if (x != null) {
1870
+ result['x'] = x;
1871
+ }
1872
+ if (y != null) {
1873
+ result['y'] = y;
1874
+ }
1875
+ if (z != null) {
1876
+ result['z'] = z;
1947
1877
  }
1948
1878
  if (!hasZ && !hasX && !hasY) {
1949
1879
  return undefined;
@@ -1955,25 +1885,46 @@ function buildRotationAnim(transform, timeContext) {
1955
1885
  }
1956
1886
  return result;
1957
1887
  }
1958
- function axisHasRotationValue(rotation, axis) {
1959
- var _ref;
1960
- var _rotation_keyframes;
1961
- if (!rotation.keyframed) {
1962
- var _ref1;
1963
- var _rotation_value;
1964
- return Math.abs((_ref1 = (_rotation_value = rotation.value) == null ? void 0 : _rotation_value[axis]) != null ? _ref1 : 0) > 0.0001;
1888
+ function buildRotationAxis(property, timeContext) {
1889
+ if (property == null) {
1890
+ return undefined;
1891
+ }
1892
+ if (!property.keyframed) {
1893
+ return property.value !== 0 ? [
1894
+ ValueType.CONSTANT,
1895
+ property.value
1896
+ ] : undefined;
1897
+ }
1898
+ if (property.keyframes.length === 1) {
1899
+ var value = property.keyframes[0].value;
1900
+ return value !== 0 ? [
1901
+ ValueType.CONSTANT,
1902
+ value
1903
+ ] : undefined;
1904
+ }
1905
+ if (!axisHasRotationValue(property)) {
1906
+ return undefined;
1965
1907
  }
1966
- return (_ref = (_rotation_keyframes = rotation.keyframes) == null ? void 0 : _rotation_keyframes.some(function(keyframe) {
1967
- var _keyframe_value_axis, _ref;
1908
+ var curves = irScalarKeyframesToGE(property, timeContext);
1909
+ return curves != null ? [
1910
+ ValueType.BEZIER_CURVE,
1911
+ curves[0]
1912
+ ] : undefined;
1913
+ }
1914
+ function axisHasRotationValue(rotation) {
1915
+ return rotation.keyframes.some(function(keyframe) {
1968
1916
  var _keyframe_endValue;
1969
- return Math.abs((_keyframe_value_axis = keyframe.value[axis]) != null ? _keyframe_value_axis : 0) > 0.0001 || Math.abs((_ref = (_keyframe_endValue = keyframe.endValue) == null ? void 0 : _keyframe_endValue[axis]) != null ? _ref : 0) > 0.0001;
1970
- })) != null ? _ref : false;
1917
+ return Math.abs(keyframe.value) > 0.0001 || Math.abs((_keyframe_endValue = keyframe.endValue) != null ? _keyframe_endValue : 0) > 0.0001;
1918
+ });
1971
1919
  }
1972
1920
  function buildSizeAnim(transform, timeContext) {
1973
1921
  if (transform.scale == null) {
1974
1922
  return undefined;
1975
1923
  }
1976
1924
  if (transform.scale.keyframed) {
1925
+ if (transform.scale.keyframes.length === 1) {
1926
+ return buildConstantSizeAnimation(transform.scale.keyframes[0].value);
1927
+ }
1977
1928
  var curves = irVectorKeyframesToGE(transform.scale, timeContext);
1978
1929
  if (curves != null && curves.length >= 2) {
1979
1930
  return _extends({
@@ -1995,30 +1946,31 @@ function buildSizeAnim(transform, timeContext) {
1995
1946
  }
1996
1947
  return undefined;
1997
1948
  }
1998
- var scale = transform.scale.value;
1999
- if (Array.isArray(scale) && (Math.abs(scale[0] - 1) > 0.0001 || Math.abs(scale[1] - 1) > 0.0001)) {
2000
- var _scale_;
2001
- return {
2002
- separateAxes: true,
2003
- x: [
2004
- ValueType.CONSTANT,
2005
- scale[0]
2006
- ],
2007
- y: [
2008
- ValueType.CONSTANT,
2009
- scale[1]
2010
- ],
2011
- z: [
2012
- ValueType.CONSTANT,
2013
- (_scale_ = scale[2]) != null ? _scale_ : 1
2014
- ]
2015
- };
1949
+ return buildConstantSizeAnimation(transform.scale.value);
1950
+ }
1951
+ function buildConstantSizeAnimation(scale) {
1952
+ if (Math.abs(scale[0] - 1) <= 0.0001 && Math.abs(scale[1] - 1) <= 0.0001) {
1953
+ return undefined;
2016
1954
  }
2017
- return undefined;
1955
+ return {
1956
+ separateAxes: true,
1957
+ x: [
1958
+ ValueType.CONSTANT,
1959
+ scale[0]
1960
+ ],
1961
+ y: [
1962
+ ValueType.CONSTANT,
1963
+ scale[1]
1964
+ ],
1965
+ z: [
1966
+ ValueType.CONSTANT,
1967
+ scale[2]
1968
+ ]
1969
+ };
2018
1970
  }
2019
1971
  function buildColorAnimation(layer, ir) {
2020
- var _readGE2IRMetadata;
2021
- var passthroughColor = (_readGE2IRMetadata = readGE2IRMetadata(ir, layer)) == null ? void 0 : _readGE2IRMetadata.colorOverLifetime;
1972
+ var _getEffectsLayerSpecific;
1973
+ var passthroughColor = (_getEffectsLayerSpecific = getEffectsLayerSpecific(ir, layer)) == null ? void 0 : _getEffectsLayerSpecific.colorOverLifetime;
2022
1974
  if (passthroughColor != null) {
2023
1975
  return passthroughColor;
2024
1976
  }
@@ -2036,6 +1988,15 @@ function buildColorAnimation(layer, ir) {
2036
1988
  };
2037
1989
  }
2038
1990
  if (transform.opacity.keyframed) {
1991
+ if (transform.opacity.keyframes.length === 1) {
1992
+ var opacityValue = transform.opacity.keyframes[0].value;
1993
+ return opacityValue !== 1 ? {
1994
+ opacity: [
1995
+ ValueType.CONSTANT,
1996
+ opacityValue
1997
+ ]
1998
+ } : undefined;
1999
+ }
2039
2000
  var curves = irScalarKeyframesToGE(transform.opacity, timeContext);
2040
2001
  if (curves != null) {
2041
2002
  return {
@@ -2047,12 +2008,12 @@ function buildColorAnimation(layer, ir) {
2047
2008
  }
2048
2009
  return undefined;
2049
2010
  }
2050
- var opacityValue = transform.opacity.value;
2051
- if (typeof opacityValue === 'number' && opacityValue !== 1) {
2011
+ var opacityValue1 = transform.opacity.value;
2012
+ if (typeof opacityValue1 === 'number' && opacityValue1 !== 1) {
2052
2013
  return {
2053
2014
  opacity: [
2054
2015
  ValueType.CONSTANT,
2055
- opacityValue
2016
+ opacityValue1
2056
2017
  ]
2057
2018
  };
2058
2019
  }
@@ -2134,18 +2095,20 @@ function mapBlendingMode(blendMode) {
2134
2095
  return GE_BLENDING_BY_IR_MODE[blendMode];
2135
2096
  }
2136
2097
 
2137
- var DEFAULT_DISPLAY_SIZE = {
2098
+ var DEFAULT_LOCAL_BOUNDS = {
2099
+ x: 0,
2100
+ y: 0,
2138
2101
  width: 1,
2139
2102
  height: 1
2140
2103
  };
2141
2104
  /**
2142
- * Read the producer-baked display size from an IR layer. When the producer
2143
- * did not resolve one, returns `fallback` (defaults to `{ 1, 1 }` — the
2144
- * value every existing call site was using inline).
2145
- */ function getLayerDisplaySize(layer, fallback) {
2146
- if (fallback === void 0) fallback = DEFAULT_DISPLAY_SIZE;
2147
- var _layer_displaySize;
2148
- return (_layer_displaySize = layer.displaySize) != null ? _layer_displaySize : fallback;
2105
+ * Read source-neutral local bounds from an IR layer. When the producer
2106
+ * did not resolve one, returns `fallback` (defaults to bounds at the origin
2107
+ * with a one-pixel width and height).
2108
+ */ function getLayerLocalBounds(layer, fallback) {
2109
+ if (fallback === void 0) fallback = DEFAULT_LOCAL_BOUNDS;
2110
+ var _layer_localBounds;
2111
+ return (_layer_localBounds = layer.localBounds) != null ? _layer_localBounds : fallback;
2149
2112
  }
2150
2113
 
2151
2114
  function buildComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
@@ -2162,21 +2125,20 @@ function buildComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
2162
2125
  }
2163
2126
  }
2164
2127
  /**
2165
- * Copy the raw GE mask object (from ge2ir passthrough metadata) onto a freshly
2128
+ * Copy the raw GE mask object (from specific.effects passthrough) onto a freshly
2166
2129
  * built component, as a top-level `mask` field matching GE's structure. For a
2167
2130
  * mask SOURCE this carries `{isMask:true, alphaMaskEnabled}`; for a TARGET it
2168
2131
  * carries `{isMask:false, reference, inverted}` where `reference.id` is still
2169
- * the stale GE1 component id — `applyGeMaskRemap` rewrites it in post-process.
2170
- * No-op for non-ge sources (Lottie masks go through the IRLayerNode.mask path).
2171
- */ function applyGeMask(ir, layer, component) {
2172
- var _readGE2IRMetadata;
2173
- var geMask = (_readGE2IRMetadata = readGE2IRMetadata(ir, layer)) == null ? void 0 : _readGE2IRMetadata.geMask;
2174
- if (geMask != null && component['mask'] == null) {
2175
- component['mask'] = _extends({}, geMask);
2132
+ * the stale GE1 component id — `applyGEMaskRemap` rewrites it in post-process.
2133
+ * No-op for non-GE sources (Lottie masks go through the IRLayerNode.mask path).
2134
+ */ function applyGEMask(ir, layer, component) {
2135
+ var _getEffectsLayerSpecific;
2136
+ var effectsMask = (_getEffectsLayerSpecific = getEffectsLayerSpecific(ir, layer)) == null ? void 0 : _getEffectsLayerSpecific.mask;
2137
+ if (effectsMask != null && component['mask'] == null) {
2138
+ component['mask'] = _extends({}, effectsMask);
2176
2139
  }
2177
2140
  }
2178
2141
  function buildSpriteComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
2179
- var _ref;
2180
2142
  var _layer_asset, _layer_asset1;
2181
2143
  var componentId = createId();
2182
2144
  var blending = mapBlendingMode(layer.blendMode);
@@ -2192,7 +2154,8 @@ function buildSpriteComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
2192
2154
  1
2193
2155
  ];
2194
2156
  var textureDataPath;
2195
- var textureUrl = (_ref = (_layer_asset = layer.asset) == null ? void 0 : _layer_asset.url) != null ? _ref : (_layer_asset1 = layer.asset) == null ? void 0 : _layer_asset1.refId;
2157
+ var assetUrl = (_layer_asset = layer.asset) == null ? void 0 : _layer_asset.url;
2158
+ var textureUrl = assetUrl != null && assetUrl !== '' ? assetUrl : (_layer_asset1 = layer.asset) == null ? void 0 : _layer_asset1.refId;
2196
2159
  if (textureUrl != null && textureUrl !== '' && textureUrl !== 'mask://placeholder') {
2197
2160
  textureDataPath = registerTexture(ctx.collector, textureUrl, ctx.textureCache);
2198
2161
  }
@@ -2218,7 +2181,7 @@ function buildSpriteComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
2218
2181
  roundNumber(anchorScaleY, 4)
2219
2182
  ];
2220
2183
  }
2221
- applyGeMask(ctx.ir, layer, component);
2184
+ applyGEMask(ctx.ir, layer, component);
2222
2185
  ctx.collector.components.push(component);
2223
2186
  return componentId;
2224
2187
  }
@@ -2239,7 +2202,7 @@ function buildTextComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
2239
2202
  var textWidth = (_textInfo_width = textInfo.width) != null ? _textInfo_width : estimateTextWidth(textInfo.content, textInfo.fontSize, textInfo.letterSpacing);
2240
2203
  var lineHeight = typeof textInfo.lineHeight === 'number' && textInfo.lineHeight > 0 ? textInfo.lineHeight : textInfo.fontSize;
2241
2204
  var textHeight = Math.max((_textInfo_height = textInfo.height) != null ? _textInfo_height : textInfo.fontSize * 1.2, lineHeight);
2242
- var _getLayerDisplaySize = getLayerDisplaySize(layer), layerWidth = _getLayerDisplaySize.width, layerHeight = _getLayerDisplaySize.height;
2205
+ var _getLayerLocalBounds = getLayerLocalBounds(layer), layerWidth = _getLayerLocalBounds.width, layerHeight = _getLayerLocalBounds.height;
2243
2206
  var textSizeW = roundNumber(ctx.ratio * layerWidth, 4);
2244
2207
  var textSizeH = roundNumber(ctx.ratio * layerHeight, 4);
2245
2208
  var component = {
@@ -2274,7 +2237,7 @@ function buildTextComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx) {
2274
2237
  blending: blending
2275
2238
  })
2276
2239
  };
2277
- applyGeMask(ctx.ir, layer, component);
2240
+ applyGEMask(ctx.ir, layer, component);
2278
2241
  ctx.collector.components.push(component);
2279
2242
  return componentId;
2280
2243
  }
@@ -2296,7 +2259,7 @@ function buildShapeComponent(layer, itemId, ctx) {
2296
2259
  blending: blending
2297
2260
  })
2298
2261
  });
2299
- applyGeMask(ctx.ir, layer, component);
2262
+ applyGEMask(ctx.ir, layer, component);
2300
2263
  ctx.collector.components.push(component);
2301
2264
  return componentId;
2302
2265
  }
@@ -2304,21 +2267,35 @@ function buildShapeOptions(shapeData, ratio, ctx) {
2304
2267
  var options = {
2305
2268
  type: mapShapePrimitiveType(shapeData.primitiveType)
2306
2269
  };
2307
- if (shapeData.size != null) {
2308
- options['xSize'] = roundNumber(shapeData.size[0] * ratio, 4);
2309
- options['ySize'] = roundNumber(shapeData.size[1] * ratio, 4);
2310
- }
2311
- setScaledNumber(options, shapeData, 'xRadius', ratio);
2312
- setScaledNumber(options, shapeData, 'yRadius', ratio);
2313
- setScaledNumber(options, shapeData, 'width', ratio);
2314
- setScaledNumber(options, shapeData, 'height', ratio);
2315
- setScaledNumber(options, shapeData, 'innerRadius', ratio);
2316
- setScaledNumber(options, shapeData, 'outerRadius', ratio);
2317
- setScaledNumber(options, shapeData, 'radius', ratio);
2318
- setRawNumber(options, shapeData, 'roundness');
2319
- setRawNumber(options, shapeData, 'pointCount');
2320
- setRawNumber(options, shapeData, 'innerRoundness');
2321
- setRawNumber(options, shapeData, 'outerRoundness');
2270
+ switch(shapeData.primitiveType){
2271
+ case animationIr.IRShapePrimitiveType.Custom:
2272
+ Object.assign(options, mapCustomPaths(shapeData.customPaths, ratio));
2273
+ break;
2274
+ case animationIr.IRShapePrimitiveType.Rectangle:
2275
+ var _shapeData_roundness;
2276
+ options['width'] = roundNumber(shapeData.width * ratio, 4);
2277
+ options['height'] = roundNumber(shapeData.height * ratio, 4);
2278
+ options['roundness'] = (_shapeData_roundness = shapeData.roundness) != null ? _shapeData_roundness : 0;
2279
+ break;
2280
+ case animationIr.IRShapePrimitiveType.Ellipse:
2281
+ options['xRadius'] = roundNumber(shapeData.xRadius * ratio, 4);
2282
+ options['yRadius'] = roundNumber(shapeData.yRadius * ratio, 4);
2283
+ break;
2284
+ case animationIr.IRShapePrimitiveType.Polygon:
2285
+ var _shapeData_roundness1;
2286
+ options['pointCount'] = shapeData.pointCount;
2287
+ options['radius'] = roundNumber(shapeData.radius * ratio, 4);
2288
+ options['roundness'] = (_shapeData_roundness1 = shapeData.roundness) != null ? _shapeData_roundness1 : 0;
2289
+ break;
2290
+ case animationIr.IRShapePrimitiveType.Star:
2291
+ var _shapeData_innerRoundness, _shapeData_outerRoundness;
2292
+ options['pointCount'] = shapeData.pointCount;
2293
+ options['innerRadius'] = roundNumber(shapeData.innerRadius * ratio, 4);
2294
+ options['outerRadius'] = roundNumber(shapeData.outerRadius * ratio, 4);
2295
+ options['innerRoundness'] = (_shapeData_innerRoundness = shapeData.innerRoundness) != null ? _shapeData_innerRoundness : 0;
2296
+ options['outerRoundness'] = (_shapeData_outerRoundness = shapeData.outerRoundness) != null ? _shapeData_outerRoundness : 0;
2297
+ break;
2298
+ }
2322
2299
  if (shapeData.fills != null && shapeData.fills.length > 0) {
2323
2300
  options['fills'] = shapeData.fills.map(function(fill) {
2324
2301
  return mapShapePaint(fill, ratio, ctx);
@@ -2346,18 +2323,6 @@ function buildShapeOptions(shapeData, ratio, ctx) {
2346
2323
  if (shapeData.strokeJoin != null) {
2347
2324
  options['strokeJoin'] = mapLineJoin(shapeData.strokeJoin);
2348
2325
  }
2349
- if (shapeData.fillRule != null) {
2350
- options['fillRule'] = mapShapeFillRule(shapeData.fillRule);
2351
- }
2352
- if (shapeData.customPaths != null && shapeData.customPaths.length > 0) {
2353
- Object.assign(options, mapCustomPaths(shapeData.customPaths, ratio));
2354
- }
2355
- if (shapeData.trimPath != null) {
2356
- options['trimPath'] = shapeData.trimPath;
2357
- }
2358
- if (shapeData.repeater != null) {
2359
- options['repeater'] = shapeData.repeater;
2360
- }
2361
2326
  return options;
2362
2327
  }
2363
2328
  var _obj;
@@ -2368,8 +2333,6 @@ var _obj2;
2368
2333
  var LINE_CAP_TO_GE = (_obj2 = {}, _obj2[animationIr.IRLineCap.Butt] = 0, _obj2[animationIr.IRLineCap.Round] = 1, _obj2[animationIr.IRLineCap.Square] = 2, _obj2);
2369
2334
  var _obj3;
2370
2335
  var LINE_JOIN_TO_GE = (_obj3 = {}, _obj3[animationIr.IRLineJoin.Round] = 0, _obj3[animationIr.IRLineJoin.Bevel] = 1, _obj3[animationIr.IRLineJoin.Miter] = 2, _obj3);
2371
- var _obj4;
2372
- var SHAPE_FILL_RULE_TO_GE = (_obj4 = {}, _obj4[animationIr.IRShapeFillRule.NonZero] = 0, _obj4[animationIr.IRShapeFillRule.EvenOdd] = 1, _obj4);
2373
2336
  function mapShapePrimitiveType(primitiveType) {
2374
2337
  return SHAPE_PRIMITIVE_TYPE_TO_GE[primitiveType];
2375
2338
  }
@@ -2381,10 +2344,6 @@ function mapLineJoin(lineJoin) {
2381
2344
  var _LINE_JOIN_TO_GE_lineJoin;
2382
2345
  return (_LINE_JOIN_TO_GE_lineJoin = LINE_JOIN_TO_GE[lineJoin]) != null ? _LINE_JOIN_TO_GE_lineJoin : 2;
2383
2346
  }
2384
- function mapShapeFillRule(fillRule) {
2385
- var _SHAPE_FILL_RULE_TO_GE_fillRule;
2386
- return (_SHAPE_FILL_RULE_TO_GE_fillRule = SHAPE_FILL_RULE_TO_GE[fillRule]) != null ? _SHAPE_FILL_RULE_TO_GE_fillRule : 0;
2387
- }
2388
2347
  function mapShapePaint(paint, ratio, ctx) {
2389
2348
  if (paint.type === animationIr.IRFillType.Solid) {
2390
2349
  return {
@@ -2393,7 +2352,7 @@ function mapShapePaint(paint, ratio, ctx) {
2393
2352
  };
2394
2353
  }
2395
2354
  if (paint.type === animationIr.IRFillType.LinearGradient || paint.type === animationIr.IRFillType.RadialGradient || paint.type === animationIr.IRFillType.AngularGradient) {
2396
- return _extends({
2355
+ return {
2397
2356
  type: FILL_TYPE_TO_GE[paint.type],
2398
2357
  gradientStops: [
2399
2358
  ValueType.GRADIENT_COLOR,
@@ -2401,13 +2360,12 @@ function mapShapePaint(paint, ratio, ctx) {
2401
2360
  ],
2402
2361
  startPoint: vec2ToGE(paint.gradientStart, ratio),
2403
2362
  endPoint: vec2ToGE(paint.gradientEnd, ratio)
2404
- }, paint.color != null && {
2405
- color: colorToGE(paint.color)
2406
- });
2363
+ };
2407
2364
  }
2408
2365
  if (paint.type === animationIr.IRFillType.Texture) {
2409
- var _ref, _paint_texture_url, _paint_scaleMode;
2410
- var textureUrl = (_ref = (_paint_texture_url = paint.texture.url) != null ? _paint_texture_url : paint.texture.refId) != null ? _ref : paint.texture.id;
2366
+ var _paint_scaleMode;
2367
+ var textureAssetUrl = paint.texture.url;
2368
+ var textureUrl = textureAssetUrl != null && textureAssetUrl !== '' ? textureAssetUrl : paint.texture.refId;
2411
2369
  var texture = textureUrl != null && ctx != null ? registerTexture(ctx.collector, textureUrl, ctx.textureCache) : undefined;
2412
2370
  return _extends({
2413
2371
  type: FILL_TYPE_TO_GE[paint.type]
@@ -2445,8 +2403,8 @@ function mapCustomPaths(paths, ratio) {
2445
2403
  for(var index = 0; index < path.points.length; index++){
2446
2404
  var _ref, _ref1, _ref2, _ref3;
2447
2405
  var point = path.points[index];
2448
- var easingIn = path.easingIns[index];
2449
- var easingOut = path.easingOuts[index];
2406
+ var easingIn = path.inTangents[index];
2407
+ var easingOut = path.outTangents[index];
2450
2408
  var pointIndex = points.length;
2451
2409
  points.push({
2452
2410
  x: roundNumber(point.x * ratio, 4),
@@ -2467,7 +2425,7 @@ function mapCustomPaths(paths, ratio) {
2467
2425
  });
2468
2426
  }
2469
2427
  shapes.push({
2470
- close: path.close,
2428
+ close: path.closed,
2471
2429
  indexes: indexes
2472
2430
  });
2473
2431
  }
@@ -2478,100 +2436,54 @@ function mapCustomPaths(paths, ratio) {
2478
2436
  shapes: shapes
2479
2437
  };
2480
2438
  }
2481
- function setScaledNumber(options, shapeData, key, ratio) {
2482
- var value = shapeData[key];
2483
- if (typeof value === 'number') {
2484
- options[key] = roundNumber(value * ratio, 4);
2485
- }
2486
- }
2487
- function setRawNumber(options, shapeData, key) {
2488
- var value = shapeData[key];
2489
- if (typeof value === 'number') {
2490
- options[key] = value;
2491
- }
2492
- }
2493
2439
 
2494
- function getStaticAnchorBehavior(ir, layer) {
2495
- if (layer.transformSplit === true) {
2440
+ function planGELayerLowering(ir, layer) {
2441
+ var _getEffectsLayerSpecific;
2442
+ var sourceHierarchy = (_getEffectsLayerSpecific = getEffectsLayerSpecific(ir, layer)) == null ? void 0 : _getEffectsLayerSpecific.sourceHierarchy;
2443
+ if (sourceHierarchy === 'null-sprite-pair') {
2496
2444
  return {
2497
2445
  kind: 'split-null-sprite'
2498
2446
  };
2499
2447
  }
2500
- // B-class real semantic difference — kept as source branch because pre-baking
2501
- // anchorScale/anchorOffset into the IR would require pulling computeAnchorInfo's
2502
- // full input set (text anchorAdjust, static-rotation anchor rotation, display
2503
- // size fallback) into the producer, at high cost with no readability benefit.
2504
- // The split gate itself is already pre-baked via `transformSplit` above.
2505
- //
2506
- // ge source shares the lottie inline-anchor math: ge2ir reverses GE's
2507
- // `renderer.anchor` into IRLayerNode.transform.anchor (px) + displaySize, so
2508
- // computeAnchorInfo reproduces the exact anchorScale/anchorOffset that GE had.
2509
- // Without this, ge layers fall through to the centered [0.5,0.5] default and
2510
- // their authored anchor (e.g. a top-anchored sweep) is lost on round-trip.
2511
- // ge never reaches the lottieNeedsTransformSplit geometry check — its split
2512
- // decision is pre-baked via `transformSplit` by the ge2ir null+sprite merger.
2513
- if (ir.source === 'lottie' || ir.source === 'ge') {
2514
- if (ir.source === 'lottie' && lottieNeedsTransformSplit(layer)) {
2515
- return {
2516
- kind: 'split-null-sprite'
2517
- };
2518
- }
2519
- // The inline-anchor math needs non-zero dimensions to avoid divide-by-zero
2520
- // in `computeAnchorInfo`; substitute the legacy {1, 1} fallback at the call site
2521
- // so the field-level default stays neutral.
2522
- var _getLayerDisplaySize = getLayerDisplaySize(layer), width = _getLayerDisplaySize.width, height = _getLayerDisplaySize.height;
2523
- var info = computeAnchorInfo(layer, width, height);
2448
+ var bounds = getLayerLocalBounds(layer);
2449
+ if (sourceHierarchy !== 'single-item' && needsPivotContainer(layer, bounds)) {
2524
2450
  return {
2525
- kind: 'inline-anchor',
2526
- anchorScale: [
2527
- info.anchorScaleX,
2528
- info.anchorScaleY
2529
- ],
2530
- anchorOffset: [
2531
- info.anchorOffsetX,
2532
- info.anchorOffsetY
2533
- ]
2451
+ kind: 'split-null-sprite'
2534
2452
  };
2535
2453
  }
2536
- // dsl layers with off-center anchor have `transformSplit = true` set by the
2537
- // producer, caught by the guard at the top. Any layer reaching here is
2538
- // centered — return the default inline-anchor.
2454
+ var info = computeAnchorInfo(layer, bounds);
2539
2455
  return {
2540
2456
  kind: 'inline-anchor',
2541
2457
  anchorScale: [
2542
- 0.5,
2543
- 0.5
2458
+ info.anchorScaleX,
2459
+ info.anchorScaleY
2544
2460
  ],
2545
2461
  anchorOffset: [
2546
- 0,
2547
- 0
2462
+ info.anchorOffsetX,
2463
+ info.anchorOffsetY
2548
2464
  ]
2549
2465
  };
2550
2466
  }
2551
- function lottieNeedsTransformSplit(layer) {
2552
- var _transform_rotation, _sep_x, _sep_y, _sep_z, _transform_scale;
2467
+ function needsPivotContainer(layer, bounds) {
2468
+ var _rotation_x, _rotation_y, _rotation_z, _transform_scale;
2553
2469
  if (layer.type !== 'image' && layer.type !== 'solid') {
2554
2470
  return false;
2555
2471
  }
2556
- // Without a producer-baked displaySize we cannot decide off-center;
2557
- // fall through to inline-anchor (matches the pre-displaySize behavior
2558
- // where missing dimensions returned the {1, 1} default and never split).
2559
- var size = layer.displaySize;
2560
- if (size == null) {
2472
+ if (layer.localBounds == null) {
2561
2473
  return false;
2562
2474
  }
2563
- var width = size.width, height = size.height;
2475
+ var x = bounds.x, y = bounds.y, width = bounds.width, height = bounds.height;
2564
2476
  if (width <= 0 || height <= 0) {
2565
2477
  return false;
2566
2478
  }
2567
2479
  var anchor = getStaticAnchor(layer);
2568
- var anchorOffCenter = Math.abs(anchor[0] - width / 2) > 0.5 || Math.abs(anchor[1] - height / 2) > 0.5;
2480
+ var anchorOffCenter = Math.abs(anchor[0] - (x + width / 2)) > 0.5 || Math.abs(anchor[1] - (y + height / 2)) > 0.5;
2569
2481
  if (!anchorOffCenter) {
2570
2482
  return false;
2571
2483
  }
2572
2484
  var transform = layer.transform;
2573
- var sep = transform == null ? void 0 : transform.separatedRotation;
2574
- var hasRotationAnim = (transform == null ? void 0 : (_transform_rotation = transform.rotation) == null ? void 0 : _transform_rotation.keyframed) === true || (sep == null ? void 0 : (_sep_x = sep.x) == null ? void 0 : _sep_x.keyframed) === true || (sep == null ? void 0 : (_sep_y = sep.y) == null ? void 0 : _sep_y.keyframed) === true || (sep == null ? void 0 : (_sep_z = sep.z) == null ? void 0 : _sep_z.keyframed) === true;
2485
+ var rotation = transform == null ? void 0 : transform.rotation;
2486
+ var hasRotationAnim = (rotation == null ? void 0 : (_rotation_x = rotation.x) == null ? void 0 : _rotation_x.keyframed) === true || (rotation == null ? void 0 : (_rotation_y = rotation.y) == null ? void 0 : _rotation_y.keyframed) === true || (rotation == null ? void 0 : (_rotation_z = rotation.z) == null ? void 0 : _rotation_z.keyframed) === true;
2575
2487
  var hasScaleAnim = (transform == null ? void 0 : (_transform_scale = transform.scale) == null ? void 0 : _transform_scale.keyframed) === true;
2576
2488
  return hasRotationAnim || hasScaleAnim;
2577
2489
  }
@@ -2580,7 +2492,7 @@ function processNullLayer(layer, ctx) {
2580
2492
  var itemId = createId();
2581
2493
  var layerIndex = layer.index;
2582
2494
  ctx.layerToItemId[layerIndex] = itemId;
2583
- var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2495
+ var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate, ctx.ir.inPoint), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2584
2496
  var animation = buildTransformAnimation(layer, ctx);
2585
2497
  var position = computeStaticPosition(layer, ctx);
2586
2498
  var objectBindingTrackId = buildTimelineTracks(ctx.collector, delay, layerDuration, 4, animation, 'null');
@@ -2590,7 +2502,7 @@ function processNullLayer(layer, ctx) {
2590
2502
  name: layer.name,
2591
2503
  duration: layerDuration,
2592
2504
  type: '3',
2593
- visible: layer.visibility.enabled && !layer.visibility.hidden,
2505
+ visible: layer.visible,
2594
2506
  endBehavior: 4,
2595
2507
  delay: delay,
2596
2508
  renderLevel: 'B+',
@@ -2626,19 +2538,19 @@ function processPrecompLayer(layer, ctx) {
2626
2538
  var itemId = createId();
2627
2539
  var layerIndex = layer.index;
2628
2540
  ctx.layerToItemId[layerIndex] = itemId;
2629
- var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2541
+ var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate, ctx.ir.inPoint), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2630
2542
  var animation = buildTransformAnimation(layer, ctx);
2631
2543
  var position = computeStaticPosition(layer, ctx);
2632
2544
  var objectBindingTrackId = buildTimelineTracks(ctx.collector, delay, layerDuration, 4, animation, 'precomp');
2633
- var geMetadata = readGE2IRMetadata(ctx.ir, layer);
2634
- var content = buildPrecompContent(geMetadata == null ? void 0 : geMetadata.precompContent, geMetadata == null ? void 0 : geMetadata.precompRefId);
2545
+ var effectsSpecific = getEffectsLayerSpecific(ctx.ir, layer);
2546
+ var content = buildPrecompContent(effectsSpecific == null ? void 0 : effectsSpecific.precompContent, effectsSpecific == null ? void 0 : effectsSpecific.precompRefId);
2635
2547
  var item = {
2636
2548
  id: itemId,
2637
2549
  dataType: 'VFXItemData',
2638
2550
  name: layer.name,
2639
2551
  duration: layerDuration,
2640
2552
  type: '7',
2641
- visible: layer.visibility.enabled && !layer.visibility.hidden,
2553
+ visible: layer.visible,
2642
2554
  endBehavior: 4,
2643
2555
  delay: delay,
2644
2556
  renderLevel: 'B+',
@@ -2682,14 +2594,13 @@ function isRecord$3(value) {
2682
2594
  * the layer's logical position; the sprite/text child carries the visual
2683
2595
  * content offset by the anchor so the pivot is at the right point.
2684
2596
  *
2685
- * Used by both `processParentLayer` (layers referenced as `parent` by others)
2686
- * and `processTransformSplitLayer` (layers with `transformSplit=true`). The
2687
- * only knob is `childScale` — parent-layer callers pass a text-aware scale
2688
- * while transformSplit always uses `[1, 1, 1]`.
2689
- */ function emitNullSpritePair(layer, ctx, childScale) {
2597
+ * Used by both `processParentLayer` and GE lowering for layers that require a
2598
+ * pivot container.
2599
+ */ function emitNullSpritePair(layer, ctx) {
2690
2600
  var layerIndex = layer.index;
2691
- var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2692
- var _getLayerDisplaySize = getLayerDisplaySize(layer), layerWidth = _getLayerDisplaySize.width, layerHeight = _getLayerDisplaySize.height;
2601
+ var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate, ctx.ir.inPoint), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2602
+ var bounds = getLayerLocalBounds(layer);
2603
+ var x = bounds.x, y = bounds.y, layerWidth = bounds.width, layerHeight = bounds.height;
2693
2604
  var nullItemId = createId();
2694
2605
  ctx.layerToItemId[layerIndex] = nullItemId;
2695
2606
  var nullAnimation = buildTransformAnimation(layer, ctx);
@@ -2734,9 +2645,11 @@ function isRecord$3(value) {
2734
2645
  });
2735
2646
  var childItemId = createId();
2736
2647
  var anchor = getStaticAnchor(layer);
2648
+ var centerX = x + layerWidth / 2;
2649
+ var centerY = y + layerHeight / 2;
2737
2650
  var childPosition = [
2738
- -ctx.ratio * (anchor[0] - layerWidth / 2),
2739
- ctx.ratio * (anchor[1] - layerHeight / 2),
2651
+ -ctx.ratio * (anchor[0] - centerX),
2652
+ ctx.ratio * (anchor[1] - centerY),
2740
2653
  0
2741
2654
  ];
2742
2655
  var childColorAnim = buildColorAnimation(layer, ctx.ir);
@@ -2749,13 +2662,22 @@ function isRecord$3(value) {
2749
2662
  }
2750
2663
  var scaledW = roundNumber(ctx.ratio * layerWidth, 4);
2751
2664
  var scaledH = roundNumber(ctx.ratio * layerHeight, 4);
2665
+ var childScale = layer.type === 'text' ? [
2666
+ scaledW,
2667
+ scaledH,
2668
+ 1
2669
+ ] : [
2670
+ 1,
2671
+ 1,
2672
+ 1
2673
+ ];
2752
2674
  var childItem = {
2753
2675
  id: childItemId,
2754
2676
  dataType: 'VFXItemData',
2755
2677
  name: layer.name,
2756
2678
  duration: layerDuration,
2757
2679
  type: getGEItemTypeCode(layer.type),
2758
- visible: layer.visibility.enabled && !layer.visibility.hidden,
2680
+ visible: layer.visible,
2759
2681
  endBehavior: 0,
2760
2682
  delay: delay,
2761
2683
  renderLevel: 'B+',
@@ -2786,35 +2708,24 @@ function isRecord$3(value) {
2786
2708
  });
2787
2709
  }
2788
2710
  function processParentLayer(layer, ctx) {
2789
- var _getLayerDisplaySize = getLayerDisplaySize(layer), layerWidth = _getLayerDisplaySize.width, layerHeight = _getLayerDisplaySize.height;
2790
- var scaledW = roundNumber(ctx.ratio * layerWidth, 4);
2791
- var scaledH = roundNumber(ctx.ratio * layerHeight, 4);
2792
- var childScale = layer.type === 'text' ? [
2793
- scaledW,
2794
- scaledH,
2795
- 1
2796
- ] : [
2797
- 1,
2798
- 1,
2799
- 1
2800
- ];
2801
- emitNullSpritePair(layer, ctx, childScale);
2711
+ emitNullSpritePair(layer, ctx);
2802
2712
  }
2803
2713
  function processVisualLayer(layer, ctx) {
2804
- if (layer.type === 'shape' && layer.shapes != null && layer.shapes.length > 0) {
2805
- processShapeLayerMultiItem(layer, ctx);
2714
+ var strategy = planGELayerLowering(ctx.ir, layer);
2715
+ if (strategy.kind === 'split-null-sprite') {
2716
+ processPivotContainerLayer(layer, ctx);
2806
2717
  return;
2807
2718
  }
2808
- var strategy = getStaticAnchorBehavior(ctx.ir, layer);
2809
- if (strategy.kind === 'split-null-sprite') {
2810
- processTransformSplitLayer(layer, ctx);
2719
+ if (layer.type === 'shape' && layer.shapes != null && layer.shapes.length > 0) {
2720
+ processShapeLayerMultiItem(layer, ctx);
2811
2721
  return;
2812
2722
  }
2813
2723
  var itemId = createId();
2814
2724
  var layerIndex = layer.index;
2815
2725
  ctx.layerToItemId[layerIndex] = itemId;
2816
- var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2817
- var _getLayerDisplaySize = getLayerDisplaySize(layer), layerWidth = _getLayerDisplaySize.width, layerHeight = _getLayerDisplaySize.height;
2726
+ var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate, ctx.ir.inPoint), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2727
+ var bounds = getLayerLocalBounds(layer);
2728
+ var layerWidth = bounds.width, layerHeight = bounds.height;
2818
2729
  var scaledW = ctx.ratio * layerWidth;
2819
2730
  var scaledH = ctx.ratio * layerHeight;
2820
2731
  var _strategy_anchorScale = strategy.anchorScale, anchorScaleX = _strategy_anchorScale[0], anchorScaleY = _strategy_anchorScale[1];
@@ -2825,7 +2736,7 @@ function processVisualLayer(layer, ctx) {
2825
2736
  colorOverLifetime: colorAnimation
2826
2737
  });
2827
2738
  var rawPosition = computeStaticPosition(layer, ctx, anchorOffsetX, anchorOffsetY);
2828
- var position = applyScalePositionAdjust(rawPosition, layer, layerWidth, layerHeight, ctx.ratio);
2739
+ var position = applyScalePositionAdjust(rawPosition, layer, bounds, ctx.ratio);
2829
2740
  var itemType = getGEItemType(layer.type);
2830
2741
  var objectBindingTrackId = buildTimelineTracks(ctx.collector, delay, layerDuration, 0, fullAnimation, itemType);
2831
2742
  var componentId = buildComponent(layer, itemId, anchorScaleX, anchorScaleY, ctx);
@@ -2852,7 +2763,7 @@ function processVisualLayer(layer, ctx) {
2852
2763
  name: layer.name,
2853
2764
  duration: layerDuration,
2854
2765
  type: getGEItemTypeCode(layer.type),
2855
- visible: layer.visibility.enabled && !layer.visibility.hidden,
2766
+ visible: layer.visible,
2856
2767
  endBehavior: 0,
2857
2768
  delay: delay,
2858
2769
  renderLevel: 'B+',
@@ -2881,19 +2792,24 @@ function processVisualLayer(layer, ctx) {
2881
2792
  layerIndex: layerIndex
2882
2793
  });
2883
2794
  }
2884
- function processTransformSplitLayer(layer, ctx) {
2885
- emitNullSpritePair(layer, ctx, [
2886
- 1,
2887
- 1,
2888
- 1
2889
- ]);
2795
+ function processPivotContainerLayer(layer, ctx) {
2796
+ emitNullSpritePair(layer, ctx);
2890
2797
  }
2891
2798
  function processShapeLayerMultiItem(layer, ctx) {
2892
2799
  var layerIndex = layer.index;
2893
- var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2894
- var _getLayerDisplaySize = getLayerDisplaySize(layer), layerWidth = _getLayerDisplaySize.width, layerHeight = _getLayerDisplaySize.height;
2800
+ var _computeLayerTiming = computeLayerTiming(layer, ctx.frameRate, ctx.ir.inPoint), delay = _computeLayerTiming.delay, layerDuration = _computeLayerTiming.layerDuration;
2801
+ // A GE Shape item commonly has no transform.size, so ge2ir cannot recover
2802
+ // layer-local bounds. Treat missing bounds as empty here: the generic 1×1
2803
+ // fallback would invent a half-pixel anchor offset and shift every rebuilt
2804
+ // shape (notably mask sources) away from its authored position.
2805
+ var bounds = getLayerLocalBounds(layer, {
2806
+ x: 0,
2807
+ y: 0,
2808
+ width: 0,
2809
+ height: 0
2810
+ });
2895
2811
  var anchor = getStaticAnchor(layer);
2896
- var _computeAnchorInfo = computeAnchorInfo(layer, layerWidth, layerHeight), anchorOffsetX = _computeAnchorInfo.anchorOffsetX, anchorOffsetY = _computeAnchorInfo.anchorOffsetY;
2812
+ var _computeAnchorInfo = computeAnchorInfo(layer, bounds), anchorOffsetX = _computeAnchorInfo.anchorOffsetX, anchorOffsetY = _computeAnchorInfo.anchorOffsetY;
2897
2813
  var animation = buildTransformAnimation(layer, ctx);
2898
2814
  var colorAnimation = buildColorAnimation(layer, ctx.ir);
2899
2815
  var fullAnimation = _extends({}, animation, {
@@ -2928,7 +2844,7 @@ function processShapeLayerMultiItem(layer, ctx) {
2928
2844
  });
2929
2845
  // Mask source shape (isMask:true) — copy onto the first shape item only.
2930
2846
  if (shapeIdx === 0) {
2931
- applyGeMask(ctx.ir, layer, component);
2847
+ applyGEMask(ctx.ir, layer, component);
2932
2848
  }
2933
2849
  ctx.collector.components.push(component);
2934
2850
  if (shapeIdx === 0) {
@@ -2941,7 +2857,7 @@ function processShapeLayerMultiItem(layer, ctx) {
2941
2857
  name: shapeIdx === 0 ? layer.name : layer.name + "_shape_" + shapeIdx,
2942
2858
  duration: layerDuration,
2943
2859
  type: 'shape',
2944
- visible: layer.visibility.enabled && !layer.visibility.hidden,
2860
+ visible: layer.visible,
2945
2861
  endBehavior: 0,
2946
2862
  delay: delay,
2947
2863
  renderLevel: 'B+',
@@ -3074,16 +2990,20 @@ function deriveDuration(ir) {
3074
2990
  }
3075
2991
  /**
3076
2992
  * Map IR composition end behavior to GE's numeric end-behavior.
3077
- * Lottie IR currently leaves this unset; treat undefined as Loop (5) so the
3078
- * legacy lottie behavior is preserved. dsl2ge writes either Loop or Stop.
2993
+ * Undefined defaults to Restart (5) for backward compatibility. DSL's boolean
2994
+ * loop flag maps to either Restart or Destroy at the adapter boundary.
3079
2995
  */ function mapCompositionEndBehavior(eb) {
3080
- if (eb == null || eb === animationIr.IREndBehavior.Loop) {
3081
- return 5;
3082
- }
3083
- if (eb === animationIr.IREndBehavior.Hold) {
3084
- return 4;
2996
+ switch(eb){
2997
+ case undefined:
2998
+ case animationIr.IREndBehavior.Restart:
2999
+ return 5;
3000
+ case animationIr.IREndBehavior.Forward:
3001
+ return 2;
3002
+ case animationIr.IREndBehavior.Freeze:
3003
+ return 4;
3004
+ case animationIr.IREndBehavior.Destroy:
3005
+ return 0;
3085
3006
  }
3086
- return 0;
3087
3007
  }
3088
3008
  function colorToRoundedRgba(color) {
3089
3009
  return [
@@ -3154,13 +3074,10 @@ function applyMasks(ir, collector, processedItems, ratio, width, height, frameRa
3154
3074
  continue;
3155
3075
  }
3156
3076
  var layerComponentId = lookup.getComponentId(layer.index);
3157
- buildMaskForLayer(layer, layerItemId, layerComponentId, collector, processedItems, ratio, width, height, frameRate, lookup, maskSlotMeta, componentById, maskData);
3077
+ buildMaskForLayer(layer, layerItemId, layerComponentId, collector, processedItems, ratio, width, height, frameRate, ir.inPoint, lookup, maskSlotMeta, componentById, maskData);
3158
3078
  }
3159
3079
  }
3160
- function getPrimaryPath(mask) {
3161
- return mask.paths[0];
3162
- }
3163
- function buildMaskForLayer(layer, layerItemId, layerComponentId, collector, processedItems, ratio, width, height, frameRate, lookup, maskSlotMeta, componentById, maskData) {
3080
+ function buildMaskForLayer(layer, layerItemId, layerComponentId, collector, processedItems, ratio, width, height, frameRate, compositionInPoint, lookup, maskSlotMeta, componentById, maskData) {
3164
3081
  var mask = maskData != null ? maskData : layer.mask;
3165
3082
  var maskItemId = createId();
3166
3083
  var maskComponentId = createId();
@@ -3168,7 +3085,7 @@ function buildMaskForLayer(layer, layerItemId, layerComponentId, collector, proc
3168
3085
  var _getStaticAnchor = getStaticAnchor(layer), anchorX = _getStaticAnchor[0], anchorY = _getStaticAnchor[1];
3169
3086
  var maskPosX = roundNumber((maskBounds.cx - anchorX) * ratio, 4);
3170
3087
  var maskPosY = roundNumber(-(maskBounds.cy - anchorY) * ratio, 4);
3171
- var timing = computeLayerTiming(layer, frameRate);
3088
+ var timing = computeLayerTiming(layer, frameRate, compositionInPoint);
3172
3089
  var delay = timing.delay;
3173
3090
  var maskDuration = timing.layerDuration;
3174
3091
  var layerIsParent = lookup.isParentLayer(layer.index) || layer.type === 'null' || layer.type === 'precomp';
@@ -3360,8 +3277,8 @@ function computePointBounds(points) {
3360
3277
  };
3361
3278
  }
3362
3279
  function isMaskExactCrop(mask, layer, width, height, lookup) {
3363
- var path = getPrimaryPath(mask);
3364
- if (path == null || path.points.length === 0) {
3280
+ var path = mask.path;
3281
+ if (path.points.length === 0) {
3365
3282
  return true;
3366
3283
  }
3367
3284
  var _computePointBounds = computePointBounds(path.points), minX = _computePointBounds.minX, minY = _computePointBounds.minY, maxX = _computePointBounds.maxX, maxY = _computePointBounds.maxY;
@@ -3386,8 +3303,8 @@ function isMaskExactCrop(mask, layer, width, height, lookup) {
3386
3303
  return false;
3387
3304
  }
3388
3305
  function getMaskBounds(mask) {
3389
- var path = getPrimaryPath(mask);
3390
- if (path == null || path.points.length === 0) {
3306
+ var path = mask.path;
3307
+ if (path.points.length === 0) {
3391
3308
  return {
3392
3309
  cx: 0,
3393
3310
  cy: 0,
@@ -3404,47 +3321,41 @@ function getMaskBounds(mask) {
3404
3321
  };
3405
3322
  }
3406
3323
  function isSimpleRectMask(mask) {
3407
- var path = getPrimaryPath(mask);
3408
- if (path == null) {
3409
- return false;
3410
- }
3411
- return path.points.length === 4 && path.easingIns.every(function(e) {
3412
- return Math.abs(e.x) < 0.01 && Math.abs(e.y) < 0.01;
3413
- }) && path.easingOuts.every(function(e) {
3414
- return Math.abs(e.x) < 0.01 && Math.abs(e.y) < 0.01;
3324
+ var path = mask.path;
3325
+ return path.points.length === 4 && path.inTangents.every(function(tangent) {
3326
+ return Math.abs(tangent.x) < 0.01 && Math.abs(tangent.y) < 0.01;
3327
+ }) && path.outTangents.every(function(tangent) {
3328
+ return Math.abs(tangent.x) < 0.01 && Math.abs(tangent.y) < 0.01;
3415
3329
  });
3416
3330
  }
3417
3331
  function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ratio) {
3418
- var _ref;
3419
- var path = getPrimaryPath(mask);
3332
+ var path = mask.path;
3420
3333
  var customPoints = [];
3421
3334
  var customEasingIns = [];
3422
3335
  var customEasingOuts = [];
3423
3336
  var customIndexes = [];
3424
- if (path != null) {
3425
- for(var idx = 0; idx < path.points.length; idx++){
3426
- var _ref1, _ref2, _ref3, _ref4;
3427
- var pt = path.points[idx];
3428
- var ei = path.easingIns[idx];
3429
- var eo = path.easingOuts[idx];
3430
- customPoints.push({
3431
- x: roundNumber((pt.x - bounds.cx) * ratio, 4),
3432
- y: roundNumber(-(pt.y - bounds.cy) * ratio, 4)
3433
- });
3434
- customEasingIns.push({
3435
- x: roundNumber(((_ref1 = ei == null ? void 0 : ei.x) != null ? _ref1 : 0) * ratio, 4),
3436
- y: roundNumber(-((_ref2 = ei == null ? void 0 : ei.y) != null ? _ref2 : 0) * ratio, 4)
3437
- });
3438
- customEasingOuts.push({
3439
- x: roundNumber(((_ref3 = eo == null ? void 0 : eo.x) != null ? _ref3 : 0) * ratio, 4),
3440
- y: roundNumber(-((_ref4 = eo == null ? void 0 : eo.y) != null ? _ref4 : 0) * ratio, 4)
3441
- });
3442
- customIndexes.push({
3443
- point: idx,
3444
- easingIn: idx,
3445
- easingOut: idx
3446
- });
3447
- }
3337
+ for(var idx = 0; idx < path.points.length; idx++){
3338
+ var _ref, _ref1, _ref2, _ref3;
3339
+ var pt = path.points[idx];
3340
+ var ei = path.inTangents[idx];
3341
+ var eo = path.outTangents[idx];
3342
+ customPoints.push({
3343
+ x: roundNumber((pt.x - bounds.cx) * ratio, 4),
3344
+ y: roundNumber(-(pt.y - bounds.cy) * ratio, 4)
3345
+ });
3346
+ customEasingIns.push({
3347
+ x: roundNumber(((_ref = ei == null ? void 0 : ei.x) != null ? _ref : 0) * ratio, 4),
3348
+ y: roundNumber(-((_ref1 = ei == null ? void 0 : ei.y) != null ? _ref1 : 0) * ratio, 4)
3349
+ });
3350
+ customEasingOuts.push({
3351
+ x: roundNumber(((_ref2 = eo == null ? void 0 : eo.x) != null ? _ref2 : 0) * ratio, 4),
3352
+ y: roundNumber(-((_ref3 = eo == null ? void 0 : eo.y) != null ? _ref3 : 0) * ratio, 4)
3353
+ });
3354
+ customIndexes.push({
3355
+ point: idx,
3356
+ easingIn: idx,
3357
+ easingOut: idx
3358
+ });
3448
3359
  }
3449
3360
  return {
3450
3361
  id: maskComponentId,
@@ -3456,7 +3367,7 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3456
3367
  easingOuts: customEasingOuts,
3457
3368
  shapes: [
3458
3369
  {
3459
- close: (_ref = path == null ? void 0 : path.close) != null ? _ref : true,
3370
+ close: path.closed,
3460
3371
  indexes: customIndexes
3461
3372
  }
3462
3373
  ],
@@ -3489,10 +3400,10 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3489
3400
  * Remap GE mask references after ge2ir round-trip.
3490
3401
  *
3491
3402
  * ge2ir carries each masked component's raw `mask` object verbatim (via
3492
- * `IRLayerNode.metadata.ge2ir.geMask`), but `mask.reference.id` still points at the
3403
+ * `IRLayerNode.specific.effects.mask`), but `mask.reference.id` still points at the
3493
3404
  * ORIGINAL (GE1) mask-source component id, which ir2ge has regenerated. This
3494
3405
  * pass rewrites every target's `reference.id` from the stale GE1 id to the
3495
- * freshly-minted GE2 component id, using the `geComponentId → newId` map built
3406
+ * freshly-minted GE2 component id, using the `GEComponentId → newId` map built
3496
3407
  * during the layer walk.
3497
3408
  *
3498
3409
  * Mirrors `applyParenting`: an IR-side reference (here the stale id stored in
@@ -3500,7 +3411,7 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3500
3411
  * no `reference` and are skipped. Dangling references (source not regenerated —
3501
3412
  * e.g. dropped by the null+sprite merger) have their `mask` removed so the GE
3502
3413
  * runtime doesn't choke on an id that resolves to nothing.
3503
- */ function applyGeMaskRemap(collector, geComponentIdToNewId) {
3414
+ */ function applyGEMaskRemap(collector, GEComponentIdToNewId) {
3504
3415
  for(var _iterator = _create_for_of_iterator_helper_loose(collector.components), _step; !(_step = _iterator()).done;){
3505
3416
  var component = _step.value;
3506
3417
  var mask = component['mask'];
@@ -3512,7 +3423,7 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3512
3423
  if (oldId == null) {
3513
3424
  continue;
3514
3425
  }
3515
- var newId = geComponentIdToNewId[oldId];
3426
+ var newId = GEComponentIdToNewId[oldId];
3516
3427
  if (newId == null) {
3517
3428
  // Dangling: the referenced source was not regenerated. Drop the mask so
3518
3429
  // the target renders unmasked rather than referencing a nonexistent id.
@@ -3527,15 +3438,15 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3527
3438
  * Normalize child visibility delays so children never appear before their parent.
3528
3439
  *
3529
3440
  * Topologically sorts items (parent-first) so by the time we process any child
3530
- * its parent's delay/duration are already finalized. For transform-only
3531
- * parent-link children, we instead advance the parent's delay/duration so the
3441
+ * its parent's delay/duration are already finalized. For children with an
3442
+ * independent lifetime, we instead advance the parent's delay/duration so the
3532
3443
  * child can render from its own start time (GE requires the parent to be active
3533
3444
  * for transform inheritance, but the parent-link relationship does not propagate
3534
3445
  * visibility). Only the ActivationTrack clip is updated; TransformTrack
3535
3446
  * keyframes are normalized to the original time range and would hold their
3536
3447
  * first frame value if the track started earlier.
3537
3448
  */ function normalizeChildVisibilityByParentDelays(param) {
3538
- var items = param.items, miscs = param.miscs, processedItems = param.processedItems, _param_transformOnlyParentLinkItemIds = param.transformOnlyParentLinkItemIds, transformOnlyParentLinkItemIds = _param_transformOnlyParentLinkItemIds === void 0 ? new Set() : _param_transformOnlyParentLinkItemIds, roundNumber = param.roundNumber;
3449
+ var items = param.items, miscs = param.miscs, processedItems = param.processedItems, _param_independentLifetimeChildItemIds = param.independentLifetimeChildItemIds, independentLifetimeChildItemIds = _param_independentLifetimeChildItemIds === void 0 ? new Set() : _param_independentLifetimeChildItemIds, roundNumber = param.roundNumber;
3539
3450
  var itemById = new Map();
3540
3451
  for(var _iterator = _create_for_of_iterator_helper_loose(items), _step; !(_step = _iterator()).done;){
3541
3452
  var item = _step.value;
@@ -3551,9 +3462,9 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3551
3462
  var misc = _step2.value;
3552
3463
  miscById.set(misc['id'], misc);
3553
3464
  }
3554
- // Phase 1: Advance transform-only parent-link parents so their children can
3465
+ // Phase 1: Advance transform parents so independent-lifetime children can
3555
3466
  // render from the child's own start time.
3556
- advanceTransformOnlyParentLinkParents(items, itemById, processedByItemId, miscById, transformOnlyParentLinkItemIds, roundNumber);
3467
+ advanceIndependentLifetimeParents(items, itemById, processedByItemId, miscById, independentLifetimeChildItemIds, roundNumber);
3557
3468
  // Phase 2: Normalize precomp child visibility (unchanged).
3558
3469
  var effectiveDelayCache = new Map();
3559
3470
  function getEffectiveDelay(itemId, visited) {
@@ -3615,8 +3526,8 @@ function buildPolygonMaskComponent(maskComponentId, maskItemId, mask, bounds, ra
3615
3526
  syncTimelineClips(itemId, effectiveDelay, newDuration, processedByItemId, miscById, roundNumber);
3616
3527
  }
3617
3528
  }
3618
- function advanceTransformOnlyParentLinkParents(items, itemById, processedByItemId, miscById, transformOnlyParentLinkItemIds, roundNumber) {
3619
- if (transformOnlyParentLinkItemIds.size === 0) {
3529
+ function advanceIndependentLifetimeParents(items, itemById, processedByItemId, miscById, independentLifetimeChildItemIds, roundNumber) {
3530
+ if (independentLifetimeChildItemIds.size === 0) {
3620
3531
  return;
3621
3532
  }
3622
3533
  // Collect the maximum advance (head) and extension (tail) needed per parent.
@@ -3625,7 +3536,7 @@ function advanceTransformOnlyParentLinkParents(items, itemById, processedByItemI
3625
3536
  for(var _iterator = _create_for_of_iterator_helper_loose(items), _step; !(_step = _iterator()).done;){
3626
3537
  var item = _step.value;
3627
3538
  var _item_delay, _item_duration, _parentItem_delay, _parentItem_duration;
3628
- if (!transformOnlyParentLinkItemIds.has(item['id'])) {
3539
+ if (!independentLifetimeChildItemIds.has(item['id'])) {
3629
3540
  continue;
3630
3541
  }
3631
3542
  var parentId = item['parentId'];
@@ -3761,18 +3672,18 @@ function syncTimelineClips(itemId, delay, duration, processedByItemId, miscById,
3761
3672
  */ function applyPostProcess(ir, state) {
3762
3673
  applyParentingStep(ir, state);
3763
3674
  applySharedMaskPostProcess(ir, state);
3764
- applyGeMaskRemapStep(ir, state);
3675
+ applyGEMaskRemapStep(ir, state);
3765
3676
  applyVisibilityStep(ir, state);
3766
3677
  }
3767
- function applyGeMaskRemapStep(ir, state) {
3768
- // Only ge-sourced compositions carry passthrough mask references that need
3678
+ function applyGEMaskRemapStep(ir, state) {
3679
+ // Only Effects-sourced compositions carry passthrough mask references that need
3769
3680
  // remapping. Lottie/dsl masks are built with correct ids by applyMasks and
3770
- // must not be touched (their reference ids are absent from the ge map, so a
3681
+ // must not be touched (their reference ids are absent from the GE map, so a
3771
3682
  // blind remap would wrongly delete them).
3772
- if (ir.source !== 'ge' || state.geComponentIdToNewId == null) {
3683
+ if (ir.source !== 'effects' || state.GEComponentIdToNewId == null) {
3773
3684
  return;
3774
3685
  }
3775
- applyGeMaskRemap(state.collector, state.geComponentIdToNewId);
3686
+ applyGEMaskRemap(state.collector, state.GEComponentIdToNewId);
3776
3687
  }
3777
3688
  function applySharedMaskPostProcess(ir, state) {
3778
3689
  if (state.maskLookup == null || state.ratio == null || state.width == null || state.height == null || state.frameRate == null) {
@@ -3792,13 +3703,13 @@ function applyVisibilityStep(ir, state) {
3792
3703
  if (layerToItemId == null) {
3793
3704
  return;
3794
3705
  }
3795
- var transformOnlyParentLinkItemIds = new Set();
3706
+ var independentLifetimeChildItemIds = new Set();
3796
3707
  for(var _iterator = _create_for_of_iterator_helper_loose(ir.layers), _step; !(_step = _iterator()).done;){
3797
3708
  var layer = _step.value;
3798
- if (isTransformOnlyParentLink(layer)) {
3709
+ if (hasIndependentParentLifetime(layer)) {
3799
3710
  var itemId = layerToItemId[layer.index];
3800
3711
  if (itemId != null) {
3801
- transformOnlyParentLinkItemIds.add(itemId);
3712
+ independentLifetimeChildItemIds.add(itemId);
3802
3713
  }
3803
3714
  }
3804
3715
  }
@@ -3806,7 +3717,7 @@ function applyVisibilityStep(ir, state) {
3806
3717
  items: collector.items,
3807
3718
  miscs: collector.miscs,
3808
3719
  processedItems: processedItems,
3809
- transformOnlyParentLinkItemIds: transformOnlyParentLinkItemIds,
3720
+ independentLifetimeChildItemIds: independentLifetimeChildItemIds,
3810
3721
  roundNumber: roundNumber
3811
3722
  });
3812
3723
  }
@@ -3863,16 +3774,15 @@ function normalize(value, path, inArray) {
3863
3774
  * Convert an IR composition to a GE JSONScene.
3864
3775
  *
3865
3776
  * All IR sources (lottie, dsl, future) go through this single unified
3866
- * pipeline. Source-specific features are gated by data existence (e.g. mask,
3867
- * precomp, shape layers are absent in dsl IR and naturally skipped);
3868
- * `ir.source` branches are used only for B-class real semantic differences
3869
- * that cannot be expressed via data existence.
3777
+ * pipeline. Normalized animation semantics select the GE lowering plan;
3778
+ * source-specific payloads may preserve authored GE hierarchy or restore
3779
+ * mask and precomp graphs.
3870
3780
  *
3871
3781
  * The optional `duration` arg is a caller override; lottie2ge currently passes
3872
3782
  * the duration computed from the raw json upstream. When omitted, the
3873
3783
  * canonical assembler derives it from `(outPoint - inPoint) / frameRate`.
3874
3784
  */ function convertIRToGE(ir, duration) {
3875
- animationIr.validateIRCompositionWithWarnings(ir);
3785
+ animationIr.validateIRCompositionOrThrow(ir);
3876
3786
  var width = ir.width, height = ir.height, frameRate = ir.frameRate;
3877
3787
  var ratio = get2dTo3dRatio(width, height);
3878
3788
  var collector = {
@@ -3915,15 +3825,15 @@ function normalize(value, path, inArray) {
3915
3825
  }
3916
3826
  // Build GE1-component-id → regenerated-component-id map for mask reference
3917
3827
  // remapping (ge2ir round-trip). Keyed by the original GE component id that
3918
- // ge2ir stored in metadata; value is the component id this layer minted.
3919
- var geComponentIdToNewId = {};
3828
+ // ge2ir stored in specific.effects; value is the component id this layer minted.
3829
+ var GEComponentIdToNewId = {};
3920
3830
  for(var _iterator2 = _create_for_of_iterator_helper_loose(workingIR.layers), _step2; !(_step2 = _iterator2()).done;){
3921
3831
  var layer2 = _step2.value;
3922
- var _readGE2IRMetadata;
3923
- var geComponentId = (_readGE2IRMetadata = readGE2IRMetadata(workingIR, layer2)) == null ? void 0 : _readGE2IRMetadata.geComponentId;
3832
+ var _getEffectsLayerSpecific;
3833
+ var GEComponentId = (_getEffectsLayerSpecific = getEffectsLayerSpecific(workingIR, layer2)) == null ? void 0 : _getEffectsLayerSpecific.sourceComponentId;
3924
3834
  var newId = layerToComponentId[layer2.index];
3925
- if (geComponentId != null && newId != null) {
3926
- geComponentIdToNewId[geComponentId] = newId;
3835
+ if (GEComponentId != null && newId != null) {
3836
+ GEComponentIdToNewId[GEComponentId] = newId;
3927
3837
  }
3928
3838
  }
3929
3839
  applyPostProcess(workingIR, {
@@ -3934,7 +3844,7 @@ function normalize(value, path, inArray) {
3934
3844
  width: width,
3935
3845
  height: height,
3936
3846
  frameRate: frameRate,
3937
- geComponentIdToNewId: geComponentIdToNewId,
3847
+ GEComponentIdToNewId: GEComponentIdToNewId,
3938
3848
  maskLookup: {
3939
3849
  getItemId: function getItemId(idx) {
3940
3850
  return layerToItemId[idx];
@@ -3967,16 +3877,16 @@ function processLayer(layer, ctx) {
3967
3877
  }
3968
3878
  }
3969
3879
  function hasGEPrecompMetadata(ir, layer) {
3970
- var metadata = readGE2IRMetadata(ir, layer);
3971
- return (metadata == null ? void 0 : metadata.precompRefId) != null || (metadata == null ? void 0 : metadata.precompContent) != null;
3880
+ var specific = getEffectsLayerSpecific(ir, layer);
3881
+ return (specific == null ? void 0 : specific.precompRefId) != null || (specific == null ? void 0 : specific.precompContent) != null;
3972
3882
  }
3973
3883
  /**
3974
- * Extend parent layers' endFrame to cover transform-only children's time spans.
3884
+ * Extend parent layers' endFrame to cover independent child lifetimes.
3975
3885
  *
3976
3886
  * In Lottie, child layers (linked via layer.parent) inherit the parent's transform
3977
3887
  * even after the parent becomes invisible. GE requires the parent item to be active
3978
3888
  * for transform inheritance to work, so we extend the parent's endFrame to cover
3979
- * the full lifetime of its transform-only children.
3889
+ * the full lifetime of children whose lifetime is independent.
3980
3890
  *
3981
3891
  * Keyframes beyond the extended endFrame are NOT included — they represent animation
3982
3892
  * that never plays in Lottie (layer is invisible and has no child needing it).
@@ -3995,7 +3905,7 @@ function hasGEPrecompMetadata(ir, layer) {
3995
3905
  for(var _iterator1 = _create_for_of_iterator_helper_loose(clonedLayers), _step1; !(_step1 = _iterator1()).done;){
3996
3906
  var child = _step1.value;
3997
3907
  var _child_parent;
3998
- if (((_child_parent = child.parent) == null ? void 0 : _child_parent.index) === layer.index && child.parent.linkKind === 'transform-only') {
3908
+ if (((_child_parent = child.parent) == null ? void 0 : _child_parent.index) === layer.index && child.parent.lifetimeMode === 'independent') {
3999
3909
  if (child.time.endFrame > maxEnd) {
4000
3910
  maxEnd = child.time.endFrame;
4001
3911
  }
@@ -4014,13 +3924,13 @@ function mergePreservedPrecompScene(generated, ir) {
4014
3924
  return !isExcludedPoolEntry(pool, entry, excluded);
4015
3925
  }));
4016
3926
  };
4017
- var metadata = readGE2IRCompositionMetadata(ir);
4018
- var sourceScene = metadata == null ? void 0 : metadata.sourceScene;
3927
+ var specific = getEffectsCompositionSpecific(ir);
3928
+ var sourceScene = specific == null ? void 0 : specific.sourceScene;
4019
3929
  if (sourceScene == null) {
4020
3930
  return generated;
4021
3931
  }
4022
3932
  var result = _extends({}, generated);
4023
- var sourceCompositionId = metadata == null ? void 0 : metadata.sourceCompositionId;
3933
+ var sourceCompositionId = specific == null ? void 0 : specific.sourceCompositionId;
4024
3934
  var excluded = collectRootCompositionIds(sourceScene, sourceCompositionId);
4025
3935
  var pools = [
4026
3936
  'images',
@@ -4240,23 +4150,25 @@ function resolveDataPathId(ref) {
4240
4150
  return typeof id === 'string' ? id : undefined;
4241
4151
  }
4242
4152
 
4243
- function reverseEndBehavior(geBehavior) {
4244
- if (geBehavior == null) {
4153
+ function reverseEndBehavior(GEBehavior) {
4154
+ if (GEBehavior == null) {
4245
4155
  return undefined;
4246
4156
  }
4247
- switch(geBehavior){
4157
+ switch(GEBehavior){
4248
4158
  case 0:
4249
- return animationIr.IREndBehavior.Stop;
4159
+ return animationIr.IREndBehavior.Destroy;
4160
+ case 2:
4161
+ return animationIr.IREndBehavior.Forward;
4250
4162
  case 4:
4251
- return animationIr.IREndBehavior.Hold;
4163
+ return animationIr.IREndBehavior.Freeze;
4252
4164
  case 5:
4253
- return animationIr.IREndBehavior.Loop;
4165
+ return animationIr.IREndBehavior.Restart;
4254
4166
  default:
4255
4167
  return undefined;
4256
4168
  }
4257
4169
  }
4258
- function reverseCompositionEndBehavior(geBehavior) {
4259
- return reverseEndBehavior(geBehavior);
4170
+ function reverseCompositionEndBehavior(GEBehavior) {
4171
+ return reverseEndBehavior(GEBehavior);
4260
4172
  }
4261
4173
 
4262
4174
  function buildSceneContext(scene, options) {
@@ -4276,7 +4188,10 @@ function buildSceneContext(scene, options) {
4276
4188
  var frameRate = options.frameRate;
4277
4189
  var ratio = get2dTo3dRatio(width, height);
4278
4190
  var inPoint = 0;
4279
- var outPoint = Math.round(duration * frameRate);
4191
+ // GE durations are expressed in seconds and are not guaranteed to land on
4192
+ // an integer frame. Preserve the fractional frame so GE → IR → GE does not
4193
+ // shorten or extend the composition at the tail.
4194
+ var outPoint = duration * frameRate;
4280
4195
  var endBehavior = reverseCompositionEndBehavior(composition['endBehavior']);
4281
4196
  var backgroundColor;
4282
4197
  var bg = composition['background'];
@@ -4484,16 +4399,26 @@ function parseStaticTransform(itemTransform, ctx) {
4484
4399
  }
4485
4400
  var eulerHint = itemTransform['eulerHint'];
4486
4401
  if (eulerHint != null) {
4487
- var hasRotation = Math.abs(eulerHint.x) > 1e-6 || Math.abs(eulerHint.y) > 1e-6 || Math.abs(eulerHint.z) > 1e-6;
4488
- if (hasRotation) {
4489
- channels.rotation = {
4490
- keyframed: false,
4491
- value: [
4492
- eulerHint.x,
4493
- eulerHint.y,
4494
- eulerHint.z
4495
- ]
4496
- };
4402
+ var x = Math.abs(eulerHint.x) > 1e-6 ? {
4403
+ keyframed: false,
4404
+ value: eulerHint.x
4405
+ } : undefined;
4406
+ var y = Math.abs(eulerHint.y) > 1e-6 ? {
4407
+ keyframed: false,
4408
+ value: eulerHint.y
4409
+ } : undefined;
4410
+ var z = Math.abs(eulerHint.z) > 1e-6 ? {
4411
+ keyframed: false,
4412
+ value: eulerHint.z
4413
+ } : undefined;
4414
+ if (x != null || y != null || z != null) {
4415
+ channels.rotation = _extends({}, x != null && {
4416
+ x: x
4417
+ }, y != null && {
4418
+ y: y
4419
+ }, z != null && {
4420
+ z: z
4421
+ });
4497
4422
  }
4498
4423
  }
4499
4424
  return channels;
@@ -4542,7 +4467,7 @@ function parseBezierKeyframes(curves, startFrame, endFrame) {
4542
4467
  };
4543
4468
  if (i === 0) {
4544
4469
  keyframes.push(_extends({
4545
- t: frameTime,
4470
+ frame: frameTime,
4546
4471
  value: v0
4547
4472
  }, isHold ? {
4548
4473
  hold: true
@@ -4562,7 +4487,7 @@ function parseBezierKeyframes(curves, startFrame, endFrame) {
4562
4487
  y: inverseLerp(prevV0, prevV1, prevInCpY)
4563
4488
  };
4564
4489
  keyframes.push(_extends({
4565
- t: frameTime,
4490
+ frame: frameTime,
4566
4491
  value: v0,
4567
4492
  inTangent: inTangent
4568
4493
  }, isHold ? {
@@ -4581,7 +4506,7 @@ function parseBezierKeyframes(curves, startFrame, endFrame) {
4581
4506
  y: inverseLerp(lastSeg[1], lastSeg[7], lastSeg[5])
4582
4507
  };
4583
4508
  keyframes.push({
4584
- t: lastFrameTime,
4509
+ frame: lastFrameTime,
4585
4510
  value: lastV1,
4586
4511
  inTangent: lastInTangent
4587
4512
  });
@@ -4677,7 +4602,7 @@ function parsePositionTimingKeyframes(curves, startFrame, endFrame) {
4677
4602
  };
4678
4603
  if (i === 0) {
4679
4604
  result.push({
4680
- t: frameTime,
4605
+ frame: frameTime,
4681
4606
  outTangent: outTangent
4682
4607
  });
4683
4608
  } else {
@@ -4687,7 +4612,7 @@ function parsePositionTimingKeyframes(curves, startFrame, endFrame) {
4687
4612
  y: inverseLerp(prevSeg[0], prevSeg[6], prevSeg[5])
4688
4613
  };
4689
4614
  result.push({
4690
- t: frameTime,
4615
+ frame: frameTime,
4691
4616
  outTangent: outTangent,
4692
4617
  inTangent: inTangent
4693
4618
  });
@@ -4700,7 +4625,7 @@ function parsePositionTimingKeyframes(curves, startFrame, endFrame) {
4700
4625
  y: inverseLerp(lastSeg[0], lastSeg[6], lastSeg[5])
4701
4626
  };
4702
4627
  result.push({
4703
- t: lastFrameTime,
4628
+ frame: lastFrameTime,
4704
4629
  inTangent: lastInTangent
4705
4630
  });
4706
4631
  return result;
@@ -4717,12 +4642,9 @@ function parseTransformAnimation(asset, startFrame, endFrame, ctx) {
4717
4642
  }
4718
4643
  var rotOverLifetime = asset['rotationOverLifetime'];
4719
4644
  if (rotOverLifetime != null) {
4720
- var rotResult = parseRotationAnimation(rotOverLifetime, startFrame, endFrame);
4721
- if (rotResult.rotation != null) {
4722
- channels.rotation = rotResult.rotation;
4723
- }
4724
- if (rotResult.separatedRotation != null) {
4725
- channels.separatedRotation = rotResult.separatedRotation;
4645
+ var rotation = parseRotationAnimation(rotOverLifetime, startFrame, endFrame);
4646
+ if (rotation != null) {
4647
+ channels.rotation = rotation;
4726
4648
  }
4727
4649
  }
4728
4650
  var sizeOverLifetime = asset['sizeOverLifetime'];
@@ -4802,7 +4724,7 @@ function parsePositionAnimation(posOverLifetime, startFrame, endFrame, ctx) {
4802
4724
  var pp = pathPoints[Math.min(i, pathPoints.length - 1)];
4803
4725
  var pos2d = convert3dTo2dPoint(pp[0], pp[1], (_pp_ = pp[2]) != null ? _pp_ : 0, ctx.width, ctx.height);
4804
4726
  var kf = {
4805
- t: timing.t,
4727
+ frame: timing.frame,
4806
4728
  value: pos2d
4807
4729
  };
4808
4730
  if (i > startIdx && timing.inTangent != null) {
@@ -4851,83 +4773,26 @@ function parsePositionAnimation(posOverLifetime, startFrame, endFrame, ctx) {
4851
4773
  };
4852
4774
  }
4853
4775
  function parseRotationAnimation(rotOverLifetime, startFrame, endFrame) {
4854
- var separateAxes = rotOverLifetime['separateAxes'];
4776
+ var separateAxes = rotOverLifetime['separateAxes'] === true;
4855
4777
  var xData = rotOverLifetime['x'];
4856
4778
  var yData = rotOverLifetime['y'];
4857
4779
  var zData = rotOverLifetime['z'];
4858
- if (separateAxes === true) {
4859
- var x = parseScalarChannel(xData, startFrame, endFrame);
4860
- var y = parseScalarChannel(yData, startFrame, endFrame);
4861
- var z = parseScalarChannel(zData, startFrame, endFrame);
4862
- var hasMultiAxis = (x != null ? 1 : 0) + (y != null ? 1 : 0) + (z != null ? 1 : 0) > 1;
4863
- var hasXOrY = x != null || y != null;
4864
- if (hasMultiAxis || hasXOrY) {
4865
- return {
4866
- separatedRotation: _extends({}, x != null && {
4867
- x: x
4868
- }, y != null && {
4869
- y: y
4870
- }, z != null && {
4871
- z: z
4872
- })
4873
- };
4874
- }
4875
- if (z != null) {
4876
- return {
4877
- separatedRotation: {
4878
- z: z
4879
- }
4880
- };
4881
- }
4882
- }
4883
- // Single-axis z rotation (non-separated)
4884
- if (zData != null) {
4885
- var z1 = parseScalarChannel(zData, startFrame, endFrame);
4886
- if (z1 != null) {
4887
- if (z1.keyframed) {
4888
- var vecKeyframes = z1.keyframes.map(function(kf) {
4889
- var result = {
4890
- t: kf.t,
4891
- value: [
4892
- 0,
4893
- 0,
4894
- kf.value
4895
- ]
4896
- };
4897
- if (kf.hold != null) {
4898
- result.hold = kf.hold;
4899
- }
4900
- if (kf.inTangent != null) {
4901
- result.inTangent = kf.inTangent;
4902
- }
4903
- if (kf.outTangent != null) {
4904
- result.outTangent = kf.outTangent;
4905
- }
4906
- return result;
4907
- });
4908
- return {
4909
- rotation: {
4910
- keyframed: true,
4911
- keyframes: vecKeyframes
4912
- }
4913
- };
4914
- }
4915
- return {
4916
- rotation: {
4917
- keyframed: false,
4918
- value: [
4919
- 0,
4920
- 0,
4921
- z1.value
4922
- ]
4923
- }
4924
- };
4925
- }
4780
+ var x = separateAxes ? parseScalarChannel(xData, startFrame, endFrame) : undefined;
4781
+ var y = separateAxes ? parseScalarChannel(yData, startFrame, endFrame) : undefined;
4782
+ var z = parseScalarChannel(zData, startFrame, endFrame);
4783
+ if (x == null && y == null && z == null) {
4784
+ return undefined;
4926
4785
  }
4927
- return {};
4786
+ return _extends({}, x != null && {
4787
+ x: x
4788
+ }, y != null && {
4789
+ y: y
4790
+ }, z != null && {
4791
+ z: z
4792
+ });
4928
4793
  }
4929
4794
  function parseScaleAnimation(sizeOverLifetime, startFrame, endFrame) {
4930
- var _ref, _ref1, _ref2, _ref3, _ref4, _ref5, _ref6, _ref7, _ref8;
4795
+ var _ref, _ref1, _ref2;
4931
4796
  var xData = sizeOverLifetime['x'];
4932
4797
  var yData = sizeOverLifetime['y'];
4933
4798
  var zData = sizeOverLifetime['z'];
@@ -4940,71 +4805,72 @@ function parseScaleAnimation(sizeOverLifetime, startFrame, endFrame) {
4940
4805
  var xKeyframed = (x == null ? void 0 : x.keyframed) === true;
4941
4806
  var yKeyframed = (y == null ? void 0 : y.keyframed) === true;
4942
4807
  var zKeyframed = (z == null ? void 0 : z.keyframed) === true;
4808
+ var xStaticValue = (x == null ? void 0 : x.keyframed) === false ? x.value : 1;
4809
+ var yStaticValue = (y == null ? void 0 : y.keyframed) === false ? y.value : 1;
4810
+ var zStaticValue = (z == null ? void 0 : z.keyframed) === false ? z.value : 1;
4943
4811
  if (!xKeyframed && !yKeyframed && !zKeyframed) {
4944
- var _ref9, _ref10, _ref11;
4945
4812
  return {
4946
4813
  keyframed: false,
4947
4814
  value: [
4948
- (_ref9 = x == null ? void 0 : x.value) != null ? _ref9 : 1,
4949
- (_ref10 = y == null ? void 0 : y.value) != null ? _ref10 : 1,
4950
- (_ref11 = z == null ? void 0 : z.value) != null ? _ref11 : 1
4815
+ xStaticValue,
4816
+ yStaticValue,
4817
+ zStaticValue
4951
4818
  ]
4952
4819
  };
4953
4820
  }
4954
4821
  var xKfs = (_ref = x == null ? void 0 : x.keyframes) != null ? _ref : [
4955
4822
  {
4956
- t: startFrame,
4957
- value: (_ref1 = x == null ? void 0 : x.value) != null ? _ref1 : 1
4823
+ frame: startFrame,
4824
+ value: xStaticValue
4958
4825
  },
4959
4826
  {
4960
- t: endFrame,
4961
- value: (_ref2 = x == null ? void 0 : x.value) != null ? _ref2 : 1
4827
+ frame: endFrame,
4828
+ value: xStaticValue
4962
4829
  }
4963
4830
  ];
4964
- var yKfs = (_ref3 = y == null ? void 0 : y.keyframes) != null ? _ref3 : [
4831
+ var yKfs = (_ref1 = y == null ? void 0 : y.keyframes) != null ? _ref1 : [
4965
4832
  {
4966
- t: startFrame,
4967
- value: (_ref4 = y == null ? void 0 : y.value) != null ? _ref4 : 1
4833
+ frame: startFrame,
4834
+ value: yStaticValue
4968
4835
  },
4969
4836
  {
4970
- t: endFrame,
4971
- value: (_ref5 = y == null ? void 0 : y.value) != null ? _ref5 : 1
4837
+ frame: endFrame,
4838
+ value: yStaticValue
4972
4839
  }
4973
4840
  ];
4974
- var zKfs = (_ref6 = z == null ? void 0 : z.keyframes) != null ? _ref6 : [
4841
+ var zKfs = (_ref2 = z == null ? void 0 : z.keyframes) != null ? _ref2 : [
4975
4842
  {
4976
- t: startFrame,
4977
- value: (_ref7 = z == null ? void 0 : z.value) != null ? _ref7 : 1
4843
+ frame: startFrame,
4844
+ value: zStaticValue
4978
4845
  },
4979
4846
  {
4980
- t: endFrame,
4981
- value: (_ref8 = z == null ? void 0 : z.value) != null ? _ref8 : 1
4847
+ frame: endFrame,
4848
+ value: zStaticValue
4982
4849
  }
4983
4850
  ];
4984
- var allTimes = new Set();
4851
+ var allFrames = new Set();
4985
4852
  for(var _iterator = _create_for_of_iterator_helper_loose(xKfs), _step; !(_step = _iterator()).done;){
4986
4853
  var kf = _step.value;
4987
- allTimes.add(kf.t);
4854
+ allFrames.add(kf.frame);
4988
4855
  }
4989
4856
  for(var _iterator1 = _create_for_of_iterator_helper_loose(yKfs), _step1; !(_step1 = _iterator1()).done;){
4990
4857
  var kf1 = _step1.value;
4991
- allTimes.add(kf1.t);
4858
+ allFrames.add(kf1.frame);
4992
4859
  }
4993
4860
  for(var _iterator2 = _create_for_of_iterator_helper_loose(zKfs), _step2; !(_step2 = _iterator2()).done;){
4994
4861
  var kf2 = _step2.value;
4995
- allTimes.add(kf2.t);
4862
+ allFrames.add(kf2.frame);
4996
4863
  }
4997
4864
  // Keep Array.from: loose SWC array-spread lowering does not expand Set in dist.
4998
- var sortedTimes = Array.from(allTimes).sort(function(a, b) {
4865
+ var sortedFrames = Array.from(allFrames).sort(function(a, b) {
4999
4866
  return a - b;
5000
4867
  });
5001
- var keyframes = sortedTimes.map(function(t) {
5002
- var _ref, _ref1, _ref2;
5003
- var xv = findValueAtTime(xKfs, t, (_ref = x == null ? void 0 : x.value) != null ? _ref : 1);
5004
- var yv = findValueAtTime(yKfs, t, (_ref1 = y == null ? void 0 : y.value) != null ? _ref1 : 1);
5005
- var zv = findValueAtTime(zKfs, t, (_ref2 = z == null ? void 0 : z.value) != null ? _ref2 : 1);
4868
+ var keyframes = sortedFrames.map(function(frame) {
4869
+ var xv = findValueAtFrame(xKfs, frame, xStaticValue);
4870
+ var yv = findValueAtFrame(yKfs, frame, yStaticValue);
4871
+ var zv = findValueAtFrame(zKfs, frame, zStaticValue);
5006
4872
  var kf = {
5007
- t: t,
4873
+ frame: frame,
5008
4874
  value: [
5009
4875
  xv.value,
5010
4876
  yv.value,
@@ -5050,10 +4916,10 @@ function parseScalarChannel(data, startFrame, endFrame) {
5050
4916
  }
5051
4917
  return undefined;
5052
4918
  }
5053
- function findValueAtTime(keyframes, t, defaultValue) {
4919
+ function findValueAtFrame(keyframes, frame, defaultValue) {
5054
4920
  for(var _iterator = _create_for_of_iterator_helper_loose(keyframes), _step; !(_step = _iterator()).done;){
5055
4921
  var kf = _step.value;
5056
- if (Math.abs(kf.t - t) < 1e-6) {
4922
+ if (Math.abs(kf.frame - frame) < 1e-6) {
5057
4923
  return {
5058
4924
  value: kf.value,
5059
4925
  outTangent: kf.outTangent,
@@ -5085,11 +4951,11 @@ var IR_BLEND_MODE_BY_GE = {
5085
4951
  15: animationIr.IRBlendMode.SoftLight,
5086
4952
  16: animationIr.IRBlendMode.Luminosity
5087
4953
  };
5088
- function reverseBlendMode(geCode) {
5089
- if (geCode == null) {
4954
+ function reverseBlendMode(GECode) {
4955
+ if (GECode == null) {
5090
4956
  return undefined;
5091
4957
  }
5092
- return IR_BLEND_MODE_BY_GE[geCode];
4958
+ return IR_BLEND_MODE_BY_GE[GECode];
5093
4959
  }
5094
4960
 
5095
4961
  function parseComponent(item, ctx) {
@@ -5119,7 +4985,7 @@ function parseComponent(item, ctx) {
5119
4985
  if (result == null) {
5120
4986
  continue;
5121
4987
  }
5122
- result.geComponentId = component['id'];
4988
+ result.GEComponentId = component['id'];
5123
4989
  var mask = component['mask'];
5124
4990
  if (mask != null) {
5125
4991
  result.rawMask = mask;
@@ -5243,7 +5109,7 @@ function parseShapeComponent(component, ctx) {
5243
5109
  if (renderer != null) {
5244
5110
  blendMode = reverseBlendMode(renderer['blending']);
5245
5111
  }
5246
- var shapeData = parseShapeOptions(component, ctx.ratio);
5112
+ var shapeData = parseShapeOptions(component, ctx);
5247
5113
  return {
5248
5114
  type: 'shape',
5249
5115
  shapes: shapeData != null ? [
@@ -5252,85 +5118,100 @@ function parseShapeComponent(component, ctx) {
5252
5118
  blendMode: blendMode
5253
5119
  };
5254
5120
  }
5255
- function parseShapeOptions(component, ratio) {
5256
- var geType = component['type'];
5257
- var primitiveType = reverseShapePrimitiveType(geType != null ? geType : 0);
5258
- var xSize = component['xSize'];
5259
- var ySize = component['ySize'];
5260
- var size = [
5261
- xSize != null ? xSize / ratio : 0,
5262
- ySize != null ? ySize / ratio : 0
5263
- ];
5264
- var shape = {
5265
- primitiveType: primitiveType,
5121
+ function parseShapeOptions(component, ctx) {
5122
+ var GEType = component['type'];
5123
+ var primitiveType = reverseShapePrimitiveType(GEType != null ? GEType : 0);
5124
+ var style = {
5266
5125
  position: [
5267
5126
  0,
5268
5127
  0
5269
5128
  ],
5270
- size: size,
5271
5129
  fills: [],
5272
5130
  strokes: []
5273
5131
  };
5274
- var shapeRec = shape;
5275
- reverseScaledNumber(shapeRec, component, 'xRadius', ratio);
5276
- reverseScaledNumber(shapeRec, component, 'yRadius', ratio);
5277
- reverseScaledNumber(shapeRec, component, 'width', ratio);
5278
- reverseScaledNumber(shapeRec, component, 'height', ratio);
5279
- reverseScaledNumber(shapeRec, component, 'innerRadius', ratio);
5280
- reverseScaledNumber(shapeRec, component, 'outerRadius', ratio);
5281
- reverseScaledNumber(shapeRec, component, 'radius', ratio);
5282
- reverseRawNumber(shapeRec, component, 'roundness');
5283
- reverseRawNumber(shapeRec, component, 'pointCount');
5284
- reverseRawNumber(shapeRec, component, 'innerRoundness');
5285
- reverseRawNumber(shapeRec, component, 'outerRoundness');
5286
- var geFills = component['fills'];
5287
- if (geFills != null) {
5288
- shape.fills = geFills.map(function(f) {
5289
- return reverseShapePaint(f, ratio);
5132
+ var GEFills = component['fills'];
5133
+ if (GEFills != null) {
5134
+ style.fills = GEFills.map(function(f) {
5135
+ return reverseShapePaint(f, ctx);
5290
5136
  }).filter(function(f) {
5291
5137
  return f != null;
5292
5138
  });
5293
5139
  }
5294
- var geStrokes = component['strokes'];
5295
- if (geStrokes != null) {
5296
- shape.strokes = geStrokes.map(function(s) {
5297
- return reverseShapePaint(s, ratio);
5140
+ var GEStrokes = component['strokes'];
5141
+ if (GEStrokes != null) {
5142
+ style.strokes = GEStrokes.map(function(s) {
5143
+ return reverseShapePaint(s, ctx);
5298
5144
  }).filter(function(s) {
5299
5145
  return s != null;
5300
5146
  });
5301
5147
  }
5302
- var geStrokeWidth = component['strokeWidth'];
5303
- if (geStrokeWidth != null) {
5304
- shape.strokeWidth = geStrokeWidth / ratio;
5305
- }
5306
- var geStrokeCap = component['strokeCap'];
5307
- if (geStrokeCap != null) {
5308
- shape.strokeCap = reverseLineCap(geStrokeCap);
5309
- }
5310
- var geStrokeJoin = component['strokeJoin'];
5311
- if (geStrokeJoin != null) {
5312
- shape.strokeJoin = reverseLineJoin(geStrokeJoin);
5313
- }
5314
- var geFillRule = component['fillRule'];
5315
- if (geFillRule != null) {
5316
- shape.fillRule = reverseShapeFillRule(geFillRule);
5148
+ var GEStrokeWidth = component['strokeWidth'];
5149
+ if (typeof GEStrokeWidth === 'number' && Number.isFinite(GEStrokeWidth) && GEStrokeWidth >= 0) {
5150
+ style.strokeWidth = GEStrokeWidth / ctx.ratio;
5317
5151
  }
5318
- var geShapes = component['shapes'];
5319
- if (geShapes != null) {
5320
- var paths = reverseCustomPaths(component, ratio);
5321
- if (paths.length > 0) {
5322
- shape.customPaths = paths;
5323
- }
5152
+ var GEStrokeCap = component['strokeCap'];
5153
+ if (GEStrokeCap != null) {
5154
+ style.strokeCap = reverseLineCap(GEStrokeCap);
5324
5155
  }
5325
- var trimPath = component['trimPath'];
5326
- if (trimPath != null) {
5327
- shape.trimPath = trimPath;
5156
+ var GEStrokeJoin = component['strokeJoin'];
5157
+ if (GEStrokeJoin != null) {
5158
+ style.strokeJoin = reverseLineJoin(GEStrokeJoin);
5328
5159
  }
5329
- var repeater = component['repeater'];
5330
- if (repeater != null) {
5331
- shape.repeater = repeater;
5160
+ switch(primitiveType){
5161
+ case animationIr.IRShapePrimitiveType.Custom:
5162
+ {
5163
+ var customPaths = reverseCustomPaths(component, ctx.ratio);
5164
+ var firstPath = customPaths[0];
5165
+ return firstPath != null ? _extends({}, style, {
5166
+ primitiveType: primitiveType,
5167
+ customPaths: [].concat([
5168
+ firstPath
5169
+ ], customPaths.slice(1))
5170
+ }) : undefined;
5171
+ }
5172
+ case animationIr.IRShapePrimitiveType.Rectangle:
5173
+ {
5174
+ var width = readScaledNumber(component, 'width', ctx.ratio);
5175
+ var height = readScaledNumber(component, 'height', ctx.ratio);
5176
+ return width != null && height != null ? _extends({}, style, {
5177
+ primitiveType: primitiveType,
5178
+ width: width,
5179
+ height: height
5180
+ }, readOptionalNumberField(component, 'roundness')) : undefined;
5181
+ }
5182
+ case animationIr.IRShapePrimitiveType.Ellipse:
5183
+ {
5184
+ var xRadius = readScaledNumber(component, 'xRadius', ctx.ratio);
5185
+ var yRadius = readScaledNumber(component, 'yRadius', ctx.ratio);
5186
+ return xRadius != null && yRadius != null ? _extends({}, style, {
5187
+ primitiveType: primitiveType,
5188
+ xRadius: xRadius,
5189
+ yRadius: yRadius
5190
+ }) : undefined;
5191
+ }
5192
+ case animationIr.IRShapePrimitiveType.Polygon:
5193
+ {
5194
+ var pointCount = readPointCount(component);
5195
+ var radius = readScaledNumber(component, 'radius', ctx.ratio);
5196
+ return pointCount != null && radius != null ? _extends({}, style, {
5197
+ primitiveType: primitiveType,
5198
+ pointCount: pointCount,
5199
+ radius: radius
5200
+ }, readOptionalNumberField(component, 'roundness')) : undefined;
5201
+ }
5202
+ case animationIr.IRShapePrimitiveType.Star:
5203
+ {
5204
+ var pointCount1 = readPointCount(component);
5205
+ var innerRadius = readScaledNumber(component, 'innerRadius', ctx.ratio);
5206
+ var outerRadius = readScaledNumber(component, 'outerRadius', ctx.ratio);
5207
+ return pointCount1 != null && innerRadius != null && outerRadius != null ? _extends({}, style, {
5208
+ primitiveType: primitiveType,
5209
+ pointCount: pointCount1,
5210
+ innerRadius: innerRadius,
5211
+ outerRadius: outerRadius
5212
+ }, readOptionalNumberField(component, 'innerRoundness'), readOptionalNumberField(component, 'outerRoundness')) : undefined;
5213
+ }
5332
5214
  }
5333
- return shape;
5334
5215
  }
5335
5216
  var GE_TO_SHAPE_PRIMITIVE_TYPE = {
5336
5217
  0: animationIr.IRShapePrimitiveType.Custom,
@@ -5339,13 +5220,13 @@ var GE_TO_SHAPE_PRIMITIVE_TYPE = {
5339
5220
  3: animationIr.IRShapePrimitiveType.Polygon,
5340
5221
  4: animationIr.IRShapePrimitiveType.Star
5341
5222
  };
5342
- function reverseShapePrimitiveType(geType) {
5343
- var _GE_TO_SHAPE_PRIMITIVE_TYPE_geType;
5344
- return (_GE_TO_SHAPE_PRIMITIVE_TYPE_geType = GE_TO_SHAPE_PRIMITIVE_TYPE[geType]) != null ? _GE_TO_SHAPE_PRIMITIVE_TYPE_geType : animationIr.IRShapePrimitiveType.Custom;
5223
+ function reverseShapePrimitiveType(GEType) {
5224
+ var _GE_TO_SHAPE_PRIMITIVE_TYPE_GEType;
5225
+ return (_GE_TO_SHAPE_PRIMITIVE_TYPE_GEType = GE_TO_SHAPE_PRIMITIVE_TYPE[GEType]) != null ? _GE_TO_SHAPE_PRIMITIVE_TYPE_GEType : animationIr.IRShapePrimitiveType.Custom;
5345
5226
  }
5346
- function reverseShapePaint(paint, ratio) {
5347
- var geType = paint['type'];
5348
- if (geType === 0) {
5227
+ function reverseShapePaint(paint, ctx) {
5228
+ var GEType = paint['type'];
5229
+ if (GEType === 0) {
5349
5230
  var color = paint['color'];
5350
5231
  if (color == null) {
5351
5232
  return undefined;
@@ -5360,7 +5241,7 @@ function reverseShapePaint(paint, ratio) {
5360
5241
  ]
5361
5242
  };
5362
5243
  }
5363
- if (geType === 1 || geType === 2 || geType === 3) {
5244
+ if (GEType === 1 || GEType === 2 || GEType === 3) {
5364
5245
  var typeMap = {
5365
5246
  1: animationIr.IRFillType.LinearGradient,
5366
5247
  2: animationIr.IRFillType.RadialGradient,
@@ -5371,45 +5252,50 @@ function reverseShapePaint(paint, ratio) {
5371
5252
  var startPoint = paint['startPoint'];
5372
5253
  var endPoint = paint['endPoint'];
5373
5254
  return {
5374
- type: typeMap[geType],
5255
+ type: typeMap[GEType],
5375
5256
  gradientStops: stops,
5376
5257
  gradientStart: startPoint != null ? [
5377
- startPoint.x / ratio,
5378
- -startPoint.y / ratio
5258
+ startPoint.x / ctx.ratio,
5259
+ -startPoint.y / ctx.ratio
5379
5260
  ] : undefined,
5380
5261
  gradientEnd: endPoint != null ? [
5381
- endPoint.x / ratio,
5382
- -endPoint.y / ratio
5262
+ endPoint.x / ctx.ratio,
5263
+ -endPoint.y / ctx.ratio
5383
5264
  ] : undefined
5384
5265
  };
5385
5266
  }
5267
+ if (GEType === 4) {
5268
+ var texture = resolveTextureAsset(paint['texture'], ctx);
5269
+ if (texture == null) {
5270
+ return undefined;
5271
+ }
5272
+ var scaleMode = paint['scaleMode'];
5273
+ return _extends({
5274
+ type: animationIr.IRFillType.Texture,
5275
+ texture: texture
5276
+ }, isTextureScaleMode(scaleMode) && {
5277
+ scaleMode: scaleMode
5278
+ });
5279
+ }
5386
5280
  return undefined;
5387
5281
  }
5388
- function reverseLineCap(geCode) {
5389
- var _map_geCode;
5282
+ function reverseLineCap(GECode) {
5283
+ var _map_GECode;
5390
5284
  var map = {
5391
5285
  0: animationIr.IRLineCap.Butt,
5392
5286
  1: animationIr.IRLineCap.Round,
5393
5287
  2: animationIr.IRLineCap.Square
5394
5288
  };
5395
- return (_map_geCode = map[geCode]) != null ? _map_geCode : animationIr.IRLineCap.Butt;
5289
+ return (_map_GECode = map[GECode]) != null ? _map_GECode : animationIr.IRLineCap.Butt;
5396
5290
  }
5397
- function reverseLineJoin(geCode) {
5398
- var _map_geCode;
5291
+ function reverseLineJoin(GECode) {
5292
+ var _map_GECode;
5399
5293
  var map = {
5400
5294
  0: animationIr.IRLineJoin.Round,
5401
5295
  1: animationIr.IRLineJoin.Bevel,
5402
5296
  2: animationIr.IRLineJoin.Miter
5403
5297
  };
5404
- return (_map_geCode = map[geCode]) != null ? _map_geCode : animationIr.IRLineJoin.Miter;
5405
- }
5406
- function reverseShapeFillRule(geCode) {
5407
- var _map_geCode;
5408
- var map = {
5409
- 0: animationIr.IRShapeFillRule.NonZero,
5410
- 1: animationIr.IRShapeFillRule.EvenOdd
5411
- };
5412
- return (_map_geCode = map[geCode]) != null ? _map_geCode : animationIr.IRShapeFillRule.NonZero;
5298
+ return (_map_GECode = map[GECode]) != null ? _map_GECode : animationIr.IRLineJoin.Miter;
5413
5299
  }
5414
5300
  function reverseCustomPaths(component, ratio) {
5415
5301
  var points = component['points'];
@@ -5421,8 +5307,8 @@ function reverseCustomPaths(component, ratio) {
5421
5307
  }
5422
5308
  return shapes.map(function(shape) {
5423
5309
  var pathPoints = [];
5424
- var pathEasingIns = [];
5425
- var pathEasingOuts = [];
5310
+ var pathInTangents = [];
5311
+ var pathOutTangents = [];
5426
5312
  for(var _iterator = _create_for_of_iterator_helper_loose(shape.indexes), _step; !(_step = _iterator()).done;){
5427
5313
  var idx = _step.value;
5428
5314
  var _ref, _ref1, _ref2, _ref3;
@@ -5433,34 +5319,50 @@ function reverseCustomPaths(component, ratio) {
5433
5319
  x: pt.x / ratio,
5434
5320
  y: -pt.y / ratio
5435
5321
  });
5436
- pathEasingIns.push({
5322
+ pathInTangents.push({
5437
5323
  x: ((_ref = ei == null ? void 0 : ei.x) != null ? _ref : 0) / ratio,
5438
5324
  y: -((_ref1 = ei == null ? void 0 : ei.y) != null ? _ref1 : 0) / ratio
5439
5325
  });
5440
- pathEasingOuts.push({
5326
+ pathOutTangents.push({
5441
5327
  x: ((_ref2 = eo == null ? void 0 : eo.x) != null ? _ref2 : 0) / ratio,
5442
5328
  y: -((_ref3 = eo == null ? void 0 : eo.y) != null ? _ref3 : 0) / ratio
5443
5329
  });
5444
5330
  }
5445
5331
  return {
5446
5332
  points: pathPoints,
5447
- easingIns: pathEasingIns,
5448
- easingOuts: pathEasingOuts,
5449
- close: shape.close
5333
+ inTangents: pathInTangents,
5334
+ outTangents: pathOutTangents,
5335
+ closed: shape.close
5450
5336
  };
5451
5337
  });
5452
5338
  }
5453
- function reverseScaledNumber(shape, component, key, ratio) {
5339
+ function readScaledNumber(component, key, ratio) {
5454
5340
  var value = component[key];
5455
- if (typeof value === 'number') {
5456
- shape[key] = value / ratio;
5341
+ if (typeof value !== 'number' || !Number.isFinite(value) || value < 0) {
5342
+ return undefined;
5457
5343
  }
5344
+ return value / ratio;
5458
5345
  }
5459
- function reverseRawNumber(shape, component, key) {
5346
+ function readOptionalNumberField(component, key) {
5460
5347
  var value = component[key];
5461
- if (typeof value === 'number') {
5462
- shape[key] = value;
5463
- }
5348
+ var _obj;
5349
+ return typeof value === 'number' && Number.isFinite(value) ? (_obj = {}, _obj[key] = value, _obj) : {};
5350
+ }
5351
+ function readPointCount(component) {
5352
+ var value = component['pointCount'];
5353
+ return typeof value === 'number' && Number.isInteger(value) && value >= 2 ? value : undefined;
5354
+ }
5355
+ function resolveTextureAsset(textureRef, ctx) {
5356
+ var texture = resolveDataPath(ctx.textureById, textureRef);
5357
+ var sourceRef = texture == null ? void 0 : texture['source'];
5358
+ var image = sourceRef != null ? resolveDataPath(ctx.imageById, sourceRef) : undefined;
5359
+ var url = image == null ? void 0 : image['url'];
5360
+ return typeof url === 'string' && url.trim() !== '' ? {
5361
+ url: url
5362
+ } : undefined;
5363
+ }
5364
+ function isTextureScaleMode(value) {
5365
+ return typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= 3;
5464
5366
  }
5465
5367
 
5466
5368
  function reverseLayerTiming(delay, duration, frameRate) {
@@ -5501,7 +5403,7 @@ function mergeNullSpritePairs(descriptors, ctx) {
5501
5403
  // child is exactly one same-name visual sprite. ir2ge's emitNullSpritePair
5502
5404
  // produces precisely this shape (null + one same-name child). If the null
5503
5405
  // has any OTHER children, it is a genuine Lottie parent null — merging it
5504
- // into a transformSplit would change the anchor those other children are
5406
+ // into a single semantic layer would change the anchor those other children are
5505
5407
  // parented against, shifting them. Leave such nulls intact.
5506
5408
  if (children.length !== 1) {
5507
5409
  continue;
@@ -5615,19 +5517,17 @@ function isRecord$1(value) {
5615
5517
  return value != null && (typeof value === "undefined" ? "undefined" : _type_of(value)) === 'object' && !Array.isArray(value);
5616
5518
  }
5617
5519
  function mergeNullAndSprite(nullDesc, childDesc, ctx) {
5618
- var _childDesc_layer_transform;
5520
+ var _childDesc_layer_transform, _merged_specific;
5619
5521
  var merged = _extends({}, nullDesc.layer);
5620
5522
  // Take type from child
5621
5523
  merged.type = childDesc.layer.type;
5622
5524
  merged.asset = childDesc.layer.asset;
5623
5525
  merged.text = childDesc.layer.text;
5624
5526
  merged.shapes = childDesc.layer.shapes;
5625
- merged.shapeLayer = childDesc.layer.shapeLayer;
5626
5527
  merged.solidColor = childDesc.layer.solidColor;
5627
5528
  merged.blendMode = childDesc.layer.blendMode;
5628
- merged.transformSplit = true;
5629
5529
  // Visibility from child
5630
- merged.visibility = childDesc.layer.visibility;
5530
+ merged.visible = childDesc.layer.visible;
5631
5531
  // Compute anchor from child position offset
5632
5532
  var childTransform = childDesc.item['transform'];
5633
5533
  var childPosition = childTransform == null ? void 0 : childTransform['position'];
@@ -5648,7 +5548,9 @@ function mergeNullAndSprite(nullDesc, childDesc, ctx) {
5648
5548
  0
5649
5549
  ]
5650
5550
  };
5651
- merged.displaySize = {
5551
+ merged.localBounds = {
5552
+ x: 0,
5553
+ y: 0,
5652
5554
  width: layerWidth,
5653
5555
  height: layerHeight
5654
5556
  };
@@ -5661,17 +5563,21 @@ function mergeNullAndSprite(nullDesc, childDesc, ctx) {
5661
5563
  merged.transform.opacity = childDesc.layer.transform.opacity;
5662
5564
  }
5663
5565
  // The merged layer renders the child's visual component, but the parent owns
5664
- // transform animation passthrough. Deep-merge the ge2ir namespace so neither
5665
- // side overwrites the other's GE round-trip data.
5666
- if (childDesc.layer.metadata != null) {
5667
- var _merged_metadata;
5668
- var parentGE2IR = isRecord$1((_merged_metadata = merged.metadata) == null ? void 0 : _merged_metadata['ge2ir']) ? merged.metadata['ge2ir'] : undefined;
5669
- var childGE2IR = isRecord$1(childDesc.layer.metadata['ge2ir']) ? childDesc.layer.metadata['ge2ir'] : undefined;
5670
- merged.metadata = _extends({}, merged.metadata, childDesc.layer.metadata);
5671
- if (parentGE2IR != null || childGE2IR != null) {
5672
- merged.metadata['ge2ir'] = _extends({}, parentGE2IR != null ? parentGE2IR : {}, childGE2IR != null ? childGE2IR : {});
5673
- }
5566
+ // transform animation passthrough. Deep-merge specific.effects so neither side
5567
+ // loses GE reconstruction data.
5568
+ if (childDesc.layer.specific != null) {
5569
+ var _merged_specific1;
5570
+ var parentEffects = (_merged_specific1 = merged.specific) == null ? void 0 : _merged_specific1.effects;
5571
+ var childEffects = childDesc.layer.specific.effects;
5572
+ merged.specific = _extends({}, merged.specific, childDesc.layer.specific, (parentEffects != null || childEffects != null) && {
5573
+ effects: _extends({}, parentEffects != null ? parentEffects : {}, childEffects != null ? childEffects : {})
5574
+ });
5674
5575
  }
5576
+ merged.specific = _extends({}, merged.specific, {
5577
+ effects: _extends({}, (_merged_specific = merged.specific) == null ? void 0 : _merged_specific.effects, {
5578
+ sourceHierarchy: 'null-sprite-pair'
5579
+ })
5580
+ });
5675
5581
  return {
5676
5582
  itemId: nullDesc.itemId,
5677
5583
  item: nullDesc.item,
@@ -5700,7 +5606,7 @@ function resolveHierarchy(descriptors, ctx) {
5700
5606
  }
5701
5607
  desc1.layer.parent = {
5702
5608
  index: parentIndex,
5703
- name: parentDesc.layer.name
5609
+ lifetimeMode: 'clipped'
5704
5610
  };
5705
5611
  var parentAnchor = getAnchorFromDesc(parentDesc);
5706
5612
  var pos = (_desc_layer_transform = desc1.layer.transform) == null ? void 0 : _desc_layer_transform.position;
@@ -5765,7 +5671,7 @@ function convertGEToIR(scene, options) {
5765
5671
  return d.layer;
5766
5672
  });
5767
5673
  return normalizeJsonValue({
5768
- source: 'ge',
5674
+ source: 'effects',
5769
5675
  name: ctx.compositionName,
5770
5676
  width: ctx.width,
5771
5677
  height: ctx.height,
@@ -5775,14 +5681,14 @@ function convertGEToIR(scene, options) {
5775
5681
  backgroundColor: ctx.backgroundColor,
5776
5682
  endBehavior: ctx.endBehavior,
5777
5683
  layers: layers,
5778
- metadata: buildCompositionMetadata(scene, ctx.compositionId, itemIds, ctx)
5684
+ specific: buildCompositionSpecific(scene, ctx.compositionId, itemIds, ctx)
5779
5685
  });
5780
5686
  }
5781
5687
  function parseItemToLayer(item, itemId, index, ctx) {
5782
- var _item_name, _item_visible, _ref, _item_delay, _ref1, _item_duration;
5688
+ var _item_name, _item_visible, _ref, _item_delay, _ref1, _item_duration, _ref2;
5783
5689
  var _item_transform;
5784
5690
  var name = (_item_name = item['name']) != null ? _item_name : "layer_" + index;
5785
- var geType = item['type'];
5691
+ var GEType = item['type'];
5786
5692
  var visible = (_item_visible = item['visible']) != null ? _item_visible : true;
5787
5693
  var rawTransformPassthrough;
5788
5694
  var timeline = parseTimeline(itemId, ctx);
@@ -5791,19 +5697,19 @@ function parseItemToLayer(item, itemId, index, ctx) {
5791
5697
  var time = reverseLayerTiming(delay, duration, ctx.frameRate);
5792
5698
  var componentData = parseComponent(item, ctx);
5793
5699
  var type;
5794
- if (geType === '3') {
5700
+ if (GEType === '3') {
5795
5701
  type = 'null';
5796
- } else if ((componentData == null ? void 0 : componentData.type) === 'text' || geType === 'text') {
5702
+ } else if ((componentData == null ? void 0 : componentData.type) === 'text' || GEType === 'text') {
5797
5703
  type = 'text';
5798
- } else if ((componentData == null ? void 0 : componentData.type) === 'shape' || geType === 'shape') {
5704
+ } else if ((componentData == null ? void 0 : componentData.type) === 'shape' || GEType === 'shape') {
5799
5705
  type = 'shape';
5800
5706
  } else if ((componentData == null ? void 0 : componentData.type) === 'image') {
5801
5707
  type = 'image';
5802
- } else if (geType === '7') {
5708
+ } else if (GEType === '7') {
5803
5709
  type = 'precomp';
5804
5710
  } else if ((componentData == null ? void 0 : componentData.solidColor) != null) {
5805
5711
  type = 'solid';
5806
- } else if (geType === '1') {
5712
+ } else if (GEType === '1') {
5807
5713
  type = 'solid';
5808
5714
  } else {
5809
5715
  type = 'null';
@@ -5815,18 +5721,18 @@ function parseItemToLayer(item, itemId, index, ctx) {
5815
5721
  var staticChannels = parseStaticTransform(itemTransform, ctx);
5816
5722
  transform = _extends({}, staticChannels);
5817
5723
  // Text layers carry their pixel-sizing scale on transform.scale
5818
- // (scale = ratio × displaySize). ir2ge RECOMPUTES this item scale from
5819
- // displaySize in processVisualLayer, so keeping it in the IR scale channel
5724
+ // (scale = ratio × local bounds). ir2ge RECOMPUTES this item scale from
5725
+ // localBounds in processVisualLayer, so keeping it in the IR scale channel
5820
5726
  // would make buildSizeAnim emit a duplicate sizeOverLifetime constant that
5821
5727
  // double-scales the glyphs (garbled/stretched text). Drop the static scale
5822
5728
  // for text; genuine text scale animation still rides through
5823
- // metadata.ge2ir.sizeOverLifetime passthrough.
5729
+ // specific.effects.sizeOverLifetime passthrough.
5824
5730
  if (type === 'text') {
5825
5731
  delete transform.scale;
5826
5732
  }
5827
5733
  }
5828
5734
  // Parse animation from timeline tracks — passthrough raw GE animation data
5829
- // via metadata. Converting to IR keyframes and back would lose data (ir2ge
5735
+ // via specific.effects. Converting to IR keyframes and back would lose data (ir2ge
5830
5736
  // only handles specific ValueType variants and makes assumptions about
5831
5737
  // static positions). The raw data is injected verbatim by ir2ge.
5832
5738
  if ((timeline == null ? void 0 : timeline.transformAsset) != null) {
@@ -5840,10 +5746,6 @@ function parseItemToLayer(item, itemId, index, ctx) {
5840
5746
  if (animChannels.rotation != null) {
5841
5747
  transform.rotation = animChannels.rotation;
5842
5748
  }
5843
- if (animChannels.separatedRotation != null) {
5844
- transform.separatedRotation = animChannels.separatedRotation;
5845
- delete transform.rotation;
5846
- }
5847
5749
  if (animChannels.scale != null) {
5848
5750
  transform.scale = animChannels.scale;
5849
5751
  }
@@ -5885,10 +5787,10 @@ function parseItemToLayer(item, itemId, index, ctx) {
5885
5787
  var _item_transform1;
5886
5788
  var itemSize = (_item_transform1 = item['transform']) == null ? void 0 : _item_transform1['size'];
5887
5789
  if (itemSize != null) {
5888
- var _ref2;
5790
+ var _ref3;
5889
5791
  var layerWidth = itemSize.x / ctx.ratio;
5890
5792
  var layerHeight = itemSize.y / ctx.ratio;
5891
- var anchorScale = (_ref2 = componentData == null ? void 0 : componentData.anchorScale) != null ? _ref2 : [
5793
+ var anchorScale = (_ref3 = componentData == null ? void 0 : componentData.anchorScale) != null ? _ref3 : [
5892
5794
  0.5,
5893
5795
  0.5
5894
5796
  ];
@@ -5953,35 +5855,46 @@ function parseItemToLayer(item, itemId, index, ctx) {
5953
5855
  }
5954
5856
  }
5955
5857
  }
5956
- // Display size from item transform.size
5957
- var displaySize;
5858
+ // Layer-local bounds from item transform.size
5859
+ var localBounds;
5958
5860
  var itemSize1 = (_item_transform = item['transform']) == null ? void 0 : _item_transform['size'];
5959
- if (itemSize1 != null) {
5960
- displaySize = {
5861
+ if (itemSize1 != null && itemSize1.x > 0 && itemSize1.y > 0) {
5862
+ localBounds = {
5863
+ x: 0,
5864
+ y: 0,
5961
5865
  width: itemSize1.x / ctx.ratio,
5962
5866
  height: itemSize1.y / ctx.ratio
5963
5867
  };
5964
5868
  }
5869
+ var text = (componentData == null ? void 0 : componentData.text) == null ? undefined : _extends({}, componentData.text);
5870
+ var solidColor = type === 'solid' ? (_ref2 = componentData == null ? void 0 : componentData.solidColor) != null ? _ref2 : [
5871
+ 1,
5872
+ 1,
5873
+ 1,
5874
+ 1
5875
+ ] : componentData == null ? void 0 : componentData.solidColor;
5876
+ if ((text == null ? void 0 : text.autoWidth) === false) {
5877
+ var _text, _width, _text1, _height;
5878
+ (_width = (_text = text).width) != null ? _width : _text.width = localBounds == null ? void 0 : localBounds.width;
5879
+ (_height = (_text1 = text).height) != null ? _height : _text1.height = localBounds == null ? void 0 : localBounds.height;
5880
+ }
5965
5881
  var layer = {
5966
5882
  index: index,
5967
5883
  name: name,
5968
5884
  type: type,
5969
5885
  time: time,
5970
- visibility: {
5971
- hidden: !visible,
5972
- enabled: visible
5973
- },
5886
+ visible: visible,
5974
5887
  transform: transform,
5975
- displaySize: displaySize
5888
+ localBounds: localBounds
5976
5889
  };
5977
5890
  if ((componentData == null ? void 0 : componentData.asset) != null) {
5978
5891
  layer.asset = componentData.asset;
5979
5892
  }
5980
- if ((componentData == null ? void 0 : componentData.solidColor) != null) {
5981
- layer.solidColor = componentData.solidColor;
5893
+ if (solidColor != null) {
5894
+ layer.solidColor = solidColor;
5982
5895
  }
5983
- if ((componentData == null ? void 0 : componentData.text) != null) {
5984
- layer.text = componentData.text;
5896
+ if (text != null) {
5897
+ layer.text = text;
5985
5898
  }
5986
5899
  if ((componentData == null ? void 0 : componentData.shapes) != null) {
5987
5900
  layer.shapes = componentData.shapes;
@@ -5989,38 +5902,39 @@ function parseItemToLayer(item, itemId, index, ctx) {
5989
5902
  if ((componentData == null ? void 0 : componentData.blendMode) != null) {
5990
5903
  layer.blendMode = componentData.blendMode;
5991
5904
  }
5992
- var geComponentId = componentData == null ? void 0 : componentData.geComponentId;
5905
+ var GEComponentId = componentData == null ? void 0 : componentData.GEComponentId;
5993
5906
  var rawMask = componentData == null ? void 0 : componentData.rawMask;
5994
- var precompContent = geType === '7' ? item['content'] : undefined;
5907
+ var precompContent = GEType === '7' ? item['content'] : undefined;
5995
5908
  var precompRefId = isRecord(precompContent == null ? void 0 : precompContent['options']) ? precompContent['options']['refId'] : undefined;
5996
- if (rawTransformPassthrough != null || rawColorOverLifetime != null || geComponentId != null || rawMask != null || typeof precompRefId === 'string' || precompContent != null) {
5997
- // Mask round-trip: geComponentId is the rendezvous key linking a target's
5998
- // mask.reference.id (a GE1 component id) to the regenerated GE2 component id.
5999
- // ir2ge copies ge2ir.geMask onto the rebuilt component and a post-process pass
6000
- // remaps the stale reference id.
6001
- var ge2irMetadata = _extends({}, rawTransformPassthrough != null ? rawTransformPassthrough : {}, rawColorOverLifetime != null && {
6002
- colorOverLifetime: rawColorOverLifetime
6003
- }, geComponentId != null && {
6004
- geComponentId: geComponentId
6005
- }, rawMask != null && {
6006
- geMask: rawMask
6007
- }, typeof precompRefId === 'string' && {
6008
- precompRefId: precompRefId
6009
- }, precompContent != null && {
6010
- precompContent: cloneJson(precompContent)
6011
- });
6012
- layer.metadata = _extends({}, layer.metadata, {
6013
- ge2ir: ge2irMetadata
6014
- });
6015
- }
5909
+ // Mask round-trip: GEComponentId is the rendezvous key linking a target's
5910
+ // mask.reference.id (a GE1 component id) to the regenerated GE2 component id.
5911
+ // ir2ge copies specific.effects.mask onto the rebuilt component and a post-process pass
5912
+ // remaps the stale reference id. sourceHierarchy records the pre-merge shape;
5913
+ // mergeNullSpritePairs replaces it when a pair collapses into one semantic layer.
5914
+ var effectsSpecific = _extends({
5915
+ sourceHierarchy: 'single-item'
5916
+ }, rawTransformPassthrough != null ? rawTransformPassthrough : {}, rawColorOverLifetime != null && {
5917
+ colorOverLifetime: rawColorOverLifetime
5918
+ }, GEComponentId != null && {
5919
+ sourceComponentId: GEComponentId
5920
+ }, rawMask != null && {
5921
+ mask: rawMask
5922
+ }, typeof precompRefId === 'string' && {
5923
+ precompRefId: precompRefId
5924
+ }, precompContent != null && {
5925
+ precompContent: cloneJson(precompContent)
5926
+ });
5927
+ layer.specific = _extends({}, layer.specific, {
5928
+ effects: effectsSpecific
5929
+ });
6016
5930
  return layer;
6017
5931
  }
6018
- function buildCompositionMetadata(scene, compositionId, itemIds, ctx) {
5932
+ function buildCompositionSpecific(scene, compositionId, itemIds, ctx) {
6019
5933
  if (!hasPrecompItem(itemIds, ctx)) {
6020
5934
  return undefined;
6021
5935
  }
6022
5936
  return {
6023
- ge2ir: {
5937
+ effects: {
6024
5938
  sourceCompositionId: compositionId,
6025
5939
  sourceScene: cloneJson(scene)
6026
5940
  }
@@ -6043,12 +5957,10 @@ function isRecord(value) {
6043
5957
  * Read-side accessors for the `IRLayerNode.specific.lottie` slot.
6044
5958
  *
6045
5959
  * The shared generator must not branch on lottie semantics directly — every
6046
- * lottie-specific read goes through these helpers so the rest of `ir2ge` stays
5960
+ * Lottie-specific reads go through these helpers so the rest of ir2ge stays
6047
5961
  * agnostic to the producing tool.
6048
5962
  *
6049
- * `isTransformOnlyParentLink` used to live here, reading
6050
- * `specific.lottie.explicitParent`. It was promoted to a generic IR field
6051
- * (`IRLayerReference.linkKind`); the accessor now lives at `./parent-link.ts`.
5963
+ * Parent lifetime semantics are represented directly by the generic IR relation.
6052
5964
  */ function readLottieSpecific(layer) {
6053
5965
  var _layer_specific;
6054
5966
  return (_layer_specific = layer.specific) == null ? void 0 : _layer_specific.lottie;
@@ -6065,10 +5977,15 @@ exports.convertIRToGE = convertIRToGE;
6065
5977
  exports.createId = createId;
6066
5978
  exports.estimateTextWidth = estimateTextWidth;
6067
5979
  exports.get2dTo3dRatio = get2dTo3dRatio;
5980
+ exports.getEffectsCompositionSpecific = getEffectsCompositionSpecific;
5981
+ exports.getEffectsLayerSpecific = getEffectsLayerSpecific;
5982
+ exports.hasEffectsAnimationPassthrough = hasEffectsAnimationPassthrough;
5983
+ exports.hasEffectsColorAnimationPassthrough = hasEffectsColorAnimationPassthrough;
5984
+ exports.hasIndependentParentLifetime = hasIndependentParentLifetime;
5985
+ exports.invalidateEffectsLayerSpecific = invalidateEffectsLayerSpecific;
6068
5986
  exports.irPositionKeyframesToGE = irPositionKeyframesToGE;
6069
5987
  exports.irScalarKeyframesToGE = irScalarKeyframesToGE;
6070
5988
  exports.irVectorKeyframesToGE = irVectorKeyframesToGE;
6071
- exports.isTransformOnlyParentLink = isTransformOnlyParentLink;
6072
5989
  exports.lerp = lerp;
6073
5990
  exports.normalizeChildVisibilityByParentDelays = normalizeChildVisibilityByParentDelays;
6074
5991
  exports.readLottieSpecific = readLottieSpecific;