diff options
-rw-r--r-- | vcl/inc/quartz/salbmp.h | 6 | ||||
-rw-r--r-- | vcl/osx/salinst.cxx | 6 | ||||
-rw-r--r-- | vcl/quartz/AquaGraphicsBackend.cxx | 139 | ||||
-rw-r--r-- | vcl/quartz/salbmp.cxx | 60 |
4 files changed, 210 insertions, 1 deletions
diff --git a/vcl/inc/quartz/salbmp.h b/vcl/inc/quartz/salbmp.h index 8a9e94d043cc..459a2b528f99 100644 --- a/vcl/inc/quartz/salbmp.h +++ b/vcl/inc/quartz/salbmp.h @@ -30,6 +30,9 @@ #include <salinst.hxx> #include <salvd.hxx> #include <salbmp.hxx> +#if HAVE_FEATURE_SKIA +#include <skia/salbmp.hxx> +#endif #include <memory> @@ -61,6 +64,9 @@ public: bool Create( const SalBitmap& rSalBmp ) override; bool Create( const SalBitmap& rSalBmp, SalGraphics* pGraphics ) override; bool Create( const SalBitmap& rSalBmp, vcl::PixelFormat eNewPixelFormat) override; +#if HAVE_FEATURE_SKIA + bool Create( const SkiaSalBitmap& rSkiaSalBmp, const SalTwoRect& rPosAry ); +#endif virtual bool Create( const css::uno::Reference< css::rendering::XBitmapCanvas >& rBitmapCanvas, Size& rSize, bool bMask = false ) override; diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx index e7f202ae7ae5..22a024bc265d 100644 --- a/vcl/osx/salinst.cxx +++ b/vcl/osx/salinst.cxx @@ -524,7 +524,11 @@ void AquaSalInstance::handleAppDefinedEvent( NSEvent* pEvent ) bool AquaSalInstance::RunInMainYield( bool bHandleAllCurrentEvents ) { OSX_SALDATA_RUNINMAIN_UNION( DoYield( false, bHandleAllCurrentEvents), boolean ) - assert( false && "Don't call this from the main thread!" ); + + // PrinterController::removeTransparencies() calls this frequently on the + // main thread so reduce the severity from an assert so that printing still + // works in a debug builds + SAL_WARN_IF( true, "vcl", "Don't call this from the main thread!" ); return false; } 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*/ ) { |