/************************************************************** * * 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 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * *************************************************************/ #include "precompiled_sd.hxx" #include "PresenterCanvas.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using ::rtl::OUString; namespace sd { namespace presenter { //===== Service =============================================================== Reference SAL_CALL PresenterCanvas_createInstance ( const Reference& rxContext) { (void)rxContext; return Reference(static_cast(new PresenterCanvas())); } ::rtl::OUString PresenterCanvas_getImplementationName (void) throw(RuntimeException) { return OUString::createFromAscii("com.sun.star.comp.Draw.PresenterCanvasFactory"); } Sequence SAL_CALL PresenterCanvas_getSupportedServiceNames (void) throw (RuntimeException) { static const ::rtl::OUString sServiceName( ::rtl::OUString::createFromAscii("com.sun.star.rendering.Canvas")); return Sequence(&sServiceName, 1); } //===== PresenterCustomSprite ================================================= /** Wrapper around a sprite that is displayed on a PresenterCanvas. */ namespace { typedef ::cppu::WeakComponentImplHelper1 < css::rendering::XCustomSprite > PresenterCustomSpriteInterfaceBase; } class PresenterCustomSprite : private ::boost::noncopyable, protected ::cppu::BaseMutex, public PresenterCustomSpriteInterfaceBase { public: PresenterCustomSprite ( const rtl::Reference& rpCanvas, const Reference& rxSprite, const Reference& rxBaseWindow, const css::geometry::RealSize2D& rSpriteSize); virtual ~PresenterCustomSprite (void); virtual void SAL_CALL disposing (void) throw (RuntimeException); // XSprite virtual void SAL_CALL setAlpha (double nAlpha) throw (lang::IllegalArgumentException,RuntimeException); virtual void SAL_CALL move (const geometry::RealPoint2D& rNewPos, const rendering::ViewState& rViewState, const rendering::RenderState& rRenderState) throw (lang::IllegalArgumentException,RuntimeException); virtual void SAL_CALL transform (const geometry::AffineMatrix2D& rTransformation) throw (lang::IllegalArgumentException,RuntimeException); virtual void SAL_CALL clip (const Reference& rClip) throw (RuntimeException); virtual void SAL_CALL setPriority (double nPriority) throw (RuntimeException); virtual void SAL_CALL show (void) throw (RuntimeException); virtual void SAL_CALL hide (void) throw (RuntimeException); // XCustomSprite virtual Reference SAL_CALL getContentCanvas (void) throw (RuntimeException); private: rtl::Reference mpCanvas; Reference mxSprite; Reference mxBaseWindow; geometry::RealPoint2D maPosition; geometry::RealSize2D maSpriteSize; void ThrowIfDisposed (void) throw (css::lang::DisposedException); }; //===== PresenterCanvas ======================================================= PresenterCanvas::PresenterCanvas (void) : PresenterCanvasInterfaceBase(m_aMutex), mxUpdateCanvas(), mxSharedCanvas(), mxSharedWindow(), mxWindow(), maOffset(), mpUpdateRequester(), maClipRectangle(), mbOffsetUpdatePending(true) { } PresenterCanvas::PresenterCanvas ( const Reference& rxUpdateCanvas, const Reference& rxUpdateWindow, const Reference& rxSharedCanvas, const Reference& rxSharedWindow, const Reference& rxWindow) : PresenterCanvasInterfaceBase(m_aMutex), mxUpdateCanvas(rxUpdateCanvas), mxUpdateWindow(rxUpdateWindow), mxSharedCanvas(rxSharedCanvas), mxSharedWindow(rxSharedWindow), mxWindow(rxWindow), maOffset(), mpUpdateRequester(), maClipRectangle(), mbOffsetUpdatePending(true) { if (mxWindow.is()) mxWindow->addWindowListener(this); if (mxUpdateCanvas.is()) mpUpdateRequester = CanvasUpdateRequester::Instance(mxUpdateCanvas); } PresenterCanvas::~PresenterCanvas (void) { } void SAL_CALL PresenterCanvas::disposing (void) throw (css::uno::RuntimeException) { if (mxWindow.is()) mxWindow->removeWindowListener(this); } //----- XInitialization ------------------------------------------------------- void SAL_CALL PresenterCanvas::initialize ( const Sequence& rArguments) throw(Exception, RuntimeException) { if (rBHelper.bDisposed || rBHelper.bInDispose) ThrowIfDisposed(); if (rArguments.getLength() == 5) { try { // First and second argument may be NULL. rArguments[0] >>= mxUpdateCanvas; rArguments[1] >>= mxUpdateWindow; if ( ! (rArguments[2] >>= mxSharedWindow)) { throw lang::IllegalArgumentException( OUString::createFromAscii("PresenterCanvas: invalid shared window"), static_cast(this), 1); } if ( ! (rArguments[3] >>= mxSharedCanvas)) { throw lang::IllegalArgumentException( OUString::createFromAscii("PresenterCanvas: invalid shared canvas"), static_cast(this), 2); } if ( ! (rArguments[4] >>= mxWindow)) { throw lang::IllegalArgumentException( OUString::createFromAscii("PresenterCanvas: invalid window"), static_cast(this), 3); } mpUpdateRequester = CanvasUpdateRequester::Instance(mxUpdateCanvas); mbOffsetUpdatePending = true; if (mxWindow.is()) mxWindow->addWindowListener(this); } catch (RuntimeException&) { mxSharedWindow = NULL; mxWindow = NULL; throw; } } else { throw RuntimeException( OUString::createFromAscii("PresenterCanvas: invalid number of arguments"), static_cast(this)); } } //----- XCanvas --------------------------------------------------------------- void SAL_CALL PresenterCanvas::clear (void) throw (css::uno::RuntimeException) { ThrowIfDisposed(); // ToDo: Clear the area covered by the child window. A simple forward // would clear the whole shared canvas. } void SAL_CALL PresenterCanvas::drawPoint ( const css::geometry::RealPoint2D& aPoint, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); mxSharedCanvas->drawPoint(aPoint,MergeViewState(aViewState),aRenderState); } void SAL_CALL PresenterCanvas::drawLine ( const css::geometry::RealPoint2D& aStartPoint, const css::geometry::RealPoint2D& aEndPoint, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); mxSharedCanvas->drawLine(aStartPoint,aEndPoint,MergeViewState(aViewState),aRenderState); } void SAL_CALL PresenterCanvas::drawBezier ( const css::geometry::RealBezierSegment2D& aBezierSegment, const css::geometry::RealPoint2D& aEndPoint, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); mxSharedCanvas->drawBezier(aBezierSegment,aEndPoint,MergeViewState(aViewState),aRenderState); } css::uno::Reference SAL_CALL PresenterCanvas::drawPolyPolygon ( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->drawPolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState); } css::uno::Reference SAL_CALL PresenterCanvas::strokePolyPolygon ( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, const css::rendering::StrokeAttributes& aStrokeAttributes) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->strokePolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState, aStrokeAttributes); } css::uno::Reference SAL_CALL PresenterCanvas::strokeTexturedPolyPolygon ( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, const css::uno::Sequence< css::rendering::Texture >& aTextures, const css::rendering::StrokeAttributes& aStrokeAttributes) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->strokeTexturedPolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState, aTextures, aStrokeAttributes); } css::uno::Reference SAL_CALL PresenterCanvas::strokeTextureMappedPolyPolygon( const css::uno::Reference& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, const css::uno::Sequence& aTextures, const css::uno::Reference& xMapping, const css::rendering::StrokeAttributes& aStrokeAttributes) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->strokeTextureMappedPolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState, aTextures, xMapping, aStrokeAttributes); } css::uno::Reference SAL_CALL PresenterCanvas::queryStrokeShapes( const css::uno::Reference& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, const css::rendering::StrokeAttributes& aStrokeAttributes) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->queryStrokeShapes( xPolyPolygon, MergeViewState(aViewState), aRenderState, aStrokeAttributes); } css::uno::Reference SAL_CALL PresenterCanvas::fillPolyPolygon( const css::uno::Reference& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->fillPolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState); } css::uno::Reference SAL_CALL PresenterCanvas::fillTexturedPolyPolygon( const css::uno::Reference& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, const css::uno::Sequence& xTextures) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->fillTexturedPolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState, xTextures); } css::uno::Reference SAL_CALL PresenterCanvas::fillTextureMappedPolyPolygon( const css::uno::Reference< css::rendering::XPolyPolygon2D >& xPolyPolygon, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, const css::uno::Sequence< css::rendering::Texture >& xTextures, const css::uno::Reference< css::geometry::XMapping2D >& xMapping) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->fillTextureMappedPolyPolygon( xPolyPolygon, MergeViewState(aViewState), aRenderState, xTextures, xMapping); } css::uno::Reference SAL_CALL PresenterCanvas::createFont( const css::rendering::FontRequest& aFontRequest, const css::uno::Sequence< css::beans::PropertyValue >& aExtraFontProperties, const css::geometry::Matrix2D& aFontMatrix) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->createFont( aFontRequest, aExtraFontProperties, aFontMatrix); } css::uno::Sequence SAL_CALL PresenterCanvas::queryAvailableFonts( const css::rendering::FontInfo& aFilter, const css::uno::Sequence< css::beans::PropertyValue >& aFontProperties) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->queryAvailableFonts(aFilter, aFontProperties); } css::uno::Reference SAL_CALL PresenterCanvas::drawText( const css::rendering::StringContext& aText, const css::uno::Reference< css::rendering::XCanvasFont >& xFont, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState, ::sal_Int8 nTextDirection) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->drawText( aText, xFont, MergeViewState(aViewState), aRenderState, nTextDirection); } css::uno::Reference SAL_CALL PresenterCanvas::drawTextLayout( const css::uno::Reference< css::rendering::XTextLayout >& xLayoutetText, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->drawTextLayout( xLayoutetText, MergeViewState(aViewState), aRenderState); } css::uno::Reference SAL_CALL PresenterCanvas::drawBitmap( const css::uno::Reference< css::rendering::XBitmap >& xBitmap, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->drawBitmap( xBitmap, MergeViewState(aViewState), aRenderState); } css::uno::Reference SAL_CALL PresenterCanvas::drawBitmapModulated( const css::uno::Reference< css::rendering::XBitmap>& xBitmap, const css::rendering::ViewState& aViewState, const css::rendering::RenderState& aRenderState) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->drawBitmapModulated( xBitmap, MergeViewState(aViewState), aRenderState); } css::uno::Reference SAL_CALL PresenterCanvas::getDevice (void) throw (css::uno::RuntimeException) { ThrowIfDisposed(); return mxSharedCanvas->getDevice(); } //----- XBitmapCanvas --------------------------------------------------------- void SAL_CALL PresenterCanvas::copyRect( const css::uno::Reference& rxSourceCanvas, const css::geometry::RealRectangle2D& rSourceRect, const css::rendering::ViewState& rSourceViewState, const css::rendering::RenderState& rSourceRenderState, const css::geometry::RealRectangle2D& rDestRect, const css::rendering::ViewState& rDestViewState, const css::rendering::RenderState& rDestRenderState) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); Reference xBitmapCanvas (mxSharedCanvas, UNO_QUERY); if (xBitmapCanvas.is()) { rendering::ViewState aSourceViewState (rSourceViewState); if (rxSourceCanvas == Reference(this)) aSourceViewState = MergeViewState(aSourceViewState); xBitmapCanvas->copyRect( rxSourceCanvas, rSourceRect, aSourceViewState, rSourceRenderState, rDestRect, MergeViewState(rDestViewState), rDestRenderState); } } //----- XSpriteCanvas --------------------------------------------------------- Reference SAL_CALL PresenterCanvas::createSpriteFromAnimation ( const css::uno::Reference& rAnimation) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); Reference xSpriteCanvas (mxSharedCanvas, UNO_QUERY); if (xSpriteCanvas.is()) return xSpriteCanvas->createSpriteFromAnimation(rAnimation); else return NULL; } Reference SAL_CALL PresenterCanvas::createSpriteFromBitmaps ( const css::uno::Sequence< css::uno::Reference< css::rendering::XBitmap > >& rAnimationBitmaps, ::sal_Int8 nInterpolationMode) throw (css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException, css::uno::RuntimeException) { ThrowIfDisposed(); Reference xSpriteCanvas (mxSharedCanvas, UNO_QUERY); if (xSpriteCanvas.is()) return xSpriteCanvas->createSpriteFromBitmaps(rAnimationBitmaps, nInterpolationMode); else return NULL; } Reference SAL_CALL PresenterCanvas::createCustomSprite ( const css::geometry::RealSize2D& rSpriteSize) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); Reference xSpriteCanvas (mxSharedCanvas, UNO_QUERY); if (xSpriteCanvas.is()) return new PresenterCustomSprite( this, xSpriteCanvas->createCustomSprite(rSpriteSize), mxSharedWindow, rSpriteSize); else if (mxUpdateCanvas.is()) return new PresenterCustomSprite( this, mxUpdateCanvas->createCustomSprite(rSpriteSize), mxUpdateWindow, rSpriteSize); else return NULL; } Reference SAL_CALL PresenterCanvas::createClonedSprite ( const css::uno::Reference< css::rendering::XSprite >& rxOriginal) throw (css::lang::IllegalArgumentException, css::uno::RuntimeException) { ThrowIfDisposed(); Reference xSpriteCanvas (mxSharedCanvas, UNO_QUERY); if (xSpriteCanvas.is()) return xSpriteCanvas->createClonedSprite(rxOriginal); if (mxUpdateCanvas.is()) return mxUpdateCanvas->createClonedSprite(rxOriginal); return NULL; } ::sal_Bool SAL_CALL PresenterCanvas::updateScreen (::sal_Bool bUpdateAll) throw (css::uno::RuntimeException) { ThrowIfDisposed(); mbOffsetUpdatePending = true; if (mpUpdateRequester.get() != NULL) { mpUpdateRequester->RequestUpdate(bUpdateAll); return sal_True; } else { return sal_False; } } //----- XEventListener -------------------------------------------------------- void SAL_CALL PresenterCanvas::disposing (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException) { ThrowIfDisposed(); if (rEvent.Source == mxWindow) mxWindow = NULL; } //----- XWindowListener ------------------------------------------------------- void SAL_CALL PresenterCanvas::windowResized (const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); mbOffsetUpdatePending = true; } void SAL_CALL PresenterCanvas::windowMoved (const css::awt::WindowEvent& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); mbOffsetUpdatePending = true; } void SAL_CALL PresenterCanvas::windowShown (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); mbOffsetUpdatePending = true; } void SAL_CALL PresenterCanvas::windowHidden (const css::lang::EventObject& rEvent) throw (css::uno::RuntimeException) { (void)rEvent; ThrowIfDisposed(); } //----- XBitmap --------------------------------------------------------------- geometry::IntegerSize2D SAL_CALL PresenterCanvas::getSize (void) throw (RuntimeException) { ThrowIfDisposed(); if (mxWindow.is()) { const awt::Rectangle aWindowBox (mxWindow->getPosSize()); return geometry::IntegerSize2D(aWindowBox.Width, aWindowBox.Height); } else return geometry::IntegerSize2D(0,0); } sal_Bool SAL_CALL PresenterCanvas::hasAlpha (void) throw (RuntimeException) { Reference xBitmap (mxSharedCanvas, UNO_QUERY); if (xBitmap.is()) return xBitmap->hasAlpha(); else return sal_False; } Reference SAL_CALL PresenterCanvas::queryBitmapCanvas (void) throw (RuntimeException) { ThrowIfDisposed(); return this; } Reference SAL_CALL PresenterCanvas::getScaledBitmap( const css::geometry::RealSize2D& rNewSize, sal_Bool bFast) throw (css::uno::RuntimeException, css::lang::IllegalArgumentException, css::rendering::VolatileContentDestroyedException) { (void)rNewSize; (void)bFast; ThrowIfDisposed(); // Not implemented. return NULL; } //----------------------------------------------------------------------------- rendering::ViewState PresenterCanvas::MergeViewState ( const rendering::ViewState& rViewState) { // Make sure the offset is up-to-date. if (mbOffsetUpdatePending) maOffset = GetOffset(mxSharedWindow); return MergeViewState(rViewState, maOffset); } css::rendering::ViewState PresenterCanvas::MergeViewState ( const css::rendering::ViewState& rViewState, const css::awt::Point& rOffset) { // Early rejects. if ( ! mxSharedCanvas.is()) return rViewState; Reference xDevice (mxSharedCanvas->getDevice()); if ( ! xDevice.is()) return rViewState; // Create a modifiable copy of the given view state. rendering::ViewState aViewState (rViewState); // Prepare the local clip rectangle. ::basegfx::B2DRectangle aWindowRange (GetClipRectangle(aViewState.AffineTransform, rOffset)); // Adapt the offset of the view state. aViewState.AffineTransform.m02 += rOffset.X; aViewState.AffineTransform.m12 += rOffset.Y; // Adapt the clip polygon. if ( ! aViewState.Clip.is()) { // Cancel out the later multiplication with the view state // transformation. aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( xDevice, ::basegfx::B2DPolyPolygon(::basegfx::tools::createPolygonFromRect(aWindowRange))); } else { // Have to compute the intersection of the given clipping polygon in // the view state and the local clip rectangle. // Clip the view state clipping polygon against the local clip rectangle. const ::basegfx::B2DPolyPolygon aClipPolygon ( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D( aViewState.Clip)); const ::basegfx::B2DPolyPolygon aClippedClipPolygon ( ::basegfx::tools::clipPolyPolygonOnRange( aClipPolygon, aWindowRange, true, /* bInside */ false /* bStroke */)); aViewState.Clip = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( xDevice, aClippedClipPolygon); } return aViewState; } awt::Point PresenterCanvas::GetOffset (const Reference& rxBaseWindow) { mbOffsetUpdatePending = false; if (mxWindow.is() && rxBaseWindow.is()) { ::Window* pWindow = VCLUnoHelper::GetWindow(mxWindow); ::Window* pSharedWindow = VCLUnoHelper::GetWindow(rxBaseWindow); if (pWindow!=NULL && pSharedWindow!=NULL) { Rectangle aBox = pWindow->GetWindowExtentsRelative(pSharedWindow); // Calculate offset of this canvas with respect to the shared // canvas. return awt::Point(aBox.Left(), aBox.Top()); } } return awt::Point(0, 0); } ::basegfx::B2DRectangle PresenterCanvas::GetClipRectangle ( const css::geometry::AffineMatrix2D& rViewTransform, const awt::Point& rOffset) { ::basegfx::B2DRectangle aClipRectangle; ::Window* pWindow = VCLUnoHelper::GetWindow(mxWindow); if (pWindow == NULL) return ::basegfx::B2DRectangle(); ::Window* pSharedWindow = VCLUnoHelper::GetWindow(mxSharedWindow); if (pSharedWindow == NULL) return ::basegfx::B2DRectangle(); // Get the bounding box of the window and create a range in the // coordinate system of the child window. Rectangle aLocalClip; if (maClipRectangle.Width <= 0 || maClipRectangle.Height <= 0) { // No clip rectangle has been set via SetClip by the pane. // Use the window extents instead. aLocalClip = pWindow->GetWindowExtentsRelative(pSharedWindow); } else { // Use a previously given clip rectangle. aLocalClip = Rectangle( maClipRectangle.X + rOffset.X, maClipRectangle.Y + rOffset.Y, maClipRectangle.X + maClipRectangle.Width + rOffset.X, maClipRectangle.Y + maClipRectangle.Height + rOffset.Y); } // The local clip rectangle is used to clip the view state clipping // polygon. ::basegfx::B2DRectangle aWindowRectangle ( aLocalClip.Left() - rOffset.X, aLocalClip.Top() - rOffset.Y, aLocalClip.Right() - rOffset.X + 1, aLocalClip.Bottom() - rOffset.Y + 1); // Calculate the inverted view state transformation to cancel out a // later transformation of the local clip polygon with the view state // transformation. ::basegfx::B2DHomMatrix aInvertedViewStateTransformation; ::basegfx::unotools::homMatrixFromAffineMatrix( aInvertedViewStateTransformation, rViewTransform); if (aInvertedViewStateTransformation.invert()) { // Cancel out the later multiplication with the view state // transformation. aWindowRectangle.transform(aInvertedViewStateTransformation); } return aWindowRectangle; } Reference PresenterCanvas::UpdateSpriteClip ( const Reference& rxOriginalClip, const geometry::RealPoint2D& rLocation, const geometry::RealSize2D& rSize) { (void)rSize; // Check used resources and just return the original clip when not // every one of them is available. if ( ! mxWindow.is()) return rxOriginalClip; Reference xDevice (mxSharedCanvas->getDevice()); if ( ! xDevice.is()) return rxOriginalClip; // Determine the bounds of the clip rectangle (the window border) in the // coordinate system of the sprite. const awt::Rectangle aWindowBox (mxWindow->getPosSize()); const double nMinX (-rLocation.X); const double nMinY (-rLocation.Y); const double nMaxX (aWindowBox.Width-rLocation.X); const double nMaxY (aWindowBox.Height-rLocation.Y); // Create a clip polygon. Reference xPolygon; if (rxOriginalClip.is()) { // Combine the original clip with the window clip. const ::basegfx::B2DPolyPolygon aOriginalClip ( ::basegfx::unotools::b2DPolyPolygonFromXPolyPolygon2D(rxOriginalClip)); ::basegfx::B2DRectangle aWindowRange (nMinX, nMinY, nMaxX, nMaxY); const ::basegfx::B2DPolyPolygon aClippedClipPolygon ( ::basegfx::tools::clipPolyPolygonOnRange( aOriginalClip, aWindowRange, true, /* bInside */ false /* bStroke */)); xPolygon = ::basegfx::unotools::xPolyPolygonFromB2DPolyPolygon( xDevice, aClippedClipPolygon); } else { // Create a new clip polygon from the window clip rectangle. Sequence > aPoints (1); aPoints[0] = Sequence(4); aPoints[0][0] = geometry::RealPoint2D(nMinX,nMinY); aPoints[0][1] = geometry::RealPoint2D(nMaxX,nMinY); aPoints[0][2] = geometry::RealPoint2D(nMaxX,nMaxY); aPoints[0][3] = geometry::RealPoint2D(nMinX,nMaxY); Reference xLinePolygon( xDevice->createCompatibleLinePolyPolygon(aPoints)); if (xLinePolygon.is()) xLinePolygon->setClosed(0, sal_True); xPolygon = Reference(xLinePolygon, UNO_QUERY); } return xPolygon; } void PresenterCanvas::ThrowIfDisposed (void) throw (css::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose || ! mxSharedCanvas.is()) { throw lang::DisposedException ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "PresenterCanvas object has already been disposed")), static_cast(this)); } } //===== PresenterCustomSprite ================================================= PresenterCustomSprite::PresenterCustomSprite ( const rtl::Reference& rpCanvas, const Reference& rxSprite, const Reference& rxBaseWindow, const css::geometry::RealSize2D& rSpriteSize) : PresenterCustomSpriteInterfaceBase(m_aMutex), mpCanvas(rpCanvas), mxSprite(rxSprite), mxBaseWindow(rxBaseWindow), maPosition(0,0), maSpriteSize(rSpriteSize) { } PresenterCustomSprite::~PresenterCustomSprite (void) { } void SAL_CALL PresenterCustomSprite::disposing (void) throw (RuntimeException) { Reference xComponent (mxSprite, UNO_QUERY); mxSprite = NULL; if (xComponent.is()) xComponent->dispose(); mpCanvas = rtl::Reference(); } //----- XSprite --------------------------------------------------------------- void SAL_CALL PresenterCustomSprite::setAlpha (const double nAlpha) throw (lang::IllegalArgumentException,RuntimeException) { ThrowIfDisposed(); mxSprite->setAlpha(nAlpha); } void SAL_CALL PresenterCustomSprite::move ( const geometry::RealPoint2D& rNewPos, const rendering::ViewState& rViewState, const rendering::RenderState& rRenderState) throw (lang::IllegalArgumentException,RuntimeException) { ThrowIfDisposed(); maPosition = rNewPos; mxSprite->move( rNewPos, mpCanvas->MergeViewState(rViewState, mpCanvas->GetOffset(mxBaseWindow)), rRenderState); // Clip sprite against window bounds. This call is necessary because // sprite clipping is done in the corrdinate system of the sprite. // Therefore, after each change of the sprites location the window // bounds have to be transformed into the sprites coordinate system. clip(NULL); } void SAL_CALL PresenterCustomSprite::transform (const geometry::AffineMatrix2D& rTransformation) throw (lang::IllegalArgumentException,RuntimeException) { ThrowIfDisposed(); mxSprite->transform(rTransformation); } void SAL_CALL PresenterCustomSprite::clip (const Reference& rxClip) throw (RuntimeException) { ThrowIfDisposed(); // The clip region is expected in the coordinate system of the sprite. // UpdateSpriteClip() integrates the window bounds, transformed into the // sprites coordinate system, with the given clip. mxSprite->clip(mpCanvas->UpdateSpriteClip(rxClip, maPosition, maSpriteSize)); } void SAL_CALL PresenterCustomSprite::setPriority (const double nPriority) throw (RuntimeException) { ThrowIfDisposed(); mxSprite->setPriority(nPriority); } void SAL_CALL PresenterCustomSprite::show (void) throw (RuntimeException) { ThrowIfDisposed(); mxSprite->show(); } void SAL_CALL PresenterCustomSprite::hide (void) throw (RuntimeException) { ThrowIfDisposed(); mxSprite->hide(); } //----- XCustomSprite --------------------------------------------------------- Reference PresenterCustomSprite::getContentCanvas (void) throw (RuntimeException) { ThrowIfDisposed(); return mxSprite->getContentCanvas(); } //----------------------------------------------------------------------------- void PresenterCustomSprite::ThrowIfDisposed (void) throw (css::lang::DisposedException) { if (rBHelper.bDisposed || rBHelper.bInDispose || ! mxSprite.is()) { throw lang::DisposedException ( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "PresenterCustomSprite object has already been disposed")), static_cast(this)); } } } } // end of namespace ::sd::presenter