lottie/text: applied Text Range randomization.

on each parse, if the `randomize` is enabled,
the start and end of the Text Range are redefined
with the same gap as the original range.

issue: https://github.com/thorvg/thorvg/issues/2178
This commit is contained in:
Jinny You 2024-09-18 15:42:56 +09:00 committed by Hermet Park
parent 8acb135cb0
commit c10c713c05
4 changed files with 25 additions and 9 deletions

View file

@ -1069,14 +1069,10 @@ void LottieBuilder::updateText(LottieLayer* layer, float frameNo)
//text range process //text range process
for (auto s = text->ranges.begin(); s < text->ranges.end(); ++s) { for (auto s = text->ranges.begin(); s < text->ranges.end(); ++s) {
float start, end;
(*s)->range(frameNo, totalChars, start, end);
auto basedIdx = idx; auto basedIdx = idx;
float divisor = (*s)->rangeUnit == LottieTextRange::Unit::Percent ? (100.0f / totalChars) : 1;
auto offset = (*s)->offset(frameNo) / divisor;
auto start = nearbyintf((*s)->start(frameNo) / divisor) + offset;
auto end = nearbyintf((*s)->end(frameNo) / divisor) + offset;
if (start > end) std::swap(start, end);
if ((*s)->based == LottieTextRange::Based::CharsExcludingSpaces) basedIdx = idx - space; if ((*s)->based == LottieTextRange::Based::CharsExcludingSpaces) basedIdx = idx - space;
else if ((*s)->based == LottieTextRange::Based::Words) basedIdx = line + space; else if ((*s)->based == LottieTextRange::Based::Words) basedIdx = line + space;
else if ((*s)->based == LottieTextRange::Based::Lines) basedIdx = line; else if ((*s)->based == LottieTextRange::Based::Lines) basedIdx = line;

View file

@ -110,6 +110,24 @@ void LottieSlot::assign(LottieObject* target)
} }
void LottieTextRange::range(float frameNo, size_t totalLen, float& start, float& end)
{
float divisor = rangeUnit == Unit::Percent ? (100.0f / totalLen) : 1;
auto offset = this->offset(frameNo) / divisor;
start = nearbyintf(this->start(frameNo) / divisor) + offset;
end = nearbyintf(this->end(frameNo) / divisor) + offset;
if (start > end) std::swap(start, end);
if (random == 0) return;
auto range = end - start;
auto len = rangeUnit == Unit::Percent ? 100 : totalLen;
start = random % int(len - range);
end = start + range;
}
LottieImage::~LottieImage() LottieImage::~LottieImage()
{ {
free(b64Data); free(b64Data);

View file

@ -184,8 +184,10 @@ struct LottieTextRange
Based based = Chars; Based based = Chars;
Shape shape = Square; Shape shape = Square;
Unit rangeUnit = Percent; Unit rangeUnit = Percent;
uint8_t random = 0;
bool expressible = false; bool expressible = false;
bool randomize = false;
void range(float frameNo, size_t totalLen, float& start, float& end);
}; };

View file

@ -1123,7 +1123,7 @@ void LottieParser::parseTextRange(LottieText* text)
else if (KEY_AS("ne")) parseProperty<LottieProperty::Type::Float>(selector->minEase); else if (KEY_AS("ne")) parseProperty<LottieProperty::Type::Float>(selector->minEase);
else if (KEY_AS("a")) parseProperty<LottieProperty::Type::Float>(selector->maxAmount); else if (KEY_AS("a")) parseProperty<LottieProperty::Type::Float>(selector->maxAmount);
else if (KEY_AS("b")) selector->based = (LottieTextRange::Based) getInt(); else if (KEY_AS("b")) selector->based = (LottieTextRange::Based) getInt();
else if (KEY_AS("rn")) selector->randomize = (bool) getInt(); else if (KEY_AS("rn") && getInt()) selector->random = rand();
else if (KEY_AS("sh")) selector->shape = (LottieTextRange::Shape) getInt(); else if (KEY_AS("sh")) selector->shape = (LottieTextRange::Shape) getInt();
else if (KEY_AS("o")) parseProperty<LottieProperty::Type::Float>(selector->offset); else if (KEY_AS("o")) parseProperty<LottieProperty::Type::Float>(selector->offset);
else if (KEY_AS("r")) selector->rangeUnit = (LottieTextRange::Unit) getInt(); else if (KEY_AS("r")) selector->rangeUnit = (LottieTextRange::Unit) getInt();