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)

Reply via email to