summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/Executable_soffice_bin.mk13
-rw-r--r--solenv/clang-format/blacklist4
-rw-r--r--vcl/Library_vcl.mk1
-rw-r--r--vcl/Library_vclplug_osx.mk3
-rw-r--r--vcl/inc/quartz/salgdi.h15
-rw-r--r--vcl/ios/salios.cxx433
-rw-r--r--vcl/osx/salgdiutils.cxx (renamed from vcl/quartz/salgdiutils.cxx)41
-rw-r--r--vcl/osx/salinst.cxx15
-rw-r--r--vcl/osx/salmacos.cxx383
-rw-r--r--vcl/quartz/salbmp.cxx50
-rw-r--r--vcl/quartz/salgdi.cxx8
-rw-r--r--vcl/quartz/salgdicommon.cxx236
-rw-r--r--vcl/quartz/salvd.cxx133
13 files changed, 894 insertions, 441 deletions
diff --git a/desktop/Executable_soffice_bin.mk b/desktop/Executable_soffice_bin.mk
index ecf75893ab96..cabd31af29f2 100644
--- a/desktop/Executable_soffice_bin.mk
+++ b/desktop/Executable_soffice_bin.mk
@@ -31,19 +31,6 @@ $(eval $(call gb_Executable_set_ldflags,\
endif
-ifeq ($(OS)-$(HAVE_MACOS_LD_PLATFORMVERSION),MACOSX-TRUE)
-# At least when building against SDK 10.15, changing the LC_VERSION_MIN_MACOSX load command's sdk
-# value from 10.15 to "n/a" (i.e., 0.0.0) is necessary to avoid blurry text in the LO UI (see
-# <https://github.com/llvm/llvm-project/commit/25ce33a6e4f3b13732c0f851e68390dc2acb9123>
-# "[driver][darwin] Pass -platform_version flag to the linker instead of the
-# -<platform>_version_min flag", clang/test/Driver/darwin-ld-platform-version-macos.c in particular,
-# for the -platform_version that Clang passes by default to new-enough ld):
-$(eval $(call gb_Executable_add_ldflags,soffice_bin, \
- -Xlinker -platform_version -Xlinker macos -Xlinker $(MAC_OS_X_VERSION_MIN_REQUIRED_DOTS) \
- -Xlinker 0.0.0 \
-))
-endif
-
ifeq ($(OS),WNT)
$(eval $(call gb_Executable_set_targettype_gui,soffice_bin,NO))
diff --git a/solenv/clang-format/blacklist b/solenv/clang-format/blacklist
index 521ff3e43683..864518c389e4 100644
--- a/solenv/clang-format/blacklist
+++ b/solenv/clang-format/blacklist
@@ -17554,6 +17554,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/opengl/DeviceInfo.cxx
vcl/opengl/FixedTextureAtlas.cxx
@@ -17623,7 +17624,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
@@ -17656,7 +17659,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/ITiledRenderable.cxx
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 9afdac80ef86..15a083df19a6 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -671,6 +671,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 b1170cca2b83..e21c286f87ec 100644
--- a/vcl/Library_vclplug_osx.mk
+++ b/vcl/Library_vclplug_osx.mk
@@ -124,7 +124,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 \
@@ -136,7 +138,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 433fce10f029..aac4e140f5f9 100644
--- a/vcl/inc/quartz/salgdi.h
+++ b/vcl/inc/quartz/salgdi.h
@@ -172,6 +172,7 @@ class AquaSalGraphics : public SalGraphics
#ifdef MACOSX
/// is this a window graphics
bool mbWindow;
+ bool mbWindowScaling;
#else // IOS
@@ -187,15 +188,16 @@ public:
bool IsPenVisible() const { return maLineColor.IsVisible(); }
bool IsBrushVisible() const { return maFillColor.IsVisible(); }
- void SetWindowGraphics( AquaSalFrame* pFrame );
- void SetPrinterGraphics( CGContextRef, long nRealDPIX, long 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, long nRealDPIX, long nRealDPIY);
AquaSalFrame* getGraphicsFrame() const { return mpFrame; }
void setGraphicsFrame( AquaSalFrame* pFrame ) { mpFrame = pFrame; }
#endif
@@ -294,9 +296,12 @@ public:
virtual bool drawAlphaRect( long nX, long nY, long nWidth,
long nHeight, sal_uInt8 nTransparency ) override;
- // native widget rendering methods that require mirroring
#ifdef MACOSX
+
protected:
+
+ // native widget rendering methods that require mirroring
+
virtual bool isNativeControlSupported( ControlType nType, ControlPart nPart ) override;
virtual bool hitTestNativeControl( ControlType nType, ControlPart nPart, const tools::Rectangle& rControlRegion,
@@ -308,9 +313,11 @@ protected:
const ImplControlValue& aValue, const OUString& aCaption,
tools::Rectangle &rNativeBoundingRegion, tools::Rectangle &rNativeContentRegion ) override;
-public:
+ void copyScaledArea( long nDestX, long nDestY, long nSrcX, long nSrcY,
+ long nSrcWidth, long nSrcHeight, SalGraphics* pSrcGraphics );
#endif
+public:
// get device resolution
virtual void GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY ) override;
// get the depth of the device
diff --git a/vcl/ios/salios.cxx b/vcl/ios/salios.cxx
new file mode 100644
index 000000000000..fc972909cdd2
--- /dev/null
+++ b/vcl/ios/salios.cxx
@@ -0,0 +1,433 @@
+/* -*- 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 <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( long nDstX, long nDstY,long nSrcX, long nSrcY,
+ long nSrcWidth, 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();
+
+ long nScaledSourceX = nSrcX * fScale;
+ long nScaledSourceY = nSrcY * fScale;
+
+ long nScaledTargetX = nDstX * fScale;
+ long nScaledTargetY = nDstY * fScale;
+
+ long nScaledSourceWidth = nSrcWidth * fScale;
+ 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);
+ }
+ CGContextDrawLayerAtPoint(xSrcContext, aSrcPoint, maLayer.get());
+ }
+
+ // draw at new destination
+ const CGRect aTargetRect = CGRectMake(nScaledTargetX, nScaledTargetY, nScaledSourceWidth, nScaledSourceHeight);
+ 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( long nDX, 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 Quartz layer 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() );
+ 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 426aea29dc78..abd90deaa84b 100644
--- a/vcl/quartz/salgdiutils.cxx
+++ b/vcl/osx/salgdiutils.cxx
@@ -32,6 +32,39 @@
#include <osx/salframe.h>
#include <osx/saldata.hxx>
+float AquaSalGraphics::GetWindowScaling()
+{
+ float fScale = 1.0f;
+
+#ifdef MACOSX
+
+ // Window scaling independent from main display may be forced by setting VCL_MACOS_FORCE_WINDOW_SCALING environment variable
+ // whose setting is stored in mbWindowScaling. After implementation of full support of scaled displays window scaling will be
+ // set to 2.0f for macOS as default. This will allow moving of windows between non retina and retina displays without blurry
+ // text and graphics.
+
+ // TODO: After implementation of full support of scaled displays code has to be modified to set a scaling of 2.0f as default.
+
+ if (mbWindowScaling)
+ {
+ fScale = 2.0f;
+ return fScale;
+ }
+
+#endif
+
+ AquaSalFrame *pSalFrame = mpFrame;
+ if (!pSalFrame)
+ pSalFrame = static_cast<AquaSalFrame *>(GetSalData()->mpInstance->anyFrame());
+ if (pSalFrame)
+ {
+ NSWindow *pNSWindow = pSalFrame->getNSWindow();
+ if (pNSWindow)
+ fScale = [pNSWindow backingScaleFactor];
+ }
+ return fScale;
+}
+
void AquaSalGraphics::SetWindowGraphics( AquaSalFrame* pFrame )
{
mpFrame = pFrame;
@@ -96,13 +129,7 @@ bool AquaSalGraphics::CheckContext()
{
const unsigned int nWidth = mpFrame->maGeometry.nWidth;
const unsigned int nHeight = mpFrame->maGeometry.nHeight;
-
- // Let's get the window scaling factor if possible, or use 1.0
- // as the scaling factor.
- float fScale = 1.0f;
- if (mpFrame->getNSWindow())
- fScale = [mpFrame->getNSWindow() backingScaleFactor];
-
+ const float fScale = GetWindowScaling();
CGLayerRef rReleaseLayer = nullptr;
// check if a new drawing context is needed (e.g. after a resize)
diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 45f9ba3546f3..a524f24f0293 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -310,6 +310,21 @@ VCLPLUG_OSX_PUBLIC SalInstance* create_SalInstance()
// put cocoa into multithreaded mode
[NSThread detachNewThreadSelector:@selector(enableCocoaThreads:) toTarget:[[CocoaThreadEnabler alloc] init] withObject:nil];
+ // Dark mode is disabled as long as it is not implemented completely. For development purposes, it may be controlled by
+ // environment variables: VCL_MACOS_FORCE_DARK_MODE enable dark mode independent of system settings,
+ // VCL_MACOS_USE_SYSTEM_APPEARANCE to use system settings (light mode oder dark mode as configured within system preferences).
+
+ // TODO: After implementation of dark mode, this code has to be removed.
+
+ if (getenv("VCL_MACOS_FORCE_DARK_MODE"))
+ {
+ if (@available(macOS 10.14, iOS 13, *))
+ [NSApp setAppearance: [NSAppearance appearanceNamed: NSAppearanceNameDarkAqua]];
+ }
+ else
+ if (!getenv("VCL_MACOS_USE_SYSTEM_APPEARANCE"))
+ [NSApp setAppearance: [NSAppearance appearanceNamed: NSAppearanceNameAqua]];
+
// activate our delegate methods
[NSApp setDelegate: NSApp];
diff --git a/vcl/osx/salmacos.cxx b/vcl/osx/salmacos.cxx
new file mode 100644
index 000000000000..14ced4b96afe
--- /dev/null
+++ b/vcl/osx/salmacos.cxx
@@ -0,0 +1,383 @@
+/* -*- 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 <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(long nDstX, long nDstY, long nSrcX, long nSrcY,
+ long nSrcWidth, 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(long nDstX, long nDstY, long nSrcX, long nSrcY,
+ long nSrcWidth, 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);
+ 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(long nDX, 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 117c038c844e..ea248d9763d9 100644
--- a/vcl/quartz/salbmp.cxx
+++ b/vcl/quartz/salbmp.cxx
@@ -69,56 +69,6 @@ QuartzSalBitmap::~QuartzSalBitmap()
doDestroy();
}
-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;
-}
-
bool QuartzSalBitmap::Create( const Size& rSize, sal_uInt16 nBits, const BitmapPalette& rBitmapPalette )
{
if( !isValidBitCount( nBits ) )
diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index b6df53319e28..db272df57587 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -200,6 +200,14 @@ AquaSalGraphics::AquaSalGraphics()
, mbVirDev( false )
#ifdef MACOSX
, mbWindow( false )
+
+ // Window scaling independent from main display may be forced by setting VCL_MACOS_FORCE_WINDOW_SCALING environment variable. If
+ // unset window scaling from main display will be used. After implementation of full support of scaled displays window scaling
+ // will be set to 2.0f for macOS as default.
+
+ // TODO: After implementation of full support of scaled displays VCL_FORCE_WINDOW_SCALING control has to be removed.
+
+ , mbWindowScaling( getenv("VCL_MACOS_FORCE_WINDOW_SCALING") )
#else
, mbForeignContext( false )
#endif
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index ac86808147e1..f2122dd5e2fb 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -294,109 +294,6 @@ static void alignLinePoint( const SalPoint* i_pIn, float& o_fX, float& o_fY )
o_fY = static_cast<float>(i_pIn->mnY ) + 0.5;
}
-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;
- }
-
-#ifdef IOS
- // If called from idle layout, maContextHolder.get() is NULL, no idea what to do
- if (!maContextHolder.isSet())
- return;
-#endif
-
- // accelerate trivial operations
- /*const*/ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
- const bool bSameGraphics = (this == pSrc)
-#ifdef MACOSX
- || (mbWindow && mpFrame && pSrc->mbWindow && (mpFrame == pSrc->mpFrame))
-#endif
- ;
-
- 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 );
- }
- }
-}
-
static void DrawPattern50( void*, CGContextRef rContext )
{
static const CGRect aRects[2] = { { {0,0}, { 2, 2 } }, { { 2, 2 }, { 2, 2 } } };
@@ -464,81 +361,6 @@ void AquaSalGraphics::ApplyXorContext()
}
}
-void AquaSalGraphics::copyArea( long nDstX, long nDstY,long nSrcX, long nSrcY,
- long nSrcWidth, long nSrcHeight, bool /*bWindowInvalidate*/ )
-{
- SAL_WARN_IF (!maLayer.isSet(), "vcl.quartz",
- "AquaSalGraphics::copyArea() for non-layered graphics this=" << this);
-
-#ifdef IOS
- if (!maLayer.isSet())
- return;
-#endif
- float fScale = maLayer.getScale();
-
- long nScaledSourceX = nSrcX * fScale;
- long nScaledSourceY = nSrcY * fScale;
-
- long nScaledTargetX = nDstX * fScale;
- long nScaledTargetY = nDstY * fScale;
-
- long nScaledSourceWidth = nSrcWidth * fScale;
- 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);
- }
- CGContextDrawLayerAtPoint(xSrcContext, aSrcPoint, maLayer.get());
- }
-
- // draw at new destination
- const CGRect aTargetRect = CGRectMake(nScaledTargetX, nScaledTargetY, nScaledSourceWidth, nScaledSourceHeight);
- 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 );
-}
-
#ifndef IOS
void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics )
@@ -1986,62 +1808,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 );
-
-#ifndef IOS
- mbWindow = false;
-#endif
- mbPrinter = false;
- mbVirDev = true;
-
- // set graphics properties
- maLayer = rLayer;
- maContextHolder.set(xContext);
-
- mnBitmapDepth = nBitmapDepth;
-
-#ifdef IOS
- mbForeignContext = xContext != NULL;
-#endif
-
- // 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();
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/quartz/salvd.cxx b/vcl/quartz/salvd.cxx
index c06ba33c5b6f..e9fe55d27406 100644
--- a/vcl/quartz/salvd.cxx
+++ b/vcl/quartz/salvd.cxx
@@ -103,6 +103,10 @@ AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long &nDX
}
mpGraphics->SetVirDevGraphics(maLayer, pData->rCGContext);
+
+ SAL_INFO("vcl.virdev", "AquaSalVirtualDevice::AquaSalVirtualDevice() this=" << this <<
+ " (" << nDX << "x" << nDY << ") mbForeignContext=" << (mbForeignContext ? "YES" : "NO"));
+
}
else
{
@@ -156,36 +160,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())
- {
- void* pRawData = CGBitmapContextGetData(maBitmapContext.get());
- std::free(pRawData);
- CGContextRelease(maBitmapContext.get());
- maBitmapContext.set(nullptr);
- }
-}
-
SalGraphics* AquaSalVirtualDevice::AcquireGraphics()
{
if( mbGraphicsUsed || !mpGraphics )
@@ -201,103 +175,4 @@ void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* )
mbGraphicsUsed = false;
}
-bool AquaSalVirtualDevice::SetSize( long nDX, 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 Quartz layer 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
- {
-#ifdef MACOSX
- // default to a NSView target context
- AquaSalFrame* pSalFrame = mpGraphics->getGraphicsFrame();
- if( !pSalFrame || !AquaSalFrame::isAlive( pSalFrame ))
- {
- pSalFrame = static_cast<AquaSalFrame*>( GetSalData()->mpInstance->anyFrame() );
- if ( pSalFrame )
- // update the frame reference
- mpGraphics->setGraphicsFrame( pSalFrame );
- }
- if( pSalFrame )
- {
- // #i91990#
- NSWindow* pNSWindow = pSalFrame->getNSWindow();
- if ( pNSWindow )
- {
- NSGraphicsContext* pNSContext = [NSGraphicsContext graphicsContextWithWindow: pNSWindow];
- if( pNSContext )
- {
- xCGContextHolder.set([pNSContext CGContext]);
- }
- }
- }
-#endif
-
- if (!xCGContextHolder.isSet())
- {
- // assert(Application::IsBitmapRendering());
- mnBitmapDepth = 32;
-
- const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;
- void* pRawData = std::malloc( nBytesPerRow * nDY );
-#ifdef MACOSX
- const int nFlags = kCGImageAlphaNoneSkipFirst;
-#else
- const int nFlags = kCGImageAlphaNoneSkipFirst | kCGImageByteOrder32Little;
-#endif
- 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() );
- mpGraphics->SetVirDevGraphics(maLayer.get(), xDrawContext, mnBitmapDepth);
- }
-
- return maLayer.isSet();
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */