canvas/source/cairo/cairo_canvashelper.cxx | 10 - vcl/source/bitmap/BitmapTools.cxx | 214 ++++++++++------------------- 2 files changed, 82 insertions(+), 142 deletions(-)
New commits: commit eb4394e3460932011940a1e3c03d5d67d7f45885 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Mon Aug 18 13:31:30 2025 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Mon Aug 18 19:08:54 2025 +0200 tdf#167893 and tdf#167876 weird effects in slideshow this was a little confusing, because the bibisect pointed at one commit, but it was actually an earlier commit which had the bug. It just happened that the later commit made more active use of the code from the earlier commit. The bug was mostly in CanvasCairoExtractBitmapData, which was, I think, largely unused before commit 088a7c7c451321a800ca8d3523a18b6bb93239b7 Author: Noel Grandin <noelgran...@gmail.com> Date: Tue Sep 24 16:18:11 2024 +0200 remove alpha device from OutputDevice At which point some of the optimised paths in slideshow stopped triggering as often (which is a different issue which will need resolving) Also, CanvasCairoExtractBitmapData was largely wrong, returning unpremultipled data when cairo wants premultiplied data, and returning 4-byte RGBA when the calling code was going to tell cairo that the format was 3-byte RGBA. So anyhow, things now work better, and the CanvasCairoExtractBitmapData method is considerably smaller and simpler. Change-Id: I7d668ae08f4caf8dd0d5561a2d94e23e767216d5 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/189867 Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> Tested-by: Jenkins diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx index 0170499c6abb..58a3798deeff 100644 --- a/canvas/source/cairo/cairo_canvashelper.cxx +++ b/canvas/source/cairo/cairo_canvashelper.cxx @@ -340,15 +340,7 @@ constexpr OUStringLiteral PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME = u"Canvas:: { ::Bitmap aBitmap = bitmapFromXBitmap(xBitmap); - // there's no pixmap for alpha bitmap. we might still - // use rgb pixmap and only access alpha pixels the - // slow way. now we just speedup rgb bitmaps - if( !aBitmap.HasAlpha() ) - { - pSurface = rSurfaceProvider->createSurface( aBitmap ); - data = nullptr; - bHasAlpha = false; - } + pSurface = rSurfaceProvider->createSurface( aBitmap ); if( !pSurface ) { diff --git a/vcl/source/bitmap/BitmapTools.cxx b/vcl/source/bitmap/BitmapTools.cxx index 7feb78098af8..febb4d2331e2 100644 --- a/vcl/source/bitmap/BitmapTools.cxx +++ b/vcl/source/bitmap/BitmapTools.cxx @@ -988,6 +988,8 @@ void CanvasCairoExtractBitmapData( BitmapEx const & aBmpEx, const Bitmap & aBitm } /** + * This returns data formatted the way Cairo wants it, i.e. either CAIRO_FORMAT_ARGB32 or CAIRO_FORMAT_RGB24 + * * @param data will be filled with alpha data, if xBitmap is alpha/transparent image * @param bHasAlpha will be set to true if resulting surface has alpha **/ @@ -997,19 +999,15 @@ void CanvasCairoExtractBitmapData( const Bitmap & aBitmap, unsigned char*& data, const tools::Long nWidth = rnWidth = pBitmapReadAcc->Width(); const tools::Long nHeight = rnHeight = pBitmapReadAcc->Height(); tools::Long nX, nY; - bool bIsAlpha = false; + bHasAlpha = aBitmap.HasAlpha(); - data = static_cast<unsigned char*>(malloc( nWidth*nHeight*4 )); + data = static_cast<unsigned char*>(malloc( nWidth*nHeight*(bHasAlpha ? 4 : 3) )); if (!data) std::abort(); tools::Long nOff = 0; ::Color aColor; - unsigned int nAlpha = 255; -#if !ENABLE_WASM_STRIP_PREMULTIPLY - vcl::bitmap::lookup_table const & premultiply_table = vcl::bitmap::get_premultiply_table(); -#endif for( nY = 0; nY < nHeight; nY++ ) { ::Scanline pReadScan; @@ -1017,186 +1015,138 @@ void CanvasCairoExtractBitmapData( const Bitmap & aBitmap, unsigned char*& data, switch( pBitmapReadAcc->GetScanlineFormat() ) { case ScanlineFormat::N8BitPal: + assert(!bHasAlpha); pReadScan = pBitmapReadAcc->GetScanline( nY ); for( nX = 0; nX < nWidth; nX++ ) { -#ifdef OSL_BIGENDIAN - nAlpha = data[ nOff++ ] = 255; -#else - nAlpha = data[ nOff + 3 ] = 255; -#endif aColor = pBitmapReadAcc->GetPaletteColor(*pReadScan++); - #ifdef OSL_BIGENDIAN -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(aColor.GetRed(), nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(aColor.GetGreen(), nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(aColor.GetBlue(), nAlpha); -#else - data[ nOff++ ] = premultiply_table[nAlpha][aColor.GetRed()]; - data[ nOff++ ] = premultiply_table[nAlpha][aColor.GetGreen()]; - data[ nOff++ ] = premultiply_table[nAlpha][aColor.GetBlue()]; -#endif + data[ nOff++ ] = aColor.GetRed(); + data[ nOff++ ] = aColor.GetGreen(); + data[ nOff++ ] = aColor.GetBlue(); #else -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(aColor.GetBlue(), nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(aColor.GetGreen(), nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(aColor.GetRed(), nAlpha); -#else - data[ nOff++ ] = premultiply_table[nAlpha][aColor.GetBlue()]; - data[ nOff++ ] = premultiply_table[nAlpha][aColor.GetGreen()]; - data[ nOff++ ] = premultiply_table[nAlpha][aColor.GetRed()]; -#endif - nOff++; + data[ nOff++ ] = aColor.GetBlue(); + data[ nOff++ ] = aColor.GetGreen(); + data[ nOff++ ] = aColor.GetRed(); #endif } break; case ScanlineFormat::N24BitTcBgr: + assert(!bHasAlpha); pReadScan = pBitmapReadAcc->GetScanline( nY ); for( nX = 0; nX < nWidth; nX++ ) { #ifdef OSL_BIGENDIAN - nAlpha = data[ nOff ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff + 3 ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff + 2 ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff + 1 ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); + data[ nOff + 3 ] = *pReadScan++; + data[ nOff + 2 ] = *pReadScan++; + data[ nOff + 1 ] = *pReadScan++; #else - data[ nOff + 3 ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff + 2 ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff + 1 ] = premultiply_table[nAlpha][*pReadScan++]; -#endif - nOff += 4; -#else - nAlpha = data[ nOff + 3 ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); -#else - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; -#endif - nOff++; + data[ nOff + 1 ] = *pReadScan++; + data[ nOff + 2 ] = *pReadScan++; + data[ nOff + 3 ] = *pReadScan++; #endif + nOff += 3; } break; case ScanlineFormat::N24BitTcRgb: + assert(!bHasAlpha); pReadScan = pBitmapReadAcc->GetScanline( nY ); for( nX = 0; nX < nWidth; nX++ ) { #ifdef OSL_BIGENDIAN - nAlpha = data[ nOff++ ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); + data[ nOff + 3 ] = *pReadScan++; + data[ nOff + 2 ] = *pReadScan++; + data[ nOff + 1 ] = *pReadScan++; #else - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; -#endif -#else - nAlpha = data[ nOff + 3 ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 2 ], nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 1 ], nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 0 ], nAlpha); -#else - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 2 ]]; - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 1 ]]; - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 0 ]]; -#endif - pReadScan += 3; - nOff++; + data[ nOff + 1 ] = *pReadScan++; + data[ nOff + 2 ] = *pReadScan++; + data[ nOff + 3 ] = *pReadScan++; #endif + nOff += 3; } break; case ScanlineFormat::N32BitTcBgra: - bIsAlpha = true; - [[fallthrough]]; - case ScanlineFormat::N32BitTcBgrx: + assert(bHasAlpha); pReadScan = pBitmapReadAcc->GetScanline( nY ); + // this data is already premultiplied for( nX = 0; nX < nWidth; nX++ ) { #ifdef OSL_BIGENDIAN - if( bIsAlpha ) - nAlpha = pReadScan[3]; - else - nAlpha = data[ nOff++ ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 2 ], nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 1 ], nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 0 ], nAlpha); + data[ nOff++ ] = pReadScan[ 3 ]; + data[ nOff++ ] = pReadScan[ 2 ]; + data[ nOff++ ] = pReadScan[ 1 ]; + data[ nOff++ ] = pReadScan[ 0 ]; + pReadScan += 4; #else - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 2 ]]; - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 1 ]]; - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 0 ]]; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; #endif + } + break; + + case ScanlineFormat::N32BitTcBgrx: + assert(!bHasAlpha); + pReadScan = pBitmapReadAcc->GetScanline( nY ); + + for( nX = 0; nX < nWidth; nX++ ) + { +#ifdef OSL_BIGENDIAN + data[ nOff++ ] = pReadScan[ 2 ]; + data[ nOff++ ] = pReadScan[ 1 ]; + data[ nOff++ ] = pReadScan[ 0 ]; pReadScan += 4; #else - if( bIsAlpha ) - nAlpha = pReadScan[3]; - else - nAlpha = data[ nOff + 3 ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); -#else - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; -#endif + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; pReadScan++; - nOff++; #endif } break; case ScanlineFormat::N32BitTcRgba: - bIsAlpha = true; - [[fallthrough]]; - case ScanlineFormat::N32BitTcRgbx: + assert(bHasAlpha); pReadScan = pBitmapReadAcc->GetScanline( nY ); + // this data is already premultiplied for( nX = 0; nX < nWidth; nX++ ) { #ifdef OSL_BIGENDIAN - if( bIsAlpha ) - nAlpha = pReadScan[3]; - else - nAlpha = data[ nOff ++ ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(*pReadScan++, nAlpha); + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; #else - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; - data[ nOff++ ] = premultiply_table[nAlpha][*pReadScan++]; + data[ nOff++ ] = pReadScan[ 3 ]; + data[ nOff++ ] = pReadScan[ 2 ]; + data[ nOff++ ] = pReadScan[ 1 ]; + data[ nOff++ ] = pReadScan[ 0 ]; + pReadScan += 4; #endif + } + break; + + case ScanlineFormat::N32BitTcRgbx: + assert(!bHasAlpha); + pReadScan = pBitmapReadAcc->GetScanline( nY ); + + for( nX = 0; nX < nWidth; nX++ ) + { +#ifdef OSL_BIGENDIAN + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; + data[ nOff++ ] = *pReadScan++; pReadScan++; #else - if( bIsAlpha ) - nAlpha = pReadScan[3]; - else - nAlpha = data[ nOff + 3 ] = 255; -#if ENABLE_WASM_STRIP_PREMULTIPLY - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 2 ], nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 1 ], nAlpha); - data[ nOff++ ] = vcl::bitmap::premultiply(pReadScan[ 0 ], nAlpha); -#else - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 2 ]]; - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 1 ]]; - data[ nOff++ ] = premultiply_table[nAlpha][pReadScan[ 0 ]]; -#endif + data[ nOff++ ] = pReadScan[ 2 ]; + data[ nOff++ ] = pReadScan[ 1 ]; + data[ nOff++ ] = pReadScan[ 0 ]; pReadScan += 4; - nOff++; #endif } break; @@ -1204,8 +1154,6 @@ void CanvasCairoExtractBitmapData( const Bitmap & aBitmap, unsigned char*& data, assert(false && "unknown format"); } } - - bHasAlpha = bIsAlpha; } uno::Sequence< sal_Int8 > CanvasExtractBitmapData(Bitmap const & rBitmap, const geometry::IntegerRectangle2D& rect)