lottie: Revise the gradient model

Currently, the `LottieGradient` does not incorporate the `LottieObject` functionality.

It now inherits from the `LottieObject`.
This commit is contained in:
Jinny You 2024-02-16 15:24:17 +09:00 committed by Hermet Park
parent c6cf9cb2cf
commit e333ca9515

View file

@ -80,112 +80,6 @@ struct LottieStroke
};
struct LottieGradient
{
uint32_t populate(ColorStop& color)
{
uint32_t alphaCnt = (color.input->count - (colorStops.count * 4)) / 2;
Array<Fill::ColorStop> output(colorStops.count + alphaCnt);
uint32_t cidx = 0; //color count
uint32_t clast = colorStops.count * 4;
uint32_t aidx = clast; //alpha count
Fill::ColorStop cs;
//merge color stops.
for (uint32_t i = 0; i < color.input->count; ++i) {
if (cidx == clast || aidx == color.input->count) break;
if ((*color.input)[cidx] == (*color.input)[aidx]) {
cs.offset = (*color.input)[cidx];
cs.r = lroundf((*color.input)[cidx + 1] * 255.0f);
cs.g = lroundf((*color.input)[cidx + 2] * 255.0f);
cs.b = lroundf((*color.input)[cidx + 3] * 255.0f);
cs.a = lroundf((*color.input)[aidx + 1] * 255.0f);
cidx += 4;
aidx += 2;
} else if ((*color.input)[cidx] < (*color.input)[aidx]) {
cs.offset = (*color.input)[cidx];
cs.r = lroundf((*color.input)[cidx + 1] * 255.0f);
cs.g = lroundf((*color.input)[cidx + 2] * 255.0f);
cs.b = lroundf((*color.input)[cidx + 3] * 255.0f);
//generate alpha value
if (output.count > 0) {
auto p = ((*color.input)[cidx] - output.last().offset) / ((*color.input)[aidx] - output.last().offset);
cs.a = mathLerp<uint8_t>(output.last().a, lroundf((*color.input)[aidx + 1] * 255.0f), p);
} else cs.a = 255;
cidx += 4;
} else {
cs.offset = (*color.input)[aidx];
cs.a = lroundf((*color.input)[aidx + 1] * 255.0f);
//generate color value
if (output.count > 0) {
auto p = ((*color.input)[aidx] - output.last().offset) / ((*color.input)[cidx] - output.last().offset);
cs.r = mathLerp<uint8_t>(output.last().r, lroundf((*color.input)[cidx + 1] * 255.0f), p);
cs.g = mathLerp<uint8_t>(output.last().g, lroundf((*color.input)[cidx + 2] * 255.0f), p);
cs.b = mathLerp<uint8_t>(output.last().b, lroundf((*color.input)[cidx + 3] * 255.0f), p);
} else cs.r = cs.g = cs.b = 255;
aidx += 2;
}
output.push(cs);
}
//color remains
while (cidx < clast) {
cs.offset = (*color.input)[cidx];
cs.r = lroundf((*color.input)[cidx + 1] * 255.0f);
cs.g = lroundf((*color.input)[cidx + 2] * 255.0f);
cs.b = lroundf((*color.input)[cidx + 3] * 255.0f);
cs.a = (output.count > 0) ? output.last().a : 255;
output.push(cs);
cidx += 4;
}
//alpha remains
while (aidx < color.input->count) {
cs.offset = (*color.input)[aidx];
cs.a = lroundf((*color.input)[aidx + 1] * 255.0f);
if (output.count > 0) {
cs.r = output.last().r;
cs.g = output.last().g;
cs.b = output.last().b;
} else cs.r = cs.g = cs.b = 255;
output.push(cs);
aidx += 2;
}
color.data = output.data;
output.data = nullptr;
color.input->reset();
delete(color.input);
return output.count;
}
bool prepare()
{
if (colorStops.frames) {
for (auto v = colorStops.frames->begin(); v < colorStops.frames->end(); ++v) {
colorStops.count = populate(v->value);
}
} else {
colorStops.count = populate(colorStops.value);
}
if (start.frames || end.frames || height.frames || angle.frames || opacity.frames || colorStops.frames) return true;
return false;
}
Fill* fill(float frameNo);
LottiePoint start = Point{0.0f, 0.0f};
LottiePoint end = Point{0.0f, 0.0f};
LottieFloat height = 0.0f;
LottieFloat angle = 0.0f;
LottieOpacity opacity = 255;
LottieColorStop colorStops;
uint8_t id = 0; //1: linear, 2: radial
};
struct LottieMask
{
LottiePathSet pathset = PathSet{nullptr, nullptr, 0, 0};
@ -456,7 +350,113 @@ struct LottieSolidFill : LottieObject
};
struct LottieGradientFill : LottieObject, LottieGradient
struct LottieGradient : LottieObject
{
uint32_t populate(ColorStop& color)
{
uint32_t alphaCnt = (color.input->count - (colorStops.count * 4)) / 2;
Array<Fill::ColorStop> output(colorStops.count + alphaCnt);
uint32_t cidx = 0; //color count
uint32_t clast = colorStops.count * 4;
uint32_t aidx = clast; //alpha count
Fill::ColorStop cs;
//merge color stops.
for (uint32_t i = 0; i < color.input->count; ++i) {
if (cidx == clast || aidx == color.input->count) break;
if ((*color.input)[cidx] == (*color.input)[aidx]) {
cs.offset = (*color.input)[cidx];
cs.r = lroundf((*color.input)[cidx + 1] * 255.0f);
cs.g = lroundf((*color.input)[cidx + 2] * 255.0f);
cs.b = lroundf((*color.input)[cidx + 3] * 255.0f);
cs.a = lroundf((*color.input)[aidx + 1] * 255.0f);
cidx += 4;
aidx += 2;
} else if ((*color.input)[cidx] < (*color.input)[aidx]) {
cs.offset = (*color.input)[cidx];
cs.r = lroundf((*color.input)[cidx + 1] * 255.0f);
cs.g = lroundf((*color.input)[cidx + 2] * 255.0f);
cs.b = lroundf((*color.input)[cidx + 3] * 255.0f);
//generate alpha value
if (output.count > 0) {
auto p = ((*color.input)[cidx] - output.last().offset) / ((*color.input)[aidx] - output.last().offset);
cs.a = mathLerp<uint8_t>(output.last().a, lroundf((*color.input)[aidx + 1] * 255.0f), p);
} else cs.a = 255;
cidx += 4;
} else {
cs.offset = (*color.input)[aidx];
cs.a = lroundf((*color.input)[aidx + 1] * 255.0f);
//generate color value
if (output.count > 0) {
auto p = ((*color.input)[aidx] - output.last().offset) / ((*color.input)[cidx] - output.last().offset);
cs.r = mathLerp<uint8_t>(output.last().r, lroundf((*color.input)[cidx + 1] * 255.0f), p);
cs.g = mathLerp<uint8_t>(output.last().g, lroundf((*color.input)[cidx + 2] * 255.0f), p);
cs.b = mathLerp<uint8_t>(output.last().b, lroundf((*color.input)[cidx + 3] * 255.0f), p);
} else cs.r = cs.g = cs.b = 255;
aidx += 2;
}
output.push(cs);
}
//color remains
while (cidx < clast) {
cs.offset = (*color.input)[cidx];
cs.r = lroundf((*color.input)[cidx + 1] * 255.0f);
cs.g = lroundf((*color.input)[cidx + 2] * 255.0f);
cs.b = lroundf((*color.input)[cidx + 3] * 255.0f);
cs.a = (output.count > 0) ? output.last().a : 255;
output.push(cs);
cidx += 4;
}
//alpha remains
while (aidx < color.input->count) {
cs.offset = (*color.input)[aidx];
cs.a = lroundf((*color.input)[aidx + 1] * 255.0f);
if (output.count > 0) {
cs.r = output.last().r;
cs.g = output.last().g;
cs.b = output.last().b;
} else cs.r = cs.g = cs.b = 255;
output.push(cs);
aidx += 2;
}
color.data = output.data;
output.data = nullptr;
color.input->reset();
delete(color.input);
return output.count;
}
bool prepare()
{
if (colorStops.frames) {
for (auto v = colorStops.frames->begin(); v < colorStops.frames->end(); ++v) {
colorStops.count = populate(v->value);
}
} else {
colorStops.count = populate(colorStops.value);
}
if (start.frames || end.frames || height.frames || angle.frames || opacity.frames || colorStops.frames) return true;
return false;
}
Fill* fill(float frameNo);
LottiePoint start = Point{0.0f, 0.0f};
LottiePoint end = Point{0.0f, 0.0f};
LottieFloat height = 0.0f;
LottieFloat angle = 0.0f;
LottieOpacity opacity = 255;
LottieColorStop colorStops;
uint8_t id = 0; //1: linear, 2: radial
};
struct LottieGradientFill : LottieGradient
{
void prepare()
{
@ -468,7 +468,7 @@ struct LottieGradientFill : LottieObject, LottieGradient
};
struct LottieGradientStroke : LottieObject, LottieStroke, LottieGradient
struct LottieGradientStroke : LottieGradient, LottieStroke
{
void prepare()
{