diff options
-rw-r--r-- | solenv/clang-format/excludelist | 4 | ||||
-rw-r--r-- | vcl/Library_vcl.mk | 1 | ||||
-rw-r--r-- | vcl/Library_vclplug_osx.mk | 3 | ||||
-rw-r--r-- | vcl/inc/quartz/salgdi.h | 14 | ||||
-rw-r--r-- | vcl/ios/salios.cxx | 443 | ||||
-rw-r--r-- | vcl/osx/salgdiutils.cxx (renamed from vcl/quartz/salgdiutils.cxx) | 0 | ||||
-rw-r--r-- | vcl/osx/salmacos.cxx | 387 | ||||
-rw-r--r-- | vcl/quartz/salbmp.cxx | 58 | ||||
-rw-r--r-- | vcl/quartz/salgdicommon.cxx | 181 | ||||
-rw-r--r-- | vcl/quartz/salvd.cxx | 104 |
10 files changed, 843 insertions, 352 deletions
diff --git a/solenv/clang-format/excludelist b/solenv/clang-format/excludelist index 99a3d5089d75..bef00255118e 100644 --- a/solenv/clang-format/excludelist +++ b/solenv/clang-format/excludelist @@ -14779,6 +14779,7 @@ vcl/inc/window.h vcl/inc/wizdlg.hxx vcl/ios/dummies.cxx vcl/ios/iosinst.cxx +vcl/ios/salios.cxx vcl/null/printerinfomanager.cxx vcl/osx/DataFlavorMapping.cxx vcl/osx/DataFlavorMapping.hxx @@ -14804,7 +14805,9 @@ vcl/osx/documentfocuslistener.cxx vcl/osx/documentfocuslistener.hxx vcl/osx/saldata.cxx vcl/osx/salframe.cxx +vcl/osx/salgdiutils.cxx vcl/osx/salinst.cxx +vcl/osx/salmacos.cxx vcl/osx/salmenu.cxx vcl/osx/salnativewidgets.cxx vcl/osx/salobj.cxx @@ -14830,7 +14833,6 @@ vcl/quartz/ctfonts.cxx vcl/quartz/salbmp.cxx vcl/quartz/salgdi.cxx vcl/quartz/salgdicommon.cxx -vcl/quartz/salgdiutils.cxx vcl/quartz/salvd.cxx vcl/quartz/utils.cxx vcl/source/app/IconThemeInfo.cxx diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk index d937fceb0a69..51b45594f97f 100644 --- a/vcl/Library_vcl.mk +++ b/vcl/Library_vcl.mk @@ -685,6 +685,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\ vcl/ios/iosinst \ vcl/ios/dummies \ vcl/ios/clipboard \ + vcl/ios/salios \ vcl/ios/iOSTransferable \ vcl/ios/DataFlavorMapping \ vcl/ios/HtmlFmtFlt \ diff --git a/vcl/Library_vclplug_osx.mk b/vcl/Library_vclplug_osx.mk index f0d22298a0c8..9b82bd44c2a6 100644 --- a/vcl/Library_vclplug_osx.mk +++ b/vcl/Library_vclplug_osx.mk @@ -120,7 +120,9 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_osx,\ vcl/osx/documentfocuslistener \ vcl/osx/saldata \ vcl/osx/salframe \ + vcl/osx/salgdiutils \ vcl/osx/salinst \ + vcl/osx/salmacos \ vcl/osx/salmenu \ vcl/osx/salnativewidgets \ vcl/osx/salobj \ @@ -132,7 +134,6 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_osx,\ vcl/quartz/salbmp \ vcl/quartz/salgdi \ vcl/quartz/salgdicommon \ - vcl/quartz/salgdiutils \ vcl/quartz/salvd \ vcl/quartz/utils \ )) diff --git a/vcl/inc/quartz/salgdi.h b/vcl/inc/quartz/salgdi.h index eb3e7563c898..69b735787bdc 100644 --- a/vcl/inc/quartz/salgdi.h +++ b/vcl/inc/quartz/salgdi.h @@ -190,16 +190,16 @@ public: bool IsPenVisible() const { return maLineColor.IsVisible(); } bool IsBrushVisible() const { return maFillColor.IsVisible(); } - float GetWindowScaling(); - void SetWindowGraphics( AquaSalFrame* pFrame ); - void SetPrinterGraphics(CGContextRef, sal_Int32 nRealDPIX, sal_Int32 nRealDPIY); void SetVirDevGraphics(CGLayerHolder const &rLayer, CGContextRef, int nBitDepth = 0); #ifdef MACOSX void initResolution( NSWindow* ); void copyResolution( AquaSalGraphics& ); void updateResolution(); + float GetWindowScaling(); + void SetWindowGraphics( AquaSalFrame* pFrame ); bool IsWindowGraphics() const { return mbWindow; } + void SetPrinterGraphics(CGContextRef, sal_Int32 nRealDPIX, sal_Int32 nRealDPIY); AquaSalFrame* getGraphicsFrame() const { return mpFrame; } void setGraphicsFrame( AquaSalFrame* pFrame ) { mpFrame = pFrame; } #endif @@ -300,14 +300,12 @@ public: virtual bool drawAlphaRect( tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt8 nTransparency ) override; +#ifdef MACOSX + protected: - virtual void copyScaledArea( tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY, - tools::Long nSrcWidth, tools::Long nSrcHeight, SalGraphics* pSrcGraphics ); // native widget rendering methods that require mirroring -#ifdef MACOSX - virtual bool isNativeControlSupported( ControlType nType, ControlPart nPart ) override; virtual bool hitTestNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion, @@ -319,6 +317,8 @@ protected: const ImplControlValue& aValue, const OUString& aCaption, tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion ) override; + void copyScaledArea( tools::Long nDestX, tools::Long nDestY, tools::Long nSrcX, tools::Long nSrcY, + tools::Long nSrcWidth, tools::Long nSrcHeight, SalGraphics* pSrcGraphics ); #endif public: diff --git a/vcl/ios/salios.cxx b/vcl/ios/salios.cxx new file mode 100644 index 000000000000..625fcb049a09 --- /dev/null +++ b/vcl/ios/salios.cxx @@ -0,0 +1,443 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +// This file contains the iOS-specific versions of the functions which were touched in the commit to +// fix tdf#138122. The funtions are here (for now) as they were before that commit. The +// macOS-specific versions of these functions are in vcl/osx/salmacos.cxx. + +#include <sal/config.h> +#include <sal/log.hxx> +#include <osl/diagnose.h> + +#include <cstddef> +#include <limits> + +#include <o3tl/make_shared.hxx> +#include <basegfx/vector/b2ivector.hxx> +#include <tools/color.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/BitmapAccessMode.hxx> +#include <vcl/BitmapBuffer.hxx> +#include <vcl/BitmapColor.hxx> +#include <vcl/BitmapPalette.hxx> +#include <vcl/ColorMask.hxx> +#include <vcl/Scanline.hxx> + +#include <bitmap/bmpfast.hxx> + +#include <headless/svpframe.hxx> +#include <headless/svpinst.hxx> +#include <headless/svpvd.hxx> + +#include <quartz/salbmp.h> +#include <quartz/salgdi.h> +#include <quartz/salvd.h> +#include <quartz/utils.h> + +#include "saldatabasic.hxx" + +// From salbmp.cxx + +bool QuartzSalBitmap::Create(CGLayerHolder const & rLayerHolder, int nBitmapBits, int nX, int nY, int nWidth, int nHeight, bool bFlipped) +{ + SAL_WARN_IF(!rLayerHolder.isSet(), "vcl", "QuartzSalBitmap::Create() from non-layered context"); + + // sanitize input parameters + if( nX < 0 ) { + nWidth += nX; + nX = 0; + } + + if( nY < 0 ) { + nHeight += nY; + nY = 0; + } + + const CGSize aLayerSize = CGLayerGetSize(rLayerHolder.get()); + + if( nWidth >= static_cast<int>(aLayerSize.width) - nX ) + nWidth = static_cast<int>(aLayerSize.width) - nX; + + if( nHeight >= static_cast<int>(aLayerSize.height) - nY ) + nHeight = static_cast<int>(aLayerSize.height) - nY; + + if( (nWidth < 0) || (nHeight < 0) ) + nWidth = nHeight = 0; + + // initialize properties + mnWidth = nWidth; + mnHeight = nHeight; + mnBits = nBitmapBits ? nBitmapBits : 32; + + // initialize drawing context + CreateContext(); + + // copy layer content into the bitmap buffer + const CGPoint aSrcPoint = { static_cast<CGFloat>(-nX), static_cast<CGFloat>(-nY) }; + if (maGraphicContext.isSet()) // remove warning + { + if( bFlipped ) + { + CGContextTranslateCTM( maGraphicContext.get(), 0, +mnHeight ); + + CGContextScaleCTM( maGraphicContext.get(), +1, -1 ); + } + + CGContextDrawLayerAtPoint(maGraphicContext.get(), aSrcPoint, rLayerHolder.get()); + } + return true; +} + +// From salgdicommon.cxx + +void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGraphics ) +{ + + if( !pSrcGraphics ) + { + pSrcGraphics = this; + } + //from unix salgdi2.cxx + //[FIXME] find a better way to prevent calc from crashing when width and height are negative + if( rPosAry.mnSrcWidth <= 0 || + rPosAry.mnSrcHeight <= 0 || + rPosAry.mnDestWidth <= 0 || + rPosAry.mnDestHeight <= 0 ) + { + return; + } + + // If called from idle layout, maContextHolder.get() is NULL, no idea what to do + if (!maContextHolder.isSet()) + return; + + // accelerate trivial operations + /*const*/ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics); + const bool bSameGraphics = (this == pSrc); + + if( bSameGraphics && + (rPosAry.mnSrcWidth == rPosAry.mnDestWidth) && + (rPosAry.mnSrcHeight == rPosAry.mnDestHeight)) + { + // short circuit if there is nothing to do + if( (rPosAry.mnSrcX == rPosAry.mnDestX) && + (rPosAry.mnSrcY == rPosAry.mnDestY)) + { + return; + } + // use copyArea() if source and destination context are identical + copyArea( rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, false/*bWindowInvalidate*/ ); + return; + } + + ApplyXorContext(); + pSrc->ApplyXorContext(); + + SAL_WARN_IF (!pSrc->maLayer.isSet(), "vcl.quartz", + "AquaSalGraphics::copyBits() from non-layered graphics this=" << this); + + const CGPoint aDstPoint = CGPointMake(+rPosAry.mnDestX - rPosAry.mnSrcX, rPosAry.mnDestY - rPosAry.mnSrcY); + if ((rPosAry.mnSrcWidth == rPosAry.mnDestWidth && + rPosAry.mnSrcHeight == rPosAry.mnDestHeight) && + (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth) + && pSrc->maLayer.isSet()) // workaround for a Quartz crash + { + // in XOR mode the drawing context is redirected to the XOR mask + // if source and target are identical then copyBits() paints onto the target context though + CGContextHolder aCopyContext = maContextHolder; + if( mpXorEmulation && mpXorEmulation->IsEnabled() ) + { + if( pSrcGraphics == this ) + { + aCopyContext.set(mpXorEmulation->GetTargetContext()); + } + } + aCopyContext.saveState(); + + const CGRect aDstRect = CGRectMake(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnDestWidth, rPosAry.mnDestHeight); + CGContextClipToRect(aCopyContext.get(), aDstRect); + + // draw at new destination + // NOTE: flipped drawing gets disabled for this, else the subimage would be drawn upside down + if( pSrc->IsFlipped() ) + { + CGContextTranslateCTM( aCopyContext.get(), 0, +mnHeight ); + CGContextScaleCTM( aCopyContext.get(), +1, -1 ); + } + + // TODO: pSrc->size() != this->size() + CGContextDrawLayerAtPoint(aCopyContext.get(), aDstPoint, pSrc->maLayer.get()); + + aCopyContext.restoreState(); + // mark the destination rectangle as updated + RefreshRect( aDstRect ); + } + else + { + std::shared_ptr<SalBitmap> pBitmap = pSrc->getBitmap( rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight ); + if( pBitmap ) + { + SalTwoRect aPosAry( rPosAry ); + aPosAry.mnSrcX = 0; + aPosAry.mnSrcY = 0; + drawBitmap( aPosAry, *pBitmap ); + } + } +} + +void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY, + tools::Long nSrcWidth, tools::Long nSrcHeight, bool /*bWindowInvalidate*/) +{ + SAL_WARN_IF (!maLayer.isSet(), "vcl.quartz", + "AquaSalGraphics::copyArea() for non-layered graphics this=" << this); + + if (!maLayer.isSet()) + return; + + float fScale = maLayer.getScale(); + + tools::Long nScaledSourceX = nSrcX * fScale; + tools::Long nScaledSourceY = nSrcY * fScale; + + tools::Long nScaledTargetX = nDstX * fScale; + tools::Long nScaledTargetY = nDstY * fScale; + + tools::Long nScaledSourceWidth = nSrcWidth * fScale; + tools::Long nScaledSourceHeight = nSrcHeight * fScale; + + ApplyXorContext(); + + maContextHolder.saveState(); + + // in XOR mode the drawing context is redirected to the XOR mask + // copyArea() always works on the target context though + CGContextRef xCopyContext = maContextHolder.get(); + + if( mpXorEmulation && mpXorEmulation->IsEnabled() ) + { + xCopyContext = mpXorEmulation->GetTargetContext(); + } + + // If we have a scaled layer, we need to revert the scaling or else + // it will interfere with the coordinate calculation + CGContextScaleCTM(xCopyContext, 1.0 / fScale, 1.0 / fScale); + + // drawing a layer onto its own context causes trouble on OSX => copy it first + // TODO: is it possible to get rid of this unneeded copy more often? + // e.g. on OSX>=10.5 only this situation causes problems: + // mnBitmapDepth && (aDstPoint.x + pSrc->mnWidth) > mnWidth + + CGLayerHolder sSourceLayerHolder(maLayer); + { + const CGSize aSrcSize = CGSizeMake(nScaledSourceWidth, nScaledSourceHeight); + sSourceLayerHolder.set(CGLayerCreateWithContext(xCopyContext, aSrcSize, nullptr)); + + const CGContextRef xSrcContext = CGLayerGetContext(sSourceLayerHolder.get()); + + CGPoint aSrcPoint = CGPointMake(-nScaledSourceX, -nScaledSourceY); + if( IsFlipped() ) + { + CGContextTranslateCTM( xSrcContext, 0, +nScaledSourceHeight ); + CGContextScaleCTM( xSrcContext, +1, -1 ); + aSrcPoint.y = (nScaledSourceY + nScaledSourceHeight) - (mnHeight * fScale); + } + CGContextSetBlendMode(xSrcContext, kCGBlendModeCopy); + + CGContextDrawLayerAtPoint(xSrcContext, aSrcPoint, maLayer.get()); + } + + // draw at new destination + const CGRect aTargetRect = CGRectMake(nScaledTargetX, nScaledTargetY, nScaledSourceWidth, nScaledSourceHeight); + CGContextSetBlendMode(xCopyContext, kCGBlendModeCopy); + CGContextDrawLayerInRect(xCopyContext, aTargetRect, sSourceLayerHolder.get()); + + maContextHolder.restoreState(); + + // cleanup + if (sSourceLayerHolder.get() != maLayer.get()) + { + CGLayerRelease(sSourceLayerHolder.get()); + } + // mark the destination rectangle as updated + RefreshRect( nDstX, nDstY, nSrcWidth, nSrcHeight ); +} + +void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const & rLayer, CGContextRef xContext, + int nBitmapDepth) +{ + SAL_INFO( "vcl.quartz", "SetVirDevGraphics() this=" << this << " layer=" << rLayer.get() << " context=" << xContext ); + + mbPrinter = false; + mbVirDev = true; + + // set graphics properties + maLayer = rLayer; + maContextHolder.set(xContext); + + mnBitmapDepth = nBitmapDepth; + + mbForeignContext = xContext != NULL; + + // return early if the virdev is being destroyed + if( !xContext ) + return; + + // get new graphics properties + if (!maLayer.isSet()) + { + mnWidth = CGBitmapContextGetWidth( maContextHolder.get() ); + mnHeight = CGBitmapContextGetHeight( maContextHolder.get() ); + } + else + { + const CGSize aSize = CGLayerGetSize(maLayer.get()); + mnWidth = static_cast<int>(aSize.width); + mnHeight = static_cast<int>(aSize.height); + } + + // prepare graphics for drawing + const CGColorSpaceRef aCGColorSpace = GetSalData()->mxRGBSpace; + CGContextSetFillColorSpace( maContextHolder.get(), aCGColorSpace ); + CGContextSetStrokeColorSpace( maContextHolder.get(), aCGColorSpace ); + + // re-enable XorEmulation for the new context + if( mpXorEmulation ) + { + mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get()); + if( mpXorEmulation->IsEnabled() ) + { + maContextHolder.set(mpXorEmulation->GetMaskContext()); + } + } + + // initialize stack of CGContext states + maContextHolder.saveState(); + SetState(); +} + +/// From salvd.cxx + +void AquaSalVirtualDevice::Destroy() +{ + SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext ); + + if( mbForeignContext ) + { + // Do not delete mxContext that we have received from outside VCL + maLayer.set(nullptr); + return; + } + + if (maLayer.isSet()) + { + if( mpGraphics ) + { + mpGraphics->SetVirDevGraphics(nullptr, nullptr); + } + CGLayerRelease(maLayer.get()); + maLayer.set(nullptr); + } + + if (maBitmapContext.isSet()) + { + void* pRawData = CGBitmapContextGetData(maBitmapContext.get()); + std::free(pRawData); + CGContextRelease(maBitmapContext.get()); + maBitmapContext.set(nullptr); + } +} + +bool AquaSalVirtualDevice::SetSize( tools::Long nDX, tools::Long nDY ) +{ + SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << + " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); + + if( mbForeignContext ) + { + // Do not delete/resize mxContext that we have received from outside VCL + return true; + } + + if (maLayer.isSet()) + { + const CGSize aSize = CGLayerGetSize(maLayer.get()); + if( (nDX == aSize.width) && (nDY == aSize.height) ) + { + // Yay, we do not have to do anything :) + return true; + } + } + + Destroy(); + + mnWidth = nDX; + mnHeight = nDY; + + // create a CGLayer matching to the intended virdev usage + CGContextHolder xCGContextHolder; + if( mnBitmapDepth && (mnBitmapDepth < 16) ) + { + mnBitmapDepth = 8; // TODO: are 1bit vdevs worth it? + const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8; + + void* pRawData = std::malloc( nBytesPerRow * nDY ); + maBitmapContext.set(CGBitmapContextCreate( pRawData, nDX, nDY, + mnBitmapDepth, nBytesPerRow, + GetSalData()->mxGraySpace, kCGImageAlphaNone)); + xCGContextHolder = maBitmapContext; + } + else + { + if (!xCGContextHolder.isSet()) + { + // assert(Application::IsBitmapRendering()); + mnBitmapDepth = 32; + + const int nBytesPerRow = (mnBitmapDepth * nDX) / 8; + void* pRawData = std::malloc( nBytesPerRow * nDY ); + const int nFlags = kCGImageAlphaNoneSkipFirst | kCGImageByteOrder32Little; + maBitmapContext.set(CGBitmapContextCreate(pRawData, nDX, nDY, 8, nBytesPerRow, + GetSalData()->mxRGBSpace, nFlags)); + xCGContextHolder = maBitmapContext; + } + } + + SAL_WARN_IF(!xCGContextHolder.isSet(), "vcl.quartz", "No context"); + + const CGSize aNewSize = { static_cast<CGFloat>(nDX), static_cast<CGFloat>(nDY) }; + maLayer.set(CGLayerCreateWithContext(xCGContextHolder.get(), aNewSize, nullptr)); + + if (maLayer.isSet() && mpGraphics) + { + // get the matching Quartz context + CGContextRef xDrawContext = CGLayerGetContext( maLayer.get() ); + + // Here we pass the CGLayerRef that the CGLayerHolder maLayer holds as the first parameter + // to SetVirDevGraphics(). That parameter is of type CGLayerHolder, so what we actually pass + // is an implicitly constructed *separate* CGLayerHolder. Is that what we want? No idea. + // Possibly we could pass just maLayer as such? But doing that does not fix tdf#138122. + mpGraphics->SetVirDevGraphics(maLayer.get(), xDrawContext, mnBitmapDepth); + } + + return maLayer.isSet(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salgdiutils.cxx b/vcl/osx/salgdiutils.cxx index 01626d348999..01626d348999 100644 --- a/vcl/quartz/salgdiutils.cxx +++ b/vcl/osx/salgdiutils.cxx diff --git a/vcl/osx/salmacos.cxx b/vcl/osx/salmacos.cxx new file mode 100644 index 000000000000..7d4569d65bca --- /dev/null +++ b/vcl/osx/salmacos.cxx @@ -0,0 +1,387 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +// This file contains the macOS-specific versions of the functions which were touched in the commit +// to fix tdf#138122. The iOS-specific versions of these functions are kept (for now, when this +// comment is written) as they were before that commit in vcl/isx/salios.cxx. + +#include <sal/config.h> +#include <sal/log.hxx> +#include <osl/diagnose.h> + +#include <cstddef> +#include <limits> + +#include <o3tl/make_shared.hxx> +#include <basegfx/vector/b2ivector.hxx> +#include <tools/color.hxx> +#include <vcl/bitmap.hxx> +#include <vcl/BitmapAccessMode.hxx> +#include <vcl/BitmapBuffer.hxx> +#include <vcl/BitmapColor.hxx> +#include <vcl/BitmapPalette.hxx> +#include <vcl/ColorMask.hxx> +#include <vcl/Scanline.hxx> + +#include <bitmap/bmpfast.hxx> + +#include <quartz/salbmp.h> +#include <quartz/salgdi.h> +#include <quartz/salvd.h> +#include <quartz/utils.h> + +#include <osx/saldata.hxx> +#include <osx/salframe.h> +#include <osx/salinst.h> + +// From salbmp.cxx + +bool QuartzSalBitmap::Create(CGLayerHolder const & rLayerHolder, int nBitmapBits, int nX, int nY, int nWidth, int nHeight, bool bFlipped) +{ + + // TODO: Bitmaps from scaled layers are reverted to single precision. This is a workaround only unless bitmaps with precision of + // source layer are implemented. + + SAL_WARN_IF(!rLayerHolder.isSet(), "vcl", "QuartzSalBitmap::Create() from non-layered context"); + + // sanitize input parameters + if( nX < 0 ) { + nWidth += nX; + nX = 0; + } + + if( nY < 0 ) { + nHeight += nY; + nY = 0; + } + + CGSize aLayerSize = CGLayerGetSize(rLayerHolder.get()); + const float fScale = rLayerHolder.getScale(); + aLayerSize.width /= fScale; + aLayerSize.height /= fScale; + + if( nWidth >= static_cast<int>(aLayerSize.width) - nX ) + nWidth = static_cast<int>(aLayerSize.width) - nX; + + if( nHeight >= static_cast<int>(aLayerSize.height) - nY ) + nHeight = static_cast<int>(aLayerSize.height) - nY; + + if( (nWidth < 0) || (nHeight < 0) ) + nWidth = nHeight = 0; + + // initialize properties + mnWidth = nWidth; + mnHeight = nHeight; + mnBits = nBitmapBits ? nBitmapBits : 32; + + // initialize drawing context + CreateContext(); + + // copy layer content into the bitmap buffer + const CGPoint aSrcPoint = { static_cast<CGFloat>(-nX * fScale), static_cast<CGFloat>(-nY * fScale) }; + if (maGraphicContext.isSet()) + { + if( bFlipped ) + { + CGContextTranslateCTM(maGraphicContext.get(), 0, +mnHeight); + CGContextScaleCTM(maGraphicContext.get(), +1, -1); + } + maGraphicContext.saveState(); + CGContextScaleCTM(maGraphicContext.get(), 1 / fScale, 1 / fScale); + CGContextDrawLayerAtPoint(maGraphicContext.get(), aSrcPoint, rLayerHolder.get()); + maGraphicContext.restoreState(); + } + return true; +} + +// From salgdicommon.cxx + +void AquaSalGraphics::copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraphics) +{ + if (!pSrcGraphics) + pSrcGraphics = this; + AquaSalGraphics *pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics); + if (rPosAry.mnSrcWidth <= 0 || rPosAry.mnSrcHeight <= 0 || rPosAry.mnDestWidth <= 0 || rPosAry.mnDestHeight <= 0) + return; + if (!maContextHolder.isSet()) + return; + + SAL_WARN_IF (!pSrc->maLayer.isSet(), "vcl.quartz", "AquaSalGraphics::copyBits() from non-layered graphics this=" << this); + + // Layered graphics are copied by AquaSalGraphics::copyScaledArea() which is able to consider the layer's scaling. + + if (pSrc->maLayer.isSet()) + copyScaledArea(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, pSrcGraphics); + else + { + ApplyXorContext(); + pSrc->ApplyXorContext(); + std::shared_ptr<SalBitmap> pBitmap = pSrc->getBitmap(rPosAry.mnSrcX, rPosAry.mnSrcY, + rPosAry.mnSrcWidth, rPosAry.mnSrcHeight); + if (pBitmap) + { + SalTwoRect aPosAry(rPosAry); + aPosAry.mnSrcX = 0; + aPosAry.mnSrcY = 0; + drawBitmap(aPosAry, *pBitmap); + } + } +} + +void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY, + tools::Long nSrcWidth, tools::Long nSrcHeight, bool) +{ + if (!maContextHolder.isSet()) + return; + + // Functionality is implemented in protected member function AquaSalGraphics::copyScaledArea() which requires an additional + // parameter of type SalGraphics to be used in AquaSalGraphics::copyBits() too. + + copyScaledArea(nDstX, nDstY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, this); +} + +void AquaSalGraphics::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY, + tools::Long nSrcWidth, tools::Long nSrcHeight, SalGraphics *pSrcGraphics) +{ + if (!pSrcGraphics) + pSrcGraphics = this; + AquaSalGraphics *pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics); + + SAL_WARN_IF(!maLayer.isSet(), "vcl.quartz", + "AquaSalGraphics::copyScaledArea() without graphics context or for non-layered graphics this=" << this); + + if (!maContextHolder.isSet() || !maLayer.isSet()) + return; + + // Determine scaled geometry of source and target area assuming source and target area have the same scale + + float fScale = maLayer.getScale(); + CGFloat nScaledSourceX = nSrcX * fScale; + CGFloat nScaledSourceY = nSrcY * fScale; + CGFloat nScaledTargetX = nDstX * fScale; + CGFloat nScaledTargetY = nDstY * fScale; + CGFloat nScaledSourceWidth = nSrcWidth * fScale; + CGFloat nScaledSourceHeight = nSrcHeight * fScale; + + // Apply XOR context and get copy context from current graphics context or XOR context + + ApplyXorContext(); + maContextHolder.saveState(); + CGContextRef xCopyContext = maContextHolder.get(); + if (mpXorEmulation && mpXorEmulation->IsEnabled()) + xCopyContext = mpXorEmulation->GetTargetContext(); + + // Set scale matrix of copy context to consider layer scaling + + CGContextScaleCTM(xCopyContext, 1 / fScale, 1 / fScale); + + // Creating an additional layer is required for drawing with the required scale and extent at the drawing destination + // thereafter. + + CGLayerHolder aSourceLayerHolder(pSrc->maLayer); + const CGSize aSourceSize = CGSizeMake(nScaledSourceWidth, nScaledSourceHeight); + aSourceLayerHolder.set(CGLayerCreateWithContext(xCopyContext, aSourceSize, nullptr)); + const CGContextRef xSourceContext = CGLayerGetContext(aSourceLayerHolder.get()); + CGPoint aSrcPoint = CGPointMake(-nScaledSourceX, -nScaledSourceY); + if (pSrc->IsFlipped()) + { + CGContextTranslateCTM(xSourceContext, 0, nScaledSourceHeight); + CGContextScaleCTM(xSourceContext, 1, -1); + aSrcPoint.y = nScaledSourceY + nScaledSourceHeight - mnHeight * fScale; + } + CGContextSetBlendMode(xSourceContext, kCGBlendModeCopy); + CGContextDrawLayerAtPoint(xSourceContext, aSrcPoint, pSrc->maLayer.get()); + + // Copy source area from additional layer to traget area + + const CGRect aTargetRect = CGRectMake(nScaledTargetX, nScaledTargetY, nScaledSourceWidth, nScaledSourceHeight); + CGContextSetBlendMode(xCopyContext, kCGBlendModeCopy); + CGContextDrawLayerInRect(xCopyContext, aTargetRect, aSourceLayerHolder.get()); + + // Housekeeping on exit + + maContextHolder.restoreState(); + if (aSourceLayerHolder.get() != maLayer.get()) + CGLayerRelease(aSourceLayerHolder.get()); + RefreshRect(nDstX, nDstY, nSrcWidth, nSrcHeight); +} + +void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const &rLayer, CGContextRef xContext, int nBitmapDepth) +{ + SAL_INFO("vcl.quartz", "SetVirDevGraphics() this=" << this << " layer=" << rLayer.get() << " context=" << xContext); + + // Set member variables + + InvalidateContext(); + mbWindow = false; + mbPrinter = false; + mbVirDev = true; + maLayer = rLayer; + mnBitmapDepth = nBitmapDepth; + + // Get size and scale from layer if set else from bitmap and AquaSalGraphics::GetWindowScaling(), which is used to determine + // scaling for direct graphics output too + + CGSize aSize; + float fScale; + if (maLayer.isSet()) + { + maContextHolder.set(CGLayerGetContext(maLayer.get())); + aSize = CGLayerGetSize(maLayer.get()); + fScale = maLayer.getScale(); + } + else + { + maContextHolder.set(xContext); + if (!xContext) + return; + aSize.width = CGBitmapContextGetWidth(xContext); + aSize.height = CGBitmapContextGetHeight(xContext); + fScale = GetWindowScaling(); + } + mnWidth = aSize.width / fScale; + mnHeight = aSize.height / fScale; + + // Set color space for fill and stroke + + CGColorSpaceRef aColorSpace = GetSalData()->mxRGBSpace; + CGContextSetFillColorSpace(maContextHolder.get(), aColorSpace); + CGContextSetStrokeColorSpace(maContextHolder.get(), aColorSpace); + + // Apply scale matrix to virtual device graphics + + CGContextScaleCTM(maContextHolder.get(), fScale, fScale); + + // Apply XOR emulation if required + + if (mpXorEmulation) + { + mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get()); + if (mpXorEmulation->IsEnabled()) + maContextHolder.set(mpXorEmulation->GetMaskContext()); + } + + // Housekeeping on exit + + maContextHolder.saveState(); + SetState(); + + SAL_INFO("vcl.quartz", "SetVirDevGraphics() this=" << this << + " (" << mnWidth << "x" << mnHeight << ") fScale=" << fScale << " mnBitmapDepth=" << mnBitmapDepth); +} + +// From salvd.cxx + +void AquaSalVirtualDevice::Destroy() +{ + SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext ); + + if( mbForeignContext ) + { + // Do not delete mxContext that we have received from outside VCL + maLayer.set(nullptr); + return; + } + + if (maLayer.isSet()) + { + if( mpGraphics ) + { + mpGraphics->SetVirDevGraphics(nullptr, nullptr); + } + CGLayerRelease(maLayer.get()); + maLayer.set(nullptr); + } + + if (maBitmapContext.isSet()) + { + CGContextRelease(maBitmapContext.get()); + maBitmapContext.set(nullptr); + } +} + +bool AquaSalVirtualDevice::SetSize(tools::Long nDX, tools::Long nDY) +{ + SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << + " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); + + // Do not delete/resize graphics context if it has been received from outside VCL + + if (mbForeignContext) + return true; + + // Do not delete/resize graphics context if no change of geometry has been requested + + float fScale; + if (maLayer.isSet()) + { + fScale = maLayer.getScale(); + const CGSize aSize = CGLayerGetSize(maLayer.get()); + if ((nDX == aSize.width / fScale) && (nDY == aSize.height / fScale)) + return true; + } + + // Destroy graphics context if change of geometry has been requested + + Destroy(); + + // Prepare new graphics context for initialization, use scaling independent of prior graphics context calculated by + // AquaSalGraphics::GetWindowScaling(), which is used to determine scaling for direct graphics output too + + mnWidth = nDX; + mnHeight = nDY; + fScale = mpGraphics->GetWindowScaling(); + CGColorSpaceRef aColorSpace; + uint32_t nFlags; + if (mnBitmapDepth && (mnBitmapDepth < 16)) + { + mnBitmapDepth = 8; + aColorSpace = GetSalData()->mxGraySpace; + nFlags = kCGImageAlphaNone; + } + else + { + mnBitmapDepth = 32; + aColorSpace = GetSalData()->mxRGBSpace; + + nFlags = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; + } + + // Allocate buffer for virtual device graphics as bitmap context to store graphics with highest required (scaled) resolution + + size_t nScaledWidth = mnWidth * fScale; + size_t nScaledHeight = mnHeight * fScale; + size_t nBytesPerRow = mnBitmapDepth * nScaledWidth / 8; + maBitmapContext.set(CGBitmapContextCreate(nullptr, nScaledWidth, nScaledHeight, 8, nBytesPerRow, aColorSpace, nFlags)); + + SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << + " fScale=" << fScale << " mnBitmapDepth=" << mnBitmapDepth); + + CGSize aLayerSize = { static_cast<CGFloat>(nScaledWidth), static_cast<CGFloat>(nScaledHeight) }; + maLayer.set(CGLayerCreateWithContext(maBitmapContext.get(), aLayerSize, nullptr)); + maLayer.setScale(fScale); + mpGraphics->SetVirDevGraphics(maLayer, CGLayerGetContext(maLayer.get()), mnBitmapDepth); + + SAL_WARN_IF(!maBitmapContext.isSet(), "vcl.quartz", "No context"); + + return maLayer.isSet(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx index cf1f26648b7f..a1570dd04ffb 100644 --- a/vcl/quartz/salbmp.cxx +++ b/vcl/quartz/salbmp.cxx @@ -69,64 +69,6 @@ QuartzSalBitmap::~QuartzSalBitmap() doDestroy(); } -bool QuartzSalBitmap::Create(CGLayerHolder const & rLayerHolder, int nBitmapBits, int nX, int nY, int nWidth, int nHeight, bool bFlipped) -{ - - // TODO: Bitmaps from scaled layers are reverted to single precision. This is a workaround only unless bitmaps with precision of - // source layer are implemented. - - SAL_WARN_IF(!rLayerHolder.isSet(), "vcl", "QuartzSalBitmap::Create() from non-layered context"); - - // sanitize input parameters - if( nX < 0 ) { - nWidth += nX; - nX = 0; - } - - if( nY < 0 ) { - nHeight += nY; - nY = 0; - } - - CGSize aLayerSize = CGLayerGetSize(rLayerHolder.get()); - const float fScale = rLayerHolder.getScale(); - aLayerSize.width /= fScale; - aLayerSize.height /= fScale; - - if( nWidth >= static_cast<int>(aLayerSize.width) - nX ) - nWidth = static_cast<int>(aLayerSize.width) - nX; - - if( nHeight >= static_cast<int>(aLayerSize.height) - nY ) - nHeight = static_cast<int>(aLayerSize.height) - nY; - - if( (nWidth < 0) || (nHeight < 0) ) - nWidth = nHeight = 0; - - // initialize properties - mnWidth = nWidth; - mnHeight = nHeight; - mnBits = nBitmapBits ? nBitmapBits : 32; - - // initialize drawing context - CreateContext(); - - // copy layer content into the bitmap buffer - const CGPoint aSrcPoint = { static_cast<CGFloat>(-nX * fScale), static_cast<CGFloat>(-nY * fScale) }; - if (maGraphicContext.isSet()) - { - if( bFlipped ) - { - CGContextTranslateCTM(maGraphicContext.get(), 0, +mnHeight); - CGContextScaleCTM(maGraphicContext.get(), +1, -1); - } - maGraphicContext.saveState(); - CGContextScaleCTM(maGraphicContext.get(), 1 / fScale, 1 / fScale); - CGContextDrawLayerAtPoint(maGraphicContext.get(), aSrcPoint, rLayerHolder.get()); - maGraphicContext.restoreState(); - } - return true; -} - bool QuartzSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette ) { if( !isValidBitCount( nBits ) ) diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx index 0597fe3d021d..33ffc43741a1 100644 --- a/vcl/quartz/salgdicommon.cxx +++ b/vcl/quartz/salgdicommon.cxx @@ -267,117 +267,6 @@ void AquaSalGraphics::ApplyXorContext() } } -void AquaSalGraphics::copyBits(const SalTwoRect &rPosAry, SalGraphics *pSrcGraphics) -{ - if (!pSrcGraphics) - pSrcGraphics = this; - AquaSalGraphics *pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics); - if (rPosAry.mnSrcWidth <= 0 || rPosAry.mnSrcHeight <= 0 || rPosAry.mnDestWidth <= 0 || rPosAry.mnDestHeight <= 0) - return; - if (!maContextHolder.isSet()) - return; - - SAL_WARN_IF (!pSrc->maLayer.isSet(), "vcl.quartz", "AquaSalGraphics::copyBits() from non-layered graphics this=" << this); - - // Layered graphics are copied by AquaSalGraphics::copyScaledArea() which is able to consider the layer's scaling. - - if (pSrc->maLayer.isSet()) - copyScaledArea(rPosAry.mnDestX, rPosAry.mnDestY, rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight, pSrcGraphics); - else - { - ApplyXorContext(); - pSrc->ApplyXorContext(); - std::shared_ptr<SalBitmap> pBitmap = pSrc->getBitmap(rPosAry.mnSrcX, rPosAry.mnSrcY, - rPosAry.mnSrcWidth, rPosAry.mnSrcHeight); - if (pBitmap) - { - SalTwoRect aPosAry(rPosAry); - aPosAry.mnSrcX = 0; - aPosAry.mnSrcY = 0; - drawBitmap(aPosAry, *pBitmap); - } - } -} - -void AquaSalGraphics::copyArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY, - tools::Long nSrcWidth, tools::Long nSrcHeight, bool) -{ - if (!maContextHolder.isSet()) - return; - - // Functionality is implemented in protected member function AquaSalGraphics::copyScaledArea() which requires an additional - // parameter of type SalGraphics to be used in AquaSalGraphics::copyBits() too. - - copyScaledArea(nDstX, nDstY, nSrcX, nSrcY, nSrcWidth, nSrcHeight, this); -} - -void AquaSalGraphics::copyScaledArea(tools::Long nDstX, tools::Long nDstY,tools::Long nSrcX, tools::Long nSrcY, - tools::Long nSrcWidth, tools::Long nSrcHeight, SalGraphics *pSrcGraphics) -{ - if (!pSrcGraphics) - pSrcGraphics = this; - AquaSalGraphics *pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics); - - SAL_WARN_IF(!maLayer.isSet(), "vcl.quartz", - "AquaSalGraphics::copyScaledArea() without graphics context or for non-layered graphics this=" << this); - - if (!maContextHolder.isSet() || !maLayer.isSet()) - return; - - // Determine scaled geometry of source and target area assuming source and target area have the same scale - - float fScale = maLayer.getScale(); - CGFloat nScaledSourceX = nSrcX * fScale; - CGFloat nScaledSourceY = nSrcY * fScale; - CGFloat nScaledTargetX = nDstX * fScale; - CGFloat nScaledTargetY = nDstY * fScale; - CGFloat nScaledSourceWidth = nSrcWidth * fScale; - CGFloat nScaledSourceHeight = nSrcHeight * fScale; - - // Apply XOR context and get copy context from current graphics context or XOR context - - ApplyXorContext(); - maContextHolder.saveState(); - CGContextRef xCopyContext = maContextHolder.get(); - if (mpXorEmulation && mpXorEmulation->IsEnabled()) - xCopyContext = mpXorEmulation->GetTargetContext(); - - // Set scale matrix of copy context to consider layer scaling - - CGContextScaleCTM(xCopyContext, 1 / fScale, 1 / fScale); - - // Creating an additional layer is required for drawing with the required scale and extent at the drawing destination - // thereafter. - - CGLayerHolder aSourceLayerHolder(pSrc->maLayer); - const CGSize aSourceSize = CGSizeMake(nScaledSourceWidth, nScaledSourceHeight); - aSourceLayerHolder.set(CGLayerCreateWithContext(xCopyContext, aSourceSize, nullptr)); - const CGContextRef xSourceContext = CGLayerGetContext(aSourceLayerHolder.get()); - CGPoint aSrcPoint = CGPointMake(-nScaledSourceX, -nScaledSourceY); - if (pSrc->IsFlipped()) - { - CGContextTranslateCTM(xSourceContext, 0, nScaledSourceHeight); - CGContextScaleCTM(xSourceContext, 1, -1); - aSrcPoint.y = nScaledSourceY + nScaledSourceHeight - mnHeight * fScale; - } - CGContextSetBlendMode(xSourceContext, kCGBlendModeCopy); - CGContextDrawLayerAtPoint(xSourceContext, aSrcPoint, pSrc->maLayer.get()); - - // Copy source area from additional layer to traget area - - const CGRect aTargetRect = CGRectMake(nScaledTargetX, nScaledTargetY, nScaledSourceWidth, nScaledSourceHeight); - CGContextSetBlendMode(xCopyContext, kCGBlendModeCopy); - CGContextDrawLayerInRect(xCopyContext, aTargetRect, aSourceLayerHolder.get()); - - // Housekeeping on exit - - maContextHolder.restoreState(); - if (aSourceLayerHolder.get() != maLayer.get()) - CGLayerRelease(aSourceLayerHolder.get()); - RefreshRect(nDstX, nDstY, nSrcWidth, nSrcHeight); -} - #ifndef IOS void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics ) @@ -1826,74 +1715,4 @@ bool XorEmulation::UpdateTarget() return true; } -void AquaSalGraphics::SetVirDevGraphics(CGLayerHolder const &rLayer, CGContextRef xContext, int nBitmapDepth) -{ - SAL_INFO("vcl.quartz", "SetVirDevGraphics() this=" << this << " layer=" << rLayer.get() << " context=" << xContext); - - // Set member variables - - InvalidateContext(); - mbWindow = false; - mbPrinter = false; - mbVirDev = true; - maLayer = rLayer; - mnBitmapDepth = nBitmapDepth; - -#ifdef IOS - - mbForeignContext = xContext != NULL; - -#endif - - // Get size and scale from layer if set else from bitmap and AquaSalGraphics::GetWindowScaling(), which is used to determine - // scaling for direct graphics output too - - CGSize aSize; - float fScale; - if (maLayer.isSet()) - { - maContextHolder.set(CGLayerGetContext(maLayer.get())); - aSize = CGLayerGetSize(maLayer.get()); - fScale = maLayer.getScale(); - } - else - { - maContextHolder.set(xContext); - if (!xContext) - return; - aSize.width = CGBitmapContextGetWidth(xContext); - aSize.height = CGBitmapContextGetHeight(xContext); - fScale = GetWindowScaling(); - } - mnWidth = aSize.width / fScale; - mnHeight = aSize.height / fScale; - - // Set color space for fill and stroke - - CGColorSpaceRef aColorSpace = GetSalData()->mxRGBSpace; - CGContextSetFillColorSpace(maContextHolder.get(), aColorSpace); - CGContextSetStrokeColorSpace(maContextHolder.get(), aColorSpace); - - // Apply scale matrix to virtual device graphics - - CGContextScaleCTM(maContextHolder.get(), fScale, fScale); - - // Apply XOR emulation if required - - if (mpXorEmulation) - { - mpXorEmulation->SetTarget(mnWidth, mnHeight, mnBitmapDepth, maContextHolder.get(), maLayer.get()); - if (mpXorEmulation->IsEnabled()) - maContextHolder.set(mpXorEmulation->GetMaskContext()); - } - - // Housekeeping on exit - - maContextHolder.saveState(); - SetState(); - - SAL_INFO("vcl.quartz", "SetVirDevGraphics() this=" << this << - " (" << mnWidth << "x" << mnHeight << ") fScale=" << fScale << " mnBitmapDepth=" << mnBitmapDepth); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/quartz/salvd.cxx b/vcl/quartz/salvd.cxx index 5d7facd3ef38..9f6bfdd930aa 100644 --- a/vcl/quartz/salvd.cxx +++ b/vcl/quartz/salvd.cxx @@ -161,34 +161,6 @@ AquaSalVirtualDevice::~AquaSalVirtualDevice() Destroy(); } -void AquaSalVirtualDevice::Destroy() -{ - SAL_INFO( "vcl.virdev", "AquaSalVirtualDevice::Destroy() this=" << this << " mbForeignContext=" << mbForeignContext ); - - if( mbForeignContext ) - { - // Do not delete mxContext that we have received from outside VCL - maLayer.set(nullptr); - return; - } - - if (maLayer.isSet()) - { - if( mpGraphics ) - { - mpGraphics->SetVirDevGraphics(nullptr, nullptr); - } - CGLayerRelease(maLayer.get()); - maLayer.set(nullptr); - } - - if (maBitmapContext.isSet()) - { - CGContextRelease(maBitmapContext.get()); - maBitmapContext.set(nullptr); - } -} - SalGraphics* AquaSalVirtualDevice::AcquireGraphics() { if( mbGraphicsUsed || !mpGraphics ) @@ -204,80 +176,4 @@ void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* ) mbGraphicsUsed = false; } -bool AquaSalVirtualDevice::SetSize(tools::Long nDX, tools::Long nDY) -{ - SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << - " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO")); - - // Do not delete/resize graphics context if it has been received from outside VCL - - if (mbForeignContext) - return true; - - // Do not delete/resize graphics context if no change of geometry has been requested - - float fScale; - if (maLayer.isSet()) - { - fScale = maLayer.getScale(); - const CGSize aSize = CGLayerGetSize(maLayer.get()); - if ((nDX == aSize.width / fScale) && (nDY == aSize.height / fScale)) - return true; - } - - // Destroy graphics context if change of geometry has been requested - - Destroy(); - - // Prepare new graphics context for initialization, use scaling independent of prior graphics context calculated by - // AquaSalGraphics::GetWindowScaling(), which is used to determine scaling for direct graphics output too - - mnWidth = nDX; - mnHeight = nDY; - fScale = mpGraphics->GetWindowScaling(); - CGColorSpaceRef aColorSpace; - uint32_t nFlags; - if (mnBitmapDepth && (mnBitmapDepth < 16)) - { - mnBitmapDepth = 8; - aColorSpace = GetSalData()->mxGraySpace; - nFlags = kCGImageAlphaNone; - } - else - { - mnBitmapDepth = 32; - aColorSpace = GetSalData()->mxRGBSpace; - -#ifdef MACOSX - - nFlags = kCGImageAlphaNoneSkipFirst | kCGBitmapByteOrder32Host; - -#else - - nFlags = kCGImageAlphaNoneSkipFirst | kCGImageByteOrder32Little; - -#endif - - } - - // Allocate buffer for virtual device graphics as bitmap context to store graphics with highest required (scaled) resolution - - size_t nScaledWidth = mnWidth * fScale; - size_t nScaledHeight = mnHeight * fScale; - size_t nBytesPerRow = mnBitmapDepth * nScaledWidth / 8; - maBitmapContext.set(CGBitmapContextCreate(nullptr, nScaledWidth, nScaledHeight, 8, nBytesPerRow, aColorSpace, nFlags)); - - SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::SetSize() this=" << this << - " fScale=" << fScale << " mnBitmapDepth=" << mnBitmapDepth); - - CGSize aLayerSize = { static_cast<CGFloat>(nScaledWidth), static_cast<CGFloat>(nScaledHeight) }; - maLayer.set(CGLayerCreateWithContext(maBitmapContext.get(), aLayerSize, nullptr)); - maLayer.setScale(fScale); - mpGraphics->SetVirDevGraphics(maLayer, CGLayerGetContext(maLayer.get()), mnBitmapDepth); - - SAL_WARN_IF(!maBitmapContext.isSet(), "vcl.quartz", "No context"); - - return maLayer.isSet(); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |