vcl/inc/unx/salframe.h | 2 vcl/inc/unx/salgdi.h | 25 ++-- vcl/inc/unx/salvd.h | 4 vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx | 142 ++++++++++++------------ vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx | 21 +-- vcl/unx/generic/gdi/gdiimpl.hxx | 3 vcl/unx/generic/gdi/salgdi.cxx | 51 ++------ vcl/unx/generic/gdi/salvd.cxx | 41 ++++++ vcl/unx/generic/gdi/x11cairotextrender.cxx | 4 vcl/unx/generic/window/salframe.cxx | 28 ++++ 10 files changed, 184 insertions(+), 137 deletions(-)
New commits: commit d8bccf8cbeebe8d5cf9354f3818da795a072899d Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Mon Jan 9 16:16:18 2023 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Tue Jan 10 13:56:23 2023 +0000 reorg to make use of X11SalFrame/X11SalVirtualDevice surface Change-Id: I56ac5181a51aef8f6ae698c14551925847a9f400 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145252 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index b17c44aed96e..c146e4c40e85 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -35,6 +35,8 @@ #include <vclpluginapi.h> #include <ControlCacheKey.hxx> +#include <headless/CairoCommon.hxx> + #include "saltype.h" #include "saldisp.hxx" @@ -68,14 +70,9 @@ 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; } @@ -146,9 +143,15 @@ public: */ void YieldGraphicsExpose(); - cairo_t* getCairoContext(); - static void releaseCairoContext(cairo_t* cr); + cairo_t* getCairoContext() const + { + return maCairoCommon.getCairoContext(/*bXorModeAllowed*/false, getAntiAlias()); + } + void releaseCairoContext(cairo_t* cr, const basegfx::B2DRange& rExtents) const + { + return maCairoCommon.releaseCairoContext(cr, /*bXorModeAllowed*/false, rExtents); + } private: using SalGraphics::GetPixel; @@ -176,6 +179,7 @@ private: std::unique_ptr<SalGraphicsImpl> mxImpl; std::unique_ptr<TextRenderImpl> mxTextRenderImpl; X11Common maX11Common; + CairoCommon maCairoCommon; public: Drawable GetDrawable() const { return maX11Common.GetDrawable(); } diff --git a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx index 39f661e46b4d..557ac8960bca 100644 --- a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx +++ b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx @@ -22,107 +22,112 @@ #include <basegfx/polygon/b2dpolypolygontools.hxx> #include <basegfx/curve/b2dcubicbezier.hxx> -X11CairoSalGraphicsImpl::X11CairoSalGraphicsImpl(X11SalGraphics& rParent, X11Common& rX11Common) +X11CairoSalGraphicsImpl::X11CairoSalGraphicsImpl(X11SalGraphics& rParent, CairoCommon& rCairoCommon) : X11SalGraphicsImpl(rParent) - , mrX11Common(rX11Common) - , moPenColor(std::nullopt) - , moFillColor(std::nullopt) + , mrCairoCommon(rCairoCommon) { } void X11CairoSalGraphicsImpl::drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - CairoCommon::drawRect(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), nX, nY, nWidth, - nHeight); + CairoCommon::drawRect(cr, &extents, mrCairoCommon.m_oLineColor, mrCairoCommon.m_oFillColor, + getAntiAlias(), nX, nY, nWidth, nHeight); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); } void X11CairoSalGraphicsImpl::drawPolygon(sal_uInt32 nPoints, const Point* pPtAry) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - CairoCommon::drawPolygon(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), nPoints, pPtAry); + CairoCommon::drawPolygon(cr, &extents, mrCairoCommon.m_oLineColor, mrCairoCommon.m_oFillColor, + getAntiAlias(), nPoints, pPtAry); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); } -void X11CairoSalGraphicsImpl::drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints, +void X11CairoSalGraphicsImpl::drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPointCounts, const Point** pPtAry) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - CairoCommon::drawPolyPolygon(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), nPoly, - pPoints, pPtAry); + CairoCommon::drawPolyPolygon(cr, &extents, mrCairoCommon.m_oLineColor, + mrCairoCommon.m_oFillColor, getAntiAlias(), nPoly, pPointCounts, + pPtAry); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); } bool X11CairoSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - bool bRetVal(CairoCommon::drawPolyPolygon(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), + bool bRetVal(CairoCommon::drawPolyPolygon(cr, &extents, mrCairoCommon.m_oLineColor, + mrCairoCommon.m_oFillColor, getAntiAlias(), rObjectToDevice, rPolyPolygon, fTransparency)); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); + return bRetVal; } void X11CairoSalGraphicsImpl::drawPixel(tools::Long nX, tools::Long nY) { - drawPixel(nX, nY, *moPenColor); + drawPixel(nX, nY, *mrCairoCommon.m_oLineColor); } -void X11CairoSalGraphicsImpl::drawPixel(tools::Long nX, tools::Long nY, Color nColor) +void X11CairoSalGraphicsImpl::drawPixel(tools::Long nX, tools::Long nY, Color aColor) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - CairoCommon::drawPixel(cr, nullptr, nColor, nX, nY); + CairoCommon::drawPixel(cr, &extents, aColor, nX, nY); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); } Color X11CairoSalGraphicsImpl::getPixel(tools::Long nX, tools::Long nY) { - cairo_t* cr = mrX11Common.getCairoContext(); - - Color aRet = CairoCommon::getPixel(cairo_get_target(cr), nX, nY); - - X11Common::releaseCairoContext(cr); - - return aRet; + return CairoCommon::getPixel(mrCairoCommon.m_pSurface, nX, nY); } void X11CairoSalGraphicsImpl::drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(false, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - CairoCommon::drawLine(cr, nullptr, *moPenColor, getAntiAlias(), nX1, nY1, nX2, nY2); + CairoCommon::drawLine(cr, &extents, *mrCairoCommon.m_oLineColor, getAntiAlias(), nX1, nY1, nX2, + nY2); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, false, extents); } void X11CairoSalGraphicsImpl::drawPolyLine(sal_uInt32 nPoints, const Point* pPtAry) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(false, getAntiAlias()); + basegfx::B2DRange aExtents; + mrCairoCommon.clipRegion(cr); - CairoCommon::drawPolyLine(cr, nullptr, *moPenColor, getAntiAlias(), nPoints, pPtAry); + CairoCommon::drawPolyLine(cr, &aExtents, *mrCairoCommon.m_oLineColor, getAntiAlias(), nPoints, + pPtAry); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, false, aExtents); } bool X11CairoSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectToDevice, @@ -137,16 +142,18 @@ bool X11CairoSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectT if (0 == rPolyLine.count() || fTransparency < 0.0 || fTransparency >= 1.0) return true; - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(false, getAntiAlias()); + basegfx::B2DRange aExtents; + mrCairoCommon.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, *moPenColor, getAntiAlias(), rObjectToDevice, rPolyLine, fTransparency, - fLineWidth, pStroke, eLineJoin, eLineCap, fMiterMinimumAngle, bPixelSnapHairline)); + bool bRetval(CairoCommon::drawPolyLine(cr, &aExtents, *mrCairoCommon.m_oLineColor, + getAntiAlias(), rObjectToDevice, rPolyLine, + fTransparency, fLineWidth, pStroke, eLineJoin, eLineCap, + fMiterMinimumAngle, bPixelSnapHairline)); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, false, aExtents); return bRetval; } @@ -154,13 +161,14 @@ bool X11CairoSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectT bool X11CairoSalGraphicsImpl::drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt8 nTransparency) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(false, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - const bool bRetval(CairoCommon::drawAlphaRect(cr, nullptr, *moPenColor, *moFillColor, nX, nY, - nWidth, nHeight, nTransparency)); - - X11Common::releaseCairoContext(cr); + const bool bRetval(CairoCommon::drawAlphaRect(cr, &extents, *mrCairoCommon.m_oLineColor, + *mrCairoCommon.m_oFillColor, nX, nY, nWidth, + nHeight, nTransparency)); + mrCairoCommon.releaseCairoContext(cr, false, extents); return bRetval; } @@ -168,13 +176,14 @@ bool X11CairoSalGraphicsImpl::drawAlphaRect(tools::Long nX, tools::Long nY, tool bool X11CairoSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPolygon, const Gradient& rGradient) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); const bool bRetval( - CairoCommon::drawGradient(cr, nullptr, getAntiAlias(), rPolyPolygon, rGradient)); + CairoCommon::drawGradient(cr, &extents, getAntiAlias(), rPolyPolygon, rGradient)); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); return bRetval; } @@ -182,15 +191,16 @@ bool X11CairoSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPolygo bool X11CairoSalGraphicsImpl::implDrawGradient(basegfx::B2DPolyPolygon const& rPolyPolygon, SalGradient const& rGradient) { - cairo_t* cr = mrX11Common.getCairoContext(); - clipRegion(cr); + cairo_t* cr = mrCairoCommon.getCairoContext(true, getAntiAlias()); + basegfx::B2DRange extents; + mrCairoCommon.clipRegion(cr); - const bool bRetval( - CairoCommon::implDrawGradient(cr, nullptr, getAntiAlias(), rPolyPolygon, rGradient)); + bool bRetVal( + CairoCommon::implDrawGradient(cr, &extents, getAntiAlias(), rPolyPolygon, rGradient)); - X11Common::releaseCairoContext(cr); + mrCairoCommon.releaseCairoContext(cr, true, extents); - return bRetval; + return bRetVal; } bool X11CairoSalGraphicsImpl::hasFastDrawTransformedBitmap() const diff --git a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx index 9e94b0dff7ea..f7e3a13287f9 100644 --- a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx +++ b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.hxx @@ -27,51 +27,48 @@ class X11CairoSalGraphicsImpl : public X11SalGraphicsImpl { private: - X11Common& mrX11Common; - vcl::Region maClipRegion; - std::optional<Color> moPenColor; - std::optional<Color> moFillColor; + CairoCommon& mrCairoCommon; public: - X11CairoSalGraphicsImpl(X11SalGraphics& rParent, X11Common& rX11Common); + X11CairoSalGraphicsImpl(X11SalGraphics& rParent, CairoCommon& rCairoCommon); void ResetClipRegion() override { - maClipRegion.SetNull(); + mrCairoCommon.m_aClipRegion.SetNull(); X11SalGraphicsImpl::ResetClipRegion(); } void setClipRegion(const vcl::Region& i_rClip) override { - maClipRegion = i_rClip; + mrCairoCommon.m_aClipRegion = i_rClip; X11SalGraphicsImpl::setClipRegion(i_rClip); } void SetLineColor() override { - moPenColor = std::nullopt; + mrCairoCommon.m_oLineColor = std::nullopt; X11SalGraphicsImpl::SetLineColor(); } void SetLineColor(Color nColor) override { - moPenColor = nColor; + mrCairoCommon.m_oLineColor = nColor; X11SalGraphicsImpl::SetLineColor(nColor); } void SetFillColor() override { - moFillColor = std::nullopt; + mrCairoCommon.m_oFillColor = std::nullopt; X11SalGraphicsImpl::SetFillColor(); } void SetFillColor(Color nColor) override { - moFillColor = nColor; + mrCairoCommon.m_oFillColor = nColor; X11SalGraphicsImpl::SetFillColor(nColor); } - void clipRegion(cairo_t* cr) { CairoCommon::clipRegion(cr, maClipRegion); } + void clipRegion(cairo_t* cr) { CairoCommon::clipRegion(cr, mrCairoCommon.m_aClipRegion); } void drawPixel(tools::Long nX, tools::Long nY) override; void drawPixel(tools::Long nX, tools::Long nY, Color nColor) override; diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx index 74be730fe9fa..e17f73050732 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -66,20 +66,8 @@ X11Common::X11Common() : m_hDrawable(None) , m_pColormap(nullptr) - , m_pExternalSurface(nullptr) {} -cairo_t* X11Common::getCairoContext() -{ - assert(m_pExternalSurface && "must be already set"); - return cairo_create(m_pExternalSurface); -} - -void X11Common::releaseCairoContext(cairo_t* cr) -{ - cairo_destroy(cr); -} - bool X11Common::SupportsCairo() const { static bool bSupportsCairo = [this] { @@ -113,7 +101,7 @@ X11SalGraphics::X11SalGraphics(): #endif { mxTextRenderImpl.reset(new X11CairoTextRender(*this)); - mxImpl.reset(new X11CairoSalGraphicsImpl(*this, maX11Common)); + mxImpl.reset(new X11CairoSalGraphicsImpl(*this, maCairoCommon)); } } @@ -158,9 +146,15 @@ SalGraphicsImpl* X11SalGraphics::GetImpl() const return mxImpl.get(); } -void X11SalGraphics::SetDrawable(Drawable aDrawable, cairo_surface_t* pExternalSurface, SalX11Screen nXScreen) +void X11SalGraphics::SetDrawable(Drawable aDrawable, cairo_surface_t* pSurface, SalX11Screen nXScreen) { - maX11Common.m_pExternalSurface = pExternalSurface; + maCairoCommon.m_pSurface = pSurface; + if (maCairoCommon.m_pSurface) + { + maCairoCommon.m_aFrameSize.setX(cairo_xlib_surface_get_width(pSurface)); + maCairoCommon.m_aFrameSize.setY(cairo_xlib_surface_get_height(pSurface)); + dl_cairo_surface_get_device_scale(pSurface, &maCairoCommon.m_fScale, nullptr); + } // shortcut if nothing changed if( maX11Common.m_hDrawable == aDrawable ) @@ -457,14 +451,4 @@ SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const return static_cast< SalGeometryProvider * >(m_pVDev); } -cairo_t* X11SalGraphics::getCairoContext() -{ - return maX11Common.getCairoContext(); -} - -void X11SalGraphics::releaseCairoContext(cairo_t* cr) -{ - X11Common::releaseCairoContext(cr); -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/unx/generic/gdi/x11cairotextrender.cxx b/vcl/unx/generic/gdi/x11cairotextrender.cxx index 6bbbbc1bff87..bdd522a17928 100644 --- a/vcl/unx/generic/gdi/x11cairotextrender.cxx +++ b/vcl/unx/generic/gdi/x11cairotextrender.cxx @@ -60,7 +60,7 @@ void X11CairoTextRender::clipRegion(cairo_t* cr) void X11CairoTextRender::releaseCairoContext(cairo_t* cr) { - X11SalGraphics::releaseCairoContext(cr); + mrParent.releaseCairoContext(cr, basegfx::B2DRange()); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit c4243e71a59013a5532ae945ffd80f9b13485721 Author: Caolán McNamara <caol...@redhat.com> AuthorDate: Sun Jan 8 20:37:12 2023 +0000 Commit: Caolán McNamara <caol...@redhat.com> CommitDate: Tue Jan 10 13:56:11 2023 +0000 move surface into X11SalFrame/X11SalVirtualDevice Change-Id: I58b97ab074fbd094e931d0bc4a346ba55ee58dd6 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145181 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caol...@redhat.com> diff --git a/vcl/inc/unx/salframe.h b/vcl/inc/unx/salframe.h index c7418ac0ad00..3bbf9729c971 100644 --- a/vcl/inc/unx/salframe.h +++ b/vcl/inc/unx/salframe.h @@ -74,6 +74,7 @@ class X11SalFrame final : public SalFrame SalDisplay *pDisplay_; SalX11Screen m_nXScreen; ::Window mhWindow; + cairo_surface_t* mpSurface; ::Window mhShellWindow; ::Window mhForeignParent; // window to fall back to when no longer in fullscreen mode @@ -179,6 +180,7 @@ public: } const SalX11Screen& GetScreenNumber() const { return m_nXScreen; } ::Window GetWindow() const { return mhWindow; } + cairo_surface_t* GetSurface() const { return mpSurface; } ::Window GetShellWindow() const { return mhShellWindow; } ::Window GetForeignParent() const { return mhForeignParent; } ::Window GetStackingWindow() const { return mhStackingWindow; } diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h index ca4456a1c720..b17c44aed96e 100644 --- a/vcl/inc/unx/salgdi.h +++ b/vcl/inc/unx/salgdi.h @@ -47,6 +47,7 @@ class SalBitmap; class SalColormap; class SalDisplay; class SalFrame; +class X11SalFrame; class X11SalVirtualDevice; class X11SalGraphicsImpl; class X11SkiaSalVirtualDevice; @@ -71,7 +72,7 @@ public: X11Common(); - cairo_t* getCairoContext(const SalGeometryProvider* pGeom); + cairo_t* getCairoContext(); static void releaseCairoContext(cairo_t* cr); @@ -94,9 +95,9 @@ public: X11SalGraphics(); virtual ~X11SalGraphics() COVERITY_NOEXCEPT_FALSE override; - void Init( SalFrame *pFrame, Drawable aDrawable, SalX11Screen nXScreen ); - void Init( X11SalVirtualDevice *pVirtualDevice, cairo_surface_t* pPreExistingTarget = nullptr, - SalColormap* pColormap = nullptr, bool bDeleteColormap = false ); + void Init(X11SalFrame& rFrame, Drawable aDrawable, SalX11Screen nXScreen); + void Init(X11SalVirtualDevice *pVirtualDevice, SalColormap* pColormap = nullptr, + bool bDeleteColormap = false); void Init( X11SkiaSalVirtualDevice *pVirtualDevice ); void DeInit(); @@ -145,7 +146,7 @@ public: */ void YieldGraphicsExpose(); - cairo_t* getCairoContext(const SalGeometryProvider* pGeom); + cairo_t* getCairoContext(); static void releaseCairoContext(cairo_t* cr); diff --git a/vcl/inc/unx/salvd.h b/vcl/inc/unx/salvd.h index 922b9d5e271c..3acfbebd105d 100644 --- a/vcl/inc/unx/salvd.h +++ b/vcl/inc/unx/salvd.h @@ -30,6 +30,7 @@ class SalDisplay; class X11SalGraphics; +typedef struct _cairo_surface cairo_surface_t; class X11SalVirtualDevice final : public SalVirtualDevice { @@ -44,6 +45,8 @@ class X11SalVirtualDevice final : public SalVirtualDevice sal_uInt16 nDepth_; bool bGraphics_; // is Graphics used bool bExternPixmap_; + cairo_surface_t* m_pSurface; + bool m_bOwnsSurface; // nearly always true, except for edge case of tdf#127529 public: X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, @@ -60,6 +63,7 @@ public: return pDisplay_; } Pixmap GetDrawable() const { return hDrawable_; } + cairo_surface_t* GetSurface() const { return m_pSurface; } sal_uInt16 GetDepth() const { return nDepth_; } const SalX11Screen& GetXScreenNumber() const { return m_nXScreen; } diff --git a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx index 2af798bb3d33..39f661e46b4d 100644 --- a/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx +++ b/vcl/unx/generic/gdi/X11CairoSalGraphicsImpl.cxx @@ -33,7 +33,7 @@ X11CairoSalGraphicsImpl::X11CairoSalGraphicsImpl(X11SalGraphics& rParent, X11Com void X11CairoSalGraphicsImpl::drawRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); CairoCommon::drawRect(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), nX, nY, nWidth, @@ -44,7 +44,7 @@ void X11CairoSalGraphicsImpl::drawRect(tools::Long nX, tools::Long nY, tools::Lo void X11CairoSalGraphicsImpl::drawPolygon(sal_uInt32 nPoints, const Point* pPtAry) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); CairoCommon::drawPolygon(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), nPoints, pPtAry); @@ -55,7 +55,7 @@ void X11CairoSalGraphicsImpl::drawPolygon(sal_uInt32 nPoints, const Point* pPtAr void X11CairoSalGraphicsImpl::drawPolyPolygon(sal_uInt32 nPoly, const sal_uInt32* pPoints, const Point** pPtAry) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); CairoCommon::drawPolyPolygon(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), nPoly, @@ -68,7 +68,7 @@ bool X11CairoSalGraphicsImpl::drawPolyPolygon(const basegfx::B2DHomMatrix& rObje const basegfx::B2DPolyPolygon& rPolyPolygon, double fTransparency) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); bool bRetVal(CairoCommon::drawPolyPolygon(cr, nullptr, moPenColor, moFillColor, getAntiAlias(), @@ -85,7 +85,7 @@ void X11CairoSalGraphicsImpl::drawPixel(tools::Long nX, tools::Long nY) void X11CairoSalGraphicsImpl::drawPixel(tools::Long nX, tools::Long nY, Color nColor) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); CairoCommon::drawPixel(cr, nullptr, nColor, nX, nY); @@ -95,7 +95,7 @@ void X11CairoSalGraphicsImpl::drawPixel(tools::Long nX, tools::Long nY, Color nC Color X11CairoSalGraphicsImpl::getPixel(tools::Long nX, tools::Long nY) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); Color aRet = CairoCommon::getPixel(cairo_get_target(cr), nX, nY); @@ -107,7 +107,7 @@ Color X11CairoSalGraphicsImpl::getPixel(tools::Long nX, tools::Long nY) void X11CairoSalGraphicsImpl::drawLine(tools::Long nX1, tools::Long nY1, tools::Long nX2, tools::Long nY2) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); CairoCommon::drawLine(cr, nullptr, *moPenColor, getAntiAlias(), nX1, nY1, nX2, nY2); @@ -117,7 +117,7 @@ void X11CairoSalGraphicsImpl::drawLine(tools::Long nX1, tools::Long nY1, tools:: void X11CairoSalGraphicsImpl::drawPolyLine(sal_uInt32 nPoints, const Point* pPtAry) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); CairoCommon::drawPolyLine(cr, nullptr, *moPenColor, getAntiAlias(), nPoints, pPtAry); @@ -137,7 +137,7 @@ bool X11CairoSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectT if (0 == rPolyLine.count() || fTransparency < 0.0 || fTransparency >= 1.0) return true; - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); // Use the now available static drawPolyLine from the Cairo-Headless-Fallback @@ -154,7 +154,7 @@ bool X11CairoSalGraphicsImpl::drawPolyLine(const basegfx::B2DHomMatrix& rObjectT bool X11CairoSalGraphicsImpl::drawAlphaRect(tools::Long nX, tools::Long nY, tools::Long nWidth, tools::Long nHeight, sal_uInt8 nTransparency) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); const bool bRetval(CairoCommon::drawAlphaRect(cr, nullptr, *moPenColor, *moFillColor, nX, nY, @@ -168,7 +168,7 @@ bool X11CairoSalGraphicsImpl::drawAlphaRect(tools::Long nX, tools::Long nY, tool bool X11CairoSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPolygon, const Gradient& rGradient) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); const bool bRetval( @@ -182,7 +182,7 @@ bool X11CairoSalGraphicsImpl::drawGradient(const tools::PolyPolygon& rPolyPolygo bool X11CairoSalGraphicsImpl::implDrawGradient(basegfx::B2DPolyPolygon const& rPolyPolygon, SalGradient const& rGradient) { - cairo_t* cr = mrX11Common.getCairoContext(mrParent.GetGeometryProvider()); + cairo_t* cr = mrX11Common.getCairoContext(); clipRegion(cr); const bool bRetval( diff --git a/vcl/unx/generic/gdi/gdiimpl.hxx b/vcl/unx/generic/gdi/gdiimpl.hxx index d47b0082f860..91564bfccc23 100644 --- a/vcl/unx/generic/gdi/gdiimpl.hxx +++ b/vcl/unx/generic/gdi/gdiimpl.hxx @@ -41,10 +41,9 @@ class Gradient; class X11SalGraphicsImpl : public SalGraphicsImpl, public X11GraphicsImpl { -protected: +private: X11SalGraphics& mrParent; -private: std::optional<Color> moBrushColor; GC mpBrushGC; // Brush attributes Pixel mnBrushPixel; diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx index c4919e49229b..74be730fe9fa 100644 --- a/vcl/unx/generic/gdi/salgdi.cxx +++ b/vcl/unx/generic/gdi/salgdi.cxx @@ -52,6 +52,7 @@ #include <salvd.hxx> #include "gdiimpl.hxx" +#include <unx/salframe.h> #include <unx/x11/x11cairotextrender.hxx> #include <unx/x11/xrender_peer.hxx> #include "cairo_xlib_cairo.hxx" @@ -68,20 +69,10 @@ X11Common::X11Common() , m_pExternalSurface(nullptr) {} -cairo_t* X11Common::getCairoContext(const SalGeometryProvider* pGeom) +cairo_t* X11Common::getCairoContext() { - if (m_pExternalSurface) - return cairo_create(m_pExternalSurface); - - SAL_WARN_IF(!pGeom, "vcl", "No geometry available"); - int nWidth = pGeom ? pGeom->GetWidth() : SAL_MAX_INT16; - int nHeight = pGeom ? pGeom->GetHeight() : SAL_MAX_INT16; - cairo_surface_t* surface = cairo_xlib_surface_create(GetXDisplay(), m_hDrawable, GetVisual().visual, nWidth, nHeight); - - cairo_t *cr = cairo_create(surface); - cairo_surface_destroy(surface); - - return cr; + assert(m_pExternalSurface && "must be already set"); + return cairo_create(m_pExternalSurface); } void X11Common::releaseCairoContext(cairo_t* cr) @@ -192,19 +183,19 @@ void X11SalGraphics::SetDrawable(Drawable aDrawable, cairo_surface_t* pExternalS } } -void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget, +void X11SalGraphics::Init( X11SalFrame& rFrame, Drawable aTarget, SalX11Screen nXScreen ) { maX11Common.m_pColormap = &vcl_sal::getSalDisplay(GetGenericUnixSalData())->GetColormap(nXScreen); m_nXScreen = nXScreen; - m_pFrame = pFrame; + m_pFrame = &rFrame; m_pVDev = nullptr; bWindow_ = true; bVirDev_ = false; - SetDrawable(aTarget, nullptr, nXScreen); + SetDrawable(aTarget, rFrame.GetSurface(), nXScreen); mxImpl->Init(); } @@ -466,9 +457,9 @@ SalGeometryProvider *X11SalGraphics::GetGeometryProvider() const return static_cast< SalGeometryProvider * >(m_pVDev); } -cairo_t* X11SalGraphics::getCairoContext(const SalGeometryProvider* pGeom) +cairo_t* X11SalGraphics::getCairoContext() { - return maX11Common.getCairoContext(pGeom); + return maX11Common.getCairoContext(); } void X11SalGraphics::releaseCairoContext(cairo_t* cr) diff --git a/vcl/unx/generic/gdi/salvd.cxx b/vcl/unx/generic/gdi/salvd.cxx index f5e4449c625d..047437a7f78c 100644 --- a/vcl/unx/generic/gdi/salvd.cxx +++ b/vcl/unx/generic/gdi/salvd.cxx @@ -33,6 +33,7 @@ #if HAVE_FEATURE_SKIA #include <skia/x11/salvd.hxx> #endif +#include <cairo-xlib.h> std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateX11VirtualDevice(const SalGraphics& rGraphics, tools::Long &nDX, tools::Long &nDY, DeviceFormat eFormat, const SystemGraphicsData *pData, @@ -53,8 +54,7 @@ std::unique_ptr<SalVirtualDevice> X11SalInstance::CreateVirtualDevice(SalGraphic return CreateX11VirtualDevice(rGraphics, nDX, nDY, eFormat, pData, std::make_unique<X11SalGraphics>()); } -void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, cairo_surface_t* pPreExistingTarget, SalColormap* pColormap, - bool bDeleteColormap ) +void X11SalGraphics::Init(X11SalVirtualDevice *pDevice, SalColormap* pColormap, bool bDeleteColormap) { SalDisplay *pDisplay = pDevice->GetDisplay(); m_nXScreen = pDevice->GetXScreenNumber(); @@ -82,7 +82,7 @@ void X11SalGraphics::Init( X11SalVirtualDevice *pDevice, cairo_surface_t* pPreEx bWindow_ = pDisplay->IsDisplay(); bVirDev_ = true; - SetDrawable(pDevice->GetDrawable(), pPreExistingTarget, m_nXScreen); + SetDrawable(pDevice->GetDrawable(), pDevice->GetSurface(), m_nXScreen); mxImpl->Init(); } @@ -155,14 +155,29 @@ X11SalVirtualDevice::X11SalVirtualDevice(const SalGraphics& rGraphics, tools::Lo // tdf#127529 see SvpSalInstance::CreateVirtualDevice for the rare case of a non-null pPreExistingTarget cairo_surface_t* pPreExistingTarget = pData ? static_cast<cairo_surface_t*>(pData->pSurface) : nullptr; + if (pPreExistingTarget) + { + m_bOwnsSurface = false; + m_pSurface = pPreExistingTarget; + } + else + { + m_bOwnsSurface = true; + m_pSurface = cairo_xlib_surface_create(GetXDisplay(), hDrawable_, + pDisplay_->GetColormap(m_nXScreen).GetVisual().visual, + nDX_, nDY_); + } - pGraphics_->Init( this, pPreExistingTarget, pColormap, bDeleteColormap ); + pGraphics_->Init(this, pColormap, bDeleteColormap); } X11SalVirtualDevice::~X11SalVirtualDevice() { pGraphics_.reset(); + if (m_bOwnsSurface) + cairo_surface_destroy(m_pSurface); + if( GetDrawable() && !bExternPixmap_ ) XFreePixmap( GetXDisplay(), GetDrawable() ); } @@ -189,6 +204,9 @@ bool X11SalVirtualDevice::SetSize( tools::Long nDX, tools::Long nDY ) if( !nDX ) nDX = 1; if( !nDY ) nDY = 1; + if (m_bOwnsSurface) + cairo_surface_destroy(m_pSurface); + Pixmap h = limitXCreatePixmap( GetXDisplay(), pDisplay_->GetDrawable( m_nXScreen ), nDX, nDY, nDepth_ ); @@ -203,6 +221,14 @@ bool X11SalVirtualDevice::SetSize( tools::Long nDX, tools::Long nDY ) nDX_ = 1; nDY_ = 1; } + + if (m_bOwnsSurface) + { + m_pSurface = cairo_xlib_surface_create(GetXDisplay(), hDrawable_, + pDisplay_->GetColormap(m_nXScreen).GetVisual().visual, + nDX_, nDY_); + } + return false; } @@ -213,6 +239,13 @@ bool X11SalVirtualDevice::SetSize( tools::Long nDX, tools::Long nDY ) nDX_ = nDX; nDY_ = nDY; + if (m_bOwnsSurface) + { + m_pSurface = cairo_xlib_surface_create(GetXDisplay(), hDrawable_, + pDisplay_->GetColormap(m_nXScreen).GetVisual().visual, + nDX_, nDY_); + } + if( pGraphics_ ) pGraphics_->Init( this ); diff --git a/vcl/unx/generic/gdi/x11cairotextrender.cxx b/vcl/unx/generic/gdi/x11cairotextrender.cxx index 7a1d4b9fcbf7..6bbbbc1bff87 100644 --- a/vcl/unx/generic/gdi/x11cairotextrender.cxx +++ b/vcl/unx/generic/gdi/x11cairotextrender.cxx @@ -32,7 +32,7 @@ X11CairoTextRender::X11CairoTextRender(X11SalGraphics& rParent) cairo_t* X11CairoTextRender::getCairoContext() { - return mrParent.getCairoContext(mrParent.GetGeometryProvider()); + return mrParent.getCairoContext(); } void X11CairoTextRender::getSurfaceOffset( double& nDX, double& nDY ) diff --git a/vcl/unx/generic/window/salframe.cxx b/vcl/unx/generic/window/salframe.cxx index 916471520679..d0e41a2617fb 100644 --- a/vcl/unx/generic/window/salframe.cxx +++ b/vcl/unx/generic/window/salframe.cxx @@ -59,6 +59,8 @@ #include <svdata.hxx> #include <bitmaps.hlst> +#include <cairo-xlib.h> + #include <optional> #include <algorithm> @@ -634,6 +636,10 @@ void X11SalFrame::Init( SalFrameStyleFlags nSalFrameStyle, SalX11Screen nXScreen rVis.GetVisual(), nAttrMask, &Attributes ); + mpSurface = cairo_xlib_surface_create(GetXDisplay(), mhWindow, + rVis.GetVisual(), + w, h); + // FIXME: see above: fake shell window for now to own window if( pParentData == nullptr ) { @@ -799,6 +805,7 @@ X11SalFrame::X11SalFrame( SalFrame *pParent, SalFrameStyleFlags nSalFrameStyle, pDisplay_->registerFrame( this ); mhWindow = None; + mpSurface = nullptr; mhShellWindow = None; mhStackingWindow = None; mhForeignParent = None; @@ -910,6 +917,9 @@ X11SalFrame::~X11SalFrame() pContext = pContext->mpPrevContext; } + if (mpSurface) + cairo_surface_destroy(mpSurface); + XDestroyWindow( GetXDisplay(), mhWindow ); } @@ -949,7 +959,7 @@ SalGraphics *X11SalFrame::AcquireGraphics() else { pGraphics_.reset(new X11SalGraphics()); - pGraphics_->Init( this, GetWindow(), m_nXScreen ); + pGraphics_->Init(*this, GetWindow(), m_nXScreen); } return pGraphics_.get(); @@ -969,9 +979,9 @@ void X11SalFrame::updateGraphics( bool bClear ) { Drawable aDrawable = bClear ? None : GetWindow(); if( pGraphics_ ) - pGraphics_->SetDrawable( aDrawable, nullptr, m_nXScreen ); + pGraphics_->SetDrawable( aDrawable, mpSurface, m_nXScreen ); if( pFreeGraphics_ ) - pFreeGraphics_->SetDrawable( aDrawable, nullptr, m_nXScreen ); + pFreeGraphics_->SetDrawable( aDrawable, mpSurface, m_nXScreen ); } void X11SalFrame::SetIcon( sal_uInt16 nIcon ) @@ -1637,6 +1647,7 @@ void X11SalFrame::SetWindowState( const vcl::WindowData *pState ) // guess maximized geometry from last time maGeometry.setPos({ pState->GetMaximizedX(), pState->GetMaximizedY() }); maGeometry.setSize({ pState->GetMaximizedWidth(), pState->GetMaximizedHeight() }); + cairo_xlib_surface_set_size(mpSurface, pState->GetMaximizedWidth(), pState->GetMaximizedHeight()); updateScreenNumber(); } else @@ -1833,6 +1844,7 @@ void X11SalFrame::SetSize( const Size &rSize ) XResizeWindow( GetXDisplay(), GetWindow(), rSize.Width(), rSize.Height() ); } + cairo_xlib_surface_set_size(mpSurface, rSize.Width(), rSize.Height()); maGeometry.setSize(rSize); // allow the external status window to reposition @@ -1929,6 +1941,7 @@ void X11SalFrame::SetPosSize( const tools::Rectangle &rPosSize ) XMoveResizeWindow( GetXDisplay(), GetWindow(), values.x, values.y, values.width, values.height ); } + cairo_xlib_surface_set_size(mpSurface, values.width, values.height); maGeometry.setPosSize({ values.x, values.y }, { values.width, values.height }); if( IsSysChildWindow() && mpParent ) // translate back to root coordinates @@ -2375,6 +2388,11 @@ void X11SalFrame::createNewWindow( ::Window aNewParent, SalX11Screen nXScreen ) hPresentationWindow = None; doReparentPresentationDialogues( GetDisplay() ); } + if (mpSurface) + { + cairo_surface_destroy(mpSurface); + mpSurface = nullptr; + } XDestroyWindow( GetXDisplay(), mhWindow ); mhWindow = None; @@ -3421,10 +3439,13 @@ bool X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent ) } if( pEvent->window == GetForeignParent() ) + { XResizeWindow( GetXDisplay(), GetWindow(), pEvent->width, pEvent->height ); + cairo_xlib_surface_set_size(mpSurface, pEvent->width, pEvent->height); + } ::Window hDummy; XTranslateCoordinates( GetXDisplay(), @@ -3464,6 +3485,7 @@ bool X11SalFrame::HandleSizeEvent( XConfigureEvent *pEvent ) bool bMoved = ( pEvent->x != maGeometry.x() || pEvent->y != maGeometry.y() ); bool bSized = ( pEvent->width != static_cast<int>(maGeometry.width()) || pEvent->height != static_cast<int>(maGeometry.height()) ); + cairo_xlib_surface_set_size(mpSurface, pEvent->width, pEvent->height); maGeometry.setPosSize({ pEvent->x, pEvent->y }, { pEvent->width, pEvent->height }); updateScreenNumber();