Skip to content

Commit 08cb051

Browse files
committed
lottie: clamp playback to last frame
Clamp fractional frame values at the final valid frame instead of only clamping values at the exclusive out point. This prevents playback from advancing past the last frame and then jumping backward when progress reaches the animation endpoint. rename the inFrame, outFrame -> inPoint, outPoint to align with the lottie spec.
1 parent 5544fc2 commit 08cb051

4 files changed

Lines changed: 25 additions & 25 deletions

File tree

src/loaders/lottie/tvgLottieBuilder.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ void LottieBuilder::updateImage(LottieLayer* layer, float frameNo)
981981
}
982982

983983
layer->scene->add(picture->refCnt() == 1 ? picture : picture->duplicate());
984-
image->play((frameNo - layer->inFrame) / (layer->outFrame - layer->inFrame));
984+
image->play((frameNo - layer->inPoint) / (layer->outPoint - layer->inPoint));
985985
}
986986

987987

@@ -1547,7 +1547,7 @@ void LottieBuilder::updateLayer(LottieComposition* comp, Scene* scene, LottieLay
15471547
layer->scene = nullptr;
15481548

15491549
//visibility
1550-
if (frameNo < layer->inFrame || frameNo >= layer->outFrame) {
1550+
if (frameNo < layer->inPoint || frameNo >= layer->outPoint) {
15511551
layer->invalidate();
15521552
return;
15531553
}
@@ -1722,13 +1722,13 @@ void LottieBuilder::updateAudio(LottieComposition* comp, LottieLayer* layer, flo
17221722
if (layer->children.empty()) return;
17231723

17241724
auto ctrl = layer->audio();
1725-
auto active = frameNo >= layer->inFrame && frameNo < layer->outFrame;
1725+
auto active = frameNo >= layer->inPoint && frameNo < layer->outPoint;
17261726
auto volume = active ? ctrl->volume(frameNo, tween, exps) : 100.0f;
17271727

17281728
// audio condition is changed
17291729
if ((active != ctrl->prevActive) || (active && !tvg::equal(volume, ctrl->prevVolume))) {
17301730
auto& src = static_cast<LottieAudio*>(layer->children.first())->src;
1731-
auto offset = active ? (layer->remap(comp, frameNo, exps) - layer->remap(comp, layer->inFrame, exps)) / comp->frameRate : 0.0f;
1731+
auto offset = active ? (layer->remap(comp, frameNo, exps) - layer->remap(comp, layer->inPoint, exps)) / comp->frameRate : 0.0f;
17321732
LottieAudioResolver info = {src.data, src.mimeType, src.size, offset, volume, active, (src.size > 0)};
17331733
audioResolver.func(info, audioResolver.data);
17341734
}

src/loaders/lottie/tvgLottieExpressions.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -489,11 +489,11 @@ static void _buildLayer(jerry_value_t context, float frameNo, LottieLayer* layer
489489
jerry_object_set_sz(context, "hasParent", hasParent);
490490
jerry_value_free(hasParent);
491491

492-
auto inPoint = jerry_number(layer->inFrame / exp->comp->frameRate);
492+
auto inPoint = jerry_number(layer->inPoint / exp->comp->frameRate);
493493
jerry_object_set_sz(context, "inPoint", inPoint);
494494
jerry_value_free(inPoint);
495495

496-
auto outPoint = jerry_number(layer->outFrame / exp->comp->frameRate);
496+
auto outPoint = jerry_number(layer->outPoint / exp->comp->frameRate);
497497
jerry_object_set_sz(context, "outPoint", outPoint);
498498
jerry_value_free(outPoint);
499499

@@ -1127,7 +1127,7 @@ static jerry_value_t _loopOut(const jerry_call_info_t* info, const jerry_value_t
11271127
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
11281128
auto mode = static_cast<LottieProperty::Loop>((int) _loopCommon(args, argsCnt) + LOOP_OUT_OFFSET);
11291129
auto key = (argsCnt > 1) ? jerry_value_as_int32(args[1]) : 0;
1130-
return _buildValue(data->exp->property->loop(data->frameNo, key, mode, data->exp->layer->outFrame), data->exp->property);
1130+
return _buildValue(data->exp->property->loop(data->frameNo, key, mode, data->exp->layer->outPoint), data->exp->property);
11311131
}
11321132

11331133

@@ -1145,7 +1145,7 @@ static jerry_value_t _loopIn(const jerry_call_info_t* info, const jerry_value_t
11451145
auto data = static_cast<ExpContent*>(jerry_object_get_native_ptr(info->function, &freeCb));
11461146
auto mode = _loopCommon(args, argsCnt);
11471147
auto key = (argsCnt > 1) ? jerry_value_as_int32(args[1]) : 0;
1148-
return _buildValue(data->exp->property->loop(data->frameNo, key, mode, data->exp->layer->outFrame), data->exp->property);
1148+
return _buildValue(data->exp->property->loop(data->frameNo, key, mode, data->exp->layer->outPoint), data->exp->property);
11491149
}
11501150

11511151

@@ -1418,11 +1418,11 @@ void LottieExpressions::buildGlobal(Context& context, float frameNo, LottieExpre
14181418
jerry_object_set_sz(context.global, EXP_INDEX, index);
14191419
jerry_value_free(index);
14201420

1421-
auto inPoint = jerry_number(exp->layer->inFrame / exp->comp->frameRate);
1421+
auto inPoint = jerry_number(exp->layer->inPoint / exp->comp->frameRate);
14221422
jerry_object_set_sz(context.global, "inPoint", inPoint);
14231423
jerry_value_free(inPoint);
14241424

1425-
auto outPoint = jerry_number(exp->layer->outFrame / exp->comp->frameRate);
1425+
auto outPoint = jerry_number(exp->layer->outPoint / exp->comp->frameRate);
14261426
jerry_object_set_sz(context.global, "outPoint", outPoint);
14271427
jerry_value_free(outPoint);
14281428
}

src/loaders/lottie/tvgLottieModel.h

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,8 +1047,8 @@ struct LottieRootLayer : LottieGroup
10471047

10481048
float timeStretch = 1.0f;
10491049
float w = 0.0f, h = 0.0f;
1050-
float inFrame = 0.0f;
1051-
float outFrame = 0.0f;
1050+
float inPoint = 0.0f; // frame when the layer becomes visible
1051+
float outPoint = 0.0f; // frame when the layer becomes invisible
10521052
float startFrame = 0.0f;
10531053

10541054
bool effect = false; // true if any effect is activated in its tree
@@ -1195,12 +1195,12 @@ struct LottieComposition
11951195

11961196
float timeAtFrame(float frameNo)
11971197
{
1198-
return (frameNo - root->inFrame) / frameRate;
1198+
return (frameNo - root->inPoint) / frameRate;
11991199
}
12001200

12011201
float frameCnt() const
12021202
{
1203-
return root->outFrame - root->inFrame;
1203+
return root->outPoint - root->inPoint;
12041204
}
12051205

12061206
LottieLayer* asset(unsigned long id)
@@ -1214,9 +1214,9 @@ struct LottieComposition
12141214

12151215
void clamp(float& frameNo)
12161216
{
1217-
frameNo += root->inFrame;
1218-
if (frameNo < root->inFrame) frameNo = root->inFrame;
1219-
if (frameNo >= root->outFrame) frameNo = root->outFrame - 1;
1217+
frameNo += root->inPoint;
1218+
if (frameNo < root->inPoint) frameNo = root->inPoint;
1219+
if (frameNo > root->outPoint - 1.0f) frameNo = root->outPoint - 1.0f;
12201220
}
12211221

12221222
LottieRootLayer* root = nullptr;

src/loaders/lottie/tvgLottieParser.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1595,8 +1595,8 @@ LottieLayer* LottieParser::parseLayer(LottieRootLayer* precomp)
15951595
}
15961596
else if (KEY_AS("ao")) layer->autoOrient = getInt();
15971597
else if (KEY_AS("shapes")) parseShapes(layer->children);
1598-
else if (KEY_AS("ip")) layer->inFrame = getFloat();
1599-
else if (KEY_AS("op")) layer->outFrame = getFloat();
1598+
else if (KEY_AS("ip")) layer->inPoint = getFloat();
1599+
else if (KEY_AS("op")) layer->outPoint = getFloat();
16001600
else if (KEY_AS("st")) layer->startFrame = getFloat();
16011601
else if (KEY_AS("bm")) layer->blendMethod = (BlendMethod) getInt();
16021602
else if (KEY_AS("parent")) layer->pix = getInt();
@@ -1792,14 +1792,14 @@ bool LottieParser::parse()
17921792

17931793
Array<LottieGlyph*> glyphs;
17941794

1795-
auto startFrame = 0.0f;
1796-
auto endFrame = 0.0f;
1795+
auto inPoint = 0.0f;
1796+
auto outPoint = 0.0f;
17971797

17981798
while (auto key = nextObjectKey()) {
17991799
if (KEY_AS("v")) comp->version = getStringCopy();
18001800
else if (KEY_AS("fr")) comp->frameRate = getFloat();
1801-
else if (KEY_AS("ip")) startFrame = getFloat();
1802-
else if (KEY_AS("op")) endFrame = getFloat();
1801+
else if (KEY_AS("ip")) inPoint = getFloat();
1802+
else if (KEY_AS("op")) outPoint = getFloat();
18031803
else if (KEY_AS("w")) comp->w = getFloat();
18041804
else if (KEY_AS("h")) comp->h = getFloat();
18051805
else if (KEY_AS("nm")) comp->name = getStringCopy();
@@ -1817,8 +1817,8 @@ bool LottieParser::parse()
18171817
return false;
18181818
}
18191819

1820-
comp->root->inFrame = startFrame;
1821-
comp->root->outFrame = endFrame;
1820+
comp->root->inPoint = inPoint;
1821+
comp->root->outPoint = outPoint;
18221822

18231823
postProcess(glyphs);
18241824

0 commit comments

Comments
 (0)