include/vcl/bitmap.hxx | 2 - vcl/headless/svpbmp.cxx | 13 ++------- vcl/inc/headless/svpbmp.hxx | 2 - vcl/inc/qt5/QtBitmap.hxx | 2 - vcl/inc/quartz/salbmp.h | 2 - vcl/inc/salbmp.hxx | 3 +- vcl/inc/skia/salbmp.hxx | 2 - vcl/inc/win/salbmp.h | 2 - vcl/qt5/QtBitmap.cxx | 36 +++++++++++++++++--------- vcl/quartz/salbmp.cxx | 32 ++++++++++------------- vcl/skia/salbmp.cxx | 59 +++++++++++++++++++++---------------------- vcl/source/bitmap/bitmap.cxx | 16 +++++++++++ vcl/source/bitmap/salbmp.cxx | 22 ++++++++++++++++ vcl/win/gdi/salbmp.cxx | 24 ++++++++++++++--- 14 files changed, 137 insertions(+), 80 deletions(-)
New commits: commit 18b488deededee4b62b3c041c8db84452ad72b55 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Tue Aug 26 21:26:33 2025 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Wed Aug 27 07:39:21 2025 +0200 Make Bitmap::HasAlpha() more reliable checking for 32-bit format is not sufficient when there are 32-bit formats which do not have actual alpha data. Change the SalBitmap backend interface to return ScanlineFormat rather than BitCount, to give a more reliable picture. Change-Id: I6dde931a05415a9fbe0e8e696173b58e744b0e0c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/190242 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/include/vcl/bitmap.hxx b/include/vcl/bitmap.hxx index 2267c08d4e5a..8788a718f001 100644 --- a/include/vcl/bitmap.hxx +++ b/include/vcl/bitmap.hxx @@ -142,7 +142,7 @@ public: bool HasGreyPalette8Bit() const; bool HasGreyPaletteAny() const; // does this bitmap have alpha information? - inline bool HasAlpha() const { return getPixelFormat() == vcl::PixelFormat::N32_BPP; } + bool HasAlpha() const; /** return the alpha data, copied into an AlphaMask. Will assert if this Bitmap has no alpha. */ AlphaMask CreateAlphaMask() const; diff --git a/vcl/headless/svpbmp.cxx b/vcl/headless/svpbmp.cxx index b1ef601e80e7..314269c1a01e 100644 --- a/vcl/headless/svpbmp.cxx +++ b/vcl/headless/svpbmp.cxx @@ -223,16 +223,11 @@ Size SvpSalBitmap::GetSize() const return aSize; } -sal_uInt16 SvpSalBitmap::GetBitCount() const +ScanlineFormat SvpSalBitmap::GetScanlineFormat() const { - sal_uInt16 nBitCount; - - if (moDIB.has_value()) - nBitCount = moDIB->mnBitCount; - else - nBitCount = 0; - - return nBitCount; + if (!moDIB.has_value()) + return ScanlineFormat::NONE; + return moDIB->meFormat; } BitmapBuffer* SvpSalBitmap::AcquireBuffer(BitmapAccessMode) diff --git a/vcl/inc/headless/svpbmp.hxx b/vcl/inc/headless/svpbmp.hxx index 53756e25c58e..b650626bf0e1 100644 --- a/vcl/inc/headless/svpbmp.hxx +++ b/vcl/inc/headless/svpbmp.hxx @@ -55,7 +55,7 @@ public: } SAL_DLLPRIVATE virtual void Destroy() final override; SAL_DLLPRIVATE virtual Size GetSize() const override; - SAL_DLLPRIVATE virtual sal_uInt16 GetBitCount() const override; + SAL_DLLPRIVATE virtual ScanlineFormat GetScanlineFormat() const override; SAL_DLLPRIVATE virtual BitmapBuffer* AcquireBuffer( BitmapAccessMode nMode ) override; SAL_DLLPRIVATE virtual void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) override; diff --git a/vcl/inc/qt5/QtBitmap.hxx b/vcl/inc/qt5/QtBitmap.hxx index 1005bfe5f429..6e6c82ba8fc9 100644 --- a/vcl/inc/qt5/QtBitmap.hxx +++ b/vcl/inc/qt5/QtBitmap.hxx @@ -45,7 +45,7 @@ public: Size& rSize) override; virtual void Destroy() final override; virtual Size GetSize() const override; - virtual sal_uInt16 GetBitCount() const override; + virtual ScanlineFormat GetScanlineFormat() const override; virtual BitmapBuffer* AcquireBuffer(BitmapAccessMode nMode) override; virtual void ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) override; diff --git a/vcl/inc/quartz/salbmp.h b/vcl/inc/quartz/salbmp.h index c0b30184c7c0..7ada1f6829f1 100644 --- a/vcl/inc/quartz/salbmp.h +++ b/vcl/inc/quartz/salbmp.h @@ -66,7 +66,7 @@ public: void Destroy() override; Size GetSize() const override; - sal_uInt16 GetBitCount() const override; + ScanlineFormat GetScanlineFormat() const override; BitmapBuffer *AcquireBuffer( BitmapAccessMode nMode ) override; void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) override; diff --git a/vcl/inc/salbmp.hxx b/vcl/inc/salbmp.hxx index 2b1d8e479bf4..441f630da167 100644 --- a/vcl/inc/salbmp.hxx +++ b/vcl/inc/salbmp.hxx @@ -71,7 +71,8 @@ public: Size& rSize ) = 0; virtual void Destroy() = 0; virtual Size GetSize() const = 0; - virtual sal_uInt16 GetBitCount() const = 0; + sal_uInt16 GetBitCount() const; + virtual ScanlineFormat GetScanlineFormat() const = 0; virtual BitmapBuffer* AcquireBuffer( BitmapAccessMode nMode ) = 0; virtual void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) = 0; diff --git a/vcl/inc/skia/salbmp.hxx b/vcl/inc/skia/salbmp.hxx index f9459dbff2c9..0212705c0e3e 100644 --- a/vcl/inc/skia/salbmp.hxx +++ b/vcl/inc/skia/salbmp.hxx @@ -47,7 +47,7 @@ public: virtual void Destroy() final override; virtual Size GetSize() const override; - virtual sal_uInt16 GetBitCount() const override; + virtual ScanlineFormat GetScanlineFormat() const override; virtual BitmapBuffer* AcquireBuffer(BitmapAccessMode nMode) override; virtual void ReleaseBuffer(BitmapBuffer* pBuffer, BitmapAccessMode nMode) override; diff --git a/vcl/inc/win/salbmp.h b/vcl/inc/win/salbmp.h index b7a5a1947a2b..4ad38ecbec15 100644 --- a/vcl/inc/win/salbmp.h +++ b/vcl/inc/win/salbmp.h @@ -81,7 +81,7 @@ public: virtual void Destroy() override; virtual Size GetSize() const override { return maSize; } - virtual sal_uInt16 GetBitCount() const override { return mnBitCount; } + virtual ScanlineFormat GetScanlineFormat() const override; virtual BitmapBuffer* AcquireBuffer( BitmapAccessMode nMode ) override; virtual void ReleaseBuffer( BitmapBuffer* pBuffer, BitmapAccessMode nMode ) override; diff --git a/vcl/qt5/QtBitmap.cxx b/vcl/qt5/QtBitmap.cxx index 53277649d774..643208b23c5d 100644 --- a/vcl/qt5/QtBitmap.cxx +++ b/vcl/qt5/QtBitmap.cxx @@ -96,11 +96,30 @@ Size QtBitmap::GetSize() const return Size(); } -sal_uInt16 QtBitmap::GetBitCount() const +ScanlineFormat QtBitmap::GetScanlineFormat() const { - if (m_pImage) - return getFormatBits(m_pImage->format()); - return 0; + if (!m_pImage) + return ScanlineFormat::NONE; + auto nBits = getFormatBits(m_pImage->format()); + switch (nBits) + { + case 1: + return ScanlineFormat::N1BitMsbPal; + case 8: + return ScanlineFormat::N8BitPal; + case 24: + return ScanlineFormat::N24BitTcRgb; + case 32: + { +#ifdef OSL_BIGENDIAN + return ScanlineFormat::N32BitTcArgb; +#else + return ScanlineFormat::N32BitTcBgra; +#endif + } + default: + abort(); + } } BitmapBuffer* QtBitmap::AcquireBuffer(BitmapAccessMode /*nMode*/) @@ -118,28 +137,21 @@ BitmapBuffer* QtBitmap::AcquireBuffer(BitmapAccessMode /*nMode*/) pBuffer->mpBits = m_pImage->bits(); pBuffer->mnScanlineSize = m_pImage->bytesPerLine(); pBuffer->meDirection = ScanlineDirection::TopDown; + pBuffer->meFormat = GetScanlineFormat(); switch (pBuffer->mnBitCount) { case 1: - pBuffer->meFormat = ScanlineFormat::N1BitMsbPal; pBuffer->maPalette = m_aPalette; break; case 8: - pBuffer->meFormat = ScanlineFormat::N8BitPal; pBuffer->maPalette = m_aPalette; break; case 24: - pBuffer->meFormat = ScanlineFormat::N24BitTcRgb; pBuffer->maPalette = aEmptyPalette; break; case 32: { -#ifdef OSL_BIGENDIAN - pBuffer->meFormat = ScanlineFormat::N32BitTcArgb; -#else - pBuffer->meFormat = ScanlineFormat::N32BitTcBgra; -#endif pBuffer->maPalette = aEmptyPalette; break; } diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx index 725aa5574996..e65de0090e4d 100644 --- a/vcl/quartz/salbmp.cxx +++ b/vcl/quartz/salbmp.cxx @@ -320,9 +320,20 @@ Size QuartzSalBitmap::GetSize() const return Size( mnWidth, mnHeight ); } -sal_uInt16 QuartzSalBitmap::GetBitCount() const +ScanlineFormat QuartzSalBitmap::GetScanlineFormat() const { - return mnBits; + switch( mnBits ) + { + case 1: + return ScanlineFormat::N1BitMsbPal; + case 8: + return ScanlineFormat::N8BitPal; + case 24: + return ScanlineFormat::N24BitTcBgr; + case 32: + return ScanlineFormat::N32BitTcArgb; + default: abort(); + } } namespace { @@ -427,22 +438,7 @@ BitmapBuffer* QuartzSalBitmap::AcquireBuffer( BitmapAccessMode /*nMode*/ ) pBuffer->mnScanlineSize = mnBytesPerRow; pBuffer->mpBits = m_pUserBuffer.get(); pBuffer->mnBitCount = mnBits; - switch( mnBits ) - { - case 1: - pBuffer->meFormat = ScanlineFormat::N1BitMsbPal; - break; - case 8: - pBuffer->meFormat = ScanlineFormat::N8BitPal; - break; - case 24: - pBuffer->meFormat = ScanlineFormat::N24BitTcBgr; - break; - case 32: - pBuffer->meFormat = ScanlineFormat::N32BitTcArgb; - break; - default: assert(false); - } + pBuffer->meFormat = GetScanlineFormat(); // some BitmapBuffer users depend on a complete palette if( (mnBits <= 8) && !maPalette ) diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx index ddea043133a4..16cfb2b1c994 100644 --- a/vcl/skia/salbmp.cxx +++ b/vcl/skia/salbmp.cxx @@ -201,7 +201,34 @@ void SkiaSalBitmap::Destroy() Size SkiaSalBitmap::GetSize() const { return mSize; } -sal_uInt16 SkiaSalBitmap::GetBitCount() const { return mBitCount; } +ScanlineFormat SkiaSalBitmap::GetScanlineFormat() const +{ + switch (mBitCount) + { + case 1: + return ScanlineFormat::N1BitMsbPal; + case 8: + return ScanlineFormat::N8BitPal; + case 24: + // Make the RGB/BGR format match the default Skia 32bpp format, to allow + // easy conversion later. + return kN32_SkColorTypeIsBGRA ? ScanlineFormat::N24BitTcBgr + : ScanlineFormat::N24BitTcRgb; + case 32: + if (m_bWithoutAlpha) + { + return kN32_SkColorTypeIsBGRA ? ScanlineFormat::N32BitTcBgrx + : ScanlineFormat::N32BitTcRgbx; + } + else + { + return kN32_SkColorTypeIsBGRA ? ScanlineFormat::N32BitTcBgra + : ScanlineFormat::N32BitTcRgba; + } + default: + abort(); + } +} BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) { @@ -282,35 +309,7 @@ BitmapBuffer* SkiaSalBitmap::AcquireBuffer(BitmapAccessMode nMode) mPixelsSize = savedPixelsSize; ComputeScanlineSize(); } - switch (mBitCount) - { - case 1: - buffer->meFormat = ScanlineFormat::N1BitMsbPal; - break; - case 8: - buffer->meFormat = ScanlineFormat::N8BitPal; - break; - case 24: - // Make the RGB/BGR format match the default Skia 32bpp format, to allow - // easy conversion later. - buffer->meFormat = kN32_SkColorTypeIsBGRA ? ScanlineFormat::N24BitTcBgr - : ScanlineFormat::N24BitTcRgb; - break; - case 32: - if (m_bWithoutAlpha) - { - buffer->meFormat = kN32_SkColorTypeIsBGRA ? ScanlineFormat::N32BitTcBgrx - : ScanlineFormat::N32BitTcRgbx; - } - else - { - buffer->meFormat = kN32_SkColorTypeIsBGRA ? ScanlineFormat::N32BitTcBgra - : ScanlineFormat::N32BitTcRgba; - } - break; - default: - abort(); - } + buffer->meFormat = GetScanlineFormat(); buffer->meDirection = ScanlineDirection::TopDown; // Refcount all read/write accesses, to catch problems with existing accesses while // a bitmap changes, and also to detect when we can free mBuffer if wanted. diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx index e41c571ce176..e5d8f81a8102 100644 --- a/vcl/source/bitmap/bitmap.cxx +++ b/vcl/source/bitmap/bitmap.cxx @@ -353,6 +353,22 @@ vcl::PixelFormat Bitmap::getPixelFormat() const return vcl::PixelFormat::INVALID; } +bool Bitmap::HasAlpha() const +{ + if (!mxSalBmp) + return false; + switch(mxSalBmp->GetScanlineFormat()) + { + case ScanlineFormat::N32BitTcAbgr: + case ScanlineFormat::N32BitTcArgb: + case ScanlineFormat::N32BitTcBgra: + case ScanlineFormat::N32BitTcRgba: + return true; + default: + return false; + } +} + bool Bitmap::HasGreyPaletteAny() const { bool bRet = false; diff --git a/vcl/source/bitmap/salbmp.cxx b/vcl/source/bitmap/salbmp.cxx index 6148e2ee3a48..fec5751e3e1f 100644 --- a/vcl/source/bitmap/salbmp.cxx +++ b/vcl/source/bitmap/salbmp.cxx @@ -85,6 +85,28 @@ void SalBitmap::updateChecksum() const } } +sal_uInt16 SalBitmap::GetBitCount() const +{ + switch (GetScanlineFormat()) + { + case ScanlineFormat::NONE: return 0; + case ScanlineFormat::N1BitMsbPal: return 1; + case ScanlineFormat::N8BitPal: return 8; + case ScanlineFormat::N24BitTcBgr: return 24; + case ScanlineFormat::N24BitTcRgb: return 24; + case ScanlineFormat::N32BitTcAbgr: + case ScanlineFormat::N32BitTcXbgr: + case ScanlineFormat::N32BitTcArgb: + case ScanlineFormat::N32BitTcXrgb: + case ScanlineFormat::N32BitTcBgra: + case ScanlineFormat::N32BitTcBgrx: + case ScanlineFormat::N32BitTcRgba: + case ScanlineFormat::N32BitTcRgbx: + return 32; + default: abort(); + } +} + namespace { diff --git a/vcl/win/gdi/salbmp.cxx b/vcl/win/gdi/salbmp.cxx index 3475377351d1..b3d7ea40fa08 100644 --- a/vcl/win/gdi/salbmp.cxx +++ b/vcl/win/gdi/salbmp.cxx @@ -730,6 +730,25 @@ void* WinSalBitmap::ImplCopyDIB( void* pDIB, sal_Int32 nSize ) return pCopy; } +ScanlineFormat WinSalBitmap::GetScanlineFormat() const +{ + if (!mpDIB) + return ScanlineFormat::NONE; + + PBITMAPINFO pBI = static_cast<PBITMAPINFO>(mpDIB); + if (!pBI) + return ScanlineFormat::NONE; + + PBITMAPINFOHEADER pBIH = &pBI->bmiHeader; + if( pBIH->biPlanes != 1 ) + return ScanlineFormat::NONE; + + return pBIH->biBitCount == 8 ? ScanlineFormat::N8BitPal : + pBIH->biBitCount == 24 ? ScanlineFormat::N24BitTcBgr : + pBIH->biBitCount == 32 ? ScanlineFormat::N32BitTcBgra : + ScanlineFormat::NONE; +} + BitmapBuffer* WinSalBitmap::AcquireBuffer( BitmapAccessMode /*nMode*/ ) { if (!mpDIB) @@ -746,10 +765,7 @@ BitmapBuffer* WinSalBitmap::AcquireBuffer( BitmapAccessMode /*nMode*/ ) { pBuffer.reset(new BitmapBuffer); - pBuffer->meFormat = pBIH->biBitCount == 8 ? ScanlineFormat::N8BitPal : - pBIH->biBitCount == 24 ? ScanlineFormat::N24BitTcBgr : - pBIH->biBitCount == 32 ? ScanlineFormat::N32BitTcBgra : - ScanlineFormat::NONE; + pBuffer->meFormat = GetScanlineFormat(); assert (pBuffer->meFormat != ScanlineFormat::NONE); if (pBuffer->meFormat != ScanlineFormat::NONE)