From f5ddeec76de3a36eb58301de6bc530ffe67dc9c7 Mon Sep 17 00:00:00 2001 From: subhransu mohanty Date: Tue, 15 Jan 2019 15:54:12 +0900 Subject: [PATCH] lottie/vector: Added transform image rendering support in the render backend. Change-Id: I84ae9229446b1f46a91b28544641c62dee96a23f --- src/vector/vdrawhelper.cpp | 139 ++++++++++++++++++++++++++++++++++--- src/vector/vdrawhelper.h | 2 + 2 files changed, 133 insertions(+), 8 deletions(-) diff --git a/src/vector/vdrawhelper.cpp b/src/vector/vdrawhelper.cpp index 46d2657..3a25483 100644 --- a/src/vector/vdrawhelper.cpp +++ b/src/vector/vdrawhelper.cpp @@ -587,6 +587,111 @@ static void blendGradientARGB(int count, const VRle::Span *spans, } } +template +constexpr const T& clamp( const T& v, const T& lo, const T& hi) +{ + return v < lo ? lo : hi < v ? hi : v; +} + +static const int buffer_size = 1024; +static const int fixed_scale = 1 << 16; +static void blend_transformed_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); + uint buffer[buffer_size]; + + const int image_x1 = data->mBitmap.x1; + const int image_y1 = data->mBitmap.y1; + const int image_x2 = data->mBitmap.x2 - 1; + const int image_y2 = data->mBitmap.y2 - 1; + + if (data->fast_matrix) { + // The increment pr x in the scanline + int fdx = (int)(data->m11 * fixed_scale); + int fdy = (int)(data->m12 * fixed_scale); + + while (count--) { + uint *target = data->buffer(spans->x, spans->y); + + const float cx = spans->x + float(0.5); + const float cy = spans->y + float(0.5); + + int x = int((data->m21 * cy + + data->m11 * cx + data->dx) * fixed_scale); + int y = int((data->m22 * cy + + data->m12 * cx + data->dy) * fixed_scale); + + int length = spans->len; + const int coverage = (spans->coverage * data->mBitmap.const_alpha) >> 8; + while (length) { + int l = std::min(length, buffer_size); + const uint *end = buffer + l; + uint *b = buffer; + while (b < end) { + int px = clamp(x >> 16, image_x1, image_x2); + int py = clamp(y >> 16, image_y1, image_y2); + *b = reinterpret_cast(data->mBitmap.scanLine(py))[px]; + + x += fdx; + y += fdy; + ++b; + } + op.func(target, buffer, l, coverage); + target += l; + length -= l; + } + ++spans; + } + } else { + const float fdx = data->m11; + const float fdy = data->m12; + const float fdw = data->m13; + while (count--) { + uint *target = data->buffer(spans->x, spans->y); + + const float cx = spans->x + float(0.5); + const float cy = spans->y + float(0.5); + + float x = data->m21 * cy + data->m11 * cx + data->dx; + float y = data->m22 * cy + data->m12 * cx + data->dy; + float w = data->m23 * cy + data->m13 * cx + data->m33; + + int length = spans->len; + const int coverage = (spans->coverage * data->mBitmap.const_alpha) >> 8; + while (length) { + int l = std::min(length, buffer_size); + const uint *end = buffer + l; + uint *b = buffer; + while (b < end) { + const float iw = w == 0 ? 1 : 1 / w; + const float tx = x * iw; + const float ty = y * iw; + const int px = clamp(int(tx) - (tx < 0), image_x1, image_x2); + const int py = clamp(int(ty) - (ty < 0), image_y1, image_y2); + + *b = reinterpret_cast(data->mBitmap.scanLine(py))[px]; + x += fdx; + y += fdy; + w += fdw; + + ++b; + } + op.func(target, buffer, l, coverage); + target += l; + length -= l; + } + ++spans; + } + } +} + static void blend_untransformed_argb(int count, const VRle::Span *spans, void *userData) { VSpanData *data = reinterpret_cast(userData); @@ -631,6 +736,8 @@ static void blend_untransformed_argb(int count, const VRle::Span *spans, void *u void VSpanData::setup(const VBrush &brush, VPainter::CompositionMode /*mode*/, int /*alpha*/) { + transformType = VMatrix::MatrixType::None; + switch (brush.type()) { case VBrush::Type::NoBrush: mType = VSpanData::Type::None; @@ -667,6 +774,13 @@ void VSpanData::setup(const VBrush &brush, VPainter::CompositionMode /*mode*/, setupMatrix(brush.mGradient->mMatrix); break; } + case VBrush::Type::Texture: { + mType = VSpanData::Type::Texture; + initTexture(&brush.mTexture, 255, VBitmapData::Plain, + VRect(0, 0, brush.mTexture.width(), brush.mTexture.height())); + setupMatrix(brush.mMatrix); + break; + } default: break; } @@ -685,13 +799,18 @@ void VSpanData::setupMatrix(const VMatrix &matrix) m33 = inv.m33; dx = inv.mtx; dy = inv.mty; - - // const bool affine = inv.isAffine(); - // fast_matrix = affine - // && m11 * m11 + m21 * m21 < 1e4 - // && m12 * m12 + m22 * m22 < 1e4 - // && fabs(dx) < 1e4 - // && fabs(dy) < 1e4; + transformType = inv.type(); + + const bool affine = inv.isAffine(); + const float f1 = m11 * m11 + m21 * m21; + const float f2 = m12 * m12 + m22 * m22; + fast_matrix = affine + && f1 < 1e4 + && f2 < 1e4 + && f1 > (1.0 / 65536) + && f2 > (1.0 / 65536) + && fabs(dx) < 1e4 + && fabs(dy) < 1e4; } void VSpanData::initTexture(const VBitmap *bitmap, int alpha, VBitmapData::Type type, const VRect &sourceRect) @@ -730,7 +849,11 @@ void VSpanData::updateSpanFunc() } case VSpanData::Type::Texture: { //@TODO update proper image function. - mUnclippedBlendFunc = &blend_untransformed_argb; + if (transformType <= VMatrix::MatrixType::Translate){ + mUnclippedBlendFunc = &blend_untransformed_argb; + } else { + mUnclippedBlendFunc = &blend_transformed_argb; + } break; } } diff --git a/src/vector/vdrawhelper.h b/src/vector/vdrawhelper.h index 52852bf..a02f947 100644 --- a/src/vector/vdrawhelper.h +++ b/src/vector/vdrawhelper.h @@ -176,6 +176,8 @@ struct VSpanData { VBitmapData mBitmap; }; float m11, m12, m13, m21, m22, m23, m33, dx, dy; // inverse xform matrix + bool fast_matrix{true}; + VMatrix::MatrixType transformType{VMatrix::MatrixType::None}; }; void vInitDrawhelperFunctions(); -- 2.34.1