#include <cstring>
#include <mutex>
#include <unordered_map>
+#include <algorithm>
class VGradientCache {
public:
static VGradientCache VGradientCacheInstance;
-void VRasterBuffer::init()
-{
- mBuffer = nullptr;
- mWidth = 0;
- mHeight = 0;
- mCompositionMode = VPainter::CompModeSrcOver;
-}
-
void VRasterBuffer::clear()
{
memset(mBuffer, 0, mHeight * mBytesPerLine);
break;
}
- op.mode = data->mRasterBuffer->mCompositionMode;
+ op.mode = data->mCompositionMode;
if (op.mode == VPainter::CompModeSrcOver && solidSource)
op.mode = VPainter::CompModeSrc;
}
}
+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*/)
{
// && 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) {
mUnclippedBlendFunc = &blendGradientARGB;
break;
}
- default:
+ case VSpanData::Type::Texture: {
+ //@TODO update proper image function.
+ mUnclippedBlendFunc = &blend_untransformed_argb;
break;
}
+ }
}
#if !defined(__SSE2__) && !defined(__ARM_NEON__)
class VRasterBuffer {
public:
- VRasterBuffer() { init(); }
- void init();
VBitmap::Format prepare(VBitmap *image);
void clear();
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};
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);
{
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;
union {
uint32_t mSolid;
VGradientData mGradient;
+ VBitmapData mBitmap;
};
float m11, m12, m13, m21, m22, m23, m33, dx, dy; // inverse xform matrix
};