drawinglayer/source/primitive2d/textlayoutdevice.cxx       |   32 ++
 drawinglayer/source/processor2d/cairopixelprocessor2d.cxx  |  158 ++++++++++++-
 include/drawinglayer/primitive2d/textlayoutdevice.hxx      |   19 +
 include/drawinglayer/processor2d/cairopixelprocessor2d.hxx |   11 
 include/vcl/vcllayout.hxx                                  |    3 
 vcl/headless/svptext.cxx                                   |   10 
 vcl/inc/headless/svpgdi.hxx                                |    1 
 vcl/inc/salgdi.hxx                                         |    1 
 vcl/inc/sallayout.hxx                                      |    2 
 vcl/inc/unx/cairotextrender.hxx                            |    7 
 vcl/source/gdi/CommonSalLayout.cxx                         |    5 
 vcl/unx/generic/gdi/cairotextrender.cxx                    |   37 +--
 12 files changed, 265 insertions(+), 21 deletions(-)

New commits:
commit bf9e8d5ffd3f29fa027f0009a70f27d3456b648b
Author:     Armin Le Grand (Collabora) <[email protected]>
AuthorDate: Fri Aug 2 15:56:52 2024 +0200
Commit:     Armin Le Grand <[email protected]>
CommitDate: Mon Aug 5 12:29:02 2024 +0200

    CairoSDPR: direct text rendering using Cairo
    
    I have added basic support for the text primitives
    (TextSimplePortionPrimitive2D) to the SDPR Cairo
    renderer. It can now basically render Text using
    a fallback to the already existing CairoTextRender.
    
    NOTE: This is not yet complete, but for discussion.
    Change-Id: I9b0c7b6bb4892905576593ef4e2b4071c7663c63
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/171429
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <[email protected]>

diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx 
b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
index 3daecb4bec62..3a6667d0461f 100644
--- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx
+++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx
@@ -38,6 +38,8 @@
 #include <vcl/metric.hxx>
 #include <i18nlangtag/languagetag.hxx>
 #include <vcl/svapp.hxx>
+#include <vcl/vcllayout.hxx>
+#include <vcl/glyphitemcache.hxx>
 
 namespace drawinglayer::primitive2d
 {
@@ -192,6 +194,21 @@ void TextLayouterDevice::setFontAttribute(const 
attribute::FontAttribute& rFontA
     }
 }
 
+void TextLayouterDevice::setLayoutMode(vcl::text::ComplexTextLayoutFlags 
nTextLayoutMode)
+{
+    mrDevice.SetLayoutMode(nTextLayoutMode);
+}
+
+vcl::text::ComplexTextLayoutFlags TextLayouterDevice::getLayoutMode() const
+{
+    return mrDevice.GetLayoutMode();
+}
+
+void TextLayouterDevice::setTextColor(const basegfx::BColor& rColor)
+{
+    mrDevice.SetTextColor(Color(rColor));
+}
+
 double TextLayouterDevice::getOverlineOffset() const
 {
     const ::FontMetric& rMetric = mrDevice.GetFontMetric();
@@ -348,6 +365,21 @@ std::vector<double> TextLayouterDevice::getTextArray(const 
OUString& rText, sal_
     return aRetval;
 }
 
+std::unique_ptr<SalLayout> TextLayouterDevice::getSalLayout(const OUString& 
rText,
+                                                            sal_uInt32 nIndex, 
sal_uInt32 nLength,
+                                                            const 
basegfx::B2DPoint& rStartPoint,
+                                                            const KernArray& 
rDXArray,
+                                                            std::span<const 
sal_Bool> pKashidaAry)
+{
+    const SalLayoutGlyphs* pGlyphs(
+        SalLayoutGlyphsCache::self()->GetLayoutGlyphs(&mrDevice, rText, 
nIndex, nLength));
+    const Point aStartPoint(basegfx::fround<tools::Long>(rStartPoint.getX()),
+                            basegfx::fround<tools::Long>(rStartPoint.getY()));
+    KernArraySpan aKernArraySpan(rDXArray);
+    return mrDevice.ImplLayout(rText, nIndex, nLength, aStartPoint, 0, 
aKernArraySpan, pKashidaAry,
+                               SalLayoutFlags::NONE, nullptr, pGlyphs);
+}
+
 // helper methods for vcl font handling
 
 vcl::Font getVclFontFromFontAttribute(const attribute::FontAttribute& 
rFontAttribute,
diff --git a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx 
b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
index f6483e4a795e..baea016068c1 100644
--- a/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/cairopixelprocessor2d.cxx
@@ -39,12 +39,17 @@
 #include <drawinglayer/primitive2d/PolyPolygonGradientPrimitive2D.hxx>
 #include <drawinglayer/primitive2d/PolyPolygonRGBAPrimitive2D.hxx>
 #include <drawinglayer/primitive2d/BitmapAlphaPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/textprimitive2d.hxx>
+#include <drawinglayer/primitive2d/textdecoratedprimitive2d.hxx>
 #include <drawinglayer/converters.hxx>
+#include <drawinglayer/primitive2d/textlayoutdevice.hxx>
 #include <basegfx/curve/b2dcubicbezier.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <basegfx/utils/systemdependentdata.hxx>
 #include <basegfx/utils/bgradient.hxx>
 #include <vcl/BitmapReadAccess.hxx>
+#include <officecfg/Office/Common.hxx>
+#include <vcl/vcllayout.hxx>
 #include <unordered_map>
 #include <dlfcn.h>
 
@@ -285,7 +290,7 @@ void checkAndDoPixelSnap(cairo_t* pRT,
 
     // with the comments above at CairoPathHelper we cannot do PixelSnap
     // at path construction time, so it needs to be done *after* the path
-    // data is added to the cairo context. ADvantage is that all general
+    // data is added to the cairo context. Advantage is that all general
     // path data can be buffered, though, but needs view-dependent manipulation
     // here after being added.
     // For now, just snap all points - no real need to identify hor/ver lines
@@ -807,6 +812,10 @@ CairoPixelProcessor2D::CairoPixelProcessor2D(const 
geometry::ViewInformation2D&
     : BaseProcessor2D(rViewInformation)
     , maBColorModifierStack()
     , mpRT(nullptr)
+    , mbRenderSimpleTextDirect(
+          
officecfg::Office::Common::Drawinglayer::RenderSimpleTextDirect::get())
+    , mbRenderDecoratedTextDirect(
+          
officecfg::Office::Common::Drawinglayer::RenderDecoratedTextDirect::get())
 {
     if (pTarget)
     {
@@ -2793,6 +2802,141 @@ void 
CairoPixelProcessor2D::processBitmapAlphaPrimitive2D(
                      rBitmapAlphaPrimitive2D.getTransparency());
 }
 
+void CairoPixelProcessor2D::processTextSimplePortionPrimitive2D(
+    const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+{
+    if (SAL_LIKELY(mbRenderSimpleTextDirect))
+    {
+        renderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
+    }
+    else
+    {
+        process(rCandidate);
+    }
+}
+
+void CairoPixelProcessor2D::processTextDecoratedPortionPrimitive2D(
+    const primitive2d::TextSimplePortionPrimitive2D& rCandidate)
+{
+    if (SAL_LIKELY(mbRenderDecoratedTextDirect))
+    {
+        renderTextSimpleOrDecoratedPortionPrimitive2D(rCandidate);
+    }
+    else
+    {
+        process(rCandidate);
+    }
+}
+
+void CairoPixelProcessor2D::renderTextSimpleOrDecoratedPortionPrimitive2D(
+    const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate)
+{
+    // decompose matrix to have global position and scale of text
+    const basegfx::B2DHomMatrix aGlobalFontTransform(
+        getViewInformation2D().getObjectToViewTransformation() * 
rTextCandidate.getTextTransform());
+    basegfx::B2DVector aGlobalFontScaling, aGlobalFontTranslate;
+    double fGlobalFontRotate, fGlobalFontShearX;
+    aGlobalFontTransform.decompose(aGlobalFontScaling, aGlobalFontTranslate, 
fGlobalFontRotate,
+                                   fGlobalFontShearX);
+
+    // decompose primitive-local matrix to get local font scaling
+    double fLocalFontRotate, fLocalFontShearX;
+    basegfx::B2DVector aLocalFontSize, aLocalFontTranslate;
+    rTextCandidate.getTextTransform().decompose(aLocalFontSize, 
aLocalFontTranslate,
+                                                fLocalFontRotate, 
fLocalFontShearX);
+
+    // Get the VCL font from existing processor tooling. Do not use
+    // rotation, for Cairo we can transform the whole text render and
+    // thus handle the xext in it's local coordinate system untransformed
+    vcl::Font aFont(primitive2d::getVclFontFromFontAttribute(
+        rTextCandidate.getFontAttribute(), aGlobalFontScaling.getX(), 
aGlobalFontScaling.getY(),
+        0.0, rTextCandidate.getLocale()));
+
+    if (aFont.GetFontSize().Height() <= 0)
+    {
+        // Don't draw fonts without height, error. use decompose as fallback
+        process(rTextCandidate);
+        return;
+    }
+
+    // set FillColor Attribute at Font
+    Color aFillColor(
+        
maBColorModifierStack.getModifiedColor(rTextCandidate.getTextFillColor().getBColor()));
+    aFont.SetTransparent(rTextCandidate.getTextFillColor().IsTransparent());
+    if (rTextCandidate.getTextFillColor().IsTransparent())
+        aFillColor.SetAlpha(rTextCandidate.getTextFillColor().GetAlpha());
+    aFont.SetFillColor(aFillColor);
+
+    // create integer DXArray. As mentioned above we can act in the
+    // Text's local coordinate system without transformation at all
+    const ::std::vector<double>& rDXArray(rTextCandidate.getDXArray());
+    KernArray aDXArray;
+
+    if (!rDXArray.empty())
+    {
+        aDXArray.reserve(rDXArray.size());
+        for (auto const& elem : rDXArray)
+            aDXArray.push_back(basegfx::fround(elem));
+    }
+
+    // set parameters and paint text snippet
+    const basegfx::BColor aRGBFontColor(
+        maBColorModifierStack.getModifiedColor(rTextCandidate.getFontColor()));
+
+    // create a TextLayouter to access encapsulated VCL Text/Font related 
tooling
+    primitive2d::TextLayouterDevice aTextLayouter;
+    aTextLayouter.setFontAttribute(rTextCandidate.getFontAttribute(), 
aLocalFontSize.getX(),
+                                   aLocalFontSize.getY(), 
rTextCandidate.getLocale());
+    aTextLayouter.setTextColor(aRGBFontColor);
+
+    if (rTextCandidate.getFontAttribute().getRTL())
+    {
+        vcl::text::ComplexTextLayoutFlags nRTLLayoutMode(
+            aTextLayouter.getLayoutMode() & 
~vcl::text::ComplexTextLayoutFlags::BiDiStrong);
+        nRTLLayoutMode |= vcl::text::ComplexTextLayoutFlags::BiDiRtl
+                          | vcl::text::ComplexTextLayoutFlags::TextOriginLeft;
+        aTextLayouter.setLayoutMode(nRTLLayoutMode);
+    }
+    else
+    {
+        // tdf#101686: This is LTR text, but the output device may have RTL 
state.
+        vcl::text::ComplexTextLayoutFlags 
nLTRLayoutMode(aTextLayouter.getLayoutMode());
+        nLTRLayoutMode = nLTRLayoutMode & 
~vcl::text::ComplexTextLayoutFlags::BiDiRtl;
+        nLTRLayoutMode = nLTRLayoutMode & 
~vcl::text::ComplexTextLayoutFlags::BiDiStrong;
+        aTextLayouter.setLayoutMode(nLTRLayoutMode);
+    }
+
+    // create SalLayout. No need for a position, as mentioned text can work
+    // without transformations, so start point is always 0,0
+    std::unique_ptr<SalLayout> pSalLayout(aTextLayouter.getSalLayout(
+        rTextCandidate.getText(), rTextCandidate.getTextPosition(), 
rTextCandidate.getTextLength(),
+        basegfx::B2DPoint(0.0, 0.0), aDXArray, 
rTextCandidate.getKashidaArray()));
+
+    if (!pSalLayout)
+    {
+        // got no layout, error. use decompose as fallback
+        process(rTextCandidate);
+        return;
+    }
+
+    // draw using Cairo, use existing tooling (this tunnels to
+    // CairoTextRender::ImplDrawTextLayout)
+    cairo_save(mpRT);
+    const basegfx::B2DHomMatrix aObjTransformWithoutScale(
+        
basegfx::utils::createShearXRotateTranslateB2DHomMatrix(fLocalFontShearX, 
fLocalFontRotate,
+                                                                
aLocalFontTranslate));
+    const basegfx::B2DHomMatrix aFullTextTransform(
+        getViewInformation2D().getObjectToViewTransformation() * 
aObjTransformWithoutScale);
+
+    cairo_matrix_t aMatrix;
+    cairo_matrix_init(&aMatrix, aFullTextTransform.a(), aFullTextTransform.b(),
+                      aFullTextTransform.c(), aFullTextTransform.d(), 
aFullTextTransform.e(),
+                      aFullTextTransform.f());
+    cairo_set_matrix(mpRT, &aMatrix);
+    pSalLayout->drawSalLayout(mpRT, aRGBFontColor, 
getViewInformation2D().getUseAntiAliasing());
+    cairo_restore(mpRT);
+}
+
 void CairoPixelProcessor2D::processBasePrimitive2D(const 
primitive2d::BasePrimitive2D& rCandidate)
 {
     switch (rCandidate.getPrimitive2DID())
@@ -2921,6 +3065,18 @@ void CairoPixelProcessor2D::processBasePrimitive2D(const 
primitive2d::BasePrimit
                 static_cast<const 
primitive2d::BitmapAlphaPrimitive2D&>(rCandidate));
             break;
         }
+        case PRIMITIVE2D_ID_TEXTSIMPLEPORTIONPRIMITIVE2D:
+        {
+            processTextSimplePortionPrimitive2D(
+                static_cast<const 
primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
+            break;
+        }
+        case PRIMITIVE2D_ID_TEXTDECORATEDPORTIONPRIMITIVE2D:
+        {
+            processTextDecoratedPortionPrimitive2D(
+                static_cast<const 
primitive2d::TextSimplePortionPrimitive2D&>(rCandidate));
+            break;
+        }
 
         // continue with decompose
         default:
diff --git a/include/drawinglayer/primitive2d/textlayoutdevice.hxx 
b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
index db019494a8c0..de7a1e214a2a 100644
--- a/include/drawinglayer/primitive2d/textlayoutdevice.hxx
+++ b/include/drawinglayer/primitive2d/textlayoutdevice.hxx
@@ -25,11 +25,14 @@
 #include <vector>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <vcl/svapp.hxx>
+#include <span>
 
 // predefines
 class VirtualDevice;
 class GDIMetaFile;
 enum class DrawTextFlags;
+class SalLayout;
+class KernArray;
 namespace vcl
 {
 class Font;
@@ -46,6 +49,14 @@ namespace com::sun::star::lang
 {
 struct Locale;
 }
+namespace vcl::text
+{
+enum class ComplexTextLayoutFlags : sal_uInt8;
+}
+namespace basegfx
+{
+class BColor;
+}
 
 // access to one global impTimedRefDev incarnation in namespace 
drawinglayer::primitive
 
@@ -75,6 +86,9 @@ public:
     void setFont(const vcl::Font& rFont);
     void setFontAttribute(const attribute::FontAttribute& rFontAttribute, 
double fFontScaleX,
                           double fFontScaleY, const css::lang::Locale& 
rLocale);
+    void setLayoutMode(vcl::text::ComplexTextLayoutFlags nTextLayoutMode);
+    vcl::text::ComplexTextLayoutFlags getLayoutMode() const;
+    void setTextColor(const basegfx::BColor& rColor);
 
     double getTextHeight() const;
     double getOverlineHeight() const;
@@ -100,6 +114,11 @@ public:
 
     ::std::vector<double> getTextArray(const OUString& rText, sal_uInt32 
nIndex, sal_uInt32 nLength,
                                        bool bCaret = false) const;
+    std::unique_ptr<SalLayout> getSalLayout(const OUString& rText, sal_uInt32 
nIndex,
+                                            sal_uInt32 nLength,
+                                            const basegfx::B2DPoint& 
rStartPoint,
+                                            const KernArray& rDXArray,
+                                            std::span<const sal_Bool> 
pKashidaAry);
 };
 
 // helper methods for vcl font handling
diff --git a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx 
b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
index 129daaef86fa..21cffda24e7c 100644
--- a/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
+++ b/include/drawinglayer/processor2d/cairopixelprocessor2d.hxx
@@ -39,6 +39,7 @@ class PolyPolygonRGBAGradientPrimitive2D;
 class FillGraphicPrimitive2D;
 class PolyPolygonRGBAPrimitive2D;
 class BitmapAlphaPrimitive2D;
+class TextSimplePortionPrimitive2D;
 }
 
 namespace basegfx
@@ -58,6 +59,10 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) 
CairoPixelProcessor2D final : pub
     // cairo specific data
     cairo_t* mpRT;
 
+    // get text render config settings
+    bool mbRenderSimpleTextDirect;
+    bool mbRenderDecoratedTextDirect;
+
     // helpers for direct paints
     void paintPolyPoylgonRGBA(const basegfx::B2DPolyPolygon& rPolyPolygon,
                               const basegfx::BColor& rColor, double 
fTransparency = 0.0);
@@ -99,6 +104,12 @@ class UNLESS_MERGELIBS(DRAWINGLAYER_DLLPUBLIC) 
CairoPixelProcessor2D final : pub
                           double fTransparency = 0.0);
     void processBitmapAlphaPrimitive2D(
         const primitive2d::BitmapAlphaPrimitive2D& rBitmapAlphaPrimitive2D);
+    void processTextSimplePortionPrimitive2D(
+        const primitive2d::TextSimplePortionPrimitive2D& rCandidate);
+    void processTextDecoratedPortionPrimitive2D(
+        const primitive2d::TextSimplePortionPrimitive2D& rCandidate);
+    void renderTextSimpleOrDecoratedPortionPrimitive2D(
+        const primitive2d::TextSimplePortionPrimitive2D& rTextCandidate);
 
     /*  the local processor for BasePrimitive2D-Implementation based 
primitives,
         called from the common process()-implementation
diff --git a/include/vcl/vcllayout.hxx b/include/vcl/vcllayout.hxx
index dd0747eae3ec..9c84d7453a3c 100644
--- a/include/vcl/vcllayout.hxx
+++ b/include/vcl/vcllayout.hxx
@@ -32,6 +32,7 @@
 class LogicalFontInstance;
 namespace vcl::text { class ImplLayoutArgs; }
 namespace vcl::font { class PhysicalFontFace; }
+namespace basegfx { class BColor; }
 class SalGraphics;
 class GlyphItem;
 
@@ -120,6 +121,8 @@ public:
 
     virtual SalLayoutGlyphs GetGlyphs() const;
 
+    virtual void drawSalLayout(void* /*pSurface*/, const basegfx::BColor& 
/*rTextColor*/, bool /*bAntiAliased*/) const {}
+
 protected:
     // used by layout engines
     SalLayout();
diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx
index ff9653aa6f6d..22b7b37c5507 100644
--- a/vcl/headless/svptext.cxx
+++ b/vcl/headless/svptext.cxx
@@ -69,6 +69,16 @@ void SvpSalGraphics::DrawTextLayout(const GenericSalLayout& 
rLayout)
     m_aTextRenderImpl.DrawTextLayout(rLayout, *this);
 }
 
+void SvpSalGraphics::DrawSalLayout(const GenericSalLayout& rLayout, void* 
pSurface, const basegfx::BColor& rTextColor, bool bAntiAliased) const
+{
+    CairoTextRender::ImplDrawTextLayout(
+        static_cast<cairo_t*>(pSurface),
+        Color(rTextColor),
+        rLayout,
+        nullptr,
+        bAntiAliased);
+}
+
 void SvpSalGraphics::SetTextColor( Color nColor )
 {
     m_aTextRenderImpl.SetTextColor(nColor);
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 78d04d753ac4..0c4476e9aa5b 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -78,6 +78,7 @@ public:
     virtual std::unique_ptr<GenericSalLayout>
                             GetTextLayout(int nFallbackLevel) override;
     virtual void            DrawTextLayout( const GenericSalLayout& ) override;
+    virtual void DrawSalLayout(const GenericSalLayout& rLayout, void* 
pSurface, const basegfx::BColor& rTextColor, bool bAntiAliased) const override;
 
     virtual bool            ShouldDownscaleIconsAtSurface(double* pScaleOut) 
const override;
 
diff --git a/vcl/inc/salgdi.hxx b/vcl/inc/salgdi.hxx
index d592bc10daea..4296cb4e3e51 100644
--- a/vcl/inc/salgdi.hxx
+++ b/vcl/inc/salgdi.hxx
@@ -162,6 +162,7 @@ public:
     virtual std::unique_ptr<GenericSalLayout>
                                 GetTextLayout(int nFallbackLevel) = 0;
     virtual void                DrawTextLayout( const GenericSalLayout& ) = 0;
+    virtual void DrawSalLayout(const GenericSalLayout&, void*, const 
basegfx::BColor&, bool ) const {}
 
     virtual bool                supportsOperation( OutDevSupportType ) const = 
0;
 
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index 0b10629fcb3e..fdb5151bc2a5 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -136,6 +136,8 @@ public:
 
     const SalLayoutGlyphsImpl& GlyphsImpl() const { return m_GlyphItems; }
 
+    virtual void drawSalLayout(void* /*pSurface*/, const basegfx::BColor& 
/*rTextColor*/, bool /*bAntiAliased*/) const override;
+
 private:
     // for glyph+font+script fallback
     SAL_DLLPRIVATE void MoveGlyph(int nStart, double nNewXPos);
diff --git a/vcl/inc/unx/cairotextrender.hxx b/vcl/inc/unx/cairotextrender.hxx
index 50848ed19fa6..e98d12bf207e 100644
--- a/vcl/inc/unx/cairotextrender.hxx
+++ b/vcl/inc/unx/cairotextrender.hxx
@@ -34,10 +34,13 @@ private:
 protected:
     cairo_t*                getCairoContext();
     void                    releaseCairoContext(cairo_t* cr);
-    void                    clipRegion(cairo_t* cr);
 
 public:
-    virtual void            DrawTextLayout(const GenericSalLayout&, const 
SalGraphics&) override;
+    // helper to call DrawTextLayout with already setup cairo_t context,
+    // so no CairoCommon is needed.
+    static void ImplDrawTextLayout(cairo_t* cr, const Color& rTextColor, const 
GenericSalLayout& rLayout, CairoCommon* pCairoCommon, bool bAntiAlias);
+
+    virtual void DrawTextLayout(const GenericSalLayout&, const SalGraphics&) 
override;
     CairoTextRender(CairoCommon& rCairoCommon);
     virtual ~CairoTextRender();
 };
diff --git a/vcl/source/gdi/CommonSalLayout.cxx 
b/vcl/source/gdi/CommonSalLayout.cxx
index e11fcbacd35a..2463301a4d05 100644
--- a/vcl/source/gdi/CommonSalLayout.cxx
+++ b/vcl/source/gdi/CommonSalLayout.cxx
@@ -1029,4 +1029,9 @@ bool GenericSalLayout::IsKashidaPosValid(int nCharPos, 
int nNextCharPos) const
     return rNextGlyph->IsSafeToInsertKashida();
 }
 
+void GenericSalLayout::drawSalLayout(void* pSurface, const basegfx::BColor& 
rTextColor, bool bAntiAliased) const
+{
+    Application::GetDefaultDevice()->GetGraphics()->DrawSalLayout(*this, 
pSurface, rTextColor, bAntiAliased);
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/unx/generic/gdi/cairotextrender.cxx 
b/vcl/unx/generic/gdi/cairotextrender.cxx
index 7e7ce9ca700f..9c201a2cc1ec 100644
--- a/vcl/unx/generic/gdi/cairotextrender.cxx
+++ b/vcl/unx/generic/gdi/cairotextrender.cxx
@@ -240,10 +240,6 @@ static CairoFontsCache::CacheId makeCacheId(const 
GenericSalLayout& rLayout)
 
 void CairoTextRender::DrawTextLayout(const GenericSalLayout& rLayout, const 
SalGraphics& rGraphics)
 {
-    const LogicalFontInstance& rInstance = rLayout.GetFont();
-
-    const bool bSubpixelPositioning = rLayout.GetSubpixelPositioning();
-
     /*
      * It might be ideal to cache surface and cairo context between calls and
      * only destroy it when the drawable changes, but to do that we need to at
@@ -258,6 +254,15 @@ void CairoTextRender::DrawTextLayout(const 
GenericSalLayout& rLayout, const SalG
     }
     comphelper::ScopeGuard releaseContext([this, cr]() { 
releaseCairoContext(cr); });
 
+    // void CairoCommon::clipRegion(cairo_t* cr) { CairoCommon::clipRegion(cr, 
m_aClipRegion); }
+    ImplDrawTextLayout(cr, mnTextColor, rLayout, &mrCairoCommon, 
rGraphics.getAntiAlias());
+}
+
+void CairoTextRender::ImplDrawTextLayout(cairo_t* cr, const Color& rTextColor, 
const GenericSalLayout& rLayout, CairoCommon* pCairoCommon, bool bAntiAlias)
+{
+    const LogicalFontInstance& rInstance = rLayout.GetFont();
+    const bool bSubpixelPositioning = rLayout.GetSubpixelPositioning();
+
     std::vector<cairo_glyph_t> cairo_glyphs;
     std::vector<int> glyph_extrarotation;
     cairo_glyphs.reserve( 256 );
@@ -342,13 +347,14 @@ void CairoTextRender::DrawTextLayout(const 
GenericSalLayout& rLayout, const SalG
     }
 #endif
 
-    clipRegion(cr);
+    if (nullptr != pCairoCommon)
+        pCairoCommon->clipRegion(cr);
 
     cairo_set_source_rgba(cr,
-        mnTextColor.GetRed()/255.0,
-        mnTextColor.GetGreen()/255.0,
-        mnTextColor.GetBlue()/255.0,
-        mnTextColor.GetAlpha()/255.0);
+        rTextColor.GetRed()/255.0,
+        rTextColor.GetGreen()/255.0,
+        rTextColor.GetBlue()/255.0,
+        rTextColor.GetAlpha()/255.0);
 
     int nRatio = nWidth * 10 / nHeight;
 
@@ -381,9 +387,9 @@ void CairoTextRender::DrawTextLayout(const 
GenericSalLayout& rLayout, const SalG
         ApplyFont(temp_cr, aId, nHeight, nHeight, 0, rLayout);
 
         cairo_set_source_rgb(temp_cr,
-            mnTextColor.GetRed()/255.0,
-            mnTextColor.GetGreen()/255.0,
-            mnTextColor.GetBlue()/255.0);
+            rTextColor.GetRed()/255.0,
+            rTextColor.GetGreen()/255.0,
+            rTextColor.GetBlue()/255.0);
 
         cairo_show_glyphs(temp_cr, &glyph, 1);
         cairo_destroy(temp_cr);
@@ -417,7 +423,7 @@ void CairoTextRender::DrawTextLayout(const 
GenericSalLayout& rLayout, const SalG
 #endif
 
     const StyleSettings& rStyleSettings = 
Application::GetSettings().GetStyleSettings();
-    const bool bDisableAA = !rStyleSettings.GetUseFontAAFromSystem() && 
!rGraphics.getAntiAlias();
+    const bool bDisableAA = !rStyleSettings.GetUseFontAAFromSystem() && 
!bAntiAlias;
     static bool bAllowDefaultHinting = getenv("SAL_ALLOW_DEFAULT_HINTING") != 
nullptr;
 
     const cairo_font_options_t* pFontOptions = 
GetSalInstance()->GetCairoFontOptions();
@@ -505,11 +511,6 @@ cairo_t* CairoTextRender::getCairoContext()
     return mrCairoCommon.getCairoContext(/*bXorModeAllowed*/false, 
/*bAntiAlias*/true);
 }
 
-void CairoTextRender::clipRegion(cairo_t* cr)
-{
-    mrCairoCommon.clipRegion(cr);
-}
-
 void CairoTextRender::releaseCairoContext(cairo_t* cr)
 {
     mrCairoCommon.releaseCairoContext(cr, /*bXorModeAllowed*/false, 
basegfx::B2DRange());

Reply via email to