iOS tiled rendering work

Possibly quite broken intermediate commit. But anyway, now it is
possible to render the tile diretly to a CGContext. Can be seen in
the MobileLibreOffice app when build in the Debug_tile_tester
configuration. See touch_lo_draw_tile() in viewsh.cxx. Unfortunately
the old plain LibreOffice test app is now broken, though, and
displays nothing at all.

This refactoring and hacking in vcl was done in a quite ugly fashion,
with ifdefs etc. But trust me, I did try, several times, for many
days, to get where I wanted in an elegant and clean fashion. But doing
it cleanly meant not being able to actually build it for days while
trying to figure ut which bits go where and which class should be
split into what base and derived class(es), and it was too much for my
limited brain capacity. I just couldn't juggle all the vcl class
structure in my head, especially as I don't have any good
understanding of the general design of it all.

Change-Id: Ia59d6a9cce15a63e63f94e8d8574bef21993fb1f
diff --git a/ios/MobileLibreOffice/MobileLibreOffice.xcodeproj/project.pbxproj b/ios/MobileLibreOffice/MobileLibreOffice.xcodeproj/project.pbxproj
index 858beb7..ce34006 100644
--- a/ios/MobileLibreOffice/MobileLibreOffice.xcodeproj/project.pbxproj
+++ b/ios/MobileLibreOffice/MobileLibreOffice.xcodeproj/project.pbxproj
@@ -268,6 +268,7 @@
		BE82BE4D1822D10F00A447B5 /* ctlayout.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = ctlayout.cxx; path = ../../vcl/quartz/ctlayout.cxx; sourceTree = "<group>"; };
		BE82BE4E1822D10F00A447B5 /* salgdi.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdi.cxx; path = ../../vcl/quartz/salgdi.cxx; sourceTree = "<group>"; };
		BEC9DABC1858BA39009CCCB3 /* svdpagv.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = svdpagv.cxx; path = ../../svx/source/svdraw/svdpagv.cxx; sourceTree = "<group>"; };
		BEDB0EFB185A05BE009A6F26 /* salvd.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salvd.cxx; path = ../../vcl/quartz/salvd.cxx; sourceTree = "<group>"; };
		BEE68B5D185715EE0049ECE0 /* salbmp.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salbmp.cxx; path = ../../vcl/quartz/salbmp.cxx; sourceTree = "<group>"; };
		BEE68B5E185715EE0049ECE0 /* salgdicommon.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdicommon.cxx; path = ../../vcl/quartz/salgdicommon.cxx; sourceTree = "<group>"; };
		BEE68B5F185715EE0049ECE0 /* salgdiutils.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = salgdiutils.cxx; path = ../../vcl/quartz/salgdiutils.cxx; sourceTree = "<group>"; };
@@ -700,6 +701,7 @@
				BEE68B5E185715EE0049ECE0 /* salgdicommon.cxx */,
				BEE68B5F185715EE0049ECE0 /* salgdiutils.cxx */,
				BEE68B60185715EE0049ECE0 /* salmathutils.cxx */,
				BEDB0EFB185A05BE009A6F26 /* salvd.cxx */,
				BEE68B61185715EE0049ECE0 /* utils.cxx */,
			);
			name = quartz;
diff --git a/ios/experimental/LibreOffice/LibreOffice.xcodeproj/project.pbxproj b/ios/experimental/LibreOffice/LibreOffice.xcodeproj/project.pbxproj
index 8108649..26b1df6 100644
--- a/ios/experimental/LibreOffice/LibreOffice.xcodeproj/project.pbxproj
+++ b/ios/experimental/LibreOffice/LibreOffice.xcodeproj/project.pbxproj
@@ -99,6 +99,7 @@
		BECB749A17185F48001BEB85 /* view0.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = view0.cxx; path = ../../../../sw/source/ui/uiview/view0.cxx; sourceTree = "<group>"; };
		BECB749B17185F48001BEB85 /* view1.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = view1.cxx; path = ../../../../sw/source/ui/uiview/view1.cxx; sourceTree = "<group>"; };
		BECB749C17185F48001BEB85 /* view2.cxx */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = view2.cxx; path = ../../../../sw/source/ui/uiview/view2.cxx; sourceTree = "<group>"; };
		BEDB0EFA1859C206009A6F26 /* outdev2.cxx */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = outdev2.cxx; path = ../../../../vcl/source/gdi/outdev2.cxx; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
@@ -144,6 +145,7 @@
			children = (
				BE9A8D56181DBC70002A11AD /* cursor.cxx */,
				BE954A2E1704F9500040D517 /* iosinst.cxx */,
				BEDB0EFA1859C206009A6F26 /* outdev2.cxx */,
				BEB752BD180C90D0005B5696 /* outmap.cxx */,
				BE96AEB7181973DA00BD1AC4 /* salbmp.cxx */,
				BEBF3E3A17002D0200C454AC /* svapp.cxx */,
@@ -469,7 +471,7 @@
				GCC_PREFIX_HEADER = "LibreOffice/LibreOffice-Prefix.pch";
				INFOPLIST_FILE = "LibreOffice/LibreOffice-Info.plist";
				IPHONEOS_DEPLOYMENT_TARGET = 6.1;
				LIBRARY_SEARCH_PATHS = "../../../workdir/LinkTarget/Library";
				LIBRARY_SEARCH_PATHS = ../../../workdir/LinkTarget/Library;
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = app;
			};
@@ -482,7 +484,7 @@
				GCC_PREFIX_HEADER = "LibreOffice/LibreOffice-Prefix.pch";
				INFOPLIST_FILE = "LibreOffice/LibreOffice-Info.plist";
				IPHONEOS_DEPLOYMENT_TARGET = 6.1;
				LIBRARY_SEARCH_PATHS = "../../../workdir/LinkTarget/Library";
				LIBRARY_SEARCH_PATHS = ../../../workdir/LinkTarget/Library;
				PRODUCT_NAME = "$(TARGET_NAME)";
				WRAPPER_EXTENSION = app;
			};
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index add342d..01933762 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -67,6 +67,7 @@
#include "../../ui/inc/view.hxx"
#include <PostItMgr.hxx>
#include <vcl/dibtools.hxx>
#include <vcl/sysdata.hxx>
#include <vcl/virdev.hxx>
#include <vcl/svapp.hxx>
#include <svx/sdrpaintwindow.hxx>
@@ -1756,6 +1757,9 @@ void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contex
    mbTiledRendering = true;
    mpOut = &rDevice;

    // resizes the virtual device so to contain the entrie context
    rDevice.SetOutputSizePixel(Size(contextWidth, contextHeight));

    // setup the output device to draw the tile
    MapMode aMapMode(rDevice.GetMapMode());
    aMapMode.SetMapUnit(MAP_TWIP);
@@ -1769,9 +1773,6 @@ void SwViewShell::PaintTile(VirtualDevice &rDevice, int contextWidth, int contex
    aMapMode.SetScaleY(scaleY);
    rDevice.SetMapMode(aMapMode);

    // resizes the virtual device so to contain the entrie context
    rDevice.SetOutputSizePixel(Size(contextWidth, contextHeight));

    // scroll the requested area into view if necessary
    MakeVisible(SwRect(Point(tilePosX, tilePosY), rDevice.PixelToLogic(Size(contextWidth, contextHeight))));

@@ -1813,25 +1814,11 @@ void touch_lo_draw_tile(void *context, int contextWidth, int contextHeight, MLOD
    Application::AcquireSolarMutex(1);
    if (pViewShell)
    {
        // TODO create a VirtualDevice based on SystemGraphicsData instead so
        // that we get direct rendering; something like:
        //
        VirtualDevice aDevice;

        SystemGraphicsData aData;
        aData.rCGContext = (CGContextRef) context;
        VirtualDevice aDevice(&aData, (sal_uInt16)0);
        // paint to it
        pViewShell->PaintTile(aDevice, contextWidth, contextHeight, tilePosX, tilePosY, tileWidth, tileHeight);

        // copy the aDevice content to mpImage
        Bitmap aBitmap(aDevice.GetBitmap(aDevice.PixelToLogic(Point(0,0)), aDevice.PixelToLogic(Size(contextWidth, contextHeight))));
        BitmapReadAccess * readAccess = aBitmap.AcquireReadAccess();
        touch_lo_copy_buffer((void *) readAccess->GetBuffer(),
                             contextWidth,
                             contextHeight,
                             readAccess-> GetScanlineSize(),
                             context,
                             contextWidth,
                             contextHeight);
        aBitmap.ReleaseAccess(readAccess);
    }
    Application::ReleaseSolarMutex();
#else
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 72d665a..e178412 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -339,6 +339,8 @@ endif
vcl_quartz_code= \
    vcl/quartz/salbmp \
    vcl/quartz/utils \
    vcl/quartz/salgdicommon \
    vcl/quartz/salvd \

vcl_coretext_code= \
    vcl/quartz/ctfonts \
@@ -419,12 +421,10 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
    vcl/osx/clipboard \
    vcl/osx/service_entry \
    $(vcl_quartz_code) \
    vcl/quartz/salgdicommon \
    vcl/quartz/salgdiutils \
    vcl/quartz/salmathutils \
    vcl/osx/salnativewidgets \
    vcl/osx/salprn \
    vcl/osx/salvd \
    vcl/osx/salframe \
    vcl/osx/salmenu \
    vcl/osx/salobj \
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 2a1035f..0917f9e 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -286,6 +286,10 @@ bool SvpSalGraphics::isClippedSetup( const basegfx::B2IBox &aRange, SvpSalGraphi
// bitmapdevice instead.
bool SvpSalGraphics::setClipRegion( const Region& i_rClip )
{
#ifdef IOS
    if (mbForeignContext)
        return true;
#endif
    m_aClipRegion = i_rClip;
    m_aClipMap.reset();
    if( i_rClip.IsEmpty() )
@@ -314,6 +318,8 @@ bool SvpSalGraphics::setClipRegion( const Region& i_rClip )
    return true;
}

#ifndef IOS

void SvpSalGraphics::SetLineColor()
{
    m_bUseLineColor = false;
@@ -677,6 +683,8 @@ SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeigh
    return pBitmap;
}

#endif

SalColor SvpSalGraphics::getPixel( long nX, long nY )
{
    basebmp::Color aColor( m_aOrigDevice->getPixel( basegfx::B2IPoint( nX, nY ) ) );
diff --git a/vcl/headless/svpinst.cxx b/vcl/headless/svpinst.cxx
index 340f4f4..7a43eb1 100644
--- a/vcl/headless/svpinst.cxx
+++ b/vcl/headless/svpinst.cxx
@@ -30,6 +30,12 @@
#include "headless/svpframe.hxx"
#include "headless/svpdummies.hxx"
#include "headless/svpvd.hxx"
#ifdef IOS
#include "headless/svpgdi.hxx"
#include "quartz/salbmp.h"
#include "quartz/salgdi.h"
#include "quartz/salvd.h"
#endif
#include "headless/svpbmp.hxx"

#include <salframe.hxx>
@@ -211,13 +217,27 @@ void SvpSalInstance::DestroyObject( SalObject* pObject )
    delete pObject;
}

SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics*,
SalVirtualDevice* SvpSalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
                                                       long nDX, long nDY,
                                                       sal_uInt16 nBitCount, const SystemGraphicsData* )
                                                       sal_uInt16 nBitCount,
                                                       const SystemGraphicsData* pData )
{
#ifdef IOS
    if( pData )
        return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
    else
    {
        SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
        pNew->SetSize( nDX, nDY );
        return pNew;
    }
#else
    (void) pGraphics;
    (void) pData;
    SvpSalVirtualDevice* pNew = new SvpSalVirtualDevice( nBitCount );
    pNew->SetSize( nDX, nDY );
    return pNew;
#endif
}

void SvpSalInstance::DestroyVirtualDevice( SalVirtualDevice* pDevice )
@@ -242,7 +262,11 @@ SalSystem* SvpSalInstance::CreateSalSystem()

SalBitmap* SvpSalInstance::CreateSalBitmap()
{
#ifdef IOS
    return new QuartzSalBitmap();
#else
    return new SvpSalBitmap();
#endif
}

void SvpSalInstance::Yield( bool bWait, bool bHandleAllCurrentEvents )
diff --git a/vcl/inc/headless/svpframe.hxx b/vcl/inc/headless/svpframe.hxx
index 34bf77b..865fd28 100644
--- a/vcl/inc/headless/svpframe.hxx
+++ b/vcl/inc/headless/svpframe.hxx
@@ -30,6 +30,7 @@

#ifdef IOS
#define SvpSalGraphics AquaSalGraphics
#define SvpSalInstance AquaSalInstance
#endif

class SvpSalInstance;
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 8e38bd2..1135c7d 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -22,6 +22,7 @@

#include <basebmp/bitmapdevice.hxx>
#include <basebmp/color.hxx>
#include <vcl/sysdata.hxx>

#include "salgdi.hxx"
#include "sallayout.hxx"
@@ -48,6 +49,7 @@ class SvpSalGraphics : public SalGraphics
    basebmp::BitmapDeviceSharedPtr       m_aDevice;
    basebmp::BitmapDeviceSharedPtr       m_aOrigDevice;

#ifndef IOS
    bool                                 m_bUseLineColor;
    basebmp::Color                       m_aLineColor;
    bool                                 m_bUseFillColor;
@@ -55,12 +57,48 @@ class SvpSalGraphics : public SalGraphics

    basebmp::DrawMode                    m_aDrawMode;

#ifndef IOS
    // These fields are used only when we use FreeType to draw into a
    // headless backend, i.e. not on iOS.
    basebmp::Color                       m_aTextColor;
    ServerFont*                          m_pServerFont[ MAX_FALLBACK ];
    basebmp::Format                      m_eTextFmt;
#else
    friend class CTLayout;

    CGLayerRef                              mxLayer;
    // mirror AquaSalVirtualDevice::mbForeignContext for SvpSalGraphics objects related to such
    bool mbForeignContext;
    CGContextRef                         mrContext;
    class XorEmulation*                     mpXorEmulation;
    int                                     mnXorMode; // 0: off 1: on 2: invert only
    int                                     mnWidth;
    int                                     mnHeight;
    int                                  mnBitmapDepth;  // zero unless bitmap
    /// some graphics implementations (e.g. AquaSalInfoPrinter) scale
    /// everything down by a factor (see SetupPrinterGraphics for details)
    /// so we have to compensate for it with the inverse factor
    double                               mfFakeDPIScale;

    /// path representing current clip region
    CGMutablePathRef                        mxClipPath;

    /// Drawing colors
    /// pen color RGBA
    RGBAColor                               maLineColor;
    /// brush color RGBA
    RGBAColor                               maFillColor;

    // Device Font settings
    const CoreTextFontData*                 mpFontData;
    CoreTextStyle*                          mpTextStyle;
    RGBAColor                               maTextColor;
    /// allows text to be rendered without antialiasing
    bool                                    mbNonAntialiasedText;

    /// is this a printer graphics
    bool                                    mbPrinter;
    /// is this a virtual device graphics
    bool                                    mbVirDev;
#endif

    basebmp::BitmapDeviceSharedPtr       m_aClipMap;
@@ -81,22 +119,6 @@ private:
    void ensureClip();

protected:

#ifdef IOS
    friend class CTLayout;

    CGContextRef                         mrContext;
    double                               mfFakeDPIScale;

    // Device Font settings
    const CoreTextFontData*                 mpFontData;
    CoreTextStyle*                          mpTextStyle;
    RGBAColor                               maTextColor;
    /// allows text to be rendered without antialiasing
    bool                                    mbNonAntialiasedText;

#endif

    virtual bool drawAlphaBitmap( const SalTwoRect&, const SalBitmap& rSourceBitmap, const SalBitmap& rAlphaBitmap );
    virtual bool drawTransformedBitmap(
        const basegfx::B2DPoint& rNull,
@@ -218,11 +240,30 @@ public:
    virtual SystemFontData  GetSysFontData( int nFallbacklevel ) const;

#ifdef IOS
    void                SetVirDevGraphics( CGLayerRef xLayer, CGContextRef xContext, int = 0 )
    {
        mxLayer = xLayer;
        mrContext = xContext;
        mbForeignContext = xContext != NULL;
    };

    bool CheckContext();
    CGContextRef GetContext();
    bool GetRawFontData( const PhysicalFontFace* pFontData,
                         std::vector<unsigned char>& rBuffer,
                         bool* pJustCFF );
    void                RefreshRect( const CGRect& ) { };
    void                RefreshRect(float /* lX */, float /* lY */, float /* lWidth */, float /* lHeight */) { };
    void                SetState();
    void                UnsetState();
    void                InvalidateContext();
    bool                IsPenVisible() const    { return maLineColor.IsVisible(); }
    bool                IsBrushVisible() const  { return maFillColor.IsVisible(); }
    void                ImplDrawPixel( long nX, long nY, const RGBAColor& ); // helper to draw single pixels
    CGPoint*                makeCGptArray(sal_uLong nPoints, const SalPoint*  pPtAry);
    bool IsFlipped() const { return false; }
    void ApplyXorContext();
    void Pattern50Fill();
#endif
};

diff --git a/vcl/inc/headless/svpinst.hxx b/vcl/inc/headless/svpinst.hxx
index e1ef8d4..79e5e1f 100644
--- a/vcl/inc/headless/svpinst.hxx
+++ b/vcl/inc/headless/svpinst.hxx
@@ -37,6 +37,10 @@
#define VIRTUAL_DESKTOP_WIDTH 1024
#define VIRTUAL_DESKTOP_HEIGHT 768

#ifdef IOS
#define SvpSalInstance AquaSalInstance
#endif

class SvpSalInstance;
class SvpSalTimer : public SalTimer
{
diff --git a/vcl/inc/osx/saldata.hxx b/vcl/inc/osx/saldata.hxx
index c9c44bf..2bc0a6f 100644
--- a/vcl/inc/osx/saldata.hxx
+++ b/vcl/inc/osx/saldata.hxx
@@ -61,6 +61,9 @@ struct FrameHash : public boost::hash<sal_IntPtr>

#define INVALID_CURSOR_PTR (NSCursor*)0xdeadbeef

// Singleton, instantiated from Application::Application() in
// vcl/source/app/svapp.cxx through InitSalData().

class SalData
{
public:
@@ -75,11 +78,8 @@ public:
    SystemFontList                               *mpFontList;
    NSStatusItem*                                 mpStatusItem;     // one status item that draws all our stati
                                                                    // at the moment this is only one add menu button

    CGColorSpaceRef                               mxRGBSpace;
    CGColorSpaceRef                               mxGraySpace;
    CGColorSpaceRef                               mxP50Space;
    CGPatternRef                                  mxP50Pattern;

    std::vector< NSCursor* >                      maCursors;
    std::vector< NSMenuItem* >                    maFallbackMenu;
diff --git a/vcl/inc/osx/salinst.h b/vcl/inc/osx/salinst.h
index 62b7f85..d6d2824 100644
--- a/vcl/inc/osx/salinst.h
+++ b/vcl/inc/osx/salinst.h
@@ -25,7 +25,9 @@
#include "osl/conditn.h"
#include <vcl/solarmutex.hxx>

#ifdef MACOSX
#include "osx/osxvcltypes.h"
#endif

#include "salinst.hxx"

@@ -51,7 +53,6 @@ public:

#define YIELD_GUARD osl::Guard< comphelper::SolarMutex > aGuard( GetSalData()->mpFirstInstance->GetYieldMutex() )


class AquaSalInstance : public SalInstance
{
    struct SalUserEvent
diff --git a/vcl/inc/quartz/salbmp.h b/vcl/inc/quartz/salbmp.h
index a645999..510c64f 100644
--- a/vcl/inc/quartz/salbmp.h
+++ b/vcl/inc/quartz/salbmp.h
@@ -92,7 +92,7 @@ private:
                                       sal_uInt16 nSrcBits, sal_uInt32 nSrcBytesPerRow, const BitmapPalette& rSrcPalette, sal_uInt8* pSrcData );

public:
    bool            Create( CGLayerRef xLayer, int nBitCount, int nX, int nY, int nWidth, int nHeight, bool bMirrorVert = true );
    bool            Create( CGLayerRef xLayer, int nBitCount, int nX, int nY, int nWidth, int nHeight );

public:
    CGImageRef      CreateWithMask( const QuartzSalBitmap& rMask, int nX, int nY, int nWidth, int nHeight ) const;
diff --git a/vcl/inc/osx/salvd.h b/vcl/inc/quartz/salvd.h
similarity index 82%
rename from vcl/inc/osx/salvd.h
rename to vcl/inc/quartz/salvd.h
index 1c32ad4..fe69336 100644
--- a/vcl/inc/osx/salvd.h
+++ b/vcl/inc/quartz/salvd.h
@@ -21,25 +21,17 @@
#define INCLUDED_VCL_INC_OSX_SALVD_H

#include "premac.h"
#ifdef MACOSX
#include <ApplicationServices/ApplicationServices.h>
#else
#include <CoreGraphics/CoreGraphics.h>
#endif
#include "postmac.h"

#include "quartz/salgdi.h"

#include "salvd.hxx"

#if PRAGMA_ONCE
    #pragma once
#endif

// =======================================================================

// =======================================================================

// -----------------
// - SalVirDevData -
// -----------------

struct SalVirDevData
{
};
@@ -48,14 +40,8 @@ typedef struct SalVirDevData   SalVirDevData;
typedef SalVirDevData         *SalVirDevDataPtr;
typedef SalVirDevDataPtr      *SalVirDevDataHandle;

// =======================================================================

class AquaSalGraphics;

// -----------------
// - SalVirDevData -
// -----------------

class AquaSalVirtualDevice : public SalVirtualDevice
{
private:
@@ -78,8 +64,6 @@ public:
    virtual void                       GetSize( long& rWidth, long& rHeight );
};

// =======================================================================

#endif // INCLUDED_VCL_INC_OSX_SALVD_H

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/saldatabasic.hxx b/vcl/inc/saldatabasic.hxx
index 3d2d2c0..0c504e4 100644
--- a/vcl/inc/saldatabasic.hxx
+++ b/vcl/inc/saldatabasic.hxx
@@ -45,9 +45,10 @@ public:
    SalData();
    virtual ~SalData();
#ifdef IOS
    SystemFontList*               mpFontList;
    CGColorSpaceRef               mxRGBSpace;
    CGColorSpaceRef               mxGraySpace;
    SystemFontList*               mpFontList;
    static void ensureThreadAutoreleasePool() {};
#endif
};

diff --git a/vcl/ios/iosinst.cxx b/vcl/ios/iosinst.cxx
index 0b3f69f..bcef629 100644
--- a/vcl/ios/iosinst.cxx
+++ b/vcl/ios/iosinst.cxx
@@ -248,7 +248,9 @@ SalData::SalData() :
    m_pInstance( 0 ),
    m_pPlugin( 0 ),
    m_pPIManager(0 ),
    mpFontList( 0 )
    mpFontList( 0 ),
    mxRGBSpace( CGColorSpaceCreateDeviceRGB() ),
    mxGraySpace( CGColorSpaceCreateDeviceGray() )
{
}

diff --git a/vcl/osx/salinst.cxx b/vcl/osx/salinst.cxx
index 9aab3a0..538747c 100644
--- a/vcl/osx/salinst.cxx
+++ b/vcl/osx/salinst.cxx
@@ -37,7 +37,7 @@
#include "osx/salframe.h"
#include "osx/salobj.h"
#include "osx/salsys.h"
#include "osx/salvd.h"
#include "quartz/salvd.h"
#include "quartz/salbmp.h"
#include "quartz/utils.h"
#include "osx/salprn.h"
diff --git a/vcl/quartz/salbmp.cxx b/vcl/quartz/salbmp.cxx
index 1a509bd..933bd2b 100644
--- a/vcl/quartz/salbmp.cxx
+++ b/vcl/quartz/salbmp.cxx
@@ -75,7 +75,7 @@ QuartzSalBitmap::~QuartzSalBitmap()
// ------------------------------------------------------------------

bool QuartzSalBitmap::Create( CGLayerRef xLayer, int nBitmapBits,
    int nX, int nY, int nWidth, int nHeight, bool /*bMirrorVert*/ )
    int nX, int nY, int nWidth, int nHeight )
{
    DBG_ASSERT( xLayer, "QuartzSalBitmap::Create() from non-layered context" );

@@ -102,7 +102,7 @@ bool QuartzSalBitmap::Create( CGLayerRef xLayer, int nBitmapBits,

    // copy layer content into the bitmap buffer
    const CGPoint aSrcPoint = { static_cast<CGFloat>(-nX), static_cast<CGFloat>(-nY) };
    ::CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer );
    CGContextDrawLayerAtPoint( mxGraphicContext, aSrcPoint, xLayer );
    return true;
}

@@ -239,7 +239,7 @@ bool QuartzSalBitmap::CreateContext()

    if( maContextBuffer.get() )
    {
        mxGraphicContext = ::CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight,
        mxGraphicContext = CGBitmapContextCreate( maContextBuffer.get(), mnWidth, mnHeight,
            bitsPerComponent, nContextBytesPerRow, aCGColorSpace, aCGBmpInfo );
    }

diff --git a/vcl/quartz/salgdi.cxx b/vcl/quartz/salgdi.cxx
index ee80205..25a219f 100644
--- a/vcl/quartz/salgdi.cxx
+++ b/vcl/quartz/salgdi.cxx
@@ -266,39 +266,53 @@ AquaSalGraphics::AquaSalGraphics()
    , mbVirDev( false )
    , mbWindow( false )
#else
    : mrContext( NULL )
    : mxLayer( NULL )
    , mbForeignContext( false )
    , mrContext( NULL )
    , mpXorEmulation( NULL )
    , mnXorMode( 0 )
    , mnWidth( 0 )
    , mnHeight( 0 )
    , mnBitmapDepth( 0 )
    , mfFakeDPIScale( 1.0 )
    , mxClipPath( NULL )
    , maLineColor( COL_WHITE )
    , maFillColor( COL_BLACK )
    , mpFontData( NULL )
    , mpTextStyle( NULL )
    , maTextColor( COL_BLACK )
    , mbNonAntialiasedText( false )
    , mbPrinter( false )
    , mbVirDev( false )
#endif
{}

// -----------------------------------------------------------------------

AquaSalGraphics::~AquaSalGraphics()
{
#ifdef MACOSX
    CGPathRelease( mxClipPath );
    delete mpTextStyle;

    if( mpXorEmulation )
        delete mpXorEmulation;

#ifdef IOS
    if (mbForeignContext)
        return;
#endif
    if( mxLayer )
        CGLayerRelease( mxLayer );
    else if( mrContext && mbWindow )
    else if( mrContext
#ifdef MACOSX
             && mbWindow
#endif
             )
    {
        // destroy backbuffer bitmap context that we created ourself
        CGContextRelease( mrContext );
        mrContext = NULL;
    }
#endif
}

// =======================================================================

void AquaSalGraphics::SetTextColor( SalColor nSalColor )
{
    maTextColor = RGBAColor( nSalColor );
@@ -792,6 +806,9 @@ SystemFontData AquaSalGraphics::GetSysFontData( int /* nFallbacklevel */ ) const

bool SvpSalGraphics::CheckContext()
{
    if (mbForeignContext)
        return true;

    const basegfx::B2IVector size = m_aDevice->getSize();
    const basegfx::B2IVector bufferSize = m_aDevice->getBufferSize();
    const sal_Int32 scanlineStride = m_aDevice->getScanlineStride();
diff --git a/vcl/quartz/salgdicommon.cxx b/vcl/quartz/salgdicommon.cxx
index 85e6a9e..a204d74 100644
--- a/vcl/quartz/salgdicommon.cxx
+++ b/vcl/quartz/salgdicommon.cxx
@@ -25,7 +25,7 @@
#include <osl/endian.h>
#include <osl/file.hxx>

#include "basegfx/polygon/b2dpolygon.hxx"
#include <basegfx/polygon/b2dpolygon.hxx>

#include "quartz/salbmp.h"
#include "quartz/salgdi.h"
@@ -33,10 +33,12 @@
#include "fontsubset.hxx"
#include "sft.hxx"

#ifdef IOS
#include "saldatabasic.hxx"
#endif

using namespace vcl;


//typedef unsigned char Boolean; // copied from MacTypes.h, should be properly included
typedef std::vector<unsigned char> ByteVector;

static const basegfx::B2DPoint aHalfPointOfs ( 0.5, 0.5 );
@@ -307,8 +309,11 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap

    // accelerate trivial operations
    /*const*/ AquaSalGraphics* pSrc = static_cast<AquaSalGraphics*>(pSrcGraphics);
    const bool bSameGraphics = (this == pSrc) ||
        (mbWindow && mpFrame && pSrc->mbWindow && (mpFrame == pSrc->mpFrame));
    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))
@@ -333,6 +338,10 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap
         rPosAry.mnSrcHeight == rPosAry.mnDestHeight) &&
        (!mnBitmapDepth || (aDstPoint.x + pSrc->mnWidth) <= mnWidth) ) // workaround a Quartz crasher
    {
#ifdef IOS
        if( !CheckContext() )
            return;
#endif
        // 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
        CGContextRef xCopyContext = mrContext;
@@ -354,7 +363,7 @@ void AquaSalGraphics::copyBits( const SalTwoRect& rPosAry, SalGraphics *pSrcGrap
            CGContextTranslateCTM( xCopyContext, 0, +mnHeight ); CGContextScaleCTM( xCopyContext, +1, -1 );
        }
        // TODO: pSrc->size() != this->size()
        ::CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, pSrc->mxLayer );
        CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, pSrc->mxLayer );
        CGContextRestoreGState( xCopyContext );
        // mark the destination rectangle as updated
        RefreshRect( aDstRect );
@@ -462,21 +471,21 @@ void AquaSalGraphics::copyArea( long nDstX, long nDstY,long nSrcX, long nSrcY,
    // TODO: if( mnBitmapDepth > 0 )
    {
        const CGSize aSrcSize = CGSizeMake(nSrcWidth, nSrcHeight);
        xSrcLayer = ::CGLayerCreateWithContext( xCopyContext, aSrcSize, NULL );
        xSrcLayer = CGLayerCreateWithContext( xCopyContext, aSrcSize, NULL );
        const CGContextRef xSrcContext = CGLayerGetContext( xSrcLayer );
        CGPoint aSrcPoint = CGPointMake(-nSrcX, -nSrcY);
        if( IsFlipped() )
        {
            ::CGContextTranslateCTM( xSrcContext, 0, +nSrcHeight );
            ::CGContextScaleCTM( xSrcContext, +1, -1 );
            CGContextTranslateCTM( xSrcContext, 0, +nSrcHeight );
            CGContextScaleCTM( xSrcContext, +1, -1 );
            aSrcPoint.y = (nSrcY + nSrcHeight) - mnHeight;
        }
        ::CGContextDrawLayerAtPoint( xSrcContext, aSrcPoint, mxLayer );
        CGContextDrawLayerAtPoint( xSrcContext, aSrcPoint, mxLayer );
    }

    // draw at new destination
    const CGPoint aDstPoint = CGPointMake(+nDstX, +nDstY);
    ::CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, xSrcLayer );
    CGContextDrawLayerAtPoint( xCopyContext, aDstPoint, xSrcLayer );

    // cleanup
    if( xSrcLayer != mxLayer )
@@ -488,6 +497,8 @@ void AquaSalGraphics::copyArea( long nDstX, long nDstY,long nSrcX, long nSrcY,

}

#ifndef IOS

void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics )
{
    if( !rGraphics.mnRealDPIY && rGraphics.mbWindow && rGraphics.mpFrame )
@@ -499,6 +510,8 @@ void AquaSalGraphics::copyResolution( AquaSalGraphics& rGraphics )
    mfFakeDPIScale = rGraphics.mfFakeDPIScale;
}

#endif

bool AquaSalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
                                       const SalBitmap& rSrcBitmap,
                                       const SalBitmap& rAlphaBmp )
@@ -655,6 +668,8 @@ void AquaSalGraphics::drawBitmap( const SalTwoRect& rPosAry, const SalBitmap& rS
    RefreshRect( aDstRect );
}

#ifndef IOS

sal_Bool AquaSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight,
                                   void* pEpsData, sal_uLong nByteCount )
{
@@ -700,6 +715,8 @@ sal_Bool AquaSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight,
    return bOK;
}

#endif

void AquaSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
{
    if( nX1 == nX2 && nY1 == nY2 )
@@ -1129,7 +1146,7 @@ SalBitmap* AquaSalGraphics::getBitmap( long  nX, long  nY, long  nDX, long  nDY 
    ApplyXorContext();

    QuartzSalBitmap* pBitmap = new QuartzSalBitmap;
    if( !pBitmap->Create( mxLayer, mnBitmapDepth, nX, nY, nDX, nDY, !mbWindow ) )
    if( !pBitmap->Create( mxLayer, mnBitmapDepth, nX, nY, nDX, nDY) )
    {
        delete pBitmap;
        pBitmap = NULL;
@@ -1138,6 +1155,8 @@ SalBitmap* AquaSalGraphics::getBitmap( long  nX, long  nY, long  nDX, long  nDY 
    return pBitmap;
}

#ifndef IOS

SystemGraphicsData AquaSalGraphics::GetGraphicsData() const
{
    SystemGraphicsData aRes;
@@ -1184,8 +1203,8 @@ SalColor AquaSalGraphics::getPixel( long nX, long nY )
    // create a one-pixel bitmap context
    // TODO: is it worth to cache it?
    CGContextRef xOnePixelContext =
        ::CGBitmapContextCreate( &aPixel, 1, 1, 8, sizeof(aPixel),
                                 aCGColorSpace, aCGBmpInfo );
        CGBitmapContextCreate( &aPixel, 1, 1, 8, sizeof(aPixel),
                               aCGColorSpace, aCGBmpInfo );

    // update this graphics layer
    ApplyXorContext();
@@ -1214,6 +1233,8 @@ void AquaSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
    rDPIY = static_cast<sal_Int32>(mfFakeDPIScale * mnRealDPIY);
}

#endif

void AquaSalGraphics::ImplDrawPixel( long nX, long nY, const RGBAColor& rColor )
{
    if( !CheckContext() )
@@ -1230,6 +1251,8 @@ void AquaSalGraphics::ImplDrawPixel( long nX, long nY, const RGBAColor& rColor )
    CGContextSetFillColor( mrContext, maFillColor.AsArray() );
}

#ifndef IOS

void AquaSalGraphics::initResolution( NSWindow* )
{
    // #i100617# read DPI only once; there is some kind of weird caching going on
@@ -1322,6 +1345,8 @@ void AquaSalGraphics::initResolution( NSWindow* )
    mfFakeDPIScale = 1.0;
}

#endif

void AquaSalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags )
{
    if ( CheckContext() )
@@ -1395,19 +1420,13 @@ void AquaSalGraphics::Pattern50Fill()
{
    static const CGFloat aFillCol[4] = { 1,1,1,1 };
    static const CGPatternCallbacks aCallback = { 0, &DrawPattern50, NULL };
    if( ! GetSalData()->mxP50Space )
    {
        GetSalData()->mxP50Space = CGColorSpaceCreatePattern( GetSalData()->mxRGBSpace );
    }
    if( ! GetSalData()->mxP50Pattern )
    {
        GetSalData()->mxP50Pattern = CGPatternCreate( NULL, CGRectMake( 0, 0, 4, 4 ),
                                                      CGAffineTransformIdentity, 4, 4,
                                                      kCGPatternTilingConstantSpacing,
                                                      false, &aCallback );
    }
    CGContextSetFillColorSpace( mrContext, GetSalData()->mxP50Space );
    CGContextSetFillPattern( mrContext, GetSalData()->mxP50Pattern, aFillCol );
    static const CGColorSpaceRef mxP50Space = CGColorSpaceCreatePattern( GetSalData()->mxRGBSpace );
    static const CGPatternRef mxP50Pattern = CGPatternCreate( NULL, CGRectMake( 0, 0, 4, 4 ),
                                                              CGAffineTransformIdentity, 4, 4,
                                                              kCGPatternTilingConstantSpacing,
                                                              false, &aCallback );
    CGContextSetFillColorSpace( mrContext, mxP50Space );
    CGContextSetFillPattern( mrContext, mxP50Pattern, aFillCol );
    CGContextFillPath( mrContext );
}

@@ -1590,6 +1609,8 @@ void AquaSalGraphics::SetXORMode( bool bSet, bool bInvertOnly )
    }
}

#ifndef IOS

void AquaSalGraphics::updateResolution()
{
    DBG_ASSERT( mbWindow, "updateResolution on inappropriate graphics" );
@@ -1597,6 +1618,7 @@ void AquaSalGraphics::updateResolution()
    initResolution( (mbWindow && mpFrame) ? mpFrame->getNSWindow() : nil );
}

#endif

// -----------------------------------------------------------

@@ -1669,10 +1691,10 @@ void XorEmulation::SetTarget( int nWidth, int nHeight, int nTargetDepth,

    // create a XorMask context
    m_pMaskBuffer = new sal_uLong[ m_nBufferLongs ];
    m_xMaskContext = ::CGBitmapContextCreate( m_pMaskBuffer,
                                              nWidth, nHeight,
                                              nBitsPerComponent, nBytesPerRow,
                                              aCGColorSpace, aCGBmpInfo );
    m_xMaskContext = CGBitmapContextCreate( m_pMaskBuffer,
                                            nWidth, nHeight,
                                            nBitsPerComponent, nBytesPerRow,
                                            aCGColorSpace, aCGBmpInfo );
    // reset the XOR mask to black
    memset( m_pMaskBuffer, 0, m_nBufferLongs * sizeof(sal_uLong) );

@@ -1684,10 +1706,10 @@ void XorEmulation::SetTarget( int nWidth, int nHeight, int nTargetDepth,
    {
        // create a bitmap context matching to the target context
        m_pTempBuffer = new sal_uLong[ m_nBufferLongs ];
        m_xTempContext = ::CGBitmapContextCreate( m_pTempBuffer,
                                                  nWidth, nHeight,
                                                  nBitsPerComponent, nBytesPerRow,
                                                  aCGColorSpace, aCGBmpInfo );
        m_xTempContext = CGBitmapContextCreate( m_pTempBuffer,
                                                nWidth, nHeight,
                                                nBitsPerComponent, nBytesPerRow,
                                                aCGColorSpace, aCGBmpInfo );
    }

    // initialize XOR mask context for drawing
diff --git a/vcl/osx/salvd.cxx b/vcl/quartz/salvd.cxx
similarity index 88%
rename from vcl/osx/salvd.cxx
rename to vcl/quartz/salvd.cxx
index 3f69ab9..7b041b9 100644
--- a/vcl/osx/salvd.cxx
+++ b/vcl/quartz/salvd.cxx
@@ -17,15 +17,21 @@
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include "vcl/svapp.hxx"
#include "vcl/sysdata.hxx"

#include "osx/salvd.h"
#include "quartz/salvd.h"
#ifdef MACOSX
#include "osx/salinst.h"
#include "quartz/salgdi.h"
#include "osx/saldata.hxx"
#include "osx/salframe.h"
#else
#include "headless/svpframe.hxx"
#include "headless/svpgdi.hxx"
#include "headless/svpinst.hxx"
#include "headless/svpvd.hxx"
#endif
#include "quartz/salgdi.h"

// -----------------------------------------------------------------------

@@ -35,7 +41,14 @@ SalVirtualDevice* AquaSalInstance::CreateVirtualDevice( SalGraphics* pGraphics,
    // #i92075# can be called first in a thread
    SalData::ensureThreadAutoreleasePool();

    return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
#ifdef IOS
    if( pData )
        return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
    else
        return new SvpSalVirtualDevice( nBitCount );
#else
        return new AquaSalVirtualDevice( static_cast< AquaSalGraphics* >( pGraphics ), nDX, nDY, nBitCount, pData );
#endif
}

// -----------------------------------------------------------------------
@@ -67,7 +80,7 @@ AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX,
        mbForeignContext = false;           // the mxContext is created within VCL
        mpGraphics = new AquaSalGraphics(); // never fails
        mnBitmapDepth = nBitCount;

#ifdef MACOSX
        // inherit resolution from reference device
        if( pGraphic )
        {
@@ -78,7 +91,7 @@ AquaSalVirtualDevice::AquaSalVirtualDevice( AquaSalGraphics* pGraphic, long nDX,
                mpGraphics->copyResolution( *pGraphic );
            }
        }

#endif
        if( nDX && nDY )
            SetSize( nDX, nDY );

@@ -148,12 +161,21 @@ void AquaSalVirtualDevice::ReleaseGraphics( SalGraphics* )

sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
{
#ifdef IOS
    (void) nDX;
    (void) nDY;
    assert(mbForeignContext);
#endif

    if( mbForeignContext )
    {
        // Do not delete/resize mxContext that we have received from outside VCL
        return true;
    }

#ifdef IOS
    return false;
#else
    if( mxLayer )
    {
        const CGSize aSize = CGLayerGetSize( mxLayer );
@@ -176,8 +198,8 @@ sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
        const int nBytesPerRow = (mnBitmapDepth * nDX + 7) / 8;

        void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
        mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY,
            mnBitmapDepth, nBytesPerRow, aCGColorSpace, aCGBmpInfo );
        mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
                                                 mnBitmapDepth, nBytesPerRow, aCGColorSpace, aCGBmpInfo );
        xCGContext = mxBitmapContext;
    }
    else
@@ -219,8 +241,8 @@ sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
                const int nBytesPerRow = (mnBitmapDepth * nDX) / 8;

                void* pRawData = rtl_allocateMemory( nBytesPerRow * nDY );
                mxBitmapContext = ::CGBitmapContextCreate( pRawData, nDX, nDY,
                                                           8, nBytesPerRow, aCGColorSpace, aCGBmpInfo );
                mxBitmapContext = CGBitmapContextCreate( pRawData, nDX, nDY,
                                                         8, nBytesPerRow, aCGColorSpace, aCGBmpInfo );
                xCGContext = mxBitmapContext;
            }
        }
@@ -239,6 +261,7 @@ sal_Bool AquaSalVirtualDevice::SetSize( long nDX, long nDY )
    }

    return (mxLayer != NULL);
#endif
}

// -----------------------------------------------------------------------