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 );