mirror of
https://github.com/thorvg/thorvg.git
synced 2025-06-14 12:04:29 +00:00
loader/lottie: revised the key-frame searching
Replace the linear search algorithm with binary-search. The performance enhancement may not yield significant benefits in normal cases. However, it becomes crucial if the animation comprises an extensive number of frames...
This commit is contained in:
parent
345b867c38
commit
4127f4ce7a
1 changed files with 87 additions and 48 deletions
|
@ -183,12 +183,19 @@ struct LottieProperty
|
||||||
if (frames->count == 1 || frameNo <= frames->first().no) return frames->first().value;
|
if (frames->count == 1 || frameNo <= frames->first().no) return frames->first().value;
|
||||||
if (frameNo >= frames->last().no) return frames->last().value;
|
if (frameNo >= frames->last().no) return frames->last().value;
|
||||||
|
|
||||||
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
|
uint32_t low = 1;
|
||||||
if (frameNo > frame->no) continue;
|
uint32_t high = frames->count - 1;
|
||||||
|
|
||||||
|
while (low <= high) {
|
||||||
|
auto mid = low + (high - low) / 2;
|
||||||
|
auto frame = frames->data + mid;
|
||||||
if (frameNo == frame->no) return frame->value;
|
if (frameNo == frame->no) return frame->value;
|
||||||
return (frame - 1)->interpolate(frame, frameNo);
|
else if (frameNo > frame->no) low = mid + 1;
|
||||||
|
else high = mid - 1;
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
|
auto frame = frames->data + low;
|
||||||
|
return (frame - 1)->interpolate(frame, frameNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
float angle(int32_t frameNo) { return 0; }
|
float angle(int32_t frameNo) { return 0; }
|
||||||
|
@ -258,29 +265,38 @@ struct LottiePathSet
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
|
uint32_t low = 1;
|
||||||
if (frameNo > frame->no) continue;
|
uint32_t high = frames->count - 1;
|
||||||
|
|
||||||
|
while (low <= high) {
|
||||||
|
auto mid = low + (high - low) / 2;
|
||||||
|
auto frame = frames->data + mid;
|
||||||
if (frameNo == frame->no) {
|
if (frameNo == frame->no) {
|
||||||
copy(frame->value, cmds);
|
copy(frame->value, cmds);
|
||||||
copy(frame->value, pts);
|
copy(frame->value, pts);
|
||||||
return true;
|
return true;
|
||||||
|
} else if (frameNo > frame->no) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid - 1;
|
||||||
}
|
}
|
||||||
//interpolate
|
|
||||||
auto pframe = frame - 1;
|
|
||||||
copy(pframe->value, cmds);
|
|
||||||
|
|
||||||
auto t = float(frameNo - pframe->no) / float(frame->no - pframe->no);
|
|
||||||
if (pframe->interpolator) t = pframe->interpolator->progress(t);
|
|
||||||
|
|
||||||
auto s = pframe->value.pts;
|
|
||||||
auto e = frame->value.pts;
|
|
||||||
|
|
||||||
for (auto i = 0; i < pframe->value.ptsCnt; ++i, ++s, ++e) {
|
|
||||||
pts.push(mathLerp(*s, *e, t));
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
//interpolate
|
||||||
|
auto frame = frames->data + low;
|
||||||
|
auto pframe = frame - 1;
|
||||||
|
copy(pframe->value, cmds);
|
||||||
|
|
||||||
|
auto t = float(frameNo - pframe->no) / float(frame->no - pframe->no);
|
||||||
|
if (pframe->interpolator) t = pframe->interpolator->progress(t);
|
||||||
|
|
||||||
|
auto s = pframe->value.pts;
|
||||||
|
auto e = frame->value.pts;
|
||||||
|
|
||||||
|
for (auto i = 0; i < pframe->value.ptsCnt; ++i, ++s, ++e) {
|
||||||
|
pts.push(mathLerp(*s, *e, t));
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare() {}
|
void prepare() {}
|
||||||
|
@ -340,34 +356,43 @@ struct LottieColorStop
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
|
uint32_t low = 1;
|
||||||
if (frameNo > frame->no) continue;
|
uint32_t high = frames->count - 1;
|
||||||
|
|
||||||
|
while (low <= high) {
|
||||||
|
auto mid = low + (high - low) / 2;
|
||||||
|
auto frame = frames->data + mid;
|
||||||
if (frameNo == frame->no) {
|
if (frameNo == frame->no) {
|
||||||
fill->colorStops(frame->value.data, count);
|
fill->colorStops(frame->value.data, count);
|
||||||
return;
|
return;
|
||||||
|
} else if (frameNo > frame->no) {
|
||||||
|
low = mid + 1;
|
||||||
|
} else {
|
||||||
|
high = mid - 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//interpolate
|
//interpolate
|
||||||
auto pframe = frame - 1;
|
auto frame = frames->data + low;
|
||||||
auto t = float(frameNo - pframe->no) / float(frame->no - pframe->no);
|
auto pframe = frame - 1;
|
||||||
if (pframe->interpolator) t = pframe->interpolator->progress(t);
|
auto t = float(frameNo - pframe->no) / float(frame->no - pframe->no);
|
||||||
|
if (pframe->interpolator) t = pframe->interpolator->progress(t);
|
||||||
|
|
||||||
auto s = pframe->value.data;
|
auto s = pframe->value.data;
|
||||||
auto e = frame->value.data;
|
auto e = frame->value.data;
|
||||||
|
|
||||||
Array<Fill::ColorStop> result;
|
Array<Fill::ColorStop> result;
|
||||||
|
|
||||||
for (auto i = 0; i < count; ++i, ++s, ++e) {
|
for (auto i = 0; i < count; ++i, ++s, ++e) {
|
||||||
auto offset = mathLerp(s->offset, e->offset, t);
|
auto offset = mathLerp(s->offset, e->offset, t);
|
||||||
auto r = mathLerp(s->r, e->r, t);
|
auto r = mathLerp(s->r, e->r, t);
|
||||||
auto g = mathLerp(s->g, e->g, t);
|
auto g = mathLerp(s->g, e->g, t);
|
||||||
auto b = mathLerp(s->b, e->b, t);
|
auto b = mathLerp(s->b, e->b, t);
|
||||||
result.push({offset, r, g, b, 255});
|
result.push({offset, r, g, b, 255});
|
||||||
}
|
}
|
||||||
fill->colorStops(result.data, count);
|
fill->colorStops(result.data, count);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare() {}
|
void prepare() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -409,12 +434,19 @@ struct LottiePosition
|
||||||
if (frames->count == 1 || frameNo <= frames->first().no) return frames->first().value;
|
if (frames->count == 1 || frameNo <= frames->first().no) return frames->first().value;
|
||||||
if (frameNo >= frames->last().no) return frames->last().value;
|
if (frameNo >= frames->last().no) return frames->last().value;
|
||||||
|
|
||||||
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
|
uint32_t low = 1;
|
||||||
if (frameNo > frame->no) continue;
|
uint32_t high = frames->count - 1;
|
||||||
|
|
||||||
|
while (low <= high) {
|
||||||
|
auto mid = low + (high - low) / 2;
|
||||||
|
auto frame = frames->data + mid;
|
||||||
if (frameNo == frame->no) return frame->value;
|
if (frameNo == frame->no) return frame->value;
|
||||||
return (frame - 1)->interpolate(frame, frameNo);
|
else if (frameNo > frame->no) low = mid + 1;
|
||||||
|
else high = mid - 1;
|
||||||
}
|
}
|
||||||
return value;
|
|
||||||
|
auto frame = frames->data + low;
|
||||||
|
return (frame - 1)->interpolate(frame, frameNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
float angle(int32_t frameNo)
|
float angle(int32_t frameNo)
|
||||||
|
@ -423,11 +455,18 @@ struct LottiePosition
|
||||||
if (frames->count == 1 || frameNo <= frames->first().no) return 0;
|
if (frames->count == 1 || frameNo <= frames->first().no) return 0;
|
||||||
if (frameNo >= frames->last().no) return 0;
|
if (frameNo >= frames->last().no) return 0;
|
||||||
|
|
||||||
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
|
uint32_t low = 1;
|
||||||
if (frameNo > frame->no) continue;
|
uint32_t high = frames->count - 1;
|
||||||
return (frame - 1)->angle(frame, frameNo);
|
|
||||||
|
while (low <= high) {
|
||||||
|
auto mid = low + (high - low) / 2;
|
||||||
|
auto frame = frames->data + mid;
|
||||||
|
if (frameNo > frame->no) low = mid + 1;
|
||||||
|
else high = mid - 1;
|
||||||
}
|
}
|
||||||
return 0;
|
|
||||||
|
auto frame = frames->data + low;
|
||||||
|
return (frame - 1)->angle(frame, frameNo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepare()
|
void prepare()
|
||||||
|
|
Loading…
Add table
Reference in a new issue