loader/lottie: introduce chaining maskings more effectively.

This commit is contained in:
Hermet Park 2023-08-25 14:59:25 +09:00
parent 21413b1872
commit 07069f6640
5 changed files with 165 additions and 121 deletions

File diff suppressed because one or more lines are too long

View file

@ -512,15 +512,19 @@ void imageFree(SwImage* image);
bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable); bool fillGenColorTable(SwFill* fill, const Fill* fdata, const Matrix* transform, SwSurface* surface, uint8_t opacity, bool ctable);
void fillReset(SwFill* fill); void fillReset(SwFill* fill);
void fillFree(SwFill* fill); void fillFree(SwFill* fill);
//OPTIMIZE_ME: Skip the function pointer access //OPTIMIZE_ME: Skip the function pointer access
void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t opacity); //composite masking ver.
void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t opacity); //direct masking ver.
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver. void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver.
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver. void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver.
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint32_t* cmp, SwBlender op, uint8_t a); //direct masking ver. void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //matting ver.
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //masking ver.
void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a); //composite masking ver.
void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a) ; //direct masking ver.
void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver. void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a); //blending ver.
void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver. void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a); //blending + BlendingMethod(op2) ver.
void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint32_t* cmp, SwBlender op, uint8_t a) ; //direct masking ver. void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //matting ver.
void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity); //masking ver.
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias); SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
SwRleData* rleRender(const SwBBox* bbox); SwRleData* rleRender(const SwBBox* bbox);

View file

@ -279,7 +279,27 @@ void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint3
} }
void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint32_t* cmp, SwBlender op, uint8_t a) void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t a)
{
auto rx = (x + 0.5f) * fill->radial.a11 + (y + 0.5f) * fill->radial.a12 + fill->radial.shiftX;
auto ry = (x + 0.5f) * fill->radial.a21 + (y + 0.5f) * fill->radial.a22 + fill->radial.shiftY;
// detSecondDerivative = d(detFirstDerivative)/dx = d( d(det)/dx )/dx
auto detSecondDerivative = fill->radial.detSecDeriv;
// detFirstDerivative = d(det)/dx
auto detFirstDerivative = 2.0f * (fill->radial.a11 * rx + fill->radial.a21 * ry) + 0.5f * detSecondDerivative;
auto det = rx * rx + ry * ry;
for (uint32_t i = 0 ; i < len ; ++i, ++dst) {
auto src = MULTIPLY(a, A(_pixel(fill, sqrtf(det))));
*dst = maskOp(src, *dst, ~src);
det += detFirstDerivative;
detFirstDerivative += detSecondDerivative;
}
}
void fillRadial(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t a)
{ {
auto rx = (x + 0.5f) * fill->radial.a11 + (y + 0.5f) * fill->radial.a12 + fill->radial.shiftX; auto rx = (x + 0.5f) * fill->radial.a11 + (y + 0.5f) * fill->radial.a12 + fill->radial.shiftX;
auto ry = (x + 0.5f) * fill->radial.a21 + (y + 0.5f) * fill->radial.a22 + fill->radial.shiftY; auto ry = (x + 0.5f) * fill->radial.a21 + (y + 0.5f) * fill->radial.a22 + fill->radial.shiftY;
@ -291,15 +311,15 @@ void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint3
auto det = rx * rx + ry * ry; auto det = rx * rx + ry * ry;
for (uint32_t i = 0 ; i < len ; ++i, ++dst, ++cmp) { for (uint32_t i = 0 ; i < len ; ++i, ++dst, ++cmp) {
auto tmp = op(_pixel(fill, sqrtf(det)), *cmp, a); auto src = MULTIPLY(A(_pixel(fill, sqrtf(det))), a);
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp)); auto tmp = maskOp(src, *cmp, 0);
*dst = tmp + MULTIPLY(*dst, ~tmp);
det += detFirstDerivative; det += detFirstDerivative;
detFirstDerivative += detSecondDerivative; detFirstDerivative += detSecondDerivative;
} }
} }
void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a) void fillRadial(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a)
{ {
auto rx = (x + 0.5f) * fill->radial.a11 + (y + 0.5f) * fill->radial.a12 + fill->radial.shiftX; auto rx = (x + 0.5f) * fill->radial.a11 + (y + 0.5f) * fill->radial.a12 + fill->radial.shiftX;
@ -404,6 +424,95 @@ void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint3
} }
void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask maskOp, uint8_t a)
{
//Rotation
float rx = x + 0.5f;
float ry = y + 0.5f;
float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1);
float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1);
if (mathZero(inc)) {
auto src = MULTIPLY(a, A(_fixedPixel(fill, static_cast<int32_t>(t * FIXPT_SIZE))));
for (uint32_t i = 0; i < len; ++i, ++dst) {
*dst = maskOp(src, *dst, ~src);
}
return;
}
auto vMax = static_cast<float>(INT32_MAX >> (FIXPT_BITS + 1));
auto vMin = -vMax;
auto v = t + (inc * len);
//we can use fixed point math
if (v < vMax && v > vMin) {
auto t2 = static_cast<int32_t>(t * FIXPT_SIZE);
auto inc2 = static_cast<int32_t>(inc * FIXPT_SIZE);
for (uint32_t j = 0; j < len; ++j, ++dst) {
auto src = MULTIPLY(_fixedPixel(fill, t2), a);
*dst = maskOp(src, *dst, ~src);
t2 += inc2;
}
//we have to fallback to float math
} else {
uint32_t counter = 0;
while (counter++ < len) {
auto src = MULTIPLY(_pixel(fill, t / GRADIENT_STOP_SIZE), a);
*dst = maskOp(src, *dst, ~src);
++dst;
t += inc;
}
}
}
void fillLinear(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask maskOp, uint8_t a)
{
//Rotation
float rx = x + 0.5f;
float ry = y + 0.5f;
float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1);
float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1);
if (mathZero(inc)) {
auto src = A(_fixedPixel(fill, static_cast<int32_t>(t * FIXPT_SIZE)));
src = MULTIPLY(src, a);
for (uint32_t i = 0; i < len; ++i, ++dst, ++cmp) {
auto tmp = maskOp(src, *cmp, 0);
*dst = tmp + MULTIPLY(*dst, ~tmp);
}
return;
}
auto vMax = static_cast<float>(INT32_MAX >> (FIXPT_BITS + 1));
auto vMin = -vMax;
auto v = t + (inc * len);
//we can use fixed point math
if (v < vMax && v > vMin) {
auto t2 = static_cast<int32_t>(t * FIXPT_SIZE);
auto inc2 = static_cast<int32_t>(inc * FIXPT_SIZE);
for (uint32_t j = 0; j < len; ++j, ++dst, ++cmp) {
auto src = MULTIPLY(a, A(_fixedPixel(fill, t2)));
auto tmp = maskOp(src, *cmp, 0);
*dst = tmp + MULTIPLY(*dst, ~tmp);
t2 += inc2;
}
//we have to fallback to float math
} else {
uint32_t counter = 0;
while (counter++ < len) {
auto src = MULTIPLY(A(_pixel(fill, t / GRADIENT_STOP_SIZE)), a);
auto tmp = maskOp(src, *cmp, 0);
*dst = tmp + MULTIPLY(*dst, ~tmp);
++dst;
++cmp;
t += inc;
}
}
}
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a)
{ {
//Rotation //Rotation
@ -444,51 +553,6 @@ void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint3
} }
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint32_t* cmp, SwBlender op, uint8_t a)
{
//Rotation
float rx = x + 0.5f;
float ry = y + 0.5f;
float t = (fill->linear.dx * rx + fill->linear.dy * ry + fill->linear.offset) * (GRADIENT_STOP_SIZE - 1);
float inc = (fill->linear.dx) * (GRADIENT_STOP_SIZE - 1);
if (mathZero(inc)) {
auto color = _fixedPixel(fill, static_cast<int32_t>(t * FIXPT_SIZE));
for (uint32_t i = 0; i < len; ++i, ++dst, ++cmp) {
auto tmp = op(color, *cmp, a);
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
}
return;
}
auto vMax = static_cast<float>(INT32_MAX >> (FIXPT_BITS + 1));
auto vMin = -vMax;
auto v = t + (inc * len);
//we can use fixed point math
if (v < vMax && v > vMin) {
auto t2 = static_cast<int32_t>(t * FIXPT_SIZE);
auto inc2 = static_cast<int32_t>(inc * FIXPT_SIZE);
for (uint32_t j = 0; j < len; ++j, ++dst, ++cmp) {
auto tmp = op(_fixedPixel(fill, t2), *cmp, a);
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
t2 += inc2;
}
//we have to fallback to float math
} else {
uint32_t counter = 0;
while (counter++ < len) {
auto tmp = op(_pixel(fill, t / GRADIENT_STOP_SIZE), *cmp, a);
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
++dst;
++cmp;
t += inc;
}
}
}
void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a) void fillLinear(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, SwBlender op2, uint8_t a)
{ {
//Rotation //Rotation

View file

@ -39,16 +39,21 @@ constexpr auto DOWN_SCALE_TOLERANCE = 0.5f;
struct FillLinear struct FillLinear
{ {
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a)
{ {
fillLinear(fill, dst, y, x, len, op, a); fillLinear(fill, dst, y, x, len, op, a);
} }
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint32_t* cmp, SwBlender op, uint8_t a) void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a)
{ {
fillLinear(fill, dst, y, x, len, cmp, op, a); fillLinear(fill, dst, y, x, len, cmp, op, a);
} }
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a)
{
fillLinear(fill, dst, y, x, len, op, a);
}
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity) void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity)
{ {
fillLinear(fill, dst, y, x, len, cmp, alpha, csize, opacity); fillLinear(fill, dst, y, x, len, cmp, alpha, csize, opacity);
@ -63,16 +68,21 @@ struct FillLinear
struct FillRadial struct FillRadial
{ {
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a) void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, SwMask op, uint8_t a)
{ {
fillRadial(fill, dst, y, x, len, op, a); fillRadial(fill, dst, y, x, len, op, a);
} }
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint32_t* cmp, SwBlender op, uint8_t a) void operator()(const SwFill* fill, uint8_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwMask op, uint8_t a)
{ {
fillRadial(fill, dst, y, x, len, cmp, op, a); fillRadial(fill, dst, y, x, len, cmp, op, a);
} }
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, SwBlender op, uint8_t a)
{
fillRadial(fill, dst, y, x, len, op, a);
}
void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity) void operator()(const SwFill* fill, uint32_t* dst, uint32_t y, uint32_t x, uint32_t len, uint8_t* cmp, SwAlpha alpha, uint8_t csize, uint8_t opacity)
{ {
fillRadial(fill, dst, y, x, len, cmp, alpha, csize, opacity); fillRadial(fill, dst, y, x, len, cmp, alpha, csize, opacity);
@ -187,33 +197,6 @@ static inline uint8_t _opMaskDifference(uint8_t s, uint8_t d, uint8_t a)
} }
static inline uint8_t _opAMaskAdd(uint8_t s, uint8_t d, uint8_t a)
{
return INTERPOLATE8(s, d, a);
}
static inline uint8_t _opAMaskSubtract(TVG_UNUSED uint8_t s, uint8_t d, uint8_t a)
{
return s;
//return ALPHA_BLEND(s, MULTIPLY(IA(d), a));
}
static inline uint8_t _opAMaskDifference(uint8_t s, uint8_t d, uint8_t a)
{
auto t = MULTIPLY(s, a);
return MULTIPLY(t, 255 - d) + MULTIPLY(d, 255 - t);
}
static inline uint8_t _opAMaskIntersect(uint8_t s, uint8_t d, uint8_t a)
{
return s;
//return ALPHA_BLEND(s, MULTIPLY(A(d), a));
}
static inline bool _direct(CompositeMethod method) static inline bool _direct(CompositeMethod method)
{ {
//subtract & Intersect allows the direct composition //subtract & Intersect allows the direct composition
@ -234,18 +217,6 @@ static inline SwMask _getMaskOp(CompositeMethod method)
} }
static inline SwMask _getAMaskOp(CompositeMethod method)
{
switch (method) {
case CompositeMethod::AddMask: return _opAMaskAdd;
case CompositeMethod::SubtractMask: return _opAMaskSubtract;
case CompositeMethod::DifferenceMask: return _opAMaskDifference;
case CompositeMethod::IntersectMask: return _opAMaskIntersect;
default: return nullptr;
}
}
static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const SwBBox& region) static bool _compositeMaskImage(SwSurface* surface, const SwImage* image, const SwBBox& region)
{ {
auto dbuffer = &surface->buf8[region.min.y * surface->stride + region.min.x]; auto dbuffer = &surface->buf8[region.min.y * surface->stride + region.min.x];
@ -1492,9 +1463,9 @@ static bool _rasterImage(SwSurface* surface, SwImage* image, const Matrix* trans
/************************************************************************/ /************************************************************************/
/* Rect Gradient */ /* Rect Gradient */
/************************************************************************/ /************************************************************************/
#if 0
template<typename fillMethod> template<typename fillMethod>
static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwBlender maskOp) static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwMask maskOp)
{ {
auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto w = static_cast<uint32_t>(region.max.x - region.min.x);
@ -1510,13 +1481,13 @@ static bool _rasterCompositeGradientMaskedRect(SwSurface* surface, const SwBBox&
template<typename fillMethod> template<typename fillMethod>
static bool _rasterDirectGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwBlender maskOp) static bool _rasterDirectGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill, SwMask maskOp)
{ {
auto h = static_cast<uint32_t>(region.max.y - region.min.y); auto h = static_cast<uint32_t>(region.max.y - region.min.y);
auto w = static_cast<uint32_t>(region.max.x - region.min.x); auto w = static_cast<uint32_t>(region.max.x - region.min.x);
auto cstride = surface->compositor->image.stride; auto cstride = surface->compositor->image.stride;
auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x); auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x);
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x); auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x);
for (uint32_t y = 0; y < h; ++y) { for (uint32_t y = 0; y < h; ++y) {
fillMethod()(fill, dbuffer, region.min.y + y, region.min.x, w, cbuffer, maskOp, 255); fillMethod()(fill, dbuffer, region.min.y + y, region.min.x, w, cbuffer, maskOp, 255);
@ -1525,12 +1496,11 @@ static bool _rasterDirectGradientMaskedRect(SwSurface* surface, const SwBBox& re
} }
return true; return true;
} }
#endif
template<typename fillMethod> template<typename fillMethod>
static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill) static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
{ {
#if 0
auto method = surface->compositor->method; auto method = surface->compositor->method;
TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y); TVGLOG("SW_ENGINE", "Masked(%d) Gradient [Region: %lu %lu %lu %lu]", (int)method, region.min.x, region.min.y, region.max.x - region.min.x, region.max.y - region.min.y);
@ -1539,7 +1509,7 @@ static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region,
if (_direct(method)) return _rasterDirectGradientMaskedRect<fillMethod>(surface, region, fill, maskOp); if (_direct(method)) return _rasterDirectGradientMaskedRect<fillMethod>(surface, region, fill, maskOp);
else return _rasterCompositeGradientMaskedRect<fillMethod>(surface, region, fill, maskOp); else return _rasterCompositeGradientMaskedRect<fillMethod>(surface, region, fill, maskOp);
#endif
return false; return false;
} }
@ -1651,29 +1621,29 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
/************************************************************************/ /************************************************************************/
/* Rle Gradient */ /* Rle Gradient */
/************************************************************************/ /************************************************************************/
#if 0
template<typename fillMethod> template<typename fillMethod>
static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwBlender maskOp) static bool _rasterCompositeGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwMask maskOp)
{ {
auto span = rle->spans; auto span = rle->spans;
auto cstride = surface->compositor->image.stride; auto cstride = surface->compositor->image.stride;
auto cbuffer = surface->compositor->image.buf32; auto cbuffer = surface->compositor->image.buf8;
for (uint32_t i = 0; i < rle->size; ++i, ++span) { for (uint32_t i = 0; i < rle->size; ++i, ++span) {
auto cmp = &cbuffer[span->y * cstride + span->x]; auto cmp = &cbuffer[span->y * cstride + span->x];
fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage); fillMethod()(fill, cmp, span->y, span->x, span->len, maskOp, span->coverage);
} }
return _rasterDirectImage(surface, &surface->compositor->image, surface->compositor->bbox, 255); return _compositeMaskImage(surface, &surface->compositor->image, surface->compositor->bbox);
} }
template<typename fillMethod> template<typename fillMethod>
static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwBlender maskOp) static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill, SwMask maskOp)
{ {
auto span = rle->spans; auto span = rle->spans;
auto cstride = surface->compositor->image.stride; auto cstride = surface->compositor->image.stride;
auto cbuffer = surface->compositor->image.buf32; auto cbuffer = surface->compositor->image.buf8;
auto dbuffer = surface->buf32; auto dbuffer = surface->buf8;
for (uint32_t i = 0; i < rle->size; ++i, ++span) { for (uint32_t i = 0; i < rle->size; ++i, ++span) {
auto cmp = &cbuffer[span->y * cstride + span->x]; auto cmp = &cbuffer[span->y * cstride + span->x];
@ -1682,7 +1652,7 @@ static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData*
} }
return true; return true;
} }
#endif
template<typename fillMethod> template<typename fillMethod>
static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill) static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, const SwFill* fill)
@ -1691,10 +1661,10 @@ static bool _rasterGradientMaskedRle(SwSurface* surface, const SwRleData* rle, c
TVGLOG("SW_ENGINE", "Masked(%d) Rle Linear Gradient", (int)method); TVGLOG("SW_ENGINE", "Masked(%d) Rle Linear Gradient", (int)method);
auto amaskOp = _getAMaskOp(method); auto maskOp = _getMaskOp(method);
//if (_direct(method)) return _rasterDirectGradientMaskedRle<fillMethod>(surface, rle, fill, amaskOp); if (_direct(method)) return _rasterDirectGradientMaskedRle<fillMethod>(surface, rle, fill, maskOp);
//else return _rasterCompositeGradientMaskedRle<fillMethod>(surface, rle, fill, amaskOp); else return _rasterCompositeGradientMaskedRle<fillMethod>(surface, rle, fill, maskOp);
return false; return false;
} }

View file

@ -558,6 +558,8 @@ static void _updateMaskings(LottieLayer* layer, int32_t frameNo)
//maskings+clipping //maskings+clipping
Shape* mergingMask = nullptr; Shape* mergingMask = nullptr;
auto pmethod = CompositeMethod::AlphaMask;
for (auto m = layer->masks.data; m < layer->masks.end(); ++m) { for (auto m = layer->masks.data; m < layer->masks.end(); ++m) {
auto mask = static_cast<LottieMask*>(*m); auto mask = static_cast<LottieMask*>(*m);
auto shape = Shape::gen().release(); auto shape = Shape::gen().release();
@ -567,14 +569,17 @@ static void _updateMaskings(LottieLayer* layer, int32_t frameNo)
P(shape)->update(RenderUpdateFlag::Path); P(shape)->update(RenderUpdateFlag::Path);
} }
if (mergingMask) { if (mergingMask) {
mergingMask->composite(cast<Shape>(shape), mask->method);
}
else {
auto method = mask->method; auto method = mask->method;
if (method == CompositeMethod::AddMask) method = CompositeMethod::AlphaMask; if (method == CompositeMethod::SubtractMask && pmethod == method) {
if (method == CompositeMethod::SubtractMask) method = CompositeMethod::InvAlphaMask; method = CompositeMethod::AddMask;
layer->scene->composite(cast<Shape>(shape), method); } else if (pmethod == CompositeMethod::DifferenceMask && pmethod == method) {
method = CompositeMethod::IntersectMask;
}
mergingMask->composite(cast<Shape>(shape), method);
} else {
layer->scene->composite(cast<Shape>(shape), CompositeMethod::AlphaMask);
} }
pmethod = mask->method;
mergingMask = shape; mergingMask = shape;
} }
} }