lottie: Take care of parentAlpha when drawing with gradient.

Change-Id: Iacdf1df1010a8afe69d15dffa5793791aabc4fef
This commit is contained in:
subhransu mohanty 2018-11-09 10:16:24 +09:00
parent 83b433d4e4
commit a30e5fe28e
4 changed files with 22 additions and 7 deletions

View File

@ -851,6 +851,7 @@ void LOTGFillItem::updateContent(int frameNo)
void LOTGFillItem::updateRenderNode() void LOTGFillItem::updateRenderNode()
{ {
mGradient->setAlpha(parentAlpha());
mDrawable->setBrush(VBrush(mGradient.get())); mDrawable->setBrush(VBrush(mGradient.get()));
mDrawable->setFillRule(mFillRule); mDrawable->setFillRule(mFillRule);
} }
@ -926,6 +927,7 @@ void LOTGStrokeItem::updateContent(int frameNo)
void LOTGStrokeItem::updateRenderNode() void LOTGStrokeItem::updateRenderNode()
{ {
float scale = getScale(mGradient->mMatrix); float scale = getScale(mGradient->mMatrix);
mGradient->setAlpha(parentAlpha());
mDrawable->setBrush(VBrush(mGradient.get())); mDrawable->setBrush(VBrush(mGradient.get()));
mDrawable->setStrokeInfo(mCap, mJoin, mMiterLimit, mDrawable->setStrokeInfo(mCap, mJoin, mMiterLimit,
mWidth * scale); mWidth * scale);

View File

@ -17,6 +17,8 @@ public:
enum class Type { Linear, Radial }; enum class Type { Linear, Radial };
VGradient(VGradient::Type type); VGradient(VGradient::Type type);
void setStops(const VGradientStops &stops); void setStops(const VGradientStops &stops);
void setAlpha(float alpha) {mAlpha = alpha;}
float alpha() const {return mAlpha;}
VGradient() = default; VGradient() = default;
public: public:
@ -25,6 +27,7 @@ public:
VGradient::Spread mSpread; VGradient::Spread mSpread;
VGradient::Mode mMode; VGradient::Mode mMode;
VGradientStops mStops; VGradientStops mStops;
float mAlpha{1.0};
union { union {
struct { struct {
float x1, y1, x2, y2; float x1, y1, x2, y2;

View File

@ -15,17 +15,16 @@ public:
typedef std::unordered_multimap<uint64_t, std::shared_ptr<const CacheInfo>> typedef std::unordered_multimap<uint64_t, std::shared_ptr<const CacheInfo>>
VGradientColorTableHash; VGradientColorTableHash;
bool generateGradientColorTable(const VGradientStops &stops, bool generateGradientColorTable(const VGradientStops &stops, float alpha,
uint32_t *colorTable, int size); uint32_t *colorTable, int size);
inline const std::shared_ptr<const CacheInfo> getBuffer( inline const std::shared_ptr<const CacheInfo> getBuffer(
const VGradient &gradient) const VGradient &gradient)
{ {
uint64_t hash_val = 0; uint64_t hash_val = 0;
std::shared_ptr<const CacheInfo> info; std::shared_ptr<const CacheInfo> info;
const VGradientStops &stops = gradient.mStops; const VGradientStops &stops = gradient.mStops;
for (uint i = 0; i < stops.size() && i <= 2; i++) for (uint i = 0; i < stops.size() && i <= 2; i++)
hash_val += stops[i].second.premulARGB(); hash_val += (stops[i].second.premulARGB() * gradient.alpha());
cacheAccess.lock(); cacheAccess.lock();
@ -72,7 +71,7 @@ protected:
} }
auto cache_entry = std::make_shared<CacheInfo>(gradient.mStops); auto cache_entry = std::make_shared<CacheInfo>(gradient.mStops);
cache_entry->alpha = generateGradientColorTable( cache_entry->alpha = generateGradientColorTable(
gradient.mStops, cache_entry->buffer32, VGradient::colorTableSize); gradient.mStops, gradient.alpha(), cache_entry->buffer32, VGradient::colorTableSize);
cache.insert(std::make_pair(hash_val, cache_entry)); cache.insert(std::make_pair(hash_val, cache_entry));
return cache_entry; return cache_entry;
} }
@ -81,7 +80,7 @@ protected:
std::mutex cacheAccess; std::mutex cacheAccess;
}; };
bool VGradientCache::generateGradientColorTable(const VGradientStops &stops, bool VGradientCache::generateGradientColorTable(const VGradientStops &stops, float opacity,
uint32_t *colorTable, int size) uint32_t *colorTable, int size)
{ {
int dist, idist, pos = 0, i; int dist, idist, pos = 0, i;
@ -91,10 +90,12 @@ bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
uint32_t curColor, nextColor; uint32_t curColor, nextColor;
float delta, t, incr, fpos; float delta, t, incr, fpos;
if (!vCompare(opacity, 1.0f)) alpha = true;
start = stops.data(); start = stops.data();
curr = start; curr = start;
if (!curr->second.isOpaque()) alpha = true; if (!curr->second.isOpaque()) alpha = true;
curColor = curr->second.premulARGB(); curColor = curr->second.premulARGB(opacity);
incr = 1.0 / (float)size; incr = 1.0 / (float)size;
fpos = 1.5 * incr; fpos = 1.5 * incr;
@ -111,7 +112,7 @@ bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
next = (start + i + 1); next = (start + i + 1);
delta = 1 / (next->first - curr->first); delta = 1 / (next->first - curr->first);
if (!next->second.isOpaque()) alpha = true; if (!next->second.isOpaque()) alpha = true;
nextColor = next->second.premulARGB(); nextColor = next->second.premulARGB(opacity);
while (fpos < next->first && pos < size) { while (fpos < next->first && pos < size) {
t = (fpos - curr->first) * delta; t = (fpos - curr->first) * delta;
dist = (int)(255 * t); dist = (int)(255 * t);

View File

@ -259,6 +259,15 @@ public:
return uint((a << 24) | (pr << 16) | (pg << 8) | (pb)); return uint((a << 24) | (pr << 16) | (pg << 8) | (pb));
} }
uint premulARGB(float opacity) const
{
int alpha = a * opacity;
int pr = (r * alpha) / 255;
int pg = (g * alpha) / 255;
int pb = (b * alpha) / 255;
return uint((alpha << 24) | (pr << 16) | (pg << 8) | (pb));
}
public: public:
uchar a; uchar a;
uchar r; uchar r;