vcl/Library_vclplug_gen.mk                      |    1 
 vcl/inc/unx/salgdi.h                            |   97 ++----
 vcl/skia/x11/salvd.cxx                          |    2 
 vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx |  185 +++++++++++++
 vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx |   97 ++++++
 vcl/unx/generic/gdi/gdiimpl.cxx                 |   32 +-
 vcl/unx/generic/gdi/gdiimpl.hxx                 |    2 
 vcl/unx/generic/gdi/salgdi.cxx                  |  339 +++---------------------
 vcl/unx/generic/gdi/salvd.cxx                   |    6 
 9 files changed, 394 insertions(+), 367 deletions(-)

New commits:
commit a98971ac975e19efa2336b608506eefa85ce2485
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Mon Apr 11 23:31:50 2022 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Apr 13 01:20:31 2022 +0200

    vcl: move X11 drawing that uses cairo into X11CairoSalGraphicsImpl
    
    If cairo is available we override drawPolyPolygon and drawPolyLine
    with an implementation that uses cairo to draw instead of X11.
    This override was previously done in X11SalGraphics, but as we want
    to have all the drawing in backends (SalGraphicsImpl children) this
    also needs to be moved to one. In this case we can just derive
    X11SalGraphicsImpl and implement specifics there. As there is some
    common stuff now betwee X11SalGraphics and X11SalGraphicsImpl,
    also add X11Common, which includes those.
    
    Change-Id: Id1e0c5227506e03d3dd0f937e4ef50d69b17bb22
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/132827
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/vcl/Library_vclplug_gen.mk b/vcl/Library_vclplug_gen.mk
index 73f5464d7362..2cefd3f76856 100644
--- a/vcl/Library_vclplug_gen.mk
+++ b/vcl/Library_vclplug_gen.mk
@@ -98,6 +98,7 @@ $(eval $(call gb_Library_add_exception_objects,vclplug_gen,\
     vcl/unx/generic/dtrans/X11_transferable \
     vcl/unx/generic/gdi/cairo_xlib_cairo \
     vcl/unx/generic/gdi/x11cairotextrender \
+    vcl/unx/generic/gdi/X11CairoSalGraphicsImpl \
     vcl/unx/generic/gdi/gdiimpl \
     vcl/unx/generic/gdi/salbmp \
     vcl/unx/generic/gdi/salgdi2 \
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index 2d0e00800886..045a3848e20f 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -62,6 +62,29 @@ namespace basegfx {
     class B2DTrapezoid;
 }
 
+class X11Common
+{
+public:
+    Drawable m_hDrawable;
+    const SalColormap* m_pColormap;
+    cairo_surface_t* m_pExternalSurface;
+
+    X11Common();
+
+    cairo_t* getCairoContext();
+
+    static void releaseCairoContext(cairo_t* cr);
+
+    bool SupportsCairo() const;
+
+    const SalColormap& GetColormap() const { return *m_pColormap; }
+    const SalDisplay* GetDisplay() const { return GetColormap().GetDisplay(); }
+    const SalVisual& GetVisual() const { return GetColormap().GetVisual(); }
+    Display* GetXDisplay() const { return GetColormap().GetXDisplay(); }
+    Pixel GetPixel(Color nColor) const { return 
GetColormap().GetPixel(nColor); }
+    Drawable GetDrawable() const { return m_hDrawable; }
+};
+
 class X11SalGraphics final : public SalGraphicsAutoDelegateToImpl
 {
     friend class X11SalGraphicsImpl;
@@ -78,18 +101,10 @@ public:
     void                            DeInit();
 
     virtual SalGraphicsImpl*        GetImpl() const override;
-    inline  const SalDisplay*       GetDisplay() const;
-    inline  Display*                GetXDisplay() const;
-    inline  const SalVisual&        GetVisual() const;
     SalGeometryProvider*            GetGeometryProvider() const;
-    Drawable                        GetDrawable() const { return hDrawable_; }
     void                            SetDrawable(Drawable d, cairo_surface_t* 
surface, SalX11Screen nXScreen);
     XRenderPictFormat*              GetXRenderFormat() const;
     void                    SetXRenderFormat( XRenderPictFormat* 
pXRenderFormat ) { m_pXRenderFormat = pXRenderFormat; }
-    const SalColormap&      GetColormap() const { return *m_pColormap; }
-
-    using SalGraphics::GetPixel;
-    inline  Pixel                   GetPixel( Color nColor ) const;
 
     const SalX11Screen&             GetScreenNumber() const { return 
m_nXScreen; }
 
@@ -98,15 +113,6 @@ public:
     // override all pure virtual methods
     virtual void                    GetResolution( sal_Int32& rDPIX, 
sal_Int32& rDPIY ) override;
 
-    virtual void                    ResetClipRegion() override;
-    virtual bool                    setClipRegion( const vcl::Region& ) 
override;
-
-    virtual void                    SetLineColor() override;
-    virtual void                    SetLineColor( Color nColor ) override;
-    virtual void                    SetFillColor() override;
-
-    virtual void                    SetFillColor( Color nColor ) override;
-
     virtual void                    SetTextColor( Color nColor ) override;
     virtual void                    SetFont(LogicalFontInstance*, int 
nFallbackLevel) override;
     virtual void                    GetFontMetric( ImplFontMetricDataRef&, int 
nFallbackLevel ) override;
@@ -138,23 +144,6 @@ public:
                                     GetTextLayout(int nFallbackLevel) override;
     virtual void                    DrawTextLayout( const GenericSalLayout& ) 
override;
 
-
-    virtual bool                    drawPolyPolygon(
-                                        const basegfx::B2DHomMatrix& 
rObjectToDevice,
-                                        const basegfx::B2DPolyPolygon&,
-                                        double fTransparency) override;
-
-    virtual bool                    drawPolyLine(
-                                        const basegfx::B2DHomMatrix& 
rObjectToDevice,
-                                        const basegfx::B2DPolygon&,
-                                        double fTransparency,
-                                        double fLineWidth,
-                                        const std::vector< double >* pStroke, 
// MM01
-                                        basegfx::B2DLineJoin,
-                                        css::drawing::LineCap,
-                                        double fMiterMinimumAngle,
-                                        bool bPixelSnapHairline) override;
-
     virtual SystemGraphicsData      GetGraphicsData() const override;
 
 #if ENABLE_CAIRO_CANVAS
@@ -181,57 +170,39 @@ public:
 
 
 private:
-    using SalGraphicsAutoDelegateToImpl::drawPolyPolygon;
-    using SalGraphicsAutoDelegateToImpl::drawPolyLine;
-
-    using SalGraphics::SetClipRegion;
+    using SalGraphics::GetPixel;
     void                            SetClipRegion( GC pGC, Region pXReg = 
nullptr ) const;
     bool                            GetDitherPixmap ( Color nColor );
 
-    using SalGraphics::DrawBitmap;
-
     void                            freeResources();
 
     SalFrame*                       m_pFrame; // the SalFrame which created 
this Graphics or NULL
     SalVirtualDevice*               m_pVDev;  // the SalVirtualDevice which 
created this Graphics or NULL
 
-    const SalColormap*              m_pColormap;
+
     std::unique_ptr<SalColormap>    m_pDeleteColormap;
-    Drawable                        hDrawable_;     // use
-    cairo_surface_t*                m_pExternalSurface;
+
     SalX11Screen                    m_nXScreen;
     mutable XRenderPictFormat*      m_pXRenderFormat;
     XID                             m_aXRenderPicture;
 
     Region                          mpClipRegion;
-#if ENABLE_CAIRO_CANVAS
-    vcl::Region                     maClipRegion;
-    Color                           mnPenColor;
-    Color                           mnFillColor;
-#endif // ENABLE_CAIRO_CANVAS
-
     Pixmap                          hBrush_;        // Dither
 
     bool                            bWindow_ : 1;       // is Window
     bool                            bVirDev_ : 1;       // is VirDev
-    bool                            m_bSkia  : 1;
 
-private:
     std::unique_ptr<SalGraphicsImpl> mxImpl;
     std::unique_ptr<TextRenderImpl> mxTextRenderImpl;
+    X11Common maX11Common;
 
+public:
+    Drawable GetDrawable() const { return maX11Common.GetDrawable(); }
+    const SalColormap& GetColormap() const { return maX11Common.GetColormap(); 
}
+    const SalDisplay* GetDisplay() const { return maX11Common.GetDisplay(); }
+    const SalVisual& GetVisual() const { return maX11Common.GetVisual(); }
+    Display* GetXDisplay() const { return maX11Common.GetXDisplay(); }
+    Pixel GetPixel(Color nColor) const { return maX11Common.GetPixel(nColor); }
 };
 
-inline const SalDisplay *X11SalGraphics::GetDisplay() const
-{ return GetColormap().GetDisplay(); }
-
-inline const SalVisual& X11SalGraphics::GetVisual() const
-{ return GetColormap().GetVisual(); }
-
-inline Display *X11SalGraphics::GetXDisplay() const
-{ return GetColormap().GetXDisplay(); }
-
-inline Pixel X11SalGraphics::GetPixel( Color nColor ) const
-{ return GetColormap().GetPixel( nColor ); }
-
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/skia/x11/salvd.cxx b/vcl/skia/x11/salvd.cxx
index bb007962f11c..73488b8a10bc 100644
--- a/vcl/skia/x11/salvd.cxx
+++ b/vcl/skia/x11/salvd.cxx
@@ -21,7 +21,7 @@ void X11SalGraphics::Init(X11SkiaSalVirtualDevice* pDevice)
     SalDisplay* pDisplay = pDevice->GetDisplay();
 
     m_nXScreen = pDevice->GetXScreenNumber();
-    m_pColormap = &pDisplay->GetColormap(m_nXScreen);
+    maX11Common.m_pColormap = &pDisplay->GetColormap(m_nXScreen);
 
     m_pVDev = pDevice;
     m_pFrame = nullptr;
diff --git a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx 
b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx
new file mode 100644
index 000000000000..2109e19b9660
--- /dev/null
+++ b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx
@@ -0,0 +1,185 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 .
+ */
+
+#include "X11CairoSalGraphicsImpl.hxx"
+
+#if ENABLE_CAIRO_CANVAS
+
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+
+X11CairoSalGraphicsImpl::X11CairoSalGraphicsImpl(X11SalGraphics& rParent, 
X11Common& rX11Common)
+    : X11SalGraphicsImpl(rParent)
+    , mrX11Common(rX11Common)
+    , mnPenColor(SALCOLOR_NONE)
+    , mnFillColor(SALCOLOR_NONE)
+{
+}
+
+bool X11CairoSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& 
rObjectToDevice,
+                                              const basegfx::B2DPolyPolygon& 
rPolyPolygon,
+                                              double fTransparency)
+{
+    if (fTransparency >= 1.0)
+    {
+        return true;
+    }
+
+    if (rPolyPolygon.count() == 0)
+    {
+        return true;
+    }
+
+    // Fallback: Transform to DeviceCoordinates
+    basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
+    aPolyPolygon.transform(rObjectToDevice);
+
+    if (SALCOLOR_NONE == mnFillColor && SALCOLOR_NONE == mnPenColor)
+    {
+        return true;
+    }
+
+    // enable by setting to something
+    static const char* 
pUseCairoForPolygons(getenv("SAL_ENABLE_USE_CAIRO_FOR_POLYGONS"));
+
+    if (nullptr != pUseCairoForPolygons && mrX11Common.SupportsCairo())
+    {
+        // snap to raster if requested
+        const bool bSnapPoints(!getAntiAlias());
+
+        if (bSnapPoints)
+        {
+            aPolyPolygon = 
basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygon);
+        }
+
+        cairo_t* cr = mrX11Common.getCairoContext();
+        clipRegion(cr);
+
+        for (auto const& rPolygon : std::as_const(aPolyPolygon))
+        {
+            const sal_uInt32 nPointCount(rPolygon.count());
+
+            if (nPointCount)
+            {
+                const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nPointCount 
: nPointCount - 1);
+
+                if (nEdgeCount)
+                {
+                    basegfx::B2DCubicBezier aEdge;
+
+                    for (sal_uInt32 b = 0; b < nEdgeCount; ++b)
+                    {
+                        rPolygon.getBezierSegment(b, aEdge);
+
+                        if (!b)
+                        {
+                            const basegfx::B2DPoint 
aStart(aEdge.getStartPoint());
+                            cairo_move_to(cr, aStart.getX(), aStart.getY());
+                        }
+
+                        const basegfx::B2DPoint aEnd(aEdge.getEndPoint());
+
+                        if (aEdge.isBezier())
+                        {
+                            const basegfx::B2DPoint 
aCP1(aEdge.getControlPointA());
+                            const basegfx::B2DPoint 
aCP2(aEdge.getControlPointB());
+                            cairo_curve_to(cr, aCP1.getX(), aCP1.getY(), 
aCP2.getX(), aCP2.getY(),
+                                           aEnd.getX(), aEnd.getY());
+                        }
+                        else
+                        {
+                            cairo_line_to(cr, aEnd.getX(), aEnd.getY());
+                        }
+                    }
+
+                    cairo_close_path(cr);
+                }
+            }
+        }
+
+        if (SALCOLOR_NONE != mnFillColor)
+        {
+            cairo_set_source_rgba(cr, mnFillColor.GetRed() / 255.0, 
mnFillColor.GetGreen() / 255.0,
+                                  mnFillColor.GetBlue() / 255.0, 1.0 - 
fTransparency);
+            cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
+            cairo_fill_preserve(cr);
+        }
+
+        if (SALCOLOR_NONE != mnPenColor)
+        {
+            cairo_set_source_rgba(cr, mnPenColor.GetRed() / 255.0, 
mnPenColor.GetGreen() / 255.0,
+                                  mnPenColor.GetBlue() / 255.0, 1.0 - 
fTransparency);
+            cairo_stroke_preserve(cr);
+        }
+
+        X11Common::releaseCairoContext(cr);
+        return true;
+    }
+
+    return X11SalGraphicsImpl::drawPolyPolygon(rObjectToDevice, rPolyPolygon, 
fTransparency);
+}
+
+bool X11CairoSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& 
rObjectToDevice,
+                                           const basegfx::B2DPolygon& rPolygon,
+                                           double fTransparency, double 
fLineWidth,
+                                           const std::vector<double>* pStroke,
+                                           basegfx::B2DLineJoin eLineJoin,
+                                           css::drawing::LineCap eLineCap,
+                                           double fMiterMinimumAngle, bool 
bPixelSnapHairline)
+{
+    if (0 == rPolygon.count())
+    {
+        return true;
+    }
+
+    if (fTransparency >= 1.0)
+    {
+        return true;
+    }
+
+    // disable by setting to something
+    static const char* 
pUseCairoForFatLines(getenv("SAL_DISABLE_USE_CAIRO_FOR_FATLINES"));
+
+    if (nullptr == pUseCairoForFatLines && mrX11Common.SupportsCairo())
+    {
+        cairo_t* cr = mrX11Common.getCairoContext();
+        clipRegion(cr);
+
+        // Use the now available static drawPolyLine from the 
Cairo-Headless-Fallback
+        // that will take care of all needed stuff
+        const bool bRetval(CairoCommon::drawPolyLine(
+            cr, nullptr, mnPenColor, getAntiAlias(), rObjectToDevice, 
rPolygon, fTransparency,
+            fLineWidth, pStroke, eLineJoin, eLineCap, fMiterMinimumAngle, 
bPixelSnapHairline));
+
+        X11Common::releaseCairoContext(cr);
+
+        if (bRetval)
+        {
+            return true;
+        }
+    }
+
+    return X11SalGraphicsImpl::drawPolyLine(rObjectToDevice, rPolygon, 
fTransparency, fLineWidth,
+                                            pStroke, eLineJoin, eLineCap, 
fMiterMinimumAngle,
+                                            bPixelSnapHairline);
+}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx 
b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx
new file mode 100644
index 000000000000..beb07e3ffc30
--- /dev/null
+++ b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx
@@ -0,0 +1,97 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * 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 .
+ */
+
+#include <config_features.h>
+#include <config_cairo_canvas.h>
+
+#if ENABLE_CAIRO_CANVAS
+
+#include <cairo-xlib.h>
+#include <unx/salgdi.h>
+#include "gdiimpl.hxx"
+#include "cairo_xlib_cairo.hxx"
+
+#include <headless/CairoCommon.hxx>
+
+class X11CairoSalGraphicsImpl : public X11SalGraphicsImpl
+{
+private:
+    X11Common& mrX11Common;
+    vcl::Region maClipRegion;
+    Color mnPenColor;
+    Color mnFillColor;
+
+    using X11SalGraphicsImpl::drawPolyPolygon;
+    using X11SalGraphicsImpl::drawPolyLine;
+
+public:
+    X11CairoSalGraphicsImpl(X11SalGraphics& rParent, X11Common& rX11Common);
+
+    void ResetClipRegion() override
+    {
+        maClipRegion.SetNull();
+        X11SalGraphicsImpl::ResetClipRegion();
+    }
+
+    bool setClipRegion(const vcl::Region& i_rClip) override
+    {
+        maClipRegion = i_rClip;
+        return X11SalGraphicsImpl::setClipRegion(i_rClip);
+    }
+
+    void SetLineColor() override
+    {
+        mnPenColor = SALCOLOR_NONE;
+        X11SalGraphicsImpl::SetLineColor();
+    }
+
+    void SetLineColor(Color nColor) override
+    {
+        mnPenColor = nColor;
+        X11SalGraphicsImpl::SetLineColor(nColor);
+    }
+
+    void SetFillColor() override
+    {
+        mnFillColor = SALCOLOR_NONE;
+        X11SalGraphicsImpl::SetFillColor();
+    }
+
+    void SetFillColor(Color nColor) override
+    {
+        mnFillColor = nColor;
+        X11SalGraphicsImpl::SetFillColor(nColor);
+    }
+
+    void clipRegion(cairo_t* cr) { CairoCommon::clipRegion(cr, maClipRegion); }
+
+    bool drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice,
+                         const basegfx::B2DPolyPolygon& rPolyPolygon,
+                         double fTransparency) override;
+
+    bool drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice,
+                      const basegfx::B2DPolygon& rPolygon, double 
fTransparency, double fLineWidth,
+                      const std::vector<double>* pStroke, basegfx::B2DLineJoin 
eLineJoin,
+                      css::drawing::LineCap eLineCap, double 
fMiterMinimumAngle,
+                      bool bPixelSnapHairline) override;
+};
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/gdiimpl.cxx b/vcl/unx/generic/gdi/gdiimpl.cxx
index 53226821b4a1..d5fc4d6c1dc7 100644
--- a/vcl/unx/generic/gdi/gdiimpl.cxx
+++ b/vcl/unx/generic/gdi/gdiimpl.cxx
@@ -167,7 +167,7 @@ XID X11SalGraphicsImpl::GetXRenderPicture()
         if( !pXRenderFormat )
             return 0;
         // get the matching xrender target for drawable
-        mrParent.m_aXRenderPicture = rRenderPeer.CreatePicture( 
mrParent.hDrawable_, pXRenderFormat, 0, nullptr );
+        mrParent.m_aXRenderPicture = rRenderPeer.CreatePicture( 
mrParent.GetDrawable(), pXRenderFormat, 0, nullptr );
     }
 
     {
@@ -211,8 +211,8 @@ GC X11SalGraphicsImpl::CreateGC( Drawable hDrawable, 
unsigned long nMask )
     XGCValues values;
 
     values.graphics_exposures   = False;
-    values.foreground           = mrParent.m_pColormap->GetBlackPixel()
-                                  ^ mrParent.m_pColormap->GetWhitePixel();
+    values.foreground           = mrParent.GetColormap().GetBlackPixel()
+                                  ^ mrParent.GetColormap().GetWhitePixel();
     values.function             = GXxor;
     values.line_width           = 1;
     values.fill_style           = FillStippled;
@@ -244,8 +244,8 @@ GC X11SalGraphicsImpl::GetTrackingGC()
         XGCValues     values;
 
         values.graphics_exposures   = False;
-        values.foreground           = mrParent.m_pColormap->GetBlackPixel()
-                                      ^ mrParent.m_pColormap->GetWhitePixel();
+        values.foreground           = mrParent.GetColormap().GetBlackPixel()
+                                      ^ mrParent.GetColormap().GetWhitePixel();
         values.function             = GXxor;
         values.line_width           = 1;
         values.line_style           = LineOnOffDash;
@@ -291,8 +291,8 @@ GC X11SalGraphicsImpl::GetInvert50GC()
         XGCValues values;
 
         values.graphics_exposures   = False;
-        values.foreground           = mrParent.m_pColormap->GetWhitePixel();
-        values.background           = mrParent.m_pColormap->GetBlackPixel();
+        values.foreground           = mrParent.GetColormap().GetWhitePixel();
+        values.background           = mrParent.GetColormap().GetBlackPixel();
         values.function             = GXinvert;
         values.line_width           = 1;
         values.line_style           = LineSolid;
@@ -353,7 +353,7 @@ GC X11SalGraphicsImpl::SelectBrush()
         values.fill_rule            = EvenOddRule;      // Pict import/ 
Gradient
         values.graphics_exposures   = False;
 
-        mpBrushGC = XCreateGC( pDisplay, mrParent.hDrawable_,
+        mpBrushGC = XCreateGC( pDisplay, mrParent.GetDrawable(),
                                GCSubwindowMode | GCFillRule | 
GCGraphicsExposures,
                                &values );
     }
@@ -390,7 +390,7 @@ GC X11SalGraphicsImpl::SelectPen()
         values.fill_rule            = EvenOddRule;      // Pict import/ 
Gradient
         values.graphics_exposures   = False;
 
-        mpPenGC = XCreateGC( pDisplay, mrParent.hDrawable_,
+        mpPenGC = XCreateGC( pDisplay, mrParent.GetDrawable(),
                              GCSubwindowMode | GCFillRule | 
GCGraphicsExposures,
                              &values );
     }
@@ -742,7 +742,7 @@ bool X11SalGraphicsImpl::drawAlphaBitmap( const SalTwoRect& 
rTR,
     // create source Picture
     int nDepth = mrParent.m_pVDev ? static_cast< X11SalVirtualDevice* 
>(mrParent.m_pVDev)->GetDepth() : rSalVis.GetDepth();
     const X11SalBitmap& rSrcX11Bmp = static_cast<const X11SalBitmap&>( 
rSrcBitmap );
-    ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( mrParent.hDrawable_, 
mrParent.m_nXScreen, nDepth, rTR );
+    ImplSalDDB* pSrcDDB = rSrcX11Bmp.ImplGetDDB( mrParent.GetDrawable(), 
mrParent.m_nXScreen, nDepth, rTR );
     if( !pSrcDDB )
         return false;
 
@@ -804,7 +804,7 @@ bool X11SalGraphicsImpl::drawAlphaBitmap( const SalTwoRect& 
rTR,
         pAlphaBits, pAlphaBuffer->mnWidth, pAlphaBuffer->mnHeight,
         pAlphaFormat->depth, pAlphaBuffer->mnScanlineSize );
 
-    Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_,
+    Pixmap aAlphaPM = limitXCreatePixmap( pXDisplay, mrParent.GetDrawable(),
         rTR.mnDestWidth, rTR.mnDestHeight, 8 );
 
     XGCValues aAlphaGCV;
@@ -1184,10 +1184,10 @@ void X11SalGraphicsImpl::drawRect( tools::Long nX, 
tools::Long nY, tools::Long n
 
 void X11SalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const Point *pPtAry 
)
 {
-    drawPolyLine( nPoints, pPtAry, false );
+    internalDrawPolyLine( nPoints, pPtAry, false );
 }
 
-void X11SalGraphicsImpl::drawPolyLine( sal_uInt32 nPoints, const Point 
*pPtAry, bool bClose )
+void X11SalGraphicsImpl::internalDrawPolyLine( sal_uInt32 nPoints, const Point 
*pPtAry, bool bClose )
 {
     if( mnPenColor != SALCOLOR_NONE )
     {
@@ -1307,7 +1307,7 @@ void X11SalGraphicsImpl::drawPolyPolygon( sal_uInt32 
nPoly,
 
     if( mnPenColor != SALCOLOR_NONE )
         for( sal_uInt32 i = 0; i < nPoly; i++ )
-            drawPolyLine( pPoints[i], pPtAry[i], true );
+            internalDrawPolyLine( pPoints[i], pPtAry[i], true );
 }
 
 bool X11SalGraphicsImpl::drawPolyLineBezier( sal_uInt32, const Point*, const 
PolyFlags* )
@@ -1486,7 +1486,7 @@ bool X11SalGraphicsImpl::drawFilledTrapezoids( const 
basegfx::B2DTrapezoid* pB2D
     {
         Display* pXDisplay = mrParent.GetXDisplay();
 
-        rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_, 
1, 1, 32 );
+        rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, 
mrParent.GetDrawable(), 1, 1, 32 );
         XRenderPictureAttributes aAttr;
         aAttr.repeat = int(true);
 
@@ -1558,7 +1558,7 @@ bool X11SalGraphicsImpl::drawFilledTriangles(
     {
         Display* pXDisplay = mrParent.GetXDisplay();
 
-        rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, mrParent.hDrawable_, 
1, 1, 32 );
+        rEntry.m_aPixmap = limitXCreatePixmap( pXDisplay, 
mrParent.GetDrawable(), 1, 1, 32 );
         XRenderPictureAttributes aAttr;
         aAttr.repeat = int(true);
 
diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx
index 6257b47d613d..48211b13d472 100644
--- a/vcl/unx/generic/gdi/gdiimpl.hxx
+++ b/vcl/unx/generic/gdi/gdiimpl.hxx
@@ -101,7 +101,7 @@ private:
                                               const SalBitmap& rSalBitmap,
                                               const SalBitmap& 
rTransparentBitmap );
 
-    void drawPolyLine( sal_uInt32 nPoints, const Point* pPtAry, bool bClose );
+    void internalDrawPolyLine( sal_uInt32 nPoints, const Point* pPtAry, bool 
bClose );
 
 public:
 
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index e311ae4652f9..d6eecfecb1e8 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -58,30 +58,61 @@
 #include <cairo-xlib.h>
 
 #if ENABLE_CAIRO_CANVAS
-#include <headless/CairoCommon.hxx>
+#include "X11CairoSalGraphicsImpl.hxx"
 #endif
 
+
+// X11Common
+
+X11Common::X11Common()
+    : m_hDrawable(None)
+    , m_pColormap(nullptr)
+    , m_pExternalSurface(nullptr)
+{}
+
+cairo_t* X11Common::getCairoContext()
+{
+    if (m_pExternalSurface)
+        return cairo_create(m_pExternalSurface);
+
+    cairo_surface_t* surface = cairo_xlib_surface_create(GetXDisplay(), 
m_hDrawable, GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
+
+    cairo_t *cr = cairo_create(surface);
+    cairo_surface_destroy(surface);
+
+    return cr;
+}
+
+void X11Common::releaseCairoContext(cairo_t* cr)
+{
+   cairo_destroy(cr);
+}
+
+bool X11Common::SupportsCairo() const
+{
+    static bool bSupportsCairo = [this] {
+        Display *pDisplay = GetXDisplay();
+        int nDummy;
+        return XQueryExtension(pDisplay, "RENDER", &nDummy, &nDummy, &nDummy);
+    }();
+    return bSupportsCairo;
+}
+
+// X11SalGraphics
+
 X11SalGraphics::X11SalGraphics():
     m_pFrame(nullptr),
     m_pVDev(nullptr),
-    m_pColormap(nullptr),
-    hDrawable_(None),
-    m_pExternalSurface(nullptr),
     m_nXScreen( 0 ),
     m_pXRenderFormat(nullptr),
     m_aXRenderPicture(0),
     mpClipRegion(nullptr),
-#if ENABLE_CAIRO_CANVAS
-    mnPenColor(SALCOLOR_NONE),
-    mnFillColor(SALCOLOR_NONE),
-#endif // ENABLE_CAIRO_CANVAS
     hBrush_(None),
     bWindow_(false),
-    bVirDev_(false),
-    m_bSkia(SkiaHelper::isVCLSkiaEnabled())
+    bVirDev_(false)
 {
 #if HAVE_FEATURE_SKIA
-    if (m_bSkia)
+    if (SkiaHelper::isVCLSkiaEnabled())
     {
         mxImpl.reset(new X11SkiaSalGraphicsImpl(*this));
         mxTextRenderImpl.reset(new SkiaTextRender);
@@ -90,9 +121,12 @@ X11SalGraphics::X11SalGraphics():
 #endif
     {
         mxTextRenderImpl.reset(new X11CairoTextRender(*this));
+#if ENABLE_CAIRO_CANVAS
+        mxImpl.reset(new X11CairoSalGraphicsImpl(*this, maX11Common));
+#else
         mxImpl.reset(new X11SalGraphicsImpl(*this));
+#endif
     }
-
 }
 
 X11SalGraphics::~X11SalGraphics() COVERITY_NOEXCEPT_FALSE
@@ -122,7 +156,7 @@ void X11SalGraphics::freeResources()
     if( m_pDeleteColormap )
     {
         m_pDeleteColormap.reset();
-        m_pColormap = nullptr;
+        maX11Common.m_pColormap = nullptr;
     }
     if( m_aXRenderPicture )
     {
@@ -138,21 +172,21 @@ SalGraphicsImpl* X11SalGraphics::GetImpl() const
 
 void X11SalGraphics::SetDrawable(Drawable aDrawable, cairo_surface_t* 
pExternalSurface, SalX11Screen nXScreen)
 {
-    m_pExternalSurface = pExternalSurface;
+    maX11Common.m_pExternalSurface = pExternalSurface;
 
     // shortcut if nothing changed
-    if( hDrawable_ == aDrawable )
+    if( maX11Common.m_hDrawable == aDrawable )
         return;
 
     // free screen specific resources if needed
     if( nXScreen != m_nXScreen )
     {
         freeResources();
-        m_pColormap = 
&vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap( nXScreen );
+        maX11Common.m_pColormap = 
&vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap( nXScreen );
         m_nXScreen = nXScreen;
     }
 
-    hDrawable_ = aDrawable;
+    maX11Common.m_hDrawable = aDrawable;
     SetXRenderFormat( nullptr );
     if( m_aXRenderPicture )
     {
@@ -164,7 +198,7 @@ void X11SalGraphics::SetDrawable(Drawable aDrawable, 
cairo_surface_t* pExternalS
 void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget,
                            SalX11Screen nXScreen )
 {
-    m_pColormap = 
&vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap(nXScreen);
+    maX11Common.m_pColormap = 
&vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap(nXScreen);
     m_nXScreen  = nXScreen;
 
     m_pFrame    = pFrame;
@@ -328,58 +362,6 @@ void X11SalGraphics::GetResolution( sal_Int32 &rDPIX, 
sal_Int32 &rDPIY ) // cons
     rDPIX = rDPIY; // y-resolution is more trustworthy
 }
 
-void X11SalGraphics::ResetClipRegion()
-{
-#if ENABLE_CAIRO_CANVAS
-    maClipRegion.SetNull();
-#endif
-    SalGraphicsAutoDelegateToImpl::ResetClipRegion();
-}
-
-bool X11SalGraphics::setClipRegion( const vcl::Region& i_rClip )
-{
-#if ENABLE_CAIRO_CANVAS
-    maClipRegion = i_rClip;
-#endif
-    return SalGraphicsAutoDelegateToImpl::setClipRegion( i_rClip );
-}
-
-void X11SalGraphics::SetLineColor()
-{
-#if ENABLE_CAIRO_CANVAS
-    mnPenColor = SALCOLOR_NONE;
-#endif // ENABLE_CAIRO_CANVAS
-
-    SalGraphicsAutoDelegateToImpl::SetLineColor();
-}
-
-void X11SalGraphics::SetLineColor( Color nColor )
-{
-#if ENABLE_CAIRO_CANVAS
-    mnPenColor = nColor;
-#endif // ENABLE_CAIRO_CANVAS
-
-    SalGraphicsAutoDelegateToImpl::SetLineColor( nColor );
-}
-
-void X11SalGraphics::SetFillColor()
-{
-#if ENABLE_CAIRO_CANVAS
-    mnFillColor = SALCOLOR_NONE;
-#endif // ENABLE_CAIRO_CANVAS
-
-    SalGraphicsAutoDelegateToImpl::SetFillColor();
-}
-
-void X11SalGraphics::SetFillColor( Color nColor )
-{
-#if ENABLE_CAIRO_CANVAS
-    mnFillColor = nColor;
-#endif // ENABLE_CAIRO_CANVAS
-
-    SalGraphicsAutoDelegateToImpl::SetFillColor( nColor );
-}
-
 XRenderPictFormat* X11SalGraphics::GetXRenderFormat() const
 {
     if( m_pXRenderFormat == nullptr )
@@ -393,7 +375,7 @@ SystemGraphicsData X11SalGraphics::GetGraphicsData() const
 
     aRes.nSize = sizeof(aRes);
     aRes.pDisplay  = GetXDisplay();
-    aRes.hDrawable = hDrawable_;
+    aRes.hDrawable = maX11Common.m_hDrawable;
     aRes.pVisual   = GetVisual().visual;
     aRes.nScreen   = m_nXScreen.getXScreen();
     aRes.pXRenderFormat = m_pXRenderFormat;
@@ -410,12 +392,7 @@ void X11SalGraphics::Flush()
 
 bool X11SalGraphics::SupportsCairo() const
 {
-    static bool bSupportsCairo = [this] {
-        Display *pDisplay = GetXDisplay();
-        int nDummy;
-        return XQueryExtension(pDisplay, "RENDER", &nDummy, &nDummy, &nDummy);
-    }();
-    return bSupportsCairo;
+    return maX11Common.SupportsCairo();
 }
 
 cairo::SurfaceSharedPtr X11SalGraphics::CreateSurface(const 
cairo::CairoSurfaceSharedPtr& rSurface) const
@@ -484,201 +461,6 @@ css::uno::Any 
X11SalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr& rS
 
 #endif // ENABLE_CAIRO_CANVAS
 
-// draw a poly-polygon
-bool X11SalGraphics::drawPolyPolygon(
-    const basegfx::B2DHomMatrix& rObjectToDevice,
-    const basegfx::B2DPolyPolygon& rPolyPolygon,
-    double fTransparency)
-{
-#if ENABLE_CAIRO_CANVAS
-    if(fTransparency >= 1.0)
-    {
-        return true;
-    }
-
-    if(rPolyPolygon.count() == 0)
-    {
-        return true;
-    }
-
-    // Fallback: Transform to DeviceCoordinates
-    basegfx::B2DPolyPolygon aPolyPolygon(rPolyPolygon);
-    aPolyPolygon.transform(rObjectToDevice);
-
-    if(SALCOLOR_NONE == mnFillColor && SALCOLOR_NONE == mnPenColor)
-    {
-        return true;
-    }
-
-    // enable by setting to something
-    static const char* 
pUseCairoForPolygons(getenv("SAL_ENABLE_USE_CAIRO_FOR_POLYGONS"));
-
-    if (!m_bSkia && nullptr != pUseCairoForPolygons && SupportsCairo())
-    {
-        // snap to raster if requested
-        const bool bSnapPoints(!getAntiAlias());
-
-        if(bSnapPoints)
-        {
-            aPolyPolygon = 
basegfx::utils::snapPointsOfHorizontalOrVerticalEdges(aPolyPolygon);
-        }
-
-        cairo_t* cr = getCairoContext();
-        clipRegion(cr);
-
-        for(auto const& rPolygon : std::as_const(aPolyPolygon))
-        {
-            const sal_uInt32 nPointCount(rPolygon.count());
-
-            if(nPointCount)
-            {
-                const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nPointCount 
: nPointCount - 1);
-
-                if(nEdgeCount)
-                {
-                    basegfx::B2DCubicBezier aEdge;
-
-                    for(sal_uInt32 b = 0; b < nEdgeCount; ++b)
-                    {
-                        rPolygon.getBezierSegment(b, aEdge);
-
-                        if(!b)
-                        {
-                            const basegfx::B2DPoint 
aStart(aEdge.getStartPoint());
-                            cairo_move_to(cr, aStart.getX(), aStart.getY());
-                        }
-
-                        const basegfx::B2DPoint aEnd(aEdge.getEndPoint());
-
-                        if(aEdge.isBezier())
-                        {
-                            const basegfx::B2DPoint 
aCP1(aEdge.getControlPointA());
-                            const basegfx::B2DPoint 
aCP2(aEdge.getControlPointB());
-                            cairo_curve_to(cr,
-                                aCP1.getX(), aCP1.getY(),
-                                aCP2.getX(), aCP2.getY(),
-                                aEnd.getX(), aEnd.getY());
-                        }
-                        else
-                        {
-                            cairo_line_to(cr, aEnd.getX(), aEnd.getY());
-                        }
-                    }
-
-                    cairo_close_path(cr);
-                }
-            }
-        }
-
-        if(SALCOLOR_NONE != mnFillColor)
-        {
-            cairo_set_source_rgba(cr,
-                mnFillColor.GetRed()/255.0,
-                mnFillColor.GetGreen()/255.0,
-                mnFillColor.GetBlue()/255.0,
-                1.0 - fTransparency);
-            cairo_set_fill_rule(cr, CAIRO_FILL_RULE_EVEN_ODD);
-            cairo_fill_preserve(cr);
-        }
-
-        if(SALCOLOR_NONE != mnPenColor)
-        {
-            cairo_set_source_rgba(cr,
-                    mnPenColor.GetRed()/255.0,
-                    mnPenColor.GetGreen()/255.0,
-                    mnPenColor.GetBlue()/255.0,
-                    1.0 - fTransparency);
-            cairo_stroke_preserve(cr);
-        }
-
-        releaseCairoContext(cr);
-        return true;
-    }
-#endif // ENABLE_CAIRO_CANVAS
-
-    return SalGraphicsAutoDelegateToImpl::drawPolyPolygon(
-        rObjectToDevice,
-        rPolyPolygon,
-        fTransparency);
-}
-
-#if ENABLE_CAIRO_CANVAS
-void X11SalGraphics::clipRegion(cairo_t* cr)
-{
-    CairoCommon::clipRegion(cr, maClipRegion);
-}
-#endif // ENABLE_CAIRO_CANVAS
-
-bool X11SalGraphics::drawPolyLine(
-    const basegfx::B2DHomMatrix& rObjectToDevice,
-    const basegfx::B2DPolygon& rPolygon,
-    double fTransparency,
-    double fLineWidth,
-    const std::vector< double >* pStroke, // MM01
-    basegfx::B2DLineJoin eLineJoin,
-    css::drawing::LineCap eLineCap,
-    double fMiterMinimumAngle,
-    bool bPixelSnapHairline)
-{
-#if ENABLE_CAIRO_CANVAS
-    if(0 == rPolygon.count())
-    {
-        return true;
-    }
-
-    if(fTransparency >= 1.0)
-    {
-        return true;
-    }
-
-
-    // disable by setting to something
-    static const char* 
pUseCairoForFatLines(getenv("SAL_DISABLE_USE_CAIRO_FOR_FATLINES"));
-
-    if (!m_bSkia && nullptr == pUseCairoForFatLines && SupportsCairo())
-    {
-        cairo_t* cr = getCairoContext();
-        clipRegion(cr);
-
-        // Use the now available static drawPolyLine from the 
Cairo-Headless-Fallback
-        // that will take care of all needed stuff
-        const bool bRetval(
-            CairoCommon::drawPolyLine(
-                cr,
-                nullptr,
-                mnPenColor,
-                getAntiAlias(),
-                rObjectToDevice,
-                rPolygon,
-                fTransparency,
-                fLineWidth,
-                pStroke, // MM01
-                eLineJoin,
-                eLineCap,
-                fMiterMinimumAngle,
-                bPixelSnapHairline));
-
-        releaseCairoContext(cr);
-
-        if(bRetval)
-        {
-            return true;
-        }
-    }
-#endif // ENABLE_CAIRO_CANVAS
-
-    return SalGraphicsAutoDelegateToImpl::drawPolyLine(
-        rObjectToDevice,
-        rPolygon,
-        fTransparency,
-        fLineWidth,
-        pStroke, // MM01
-        eLineJoin,
-        eLineCap,
-        fMiterMinimumAngle,
-        bPixelSnapHairline);
-}
-
 SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const
 {
     if (m_pFrame)
@@ -689,21 +471,12 @@ SalGeometryProvider 
*X11SalGraphics::GetGeometryProvider() const
 
 cairo_t* X11SalGraphics::getCairoContext()
 {
-    if (m_pExternalSurface)
-        return cairo_create(m_pExternalSurface);
-
-    cairo_surface_t* surface = cairo_xlib_surface_create(GetXDisplay(), 
hDrawable_,
-            GetVisual().visual, SAL_MAX_INT16, SAL_MAX_INT16);
-
-    cairo_t *cr = cairo_create(surface);
-    cairo_surface_destroy(surface);
-
-    return cr;
+    return maX11Common.getCairoContext();
 }
 
 void X11SalGraphics::releaseCairoContext(cairo_t* cr)
 {
-   cairo_destroy(cr);
+   X11Common::releaseCairoContext(cr);
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/salvd.cxx b/vcl/unx/generic/gdi/salvd.cxx
index dcb3a5e897b8..f5e4449c625d 100644
--- a/vcl/unx/generic/gdi/salvd.cxx
+++ b/vcl/unx/generic/gdi/salvd.cxx
@@ -64,16 +64,16 @@ void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, 
cairo_surface_t* pPreEx
 
     if( pColormap )
     {
-        m_pColormap = pColormap;
+        maX11Common.m_pColormap = pColormap;
         if( bDeleteColormap )
             m_pDeleteColormap.reset(pColormap);
     }
     else if( nDeviceDepth == nVisualDepth )
-        m_pColormap = &pDisplay->GetColormap( m_nXScreen );
+        maX11Common.m_pColormap = &pDisplay->GetColormap( m_nXScreen );
     else if( nDeviceDepth == 1 )
     {
         m_pDeleteColormap.reset(new SalColormap());
-        m_pColormap = m_pDeleteColormap.get();
+        maX11Common.m_pColormap = m_pDeleteColormap.get();
     }
 
     m_pVDev      = pDevice;

Reply via email to