summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorLuboš Luňák <l.lunak@collabora.com>2019-09-20 14:45:36 +0200
committerLuboš Luňák <l.lunak@collabora.com>2019-11-27 09:55:05 +0100
commit886e5d2701c8d1f08c612eb3f093027fc590c508 (patch)
treee9d8d47e441e78ebedda2bbc45e648f69f2c6b56 /vcl
parent1e9fae677579b59ddbc4cd69e201b95f51b8c742 (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.hxx5
-rw-r--r--vcl/qa/cppunit/BitmapTest.cxx7
-rw-r--r--vcl/skia/salbmp.cxx164
-rw-r--r--vcl/source/outdev/bitmap.cxx2
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())
{