From 4844c096a8ab6a9a620c410a0949d4499f12a504 Mon Sep 17 00:00:00 2001 From: Stephan Bergmann Date: Thu, 15 Dec 2022 11:44:32 +0100 Subject: loplugin:unocast (cairocanvas::SurfaceProvider) (See the upcoming commit introducing that loplugin:unocast on why such dynamic_casts from UNO types are dangerous.) There are implementation classes whose getSomething already delegates to RepaintTarget, so they can't also delegate to SurfaceProvider. So introduce the concept of comphelper::getSomethingImpl additionally delegating to a sequence of mixin classes before delegating to the base. Change-Id: I9230f3dc06abbdd1ad92514a11473dae2624f7c1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144404 Tested-by: Jenkins Reviewed-by: Stephan Bergmann --- canvas/source/cairo/cairo_canvas.cxx | 5 +- canvas/source/cairo/cairo_canvasbitmap.cxx | 3 +- canvas/source/cairo/cairo_canvascustomsprite.cxx | 4 +- canvas/source/cairo/cairo_canvashelper.cxx | 3 +- canvas/source/cairo/cairo_spritecanvas.cxx | 4 +- canvas/source/cairo/cairo_surfaceprovider.hxx | 14 ++++- include/comphelper/servicehelper.hxx | 67 +++++++++++++++++++++++- 7 files changed, 92 insertions(+), 8 deletions(-) diff --git a/canvas/source/cairo/cairo_canvas.cxx b/canvas/source/cairo/cairo_canvas.cxx index 6c9e4fe296df..255b8d84d80c 100644 --- a/canvas/source/cairo/cairo_canvas.cxx +++ b/canvas/source/cairo/cairo_canvas.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -129,7 +130,9 @@ namespace cairocanvas } sal_Int64 Canvas::getSomething(css::uno::Sequence const & aIdentifier) { - return RepaintTarget::getSomething(aIdentifier); + return comphelper::getSomethingImpl_skipDerived( + aIdentifier, this, comphelper::MixinToGetSomethingOf{}, + comphelper::FallbackToGetSomethingOf{}); } bool Canvas::repaint( const SurfaceSharedPtr& pSurface, diff --git a/canvas/source/cairo/cairo_canvasbitmap.cxx b/canvas/source/cairo/cairo_canvasbitmap.cxx index 3e0bcae618f6..30ccb2cda8e8 100644 --- a/canvas/source/cairo/cairo_canvasbitmap.cxx +++ b/canvas/source/cairo/cairo_canvasbitmap.cxx @@ -145,7 +145,8 @@ namespace cairocanvas sal_Int64 CanvasBitmap::getSomething(css::uno::Sequence const & aIdentifier) { return comphelper::getSomethingImpl( - aIdentifier, this, comphelper::FallbackToGetSomethingOf{}); + aIdentifier, this, comphelper::MixinToGetSomethingOf{}, + comphelper::FallbackToGetSomethingOf{}); } css::uno::Sequence const & CanvasBitmap::getUnoTunnelId() { diff --git a/canvas/source/cairo/cairo_canvascustomsprite.cxx b/canvas/source/cairo/cairo_canvascustomsprite.cxx index 98ead7036b34..e5f22e9c4a9c 100644 --- a/canvas/source/cairo/cairo_canvascustomsprite.cxx +++ b/canvas/source/cairo/cairo_canvascustomsprite.cxx @@ -148,7 +148,9 @@ namespace cairocanvas } sal_Int64 CanvasCustomSprite::getSomething(css::uno::Sequence const & aIdentifier) { - return RepaintTarget::getSomething(aIdentifier); + return comphelper::getSomethingImpl_skipDerived( + aIdentifier, this, comphelper::MixinToGetSomethingOf{}, + comphelper::FallbackToGetSomethingOf{}); } } diff --git a/canvas/source/cairo/cairo_canvashelper.cxx b/canvas/source/cairo/cairo_canvashelper.cxx index 9279a4c0781b..89a794bc6cd5 100644 --- a/canvas/source/cairo/cairo_canvashelper.cxx +++ b/canvas/source/cairo/cairo_canvashelper.cxx @@ -299,7 +299,8 @@ constexpr OUStringLiteral PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME = u"Canvas:: if( pBitmapImpl ) return pBitmapImpl->getSurface(); - SurfaceProvider* pSurfaceProvider = dynamic_cast( xBitmap.get() ); + SurfaceProvider* pSurfaceProvider + = comphelper::getFromUnoTunnel( xBitmap ); if( pSurfaceProvider ) return pSurfaceProvider->getSurface(); diff --git a/canvas/source/cairo/cairo_spritecanvas.cxx b/canvas/source/cairo/cairo_spritecanvas.cxx index e414f8d8d9b5..2d33d4a14c7a 100644 --- a/canvas/source/cairo/cairo_spritecanvas.cxx +++ b/canvas/source/cairo/cairo_spritecanvas.cxx @@ -152,7 +152,9 @@ namespace cairocanvas } sal_Int64 SpriteCanvas::getSomething(css::uno::Sequence const & aIdentifier) { - return RepaintTarget::getSomething(aIdentifier); + return comphelper::getSomethingImpl_skipDerived( + aIdentifier, this, comphelper::MixinToGetSomethingOf{}, + comphelper::FallbackToGetSomethingOf{}); } SurfaceSharedPtr SpriteCanvas::getSurface() diff --git a/canvas/source/cairo/cairo_surfaceprovider.hxx b/canvas/source/cairo/cairo_surfaceprovider.hxx index 1ff6f2aa7d3f..e0293373451f 100644 --- a/canvas/source/cairo/cairo_surfaceprovider.hxx +++ b/canvas/source/cairo/cairo_surfaceprovider.hxx @@ -20,7 +20,10 @@ #pragma once #include +#include #include +#include +#include #include #include @@ -37,7 +40,7 @@ namespace cairocanvas This interface must be implemented on all canvas implementations that hand out XCachedPrimitives */ - class SAL_LOPLUGIN_ANNOTATE("crosscast") SurfaceProvider : public css::uno::XInterface + class SurfaceProvider : public css::uno::XInterface { public: virtual ~SurfaceProvider() {} @@ -62,6 +65,15 @@ namespace cairocanvas /** Provides the underlying vcl outputdevice this surface renders on */ virtual OutputDevice* getOutputDevice() = 0; + + sal_Int64 getSomething(css::uno::Sequence const & aIdentifier) { + return comphelper::getSomethingImpl(aIdentifier, this); + } + + static css::uno::Sequence const & getUnoTunnelId() { + static comphelper::UnoIdInit const id; + return id.getSeq(); + } }; typedef ::rtl::Reference< SurfaceProvider > SurfaceProviderRef; diff --git a/include/comphelper/servicehelper.hxx b/include/comphelper/servicehelper.hxx index c225494ccf1b..1d157cbf1482 100644 --- a/include/comphelper/servicehelper.hxx +++ b/include/comphelper/servicehelper.hxx @@ -82,6 +82,16 @@ namespace comphelper { && memcmp(T::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16) == 0; } + template struct MixinToGetSomethingOf { + static bool get(css::uno::Sequence const & id, T * p, sal_Int64 * result) { + if (!isUnoTunnelId(id)) { + return false; + } + *result = getSomething_cast(p); + return true; + } + }; + template struct FallbackToGetSomethingOf { static sal_Int64 get(const css::uno::Sequence& rId, Base* p) @@ -95,12 +105,65 @@ namespace comphelper { static sal_Int64 get(const css::uno::Sequence&, void*) { return 0; } }; + // There are five cases how to implement T::getSomething: + // (1) Delegate to Base: + // Either, if Base has only getUnoTunnelId but no getSomething: + // return getSomethingImpl(aIdentifier, this); + // Or, if Base has getSomething: + // return Base::getSomething(aIdentifier) + // (2) Check against T::getUnoTunnelId, else return 0: + // return getSomethingImpl(aIdentifier, this); + // (3) Check against T::getUnoTunnelId, else delegate to Base: + // return getSomethingImpl(aIdentifier, this, FallbackToGetSomethingOf{}); + // (4) Check against T::getUnoTunnelId, else check against each Mixins::getUnoTunnelId, else + // delegate to Base: + // return getSomethingImpl( + // aIdentifier, this, MixinToGetSomethingOf{}, ..., + // MixinToGetSomethingOf{}, FallbackToGetSomethingOf{}); + // (5) Check against each Mixins::getUnoTunnelId, else delegate to Base: + // return getSomethingImpl_skipDerived( + // aIdentifier, this, MixinToGetSomethingOf{}, ..., + // MixinToGetSomethingOf{}, FallbackToGetSomethingOf{}); + template sal_Int64 getSomethingImpl(const css::uno::Sequence& rId, T* pThis, FallbackToGetSomethingOf = {}) { - if (isUnoTunnelId(rId)) - return getSomething_cast(pThis); + sal_Int64 res; + if (MixinToGetSomethingOf::get(rId, pThis, &res)) { + return res; + } + + return FallbackToGetSomethingOf::get(rId, pThis); + } + + template + sal_Int64 getSomethingImpl(const css::uno::Sequence& rId, T* pThis, + MixinToGetSomethingOf, MixinToGetSomethingOf..., + FallbackToGetSomethingOf) + { + sal_Int64 res; + if (((MixinToGetSomethingOf::get(rId, pThis, &res) + || MixinToGetSomethingOf::get(rId, pThis, &res)) || ... + || MixinToGetSomethingOf::get(rId, pThis, &res))) + { + return res; + } + + return FallbackToGetSomethingOf::get(rId, pThis); + } + + template + sal_Int64 getSomethingImpl_skipDerived(const css::uno::Sequence& rId, T* pThis, + MixinToGetSomethingOf, MixinToGetSomethingOf..., + FallbackToGetSomethingOf) + { + sal_Int64 res; + if ((MixinToGetSomethingOf::get(rId, pThis, &res) || ... + || MixinToGetSomethingOf::get(rId, pThis, &res))) + { + return res; + } return FallbackToGetSomethingOf::get(rId, pThis); } -- cgit