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 <sbergman@redhat.com>
This commit is contained in:
Stephan Bergmann
2022-12-15 11:44:32 +01:00
parent 9a0b523e0a
commit 4844c096a8
7 changed files with 92 additions and 8 deletions

View File

@@ -24,6 +24,7 @@
#include <com/sun/star/lang/NoSupportException.hpp> #include <com/sun/star/lang/NoSupportException.hpp>
#include <osl/mutex.hxx> #include <osl/mutex.hxx>
#include <comphelper/diagnose_ex.hxx> #include <comphelper/diagnose_ex.hxx>
#include <comphelper/servicehelper.hxx>
#include <vcl/sysdata.hxx> #include <vcl/sysdata.hxx>
#include <vcl/skia/SkiaHelper.hxx> #include <vcl/skia/SkiaHelper.hxx>
#include <cppuhelper/supportsservice.hxx> #include <cppuhelper/supportsservice.hxx>
@@ -129,7 +130,9 @@ namespace cairocanvas
} }
sal_Int64 Canvas::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) { sal_Int64 Canvas::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) {
return RepaintTarget::getSomething(aIdentifier); return comphelper::getSomethingImpl_skipDerived(
aIdentifier, this, comphelper::MixinToGetSomethingOf<SurfaceProvider>{},
comphelper::FallbackToGetSomethingOf<RepaintTarget>{});
} }
bool Canvas::repaint( const SurfaceSharedPtr& pSurface, bool Canvas::repaint( const SurfaceSharedPtr& pSurface,

View File

@@ -145,7 +145,8 @@ namespace cairocanvas
sal_Int64 CanvasBitmap::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) { sal_Int64 CanvasBitmap::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) {
return comphelper::getSomethingImpl( return comphelper::getSomethingImpl(
aIdentifier, this, comphelper::FallbackToGetSomethingOf<RepaintTarget>{}); aIdentifier, this, comphelper::MixinToGetSomethingOf<SurfaceProvider>{},
comphelper::FallbackToGetSomethingOf<RepaintTarget>{});
} }
css::uno::Sequence<sal_Int8> const & CanvasBitmap::getUnoTunnelId() { css::uno::Sequence<sal_Int8> const & CanvasBitmap::getUnoTunnelId() {

View File

@@ -148,7 +148,9 @@ namespace cairocanvas
} }
sal_Int64 CanvasCustomSprite::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) { sal_Int64 CanvasCustomSprite::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) {
return RepaintTarget::getSomething(aIdentifier); return comphelper::getSomethingImpl_skipDerived(
aIdentifier, this, comphelper::MixinToGetSomethingOf<SurfaceProvider>{},
comphelper::FallbackToGetSomethingOf<RepaintTarget>{});
} }
} }

View File

@@ -299,7 +299,8 @@ constexpr OUStringLiteral PARAMETRICPOLYPOLYGON_IMPLEMENTATION_NAME = u"Canvas::
if( pBitmapImpl ) if( pBitmapImpl )
return pBitmapImpl->getSurface(); return pBitmapImpl->getSurface();
SurfaceProvider* pSurfaceProvider = dynamic_cast<SurfaceProvider*>( xBitmap.get() ); SurfaceProvider* pSurfaceProvider
= comphelper::getFromUnoTunnel<SurfaceProvider>( xBitmap );
if( pSurfaceProvider ) if( pSurfaceProvider )
return pSurfaceProvider->getSurface(); return pSurfaceProvider->getSurface();

View File

@@ -152,7 +152,9 @@ namespace cairocanvas
} }
sal_Int64 SpriteCanvas::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) { sal_Int64 SpriteCanvas::getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) {
return RepaintTarget::getSomething(aIdentifier); return comphelper::getSomethingImpl_skipDerived(
aIdentifier, this, comphelper::MixinToGetSomethingOf<SurfaceProvider>{},
comphelper::FallbackToGetSomethingOf<RepaintTarget>{});
} }
SurfaceSharedPtr SpriteCanvas::getSurface() SurfaceSharedPtr SpriteCanvas::getSurface()

View File

@@ -20,7 +20,10 @@
#pragma once #pragma once
#include <rtl/ref.hxx> #include <rtl/ref.hxx>
#include <com/sun/star/uno/Sequence.hxx>
#include <com/sun/star/uno/XInterface.hpp> #include <com/sun/star/uno/XInterface.hpp>
#include <comphelper/servicehelper.hxx>
#include <sal/types.h>
#include <basegfx/vector/b2isize.hxx> #include <basegfx/vector/b2isize.hxx>
#include <vcl/cairo.hxx> #include <vcl/cairo.hxx>
@@ -37,7 +40,7 @@ namespace cairocanvas
This interface must be implemented on all canvas This interface must be implemented on all canvas
implementations that hand out XCachedPrimitives implementations that hand out XCachedPrimitives
*/ */
class SAL_LOPLUGIN_ANNOTATE("crosscast") SurfaceProvider : public css::uno::XInterface class SurfaceProvider : public css::uno::XInterface
{ {
public: public:
virtual ~SurfaceProvider() {} virtual ~SurfaceProvider() {}
@@ -62,6 +65,15 @@ namespace cairocanvas
/** Provides the underlying vcl outputdevice this surface renders on /** Provides the underlying vcl outputdevice this surface renders on
*/ */
virtual OutputDevice* getOutputDevice() = 0; virtual OutputDevice* getOutputDevice() = 0;
sal_Int64 getSomething(css::uno::Sequence<sal_Int8> const & aIdentifier) {
return comphelper::getSomethingImpl(aIdentifier, this);
}
static css::uno::Sequence<sal_Int8> const & getUnoTunnelId() {
static comphelper::UnoIdInit const id;
return id.getSeq();
}
}; };
typedef ::rtl::Reference< SurfaceProvider > SurfaceProviderRef; typedef ::rtl::Reference< SurfaceProvider > SurfaceProviderRef;

View File

@@ -82,6 +82,16 @@ namespace comphelper {
&& memcmp(T::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16) == 0; && memcmp(T::getUnoTunnelId().getConstArray(), rId.getConstArray(), 16) == 0;
} }
template<typename T> struct MixinToGetSomethingOf {
static bool get(css::uno::Sequence<sal_Int8> const & id, T * p, sal_Int64 * result) {
if (!isUnoTunnelId<T>(id)) {
return false;
}
*result = getSomething_cast(p);
return true;
}
};
template <class Base> struct FallbackToGetSomethingOf template <class Base> struct FallbackToGetSomethingOf
{ {
static sal_Int64 get(const css::uno::Sequence<sal_Int8>& rId, Base* p) static sal_Int64 get(const css::uno::Sequence<sal_Int8>& rId, Base* p)
@@ -95,12 +105,65 @@ namespace comphelper {
static sal_Int64 get(const css::uno::Sequence<sal_Int8>&, void*) { return 0; } static sal_Int64 get(const css::uno::Sequence<sal_Int8>&, 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<Base>(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<Base>{});
// (4) Check against T::getUnoTunnelId, else check against each Mixins::getUnoTunnelId, else
// delegate to Base:
// return getSomethingImpl(
// aIdentifier, this, MixinToGetSomethingOf<Mixin1>{}, ...,
// MixinToGetSomethingOf<MixinN>{}, FallbackToGetSomethingOf<Base>{});
// (5) Check against each Mixins::getUnoTunnelId, else delegate to Base:
// return getSomethingImpl_skipDerived(
// aIdentifier, this, MixinToGetSomethingOf<Mixin1>{}, ...,
// MixinToGetSomethingOf<MixinN>{}, FallbackToGetSomethingOf<Base>{});
template <class T, class Base = void> template <class T, class Base = void>
sal_Int64 getSomethingImpl(const css::uno::Sequence<sal_Int8>& rId, T* pThis, sal_Int64 getSomethingImpl(const css::uno::Sequence<sal_Int8>& rId, T* pThis,
FallbackToGetSomethingOf<Base> = {}) FallbackToGetSomethingOf<Base> = {})
{ {
if (isUnoTunnelId<T>(rId)) sal_Int64 res;
return getSomething_cast(pThis); if (MixinToGetSomethingOf<T>::get(rId, pThis, &res)) {
return res;
}
return FallbackToGetSomethingOf<Base>::get(rId, pThis);
}
template <class T, class Mixin, class... Mixins, class Base>
sal_Int64 getSomethingImpl(const css::uno::Sequence<sal_Int8>& rId, T* pThis,
MixinToGetSomethingOf<Mixin>, MixinToGetSomethingOf<Mixins>...,
FallbackToGetSomethingOf<Base>)
{
sal_Int64 res;
if (((MixinToGetSomethingOf<T>::get(rId, pThis, &res)
|| MixinToGetSomethingOf<Mixin>::get(rId, pThis, &res)) || ...
|| MixinToGetSomethingOf<Mixins>::get(rId, pThis, &res)))
{
return res;
}
return FallbackToGetSomethingOf<Base>::get(rId, pThis);
}
template <class T, class Mixin, class... Mixins, class Base>
sal_Int64 getSomethingImpl_skipDerived(const css::uno::Sequence<sal_Int8>& rId, T* pThis,
MixinToGetSomethingOf<Mixin>, MixinToGetSomethingOf<Mixins>...,
FallbackToGetSomethingOf<Base>)
{
sal_Int64 res;
if ((MixinToGetSomethingOf<Mixin>::get(rId, pThis, &res) || ...
|| MixinToGetSomethingOf<Mixins>::get(rId, pThis, &res)))
{
return res;
}
return FallbackToGetSomethingOf<Base>::get(rId, pThis); return FallbackToGetSomethingOf<Base>::get(rId, pThis);
} }