mirror of
https://github.com/thorvg/thorvg.git
synced 2025-07-28 09:05:52 +00:00
loader/lottie: introduce chaining maskings more effectively.
This commit is contained in:
parent
21413b1872
commit
07069f6640
5 changed files with 165 additions and 121 deletions
1
src/examples/images/like.json
Normal file
1
src/examples/images/like.json
Normal file
File diff suppressed because one or more lines are too long
|
@ -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);
|
||||
void fillReset(SwFill* fill);
|
||||
void fillFree(SwFill* fill);
|
||||
|
||||
//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, 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); //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 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, 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); //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.
|
||||
|
||||
SwRleData* rleRender(SwRleData* rle, const SwOutline* outline, const SwBBox& renderRegion, bool antiAlias);
|
||||
SwRleData* rleRender(const SwBBox* bbox);
|
||||
|
|
|
@ -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 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;
|
||||
|
||||
for (uint32_t i = 0 ; i < len ; ++i, ++dst, ++cmp) {
|
||||
auto tmp = op(_pixel(fill, sqrtf(det)), *cmp, a);
|
||||
*dst = tmp + ALPHA_BLEND(*dst, IA(tmp));
|
||||
auto src = MULTIPLY(A(_pixel(fill, sqrtf(det))), a);
|
||||
auto tmp = maskOp(src, *cmp, 0);
|
||||
*dst = tmp + MULTIPLY(*dst, ~tmp);
|
||||
det += detFirstDerivative;
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
//Rotation
|
||||
|
|
|
@ -39,16 +39,21 @@ constexpr auto DOWN_SCALE_TOLERANCE = 0.5f;
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
fillLinear(fill, dst, y, x, len, cmp, alpha, csize, opacity);
|
||||
|
@ -63,16 +68,21 @@ struct FillLinear
|
|||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
//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)
|
||||
{
|
||||
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 */
|
||||
/************************************************************************/
|
||||
#if 0
|
||||
|
||||
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 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>
|
||||
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 w = static_cast<uint32_t>(region.max.x - region.min.x);
|
||||
auto cstride = surface->compositor->image.stride;
|
||||
auto cbuffer = surface->compositor->image.buf32 + (region.min.y * cstride + region.min.x);
|
||||
auto dbuffer = surface->buf32 + (region.min.y * surface->stride + region.min.x);
|
||||
auto cbuffer = surface->compositor->image.buf8 + (region.min.y * cstride + region.min.x);
|
||||
auto dbuffer = surface->buf8 + (region.min.y * surface->stride + region.min.x);
|
||||
|
||||
for (uint32_t y = 0; y < h; ++y) {
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<typename fillMethod>
|
||||
static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region, const SwFill* fill)
|
||||
{
|
||||
#if 0
|
||||
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);
|
||||
|
@ -1539,7 +1509,7 @@ static bool _rasterGradientMaskedRect(SwSurface* surface, const SwBBox& region,
|
|||
|
||||
if (_direct(method)) return _rasterDirectGradientMaskedRect<fillMethod>(surface, region, fill, maskOp);
|
||||
else return _rasterCompositeGradientMaskedRect<fillMethod>(surface, region, fill, maskOp);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1651,29 +1621,29 @@ static bool _rasterRadialGradientRect(SwSurface* surface, const SwBBox& region,
|
|||
/************************************************************************/
|
||||
/* Rle Gradient */
|
||||
/************************************************************************/
|
||||
#if 0
|
||||
|
||||
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 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) {
|
||||
auto cmp = &cbuffer[span->y * cstride + span->x];
|
||||
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>
|
||||
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 cstride = surface->compositor->image.stride;
|
||||
auto cbuffer = surface->compositor->image.buf32;
|
||||
auto dbuffer = surface->buf32;
|
||||
auto cbuffer = surface->compositor->image.buf8;
|
||||
auto dbuffer = surface->buf8;
|
||||
|
||||
for (uint32_t i = 0; i < rle->size; ++i, ++span) {
|
||||
auto cmp = &cbuffer[span->y * cstride + span->x];
|
||||
|
@ -1682,7 +1652,7 @@ static bool _rasterDirectGradientMaskedRle(SwSurface* surface, const SwRleData*
|
|||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
template<typename fillMethod>
|
||||
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);
|
||||
|
||||
auto amaskOp = _getAMaskOp(method);
|
||||
auto maskOp = _getMaskOp(method);
|
||||
|
||||
//if (_direct(method)) return _rasterDirectGradientMaskedRle<fillMethod>(surface, rle, fill, amaskOp);
|
||||
//else return _rasterCompositeGradientMaskedRle<fillMethod>(surface, rle, fill, amaskOp);
|
||||
if (_direct(method)) return _rasterDirectGradientMaskedRle<fillMethod>(surface, rle, fill, maskOp);
|
||||
else return _rasterCompositeGradientMaskedRle<fillMethod>(surface, rle, fill, maskOp);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -558,6 +558,8 @@ static void _updateMaskings(LottieLayer* layer, int32_t frameNo)
|
|||
//maskings+clipping
|
||||
Shape* mergingMask = nullptr;
|
||||
|
||||
auto pmethod = CompositeMethod::AlphaMask;
|
||||
|
||||
for (auto m = layer->masks.data; m < layer->masks.end(); ++m) {
|
||||
auto mask = static_cast<LottieMask*>(*m);
|
||||
auto shape = Shape::gen().release();
|
||||
|
@ -567,14 +569,17 @@ static void _updateMaskings(LottieLayer* layer, int32_t frameNo)
|
|||
P(shape)->update(RenderUpdateFlag::Path);
|
||||
}
|
||||
if (mergingMask) {
|
||||
mergingMask->composite(cast<Shape>(shape), mask->method);
|
||||
}
|
||||
else {
|
||||
auto method = mask->method;
|
||||
if (method == CompositeMethod::AddMask) method = CompositeMethod::AlphaMask;
|
||||
if (method == CompositeMethod::SubtractMask) method = CompositeMethod::InvAlphaMask;
|
||||
layer->scene->composite(cast<Shape>(shape), method);
|
||||
if (method == CompositeMethod::SubtractMask && pmethod == method) {
|
||||
method = CompositeMethod::AddMask;
|
||||
} 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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue