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:
Hermet Park 2023-08-22 11:28:56 +09:00
parent 345b867c38
commit 4127f4ce7a

View file

@ -183,12 +183,19 @@ struct LottieProperty
if (frames->count == 1 || frameNo <= frames->first().no) return frames->first().value;
if (frameNo >= frames->last().no) return frames->last().value;
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
if (frameNo > frame->no) continue;
uint32_t low = 1;
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;
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; }
@ -258,14 +265,25 @@ struct LottiePathSet
return true;
}
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
if (frameNo > frame->no) continue;
uint32_t low = 1;
uint32_t high = frames->count - 1;
while (low <= high) {
auto mid = low + (high - low) / 2;
auto frame = frames->data + mid;
if (frameNo == frame->no) {
copy(frame->value, cmds);
copy(frame->value, pts);
return true;
} else if (frameNo > frame->no) {
low = mid + 1;
} else {
high = mid - 1;
}
}
//interpolate
auto frame = frames->data + low;
auto pframe = frame - 1;
copy(pframe->value, cmds);
@ -280,8 +298,6 @@ struct LottiePathSet
}
return true;
}
return false;
}
void prepare() {}
};
@ -340,14 +356,24 @@ struct LottieColorStop
return;
}
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
if (frameNo > frame->no) continue;
uint32_t low = 1;
uint32_t high = frames->count - 1;
while (low <= high) {
auto mid = low + (high - low) / 2;
auto frame = frames->data + mid;
if (frameNo == frame->no) {
fill->colorStops(frame->value.data, count);
return;
} else if (frameNo > frame->no) {
low = mid + 1;
} else {
high = mid - 1;
}
}
//interpolate
auto frame = frames->data + low;
auto pframe = frame - 1;
auto t = float(frameNo - pframe->no) / float(frame->no - pframe->no);
if (pframe->interpolator) t = pframe->interpolator->progress(t);
@ -365,9 +391,8 @@ struct LottieColorStop
result.push({offset, r, g, b, 255});
}
fill->colorStops(result.data, count);
return;
}
}
void prepare() {}
};
@ -409,12 +434,19 @@ struct LottiePosition
if (frames->count == 1 || frameNo <= frames->first().no) return frames->first().value;
if (frameNo >= frames->last().no) return frames->last().value;
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
if (frameNo > frame->no) continue;
uint32_t low = 1;
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;
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)
@ -423,11 +455,18 @@ struct LottiePosition
if (frames->count == 1 || frameNo <= frames->first().no) return 0;
if (frameNo >= frames->last().no) return 0;
for (auto frame = frames->data + 1; frame < frames->end(); ++frame) {
if (frameNo > frame->no) continue;
return (frame - 1)->angle(frame, frameNo);
uint32_t low = 1;
uint32_t high = frames->count - 1;
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()