diff options
author | Patrick Luby <plubius@neooffice.org> | 2022-12-10 14:16:39 -0500 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2022-12-11 20:02:53 +0000 |
commit | 9eb732a32023e74c44ac8c3b5af9f5424273bb6c (patch) | |
tree | 3b40f9d61aae45470f07c489f7089cbfcb704ab1 /vcl/quartz | |
parent | d7f969a133d4eb8258b5d90ed88532cfcdbc9b28 (diff) |
Related: tdf#146842 Convert SkiaSalBitmap to QuartzSalBitmap
Commit de3f13e2175564316eb5a62dee65e9ff8f31b460 disabled Skia for printing.
However, since all SalBitmaps created are either all QuartzSalBitmaps or all
SkiaSalBitmaps, a crash occurs whenever a SkiaSalBitmap is passed to a
printer's SalGraphics instance which is now always non-Skia.
Change-Id: I7c1b0e1a9993e21db18ba5695a106cb10cc4088a
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143939
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'vcl/quartz')
-rw-r--r-- | vcl/quartz/AquaGraphicsBackend.cxx | 139 | ||||
-rw-r--r-- | vcl/quartz/salbmp.cxx | 60 |
2 files changed, 199 insertions, 0 deletions
diff --git a/vcl/quartz/AquaGraphicsBackend.cxx b/vcl/quartz/AquaGraphicsBackend.cxx index 987ce5b784a5..7482986dd58a 100644 --- a/vcl/quartz/AquaGraphicsBackend.cxx +++ b/vcl/quartz/AquaGraphicsBackend.cxx @@ -44,6 +44,11 @@ #include <svdata.hxx> #endif +#if HAVE_FEATURE_SKIA +#include <vcl/skia/SkiaHelper.hxx> +#include <skia/salbmp.hxx> +#endif + using namespace vcl; namespace @@ -187,6 +192,48 @@ void drawPattern50(void*, CGContextRef rContext) CGContextAddRects(rContext, aRects, 2); CGContextFillPath(rContext); } + +#if HAVE_FEATURE_SKIA + +// Related: tdf#146842 Convert SkiaSalBitmap to QuartzSalBitmap +// Commit de3f13e2175564316eb5a62dee65e9ff8f31b460 disabled Skia for printing. +// However, since all SalBitmaps created are either all QuartzSalBitmaps or all +// SkiaSalBitmaps, a crash occurs whenever a SkiaSalBitmap is passed to a +// printer's SalGraphics instance which is now always non-Skia. +QuartzSalBitmap* checkAndConvertToQuartzSalBitmap(const SalTwoRect& rPosAry, + const SalBitmap& rSalBitmap, + SalTwoRect* pAdjustedSrcPosAry) +{ + QuartzSalBitmap* pRet = nullptr; + + if (SkiaHelper::isVCLSkiaEnabled() && dynamic_cast<const SkiaSalBitmap*>(&rSalBitmap)) + { + const SkiaSalBitmap& rSkiaBitmap = static_cast<const SkiaSalBitmap&>(rSalBitmap); + + SalTwoRect aSrcPosAry(rPosAry); + aSrcPosAry.mnDestX = 0; + aSrcPosAry.mnDestY = 0; + + pRet = new QuartzSalBitmap; + if (pRet) + { + // Ignore any failures as returning a nullptr will lead to a crash + pRet->Create(rSkiaBitmap, aSrcPosAry); + + if (pAdjustedSrcPosAry) + { + pAdjustedSrcPosAry->mnSrcX = 0; + pAdjustedSrcPosAry->mnSrcY = 0; + pAdjustedSrcPosAry->mnSrcWidth = aSrcPosAry.mnDestWidth; + pAdjustedSrcPosAry->mnSrcHeight = aSrcPosAry.mnDestHeight; + } + } + } + + return pRet; +} + +#endif } AquaGraphicsBackend::AquaGraphicsBackend(AquaSharedAttributes& rShared) @@ -904,6 +951,21 @@ void AquaGraphicsBackend::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& if (!mrShared.checkContext()) return; +#if HAVE_FEATURE_SKIA + if (mrShared.mbPrinter) + { + SAL_INFO("vcl.print", "Printing with Skia bitmaps: AquaGraphicsBackend::drawBitmap"); + SalTwoRect aDestPosAry(rPosAry); + std::unique_ptr<QuartzSalBitmap> pSalBitmap( + checkAndConvertToQuartzSalBitmap(rPosAry, rSalBitmap, &aDestPosAry)); + if (pSalBitmap) + { + drawBitmap(aDestPosAry, *pSalBitmap); + return; + } + } +#endif + const QuartzSalBitmap& rBitmap = static_cast<const QuartzSalBitmap&>(rSalBitmap); CGImageRef xImage = rBitmap.CreateCroppedImage( static_cast<int>(rPosAry.mnSrcX), static_cast<int>(rPosAry.mnSrcY), @@ -925,6 +987,31 @@ void AquaGraphicsBackend::drawBitmap(const SalTwoRect& rPosAry, const SalBitmap& if (!mrShared.checkContext()) return; +#if HAVE_FEATURE_SKIA + if (mrShared.mbPrinter) + { + SAL_INFO( + "vcl.print", + "Printing with Skia bitmaps: AquaGraphicsBackend::drawBitmapWithTranspraentBitmap"); + SalTwoRect aDestPosAry(rPosAry); + std::unique_ptr<QuartzSalBitmap> pSalBitmap( + checkAndConvertToQuartzSalBitmap(rPosAry, rSalBitmap, &aDestPosAry)); + if (pSalBitmap) + { + drawBitmap(aDestPosAry, *pSalBitmap, rTransparentBitmap); + return; + } + + pSalBitmap.reset( + checkAndConvertToQuartzSalBitmap(rPosAry, rTransparentBitmap, &aDestPosAry)); + if (pSalBitmap) + { + drawBitmap(aDestPosAry, rSalBitmap, *pSalBitmap); + return; + } + } +#endif + const QuartzSalBitmap& rBitmap = static_cast<const QuartzSalBitmap&>(rSalBitmap); const QuartzSalBitmap& rMask = static_cast<const QuartzSalBitmap&>(rTransparentBitmap); @@ -946,6 +1033,21 @@ void AquaGraphicsBackend::drawMask(const SalTwoRect& rPosAry, const SalBitmap& r if (!mrShared.checkContext()) return; +#if HAVE_FEATURE_SKIA + if (mrShared.mbPrinter) + { + SAL_INFO("vcl.print", "Printing with Skia bitmaps: AquaGraphicsBackend::drawMask"); + SalTwoRect aDestPosAry(rPosAry); + std::unique_ptr<QuartzSalBitmap> pSalBitmap( + checkAndConvertToQuartzSalBitmap(rPosAry, rSalBitmap, &aDestPosAry)); + if (pSalBitmap) + { + drawMask(aDestPosAry, *pSalBitmap, nMaskColor); + return; + } + } +#endif + const QuartzSalBitmap& rBitmap = static_cast<const QuartzSalBitmap&>(rSalBitmap); CGImageRef xImage = rBitmap.CreateColorMask(rPosAry.mnSrcX, rPosAry.mnSrcY, rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, nMaskColor); @@ -1224,6 +1326,25 @@ bool AquaGraphicsBackend::drawAlphaBitmap(const SalTwoRect& rTR, const SalBitmap if (rTR.mnDestWidth < 0 || rTR.mnDestHeight < 0) return false; +#if HAVE_FEATURE_SKIA + if (!mrShared.checkContext()) + return false; + + if (mrShared.mbPrinter) + { + SAL_INFO("vcl.print", "Printing with Skia bitmaps: AquaGraphicsBackend::drawAlphaBitmap"); + SalTwoRect aDestPosAry(rTR); + std::unique_ptr<QuartzSalBitmap> pSalBitmap( + checkAndConvertToQuartzSalBitmap(rTR, rSrcBitmap, &aDestPosAry)); + if (pSalBitmap) + return drawAlphaBitmap(aDestPosAry, *pSalBitmap, rAlphaBmp); + + pSalBitmap.reset(checkAndConvertToQuartzSalBitmap(rTR, rAlphaBmp, &aDestPosAry)); + if (pSalBitmap) + return drawAlphaBitmap(aDestPosAry, rSrcBitmap, *pSalBitmap); + } +#endif + const QuartzSalBitmap& rSrcSalBmp = static_cast<const QuartzSalBitmap&>(rSrcBitmap); const QuartzSalBitmap& rMaskSalBmp = static_cast<const QuartzSalBitmap&>(rAlphaBmp); CGImageRef xMaskedImage = rSrcSalBmp.CreateWithMask(rMaskSalBmp, rTR.mnSrcX, rTR.mnSrcY, @@ -1256,6 +1377,24 @@ bool AquaGraphicsBackend::drawTransformedBitmap(const basegfx::B2DPoint& rNull, if (fAlpha != 1.0) return false; +#if HAVE_FEATURE_SKIA + if (mrShared.mbPrinter) + { + SAL_INFO("vcl.print", + "Printing with Skia bitmaps: AquaGraphicsBackend::drawTransformedBitmap"); + const Size aSize = rSrcBitmap.GetSize(); + SalTwoRect aTR(0, 0, aSize.Width(), aSize.Height(), 0, 0, aSize.Width(), aSize.Height()); + std::unique_ptr<QuartzSalBitmap> pSalBitmap( + checkAndConvertToQuartzSalBitmap(aTR, rSrcBitmap, nullptr)); + if (pSalBitmap) + return drawTransformedBitmap(rNull, rX, rY, *pSalBitmap, pAlphaBmp, fAlpha); + + pSalBitmap.reset(checkAndConvertToQuartzSalBitmap(aTR, *pAlphaBmp, nullptr)); + if (pSalBitmap) + return drawTransformedBitmap(rNull, rX, rY, rSrcBitmap, pSalBitmap.get(), fAlpha); + } +#endif + // get the Quartz image CGImageRef xImage = nullptr; const Size aSize = rSrcBitmap.GetSize(); diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx index cdc405ad362c..cd191482f5aa 100644 --- a/vcl/quartz/salbmp.cxx +++ b/vcl/quartz/salbmp.cxx @@ -115,6 +115,66 @@ bool QuartzSalBitmap::Create( const SalBitmap& rSalBmp, vcl::PixelFormat eNewPix return false; } +#if HAVE_FEATURE_SKIA + +bool QuartzSalBitmap::Create( const SkiaSalBitmap& rSalBmp, const SalTwoRect& rPosAry ) +{ + bool bRet = false; + + // Ugly but necessary to acquire the bitmap buffer because all of the + // SalBitmap instances that callers pass are already const. At least we + // only need to read, not write to the bitmap paramter. + SkiaSalBitmap& rSkiaSalBmp = const_cast<SkiaSalBitmap&>( rSalBmp ); + + BitmapBuffer *pSrcBuffer = rSkiaSalBmp.AcquireBuffer( BitmapAccessMode::Read ); + if ( !pSrcBuffer ) + return bRet; + + if ( !pSrcBuffer->mpBits ) + { + rSkiaSalBmp.ReleaseBuffer( pSrcBuffer, BitmapAccessMode::Read ); + return bRet; + } + + // Create only a 1 pixel buffer as it will always be discarded + mnBits = 32; + mnWidth = 1; + mnHeight = 1; + if( AllocateUserData() ) + { + BitmapBuffer *pDestBuffer = AcquireBuffer( BitmapAccessMode::Read ); + if ( pDestBuffer ) + { + std::unique_ptr<BitmapBuffer> pConvertedBuffer = StretchAndConvert( *pSrcBuffer, rPosAry, pDestBuffer->mnFormat, pDestBuffer->maPalette, &pDestBuffer->maColorMask ); + bool bUseDestBuffer = ( pConvertedBuffer && + pConvertedBuffer->mpBits && + pConvertedBuffer->mnFormat == pDestBuffer->mnFormat && + pConvertedBuffer->mnWidth == rPosAry.mnDestWidth && + pConvertedBuffer->mnHeight == rPosAry.mnDestHeight ); + + ReleaseBuffer( pDestBuffer, BitmapAccessMode::Read ); + + if ( bUseDestBuffer ) + { + // Surprisingly, BitmapBuffer does not delete the bits so + // discard our 1 pixel buffer and take ownership of the bits + DestroyContext(); + m_pUserBuffer.reset( pConvertedBuffer->mpBits ); + mnWidth = pConvertedBuffer->mnWidth; + mnHeight = pConvertedBuffer->mnHeight; + mnBytesPerRow = pConvertedBuffer->mnScanlineSize; + bRet = true; + } + } + } + + rSkiaSalBmp.ReleaseBuffer( pSrcBuffer, BitmapAccessMode::Read ); + + return bRet; +} + +#endif + bool QuartzSalBitmap::Create( const css::uno::Reference< css::rendering::XBitmapCanvas >& /*xBitmapCanvas*/, Size& /*rSize*/, bool /*bMask*/ ) { |