lottie: Take care of parentAlpha when drawing with gradient. 35/192735/1
authorsubhransu mohanty <sub.mohanty@samsung.com>
Fri, 9 Nov 2018 01:16:24 +0000 (10:16 +0900)
committersubhransu mohanty <sub.mohanty@samsung.com>
Fri, 9 Nov 2018 01:16:24 +0000 (10:16 +0900)
Change-Id: Iacdf1df1010a8afe69d15dffa5793791aabc4fef

src/lottie/lottieitem.cpp
src/vector/vbrush.h
src/vector/vdrawhelper.cpp
src/vector/vglobal.h

index 0249bec..cb7a2ad 100644 (file)
@@ -851,6 +851,7 @@ void LOTGFillItem::updateContent(int frameNo)
 
 void LOTGFillItem::updateRenderNode()
 {
+    mGradient->setAlpha(parentAlpha());
     mDrawable->setBrush(VBrush(mGradient.get()));
     mDrawable->setFillRule(mFillRule);
 }
@@ -926,6 +927,7 @@ void LOTGStrokeItem::updateContent(int frameNo)
 void LOTGStrokeItem::updateRenderNode()
 {
     float scale = getScale(mGradient->mMatrix);
+    mGradient->setAlpha(parentAlpha());
     mDrawable->setBrush(VBrush(mGradient.get()));
     mDrawable->setStrokeInfo(mCap, mJoin, mMiterLimit,
                             mWidth * scale);
index ca03a1d..9a31715 100644 (file)
@@ -17,6 +17,8 @@ public:
     enum class Type { Linear, Radial };
     VGradient(VGradient::Type type);
     void setStops(const VGradientStops &stops);
+    void setAlpha(float alpha) {mAlpha = alpha;}
+    float alpha() const {return mAlpha;}
     VGradient() = default;
 
 public:
@@ -25,6 +27,7 @@ public:
     VGradient::Spread    mSpread;
     VGradient::Mode      mMode;
     VGradientStops       mStops;
+    float                mAlpha{1.0};
     union {
         struct {
             float x1, y1, x2, y2;
index 90f20eb..2deb2aa 100644 (file)
@@ -15,17 +15,16 @@ public:
 
     typedef std::unordered_multimap<uint64_t, std::shared_ptr<const CacheInfo>>
          VGradientColorTableHash;
-    bool generateGradientColorTable(const VGradientStops &stops,
+    bool generateGradientColorTable(const VGradientStops &stops, float alpha,
                                     uint32_t *colorTable, int size);
     inline const std::shared_ptr<const CacheInfo> getBuffer(
         const VGradient &gradient)
     {
         uint64_t                         hash_val = 0;
         std::shared_ptr<const CacheInfo> info;
-
         const VGradientStops &stops = gradient.mStops;
         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();
 
@@ -72,7 +71,7 @@ protected:
         }
         auto cache_entry = std::make_shared<CacheInfo>(gradient.mStops);
         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));
         return cache_entry;
     }
@@ -81,7 +80,7 @@ protected:
     std::mutex              cacheAccess;
 };
 
-bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
+bool VGradientCache::generateGradientColorTable(const VGradientStops &stops, float opacity,
                                                 uint32_t *colorTable, int size)
 {
     int                  dist, idist, pos = 0, i;
@@ -91,10 +90,12 @@ bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
     uint32_t             curColor, nextColor;
     float                delta, t, incr, fpos;
 
+    if (!vCompare(opacity, 1.0f)) alpha = true;
+
     start = stops.data();
     curr = start;
     if (!curr->second.isOpaque()) alpha = true;
-    curColor = curr->second.premulARGB();
+    curColor = curr->second.premulARGB(opacity);
     incr = 1.0 / (float)size;
     fpos = 1.5 * incr;
 
@@ -111,7 +112,7 @@ bool VGradientCache::generateGradientColorTable(const VGradientStops &stops,
         next = (start + i + 1);
         delta = 1 / (next->first - curr->first);
         if (!next->second.isOpaque()) alpha = true;
-        nextColor = next->second.premulARGB();
+        nextColor = next->second.premulARGB(opacity);
         while (fpos < next->first && pos < size) {
             t = (fpos - curr->first) * delta;
             dist = (int)(255 * t);
index d9cd17c..87438cf 100644 (file)
@@ -259,6 +259,15 @@ public:
         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:
     uchar a;
     uchar r;