vcl/source/gdi/pdfwriter_impl.cxx  |   21 ++++----------
 vcl/source/gdi/pdfwriter_impl2.cxx |   55 -------------------------------------
 2 files changed, 8 insertions(+), 68 deletions(-)

New commits:
commit b11957681f7dfbc5268e2f08528e3cf6f5c1b180
Author:     Noel Grandin <noelgran...@gmail.com>
AuthorDate: Sun Feb 9 14:05:23 2025 +0200
Commit:     Noel Grandin <noelgran...@gmail.com>
CommitDate: Mon Feb 10 07:57:26 2025 +0100

    hopefully fix the PDF export of alpha once and for all
    
    The root of the problem, is that at the bottom of the call-chain,
    we want to export transparency. We were trying to patch this in the
    middle of call-chain, by inverting. But that is unreliable because
    sometimes we don't always traverse the middle of the call-chain
    once.
    
    So remove all of the various inverting, and just invert at the
    bottom, when we want to output transparency data.
    
    Tested this with the various bugs linked in the comments I removed.
    
    Change-Id: I880ab3a3e6c44f8531893f7405a33a331e4b4295
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/181316
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>
    Tested-by: Jenkins

diff --git a/vcl/source/gdi/pdfwriter_impl.cxx 
b/vcl/source/gdi/pdfwriter_impl.cxx
index 6dfc6d0039c3..e7e28ef9f001 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -2627,16 +2627,7 @@ bool PDFWriterImpl::emitType3Font(const 
vcl::font::PhysicalFontFace* pFace,
                                        StreamMode::READ);
                 vcl::PngImageReader aReader(aStream);
 
-                // When rendering an image with an alpha mask during PDF
-                // export, the alpha mask needs to be inverted
                 BitmapEx aBitmapEx = aReader.read();
-                if ( aBitmapEx.IsAlpha())
-                {
-                    AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
-                    aAlpha.Invert();
-                    aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
-                }
-
                 const BitmapEmit& rBitmapEmit = createBitmapEmit(aBitmapEx, 
Graphic(),
                                                                  aUsedBitmaps, 
aResourceDict,
                                                                  
aOutputStreams);
@@ -9182,9 +9173,7 @@ void PDFWriterImpl::writeJPG( const JPGEmit& rObject )
         return;
 
     if( nMaskObject )
-    {
         writeBitmapMaskObject( nMaskObject, rObject.m_aAlphaMask );
-    }
 
     writeReferenceXObject(rObject.m_aReferenceXObject);
 }
@@ -9792,9 +9781,7 @@ bool PDFWriterImpl::writeBitmapObject( const BitmapEmit& 
rObject )
     if (!writeBuffer(aLine)) return false;
 
     if( nMaskObject )
-    {
         return writeBitmapMaskObject( nMaskObject, 
rObject.m_aBitmap.GetAlphaMask() );
-    }
 
     writeReferenceXObject(rObject.m_aReferenceXObject);
 
@@ -9858,9 +9845,15 @@ bool PDFWriterImpl::writeBitmapMaskObject( sal_Int32 
nMaskObject, const AlphaMas
     BitmapScopedReadAccess pAccess(aBitmap);
     //With PDF bitmaps, each row is padded to a BYTE boundary (multiple of 8 
bits).
     const int nScanLineBytes = ((pAccess->GetBitCount() * pAccess->Width()) + 
7U) / 8U;
+    // we have alpha, but we want to output transparency, so we need to invert 
the data
+    std::unique_ptr<sal_uInt8[]> pInvertedBytes = 
std::make_unique<sal_uInt8[]>(nScanLineBytes);
     for( tools::Long i = 0; i < pAccess->Height(); i++ )
     {
-        if (!writeBufferBytes(pAccess->GetScanline(i), nScanLineBytes))
+        const Scanline pScanline = pAccess->GetScanline(i);
+        std::copy(pScanline, pScanline + nScanLineBytes, pInvertedBytes.get());
+        for (auto p = pInvertedBytes.get(); p < pInvertedBytes.get() + 
nScanLineBytes; ++p)
+            *p = ~(*p);
+        if (!writeBufferBytes(pInvertedBytes.get(), nScanLineBytes))
             return false;
     }
     endCompression();
diff --git a/vcl/source/gdi/pdfwriter_impl2.cxx 
b/vcl/source/gdi/pdfwriter_impl2.cxx
index 5e648765593d..61452c17415c 100644
--- a/vcl/source/gdi/pdfwriter_impl2.cxx
+++ b/vcl/source/gdi/pdfwriter_impl2.cxx
@@ -498,16 +498,6 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
                                 xVDev->EnableMapMode( false );
 
                                 AlphaMask aAlpha(xVDev->GetBitmap(Point(), 
xVDev->GetOutputSizePixel()));
-                                const AlphaMask& 
aPaintAlpha(aPaint.GetAlphaMask());
-                                // The alpha mask is inverted from what is
-                                // expected so invert it again. To test this
-                                // code, export to PDF the transparent shapes,
-                                // gradients, and images in the documents
-                                // attached to the following bug reports:
-                                //   
https://bugs.documentfoundation.org/show_bug.cgi?id=155912
-                                //   
https://bugs.documentfoundation.org/show_bug.cgi?id=156630
-                                aAlpha.Invert(); // convert to alpha
-                                aAlpha.BlendWith(aPaintAlpha);
 #if HAVE_FEATURE_SKIA
 #if OSL_DEBUG_LEVEL > 0
                                 // In release builds, we always invert
@@ -525,6 +515,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
                                     //   
https://bugs.documentfoundation.org/attachment.cgi?id=188084
                                     aAlpha.Invert(); // convert to alpha
                                 }
+                                aAlpha.BlendWith(aPaint.GetAlphaMask());
 
                                 xVDev.disposeAndClear();
 
@@ -773,22 +764,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
                 case MetaActionType::BMPEX:
                 {
                     const MetaBmpExAction*  pA = static_cast<const 
MetaBmpExAction*>(pAction);
-
-                    // The alpha mask is inverted from what is
-                    // expected so invert it again. To test this
-                    // code, export to PDF the transparent shapes,
-                    // gradients, and images in the documents
-                    // attached to the following bug reports:
-                    //   
https://bugs.documentfoundation.org/show_bug.cgi?id=155912
-                    //   
https://bugs.documentfoundation.org/show_bug.cgi?id=156630
                     BitmapEx aBitmapEx( pA->GetBitmapEx() );
-                    if ( aBitmapEx.IsAlpha())
-                    {
-                        AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
-                        aAlpha.Invert();
-                        aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
-                    }
-
                     Size aSize( OutputDevice::LogicToLogic( 
aBitmapEx.GetPrefSize(),
                             aBitmapEx.GetPrefMapMode(), 
pDummyVDev->GetMapMode() ) );
                     Graphic aGraphic = i_pOutDevData ? 
i_pOutDevData->GetCurrentGraphic() : Graphic();
@@ -799,22 +775,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
                 case MetaActionType::BMPEXSCALE:
                 {
                     const MetaBmpExScaleAction* pA = static_cast<const 
MetaBmpExScaleAction*>(pAction);
-
-                    // The alpha mask is inverted from what is
-                    // expected so invert it again. To test this
-                    // code, export to PDF the transparent shapes,
-                    // gradients, and images in the documents
-                    // attached to the following bug reports:
-                    //   
https://bugs.documentfoundation.org/show_bug.cgi?id=155912
-                    //   
https://bugs.documentfoundation.org/show_bug.cgi?id=156630
                     BitmapEx aBitmapEx( pA->GetBitmapEx() );
-                    if ( aBitmapEx.IsAlpha())
-                    {
-                        AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
-                        aAlpha.Invert();
-                        aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
-                    }
-
                     Graphic aGraphic = i_pOutDevData ? 
i_pOutDevData->GetCurrentGraphic() : Graphic();
                     implWriteBitmapEx( pA->GetPoint(), pA->GetSize(), 
aBitmapEx, aGraphic, pDummyVDev, i_rContext );
                 }
@@ -824,21 +785,7 @@ void PDFWriterImpl::playMetafile( const GDIMetaFile& 
i_rMtf, vcl::PDFExtOutDevDa
                 {
                     const MetaBmpExScalePartAction* pA = static_cast<const 
MetaBmpExScalePartAction*>(pAction);
 
-                    // The alpha mask is inverted from what is
-                    // expected so invert it again. To test this
-                    // code, export to PDF the transparent shapes,
-                    // gradients, and images in the documents
-                    // attached to the following bug reports:
-                    //   
https://bugs.documentfoundation.org/show_bug.cgi?id=155912
-                    //   
https://bugs.documentfoundation.org/show_bug.cgi?id=156630
                     BitmapEx aBitmapEx( pA->GetBitmapEx() );
-                    if ( aBitmapEx.IsAlpha())
-                    {
-                        AlphaMask aAlpha = aBitmapEx.GetAlphaMask();
-                        aAlpha.Invert();
-                        aBitmapEx = BitmapEx(aBitmapEx.GetBitmap(), aAlpha);
-                    }
-
                     aBitmapEx.Crop( tools::Rectangle( pA->GetSrcPoint(), 
pA->GetSrcSize() ) );
                     Graphic aGraphic = i_pOutDevData ? 
i_pOutDevData->GetCurrentGraphic() : Graphic();
                     implWriteBitmapEx( pA->GetDestPoint(), pA->GetDestSize(), 
aBitmapEx, aGraphic, pDummyVDev, i_rContext );

Reply via email to