vcl/headless/CairoCommon.cxx     |  194 ++++++++++++++++++++-------------------
 vcl/inc/headless/CairoCommon.hxx |    6 +
 2 files changed, 106 insertions(+), 94 deletions(-)

New commits:
commit 95dceefe207da45bd955d07a88bf7a956b274081
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Sat Nov 12 14:53:46 2022 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Mon Nov 14 17:24:36 2022 +0100

    split CairoCommon XOR code into its own method
    
    Change-Id: If615f08a44a083d53c75f58af3578e59634f9a11
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142700
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/vcl/headless/CairoCommon.cxx b/vcl/headless/CairoCommon.cxx
index 08a14b51bc08..cba7a7328fd4 100644
--- a/vcl/headless/CairoCommon.cxx
+++ b/vcl/headless/CairoCommon.cxx
@@ -448,114 +448,120 @@ void CairoCommon::releaseCairoContext(cairo_t* cr, bool 
bXorModeAllowed,
     //are some edge cases where legacy stuff still supports it, so
     //emulate it (slowly) here.
     if (bXoring)
+        doXorOnRelease(nExtentsLeft, nExtentsTop, nExtentsRight, 
nExtentsBottom, surface, nWidth);
+
+    cairo_destroy(cr); // unref
+
+    DamageHandler* pDamage
+        = static_cast<DamageHandler*>(cairo_surface_get_user_data(m_pSurface, 
getDamageKey()));
+
+    if (pDamage)
     {
-        cairo_surface_t* target_surface = m_pSurface;
-        if (cairo_surface_get_type(target_surface) != CAIRO_SURFACE_TYPE_IMAGE)
-        {
-            //in the unlikely case we can't use m_pSurface directly, copy 
contents
-            //to another temp image surface
-            cairo_t* copycr = createTmpCompatibleCairoContext();
-            cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - 
nExtentsLeft,
-                            nExtentsBottom - nExtentsTop);
-            cairo_set_source_surface(copycr, m_pSurface, 0, 0);
-            cairo_paint(copycr);
-            target_surface = cairo_get_target(copycr);
-            cairo_destroy(copycr);
-        }
+        pDamage->damaged(pDamage->handle, nExtentsLeft, nExtentsTop, 
nExtentsRight - nExtentsLeft,
+                         nExtentsBottom - nExtentsTop);
+    }
+}
 
-        cairo_surface_flush(target_surface);
-        unsigned char* target_surface_data = 
cairo_image_surface_get_data(target_surface);
-        unsigned char* xor_surface_data = 
cairo_image_surface_get_data(surface);
-
-        cairo_format_t nFormat = 
cairo_image_surface_get_format(target_surface);
-        assert(nFormat == CAIRO_FORMAT_ARGB32
-               && "need to implement CAIRO_FORMAT_A1 after all here");
-        sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth * 
m_fScale);
-        sal_Int32 nUnscaledExtentsLeft = nExtentsLeft * m_fScale;
-        sal_Int32 nUnscaledExtentsRight = nExtentsRight * m_fScale;
-        sal_Int32 nUnscaledExtentsTop = nExtentsTop * m_fScale;
-        sal_Int32 nUnscaledExtentsBottom = nExtentsBottom * m_fScale;
-
-        // Handle headless size forced to (1,1) by 
SvpSalFrame::GetSurfaceFrameSize().
-        int target_surface_width = 
cairo_image_surface_get_width(target_surface);
-        if (nUnscaledExtentsLeft > target_surface_width)
-            nUnscaledExtentsLeft = target_surface_width;
-        if (nUnscaledExtentsRight > target_surface_width)
-            nUnscaledExtentsRight = target_surface_width;
-        int target_surface_height = 
cairo_image_surface_get_height(target_surface);
-        if (nUnscaledExtentsTop > target_surface_height)
-            nUnscaledExtentsTop = target_surface_height;
-        if (nUnscaledExtentsBottom > target_surface_height)
-            nUnscaledExtentsBottom = target_surface_height;
+void CairoCommon::doXorOnRelease(sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop,
+                                 sal_Int32 nExtentsRight, sal_Int32 
nExtentsBottom,
+                                 cairo_surface_t* const surface, sal_Int32 
nWidth) const
+{
+    //For the most part we avoid the use of XOR these days, but there
+    //are some edge cases where legacy stuff still supports it, so
+    //emulate it (slowly) here.
+    cairo_surface_t* target_surface = m_pSurface;
+    if (cairo_surface_get_type(target_surface) != CAIRO_SURFACE_TYPE_IMAGE)
+    {
+        //in the unlikely case we can't use m_pSurface directly, copy contents
+        //to another temp image surface
+        cairo_t* copycr = createTmpCompatibleCairoContext();
+        cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - 
nExtentsLeft,
+                        nExtentsBottom - nExtentsTop);
+        cairo_set_source_surface(copycr, m_pSurface, 0, 0);
+        cairo_paint(copycr);
+        target_surface = cairo_get_target(copycr);
+        cairo_destroy(copycr);
+    }
+
+    cairo_surface_flush(target_surface);
+    unsigned char* target_surface_data = 
cairo_image_surface_get_data(target_surface);
+    unsigned char* xor_surface_data = cairo_image_surface_get_data(surface);
+
+    cairo_format_t nFormat = cairo_image_surface_get_format(target_surface);
+    assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement 
CAIRO_FORMAT_A1 after all here");
+    sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth * 
m_fScale);
+    sal_Int32 nUnscaledExtentsLeft = nExtentsLeft * m_fScale;
+    sal_Int32 nUnscaledExtentsRight = nExtentsRight * m_fScale;
+    sal_Int32 nUnscaledExtentsTop = nExtentsTop * m_fScale;
+    sal_Int32 nUnscaledExtentsBottom = nExtentsBottom * m_fScale;
+
+    // Handle headless size forced to (1,1) by 
SvpSalFrame::GetSurfaceFrameSize().
+    int target_surface_width = cairo_image_surface_get_width(target_surface);
+    if (nUnscaledExtentsLeft > target_surface_width)
+        nUnscaledExtentsLeft = target_surface_width;
+    if (nUnscaledExtentsRight > target_surface_width)
+        nUnscaledExtentsRight = target_surface_width;
+    int target_surface_height = cairo_image_surface_get_height(target_surface);
+    if (nUnscaledExtentsTop > target_surface_height)
+        nUnscaledExtentsTop = target_surface_height;
+    if (nUnscaledExtentsBottom > target_surface_height)
+        nUnscaledExtentsBottom = target_surface_height;
 
 #if !ENABLE_WASM_STRIP_PREMULTIPLY
-        vcl::bitmap::lookup_table const& unpremultiply_table
-            = vcl::bitmap::get_unpremultiply_table();
-        vcl::bitmap::lookup_table const& premultiply_table = 
vcl::bitmap::get_premultiply_table();
+    vcl::bitmap::lookup_table const& unpremultiply_table = 
vcl::bitmap::get_unpremultiply_table();
+    vcl::bitmap::lookup_table const& premultiply_table = 
vcl::bitmap::get_premultiply_table();
 #endif
-        for (sal_Int32 y = nUnscaledExtentsTop; y < nUnscaledExtentsBottom; 
++y)
+    for (sal_Int32 y = nUnscaledExtentsTop; y < nUnscaledExtentsBottom; ++y)
+    {
+        unsigned char* true_row = target_surface_data + (nStride * y);
+        unsigned char* xor_row = xor_surface_data + (nStride * y);
+        unsigned char* true_data = true_row + (nUnscaledExtentsLeft * 4);
+        unsigned char* xor_data = xor_row + (nUnscaledExtentsLeft * 4);
+        for (sal_Int32 x = nUnscaledExtentsLeft; x < nUnscaledExtentsRight; 
++x)
         {
-            unsigned char* true_row = target_surface_data + (nStride * y);
-            unsigned char* xor_row = xor_surface_data + (nStride * y);
-            unsigned char* true_data = true_row + (nUnscaledExtentsLeft * 4);
-            unsigned char* xor_data = xor_row + (nUnscaledExtentsLeft * 4);
-            for (sal_Int32 x = nUnscaledExtentsLeft; x < 
nUnscaledExtentsRight; ++x)
-            {
-                sal_uInt8 a = true_data[SVP_CAIRO_ALPHA];
-                sal_uInt8 xor_a = xor_data[SVP_CAIRO_ALPHA];
+            sal_uInt8 a = true_data[SVP_CAIRO_ALPHA];
+            sal_uInt8 xor_a = xor_data[SVP_CAIRO_ALPHA];
 #if ENABLE_WASM_STRIP_PREMULTIPLY
-                sal_uInt8 b = vcl::bitmap::unpremultiply(a, 
true_data[SVP_CAIRO_BLUE])
-                              ^ vcl::bitmap::unpremultiply(xor_a, 
xor_data[SVP_CAIRO_BLUE]);
-                sal_uInt8 g = vcl::bitmap::unpremultiply(a, 
true_data[SVP_CAIRO_GREEN])
-                              ^ vcl::bitmap::unpremultiply(xor_a, 
xor_data[SVP_CAIRO_GREEN]);
-                sal_uInt8 r = vcl::bitmap::unpremultiply(a, 
true_data[SVP_CAIRO_RED])
-                              ^ vcl::bitmap::unpremultiply(xor_a, 
xor_data[SVP_CAIRO_RED]);
-                true_data[SVP_CAIRO_BLUE] = vcl::bitmap::premultiply(a, b);
-                true_data[SVP_CAIRO_GREEN] = vcl::bitmap::premultiply(a, g);
-                true_data[SVP_CAIRO_RED] = vcl::bitmap::premultiply(a, r);
+            sal_uInt8 b = vcl::bitmap::unpremultiply(a, 
true_data[SVP_CAIRO_BLUE])
+                          ^ vcl::bitmap::unpremultiply(xor_a, 
xor_data[SVP_CAIRO_BLUE]);
+            sal_uInt8 g = vcl::bitmap::unpremultiply(a, 
true_data[SVP_CAIRO_GREEN])
+                          ^ vcl::bitmap::unpremultiply(xor_a, 
xor_data[SVP_CAIRO_GREEN]);
+            sal_uInt8 r = vcl::bitmap::unpremultiply(a, 
true_data[SVP_CAIRO_RED])
+                          ^ vcl::bitmap::unpremultiply(xor_a, 
xor_data[SVP_CAIRO_RED]);
+            true_data[SVP_CAIRO_BLUE] = vcl::bitmap::premultiply(a, b);
+            true_data[SVP_CAIRO_GREEN] = vcl::bitmap::premultiply(a, g);
+            true_data[SVP_CAIRO_RED] = vcl::bitmap::premultiply(a, r);
 #else
-                sal_uInt8 b = unpremultiply_table[a][true_data[SVP_CAIRO_BLUE]]
-                              ^ 
unpremultiply_table[xor_a][xor_data[SVP_CAIRO_BLUE]];
-                sal_uInt8 g = 
unpremultiply_table[a][true_data[SVP_CAIRO_GREEN]]
-                              ^ 
unpremultiply_table[xor_a][xor_data[SVP_CAIRO_GREEN]];
-                sal_uInt8 r = unpremultiply_table[a][true_data[SVP_CAIRO_RED]]
-                              ^ 
unpremultiply_table[xor_a][xor_data[SVP_CAIRO_RED]];
-                true_data[SVP_CAIRO_BLUE] = premultiply_table[a][b];
-                true_data[SVP_CAIRO_GREEN] = premultiply_table[a][g];
-                true_data[SVP_CAIRO_RED] = premultiply_table[a][r];
+            sal_uInt8 b = unpremultiply_table[a][true_data[SVP_CAIRO_BLUE]]
+                          ^ 
unpremultiply_table[xor_a][xor_data[SVP_CAIRO_BLUE]];
+            sal_uInt8 g = unpremultiply_table[a][true_data[SVP_CAIRO_GREEN]]
+                          ^ 
unpremultiply_table[xor_a][xor_data[SVP_CAIRO_GREEN]];
+            sal_uInt8 r = unpremultiply_table[a][true_data[SVP_CAIRO_RED]]
+                          ^ 
unpremultiply_table[xor_a][xor_data[SVP_CAIRO_RED]];
+            true_data[SVP_CAIRO_BLUE] = premultiply_table[a][b];
+            true_data[SVP_CAIRO_GREEN] = premultiply_table[a][g];
+            true_data[SVP_CAIRO_RED] = premultiply_table[a][r];
 #endif
-                true_data += 4;
-                xor_data += 4;
-            }
+            true_data += 4;
+            xor_data += 4;
         }
-        cairo_surface_mark_dirty(target_surface);
-
-        if (target_surface != m_pSurface)
-        {
-            cairo_t* copycr = cairo_create(m_pSurface);
-            //unlikely case we couldn't use m_pSurface directly, copy contents
-            //back from image surface
-            cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - 
nExtentsLeft,
-                            nExtentsBottom - nExtentsTop);
-            cairo_set_source_surface(copycr, target_surface, 0, 0);
-            cairo_paint(copycr);
-            cairo_destroy(copycr);
-            cairo_surface_destroy(target_surface);
-        }
-
-        cairo_surface_destroy(surface);
     }
+    cairo_surface_mark_dirty(target_surface);
 
-    cairo_destroy(cr); // unref
-
-    DamageHandler* pDamage
-        = static_cast<DamageHandler*>(cairo_surface_get_user_data(m_pSurface, 
getDamageKey()));
-
-    if (pDamage)
+    if (target_surface != m_pSurface)
     {
-        pDamage->damaged(pDamage->handle, nExtentsLeft, nExtentsTop, 
nExtentsRight - nExtentsLeft,
-                         nExtentsBottom - nExtentsTop);
+        cairo_t* copycr = cairo_create(m_pSurface);
+        //unlikely case we couldn't use m_pSurface directly, copy contents
+        //back from image surface
+        cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - 
nExtentsLeft,
+                        nExtentsBottom - nExtentsTop);
+        cairo_set_source_surface(copycr, target_surface, 0, 0);
+        cairo_paint(copycr);
+        cairo_destroy(copycr);
+        cairo_surface_destroy(target_surface);
     }
+
+    cairo_surface_destroy(surface);
 }
 
 cairo_t* CairoCommon::createTmpCompatibleCairoContext() const
diff --git a/vcl/inc/headless/CairoCommon.hxx b/vcl/inc/headless/CairoCommon.hxx
index 476b031c451b..3fc0144ef34a 100644
--- a/vcl/inc/headless/CairoCommon.hxx
+++ b/vcl/inc/headless/CairoCommon.hxx
@@ -169,6 +169,7 @@ struct VCL_DLLPUBLIC CairoCommon
     cairo_t* getCairoContext(bool bXorModeAllowed, bool bAntiAlias) const;
     void releaseCairoContext(cairo_t* cr, bool bXorModeAllowed,
                              const basegfx::B2DRange& rExtents) const;
+
     cairo_t* createTmpCompatibleCairoContext() const;
 
     void applyColor(cairo_t* cr, Color rColor, double fTransparency = 0.0);
@@ -198,6 +199,11 @@ struct VCL_DLLPUBLIC CairoCommon
     void invert(const basegfx::B2DPolygon& rPoly, SalInvert nFlags, bool 
bAntiAlias);
 
     static cairo_surface_t* createCairoSurface(const BitmapBuffer* pBuffer);
+
+private:
+    void doXorOnRelease(sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop, 
sal_Int32 nExtentsRight,
+                        sal_Int32 nExtentsBottom, cairo_surface_t* const 
surface,
+                        sal_Int32 nWidth) const;
 };
 
 class SurfaceHelper

Reply via email to