vcl/source/bitmap/bitmap.cxx | 44 ++++++++++++++++++++++++++++++++++++++----- 1 file changed, 39 insertions(+), 5 deletions(-)
New commits: commit 20854a6715154836e05b98d2e365f994d19ed676 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Fri Aug 8 15:48:49 2025 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Sat Aug 9 11:07:45 2025 +0200 tdf#167867 Start center: transparency is missing in logo (GEN) regression from commit 2939f4b52d96ef0bd76896dc857f43d4de402d25 Author: Noel Grandin <noel.gran...@collabora.co.uk> Date: Tue Aug 5 08:26:05 2025 +0200 BitmapEx->Bitmap in CanvasBitmap which flushed out the fact that the cairo/gen backend is being very weird when drawing images with alpha, which is what we are doing in Bitmap::Bitmap(const BitmapEx&) Hit it with a large and ugly hammer for now, long run we won't need this conversion. Change-Id: Ia7a09402caf2c8d19833fda828a6b3050cb90604 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189197 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins diff --git a/vcl/source/bitmap/bitmap.cxx b/vcl/source/bitmap/bitmap.cxx index 72a84373d14f..4c261c862857 100644 --- a/vcl/source/bitmap/bitmap.cxx +++ b/vcl/source/bitmap/bitmap.cxx @@ -143,11 +143,45 @@ Bitmap::Bitmap(const BitmapEx& rBitmapEx) mxSalBmp = rBitmapEx.GetBitmap().mxSalBmp; else { - ScopedVclPtrInstance<VirtualDevice> xDev(DeviceFormat::WITH_ALPHA); - Size aPixelSize = rBitmapEx.GetSizePixel(); - xDev->SetOutputSizePixel(aPixelSize, /*bErase*/true, /*bAlphaMaskTransparent*/true); - xDev->DrawBitmapEx(Point(0, 0), aPixelSize, rBitmapEx); - mxSalBmp = xDev->GetBitmap(Point(0,0), aPixelSize).mxSalBmp; + Size aSize = rBitmapEx.GetSizePixel(); + static const BitmapPalette aPalEmpty; + mxSalBmp = ImplGetSVData()->mpDefInst->CreateSalBitmap(); + mxSalBmp->Create(aSize, vcl::PixelFormat::N32_BPP, aPalEmpty); + + BitmapScopedReadAccess pReadColorAcc(rBitmapEx.GetBitmap()); + BitmapScopedReadAccess pReadAlphaAcc(rBitmapEx.GetAlphaMask()); + BitmapScopedWriteAccess pWriteAcc(*this); + auto nHeight = pReadColorAcc->Height(); + auto nWidth = pReadColorAcc->Width(); + bool bPalette = pReadColorAcc->HasPalette(); + + for ( tools::Long nY = 0; nY < nHeight; nY++ ) + { + Scanline pScanlineColor = pReadColorAcc->GetScanline( nY ); + Scanline pScanlineAlpha = pReadAlphaAcc->GetScanline( nY ); + Scanline pScanlineWrite = pWriteAcc->GetScanline( nY ); + for (tools::Long nX = 0; nX < nWidth; ++nX) + { + BitmapColor aCol; + if (bPalette) + aCol = pReadColorAcc->GetPaletteColor(pReadColorAcc->GetIndexFromData(pScanlineColor, nX)); + else + aCol = pReadColorAcc->GetPixelFromData(pScanlineColor, nX); + auto nAlpha = pReadAlphaAcc->GetPixelFromData(pScanlineAlpha, nX).GetIndex(); + aCol.SetAlpha(nAlpha); + pWriteAcc->SetPixelOnData(pScanlineWrite, nX, aCol); + } + } + +// So.... in theory the following code should work, and be much more efficient. In practice, the gen/cairo +// code is doing something weird involving masks that results in alpha not doing the same thing as on the other +// backends. +// ScopedVclPtrInstance<VirtualDevice> xDev(DeviceFormat::WITH_ALPHA); +// Size aPixelSize = rBitmapEx.GetSizePixel(); +// xDev->SetOutputSizePixel(aPixelSize, /*bErase*/true, /*bAlphaMaskTransparent*/true); +// xDev->DrawBitmapEx(Point(0, 0), aPixelSize, rBitmapEx); +// mxSalBmp = xDev->GetBitmap(Point(0,0), aPixelSize).mxSalBmp; + } }