diff options
Diffstat (limited to 'canvas/inc')
23 files changed, 4251 insertions, 0 deletions
diff --git a/canvas/inc/base/basemutexhelper.hxx b/canvas/inc/base/basemutexhelper.hxx new file mode 100644 index 000000000..eba03cd9a --- /dev/null +++ b/canvas/inc/base/basemutexhelper.hxx @@ -0,0 +1,63 @@ +/* -*- 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 . + */ + +#pragma once + +#include <sal/config.h> + +#include <osl/mutex.hxx> + +/* Definition of the BaseMutexHelper class */ + +namespace canvas +{ + /** Base class, initializing its own baseclass with m_aMutex. + + This is necessary to make the CanvasBase, GraphicDeviceBase, + etc. classes freely combinable - letting them perform this + initialization would prohibit deriving e.g. CanvasBase from + GraphicDeviceBase. + */ + template< class Base > class BaseMutexHelper : public Base + { + protected: + /** Construct BaseMutexHelper + + This method is the whole purpose of this template: + initializing a base class with the provided m_aMutex + member (the WeakComponentImplHelper templates need that, + as they require the lifetime of the mutex to extend + theirs). + */ + BaseMutexHelper() : + Base( m_aMutex ) + { + } + + virtual void disposeThis() {} + + mutable osl::Mutex m_aMutex; + + private: + virtual void SAL_CALL disposing() override + { disposeThis(); } + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/bitmapcanvasbase.hxx b/canvas/inc/base/bitmapcanvasbase.hxx new file mode 100644 index 000000000..efbf58f55 --- /dev/null +++ b/canvas/inc/base/bitmapcanvasbase.hxx @@ -0,0 +1,125 @@ +/* -*- 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 . + */ + +#pragma once + +#include <base/canvasbase.hxx> +#include <com/sun/star/geometry/IntegerSize2D.hpp> + +namespace com::sun::star::rendering { class XBitmapCanvas; } + +namespace canvas +{ + /** Helper template to handle XBitmapCanvas method forwarding to + BitmapCanvasHelper + + Use this helper to handle the XBitmapCanvas part of your + implementation. + + @tpl Base + Base class to use, most probably one of the + WeakComponentImplHelperN templates with the appropriate + interfaces. At least XBitmapCanvas should be among them (why + else would you use this template, then?). Base class must have + a Base( const Mutex& ) constructor (like the + WeakComponentImplHelperN templates have). + + @tpl CanvasHelper + Canvas helper implementation for the backend in question + + @tpl Mutex + Lock strategy to use. Defaults to using the + BaseMutex-provided lock. Every time one of the methods is + entered, an object of type Mutex is created with m_aMutex as + the sole parameter, and destroyed again when the method scope + is left. + + @tpl UnambiguousBase + Optional unambiguous base class for XInterface of Base. It's + sometimes necessary to specify this parameter, e.g. if Base + derives from multiple UNO interface (were each provides its + own version of XInterface, making the conversion ambiguous) + + @see CanvasBase for further contractual requirements towards + the CanvasHelper type, and some examples. + */ + template< class Base, + class CanvasHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase=css::uno::XInterface > class BitmapCanvasBase : + public CanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > + { + public: + typedef CanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > BaseType; + + // XBitmap + virtual css::geometry::IntegerSize2D SAL_CALL getSize( ) override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maCanvasHelper.getSize(); + } + + virtual sal_Bool SAL_CALL hasAlpha( ) override + { + return true; + } + + virtual css::uno::Reference< css::rendering::XBitmap > SAL_CALL getScaledBitmap( const css::geometry::RealSize2D& newSize, + sal_Bool beFast ) override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maCanvasHelper.getScaledBitmap( newSize, beFast ); + } + + }; + + template< class Base, + class CanvasHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase = css::uno::XInterface > class BitmapCanvasBase2 : + public BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > + { + typedef BitmapCanvasBase< Base, CanvasHelper, Mutex, UnambiguousBase > + BaseType; + + public: + // XBitmapCanvas + virtual void SAL_CALL copyRect( const css::uno::Reference< css::rendering::XBitmapCanvas >& sourceCanvas, + const css::geometry::RealRectangle2D& sourceRect, + const css::rendering::ViewState& sourceViewState, + const css::rendering::RenderState& sourceRenderState, + const css::geometry::RealRectangle2D& destRect, + const css::rendering::ViewState& destViewState, + const css::rendering::RenderState& destRenderState ) override + { + tools::verifyArgs(sourceCanvas, sourceRect, sourceViewState, sourceRenderState, + destRect, destViewState, destRenderState, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::BaseType::MutexType aGuard( BaseType::m_aMutex ); + + BaseType::BaseType::mbSurfaceDirty = true; + } + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/bufferedgraphicdevicebase.hxx b/canvas/inc/base/bufferedgraphicdevicebase.hxx new file mode 100644 index 000000000..067d37a98 --- /dev/null +++ b/canvas/inc/base/bufferedgraphicdevicebase.hxx @@ -0,0 +1,258 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/awt/XWindow2.hpp> + +#include <canvas/canvastools.hxx> +#include <base/graphicdevicebase.hxx> + +namespace com::sun::star::awt { class XTopWindow; } + + +/* Definition of BufferedGraphicDeviceBase class */ + +namespace canvas +{ + /** Helper template base class for XGraphicDevice implementations + on windows. + + Use this base class if your target device is a + window. Additionally to GraphicDeviceBase, this template + provides an implementation of the awt::XWindowListener + interface, to receive notifications about state changes of the + associated window. + + @tpl Base + Base class to use, most probably one of the + WeakComponentImplHelperN templates with the appropriate + interfaces. At least XGraphicDevice should be among them (why else + would you use this template, then?). Base class must have an + Base( const Mutex& ) constructor (like the + WeakComponentImplHelperN templates have). As the very least, + the base class must be derived from uno::XInterface, as some + error reporting mechanisms rely on that. + + @tpl DeviceHelper + Device helper implementation for the backend in question. This + object will be held as a member of this template class, and + basically gets forwarded all XGraphicDevice API calls that + could not be handled generically. + + @tpl Mutex + Lock strategy to use. Defaults to using the + BaseMutex-provided lock. Every time one of the methods is + entered, an object of type Mutex is created with m_aMutex as + the sole parameter, and destroyed again when the method scope + is left. + + @tpl UnambiguousBase + Optional unambiguous base class for XInterface of Base. It's + sometimes necessary to specify this parameter, e.g. if Base + derives from multiple UNO interface (were each provides its + own version of XInterface, making the conversion ambiguous) + */ + template< class Base, + class DeviceHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase = css::uno::XInterface > class BufferedGraphicDeviceBase : + public GraphicDeviceBase< Base, DeviceHelper, Mutex, UnambiguousBase > + { + public: + typedef GraphicDeviceBase< Base, DeviceHelper, Mutex, UnambiguousBase > BaseType; + typedef Mutex MutexType; + + BufferedGraphicDeviceBase() : + mxWindow(), + maBounds(), + mbIsVisible( false ), + mbIsTopLevel( false ) + { + BaseType::maPropHelper.addProperties( + PropertySetHelper::MakeMap("Window", + [this] () { return this->getXWindow(); })); + } + + // XGraphicDevice + virtual css::uno::Reference< css::rendering::XBufferController > SAL_CALL getBufferController( ) override + { + return this; + } + + // XBufferController + virtual ::sal_Int32 SAL_CALL createBuffers( ::sal_Int32 nBuffers ) override + { + tools::verifyRange( nBuffers, sal_Int32(1) ); + + return 1; + } + + virtual void SAL_CALL destroyBuffers( ) override + { + } + + virtual sal_Bool SAL_CALL showBuffer( sal_Bool bUpdateAll ) override + { + MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maDeviceHelper.showBuffer( mbIsVisible, bUpdateAll ); + } + + virtual sal_Bool SAL_CALL switchBuffer( sal_Bool bUpdateAll ) override + { + MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maDeviceHelper.switchBuffer( mbIsVisible, bUpdateAll ); + } + + + /** Set corresponding canvas window + + Use this method to set the window this canvas displays + on. Comes in handy when the canvas needs to adapt size or + output position to the changing window. + + Whenever the bounds of the window change, <code>void + notifySizeUpdate( const awt::Rectangle& rBounds )</code> + is called, with rBounds the window bound rect relative to + the frame window. + */ + void setWindow( const css::uno::Reference< css::awt::XWindow2 >& rWindow ) + { + if( mxWindow.is() ) + mxWindow->removeWindowListener( this ); + + mxWindow = rWindow; + + if( mxWindow.is() ) + { + mbIsVisible = mxWindow->isVisible(); + mbIsTopLevel = + css::uno::Reference< css::awt::XTopWindow >( + mxWindow, + css::uno::UNO_QUERY ).is(); + + maBounds = transformBounds( mxWindow->getPosSize() ); + mxWindow->addWindowListener( this ); + } + } + + css::uno::Any getXWindow() const + { + return css::uno::makeAny(mxWindow); + } + + virtual void disposeThis() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + if( mxWindow.is() ) + { + mxWindow->removeWindowListener(this); + mxWindow.clear(); + } + + // pass on to base class + BaseType::disposeThis(); + } + + css::awt::Rectangle transformBounds( const css::awt::Rectangle& rBounds ) + { + // notifySizeUpdate's bounds are relative to the toplevel + // window + if( !mbIsTopLevel ) + return tools::getAbsoluteWindowRect( + rBounds, + mxWindow ); + else + return css::awt::Rectangle( 0,0,rBounds.Width,rBounds.Height ); + } + + void boundsChanged( const css::awt::WindowEvent& e ) + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + const css::awt::Rectangle& rNewBounds( + transformBounds( css::awt::Rectangle( e.X, + e.Y, + e.Width, + e.Height ))); + + if( rNewBounds.X != maBounds.X || + rNewBounds.Y != maBounds.Y || + rNewBounds.Width != maBounds.Width || + rNewBounds.Height != maBounds.Height ) + { + maBounds = rNewBounds; + BaseType::maDeviceHelper.notifySizeUpdate( maBounds ); + } + } + + // XWindowListener + virtual void disposeEventSource( const css::lang::EventObject& Source ) override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + if( Source.Source == mxWindow ) + mxWindow.clear(); + + BaseType::disposeEventSource(Source); + } + + virtual void SAL_CALL windowResized( const css::awt::WindowEvent& e ) override + { + boundsChanged( e ); + } + + virtual void SAL_CALL windowMoved( const css::awt::WindowEvent& e ) override + { + boundsChanged( e ); + } + + virtual void SAL_CALL windowShown( const css::lang::EventObject& ) override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + mbIsVisible = true; + } + + virtual void SAL_CALL windowHidden( const css::lang::EventObject& ) override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + mbIsVisible = false; + } + + protected: + css::uno::Reference< css::awt::XWindow2 > mxWindow; + + /// Current bounds of the owning Window + css::awt::Rectangle maBounds; + + /// True, if the window this canvas is contained in, is visible + bool mbIsVisible; + + private: + /// True, if the window this canvas is contained in, is a toplevel window + bool mbIsTopLevel; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/cachedprimitivebase.hxx b/canvas/inc/base/cachedprimitivebase.hxx new file mode 100644 index 000000000..ffdee6ee2 --- /dev/null +++ b/canvas/inc/base/cachedprimitivebase.hxx @@ -0,0 +1,104 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/rendering/XCachedPrimitive.hpp> +#include <com/sun/star/rendering/ViewState.hpp> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/basemutex.hxx> + +#include <canvas/canvastoolsdllapi.h> + +namespace com::sun::star::rendering { class XCanvas; } + +/* Definition of CachedPrimitiveBase class */ + +namespace canvas +{ + typedef cppu::WeakComponentImplHelper< css::rendering::XCachedPrimitive, + css::lang::XServiceInfo > CachedPrimitiveBase_Base; + + /** Base class, providing common functionality for implementers of + the XCachedPrimitive interface. + */ + class CANVASTOOLS_DLLPUBLIC CachedPrimitiveBase: + public cppu::BaseMutex, public CachedPrimitiveBase_Base + { + public: + + /** Create an XCachedPrimitive for given target canvas + + @param rUsedViewState + The viewstate the original object was rendered with + + @param rTarget + The target canvas the repaint should happen on. + */ + CachedPrimitiveBase( const css::rendering::ViewState& rUsedViewState, + const css::uno::Reference< css::rendering::XCanvas >& rTarget ); + + /// Dispose all internal references + virtual void SAL_CALL disposing() override; + + // XCachedPrimitive + virtual ::sal_Int8 SAL_CALL redraw( const css::rendering::ViewState& aState ) override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + protected: + virtual ~CachedPrimitiveBase() override; // we're a ref-counted UNO class. _We_ destroy ourselves. + + private: + CachedPrimitiveBase( const CachedPrimitiveBase& ) = delete; + CachedPrimitiveBase& operator=( const CachedPrimitiveBase& ) = delete; + + /** Actually perform the requested redraw. + + Clients must override this method, instead of the public + redraw() one. + + @param rNewState + The viewstate to redraw with + + @param rOldState + The viewstate this cache object was created with. + + @param rTargetCanvas + Target canvas to render to. + + @param bSameViewTransform + When true, rNewState and rOldState have the same transformation. + */ + virtual ::sal_Int8 doRedraw( const css::rendering::ViewState& rNewState, + const css::rendering::ViewState& rOldState, + const css::uno::Reference< css::rendering::XCanvas >& rTargetCanvas, + bool bSameViewTransform ) = 0; + + css::rendering::ViewState maUsedViewState; + css::uno::Reference< css::rendering::XCanvas > mxTarget; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/canvasbase.hxx b/canvas/inc/base/canvasbase.hxx new file mode 100644 index 000000000..323460a10 --- /dev/null +++ b/canvas/inc/base/canvasbase.hxx @@ -0,0 +1,451 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/rendering/TextDirection.hpp> +#include <osl/diagnose.h> +#include <osl/mutex.hxx> +#include <verifyinput.hxx> + +namespace com::sun::star::beans { struct PropertyValue; } +namespace com::sun::star::geometry { class XMapping2D; } +namespace com::sun::star::rendering { class XBitmap; } +namespace com::sun::star::rendering { class XCachedPrimitive; } +namespace com::sun::star::rendering { class XCanvasFont; } +namespace com::sun::star::rendering { class XGraphicDevice; } +namespace com::sun::star::rendering { class XPolyPolygon2D; } +namespace com::sun::star::rendering { class XTextLayout; } +namespace com::sun::star::rendering { struct FontInfo; } +namespace com::sun::star::rendering { struct StringContext; } + + +namespace canvas +{ + /** Helper template to handle XCanvas method forwarding to CanvasHelper + + Use this helper to handle the XCanvas part of your + implementation. In theory, we could have provided CanvasHelper + and CanvasBase as a single template, but that would duplicate + a lot of code now residing in CanvasHelper only. + + This template basically interposes itself between the full + interface you implement (i.e. not restricted to XCanvas. The + problem with UNO partial interface implementation actually is, + that you cannot do it the plain way, since deriving from a + common base subclass always introduces the whole set of pure + virtuals, that your baseclass helper just overridden) and your + implementation class. You then only have to implement the + functionality <em>besides</em> XCanvas. + + <pre> + Example: + typedef ::cppu::WeakComponentImplHelper < css::rendering::XSpriteCanvas, + css::lang::XInitialization, + css::lang::XServiceInfo, + css::lang::XServiceName > CanvasBase_Base; + typedef ::canvas::internal::CanvasBase< CanvasBase_Base, CanvasHelper > ExampleCanvas_Base; + + class ExampleCanvas : public ExampleCanvas_Base, + public SpriteSurface, + public RepaintTarget + { + }; + </pre> + + @tpl Base + Base class to use, most probably the + WeakComponentImplHelper template with the appropriate + interfaces. At least XCanvas should be among them (why else + would you use this template, then?). Base class must have an + Base( const Mutex& ) constructor (like the + WeakComponentImplHelper template has). As the very least, + the base class must be derived from uno::XInterface, as some + error reporting mechanisms rely on that. + + @tpl CanvasHelper + Canvas helper implementation for the backend in question. This + object will be held as a member of this template class, and + basically gets forwarded all XCanvas API calls. Furthermore, + every time the canvas API semantically changes the content of + the canvas, CanvasHelper::modifying() will get called + (<em>before</em> the actual modification takes place). + + @tpl Mutex + Lock strategy to use. Defaults to using the + BaseMutex-provided lock. Every time one of the methods is + entered, an object of type Mutex is created with m_aMutex as + the sole parameter, and destroyed again when the method scope + is left. + + @tpl UnambiguousBase + Optional unambiguous base class for XInterface of Base. It's + sometimes necessary to specify this parameter, e.g. if Base + derives from multiple UNO interface (were each provides its + own version of XInterface, making the conversion ambiguous) + */ + template< class Base, + class CanvasHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase=css::uno::XInterface > class CanvasBase : + public Base + { + public: + typedef Base BaseType; + typedef Mutex MutexType; + typedef UnambiguousBase UnambiguousBaseType; + + /** Create CanvasBase + */ + CanvasBase() : + maCanvasHelper(), + mbSurfaceDirty( true ) + { + } + + virtual void disposeThis() override + { + MutexType aGuard( BaseType::m_aMutex ); + + maCanvasHelper.disposing(); + + // pass on to base class + BaseType::disposeThis(); + } + + // XCanvas + virtual void SAL_CALL clear() override + { + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + maCanvasHelper.clear(); + } + + virtual void SAL_CALL drawPoint(const css::geometry::RealPoint2D& aPoint, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState) override + { + tools::verifyArgs(aPoint, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + } + + virtual void SAL_CALL drawLine(const css::geometry::RealPoint2D& aStartPoint, + const css::geometry::RealPoint2D& aEndPoint, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState) override + { + tools::verifyArgs(aStartPoint, aEndPoint, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + maCanvasHelper.drawLine( this, aStartPoint, aEndPoint, viewState, renderState ); + } + + virtual void SAL_CALL drawBezier( const css::geometry::RealBezierSegment2D& aBezierSegment, + const css::geometry::RealPoint2D& aEndPoint, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override + { + tools::verifyArgs(aBezierSegment, aEndPoint, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + maCanvasHelper.drawBezier( this, aBezierSegment, aEndPoint, viewState, renderState ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + drawPolyPolygon(const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.drawPolyPolygon( this, xPolyPolygon, viewState, renderState ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + strokePolyPolygon(const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + const css::rendering::StrokeAttributes& strokeAttributes) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, strokeAttributes, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.strokePolyPolygon( this, xPolyPolygon, viewState, renderState, strokeAttributes ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + strokeTexturedPolyPolygon( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + const css::uno::Sequence< css::rendering::Texture >& textures, + const css::rendering::StrokeAttributes& strokeAttributes ) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, strokeAttributes, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.strokeTexturedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures, strokeAttributes ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + strokeTextureMappedPolyPolygon( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + const css::uno::Sequence< css::rendering::Texture >& textures, + const css::uno::Reference< css::geometry::XMapping2D >& xMapping, + const css::rendering::StrokeAttributes& strokeAttributes ) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, textures, xMapping, strokeAttributes, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.strokeTextureMappedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures, xMapping, strokeAttributes ); + } + + virtual css::uno::Reference< css::rendering::XPolyPolygon2D > SAL_CALL + queryStrokeShapes( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + const css::rendering::StrokeAttributes& strokeAttributes ) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, strokeAttributes, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.queryStrokeShapes( this, xPolyPolygon, viewState, renderState, strokeAttributes ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + fillPolyPolygon(const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.fillPolyPolygon( this, xPolyPolygon, viewState, renderState ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + fillTexturedPolyPolygon(const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + const css::uno::Sequence< css::rendering::Texture >& textures) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, textures, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.fillTexturedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + fillTextureMappedPolyPolygon( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + const css::uno::Sequence< css::rendering::Texture >& textures, + const css::uno::Reference< css::geometry::XMapping2D >& xMapping ) override + { + tools::verifyArgs(xPolyPolygon, viewState, renderState, textures, xMapping, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.fillTextureMappedPolyPolygon( this, xPolyPolygon, viewState, renderState, textures, xMapping ); + } + + + virtual css::uno::Reference< css::rendering::XCanvasFont > SAL_CALL + createFont( const css::rendering::FontRequest& fontRequest, + const css::uno::Sequence< css::beans::PropertyValue >& extraFontProperties, + const css::geometry::Matrix2D& fontMatrix ) override + { + tools::verifyArgs(fontRequest, + // dummy, to keep argPos in sync + fontRequest, + fontMatrix, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + return maCanvasHelper.createFont( this, fontRequest, extraFontProperties, fontMatrix ); + } + + + virtual css::uno::Sequence< css::rendering::FontInfo > SAL_CALL + queryAvailableFonts( const css::rendering::FontInfo& aFilter, + const css::uno::Sequence< css::beans::PropertyValue >& aFontProperties ) override + { + tools::verifyArgs(aFilter, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + return maCanvasHelper.queryAvailableFonts( this, aFilter, aFontProperties ); + } + + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + drawText(const css::rendering::StringContext& text, + const css::uno::Reference< css::rendering::XCanvasFont >& xFont, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState, + sal_Int8 textDirection) override + { + tools::verifyArgs(xFont, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + tools::verifyRange( textDirection, + css::rendering::TextDirection::WEAK_LEFT_TO_RIGHT, + css::rendering::TextDirection::STRONG_RIGHT_TO_LEFT ); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.drawText( this, text, xFont, viewState, renderState, textDirection ); + } + + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + drawTextLayout(const css::uno::Reference< css::rendering::XTextLayout >& laidOutText, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState) override + { + tools::verifyArgs(laidOutText, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.drawTextLayout( this, laidOutText, viewState, renderState ); + } + + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + drawBitmap( const css::uno::Reference< css::rendering::XBitmap >& xBitmap, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override + { + tools::verifyArgs(xBitmap, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.drawBitmap( this, xBitmap, viewState, renderState ); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + drawBitmapModulated( const css::uno::Reference< css::rendering::XBitmap >& xBitmap, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override + { + tools::verifyArgs(xBitmap, viewState, renderState, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + mbSurfaceDirty = true; + + return maCanvasHelper.drawBitmapModulated( this, xBitmap, viewState, renderState ); + } + + virtual css::uno::Reference< css::rendering::XGraphicDevice > SAL_CALL + getDevice() override + { + MutexType aGuard( BaseType::m_aMutex ); + + return maCanvasHelper.getDevice(); + } + + protected: + ~CanvasBase() {} // we're a ref-counted UNO class. _We_ destroy ourselves. + + CanvasHelper maCanvasHelper; + mutable bool mbSurfaceDirty; + + private: + CanvasBase( const CanvasBase& ) = delete; + CanvasBase& operator=( const CanvasBase& ) = delete; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/canvascustomspritebase.hxx b/canvas/inc/base/canvascustomspritebase.hxx new file mode 100644 index 000000000..c47f232e0 --- /dev/null +++ b/canvas/inc/base/canvascustomspritebase.hxx @@ -0,0 +1,261 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/rendering/XCanvas.hpp> + +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/range/b2drange.hxx> +#include <base/integerbitmapbase.hxx> +#include <base/bitmapcanvasbase.hxx> + +namespace com::sun::star::rendering { class XPolyPolygon2D; } + +namespace canvas +{ + /** Helper template to handle XCustomSprite method forwarding to + CanvasCustomSpriteHelper + + Use this helper to handle the XCustomSprite part of your + implementation. + + @tpl Base + Base class to use, most probably one of the + WeakComponentImplHelperN templates with the appropriate + interfaces. At least XCustomSprite and Sprite should be among + them (why else would you use this template, then?). Base class + must have a Base( const Mutex& ) constructor (like the + WeakComponentImplHelperN templates have). + + @tpl SpriteHelper + Sprite helper implementation for the backend in question + + @tpl CanvasHelper + Canvas helper implementation for the backend in question + + @tpl Mutex + Lock strategy to use. Defaults to using the + BaseMutex-provided lock. Every time one of the methods is + entered, an object of type Mutex is created with m_aMutex as + the sole parameter, and destroyed again when the method scope + is left. + + @tpl UnambiguousBase + Optional unambiguous base class for XInterface of Base. It's + sometimes necessary to specify this parameter, e.g. if Base + derives from multiple UNO interface (were each provides its + own version of XInterface, making the conversion ambiguous) + + @see CanvasCustomSpriteHelper for further contractual + requirements towards the SpriteHelper type, and some examples. + */ + template< class Base, + class SpriteHelper, + class CanvasHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase = css::uno::XInterface > class CanvasCustomSpriteBase : + public IntegerBitmapBase< BitmapCanvasBase2<Base, CanvasHelper, Mutex, UnambiguousBase> > + { + public: + typedef IntegerBitmapBase< BitmapCanvasBase2<Base, CanvasHelper, Mutex, UnambiguousBase> > BaseType; + + CanvasCustomSpriteBase() : + maSpriteHelper() + { + } + + /** Object is being disposed. + + Called from the cppu helper base, to notify disposal of + this object. Already releases all internal references. + + @derive when overriding this method in derived classes, + <em>always</em> call the base class' method! + */ + virtual void disposeThis() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.disposing(); + + // pass on to base class + BaseType::disposeThis(); + } + + // XCanvas: selectively override base's methods here, for opacity tracking + virtual void SAL_CALL clear() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.clearingContent( this ); + + // and forward to base class, which handles the actual rendering + return BaseType::clear(); + } + + virtual css::uno::Reference< css::rendering::XCachedPrimitive > SAL_CALL + drawBitmap( const css::uno::Reference< css::rendering::XBitmap >& xBitmap, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override + { + tools::verifyArgs(xBitmap, viewState, renderState, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.checkDrawBitmap( this, xBitmap, viewState, renderState ); + + // and forward to base class, which handles the actual rendering + return BaseType::drawBitmap( xBitmap, + viewState, + renderState ); + } + + // TODO(F3): If somebody uses the XIntegerBitmap methods to + // clear pixel (setting alpha != 1.0 there), or a compositing + // mode results in similar alpha, maSpriteHelper might + // erroneously report fully opaque sprites. Effectively, all + // render methods must be overridden here; or better, + // functionality provided at the baseclass. + + // XSprite + virtual void SAL_CALL setAlpha( double alpha ) override + { + tools::verifyRange( alpha, 0.0, 1.0 ); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.setAlpha( this, alpha ); + } + + virtual void SAL_CALL move( const css::geometry::RealPoint2D& aNewPos, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ) override + { + tools::verifyArgs(aNewPos, viewState, renderState, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.move( this, aNewPos, viewState, renderState ); + } + + virtual void SAL_CALL transform( const css::geometry::AffineMatrix2D& aTransformation ) override + { + tools::verifyArgs(aTransformation, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.transform( this, aTransformation ); + } + + virtual void SAL_CALL clip( const css::uno::Reference< css::rendering::XPolyPolygon2D >& aClip ) override + { + // NULL xClip explicitly allowed here (to clear clipping) + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.clip( this, aClip ); + } + + virtual void SAL_CALL setPriority( double nPriority ) override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.setPriority( this, nPriority ); + } + + virtual void SAL_CALL show() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.show( this ); + } + + virtual void SAL_CALL hide() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maSpriteHelper.hide( this ); + } + + // XCustomSprite + virtual css::uno::Reference< css::rendering::XCanvas > SAL_CALL + getContentCanvas() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return this; + } + + // Sprite + virtual bool isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return maSpriteHelper.isAreaUpdateOpaque( rUpdateArea ); + } + + virtual bool isContentChanged() const override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::mbSurfaceDirty; + } + + virtual ::basegfx::B2DPoint getPosPixel() const override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return maSpriteHelper.getPosPixel(); + } + + virtual ::basegfx::B2DVector getSizePixel() const override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return maSpriteHelper.getSizePixel(); + } + + virtual ::basegfx::B2DRange getUpdateArea() const override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return maSpriteHelper.getUpdateArea(); + } + + virtual double getPriority() const override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return maSpriteHelper.getPriority(); + } + + protected: + SpriteHelper maSpriteHelper; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/canvascustomspritehelper.hxx b/canvas/inc/base/canvascustomspritehelper.hxx new file mode 100644 index 000000000..32fcf6452 --- /dev/null +++ b/canvas/inc/base/canvascustomspritehelper.hxx @@ -0,0 +1,217 @@ +/* -*- 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 . + */ + +#pragma once + +#include <basegfx/matrix/b2dhommatrix.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/polygon/b2dpolypolygon.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <base/spritesurface.hxx> +#include <canvas/canvastoolsdllapi.h> + +namespace com::sun::star::geometry { struct AffineMatrix2D; } +namespace com::sun::star::geometry { struct RealPoint2D; } +namespace com::sun::star::geometry { struct RealSize2D; } +namespace com::sun::star::rendering { class XBitmap; } +namespace com::sun::star::rendering { class XPolyPolygon2D; } +namespace com::sun::star::rendering { struct RenderState; } +namespace com::sun::star::rendering { struct ViewState; } + + +namespace canvas +{ + /* Definition of CanvasCustomSpriteHelper class */ + + /** Base class for an XSprite helper implementation - to be used + in concert with CanvasCustomSpriteBase + */ + class CANVASTOOLS_DLLPUBLIC CanvasCustomSpriteHelper + { + public: + CanvasCustomSpriteHelper(); + virtual ~CanvasCustomSpriteHelper() {} + + /** Init helper + + @param rSpriteSize + Requested size of the sprite, as passed to the + XSpriteCanvas::createCustomSprite() method + + @param rOwningSpriteCanvas + The XSpriteCanvas this sprite is displayed on + */ + void init( const css::geometry::RealSize2D& rSpriteSize, + const SpriteSurface::Reference& rOwningSpriteCanvas ); + + /** Object is being disposed, release all internal references + + @derive when overriding this method in derived classes, + <em>always</em> call the base class' method! + */ + void disposing(); + + // XCanvas + /// need to call this method for XCanvas::clear(), for opacity tracking + void clearingContent( const Sprite::Reference& rSprite ); + + /// need to call this method for XCanvas::drawBitmap(), for opacity tracking + void checkDrawBitmap( const Sprite::Reference& rSprite, + const css::uno::Reference< css::rendering::XBitmap >& xBitmap, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ); + + // XSprite + void setAlpha( const Sprite::Reference& rSprite, + double alpha ); + void move( const Sprite::Reference& rSprite, + const css::geometry::RealPoint2D& aNewPos, + const css::rendering::ViewState& viewState, + const css::rendering::RenderState& renderState ); + void transform( const Sprite::Reference& rSprite, + const css::geometry::AffineMatrix2D& aTransformation ); + void clip( const Sprite::Reference& rSprite, + const css::uno::Reference< css::rendering::XPolyPolygon2D >& aClip ); + void setPriority( const Sprite::Reference& rSprite, + double nPriority ); + void show( const Sprite::Reference& rSprite ); + void hide( const Sprite::Reference& rSprite ); + + // Sprite + bool isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const; + const ::basegfx::B2DPoint& getPosPixel() const { return maPosition; } + const ::basegfx::B2DVector& getSizePixel() const { return maSize; } + ::basegfx::B2DRange getUpdateArea() const; + double getPriority() const { return mfPriority; } + + // redraw must be implemented by derived - non sensible default implementation + // void redraw( const Sprite::Reference& rSprite, + // const ::basegfx::B2DPoint& rPos ) const; + + + // Helper methods for derived classes + + + /// Calc sprite update area from given raw sprite bounds + ::basegfx::B2DRange getUpdateArea( const ::basegfx::B2DRange& rUntransformedSpriteBounds ) const; + + /** Returns true, if sprite content bitmap is fully opaque. + + This does not take clipping or transformation into + account, but only denotes that the sprite bitmap's alpha + channel is all 1.0 + */ + bool isContentFullyOpaque() const { return mbIsContentFullyOpaque; } + + /// Returns true, if transformation has changed since last transformUpdated() call + bool hasTransformChanged() const { return mbTransformDirty; } + + /// Retrieve current alpha value + double getAlpha() const { return mfAlpha; } + + /// Retrieve current clip + const css::uno::Reference< + css::rendering::XPolyPolygon2D >& getClip() const { return mxClipPoly; } + + const ::basegfx::B2DHomMatrix& getTransformation() const { return maTransform; } + + /// Retrieve current activation state + bool isActive() const { return mbActive; } + + protected: + /** Notifies that caller is again in sync with current transformation + + const, but modifies state visible to derived + classes. beware of passing this information to the + outside! + */ + void transformUpdated() const { mbTransformDirty=false; } + + private: + CanvasCustomSpriteHelper( const CanvasCustomSpriteHelper& ) = delete; + CanvasCustomSpriteHelper& operator=( const CanvasCustomSpriteHelper& ) = delete; + + /** Called to convert an API polygon to a basegfx polygon + + @derive Needs to be provided by backend-specific code + */ + virtual ::basegfx::B2DPolyPolygon polyPolygonFromXPolyPolygon2D( + css::uno::Reference< css::rendering::XPolyPolygon2D >& xPoly ) const = 0; + + /** Update clip information from current state + + This method recomputes the maCurrClipBounds and + mbIsCurrClipRectangle members from the current clip and + transformation. IFF the clip changed from rectangular to + rectangular again, this method issues a sequence of + optimized SpriteSurface::updateSprite() calls. + + @return true, if SpriteSurface::updateSprite() was already + called within this method. + */ + bool updateClipState( const Sprite::Reference& rSprite ); + + + /// Owning sprite canvas + SpriteSurface::Reference mpSpriteCanvas; + + /** Currently active clip area. + + This member is either empty, denoting that the current + clip shows the full sprite content, or contains a + rectangular subarea of the sprite, outside of which + the sprite content is fully clipped. + + @see mbIsCurrClipRectangle + */ + ::basegfx::B2DRange maCurrClipBounds; + + // sprite state + ::basegfx::B2DPoint maPosition; + ::basegfx::B2DVector maSize; + ::basegfx::B2DHomMatrix maTransform; + css::uno::Reference< css::rendering::XPolyPolygon2D > mxClipPoly; + double mfPriority; + double mfAlpha; + bool mbActive; // true, if not hidden + + /** If true, denotes that the current sprite clip is a true + rectangle, i.e. maCurrClipBounds <em>exactly</em> + describes the visible area of the sprite. + + @see maCurrClipBounds + */ + bool mbIsCurrClipRectangle; + + /** Redraw speedup. + + When true, this flag denotes that the current sprite + content is fully opaque, thus, that blits to the screen do + neither have to take alpha into account, nor prepare any + background for the sprite area. + */ + mutable bool mbIsContentFullyOpaque; + + /// True, iff maTransform has changed + mutable bool mbTransformDirty; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/disambiguationhelper.hxx b/canvas/inc/base/disambiguationhelper.hxx new file mode 100644 index 000000000..06e6f9af0 --- /dev/null +++ b/canvas/inc/base/disambiguationhelper.hxx @@ -0,0 +1,79 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/lang/EventObject.hpp> +#include <osl/mutex.hxx> + + +/* Definition of the DisambiguationHelper class */ + +namespace canvas +{ + /** Base class, initializing its own baseclass with m_aMutex. + + This is necessary to make the CanvasBase, GraphicDeviceBase, + etc. classes freely combinable - letting them perform this + initialization would prohibit deriving e.g. CanvasBase from + GraphicDeviceBase. + + On top of that, disambiguates XEventListener::disposing and + WeakComponentImplHelper::disposing. + + Having two virtual methods with the same name, and not + overriding them in every derived class, will hide one of + them. Later trying to override the same method, will generate + a new vtable slot, and lead to very hard to spot errors. + */ + template< class Base > class DisambiguationHelper : public Base + { + protected: + /** Construct DisambiguationHelper + + This method is the whole purpose of this template: + initializing a base class with the provided m_aMutex + member (the WeakComponentImplHelper templates need that, + as they require the lifetime of the mutex to extend + theirs). + */ + DisambiguationHelper() : + Base( m_aMutex ) + { + } + + virtual void disposeThis() + {} + /// @throws css::uno::RuntimeException + virtual void disposeEventSource( const css::lang::EventObject& ) + {} + + mutable ::osl::Mutex m_aMutex; + + private: + virtual void SAL_CALL disposing() override + { disposeThis(); } + + virtual void SAL_CALL disposing( const css::lang::EventObject& Source ) override + { disposeEventSource(Source); } + + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/graphicdevicebase.hxx b/canvas/inc/base/graphicdevicebase.hxx new file mode 100644 index 000000000..3a7c49834 --- /dev/null +++ b/canvas/inc/base/graphicdevicebase.hxx @@ -0,0 +1,348 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/rendering/XBufferController.hpp> +#include <com/sun/star/rendering/XLinePolyPolygon2D.hpp> +#include <com/sun/star/rendering/XBezierPolyPolygon2D.hpp> +#include <com/sun/star/rendering/XBitmap.hpp> +#include <com/sun/star/rendering/XVolatileBitmap.hpp> + +#include <rtl/ref.hxx> + +#include <parametricpolypolygon.hxx> +#include <propertysethelper.hxx> +#include <verifyinput.hxx> + +namespace com::sun::star::beans { class XPropertySetInfo; } +namespace com::sun::star::lang { class XMultiServiceFactory; } +namespace com::sun::star::rendering { class XColorSpace; } + + +/* Definition of GraphicDeviceBase class */ + +namespace canvas +{ + /** Helper template base class for XGraphicDevice implementations. + + This base class provides partial implementations of the + XGraphicDevice-related interface, such as XColorSpace. + + This template basically interposes itself between the full + interface you implement (i.e. not restricted to XGraphicDevice + etc.). The problem with UNO partial interface implementation + actually is, that you cannot do it the plain way, since + deriving from a common base subclass always introduces the + whole set of pure virtuals, that your baseclass helper just + overridden) and your implementation class. You then only have + to implement the functionality <em>besides</em> + XGraphicDevice. If you want to support the optional debug + XUpdatable interface, also add that to the base classes + (client code will call the corresponding update() method, + whenever a burst of animations is over). + + <pre> + Example: + typedef ::cppu::WeakComponentImplHelper < css::rendering::XGraphicDevice, + css::rendering::XColorSpace, + css::rendering::XPropertySet, + css::lang::XServiceInfo, + css::lang::XServiceName > GraphicDeviceBase_Base; + typedef ::canvas::internal::GraphicDeviceBase< GraphicDeviceBase, DeviceHelper > ExampleDevice_Base; + + class ExampleDevice : public ExampleDevice_Base + { + }; + </pre> + + @tpl Base + Base class to use, most probably the + WeakComponentImplHelper template with the appropriate + interfaces. At least XGraphicDevice should be among them (why else + would you use this template, then?). Base class must have an + Base( const Mutex& ) constructor (like the + WeakComponentImplHelper template has). As the very least, + the base class must be derived from uno::XInterface, as some + error reporting mechanisms rely on that. + + @tpl DeviceHelper + Device helper implementation for the backend in question. This + object will be held as a member of this template class, and + basically gets forwarded all XGraphicDevice API calls that + could not be handled generically. + + @tpl Mutex + Lock strategy to use. Defaults to using the + DisambiguationHelper-provided lock. Every time one of the methods is + entered, an object of type Mutex is created with m_aMutex as + the sole parameter, and destroyed again when the method scope + is left. + + @tpl UnambiguousBase + Optional unambiguous base class for XInterface of Base. It's + sometimes necessary to specify this parameter, e.g. if Base + derives from multiple UNO interface (were each provides its + own version of XInterface, making the conversion ambiguous) + */ + template< class Base, + class DeviceHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase=css::uno::XInterface > class GraphicDeviceBase : + public Base + { + public: + typedef Base BaseType; + typedef Mutex MutexType; + typedef UnambiguousBase UnambiguousBaseType; + + typedef ::rtl::Reference< GraphicDeviceBase > Reference; + + GraphicDeviceBase() : + maDeviceHelper(), + maPropHelper(), + mbDumpScreenContent(false) + { + maPropHelper.initProperties( PropertySetHelper::MakeMap + ("HardwareAcceleration", + [this] () { return this->maDeviceHelper.isAccelerated(); } ) + ("DeviceHandle", + [this] () { return this->maDeviceHelper.getDeviceHandle(); } ) + ("SurfaceHandle", + [this] () { return this->maDeviceHelper.getSurfaceHandle(); } ) + ("DumpScreenContent", + [this] () { return this->getDumpScreenContent(); }, + [this] (css::uno::Any const& rAny) { this->setDumpScreenContent(rAny); })); + } + + virtual void disposeThis() override + { + MutexType aGuard( BaseType::m_aMutex ); + + maDeviceHelper.disposing(); + + // pass on to base class + BaseType::disposeThis(); + } + + // XGraphicDevice + virtual css::uno::Reference< css::rendering::XBufferController > SAL_CALL getBufferController( ) override + { + return css::uno::Reference< css::rendering::XBufferController >(); + } + + virtual css::uno::Reference< css::rendering::XColorSpace > SAL_CALL getDeviceColorSpace( ) override + { + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.getColorSpace(); + } + + virtual css::geometry::RealSize2D SAL_CALL getPhysicalResolution() override + { + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.getPhysicalResolution(); + } + + virtual css::geometry::RealSize2D SAL_CALL getPhysicalSize() override + { + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.getPhysicalSize(); + } + + virtual css::uno::Reference< css::rendering::XLinePolyPolygon2D > SAL_CALL createCompatibleLinePolyPolygon( const css::uno::Sequence< css::uno::Sequence< css::geometry::RealPoint2D > >& points ) override + { + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.createCompatibleLinePolyPolygon( this, points ); + } + + virtual css::uno::Reference< css::rendering::XBezierPolyPolygon2D > SAL_CALL createCompatibleBezierPolyPolygon( const css::uno::Sequence< css::uno::Sequence< css::geometry::RealBezierSegment2D > >& points ) override + { + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.createCompatibleBezierPolyPolygon( this, points ); + } + + virtual css::uno::Reference< css::rendering::XBitmap > SAL_CALL createCompatibleBitmap( const css::geometry::IntegerSize2D& size ) override + { + tools::verifyBitmapSize(size, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.createCompatibleBitmap( this, size ); + } + + virtual css::uno::Reference< css::rendering::XVolatileBitmap > SAL_CALL createVolatileBitmap( const css::geometry::IntegerSize2D& size ) override + { + tools::verifyBitmapSize(size, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.createVolatileBitmap( this, size ); + } + + virtual css::uno::Reference< css::rendering::XBitmap > SAL_CALL createCompatibleAlphaBitmap( const css::geometry::IntegerSize2D& size ) override + { + tools::verifyBitmapSize(size, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.createCompatibleAlphaBitmap( this, size ); + } + + virtual css::uno::Reference< css::rendering::XVolatileBitmap > SAL_CALL createVolatileAlphaBitmap( const css::geometry::IntegerSize2D& size ) override + { + tools::verifyBitmapSize(size, + OSL_THIS_FUNC, + static_cast< UnambiguousBaseType* >(this)); + + MutexType aGuard( BaseType::m_aMutex ); + + return maDeviceHelper.createVolatileAlphaBitmap( this, size ); + } + + virtual css::uno::Reference< css::lang::XMultiServiceFactory > SAL_CALL getParametricPolyPolygonFactory( ) override + { + return this; + } + + virtual sal_Bool SAL_CALL hasFullScreenMode( ) override + { + return false; + } + + virtual sal_Bool SAL_CALL enterFullScreenMode( sal_Bool ) override + { + return false; + } + + // XMultiServiceFactory + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstance( const OUString& aServiceSpecifier ) override + { + return css::uno::Reference< css::rendering::XParametricPolyPolygon2D >( + ParametricPolyPolygon::create(this, + aServiceSpecifier, + css::uno::Sequence< css::uno::Any >())); + } + + virtual css::uno::Reference< css::uno::XInterface > SAL_CALL createInstanceWithArguments( const OUString& aServiceSpecifier, const css::uno::Sequence< css::uno::Any >& Arguments ) override + { + return css::uno::Reference< css::rendering::XParametricPolyPolygon2D >( + ParametricPolyPolygon::create(this, + aServiceSpecifier, + Arguments)); + } + + virtual css::uno::Sequence< OUString > SAL_CALL getAvailableServiceNames( ) override + { + return ParametricPolyPolygon::getAvailableServiceNames(); + } + + + // XUpdatable + virtual void SAL_CALL update() override + { + MutexType aGuard( BaseType::m_aMutex ); + + if( mbDumpScreenContent ) + maDeviceHelper.dumpScreenContent(); + } + + + // XPropertySet + virtual css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() override + { + MutexType aGuard( BaseType::m_aMutex ); + return maPropHelper.getPropertySetInfo(); + } + + virtual void SAL_CALL setPropertyValue( const OUString& aPropertyName, + const css::uno::Any& aValue ) override + { + MutexType aGuard( BaseType::m_aMutex ); + maPropHelper.setPropertyValue( aPropertyName, aValue ); + } + + virtual css::uno::Any SAL_CALL getPropertyValue( const OUString& aPropertyName ) override + { + MutexType aGuard( BaseType::m_aMutex ); + return maPropHelper.getPropertyValue( aPropertyName ); + } + + virtual void SAL_CALL addPropertyChangeListener( const OUString& aPropertyName, + const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ) override + { + MutexType aGuard( BaseType::m_aMutex ); + maPropHelper.addPropertyChangeListener( aPropertyName, + xListener ); + } + + virtual void SAL_CALL removePropertyChangeListener( const OUString& , + const css::uno::Reference< css::beans::XPropertyChangeListener >& ) override + { + } + + virtual void SAL_CALL addVetoableChangeListener( const OUString& aPropertyName, + const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener ) override + { + MutexType aGuard( BaseType::m_aMutex ); + maPropHelper.addVetoableChangeListener( aPropertyName, + xListener ); + } + + virtual void SAL_CALL removeVetoableChangeListener( const OUString& , + const css::uno::Reference< css::beans::XVetoableChangeListener >& ) override + { + } + + protected: + ~GraphicDeviceBase() {} // we're a ref-counted UNO class. _We_ destroy ourselves. + + css::uno::Any getDumpScreenContent() const + { + return css::uno::makeAny( mbDumpScreenContent ); + } + + void setDumpScreenContent( const css::uno::Any& rAny ) + { + // TODO(Q1): this was mbDumpScreenContent = + // rAny.get<bool>(), only that gcc3.3 wouldn't eat it + rAny >>= mbDumpScreenContent; + } + + DeviceHelper maDeviceHelper; + PropertySetHelper maPropHelper; + bool mbDumpScreenContent; + + private: + GraphicDeviceBase( const GraphicDeviceBase& ) = delete; + GraphicDeviceBase& operator=( const GraphicDeviceBase& ) = delete; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/integerbitmapbase.hxx b/canvas/inc/base/integerbitmapbase.hxx new file mode 100644 index 000000000..aca2551f2 --- /dev/null +++ b/canvas/inc/base/integerbitmapbase.hxx @@ -0,0 +1,109 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/rendering/IntegerBitmapLayout.hpp> +#include <verifyinput.hxx> +#include <osl/diagnose.h> + + +namespace canvas +{ + /** Helper template to handle XIntegerBitmap method forwarding to + BitmapCanvasHelper + + Use this helper to handle the XIntegerBitmap part of your + implementation. + + @tpl Base + Either BitmapCanvasBase (just XBitmap) or BitmapCanvasBase2 (XBitmap and + XBitmapCanvas). + */ + template< class Base > class IntegerBitmapBase : + public Base + { + public: + // XIntegerBitmap + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getData( css::rendering::IntegerBitmapLayout& bitmapLayout, + const css::geometry::IntegerRectangle2D& rect ) override + { + tools::verifyArgs(rect, + OSL_THIS_FUNC, + static_cast< typename Base::UnambiguousBaseType* >(this)); + tools::verifyIndexRange(rect, Base::getSize() ); + + typename Base::MutexType aGuard( Base::m_aMutex ); + + return Base::maCanvasHelper.getData( bitmapLayout, + rect ); + } + + virtual void SAL_CALL setData( const css::uno::Sequence< sal_Int8 >&, + const css::rendering::IntegerBitmapLayout& bitmapLayout, + const css::geometry::IntegerRectangle2D& rect ) override + { + tools::verifyArgs(bitmapLayout, rect, + OSL_THIS_FUNC, + static_cast< typename Base::UnambiguousBaseType* >(this)); + tools::verifyIndexRange(rect, Base::getSize() ); + + typename Base::MutexType aGuard( Base::m_aMutex ); + + Base::mbSurfaceDirty = true; + } + + virtual void SAL_CALL setPixel( const css::uno::Sequence< sal_Int8 >&, + const css::rendering::IntegerBitmapLayout& bitmapLayout, + const css::geometry::IntegerPoint2D& pos ) override + { + tools::verifyArgs(bitmapLayout, pos, + OSL_THIS_FUNC, + static_cast< typename Base::UnambiguousBaseType* >(this)); + tools::verifyIndexRange(pos, Base::getSize() ); + + typename Base::MutexType aGuard( Base::m_aMutex ); + + Base::mbSurfaceDirty = true; + } + + virtual css::uno::Sequence< sal_Int8 > SAL_CALL getPixel( css::rendering::IntegerBitmapLayout& bitmapLayout, + const css::geometry::IntegerPoint2D& pos ) override + { + tools::verifyArgs(pos, + OSL_THIS_FUNC, + static_cast< typename Base::UnambiguousBaseType* >(this)); + tools::verifyIndexRange(pos, Base::getSize() ); + + typename Base::MutexType aGuard( Base::m_aMutex ); + + return Base::maCanvasHelper.getPixel( bitmapLayout, + pos ); + } + + virtual css::rendering::IntegerBitmapLayout SAL_CALL getMemoryLayout( ) override + { + typename Base::MutexType aGuard( Base::m_aMutex ); + + return Base::maCanvasHelper.getMemoryLayout(); + } + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/sprite.hxx b/canvas/inc/base/sprite.hxx new file mode 100644 index 000000000..8a89c9454 --- /dev/null +++ b/canvas/inc/base/sprite.hxx @@ -0,0 +1,110 @@ +/* -*- 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 . + */ + +#pragma once + +#include <rtl/ref.hxx> +#include <com/sun/star/lang/XComponent.hpp> +#include <basegfx/point/b2dpoint.hxx> + +namespace basegfx +{ + class B2DVector; + class B2DRange; +} + +namespace canvas +{ + /* Definition of Sprite interface (as we mix with UNO here, has to + be XInterface - reference holders to a Sprite must be able to + control lifetime of reference target) + */ + + /** Helper interface to connect SpriteCanvas with various + sprite implementations. + + This interface should be implemented from every sprite class, + as it provides essential repaint and update area facilitates. + + @derive typically, each canvas implementation will derive + another interface from this one, that adds rendering + functionality (which, of course, is impossible here in a + generic way) + */ + class Sprite : public css::lang::XComponent + { + public: + typedef ::rtl::Reference< Sprite > Reference; + + /** Query whether sprite update will fully cover the given area. + + Use this method to determine whether any background + content (regardless of static or sprite) needs an update + before rendering this sprite. + + @return true, if sprite redraw will fully overwrite given + area (and thus, the background need not be redrawn + beforehand). + */ + virtual bool isAreaUpdateOpaque( const ::basegfx::B2DRange& rUpdateArea ) const = 0; + + /** Query whether content has changed + */ + virtual bool isContentChanged() const = 0; + + /** Query position of the left, top pixel of the sprite + */ + virtual ::basegfx::B2DPoint getPosPixel() const = 0; + + /** Query size of the sprite in pixel. + */ + virtual ::basegfx::B2DVector getSizePixel() const = 0; + + /** Get area that is currently covered by the sprite + + This area is already adapted to clipping, alpha and + transformation state of this sprite. + */ + virtual ::basegfx::B2DRange getUpdateArea() const = 0; + + /** Query sprite priority + */ + virtual double getPriority() const = 0; + + protected: + ~Sprite() {} + }; + + /** Functor providing a StrictWeakOrdering for sprite references + */ + struct SpriteWeakOrder + { + bool operator()( const Sprite::Reference& rLHS, + const Sprite::Reference& rRHS ) + { + const double nPrioL( rLHS->getPriority() ); + const double nPrioR( rRHS->getPriority() ); + + // if prios are equal, tie-break on ptr value + return nPrioL == nPrioR ? rLHS.get() < rRHS.get() : nPrioL < nPrioR; + } + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/spritecanvasbase.hxx b/canvas/inc/base/spritecanvasbase.hxx new file mode 100644 index 000000000..041a6d3be --- /dev/null +++ b/canvas/inc/base/spritecanvasbase.hxx @@ -0,0 +1,190 @@ +/* -*- 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 . + */ + +#pragma once + +#include <rtl/ref.hxx> +#include <com/sun/star/rendering/InterpolationMode.hpp> +#include <base/integerbitmapbase.hxx> +#include <base/bitmapcanvasbase.hxx> +#include <spriteredrawmanager.hxx> + +namespace com::sun::star::rendering { class XAnimation; } +namespace com::sun::star::rendering { class XAnimatedSprite; } +namespace com::sun::star::rendering { class XCustomSprite; } +namespace com::sun::star::rendering { class XSprite; } + + +namespace canvas +{ + /** Helper template to handle XIntegerBitmap method forwarding to + BitmapCanvasHelper + + Use this helper to handle the XIntegerBitmap part of your + implementation. + + @tpl Base + Base class to use, most probably one of the + WeakComponentImplHelperN templates with the appropriate + interfaces. At least XSpriteCanvas and SpriteSurface should be + among them (why else would you use this template, then?). Base + class must have a Base( const Mutex& ) constructor (like the + WeakComponentImplHelperN templates have). + + @tpl CanvasHelper + Canvas helper implementation for the backend in question + + @tpl Mutex + Lock strategy to use. Defaults to using the + BaseMutex-provided lock. Every time one of the methods is + entered, an object of type Mutex is created with m_aMutex as + the sole parameter, and destroyed again when the method scope + is left. + + @tpl UnambiguousBase + Optional unambiguous base class for XInterface of Base. It's + sometimes necessary to specify this parameter, e.g. if Base + derives from multiple UNO interface (were each provides its + own version of XInterface, making the conversion ambiguous) + + @see CanvasBase for further contractual requirements towards + the CanvasHelper type, and some examples. + */ + template< class Base, + class CanvasHelper, + class Mutex=::osl::MutexGuard, + class UnambiguousBase = css::uno::XInterface > class SpriteCanvasBase : + public IntegerBitmapBase< BitmapCanvasBase<Base, CanvasHelper, Mutex, UnambiguousBase> > + { + public: + typedef IntegerBitmapBase< BitmapCanvasBase<Base, CanvasHelper, Mutex, UnambiguousBase> > BaseType; + typedef ::rtl::Reference< SpriteCanvasBase > Reference; + + SpriteCanvasBase() : + maRedrawManager() + { + } + + virtual void disposeThis() override + { + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maRedrawManager.disposing(); + + // pass on to base class + BaseType::disposeThis(); + } + + // XSpriteCanvas + virtual css::uno::Reference< css::rendering::XAnimatedSprite > SAL_CALL createSpriteFromAnimation( const css::uno::Reference< css::rendering::XAnimation >& animation ) override + { + tools::verifyArgs(animation, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maCanvasHelper.createSpriteFromAnimation(animation); + } + + virtual css::uno::Reference< css::rendering::XAnimatedSprite > SAL_CALL createSpriteFromBitmaps( const css::uno::Sequence< css::uno::Reference< css::rendering::XBitmap > >& animationBitmaps, + sal_Int8 interpolationMode ) override + { + tools::verifyArgs(animationBitmaps, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + tools::verifyRange( interpolationMode, + css::rendering::InterpolationMode::NEAREST_NEIGHBOR, + css::rendering::InterpolationMode::BEZIERSPLINE4 ); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maCanvasHelper.createSpriteFromBitmaps(animationBitmaps, interpolationMode); + } + + virtual css::uno::Reference< css::rendering::XCustomSprite > SAL_CALL createCustomSprite( const css::geometry::RealSize2D& spriteSize ) override + { + tools::verifySpriteSize(spriteSize, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maCanvasHelper.createCustomSprite(spriteSize); + } + + virtual css::uno::Reference< css::rendering::XSprite > SAL_CALL createClonedSprite( const css::uno::Reference< css::rendering::XSprite >& original ) override + { + tools::verifyArgs(original, + OSL_THIS_FUNC, + static_cast< typename BaseType::UnambiguousBaseType* >(this)); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + return BaseType::maCanvasHelper.createClonedSprite(original); + } + + // SpriteSurface + virtual void showSprite( const Sprite::Reference& rSprite ) override + { + OSL_ASSERT( rSprite.is() ); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maRedrawManager.showSprite( rSprite ); + } + + virtual void hideSprite( const Sprite::Reference& rSprite ) override + { + OSL_ASSERT( rSprite.is() ); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maRedrawManager.hideSprite( rSprite ); + } + + virtual void moveSprite( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rOldPos, + const ::basegfx::B2DPoint& rNewPos, + const ::basegfx::B2DVector& rSpriteSize ) override + { + OSL_ASSERT( rSprite.is() ); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maRedrawManager.moveSprite( rSprite, rOldPos, rNewPos, rSpriteSize ); + } + + virtual void updateSprite( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DRange& rUpdateArea ) override + { + OSL_ASSERT( rSprite.is() ); + + typename BaseType::MutexType aGuard( BaseType::m_aMutex ); + + maRedrawManager.updateSprite( rSprite, rPos, rUpdateArea ); + } + + protected: + SpriteRedrawManager maRedrawManager; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/base/spritesurface.hxx b/canvas/inc/base/spritesurface.hxx new file mode 100644 index 000000000..e49c82699 --- /dev/null +++ b/canvas/inc/base/spritesurface.hxx @@ -0,0 +1,67 @@ +/* -*- 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 . + */ + +#pragma once + +#include <base/sprite.hxx> + +namespace canvas +{ + /* Definition of the SpriteSurface interface */ + + /** Canvas surface containing sprites + + Every canvas surface that contains sprites must implement this + interface, when employing the canvas base framework. The + methods provided here are used from the individual sprites to + notify the canvas about necessary screen updates. + */ + class SpriteSurface : public css::uno::XInterface + { + public: + typedef ::rtl::Reference< SpriteSurface > Reference; + + /// Sprites should call this from XSprite::show() + virtual void showSprite( const Sprite::Reference& rSprite ) = 0; + + /// Sprites should call this from XSprite::hide() + virtual void hideSprite( const Sprite::Reference& rSprite ) = 0; + + /// Sprites should call this from XSprite::move() + virtual void moveSprite( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rOldPos, + const ::basegfx::B2DPoint& rNewPos, + const ::basegfx::B2DVector& rSpriteSize ) = 0; + + /** Sprites should call this when some part of the content has + changed. + + That includes show/hide, i.e. for show, both showSprite() + and updateSprite() must be called. + */ + virtual void updateSprite( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DRange& rUpdateArea ) = 0; + + protected: + ~SpriteSurface() {} + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/parametricpolypolygon.hxx b/canvas/inc/parametricpolypolygon.hxx new file mode 100644 index 000000000..28be8b815 --- /dev/null +++ b/canvas/inc/parametricpolypolygon.hxx @@ -0,0 +1,152 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/rendering/XParametricPolyPolygon2D.hpp> +#include <cppuhelper/compbase.hxx> +#include <cppuhelper/basemutex.hxx> +#include <basegfx/polygon/b2dpolygon.hxx> + +#include <canvas/canvastoolsdllapi.h> + +namespace com::sun::star::rendering { class XGraphicDevice; } + + +/* Definition of ParametricPolyPolygon class */ + +namespace canvas +{ + typedef cppu::WeakComponentImplHelper< css::rendering::XParametricPolyPolygon2D, + css::lang::XServiceInfo > ParametricPolyPolygon_Base; + + class CANVASTOOLS_DLLPUBLIC ParametricPolyPolygon final : public ::cppu::BaseMutex, + public ParametricPolyPolygon_Base + { + public: + enum class GradientType + { + Linear, + Elliptical, + Rectangular + }; + + /** Structure of defining values for the ParametricPolyPolygon + + This is used to copy the state of the + ParametricPolyPolygon atomically. + */ + struct Values + { + Values( const ::basegfx::B2DPolygon& rGradientPoly, + const css::uno::Sequence< css::uno::Sequence< double > >& rColors, + const css::uno::Sequence< double >& rStops, + double nAspectRatio, + GradientType eType ) : + maGradientPoly( rGradientPoly ), + mnAspectRatio( nAspectRatio ), + maColors( rColors ), + maStops( rStops ), + meType( eType ) + { + } + + /// Polygonal gradient shape (ignored for linear and axial gradient) + const ::basegfx::B2DPolygon maGradientPoly; + + /// Aspect ratio of gradient, affects scaling of innermost gradient polygon + const double mnAspectRatio; + + /// Gradient colors + const css::uno::Sequence< css::uno::Sequence< double > > maColors; + + /// Gradient color stops + const css::uno::Sequence< double > maStops; + + /// Type of gradient to render (as e.g. linear grads are not represented by maGradientPoly) + const GradientType meType; + }; + + static css::uno::Sequence< OUString > getAvailableServiceNames(); + static ParametricPolyPolygon* create( + const css::uno::Reference< css::rendering::XGraphicDevice >& rDevice, + const OUString& rServiceName, + const css::uno::Sequence< css::uno::Any >& rArgs ); + + /// Dispose all internal references + virtual void SAL_CALL disposing() override; + + // XParametricPolyPolygon2D + virtual css::uno::Reference< css::rendering::XPolyPolygon2D > SAL_CALL getOutline( double t ) override; + virtual css::uno::Sequence< double > SAL_CALL getColor( double t ) override; + virtual css::uno::Sequence< double > SAL_CALL getPointColor( const css::geometry::RealPoint2D& point ) override; + virtual css::uno::Reference< css::rendering::XColorSpace > SAL_CALL getColorSpace() override; + + // XServiceInfo + virtual OUString SAL_CALL getImplementationName( ) override; + virtual sal_Bool SAL_CALL supportsService( const OUString& ServiceName ) override; + virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames( ) override; + + /// Query all defining values of this object atomically + Values getValues() const; + + private: + virtual ~ParametricPolyPolygon() override; // we're a ref-counted UNO class. _We_ destroy ourselves. + ParametricPolyPolygon(const ParametricPolyPolygon&) = delete; + ParametricPolyPolygon& operator=( const ParametricPolyPolygon& ) = delete; + + static ParametricPolyPolygon* createLinearHorizontalGradient( const css::uno::Reference< + css::rendering::XGraphicDevice >& rDevice, + const css::uno::Sequence< css::uno::Sequence< double > >& colors, + const css::uno::Sequence< double >& stops ); + static ParametricPolyPolygon* createEllipticalGradient( const css::uno::Reference< + css::rendering::XGraphicDevice >& rDevice, + const css::uno::Sequence< css::uno::Sequence< double > >& colors, + const css::uno::Sequence< double >& stops, + double fAspect ); + static ParametricPolyPolygon* createRectangularGradient( const css::uno::Reference< + css::rendering::XGraphicDevice >& rDevice, + const css::uno::Sequence< css::uno::Sequence< double > >& colors, + const css::uno::Sequence< double >& stops, + double fAspect ); + + /// Private, because objects can only be created from the static factories + ParametricPolyPolygon( const css::uno::Reference< + css::rendering::XGraphicDevice >& rDevice, + const ::basegfx::B2DPolygon& rGradientPoly, + GradientType eType, + const css::uno::Sequence< css::uno::Sequence< double > >& colors, + const css::uno::Sequence< double >& stops, + double nAspectRatio ); + ParametricPolyPolygon( const css::uno::Reference< + css::rendering::XGraphicDevice >& rDevice, + GradientType eType, + const css::uno::Sequence< css::uno::Sequence< double > >& colors, + const css::uno::Sequence< double >& stops ); + + css::uno::Reference< + css::rendering::XGraphicDevice > mxDevice; + + /// All defining values of this object + const Values maValues; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/propertysethelper.hxx b/canvas/inc/propertysethelper.hxx new file mode 100644 index 000000000..e1a37498b --- /dev/null +++ b/canvas/inc/propertysethelper.hxx @@ -0,0 +1,143 @@ +/* -*- 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 . + */ + +#pragma once + +#include <canvas/canvastools.hxx> + +#include <functional> +#include <vector> +#include <memory> + +#include <canvas/canvastoolsdllapi.h> + +namespace com::sun::star::beans { class XPropertyChangeListener; } +namespace com::sun::star::beans { class XPropertySetInfo; } +namespace com::sun::star::beans { class XVetoableChangeListener; } + +namespace canvas +{ + /** Really simplistic XPropertySet helper for properties. + + This class provides easy access to properties, referenced via + ASCII strings. The name/property modification callbacks pairs + are passed into this class via a vector. Each time a property + is set or queried, the corresponding getter or setter callback + is called. + + Use this class as a delegate for the corresponding + XPropertySet methods, and take care of UNO XInterface and lock + handling by yourself. + + The core responsibility of this class is the name/value + mapping for property sets. + */ + class CANVASTOOLS_DLLPUBLIC PropertySetHelper + { + public: + typedef std::function<css::uno::Any ()> GetterType; + typedef std::function<void (const css::uno::Any&)> SetterType; + struct Callbacks + { + GetterType getter; + SetterType setter; + }; + typedef tools::ValueMap< Callbacks > MapType; + typedef std::vector< MapType::MapEntry > InputMap; + + class MakeMap : public InputMap + { + public: + MakeMap(const char* name, + const GetterType& getter, + const SetterType& setter) + { + MapType::MapEntry aEntry={name, {getter, setter}}; + push_back(aEntry); + } + MakeMap(const char* name, + const GetterType& getter) + { + MapType::MapEntry aEntry={name, {getter, SetterType()}}; + push_back(aEntry); + } + MakeMap& operator()(const char* name, + const GetterType& getter, + const SetterType& setter) + { + MapType::MapEntry aEntry={name, {getter, setter}}; + push_back(aEntry); + return *this; + } + MakeMap& operator()(const char* name, + const GetterType& getter) + { + MapType::MapEntry aEntry={name, {getter, SetterType()}}; + push_back(aEntry); + return *this; + } + }; + + /** Create helper with zero properties + */ + PropertySetHelper(); + + /** Init helper with new name/value map + + @param rMap + Vector of name/function pointers. Each name is offered as + a property, and reading/writing to this property is passed + on to the given function pointer. + */ + void initProperties( const InputMap& rMap ); + + /** Add given properties to helper + + @param rMap + Vector of name/function pointers. Each name is offered as + a property, and reading/writing to this property is passed + on to the given function pointer. These name/function + pairs are added to the already existing ones. + */ + void addProperties( const InputMap& rMap ); + + /** Checks whether the given string corresponds to a valid + property name. + + @return true, if the given name maps to a known property. + */ + bool isPropertyName( const OUString& aPropertyName ) const; + + // XPropertySet implementation + css::uno::Reference< css::beans::XPropertySetInfo > getPropertySetInfo() const; + void setPropertyValue( const OUString& aPropertyName, + const css::uno::Any& aValue ); + css::uno::Any getPropertyValue( const OUString& PropertyName ) const; + void addPropertyChangeListener( const OUString& aPropertyName, + const css::uno::Reference< css::beans::XPropertyChangeListener >& xListener ); + void addVetoableChangeListener( const OUString& aPropertyName, + const css::uno::Reference< css::beans::XVetoableChangeListener >& xListener ); + + private: + std::unique_ptr<MapType> mpMap; + InputMap maMapEntries; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/rendering/icolorbuffer.hxx b/canvas/inc/rendering/icolorbuffer.hxx new file mode 100644 index 000000000..7d851131e --- /dev/null +++ b/canvas/inc/rendering/icolorbuffer.hxx @@ -0,0 +1,77 @@ +/* -*- 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 . + */ + +#ifndef INCLUDED_CANVAS_RENDERING_ICOLORBUFFER_HXX +#define INCLUDED_CANVAS_RENDERING_ICOLORBUFFER_HXX + +#include <sal/types.h> + +namespace canvas +{ + /** Interface for a raw memory pixel container + + Use this interface to represent a surface of raw pixel (e.g. a + bitmap) to the canvas rendering framework. + */ + struct IColorBuffer + { + /// The underlying pixel format for this buffer + enum class Format + { + // 32-bit ARGB pixel format with alpha, 8 bits per channel. + A8R8G8B8, + + // 32-bit RGB pixel format, 8 bits per channel. + X8R8G8B8 + }; + + virtual ~IColorBuffer() {} + + /** Get a pointer to the raw memory bits of the pixel + */ + virtual sal_uInt8* lock() const = 0; + + /** unlock previous locked buffer + */ + virtual void unlock() const = 0; + + /** Get width in pixel + */ + virtual sal_uInt32 getWidth() const = 0; + + /** Get height in pixel + */ + virtual sal_uInt32 getHeight() const = 0; + + /** Offset, in bytes, between consecutive scan lines of the bitmap. + If the stride is positive, the bitmap is top-down. + If the stride is negative, the bitmap is bottom-up. + The returned value is only valid while the buffer is locked. + */ + virtual sal_uInt32 getStride() const = 0; + + /** Get format of the color buffer + */ + virtual Format getFormat() const = 0; + }; +} + +#endif // INCLUDED_CANVAS_RENDERING_ICOLORBUFFER_HXX + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/rendering/irendermodule.hxx b/canvas/inc/rendering/irendermodule.hxx new file mode 100644 index 000000000..527eedc9f --- /dev/null +++ b/canvas/inc/rendering/irendermodule.hxx @@ -0,0 +1,133 @@ +/* -*- 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 . + */ + +#pragma once + +#include <memory> + +namespace basegfx +{ + class B2IVector; +} + +namespace canvas +{ + struct ISurface; + + struct Vertex + { + float r,g,b,a; + float u,v; + float x,y,z; + }; + + /** Output module interface for backend render implementations. + + Implement this interface for each operating system- or + library-specific rendering backend, which needs coupling with + the canvas rendering framework (which can be shared between + all backend implementations). + */ + struct IRenderModule + { + /** Type of primitive passed to the render module via + pushVertex() + */ + enum class PrimitiveType + { + Unknown, + Triangle, + Quad + }; + + virtual ~IRenderModule() {} + + /// Lock rendermodule against concurrent access + virtual void lock() const = 0; + + /// Unlock rendermodule for concurrent access + virtual void unlock() const = 0; + + /** Maximal size of VRAM pages available + + This is typically the maximum texture size of the + hardware, or some arbitrary limit if the backend is + software. + */ + virtual ::basegfx::B2IVector getPageSize() = 0; + + /** Create a (possibly hardware-accelerated) surface + + @return a pointer to a surface, which is an abstraction of + a piece of (possibly hardware-accelerated) texture memory. + */ + virtual std::shared_ptr<ISurface> createSurface( const ::basegfx::B2IVector& surfaceSize ) = 0; + + /** Begin rendering the given primitive. + + Each beginPrimitive() call must be matched with an + endPrimitive() call. + */ + virtual void beginPrimitive( PrimitiveType eType ) = 0; + + /** Finish rendering a primitive. + + Each beginPrimitive() call must be matched with an + endPrimitive() call. + */ + virtual void endPrimitive() = 0; + + /** Add given vertex to current primitive + + After issuing a beginPrimitive(), each pushVertex() adds a + vertex to the active primitive. + */ + virtual void pushVertex( const Vertex& vertex ) = 0; + + /** Query error status + + @returns true, if an error occurred during primitive + construction. + */ + virtual bool isError() = 0; + }; + + /// Little RAII wrapper for guarding access to IRenderModule interface + class RenderModuleGuard + { + public: + explicit RenderModuleGuard( const std::shared_ptr<IRenderModule>& rRenderModule ) : + mpRenderModule( rRenderModule ) + { + mpRenderModule->lock(); + } + + ~RenderModuleGuard() + { + mpRenderModule->unlock(); + } + + RenderModuleGuard(const RenderModuleGuard&) = delete; + RenderModuleGuard& operator=( const RenderModuleGuard& ) = delete; + private: + const std::shared_ptr<IRenderModule> mpRenderModule; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/rendering/isurface.hxx b/canvas/inc/rendering/isurface.hxx new file mode 100644 index 000000000..f3d3beaf0 --- /dev/null +++ b/canvas/inc/rendering/isurface.hxx @@ -0,0 +1,69 @@ +/* -*- 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 . + */ + +#pragma once + +namespace basegfx +{ + class B2IRange; + class B2IPoint; +} + +namespace canvas +{ + struct IColorBuffer; + + struct ISurface + { + virtual ~ISurface() {} + + /** Select texture behind this interface to be the current one + for primitive output. + */ + virtual bool selectTexture() = 0; + + /** Tells whether the surface is valid or not + */ + virtual bool isValid() = 0; + + /** Update surface content from given IColorBuffer + + This method updates the given subarea of the surface from + the given color buffer bits. + + @param rDestPos + Position in the surface, where the subset update should + have its left, top edge + + @param rSourceRect + Size and position of the rectangular subset update in the + source color buffer + + @param rSource + Source bits to use for the update + + @return true, if the update was successful + */ + virtual bool update( const ::basegfx::B2IPoint& rDestPos, + const ::basegfx::B2IRange& rSourceRect, + IColorBuffer& rSource ) = 0; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/rendering/isurfaceproxy.hxx b/canvas/inc/rendering/isurfaceproxy.hxx new file mode 100644 index 000000000..ebe8abc10 --- /dev/null +++ b/canvas/inc/rendering/isurfaceproxy.hxx @@ -0,0 +1,98 @@ +/* -*- 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 . + */ + +#pragma once + +namespace basegfx +{ + class B2DRange; + class B2DPoint; + class B2DPolyPolygon; + class B2DHomMatrix; +} + +namespace canvas +{ + struct ISurfaceProxy + { + virtual ~ISurfaceProxy() {} + + /** Notify the proxy that the color buffer has changed + */ + virtual void setColorBufferDirty() = 0; + + /** Render the surface content to screen. + + @param fAlpha + Overall alpha for content + + @param rPos + Output position + + @param rTransform + Output transformation (does not affect output position) + */ + virtual bool draw( double fAlpha, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DHomMatrix& rTransform ) = 0; + + /** Render the surface content to screen. + + @param fAlpha + Overall alpha for content + + @param rPos + Output position + + @param rArea + Subset of the surface to render. Coordinate system are + surface area pixel, given area will be clipped to the + surface bounds. + + @param rTransform + Output transformation (does not affect output position) + */ + virtual bool draw( double fAlpha, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DRange& rArea, + const ::basegfx::B2DHomMatrix& rTransform ) = 0; + + /** Render the surface content to screen. + + @param fAlpha + Overall alpha for content + + @param rPos + Output position + + @param rClipPoly + Clip polygon for the surface. The clip polygon is also + subject to the output transformation. + + @param rTransform + Output transformation (does not affect output position) + */ + virtual bool draw( double fAlpha, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DPolyPolygon& rClipPoly, + const ::basegfx::B2DHomMatrix& rTransform ) = 0; + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/rendering/isurfaceproxymanager.hxx b/canvas/inc/rendering/isurfaceproxymanager.hxx new file mode 100644 index 000000000..71b12b29e --- /dev/null +++ b/canvas/inc/rendering/isurfaceproxymanager.hxx @@ -0,0 +1,66 @@ +/* -*- 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 . + */ + +#pragma once + +#include <canvas/canvastoolsdllapi.h> +#include <memory> + +namespace canvas +{ + struct ISurfaceProxy; + struct IColorBuffer; + struct IRenderModule; + + /** Manager interface, which handles surface proxy objects. + + Typically, each canvas instantiation has one + SurfaceProxyManager object, to handle their surfaces. Surfaces + itself are opaque objects, which encapsulate a framebuffer to + render upon, plus an optional (possibly accelerated) texture. + */ + struct ISurfaceProxyManager + { + virtual ~ISurfaceProxyManager() {} + + /** Create a surface proxy for a color buffer. + + The whole idea is build around the concept that you create + some arbitrary buffer which contains the image data and + tell the texture manager about it. From there on you can + draw into this image using any kind of graphics api you + want. In the technical sense we allocate some space in + local videomemory or AGP memory which will be filled on + demand, which means if there exists any rendering + operation that needs to read from this memory location. + This method creates a logical hardware surface object + which uses the given color buffer as the image source. + Internally this texture may even be distributed to several + real hardware surfaces. + */ + virtual std::shared_ptr< ISurfaceProxy > createSurfaceProxy( + const std::shared_ptr<IColorBuffer>& pBuffer ) const = 0; + }; + + /** Create a surface proxy for the given render module. + */ + CANVASTOOLS_DLLPUBLIC std::shared_ptr<ISurfaceProxyManager> createSurfaceProxyManager( const std::shared_ptr<IRenderModule>& rRenderModule ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/spriteredrawmanager.hxx b/canvas/inc/spriteredrawmanager.hxx new file mode 100644 index 000000000..87c692f6d --- /dev/null +++ b/canvas/inc/spriteredrawmanager.hxx @@ -0,0 +1,406 @@ +/* -*- 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 . + */ + +#pragma once + +#include <basegfx/range/b2dconnectedranges.hxx> +#include <basegfx/point/b2dpoint.hxx> +#include <basegfx/vector/b2dvector.hxx> +#include <basegfx/range/b2drange.hxx> +#include <basegfx/range/b2drectangle.hxx> + +#include <vector> +#include <algorithm> + +#include "base/sprite.hxx" +#include <canvas/canvastoolsdllapi.h> + +/* Definition of SpriteRedrawManager class */ + +namespace canvas +{ + /** This class manages smooth SpriteCanvas updates + + Use this class to handle the ::canvas::SpriteSurface methods, + that track and process sprite update events. Recorded update + events are later grouped by connected areas (i.e. all sprites + that somehow overlap over a rectangular area are grouped + together); the forEachSpriteArea() method calls the passed + functor for each of those connected areas. + + Note that, although this class generally works with IEEE + doubles, the calculation of connected areas happens in the + integer domain - it is generally expected that repaints can + only be divided at pixel boundaries, without causing visible + artifacts. Therefore, sprites that touch the same pixel (but + don't necessarily have the same floating point coordinates + there) will reside in a common sprite area and handled + together in the forEachSpriteArea functor call. + */ + class CANVASTOOLS_DLLPUBLIC SpriteRedrawManager + { + public: + /** Data container for the connected components list + */ + class SpriteInfo + { + public: + /** Create sprite info + + @param rRef + Sprite this info represents (might be the NULL ref) + + @param rTrueUpdateArea + True (un-rounded) update area this sprite has recorded + + @param bNeedsUpdate + When false, this sprite is not a member of the change + record list. Thus, it only needs redraw if within the + update area of other, changed sprites. + + @internal + */ + SpriteInfo( const Sprite::Reference& rRef, + const ::basegfx::B2DRange& rTrueUpdateArea, + bool bNeedsUpdate ) : + mpSprite( rRef ), + maTrueUpdateArea( rTrueUpdateArea ), + mbNeedsUpdate( bNeedsUpdate ), + mbIsPureMove( false ) + { + } + + /** Create sprite info, specify move type + + @param rRef + Sprite this info represents (might be the NULL ref) + + @param rTrueUpdateArea + True (un-rounded) update area this sprite has recorded + + @param bNeedsUpdate + When false, this sprite is not a member of the change + record list. Thus, it only needs redraw if within the + update area of other, changed sprites. + + @param bIsPureMove + When true, this sprite is _only_ moved, no other + changes happened. + + @internal + */ + SpriteInfo( const Sprite::Reference& rRef, + const ::basegfx::B2DRange& rTrueUpdateArea, + bool bNeedsUpdate, + bool bIsPureMove ) : + mpSprite( rRef ), + maTrueUpdateArea( rTrueUpdateArea ), + mbNeedsUpdate( bNeedsUpdate ), + mbIsPureMove( bIsPureMove ) + { + } + + const Sprite::Reference& getSprite() const { return mpSprite; } + + // #i61843# need to return by value here, to be used safely from bind + const ::basegfx::B2DRange& getUpdateArea() const { return maTrueUpdateArea; } + bool needsUpdate() const { return mbNeedsUpdate; } + bool isPureMove() const { return mbIsPureMove; } + + private: + Sprite::Reference mpSprite; + ::basegfx::B2DRange maTrueUpdateArea; + bool mbNeedsUpdate; + bool mbIsPureMove; + }; + + + /** Helper struct for SpriteTracer template + + This struct stores change information to a sprite's visual + appearance (move, content updated, and the like). + */ + struct SpriteChangeRecord + { + enum class ChangeType { move, update }; + + SpriteChangeRecord( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rOldPos, + const ::basegfx::B2DPoint& rNewPos, + const ::basegfx::B2DVector& rSpriteSize ) : + meChangeType( ChangeType::move ), + mpAffectedSprite( rSprite ), + maOldPos( rOldPos ), + maUpdateArea( rNewPos.getX(), + rNewPos.getY(), + rNewPos.getX() + rSpriteSize.getX(), + rNewPos.getY() + rSpriteSize.getY() ) + { + } + + SpriteChangeRecord( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DRange& rUpdateArea ) : + meChangeType( ChangeType::update ), + mpAffectedSprite( rSprite ), + maOldPos( rPos ), + maUpdateArea( rUpdateArea ) + { + } + + const Sprite::Reference& getSprite() const { return mpAffectedSprite; } + + ChangeType meChangeType; + Sprite::Reference mpAffectedSprite; + ::basegfx::B2DPoint maOldPos; + ::basegfx::B2DRange maUpdateArea; + }; + + typedef ::std::vector< SpriteChangeRecord > VectorOfChangeRecords; + typedef ::basegfx::B2DConnectedRanges< SpriteInfo > SpriteConnectedRanges; + typedef SpriteConnectedRanges::ComponentType AreaComponent; + typedef SpriteConnectedRanges::ConnectedComponents UpdateArea; + typedef ::std::vector< Sprite::Reference > VectorOfSprites; + + SpriteRedrawManager(); + SpriteRedrawManager(const SpriteRedrawManager&) = delete; + SpriteRedrawManager& operator=( const SpriteRedrawManager& ) = delete; + + /** Must be called when user of this object gets + disposed. Frees all internal references. + */ + void disposing(); + + /** Functor, to be used from forEachSpriteArea + */ + template< typename Functor > struct AreaUpdateCaller + { + AreaUpdateCaller( Functor& rFunc, + const SpriteRedrawManager& rManager ) : + mrFunc( rFunc ), + mrManager( rManager ) + { + } + + void operator()( const UpdateArea& rUpdateArea ) + { + mrManager.handleArea( mrFunc, rUpdateArea ); + } + + Functor& mrFunc; + const SpriteRedrawManager& mrManager; + }; + + /** Call given functor for each sprite area that needs an + update. + + This method calls the given functor for each update area + (calculated from the sprite change records). + + @tpl Functor + Must provide the following four methods: + <pre> + void backgroundPaint( ::basegfx::B2DRange aUpdateRect ); + void scrollUpdate( ::basegfx::B2DRange& o_rMoveStart, + ::basegfx::B2DRange& o_rMoveEnd, + UpdateArea aUpdateArea ); + void opaqueUpdate( const ::basegfx::B2DRange& rTotalArea, + const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites ); + void genericUpdate( const ::basegfx::B2DRange& rTotalArea, + const ::std::vector< ::canvas::Sprite::Reference >& rSortedUpdateSprites ); + </pre> + The backgroundPaint() method is called to simply repaint + background content, the scrollUpdate() method is used to + scroll a given area, and paint background in the uncovered + areas, the opaqueUpdate() method is called when a sprite + can be painted in the given area without taking background + content into account, and finally, genericUpdate() is + called for complex updates, where first the background and + then all sprites consecutively have to be repainted. + */ + template< typename Functor > void forEachSpriteArea( Functor& rFunc ) const + { + SpriteConnectedRanges aUpdateAreas; + + setupUpdateAreas( aUpdateAreas ); + + aUpdateAreas.forEachAggregate( + AreaUpdateCaller< Functor >( rFunc, *this ) ); + } + + /** Call given functor for each active sprite. + + This method calls the given functor for each active + sprite, in the order of sprite priority. + + @tpl Functor + Must provide a Functor::operator( Sprite::Reference& ) + method. + */ + template< typename Functor > void forEachSprite( const Functor& rFunc ) const + { + ::std::for_each( maSprites.begin(), + maSprites.end(), + rFunc ); + } + + /// Clear sprite change records (typically directly after a screen update) + void clearChangeRecords(); + + // SpriteSurface interface, is delegated to e.g. from SpriteCanvas + void showSprite( const Sprite::Reference& rSprite ); + void hideSprite( const Sprite::Reference& rSprite ); + void moveSprite( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rOldPos, + const ::basegfx::B2DPoint& rNewPos, + const ::basegfx::B2DVector& rSpriteSize ); + void updateSprite( const Sprite::Reference& rSprite, + const ::basegfx::B2DPoint& rPos, + const ::basegfx::B2DRange& rUpdateArea ); + + /** Internal, handles each distinct component for forEachAggregate() + + The reason why this must be public is that it needs to be + accessible from the AreaUpdateCaller functor. + + @internal + */ + template< typename Functor > void handleArea( Functor& rFunc, + const UpdateArea& rUpdateArea ) const + { + // check whether this area contains changed sprites at all + // (if not, just ignore it) + if( areSpritesChanged( rUpdateArea ) ) + { + // at least one of the sprites actually needs an + // update - process whole area. + + // check whether this area could be handled special + // (background paint, direct update, scroll, etc.) + ::basegfx::B2DRange aMoveStart; + ::basegfx::B2DRange aMoveEnd; + if( rUpdateArea.maComponentList.empty() ) + { + rFunc.backgroundPaint( rUpdateArea.maTotalBounds ); + } + else + { + // cache number of sprites in this area (it's a + // list, and both isAreaUpdateScroll() and + // isAreaUpdateOpaque() need it). + const ::std::size_t nNumSprites( + rUpdateArea.maComponentList.size() ); + + if( isAreaUpdateScroll( aMoveStart, + aMoveEnd, + rUpdateArea, + nNumSprites ) ) + { + rFunc.scrollUpdate( aMoveStart, + aMoveEnd, + rUpdateArea ); + } + else + { + // potentially, more than a single sprite + // involved. Have to sort component lists for + // sprite prio. + VectorOfSprites aSortedUpdateSprites; + for (auto const& elem : rUpdateArea.maComponentList) + { + const Sprite::Reference& rSprite( elem.second.getSprite() ); + if( rSprite.is() ) + aSortedUpdateSprites.push_back( rSprite ); + } + + ::std::sort( aSortedUpdateSprites.begin(), + aSortedUpdateSprites.end(), + SpriteWeakOrder() ); + + if( isAreaUpdateOpaque( rUpdateArea, + nNumSprites ) ) + { + rFunc.opaqueUpdate( rUpdateArea.maTotalBounds, + aSortedUpdateSprites ); + } + else + { + rFunc.genericUpdate( rUpdateArea.maTotalBounds, + aSortedUpdateSprites ); + } + } + } + } + } + + private: + /** Central method of this class. Calculates the set of + disjunct components that need an update. + */ + void setupUpdateAreas( SpriteConnectedRanges& rUpdateAreas ) const; + + bool areSpritesChanged( const UpdateArea& rUpdateArea ) const; + + bool isAreaUpdateNotOpaque( const ::basegfx::B2DRectangle& rUpdateRect, + const AreaComponent& rComponent ) const; + + bool isAreaUpdateOpaque( const UpdateArea& rUpdateArea, + ::std::size_t nNumSprites ) const; + + /** Check whether given update area can be handled by a simple + scroll + + @param o_rMoveStart + Start rect of the move + + @param o_rMoveEnd + End rect of the move. The content must be moved from start + to end rect + + @param rUpdateArea + Area to check for scroll update optimization + */ + bool isAreaUpdateScroll( ::basegfx::B2DRectangle& o_rMoveStart, + ::basegfx::B2DRectangle& o_rMoveEnd, + const UpdateArea& rUpdateArea, + ::std::size_t nNumSprites ) const; + + + VectorOfSprites maSprites; // list of active + // sprite + // objects. this + // list is only + // used for full + // repaints, + // otherwise, we + // rely on the + // active sprites + // itself to notify + // us. + + VectorOfChangeRecords maChangeRecords; // vector of + // sprites + // changes + // since last + // updateScreen() + // call + }; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/vclwrapper.hxx b/canvas/inc/vclwrapper.hxx new file mode 100644 index 000000000..a77b2757f --- /dev/null +++ b/canvas/inc/vclwrapper.hxx @@ -0,0 +1,150 @@ +/* -*- 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 . + */ + +#pragma once + +#include <vcl/svapp.hxx> + +namespace canvas +{ + namespace vcltools + { + /** This helper template wraps VCL objects, and protects + object deletion with the Solar mutex. All other operations + are unprotected, this must be handled by client code. + + The reason for this template is the fact that VCL objects + hold by value in uno::Reference-handled classes are + deleted without having the chance to get inbetween and + lock the solar mutex. + + This template handles that problem transparently, the only + inconvenience is the fact that object member access now + has to be performed via operator->, since . is not + overloadable. + + Otherwise, the template preserves the value semantics of + the wrapped object, that is, copy operations are performed + not by copying pointers, but by copying the underlying + object. This includes constness, i.e. on a const + VCLObject, only const methods of the wrapped object can be + called. Simply imagine this to be a value object of type + "template argument", with the only peculiarity that + member/method access is performed by operator-> instead of + the non-existing "operator.". + */ + template< class Wrappee_ > class VCLObject + { + public: + typedef Wrappee_ Wrappee; + + VCLObject() : + mpWrappee( new Wrappee() ) + { + } + + // no explicit here. VCLObjects should be freely + // constructible with Wrappees, and AFAIK there is no other + // implicit conversion path that could cause harm here + VCLObject( std::unique_ptr<Wrappee> pWrappee ) : + mpWrappee( pWrappee ) + { + } + + // This object has value semantics, thus, forward copy + // to wrappee + VCLObject( const VCLObject& rOrig ) + { + if( rOrig.mpWrappee ) + mpWrappee = new Wrappee( *rOrig.mpWrappee ); + else + mpWrappee = nullptr; + } + + VCLObject(VCLObject&& rOrig) noexcept + : mpWrappee(std::move(rOrig.mpWrappee)) + { + } + + // This object has value semantics, thus, forward copy + // to wrappee + VCLObject( const Wrappee& rOrig ) : + mpWrappee( new Wrappee( rOrig ) ) + { + } + + // This object has value semantics, thus, forward + // assignment to wrappee + VCLObject& operator=( const VCLObject& rhs ) + { + if (this != &rhs) + { + if( mpWrappee ) + { + if( rhs.mpWrappee ) + *mpWrappee = *rhs.mpWrappee; + } + else + { + if( rhs.mpWrappee ) + mpWrappee = new Wrappee( *rhs.mpWrappee ); + } + } + return *this; + } + + VCLObject& operator=(VCLObject&& rhs) noexcept + { + std::swap(mpWrappee, rhs.mpWrappee); + + return *this; + } + + ~VCLObject() + { + // This here is the whole purpose of the template: + // protecting object deletion with the solar mutex + SolarMutexGuard aGuard; + + mpWrappee.reset(); + } + + Wrappee* operator->() { return mpWrappee.get(); } + const Wrappee* operator->() const { return mpWrappee.get(); } + + Wrappee& operator*() { return *mpWrappee; } + const Wrappee& operator*() const { return *mpWrappee; } + + Wrappee& get() { return *mpWrappee; } + const Wrappee& get() const { return *mpWrappee; } + + void swap( VCLObject& rOther ) + { + ::std::swap( mpWrappee, rOther.mpWrappee ); + } + + private: + + std::unique_ptr<Wrappee> mpWrappee; + }; + + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/canvas/inc/verifyinput.hxx b/canvas/inc/verifyinput.hxx new file mode 100644 index 000000000..b37468ebb --- /dev/null +++ b/canvas/inc/verifyinput.hxx @@ -0,0 +1,575 @@ +/* -*- 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 . + */ + +#pragma once + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/lang/IllegalArgumentException.hpp> + +#include <canvas/canvastoolsdllapi.h> + +namespace com::sun::star::geometry +{ + struct RealPoint2D; + struct RealSize2D; + struct RealBezierSegment2D; + struct RealRectangle2D; + struct AffineMatrix2D; + struct Matrix2D; + struct IntegerPoint2D; + struct IntegerSize2D; + struct IntegerRectangle2D; +} + +namespace com::sun::star::rendering +{ + struct RenderState; + struct StrokeAttributes; + struct Texture; + struct ViewState; + struct IntegerBitmapLayout; + struct FontRequest; +} + +namespace com::sun::star::uno { template <class E> class Sequence; } + +namespace canvas +{ + namespace tools + { + + // Input checking facilities + + + // This header provides methods to check all common + // css::rendering::* method input parameters against + // compliance to the API specification. + + /** Verify that the given transformation contains valid floating point + values. + + @param rMatrix + Matrix to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::geometry::AffineMatrix2D& rMatrix, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Verify that the given transformation contains valid floating point + values. + + @param rMatrix + Matrix to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::geometry::Matrix2D& rMatrix, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Verify that the given point contains valid floating point + values. + + @param rPoint + Point to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::geometry::RealPoint2D& rPoint, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Verify that the given bezier segment contains valid + floating point values. + + @param rSegment + Segment to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::geometry::RealBezierSegment2D& rSegment, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Verify that the given rectangle contains valid floating + point values. + + @param rRect + Rect to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::geometry::RealRectangle2D& rRect, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Basic check for view state validity. + + @param viewState + Viewstate to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::rendering::ViewState& viewState, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Basic check for render state validity. + + @param renderState + Renderstate to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @param nMinColorComponents + Minimal number of color components available in + RenderState::DeviceColor + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::rendering::RenderState& renderState, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos, + sal_Int32 nMinColorComponents=0 ); + + /** Basic check for stroke attributes validity. + + @param strokeAttributes + Attributes to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::rendering::StrokeAttributes& strokeAttributes, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Basic check for texture validity. + + @param texture + Texture to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::rendering::Texture& texture, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Basic check for bitmap layout validity. + + @param bitmapLayout + Bitmap layout to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::rendering::IntegerBitmapLayout& bitmapLayout, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Basic check for font request validity. + + @param fontRequest + Font request to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + CANVASTOOLS_DLLPUBLIC void verifyInput( const css::rendering::FontRequest& fontRequest, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ); + + /** Templatized check for uno::Reference validity. + + @param rRef + Reference to check against non-NILness + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + template< class Interface > void verifyInput( + const css::uno::Reference< Interface >& rRef, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ) + { + if( !rRef.is() ) + { +#if OSL_DEBUG_LEVEL > 0 + throw css::lang::IllegalArgumentException( + OUString::createFromAscii(pStr) + ": reference is NULL", + xIf, + nArgPos ); +#else + (void)pStr; (void)xIf; (void)nArgPos; + throw css::lang::IllegalArgumentException(); +#endif + } + } + + /** Templatized check for content-of-sequence validity. + + @param rSequence + Sequence of things to check + + @param xIf + The interface that should be reported as the one + generating the exception. + + @param nArgPos + Argument position on the call site (i.e. the position of + the argument, checked here, on the UNO interface + method. Counting starts at 0). + + @throws a lang::IllegalArgumentException, if anything is wrong + */ + template< typename SequenceContent > void verifyInput( + const css::uno::Sequence< SequenceContent >& rSequence, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf, + ::sal_Int16 nArgPos ) + { + const SequenceContent* pCurr = rSequence.getConstArray(); + const SequenceContent* pEnd = pCurr + rSequence.getLength(); + while( pCurr != pEnd ) + verifyInput( *pCurr++, pStr, xIf, nArgPos ); + } + + /// Catch-all, to handle cases that DON'T need input checking (i.e. the Integer geometry ones) + template< typename T > void verifyInput( const T& /*rDummy*/, + const char* /*pStr*/, + const css::uno::Reference< css::uno::XInterface >& /*xIf*/, + ::sal_Int16 /*nArgPos*/ ) + { + } + + // TODO(Q2): Employ some template arglist magic here, to avoid + // this duplication of code... + + template< typename Arg0 > void verifyArgs( const Arg0& rArg0, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + } + + template< typename Arg0, + typename Arg1 > void verifyArgs( const Arg0& rArg0, + const Arg1& rArg1, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + verifyInput( rArg1, pStr, xIf, 1 ); + } + + template< typename Arg0, + typename Arg1, + typename Arg2 > void verifyArgs( const Arg0& rArg0, + const Arg1& rArg1, + const Arg2& rArg2, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + verifyInput( rArg1, pStr, xIf, 1 ); + verifyInput( rArg2, pStr, xIf, 2 ); + } + + template< typename Arg0, + typename Arg1, + typename Arg2, + typename Arg3 > void verifyArgs( const Arg0& rArg0, + const Arg1& rArg1, + const Arg2& rArg2, + const Arg3& rArg3, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + verifyInput( rArg1, pStr, xIf, 1 ); + verifyInput( rArg2, pStr, xIf, 2 ); + verifyInput( rArg3, pStr, xIf, 3 ); + } + + template< typename Arg0, + typename Arg1, + typename Arg2, + typename Arg3, + typename Arg4 > void verifyArgs( const Arg0& rArg0, + const Arg1& rArg1, + const Arg2& rArg2, + const Arg3& rArg3, + const Arg4& rArg4, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + verifyInput( rArg1, pStr, xIf, 1 ); + verifyInput( rArg2, pStr, xIf, 2 ); + verifyInput( rArg3, pStr, xIf, 3 ); + verifyInput( rArg4, pStr, xIf, 4 ); + } + + template< typename Arg0, + typename Arg1, + typename Arg2, + typename Arg3, + typename Arg4, + typename Arg5 > void verifyArgs( const Arg0& rArg0, + const Arg1& rArg1, + const Arg2& rArg2, + const Arg3& rArg3, + const Arg4& rArg4, + const Arg5& rArg5, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + verifyInput( rArg1, pStr, xIf, 1 ); + verifyInput( rArg2, pStr, xIf, 2 ); + verifyInput( rArg3, pStr, xIf, 3 ); + verifyInput( rArg4, pStr, xIf, 4 ); + verifyInput( rArg5, pStr, xIf, 5 ); + } + + template< typename Arg0, + typename Arg1, + typename Arg2, + typename Arg3, + typename Arg4, + typename Arg5, + typename Arg6 > void verifyArgs( const Arg0& rArg0, + const Arg1& rArg1, + const Arg2& rArg2, + const Arg3& rArg3, + const Arg4& rArg4, + const Arg5& rArg5, + const Arg6& rArg6, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ) + { + verifyInput( rArg0, pStr, xIf, 0 ); + verifyInput( rArg1, pStr, xIf, 1 ); + verifyInput( rArg2, pStr, xIf, 2 ); + verifyInput( rArg3, pStr, xIf, 3 ); + verifyInput( rArg4, pStr, xIf, 4 ); + verifyInput( rArg5, pStr, xIf, 5 ); + verifyInput( rArg6, pStr, xIf, 6 ); + } + + + /** Range checker, which throws css::lang::IllegalArgument exception, when + range is violated + */ + template< typename NumType > inline void verifyRange( NumType arg, NumType lowerBound, NumType upperBound ) + { + if( arg < lowerBound || + arg > upperBound ) + { + throw css::lang::IllegalArgumentException(); + } + } + + /** Range checker, which throws css::lang::IllegalArgument exception, when + range is violated + + The checked range is half open, i.e. only bound by the specified value. + + @param arg + Arg to check + + @param bound + Bound to check against + + @param bLowerBound + When true, given bound is the lower bound. When false, + given bound is the upper bound. + */ + template< typename NumType > inline void verifyRange( NumType arg, NumType bound, bool bLowerBound=true ) + { + if( (bLowerBound && arg < bound) || + (!bLowerBound && arg > bound) ) + { + throw css::lang::IllegalArgumentException(); + } + } + + /** Range checker, which throws css::lang::IndexOutOfBounds exception, when + index range is violated + + @param rect + Rect to verify + + @param size + Given rectangle must be within ((0,0), (size.Width, size.Height)) + */ + CANVASTOOLS_DLLPUBLIC void verifyIndexRange( const css::geometry::IntegerRectangle2D& rect, + const css::geometry::IntegerSize2D& size ); + + /** Range checker, which throws css::lang::IndexOutOfBounds exception, when + index range is violated + + @param pos + Position to verify + + @param size + Given position must be within ((0,0), (size.Width, size.Height)) + */ + CANVASTOOLS_DLLPUBLIC void verifyIndexRange( const css::geometry::IntegerPoint2D& pos, + const css::geometry::IntegerSize2D& size ); + + /** Range checker, which throws css::lang::IndexOutOfBounds exception, when + the size is negative or null + + @param size + Size to verify + */ + CANVASTOOLS_DLLPUBLIC void verifyBitmapSize( const css::geometry::IntegerSize2D& size, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ); + + /** Range checker, which throws css::lang::IndexOutOfBounds exception, when + the size is negative or null + + @param size + Size to verify + */ + CANVASTOOLS_DLLPUBLIC void verifySpriteSize( const css::geometry::RealSize2D& size, + const char* pStr, + const css::uno::Reference< css::uno::XInterface >& xIf ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |