diff options
author | Luboš Luňák <l.lunak@collabora.com> | 2019-09-23 18:53:09 +0200 |
---|---|---|
committer | Luboš Luňák <l.lunak@collabora.com> | 2019-11-27 09:55:06 +0100 |
commit | 06986d2eb8154230f2980567a80344c12a5e87e8 (patch) | |
tree | 7980d3d9f5519c722f4491d8016d0042b5cb4422 /vcl | |
parent | 17e61ec9620bdb52232428d8a94d0731d2c4a4fa (diff) |
better support for <8 bpp in SkiaSalBitmap
Change-Id: Ife79abfb9c36925405fd0b7da40f5274c0339117
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/salbmp.hxx | 2 | ||||
-rw-r--r-- | vcl/inc/skia/salbmp.hxx | 12 | ||||
-rw-r--r-- | vcl/skia/gdiimpl.cxx | 8 | ||||
-rw-r--r-- | vcl/skia/salbmp.cxx | 29 | ||||
-rw-r--r-- | vcl/source/bitmap/salbmp.cxx | 43 |
5 files changed, 85 insertions, 9 deletions
diff --git a/vcl/inc/salbmp.hxx b/vcl/inc/salbmp.hxx index b952c8ce4f61..ecb1a1b7d7bf 100644 --- a/vcl/inc/salbmp.hxx +++ b/vcl/inc/salbmp.hxx @@ -105,6 +105,8 @@ protected: // helper function to convert data in 1,2,4 bpp formats to a 24bpp format static std::unique_ptr< sal_uInt8[] > convertDataTo24Bpp( const sal_uInt8* src, int width, int height, int bitCount, int bytesPerRow, const BitmapPalette& palette, bool toBgr ); + static std::unique_ptr< sal_uInt8[] > convertDataTo32Bpp( const sal_uInt8* src, + int width, int height, int bitCount, int bytesPerRow, const BitmapPalette& palette, bool toBgra ); }; #endif diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index 005e83be76fc..63a54a8555be 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -59,18 +59,26 @@ public: sal_uInt8 nTol) override; virtual bool ConvertToGreyscale() override; + // Accesses the internal SkBitmap. If the bit count is one that Skia does + // not support natively, data from the internal buffer is converted + // to a 32bpp SkBitmap. + const SkBitmap& GetSkBitmap() const; + #ifdef DBG_UTIL void dump(const char* file) const; #endif private: + void ResetCachedBitmap(); + SkBitmap mBitmap; BitmapPalette mPalette; int mBitCount; // bpp Size mSize; - std::unique_ptr<sal_uInt8[]> mBuffer; // for 1bpp and 4bpp, Skia doesn't support those + // Skia does not natively support 1bpp and 4bpp, so such bitmaps are stored + // in a buffer (and converted to 32bpp SkBitmap on-demand using GetSkBitmap()). + std::unique_ptr<sal_uInt8[]> mBuffer; int mScanlineSize; // size of one row in mBuffer - friend class SkiaSalGraphicsImpl; // TODO }; #endif // INCLUDED_VCL_INC_OPENGL_SALBMP_H diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx index b397abd6af66..a80bf73c0cbe 100644 --- a/vcl/skia/gdiimpl.cxx +++ b/vcl/skia/gdiimpl.cxx @@ -228,7 +228,7 @@ void SkiaSalGraphicsImpl::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& return; assert(dynamic_cast<const SkiaSalBitmap*>(&rSalBitmap)); mSurface->getCanvas()->drawBitmapRect( - static_cast<const SkiaSalBitmap&>(rSalBitmap).mBitmap, + static_cast<const SkiaSalBitmap&>(rSalBitmap).GetSkBitmap(), SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight), SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight), @@ -314,11 +314,9 @@ bool SkiaSalGraphicsImpl::drawAlphaBitmap(const SalTwoRect& rPosAry, const SalBi SkCanvas canvas(tmpBitmap); SkPaint paint; paint.setBlendMode(SkBlendMode::kDst); - canvas.drawBitmap(static_cast<const SkiaSalBitmap&>(rSourceBitmap).mBitmap, 0, 0, - &paint); // TODO bpp < 8? + canvas.drawBitmap(static_cast<const SkiaSalBitmap&>(rSourceBitmap).GetSkBitmap(), 0, 0, &paint); paint.setBlendMode(SkBlendMode::kSrcIn); - canvas.drawBitmap(static_cast<const SkiaSalBitmap&>(rAlphaBitmap).mBitmap, 0, 0, - &paint); // TODO bpp < 8? + canvas.drawBitmap(static_cast<const SkiaSalBitmap&>(rAlphaBitmap).GetSkBitmap(), 0, 0, &paint); mSurface->getCanvas()->drawBitmapRect( tmpBitmap, SkRect::MakeXYWH(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight), diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index ff0a9ed1897b..88677b6132ad 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -215,12 +215,13 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) void SkiaSalBitmap::ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode 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; + if (nMode == BitmapAccessMode::Write) // TODO something more? + ResetCachedBitmap(); } bool SkiaSalBitmap::GetSystemData(BitmapSystemData& rData) @@ -249,10 +250,34 @@ bool SkiaSalBitmap::Replace(const Color& rSearchColor, const Color& rReplaceColo bool SkiaSalBitmap::ConvertToGreyscale() { return false; } +const SkBitmap& SkiaSalBitmap::GetSkBitmap() const +{ + if (mBuffer && mBitmap.drawsNothing()) + { + assert(mBitCount == 1 || mBitCount == 2 || mBitCount == 4); + std::unique_ptr<sal_uInt8[]> data = convertDataTo32Bpp( + mBuffer.get(), mSize.Width(), mSize.Height(), mBitCount, mScanlineSize, mPalette, + kN32_SkColorType == kBGRA_8888_SkColorType); // TODO + if (!const_cast<SkBitmap&>(mBitmap).installPixels( + SkImageInfo::MakeS32(mSize.Width(), mSize.Height(), kOpaque_SkAlphaType), + data.release(), mSize.Width() * 4, + [](void* addr, void*) { delete[] static_cast<sal_uInt8*>(addr); }, nullptr)) + abort(); + } + return mBitmap; +} + +// Reset the cached bitmap allocatd in GetSkBitmap(). +void SkiaSalBitmap::ResetCachedBitmap() +{ + if (mBuffer) + mBitmap.reset(); +} + #ifdef DBG_UTIL void SkiaSalBitmap::dump(const char* file) const { - sk_sp<SkImage> image = SkImage::MakeFromBitmap(mBitmap); + sk_sp<SkImage> image = SkImage::MakeFromBitmap(GetSkBitmap()); sk_sp<SkData> data = image->encodeToData(); std::ofstream ostream(file, std::ios::binary); ostream.write(static_cast<const char*>(data->data()), data->size()); diff --git a/vcl/source/bitmap/salbmp.cxx b/vcl/source/bitmap/salbmp.cxx index 0cf6fd3ab93a..c7183e117598 100644 --- a/vcl/source/bitmap/salbmp.cxx +++ b/vcl/source/bitmap/salbmp.cxx @@ -184,4 +184,47 @@ std::unique_ptr< sal_uInt8[] > SalBitmap::convertDataTo24Bpp( const sal_uInt8* s return data; } +std::unique_ptr< sal_uInt8[] > SalBitmap::convertDataTo32Bpp( const sal_uInt8* src, + int width, int height, int bitCount, int bytesPerRow, const BitmapPalette& palette, bool toBgra ) +{ + std::unique_ptr< sal_uInt8[] > data( new sal_uInt8[width * height * 4] ); + std::unique_ptr<ImplPixelFormat> pSrcFormat(ImplPixelFormat::GetFormat(bitCount, palette)); + + const sal_uInt8* pSrcData = src; + sal_uInt8* pDstData = data.get(); + + sal_uInt32 nY = height; + while( nY-- ) + { + pSrcFormat->StartLine( pSrcData ); + + sal_uInt32 nX = width; + if (toBgra) + { + while( nX-- ) + { + const BitmapColor& c = pSrcFormat->ReadPixel(); + *pDstData++ = c.GetBlue(); + *pDstData++ = c.GetGreen(); + *pDstData++ = c.GetRed(); + *pDstData++ = 0xff; + } + } + else // RGBA + { + while( nX-- ) + { + const BitmapColor& c = pSrcFormat->ReadPixel(); + *pDstData++ = c.GetRed(); + *pDstData++ = c.GetGreen(); + *pDstData++ = c.GetBlue(); + *pDstData++ = 0xff; + } + } + + pSrcData += bytesPerRow; + } + return data; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |