lottie/vector: image fill support in drawhelper 00/197200/1
authorsubhransu mohanty <sub.mohanty@samsung.com>
Wed, 9 Jan 2019 08:01:46 +0000 (17:01 +0900)
committersubhransu mohanty <sub.mohanty@samsung.com>
Thu, 10 Jan 2019 07:34:10 +0000 (16:34 +0900)
Change-Id: I678b1af37c4939d0006b33ddcb2b40f59d426169

src/vector/vdrawhelper.cpp
src/vector/vdrawhelper.h

index 7e57fde..46d2657 100644 (file)
@@ -55,6 +55,7 @@
 #include <cstring>
 #include <mutex>
 #include <unordered_map>
+#include <algorithm>
 
 class VGradientCache {
 public:
@@ -186,14 +187,6 @@ bool VGradientCache::generateGradientColorTable(const VGradientStops &stops, flo
 
 static VGradientCache VGradientCacheInstance;
 
-void VRasterBuffer::init()
-{
-    mBuffer = nullptr;
-    mWidth = 0;
-    mHeight = 0;
-    mCompositionMode = VPainter::CompModeSrcOver;
-}
-
 void VRasterBuffer::clear()
 {
     memset(mBuffer, 0, mHeight * mBytesPerLine);
@@ -529,7 +522,7 @@ static inline Operator getOperator(const VSpanData * data,
         break;
     }
 
-    op.mode = data->mRasterBuffer->mCompositionMode;
+    op.mode = data->mCompositionMode;
     if (op.mode == VPainter::CompModeSrcOver && solidSource)
         op.mode = VPainter::CompModeSrc;
 
@@ -594,6 +587,47 @@ static void blendGradientARGB(int count, const VRle::Span *spans,
     }
 }
 
+static void blend_untransformed_argb(int count, const VRle::Span *spans, void *userData)
+{
+    VSpanData *data = reinterpret_cast<VSpanData *>(userData);
+    if (data->mBitmap.format != VBitmap::Format::ARGB32_Premultiplied
+        && data->mBitmap.format != VBitmap::Format::ARGB32) {
+        //@TODO other formats not yet handled.
+        return;
+    }
+
+    Operator op = getOperator(data, spans, count);
+
+    const int image_width = data->mBitmap.width;
+    const int image_height = data->mBitmap.height;
+
+    int xoff = data->dx;
+    int yoff = data->dy;
+
+    while (count--) {
+        int x = spans->x;
+        int length = spans->len;
+        int sx = xoff + x;
+        int sy = yoff + spans->y;
+        if (sy >= 0 && sy < image_height && sx < image_width) {
+            if (sx < 0) {
+                x -= sx;
+                length += sx;
+                sx = 0;
+            }
+            if (sx + length > image_width)
+                length = image_width - sx;
+            if (length > 0) {
+                const int coverage = (spans->coverage * data->mBitmap.const_alpha) >> 8;
+                const uint *src = (const uint *)data->mBitmap.scanLine(sy) + sx;
+                uint *dest = data->buffer(x, spans->y);
+                op.func(dest, src, length, coverage);
+            }
+        }
+        ++spans;
+    }
+}
+
 void VSpanData::setup(const VBrush &brush, VPainter::CompositionMode /*mode*/,
                       int /*alpha*/)
 {
@@ -660,6 +694,26 @@ void VSpanData::setupMatrix(const VMatrix &matrix)
     //        && fabs(dy) < 1e4;
 }
 
+void VSpanData::initTexture(const VBitmap *bitmap, int alpha, VBitmapData::Type type, const VRect &sourceRect)
+{
+    mType = VSpanData::Type::Texture;
+
+    mBitmap.imageData = bitmap->data();
+    mBitmap.width = bitmap->width();
+    mBitmap.height = bitmap->height();
+    mBitmap.bytesPerLine = bitmap->stride();
+    mBitmap.format = bitmap->format();
+    mBitmap.x1 = sourceRect.x();
+    mBitmap.y1 = sourceRect.y();
+    mBitmap.x2 = std::min(mBitmap.x1 + sourceRect.width(), mBitmap.width);
+    mBitmap.y2 = std::min(mBitmap.y1 + sourceRect.height(), mBitmap.height);
+
+    mBitmap.const_alpha = alpha;
+    mBitmap.type = type;
+
+    updateSpanFunc();
+}
+
 void VSpanData::updateSpanFunc()
 {
     switch (mType) {
@@ -674,9 +728,12 @@ void VSpanData::updateSpanFunc()
         mUnclippedBlendFunc = &blendGradientARGB;
         break;
     }
-    default:
+    case VSpanData::Type::Texture: {
+        //@TODO update proper image function.
+        mUnclippedBlendFunc = &blend_untransformed_argb;
         break;
     }
+    }
 }
 
 #if !defined(__SSE2__) && !defined(__ARM_NEON__)
index 7dc288d..52852bf 100644 (file)
@@ -74,8 +74,6 @@ struct Operator {
 
 class VRasterBuffer {
 public:
-    VRasterBuffer() { init(); }
-    void            init();
     VBitmap::Format prepare(VBitmap *image);
     void            clear();
 
@@ -94,8 +92,6 @@ public:
     int bytesPerPixel() const { return mBytesPerPixel; }
 
     VBitmap::Format           mFormat{VBitmap::Format::ARGB32_Premultiplied};
-    VPainter::CompositionMode mCompositionMode{VPainter::CompositionMode::CompModeSrc};
-
 private:
     int    mWidth{0};
     int    mHeight{0};
@@ -118,12 +114,35 @@ struct VGradientData {
     bool            mColorTableAlpha;
 };
 
+struct VBitmapData
+{
+    const uchar *imageData;
+    const uchar *scanLine(int y) const { return imageData + y*bytesPerLine; }
+
+    int width;
+    int height;
+    // clip rect
+    int x1;
+    int y1;
+    int x2;
+    int y2;
+    uint bytesPerLine;
+    VBitmap::Format format;
+    bool hasAlpha;
+    enum Type {
+        Plain,
+        Tiled
+    };
+    Type type;
+    int const_alpha;
+};
+
 struct VSpanData {
     class Pinnable {
     protected:
         ~Pinnable() = default;
     };
-    enum class Type { None, Solid, LinearGradient, RadialGradient };
+    enum class Type { None, Solid, LinearGradient, RadialGradient, Texture };
 
     void  updateSpanFunc();
     void  init(VRasterBuffer *image);
@@ -141,7 +160,9 @@ struct VSpanData {
     {
         return (uint *)(mRasterBuffer->scanLine(y + mPos.y())) + x + mPos.x();
     }
+    void initTexture(const VBitmap *image, int alpha, VBitmapData::Type type, const VRect &sourceRect);
 
+    VPainter::CompositionMode            mCompositionMode{VPainter::CompositionMode::CompModeSrcOver};
     VRasterBuffer *                      mRasterBuffer;
     ProcessRleSpan                       mBlendFunc;
     ProcessRleSpan                       mUnclippedBlendFunc;
@@ -152,6 +173,7 @@ struct VSpanData {
     union {
         uint32_t      mSolid;
         VGradientData mGradient;
+        VBitmapData   mBitmap;
     };
     float m11, m12, m13, m21, m22, m23, m33, dx, dy;  // inverse xform matrix
 };