From a8cdb9b2fca2557325aafbb0840b46fb31b1b487 Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Wed, 9 Jan 2019 17:01:46 +0900 Subject: [PATCH] lottie/vector: image fill support in drawhelper Change-Id: I678b1af37c4939d0006b33ddcb2b40f59d426169 --- src/vector/vdrawhelper.cpp | 77 ++++++++++++++++++++++++++++++++++++++++------ src/vector/vdrawhelper.h | 32 ++++++++++++++++--- 2 files changed, 94 insertions(+), 15 deletions(-) diff --git a/src/vector/vdrawhelper.cpp b/src/vector/vdrawhelper.cpp index 7e57fde..46d2657 100644 --- a/src/vector/vdrawhelper.cpp +++ b/src/vector/vdrawhelper.cpp @@ -55,6 +55,7 @@ #include #include #include +#include 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(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__) diff --git a/src/vector/vdrawhelper.h b/src/vector/vdrawhelper.h index 7dc288d..52852bf 100644 --- a/src/vector/vdrawhelper.h +++ b/src/vector/vdrawhelper.h @@ -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 }; -- 2.7.4