236cdf4
From bb4586747d4b87590b976100b58cdb5340499ba4 Mon Sep 17 00:00:00 2001
236cdf4
From: rpmbuild <rpmbuild@fedoraproject.org>
236cdf4
Date: Mon, 11 Sep 2017 15:39:10 +0100
236cdf4
Subject: [PATCH] bubble the original gtk surface type through rendering
236cdf4
236cdf4
this makes presenting from a hidpi internal monitor to non-hidpi external
236cdf4
monitor use the correct sizes
236cdf4
236cdf4
and this may make scrolling a tad faster in general
236cdf4
---
236cdf4
 vcl/headless/svpframe.cxx     |   4 +-
236cdf4
 vcl/headless/svpgdi.cxx       | 135 ++++++++++++++++++++++++++----------------
236cdf4
 vcl/headless/svpvd.cxx        |  21 +++----
236cdf4
 vcl/inc/headless/svpgdi.hxx   |   5 +-
236cdf4
 vcl/inc/headless/svpvd.hxx    |   1 +
236cdf4
 vcl/inc/unx/gtk/gtkframe.hxx  |   2 +
236cdf4
 vcl/unx/gtk3/gtk3gtkframe.cxx |  50 +++++++---------
236cdf4
 7 files changed, 128 insertions(+), 90 deletions(-)
236cdf4
236cdf4
diff --git a/vcl/headless/svpframe.cxx b/vcl/headless/svpframe.cxx
236cdf4
index 7a6add2..6cd0bb9 100644
236cdf4
--- a/vcl/headless/svpframe.cxx
236cdf4
+++ b/vcl/headless/svpframe.cxx
236cdf4
@@ -144,7 +144,7 @@ SalGraphics* SvpSalFrame::AcquireGraphics()
236cdf4
 {
236cdf4
     SvpSalGraphics* pGraphics = new SvpSalGraphics();
236cdf4
 #ifndef IOS
236cdf4
-    pGraphics->setSurface( m_pSurface );
236cdf4
+    pGraphics->setSurface(m_pSurface, B2IVector(maGeometry.nWidth, maGeometry.nHeight));
236cdf4
 #endif
236cdf4
     m_aGraphics.push_back( pGraphics );
236cdf4
     return pGraphics;
236cdf4
@@ -275,7 +275,7 @@ void SvpSalFrame::SetPosSize( long nX, long nY, long nWidth, long nHeight, sal_u
236cdf4
         for( std::list< SvpSalGraphics* >::iterator it = m_aGraphics.begin();
236cdf4
              it != m_aGraphics.end(); ++it )
236cdf4
         {
236cdf4
-             (*it)->setSurface(m_pSurface);
236cdf4
+             (*it)->setSurface(m_pSurface, aFrameSize);
236cdf4
         }
236cdf4
     }
236cdf4
     if( m_bVisible )
236cdf4
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
236cdf4
index 11f408a..b518351 100644
236cdf4
--- a/vcl/headless/svpgdi.cxx
236cdf4
+++ b/vcl/headless/svpgdi.cxx
236cdf4
@@ -137,6 +137,22 @@ namespace
236cdf4
         {
236cdf4
             return source;
236cdf4
         }
236cdf4
+        void mark_dirty()
236cdf4
+        {
236cdf4
+            cairo_surface_mark_dirty(source);
236cdf4
+        }
236cdf4
+        unsigned char* getBits(sal_Int32 &rStride)
236cdf4
+        {
236cdf4
+            cairo_surface_flush(source);
236cdf4
+
236cdf4
+            unsigned char *mask_data = cairo_image_surface_get_data(source);
236cdf4
+
236cdf4
+            cairo_format_t nFormat = cairo_image_surface_get_format(source);
236cdf4
+            assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here");
236cdf4
+            rStride = cairo_format_stride_for_width(nFormat, cairo_image_surface_get_width(source));
236cdf4
+
236cdf4
+            return mask_data;
236cdf4
+        }
236cdf4
     private:
236cdf4
         SvpSalBitmap aTmpBmp;
236cdf4
         cairo_surface_t* source;
236cdf4
@@ -386,9 +402,10 @@ SvpSalGraphics::~SvpSalGraphics()
236cdf4
 {
236cdf4
 }
236cdf4
 
236cdf4
-void SvpSalGraphics::setSurface(cairo_surface_t* pSurface)
236cdf4
+void SvpSalGraphics::setSurface(cairo_surface_t* pSurface, const basegfx::B2IVector& rSize)
236cdf4
 {
236cdf4
     m_pSurface = pSurface;
236cdf4
+    m_aFrameSize = rSize;
236cdf4
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
236cdf4
     cairo_surface_get_device_scale(pSurface, &m_fScale, nullptr);
236cdf4
 #endif
236cdf4
@@ -404,14 +421,14 @@ void SvpSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
236cdf4
 
236cdf4
 sal_uInt16 SvpSalGraphics::GetBitCount() const
236cdf4
 {
236cdf4
-    if (CAIRO_FORMAT_A1 == cairo_image_surface_get_format(m_pSurface))
236cdf4
+    if (cairo_surface_get_content(m_pSurface) != CAIRO_CONTENT_COLOR_ALPHA)
236cdf4
         return 1;
236cdf4
     return 32;
236cdf4
 }
236cdf4
 
236cdf4
 long SvpSalGraphics::GetGraphicsWidth() const
236cdf4
 {
236cdf4
-    return m_pSurface ? cairo_image_surface_get_width(m_pSurface) / m_fScale : 0;
236cdf4
+    return m_pSurface ? m_aFrameSize.getX() : 0;
236cdf4
 }
236cdf4
 
236cdf4
 void SvpSalGraphics::ResetClipRegion()
236cdf4
@@ -885,7 +902,7 @@ bool SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, d
236cdf4
 
236cdf4
 void SvpSalGraphics::applyColor(cairo_t *cr, SalColor aColor)
236cdf4
 {
236cdf4
-    if (CAIRO_FORMAT_ARGB32 == cairo_image_surface_get_format(m_pSurface))
236cdf4
+    if (cairo_surface_get_content(m_pSurface) == CAIRO_CONTENT_COLOR_ALPHA)
236cdf4
     {
236cdf4
         cairo_set_source_rgba(cr, SALCOLOR_RED(aColor)/255.0,
236cdf4
                                   SALCOLOR_GREEN(aColor)/255.0,
236cdf4
@@ -982,17 +999,10 @@ void SvpSalGraphics::copyBits( const SalTwoRect& rTR,
236cdf4
     if (pSrc == this)
236cdf4
     {
236cdf4
         //self copy is a problem, so dup source in that case
236cdf4
-#if CAIRO_VERSION < CAIRO_VERSION_ENCODE(1, 12, 0)
236cdf4
         pCopy = cairo_surface_create_similar(source,
236cdf4
                                             cairo_surface_get_content(m_pSurface),
236cdf4
                                             aTR.mnSrcWidth * m_fScale,
236cdf4
                                             aTR.mnSrcHeight * m_fScale);
236cdf4
-#else
236cdf4
-        pCopy = cairo_surface_create_similar_image(source,
236cdf4
-                                            cairo_image_surface_get_format(m_pSurface),
236cdf4
-                                            aTR.mnSrcWidth * m_fScale,
236cdf4
-                                            aTR.mnSrcHeight * m_fScale);
236cdf4
-#endif
236cdf4
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
236cdf4
         cairo_surface_set_device_scale(pCopy, m_fScale, m_fScale);
236cdf4
 #endif
236cdf4
@@ -1049,16 +1059,8 @@ void SvpSalGraphics::drawMask( const SalTwoRect& rTR,
236cdf4
     /** creates an image from the given rectangle, replacing all black pixels
236cdf4
      *  with nMaskColor and make all other full transparent */
236cdf4
     SourceHelper aSurface(rSalBitmap);
236cdf4
-    cairo_surface_t* mask = aSurface.getSurface();
236cdf4
-
236cdf4
-    cairo_surface_flush(mask);
236cdf4
-
236cdf4
-    unsigned char *mask_data = cairo_image_surface_get_data(mask);
236cdf4
-
236cdf4
-    cairo_format_t nFormat = cairo_image_surface_get_format(mask);
236cdf4
-    assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here");
236cdf4
-    sal_Int32 nStride = cairo_format_stride_for_width(nFormat,
236cdf4
-                                                      cairo_image_surface_get_width(mask));
236cdf4
+    sal_Int32 nStride;
236cdf4
+    unsigned char *mask_data = aSurface.getBits(nStride);
236cdf4
     for (sal_Int32 y = rTR.mnSrcY ; y < rTR.mnSrcY + rTR.mnSrcHeight; ++y)
236cdf4
     {
236cdf4
         unsigned char *row = mask_data + (nStride*y);
236cdf4
@@ -1085,7 +1087,7 @@ void SvpSalGraphics::drawMask( const SalTwoRect& rTR,
236cdf4
             data+=4;
236cdf4
         }
236cdf4
     }
236cdf4
-    cairo_surface_mark_dirty(mask);
236cdf4
+    aSurface.mark_dirty();
236cdf4
 
236cdf4
     cairo_t* cr = getCairoContext(false);
236cdf4
     clipRegion(cr);
236cdf4
@@ -1098,7 +1100,7 @@ void SvpSalGraphics::drawMask( const SalTwoRect& rTR,
236cdf4
 
236cdf4
     cairo_translate(cr, rTR.mnDestX, rTR.mnDestY);
236cdf4
     cairo_scale(cr, (double)(rTR.mnDestWidth)/rTR.mnSrcWidth, ((double)rTR.mnDestHeight)/rTR.mnSrcHeight);
236cdf4
-    cairo_set_source_surface(cr, mask, -rTR.mnSrcX, -rTR.mnSrcY);
236cdf4
+    cairo_set_source_surface(cr, aSurface.getSurface(), -rTR.mnSrcX, -rTR.mnSrcY);
236cdf4
     cairo_paint(cr);
236cdf4
 
236cdf4
     releaseCairoContext(cr, false, extents);
236cdf4
@@ -1123,18 +1125,24 @@ SalBitmap* SvpSalGraphics::getBitmap( long nX, long nY, long nWidth, long nHeigh
236cdf4
 
236cdf4
 SalColor SvpSalGraphics::getPixel( long nX, long nY )
236cdf4
 {
236cdf4
-    cairo_surface_flush(m_pSurface);
236cdf4
-    cairo_format_t nFormat = cairo_image_surface_get_format(m_pSurface);
236cdf4
-    assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here");
236cdf4
-    sal_Int32 nStride = cairo_format_stride_for_width(nFormat,
236cdf4
-                                                      cairo_image_surface_get_width(m_pSurface));
236cdf4
-    unsigned char *surface_data = cairo_image_surface_get_data(m_pSurface);
236cdf4
-    unsigned char *row = surface_data + (nStride*nY);
236cdf4
-    unsigned char *data = row + (nX * 4);
236cdf4
+    cairo_surface_t *target = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
236cdf4
+    cairo_t* cr = cairo_create(target);
236cdf4
+
236cdf4
+    cairo_rectangle(cr, 0, 0, 1, 1);
236cdf4
+    cairo_set_source_surface(cr, m_pSurface, -nX, -nY);
236cdf4
+    cairo_paint(cr);
236cdf4
+    cairo_destroy(cr);
236cdf4
+
236cdf4
+    cairo_surface_flush(target);
236cdf4
+    unsigned char *data = cairo_image_surface_get_data(target);
236cdf4
     sal_uInt8 b = unpremultiply(data[SVP_CAIRO_BLUE], data[SVP_CAIRO_ALPHA]);
236cdf4
     sal_uInt8 g = unpremultiply(data[SVP_CAIRO_GREEN], data[SVP_CAIRO_ALPHA]);
236cdf4
     sal_uInt8 r = unpremultiply(data[SVP_CAIRO_RED], data[SVP_CAIRO_ALPHA]);
236cdf4
-    return MAKE_SALCOLOR(r, g, b);
236cdf4
+    SalColor nRet = MAKE_SALCOLOR(r, g, b);
236cdf4
+
236cdf4
+    cairo_surface_destroy(target);
236cdf4
+
236cdf4
+    return nRet;
236cdf4
 }
236cdf4
 
236cdf4
 namespace
236cdf4
@@ -1270,17 +1278,15 @@ cairo_surface_t* SvpSalGraphics::createCairoSurface(const BitmapBuffer *pBuffer)
236cdf4
     return target;
236cdf4
 }
236cdf4
 
236cdf4
-static cairo_t* createTmpCompatibleCairoContext(cairo_surface_t* pSurface, double fScale)
236cdf4
+cairo_t* SvpSalGraphics::createTmpCompatibleCairoContext() const
236cdf4
 {
236cdf4
-    cairo_surface_t *target = cairo_image_surface_create(
236cdf4
-                                cairo_image_surface_get_format(pSurface),
236cdf4
-                                cairo_image_surface_get_width(pSurface),
236cdf4
-                                cairo_image_surface_get_height(pSurface));
236cdf4
+    cairo_surface_t *target = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
236cdf4
+                                                         m_aFrameSize.getX() * m_fScale,
236cdf4
+                                                         m_aFrameSize.getY() * m_fScale);
236cdf4
 #if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
236cdf4
-    cairo_surface_set_device_scale(target, fScale, fScale);
236cdf4
-#else
236cdf4
-    (void)fScale;
236cdf4
+    cairo_surface_set_device_scale(target, m_fScale, m_fScale);
236cdf4
 #endif
236cdf4
+
236cdf4
     return cairo_create(target);
236cdf4
 }
236cdf4
 
236cdf4
@@ -1288,7 +1294,7 @@ cairo_t* SvpSalGraphics::getCairoContext(bool bXorModeAllowed) const
236cdf4
 {
236cdf4
     cairo_t* cr;
236cdf4
     if (m_ePaintMode == XOR && bXorModeAllowed)
236cdf4
-        cr = createTmpCompatibleCairoContext(m_pSurface, m_fScale);
236cdf4
+        cr = createTmpCompatibleCairoContext();
236cdf4
     else
236cdf4
         cr = cairo_create(m_pSurface);
236cdf4
     cairo_set_line_width(cr, 1);
236cdf4
@@ -1317,8 +1323,8 @@ void SvpSalGraphics::releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, cons
236cdf4
 
236cdf4
     sal_Int32 nExtentsLeft(rExtents.getMinX()), nExtentsTop(rExtents.getMinY());
236cdf4
     sal_Int32 nExtentsRight(rExtents.getMaxX()), nExtentsBottom(rExtents.getMaxY());
236cdf4
-    sal_Int32 nWidth = cairo_image_surface_get_width(m_pSurface);
236cdf4
-    sal_Int32 nHeight = cairo_image_surface_get_height(m_pSurface);
236cdf4
+    sal_Int32 nWidth = m_aFrameSize.getX();
236cdf4
+    sal_Int32 nHeight = m_aFrameSize.getY();
236cdf4
     nExtentsLeft = std::max<sal_Int32>(nExtentsLeft, 0);
236cdf4
     nExtentsTop = std::max<sal_Int32>(nExtentsTop, 0);
236cdf4
     nExtentsRight = std::min<sal_Int32>(nExtentsRight, nWidth);
236cdf4
@@ -1332,21 +1338,35 @@ void SvpSalGraphics::releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, cons
236cdf4
     //emulate it (slowly) here.
236cdf4
     if (m_ePaintMode == XOR && bXorModeAllowed)
236cdf4
     {
236cdf4
-        cairo_surface_t* true_surface = m_pSurface;
236cdf4
-        cairo_surface_flush(true_surface);
236cdf4
-        unsigned char *true_surface_data = cairo_image_surface_get_data(true_surface);
236cdf4
+        cairo_surface_t* target_surface = m_pSurface;
236cdf4
+        if (cairo_surface_get_type(target_surface) != CAIRO_SURFACE_TYPE_IMAGE)
236cdf4
+        {
236cdf4
+            //in the unlikely case we can't use m_pSurface directly, copy contents
236cdf4
+            //to another temp image surface
236cdf4
+            cairo_t* copycr = createTmpCompatibleCairoContext();
236cdf4
+            cairo_rectangle(copycr, nExtentsLeft, nExtentsTop,
236cdf4
+                                    nExtentsRight - nExtentsLeft,
236cdf4
+                                    nExtentsBottom - nExtentsTop);
236cdf4
+            cairo_set_source_surface(copycr, m_pSurface, 0, 0);
236cdf4
+            cairo_paint(copycr);
236cdf4
+            target_surface = cairo_get_target(copycr);
236cdf4
+            cairo_destroy(copycr);
236cdf4
+        }
236cdf4
+
236cdf4
+        cairo_surface_flush(target_surface);
236cdf4
+        unsigned char *target_surface_data = cairo_image_surface_get_data(target_surface);
236cdf4
         unsigned char *xor_surface_data = cairo_image_surface_get_data(surface);
236cdf4
 
236cdf4
-        cairo_format_t nFormat = cairo_image_surface_get_format(m_pSurface);
236cdf4
+        cairo_format_t nFormat = cairo_image_surface_get_format(target_surface);
236cdf4
         assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here");
236cdf4
-        sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth);
236cdf4
+        sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth * m_fScale);
236cdf4
         sal_Int32 nUnscaledExtentsLeft = nExtentsLeft * m_fScale;
236cdf4
         sal_Int32 nUnscaledExtentsRight = nExtentsRight * m_fScale;
236cdf4
         sal_Int32 nUnscaledExtentsTop = nExtentsTop * m_fScale;
236cdf4
         sal_Int32 nUnscaledExtentsBottom = nExtentsBottom * m_fScale;
236cdf4
         for (sal_Int32 y = nUnscaledExtentsTop; y < nUnscaledExtentsBottom; ++y)
236cdf4
         {
236cdf4
-            unsigned char *true_row = true_surface_data + (nStride*y);
236cdf4
+            unsigned char *true_row = target_surface_data + (nStride*y);
236cdf4
             unsigned char *xor_row = xor_surface_data + (nStride*y);
236cdf4
             unsigned char *true_data = true_row + (nUnscaledExtentsLeft * 4);
236cdf4
             unsigned char *xor_data = xor_row + (nUnscaledExtentsLeft * 4);
236cdf4
@@ -1365,7 +1385,22 @@ void SvpSalGraphics::releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, cons
236cdf4
                 xor_data+=4;
236cdf4
             }
236cdf4
         }
236cdf4
-        cairo_surface_mark_dirty(true_surface);
236cdf4
+        cairo_surface_mark_dirty(target_surface);
236cdf4
+
236cdf4
+        if (target_surface != m_pSurface)
236cdf4
+        {
236cdf4
+            cairo_t* copycr = cairo_create(m_pSurface);
236cdf4
+            //unlikely case we couldn't use m_pSurface directly, copy contents
236cdf4
+            //back from image surface
236cdf4
+            cairo_rectangle(copycr, nExtentsLeft, nExtentsTop,
236cdf4
+                                    nExtentsRight - nExtentsLeft,
236cdf4
+                                    nExtentsBottom - nExtentsTop);
236cdf4
+            cairo_set_source_surface(copycr, target_surface, 0, 0);
236cdf4
+            cairo_paint(copycr);
236cdf4
+            cairo_destroy(copycr);
236cdf4
+            cairo_surface_destroy(target_surface);
236cdf4
+        }
236cdf4
+
236cdf4
         cairo_surface_destroy(surface);
236cdf4
     }
236cdf4
 
236cdf4
diff --git a/vcl/headless/svpvd.cxx b/vcl/headless/svpvd.cxx
236cdf4
index ca28a52..b5ab755 100644
236cdf4
--- a/vcl/headless/svpvd.cxx
236cdf4
+++ b/vcl/headless/svpvd.cxx
236cdf4
@@ -38,7 +38,7 @@ SvpSalVirtualDevice::~SvpSalVirtualDevice()
236cdf4
 SalGraphics* SvpSalVirtualDevice::AcquireGraphics()
236cdf4
 {
236cdf4
     SvpSalGraphics* pGraphics = new SvpSalGraphics();
236cdf4
-    pGraphics->setSurface(m_pSurface);
236cdf4
+    pGraphics->setSurface(m_pSurface, m_aFrameSize);
236cdf4
     m_aGraphics.push_back( pGraphics );
236cdf4
     return pGraphics;
236cdf4
 }
236cdf4
@@ -62,12 +62,14 @@ bool SvpSalVirtualDevice::SetSizeUsingBuffer( long nNewDX, long nNewDY,
236cdf4
     if (nNewDY == 0)
236cdf4
         nNewDY = 1;
236cdf4
 
236cdf4
-    nNewDX *= m_fScale;
236cdf4
-    nNewDY *= m_fScale;
236cdf4
-
236cdf4
-    if (!m_pSurface || cairo_image_surface_get_width(m_pSurface) != nNewDX ||
236cdf4
-                       cairo_image_surface_get_height(m_pSurface) != nNewDY )
236cdf4
+    if (!m_pSurface || m_aFrameSize.getX() != nNewDX ||
236cdf4
+                       m_aFrameSize.getY() != nNewDY )
236cdf4
     {
236cdf4
+        m_aFrameSize = basegfx::B2IVector(nNewDX, nNewDY);
236cdf4
+
236cdf4
+        nNewDX *= m_fScale;
236cdf4
+        nNewDY *= m_fScale;
236cdf4
+
236cdf4
         if (m_pSurface)
236cdf4
         {
236cdf4
             cairo_surface_destroy(m_pSurface);
236cdf4
@@ -96,20 +98,19 @@ bool SvpSalVirtualDevice::SetSizeUsingBuffer( long nNewDX, long nNewDY,
236cdf4
         // update device in existing graphics
236cdf4
         for( std::list< SvpSalGraphics* >::iterator it = m_aGraphics.begin();
236cdf4
              it != m_aGraphics.end(); ++it )
236cdf4
-            (*it)->setSurface(m_pSurface);
236cdf4
-
236cdf4
+            (*it)->setSurface(m_pSurface, m_aFrameSize);
236cdf4
     }
236cdf4
     return true;
236cdf4
 }
236cdf4
 
236cdf4
 long SvpSalVirtualDevice::GetWidth() const
236cdf4
 {
236cdf4
-    return m_pSurface ? cairo_image_surface_get_width(m_pSurface) : 0;
236cdf4
+    return m_pSurface ? m_aFrameSize.getX() : 0;
236cdf4
 }
236cdf4
 
236cdf4
 long SvpSalVirtualDevice::GetHeight() const
236cdf4
 {
236cdf4
-    return m_pSurface ? cairo_image_surface_get_height(m_pSurface) : 0;
236cdf4
+    return m_pSurface ? m_aFrameSize.getY() : 0;
236cdf4
 }
236cdf4
 
236cdf4
 #endif
236cdf4
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
236cdf4
index 060c9f9..ed48b11 100644
236cdf4
--- a/vcl/inc/headless/svpgdi.hxx
236cdf4
+++ b/vcl/inc/headless/svpgdi.hxx
236cdf4
@@ -80,6 +80,7 @@ struct VCL_DLLPUBLIC DamageHandler
236cdf4
 class VCL_DLLPUBLIC SvpSalGraphics : public SalGraphics
236cdf4
 {
236cdf4
     cairo_surface_t*               m_pSurface;
236cdf4
+    basegfx::B2IVector             m_aFrameSize;
236cdf4
     double                         m_fScale;
236cdf4
     SalColor                       m_aLineColor;
236cdf4
     SalColor                       m_aFillColor;
236cdf4
@@ -87,7 +88,7 @@ class VCL_DLLPUBLIC SvpSalGraphics : public SalGraphics
236cdf4
 
236cdf4
 public:
236cdf4
     static GlyphCache& getPlatformGlyphCache();
236cdf4
-    void setSurface(cairo_surface_t* pSurface);
236cdf4
+    void setSurface(cairo_surface_t* pSurface, const basegfx::B2IVector& rSize);
236cdf4
     static cairo_user_data_key_t* getDamageKey();
236cdf4
 
236cdf4
 private:
236cdf4
@@ -115,6 +116,8 @@ protected:
236cdf4
         const SalBitmap* pAlphaBitmap) override;
236cdf4
     virtual bool drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) override;
236cdf4
 
236cdf4
+    cairo_t* createTmpCompatibleCairoContext() const;
236cdf4
+
236cdf4
 public:
236cdf4
     SvpSalGraphics();
236cdf4
     virtual ~SvpSalGraphics();
236cdf4
diff --git a/vcl/inc/headless/svpvd.hxx b/vcl/inc/headless/svpvd.hxx
236cdf4
index 13f2c00..146709b 100644
236cdf4
--- a/vcl/inc/headless/svpvd.hxx
236cdf4
+++ b/vcl/inc/headless/svpvd.hxx
236cdf4
@@ -31,6 +31,7 @@ class VCL_DLLPUBLIC SvpSalVirtualDevice : public SalVirtualDevice
236cdf4
 {
236cdf4
     DeviceFormat                        m_eFormat;
236cdf4
     cairo_surface_t*                    m_pSurface;
236cdf4
+    basegfx::B2IVector                  m_aFrameSize;
236cdf4
     double                              m_fScale;
236cdf4
     std::list< SvpSalGraphics* >        m_aGraphics;
236cdf4
 
236cdf4
diff --git a/vcl/inc/unx/gtk/gtkframe.hxx b/vcl/inc/unx/gtk/gtkframe.hxx
236cdf4
index 907757b..06da4ea 100644
236cdf4
--- a/vcl/inc/unx/gtk/gtkframe.hxx
236cdf4
+++ b/vcl/inc/unx/gtk/gtkframe.hxx
236cdf4
@@ -250,6 +250,7 @@ class GtkSalFrame : public SalFrame
236cdf4
 #endif
236cdf4
 #if GTK_CHECK_VERSION(3,0,0)
236cdf4
     static gboolean     signalDraw( GtkWidget*, cairo_t *cr, gpointer );
236cdf4
+    static void         signalRealize(GtkWidget*, gpointer frame);
236cdf4
     static void         sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame);
236cdf4
     static gboolean     signalTooltipQuery(GtkWidget*, gint x, gint y,
236cdf4
                                      gboolean keyboard_mode, GtkTooltip *tooltip,
236cdf4
@@ -354,6 +355,7 @@ class GtkSalFrame : public SalFrame
236cdf4
 public:
236cdf4
 #if GTK_CHECK_VERSION(3,0,0)
236cdf4
     cairo_surface_t*                m_pSurface;
236cdf4
+    basegfx::B2IVector              m_aFrameSize;
236cdf4
     DamageHandler                   m_aDamageHandler;
236cdf4
     std::vector<GdkEvent*>          m_aPendingScrollEvents;
236cdf4
     Idle                            m_aSmoothScrollIdle;
236cdf4
diff --git a/vcl/unx/gtk3/gtk3gtkframe.cxx b/vcl/unx/gtk3/gtk3gtkframe.cxx
236cdf4
index b47dd88..e343eba 100644
236cdf4
--- a/vcl/unx/gtk3/gtk3gtkframe.cxx
236cdf4
+++ b/vcl/unx/gtk3/gtk3gtkframe.cxx
236cdf4
@@ -1019,6 +1019,7 @@ void GtkSalFrame::InitCommon()
236cdf4
     m_aMouseSignalIds.push_back(g_signal_connect( G_OBJECT(pEventWidget), "scroll-event", G_CALLBACK(signalScroll), this ));
236cdf4
 
236cdf4
     g_signal_connect( G_OBJECT(m_pFixedContainer), "draw", G_CALLBACK(signalDraw), this );
236cdf4
+    g_signal_connect( G_OBJECT(m_pFixedContainer), "realize", G_CALLBACK(signalRealize), this );
236cdf4
     g_signal_connect( G_OBJECT(m_pFixedContainer), "size-allocate", G_CALLBACK(sizeAllocated), this );
236cdf4
 #if GTK_CHECK_VERSION(3,14,0)
236cdf4
     GtkGesture *pSwipe = gtk_gesture_swipe_new(pEventWidget);
236cdf4
@@ -1317,7 +1318,7 @@ SalGraphics* GtkSalFrame::AcquireGraphics()
236cdf4
             AllocateFrame();
236cdf4
             TriggerPaintEvent();
236cdf4
         }
236cdf4
-        m_pGraphics->setSurface(m_pSurface);
236cdf4
+        m_pGraphics->setSurface(m_pSurface, m_aFrameSize);
236cdf4
     }
236cdf4
     m_bGraphics = true;
236cdf4
     return m_pGraphics;
236cdf4
@@ -1570,13 +1571,11 @@ void GtkSalFrame::SetMinClientSize( long nWidth, long nHeight )
236cdf4
     }
236cdf4
 }
236cdf4
 
236cdf4
-// FIXME: we should really be an SvpSalFrame sub-class, and
236cdf4
-// share their AllocateFrame !
236cdf4
 void GtkSalFrame::AllocateFrame()
236cdf4
 {
236cdf4
     basegfx::B2IVector aFrameSize( maGeometry.nWidth, maGeometry.nHeight );
236cdf4
-    if (!m_pSurface || cairo_image_surface_get_width(m_pSurface) != aFrameSize.getX() ||
236cdf4
-                       cairo_image_surface_get_height(m_pSurface) != aFrameSize.getY() )
236cdf4
+    if (!m_pSurface || m_aFrameSize.getX() != aFrameSize.getX() ||
236cdf4
+                       m_aFrameSize.getY() != aFrameSize.getY() )
236cdf4
     {
236cdf4
         if( aFrameSize.getX() == 0 )
236cdf4
             aFrameSize.setX( 1 );
236cdf4
@@ -1586,30 +1585,17 @@ void GtkSalFrame::AllocateFrame()
236cdf4
         if (m_pSurface)
236cdf4
             cairo_surface_destroy(m_pSurface);
236cdf4
 
236cdf4
-#if GTK_CHECK_VERSION(3,10,0)
236cdf4
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
236cdf4
-        int scale = gtk_widget_get_scale_factor(m_pWindow);
236cdf4
-#else
236cdf4
-        int scale = 1;
236cdf4
-#endif
236cdf4
-        m_pSurface = gdk_window_create_similar_image_surface(widget_get_window(m_pWindow),
236cdf4
-                                                             CAIRO_FORMAT_ARGB32,
236cdf4
-                                                             aFrameSize.getX() * scale,
236cdf4
-                                                             aFrameSize.getY() * scale,
236cdf4
-                                                             scale);
236cdf4
-#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 14, 0)
236cdf4
-        cairo_surface_set_device_scale(m_pSurface, scale, scale);
236cdf4
-#endif
236cdf4
-#else
236cdf4
-        m_pSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
236cdf4
-                                                aFrameSize.getX(),
236cdf4
-                                                aFrameSize.getY());
236cdf4
-#endif
236cdf4
+        m_pSurface = gdk_window_create_similar_surface(widget_get_window(m_pWindow),
236cdf4
+                                                       CAIRO_CONTENT_COLOR_ALPHA,
236cdf4
+                                                       aFrameSize.getX(),
236cdf4
+                                                       aFrameSize.getY());
236cdf4
+        m_aFrameSize = aFrameSize;
236cdf4
+
236cdf4
         cairo_surface_set_user_data(m_pSurface, SvpSalGraphics::getDamageKey(), &m_aDamageHandler, nullptr);
236cdf4
         SAL_INFO("vcl.gtk3", "allocated Frame size of " << maGeometry.nWidth << " x " << maGeometry.nHeight);
236cdf4
 
236cdf4
         if (m_pGraphics)
236cdf4
-            m_pGraphics->setSurface(m_pSurface);
236cdf4
+            m_pGraphics->setSurface(m_pSurface, m_aFrameSize);
236cdf4
     }
236cdf4
 }
236cdf4
 
236cdf4
@@ -2956,13 +2942,23 @@ gboolean GtkSalFrame::signalDraw(GtkWidget*, cairo_t *cr, gpointer frame)
236cdf4
     return false;
236cdf4
 }
236cdf4
 
236cdf4
-void GtkSalFrame::sizeAllocated(GtkWidget*, GdkRectangle *pAllocation, gpointer frame)
236cdf4
+void GtkSalFrame::sizeAllocated(GtkWidget* pWidget, GdkRectangle *pAllocation, gpointer frame)
236cdf4
 {
236cdf4
     GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
236cdf4
     pThis->maGeometry.nWidth = pAllocation->width;
236cdf4
     pThis->maGeometry.nHeight = pAllocation->height;
236cdf4
-    pThis->AllocateFrame();
236cdf4
+    bool bRealized = gtk_widget_get_realized(pWidget);
236cdf4
+    if (bRealized)
236cdf4
+        pThis->AllocateFrame();
236cdf4
     pThis->CallCallbackExc( SalEvent::Resize, nullptr );
236cdf4
+    if (bRealized && !pThis->m_bSalObjectSetPosSize)
236cdf4
+        pThis->TriggerPaintEvent();
236cdf4
+}
236cdf4
+
236cdf4
+void GtkSalFrame::signalRealize(GtkWidget*, gpointer frame)
236cdf4
+{
236cdf4
+    GtkSalFrame* pThis = static_cast<GtkSalFrame*>(frame);
236cdf4
+    pThis->AllocateFrame();
236cdf4
     if (pThis->m_bSalObjectSetPosSize)
236cdf4
         return;
236cdf4
     pThis->TriggerPaintEvent();
236cdf4
-- 
236cdf4
2.9.5
236cdf4