desktop/Executable_soffice_bin.mk |   13 -
 solenv/clang-format/blacklist     |    4 
 vcl/Library_vcl.mk                |    1 
 vcl/Library_vclplug_osx.mk        |    3 
 vcl/inc/quartz/salgdi.h           |   15 -
 vcl/ios/salios.cxx                |  433 ++++++++++++++++++++++++++++++++++++++
 vcl/osx/salgdiutils.cxx           |   41 ++-
 vcl/osx/salinst.cxx               |   15 +
 vcl/osx/salmacos.cxx              |  383 +++++++++++++++++++++++++++++++++
 vcl/quartz/salbmp.cxx             |   50 ----
 vcl/quartz/salgdi.cxx             |    8 
 vcl/quartz/salgdicommon.cxx       |  236 --------------------
 vcl/quartz/salvd.cxx              |  133 -----------
 13 files changed, 894 insertions(+), 441 deletions(-)

New commits:
commit f55352d5e79980c358653d18008ac047dc3e0118
Author:     Thorsten Wagner <thorsten.wagne...@gmail.com>
AuthorDate: Sun Jan 10 23:49:25 2021 +0100
Commit:     Tor Lillqvist <t...@collabora.com>
CommitDate: Mon Jan 18 00:25:20 2021 +0100

    tdf#138122 Add window scaling for retina displays on macOS, plus fixes for 
iOS
    
    (1) Remove hack to make application look as if being linked against SDK 
10.13
    
    (2) Use quad storage size on virtual devices for displaying on retina 
displays thereafter
    
    (3) Apply workaround to downsample bitmaps from scaled layers (to be 
implemented)
    
    (4) Disable dark mode (to be implemented)
    
    (5) Provide new environment variables:
    
    VCL_MACOS_FORCE_WINDOW_SCALING:
    window scaling on non retina displays
    
    VCL_MACOS_FORCE_DARK_MODE:
    enable dark mode (macOS 10.14, iOS 13 and newer)
    
    VCL_MACOS_USE_SYSTEM_APPEARANCE:
    use light mode or dark mode (macOS 10.14, iOS 13 and newer) as configured 
by system preferences
    
    In this branch, this change also contains the below follow-up fix by
    tml in order to pass Jenkins for iOS:
    
    Make vcl compile again for iOS and make the Collabora Office iOS app
    work again when built against a master build of core.
    
    For now, keep the old versions of the functions touched by [this
    change] in vcl/ios/salios.cxx, and move the modified versions to the
    new file vcl/osx/salmacos.cxx.
    
    Keep the functions as they were except that ifdefs for MACOSX or IOS
    are expanded. Keep the formatting as it was to make comparisons
    easier. Thus add the new files to the clang-format exclusion list.
    
    While at it, also move vcl/quartz/salgdiutils.cxx to vcl/osx as it is
    compiled only for macOS anyway.
    
    Change-Id: I99877cd62a98cb91bcbf27af62b043c31c5f5fc9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109072
    Tested-by: Jenkins
    Reviewed-by: Tor Lillqvist <t...@collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/109493
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>

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
similarity index 86%
rename from vcl/quartz/salgdiutils.cxx
rename to 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: */
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to