diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2019-09-20 14:45:36 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2019-11-27 09:55:05 +0100 |
commit | 886e5d2701c8d1f08c612eb3f093027fc590c508 (patch) | |
tree | e9d8d47e441e78ebedda2bbc45e648f69f2c6b56 /vcl | |
parent | 1e9fae677579b59ddbc4cd69e201b95f51b8c742 (diff) |
basic functional implementation of Skia SalBmp
Not complete but can pass basic tests.
Change-Id: I8e81c44554663a99cd4b262e37f4841ba0687cf1
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/skia/salbmp.hxx | 5 | ||||
-rw-r--r-- | vcl/qa/cppunit/BitmapTest.cxx | 7 | ||||
-rw-r--r-- | vcl/skia/salbmp.cxx | 164 | ||||
-rw-r--r-- | vcl/source/outdev/bitmap.cxx | 2 |
4 files changed, 158 insertions, 20 deletions
diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 04f159b34af2..c8369ce485b4 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -59,6 +59,11 @@ public: private: SkBitmap mBitmap; + BitmapPalette mPalette; + int mBitCount; // bpp + Size mSize; + std::unique_ptr<sal_uInt8[]> mBuffer; // for 1bpp and 4bpp, Skia doesn't support those + int mScanlineSize; // size of one row in mBuffer }; #endif // INCLUDED_VCL_INC_OPENGL_SALBMP_H diff --git a/vcl/qa/cppunit/BitmapTest.cxx b/vcl/qa/cppunit/BitmapTest.cxx index 4136dce65c01..45af13a2b79f 100644 --- a/vcl/qa/cppunit/BitmapTest.cxx +++ b/vcl/qa/cppunit/BitmapTest.cxx @@ -23,6 +23,7 @@ #if HAVE_FEATURE_OPENGL #include <vcl/opengl/OpenGLHelper.hxx> #endif +#include <vcl/skia/SkiaHelper.hxx> #include <vcl/BitmapMonochromeFilter.hxx> #include <bitmapwriteaccess.hxx> @@ -358,8 +359,9 @@ void BitmapTest::testConvert() #else #if HAVE_FEATURE_OPENGL if (!OpenGLHelper::isVCLOpenGLEnabled()) - CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize()); #endif + if (!SkiaHelper::isVCLSkiaEnabled()) + CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(12), pReadAccess->GetScanlineSize()); #endif CPPUNIT_ASSERT(pReadAccess->HasPalette()); const BitmapColor& rColor = pReadAccess->GetPaletteColor(pReadAccess->GetPixelIndex(1, 1)); @@ -382,6 +384,9 @@ void BitmapTest::testConvert() CPPUNIT_ASSERT_EQUAL(sal_uInt32(30), pReadAccess->GetScanlineSize()); else #endif + if (SkiaHelper::isVCLSkiaEnabled()) + CPPUNIT_ASSERT_EQUAL(sal_uInt32(40), pReadAccess->GetScanlineSize()); + else CPPUNIT_ASSERT_EQUAL(sal_uInt32(32), pReadAccess->GetScanlineSize()); #else #if defined(_WIN32) diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index e2e60cf0743b..b57a775be288 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -19,36 +19,105 @@ #include <skia/salbmp.hxx> +#include <o3tl/safeint.hxx> +#include <tools/helpers.hxx> + +#include <salgdi.hxx> + SkiaSalBitmap::SkiaSalBitmap() {} SkiaSalBitmap::~SkiaSalBitmap() {} +static SkColorType getSkColorType(int bitCount, const BitmapPalette& palette) +{ + switch (bitCount) + { + case 8: + return palette.IsGreyPalette() ? kGray_8_SkColorType : kAlpha_8_SkColorType; + case 24: + return kRGB_888x_SkColorType; + case 32: + return kN32_SkColorType; + default: + abort(); + } +} + +static bool isValidBitCount(sal_uInt16 nBitCount) +{ + return (nBitCount == 1) || (nBitCount == 4) || (nBitCount == 8) || (nBitCount == 24) + || (nBitCount == 32); +} + bool SkiaSalBitmap::Create(const Size& rSize, sal_uInt16 nBitCount, const BitmapPalette& rPal) { - (void)rSize; - (void)nBitCount; - (void)rPal; - return false; + Destroy(); + if (!isValidBitCount(nBitCount)) + return false; + if (nBitCount >= 8) + { + // TODO SkSurface doesn't support unpremul alpha + if (!mBitmap.tryAllocPixels( + SkImageInfo::Make(rSize.Width(), rSize.Height(), getSkColorType(nBitCount, rPal), + nBitCount == 32 ? kUnpremul_SkAlphaType : kOpaque_SkAlphaType))) + { + return false; + } + } + else + { + // Skia doesn't support the (ancient) low bpp bit counts, so handle them manually + int bitScanlineWidth; + if (o3tl::checked_multiply<int>(rSize.Width(), nBitCount, bitScanlineWidth)) + { + SAL_WARN("vcl.gdi", "checked multiply failed"); + return false; + } + mScanlineSize = AlignedWidth4Bytes(bitScanlineWidth); + sal_uInt8* buffer = nullptr; + if (mScanlineSize != 0 && rSize.Height() != 0) + buffer = new sal_uInt8[mScanlineSize * rSize.Height()]; + mBuffer.reset(buffer); + } + mPalette = rPal; + mBitCount = nBitCount; + mSize = rSize; + return true; } bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp) { - (void)rSalBmp; - return false; + return Create(rSalBmp, rSalBmp.GetBitCount()); } bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, SalGraphics* pGraphics) { - (void)rSalBmp; - (void)pGraphics; - return false; + return Create(rSalBmp, pGraphics ? pGraphics->GetBitCount() : rSalBmp.GetBitCount()); } bool SkiaSalBitmap::Create(const SalBitmap& rSalBmp, sal_uInt16 nNewBitCount) { - (void)rSalBmp; - (void)nNewBitCount; - return false; + const SkiaSalBitmap& src = static_cast<const SkiaSalBitmap&>(rSalBmp); + if (nNewBitCount == src.GetBitCount()) + { + mBitmap = src.mBitmap; // TODO unshare? + mPalette = src.mPalette; + mBitCount = src.mBitCount; + mSize = src.mSize; + if (src.mBuffer != nullptr) + { + sal_uInt32 dataSize = src.mScanlineSize * src.mSize.Height(); + sal_uInt8* newBuffer = new sal_uInt8[dataSize]; + memcpy(newBuffer, src.mBuffer.get(), dataSize); + mBuffer.reset(newBuffer); + mScanlineSize = src.mScanlineSize; + } + return true; + } + if (!Create(src.mSize, src.mBitCount, src.mPalette)) + return false; + // TODO copy data + return true; } bool SkiaSalBitmap::Create(const css::uno::Reference<css::rendering::XBitmapCanvas>& rBitmapCanvas, @@ -60,22 +129,79 @@ bool SkiaSalBitmap::Create(const css::uno::Reference<css::rendering::XBitmapCanv return false; } -void SkiaSalBitmap::Destroy() {} +void SkiaSalBitmap::Destroy() +{ + mBitmap.reset(); + mBuffer.reset(); +} -Size SkiaSalBitmap::GetSize() const { return Size(); } +Size SkiaSalBitmap::GetSize() const { return mSize; } -sal_uInt16 SkiaSalBitmap::GetBitCount() const { return 0; } +sal_uInt16 SkiaSalBitmap::GetBitCount() const { return mBitCount; } BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) { - (void)nMode; - return nullptr; + (void)nMode; // TODO + if (mBitmap.drawsNothing() && !mBuffer) + return nullptr; + BitmapBuffer* buffer = new BitmapBuffer; + buffer->mnWidth = mSize.Width(); + buffer->mnHeight = mSize.Height(); + buffer->mnBitCount = mBitCount; + buffer->maPalette = mPalette; + if (mBitCount >= 8) + { + buffer->mpBits = static_cast<sal_uInt8*>(mBitmap.getPixels()); + buffer->mnScanlineSize = mBitmap.rowBytes(); + } + else + { + buffer->mpBits = mBuffer.get(); + buffer->mnScanlineSize = mScanlineSize; + } + switch (mBitCount) + { + case 1: +#ifdef OSL_BIGENDIAN + buffer->mnFormat = ScanlineFormat::N1BitMsbPal | ScanlineFormat::TopDown; +#else + buffer->mnFormat = ScanlineFormat::N1BitLsbPal | ScanlineFormat::TopDown; +#endif + break; + case 4: +#ifdef OSL_BIGENDIAN + buffer->mnFormat = ScanlineFormat::N4BitMsnPal | ScanlineFormat::TopDown; +#else + buffer->mnFormat = ScanlineFormat::N4BitLsnPal | ScanlineFormat::TopDown; +#endif + break; + case 8: + buffer->mnFormat = ScanlineFormat::N8BitPal | ScanlineFormat::TopDown; + break; + case 24: + buffer->mnFormat = ScanlineFormat::N24BitTcRgb | ScanlineFormat::TopDown; + break; + case 32: + buffer->mnFormat = mBitmap.colorType() == kRGBA_8888_SkColorType + ? ScanlineFormat::N32BitTcArgb + : ScanlineFormat::N32BitTcBgra; + buffer->mnFormat |= ScanlineFormat::TopDown; + break; + default: + abort(); + } + return buffer; } void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) { - (void)pBuffer; - (void)nMode; + mPalette = pBuffer->maPalette; + (void)nMode; // TODO? + // Are there any more ground movements underneath us ? + assert(pBuffer->mnWidth == mSize.Width()); + assert(pBuffer->mnHeight == mSize.Height()); + assert(pBuffer->mnBitCount == mBitCount); + delete pBuffer; } bool SkiaSalBitmap::GetSystemData(BitmapSystemData& rData) diff --git a/vcl/source/outdev/bitmap.cxx b/vcl/source/outdev/bitmap.cxx index de677fcdce66..0bce168579cc 100644 --- a/vcl/source/outdev/bitmap.cxx +++ b/vcl/source/outdev/bitmap.cxx @@ -690,7 +690,9 @@ void OutputDevice::DrawDeviceAlphaBitmap( const Bitmap& rBmp, const AlphaMask& r #if HAVE_FEATURE_OPENGL assert(!OpenGLHelper::isVCLOpenGLEnabled()); #endif +#if HAVE_FEATURE_SKIA assert(!SkiaHelper::isVCLSkiaEnabled()); +#endif tools::Rectangle aBmpRect(Point(), rBmp.GetSizePixel()); if (!aBmpRect.Intersection(tools::Rectangle(rSrcPtPixel, rSrcSizePixel)).IsEmpty()) { |