170f497fbSAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 370f497fbSAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 470f497fbSAndrew Rist * or more contributor license agreements. See the NOTICE file 570f497fbSAndrew Rist * distributed with this work for additional information 670f497fbSAndrew Rist * regarding copyright ownership. The ASF licenses this file 770f497fbSAndrew Rist * to you under the Apache License, Version 2.0 (the 870f497fbSAndrew Rist * "License"); you may not use this file except in compliance 970f497fbSAndrew Rist * with the License. You may obtain a copy of the License at 1070f497fbSAndrew Rist * 1170f497fbSAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 1270f497fbSAndrew Rist * 1370f497fbSAndrew Rist * Unless required by applicable law or agreed to in writing, 1470f497fbSAndrew Rist * software distributed under the License is distributed on an 1570f497fbSAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 1670f497fbSAndrew Rist * KIND, either express or implied. See the License for the 1770f497fbSAndrew Rist * specific language governing permissions and limitations 1870f497fbSAndrew Rist * under the License. 1970f497fbSAndrew Rist * 2070f497fbSAndrew Rist *************************************************************/ 2170f497fbSAndrew Rist 2270f497fbSAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_slideshow.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir // must be first 28cdf0e10cSrcweir #include <canvas/debug.hxx> 29cdf0e10cSrcweir #include <tools/diagnose_ex.h> 30cdf0e10cSrcweir #include <canvas/verbosetrace.hxx> 31cdf0e10cSrcweir 32cdf0e10cSrcweir #include <rtl/logfile.hxx> 33cdf0e10cSrcweir #include <osl/diagnose.hxx> 34cdf0e10cSrcweir #include <com/sun/star/awt/Rectangle.hpp> 35cdf0e10cSrcweir #include <com/sun/star/beans/XPropertySet.hpp> 36cdf0e10cSrcweir #include <com/sun/star/awt/FontWeight.hpp> 37cdf0e10cSrcweir #include <comphelper/anytostring.hxx> 38cdf0e10cSrcweir #include <cppuhelper/exc_hlp.hxx> 39cdf0e10cSrcweir 40cdf0e10cSrcweir #include <vcl/metaact.hxx> 41cdf0e10cSrcweir #include <vcl/gdimtf.hxx> 42cdf0e10cSrcweir #include <vcl/wrkwin.hxx> 43cdf0e10cSrcweir 44cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx> 45cdf0e10cSrcweir #include <basegfx/range/rangeexpander.hxx> 46cdf0e10cSrcweir 47cdf0e10cSrcweir #include <rtl/math.hxx> 48cdf0e10cSrcweir 49cdf0e10cSrcweir #include <com/sun/star/drawing/TextAnimationKind.hpp> 50cdf0e10cSrcweir 51cdf0e10cSrcweir #include <vcl/svapp.hxx> 52cdf0e10cSrcweir #include <vcl/window.hxx> 53cdf0e10cSrcweir #include <tools/stream.hxx> 54cdf0e10cSrcweir #include <com/sun/star/frame/XModel.hpp> 55cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp> 56cdf0e10cSrcweir #include <com/sun/star/datatransfer/XTransferable.hpp> 57cdf0e10cSrcweir 58cdf0e10cSrcweir #include <comphelper/scopeguard.hxx> 59cdf0e10cSrcweir #include <canvas/canvastools.hxx> 60cdf0e10cSrcweir 61cdf0e10cSrcweir #include <cmath> // for trigonometry and fabs 62cdf0e10cSrcweir #include <algorithm> 63cdf0e10cSrcweir #include <functional> 64cdf0e10cSrcweir #include <limits> 65cdf0e10cSrcweir 66cdf0e10cSrcweir #include "drawshapesubsetting.hxx" 67cdf0e10cSrcweir #include "drawshape.hxx" 68cdf0e10cSrcweir #include "eventqueue.hxx" 69cdf0e10cSrcweir #include "wakeupevent.hxx" 70cdf0e10cSrcweir #include "subsettableshapemanager.hxx" 71cdf0e10cSrcweir #include "intrinsicanimationactivity.hxx" 72cdf0e10cSrcweir #include "slideshowexceptions.hxx" 73cdf0e10cSrcweir #include "tools.hxx" 74cdf0e10cSrcweir #include "gdimtftools.hxx" 75cdf0e10cSrcweir #include "drawinglayeranimation.hxx" 76cdf0e10cSrcweir 77cdf0e10cSrcweir #include <boost/bind.hpp> 78cdf0e10cSrcweir #include <math.h> 79cdf0e10cSrcweir 80cdf0e10cSrcweir using namespace ::com::sun::star; 81cdf0e10cSrcweir 82cdf0e10cSrcweir 83cdf0e10cSrcweir namespace slideshow 84cdf0e10cSrcweir { 85cdf0e10cSrcweir namespace internal 86cdf0e10cSrcweir { 87cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 88cdf0e10cSrcweir // 89cdf0e10cSrcweir // Private methods 90cdf0e10cSrcweir // 91cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 92cdf0e10cSrcweir forceScrollTextMetaFile()93cdf0e10cSrcweir GDIMetaFileSharedPtr DrawShape::forceScrollTextMetaFile() 94cdf0e10cSrcweir { 95cdf0e10cSrcweir if ((mnCurrMtfLoadFlags & MTF_LOAD_SCROLL_TEXT_MTF) != MTF_LOAD_SCROLL_TEXT_MTF) 96cdf0e10cSrcweir { 97cdf0e10cSrcweir // reload with added flags: 98cdf0e10cSrcweir mpCurrMtf.reset( new GDIMetaFile ); 99cdf0e10cSrcweir mnCurrMtfLoadFlags |= MTF_LOAD_SCROLL_TEXT_MTF; 100*78d93489SArmin Le Grand getMetaFile( 101cdf0e10cSrcweir uno::Reference<lang::XComponent>(mxShape, uno::UNO_QUERY), 102cdf0e10cSrcweir mxPage, *mpCurrMtf, mnCurrMtfLoadFlags, 103cdf0e10cSrcweir mxComponentContext ); 104cdf0e10cSrcweir 105cdf0e10cSrcweir // TODO(F1): Currently, the scroll metafile will 106cdf0e10cSrcweir // never contain any verbose text comments. Thus, 107cdf0e10cSrcweir // can only display the full mtf content, no 108cdf0e10cSrcweir // subsets. 109cdf0e10cSrcweir maSubsetting.reset( mpCurrMtf ); 110cdf0e10cSrcweir 111cdf0e10cSrcweir // adapt maBounds. the requested scroll text metafile 112cdf0e10cSrcweir // will typically have dimension different from the 113cdf0e10cSrcweir // actual shape 114cdf0e10cSrcweir ::basegfx::B2DRectangle aScrollRect, aPaintRect; 115cdf0e10cSrcweir ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect, 116cdf0e10cSrcweir aPaintRect, 117cdf0e10cSrcweir mpCurrMtf ), 118cdf0e10cSrcweir "DrawShape::forceScrollTextMetaFile(): Could " 119cdf0e10cSrcweir "not extract scroll anim rectangles from mtf" ); 120cdf0e10cSrcweir 121cdf0e10cSrcweir // take the larger one of the two rectangles (that 122cdf0e10cSrcweir // should be the bound rect of the retrieved 123cdf0e10cSrcweir // metafile) 124cdf0e10cSrcweir if( aScrollRect.isInside( aPaintRect ) ) 125cdf0e10cSrcweir maBounds = aScrollRect; 126cdf0e10cSrcweir else 127cdf0e10cSrcweir maBounds = aPaintRect; 128cdf0e10cSrcweir } 129cdf0e10cSrcweir return mpCurrMtf; 130cdf0e10cSrcweir } 131cdf0e10cSrcweir updateStateIds() const132cdf0e10cSrcweir void DrawShape::updateStateIds() const 133cdf0e10cSrcweir { 134cdf0e10cSrcweir // Update the states, we've just redrawn or created a new 135cdf0e10cSrcweir // attribute layer. 136cdf0e10cSrcweir if( mpAttributeLayer ) 137cdf0e10cSrcweir { 138cdf0e10cSrcweir mnAttributeTransformationState = mpAttributeLayer->getTransformationState(); 139cdf0e10cSrcweir mnAttributeClipState = mpAttributeLayer->getClipState(); 140cdf0e10cSrcweir mnAttributeAlphaState = mpAttributeLayer->getAlphaState(); 141cdf0e10cSrcweir mnAttributePositionState = mpAttributeLayer->getPositionState(); 142cdf0e10cSrcweir mnAttributeContentState = mpAttributeLayer->getContentState(); 143cdf0e10cSrcweir mnAttributeVisibilityState = mpAttributeLayer->getVisibilityState(); 144cdf0e10cSrcweir } 145cdf0e10cSrcweir } 146cdf0e10cSrcweir ensureVerboseMtfComments() const147cdf0e10cSrcweir void DrawShape::ensureVerboseMtfComments() const 148cdf0e10cSrcweir { 149cdf0e10cSrcweir // TODO(F1): Text effects don't currently work for drawing 150cdf0e10cSrcweir // layer animations. 151cdf0e10cSrcweir 152cdf0e10cSrcweir // only touch mpCurrMtf, if we're not a DrawingLayer 153cdf0e10cSrcweir // animation. 154cdf0e10cSrcweir if( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) == 0 && 155cdf0e10cSrcweir maAnimationFrames.empty() ) 156cdf0e10cSrcweir { 157cdf0e10cSrcweir ENSURE_OR_THROW( !maSubsetting.hasSubsetShapes(), 158cdf0e10cSrcweir "DrawShape::ensureVerboseMtfComments(): reloading the metafile " 159cdf0e10cSrcweir "with active child subsets will wreak havoc on the view!" ); 160cdf0e10cSrcweir ENSURE_OR_THROW( maSubsetting.getSubsetNode().isEmpty(), 161cdf0e10cSrcweir "DrawShape::ensureVerboseMtfComments(): reloading the metafile " 162cdf0e10cSrcweir "for an ALREADY SUBSETTED shape is not possible!" ); 163cdf0e10cSrcweir 164cdf0e10cSrcweir // re-fetch metafile with comments 165cdf0e10cSrcweir // note that, in case of shapes without text, the new 166cdf0e10cSrcweir // metafile might still not provide any useful 167cdf0e10cSrcweir // subsetting information! 168cdf0e10cSrcweir mpCurrMtf.reset( new GDIMetaFile ); 169cdf0e10cSrcweir mnCurrMtfLoadFlags |= MTF_LOAD_VERBOSE_COMMENTS; 170*78d93489SArmin Le Grand getMetaFile( 171cdf0e10cSrcweir uno::Reference<lang::XComponent>(mxShape, uno::UNO_QUERY), 172cdf0e10cSrcweir mxPage, *mpCurrMtf, mnCurrMtfLoadFlags, 173cdf0e10cSrcweir mxComponentContext ); 174cdf0e10cSrcweir 175cdf0e10cSrcweir maSubsetting.reset( maSubsetting.getSubsetNode(), 176cdf0e10cSrcweir mpCurrMtf ); 177cdf0e10cSrcweir } 178cdf0e10cSrcweir } 179cdf0e10cSrcweir getViewRenderArgs() const180cdf0e10cSrcweir ViewShape::RenderArgs DrawShape::getViewRenderArgs() const 181cdf0e10cSrcweir { 182cdf0e10cSrcweir return ViewShape::RenderArgs( 183cdf0e10cSrcweir maBounds, 184cdf0e10cSrcweir getUpdateArea(), 185cdf0e10cSrcweir getBounds(), 186cdf0e10cSrcweir getActualUnitShapeBounds(), 187cdf0e10cSrcweir mpAttributeLayer, 188cdf0e10cSrcweir maSubsetting.getActiveSubsets(), 189cdf0e10cSrcweir mnPriority); 190cdf0e10cSrcweir } 191cdf0e10cSrcweir implRender(int nUpdateFlags) const192cdf0e10cSrcweir bool DrawShape::implRender( int nUpdateFlags ) const 193cdf0e10cSrcweir { 194cdf0e10cSrcweir RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShape::implRender()" ); 195cdf0e10cSrcweir RTL_LOGFILE_CONTEXT_TRACE1( aLog, "::presentation::internal::DrawShape: 0x%X", this ); 196cdf0e10cSrcweir 197cdf0e10cSrcweir // will perform the update now, clear update-enforcing 198cdf0e10cSrcweir // flags 199cdf0e10cSrcweir mbForceUpdate = false; 200cdf0e10cSrcweir mbAttributeLayerRevoked = false; 201cdf0e10cSrcweir 202cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE( !maViewShapes.empty(), 203cdf0e10cSrcweir "DrawShape::implRender(): render called on DrawShape without views" ); 204cdf0e10cSrcweir 205cdf0e10cSrcweir if( maBounds.isEmpty() ) 206cdf0e10cSrcweir { 207cdf0e10cSrcweir // zero-sized shapes are effectively invisible, 208cdf0e10cSrcweir // thus, we save us the rendering... 209cdf0e10cSrcweir return true; 210cdf0e10cSrcweir } 211cdf0e10cSrcweir 212cdf0e10cSrcweir // redraw all view shapes, by calling their update() method 213cdf0e10cSrcweir if( ::std::count_if( maViewShapes.begin(), 214cdf0e10cSrcweir maViewShapes.end(), 215cdf0e10cSrcweir ::boost::bind<bool>( 216cdf0e10cSrcweir ::boost::mem_fn( &ViewShape::update ), // though _theoretically_, 217cdf0e10cSrcweir // bind should eat this even 218cdf0e10cSrcweir // with _1 being a shared_ptr, 219cdf0e10cSrcweir // it does _not_ for MSVC without 220cdf0e10cSrcweir // the extra mem_fn. WTF. 221cdf0e10cSrcweir _1, 222cdf0e10cSrcweir ::boost::cref( mpCurrMtf ), 223cdf0e10cSrcweir ::boost::cref( 224cdf0e10cSrcweir getViewRenderArgs() ), 225cdf0e10cSrcweir nUpdateFlags, 226cdf0e10cSrcweir isVisible() ) ) 227cdf0e10cSrcweir != static_cast<ViewShapeVector::difference_type>(maViewShapes.size()) ) 228cdf0e10cSrcweir { 229cdf0e10cSrcweir // at least one of the ViewShape::update() calls did return 230cdf0e10cSrcweir // false - update failed on at least one ViewLayer 231cdf0e10cSrcweir return false; 232cdf0e10cSrcweir } 233cdf0e10cSrcweir 234cdf0e10cSrcweir // successfully redrawn - update state IDs to detect next changes 235cdf0e10cSrcweir updateStateIds(); 236cdf0e10cSrcweir 237cdf0e10cSrcweir return true; 238cdf0e10cSrcweir } 239cdf0e10cSrcweir getUpdateFlags() const240cdf0e10cSrcweir int DrawShape::getUpdateFlags() const 241cdf0e10cSrcweir { 242cdf0e10cSrcweir // default: update nothing, unless ShapeAttributeStack 243cdf0e10cSrcweir // tells us below, or if the attribute layer was revoked 244cdf0e10cSrcweir int nUpdateFlags(ViewShape::NONE); 245cdf0e10cSrcweir 246cdf0e10cSrcweir // possibly the whole shape content changed 247cdf0e10cSrcweir if( mbAttributeLayerRevoked ) 248cdf0e10cSrcweir nUpdateFlags = ViewShape::CONTENT; 249cdf0e10cSrcweir 250cdf0e10cSrcweir 251cdf0e10cSrcweir // determine what has to be updated 252cdf0e10cSrcweir // -------------------------------- 253cdf0e10cSrcweir 254cdf0e10cSrcweir // do we have an attribute layer? 255cdf0e10cSrcweir if( mpAttributeLayer ) 256cdf0e10cSrcweir { 257cdf0e10cSrcweir // Prevent nUpdateFlags to be modified when the shape is not 258cdf0e10cSrcweir // visible, except when it just was hidden. 259cdf0e10cSrcweir if (mpAttributeLayer->getVisibility() 260cdf0e10cSrcweir || mpAttributeLayer->getVisibilityState() != mnAttributeVisibilityState ) 261cdf0e10cSrcweir { 262cdf0e10cSrcweir if (mpAttributeLayer->getVisibilityState() != mnAttributeVisibilityState ) 263cdf0e10cSrcweir { 264cdf0e10cSrcweir // Change of the visibility state is mapped to 265cdf0e10cSrcweir // content change because when the visibility 266cdf0e10cSrcweir // changes then usually a sprite is shown or hidden 267cdf0e10cSrcweir // and the background under has to be painted once. 268cdf0e10cSrcweir nUpdateFlags |= ViewShape::CONTENT; 269cdf0e10cSrcweir } 270cdf0e10cSrcweir 271cdf0e10cSrcweir // TODO(P1): This can be done without conditional branching. 272cdf0e10cSrcweir // See HAKMEM. 273cdf0e10cSrcweir if( mpAttributeLayer->getPositionState() != mnAttributePositionState ) 274cdf0e10cSrcweir { 275cdf0e10cSrcweir nUpdateFlags |= ViewShape::POSITION; 276cdf0e10cSrcweir } 277cdf0e10cSrcweir if( mpAttributeLayer->getAlphaState() != mnAttributeAlphaState ) 278cdf0e10cSrcweir { 279cdf0e10cSrcweir nUpdateFlags |= ViewShape::ALPHA; 280cdf0e10cSrcweir } 281cdf0e10cSrcweir if( mpAttributeLayer->getClipState() != mnAttributeClipState ) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir nUpdateFlags |= ViewShape::CLIP; 284cdf0e10cSrcweir } 285cdf0e10cSrcweir if( mpAttributeLayer->getTransformationState() != mnAttributeTransformationState ) 286cdf0e10cSrcweir { 287cdf0e10cSrcweir nUpdateFlags |= ViewShape::TRANSFORMATION; 288cdf0e10cSrcweir } 289cdf0e10cSrcweir if( mpAttributeLayer->getContentState() != mnAttributeContentState ) 290cdf0e10cSrcweir { 291cdf0e10cSrcweir nUpdateFlags |= ViewShape::CONTENT; 292cdf0e10cSrcweir } 293cdf0e10cSrcweir } 294cdf0e10cSrcweir } 295cdf0e10cSrcweir 296cdf0e10cSrcweir return nUpdateFlags; 297cdf0e10cSrcweir } 298cdf0e10cSrcweir getActualUnitShapeBounds() const299cdf0e10cSrcweir ::basegfx::B2DRectangle DrawShape::getActualUnitShapeBounds() const 300cdf0e10cSrcweir { 301cdf0e10cSrcweir ENSURE_OR_THROW( !maViewShapes.empty(), 302cdf0e10cSrcweir "DrawShape::getActualUnitShapeBounds(): called on DrawShape without views" ); 303cdf0e10cSrcweir 304cdf0e10cSrcweir const VectorOfDocTreeNodes& rSubsets( 305cdf0e10cSrcweir maSubsetting.getActiveSubsets() ); 306cdf0e10cSrcweir 307cdf0e10cSrcweir const ::basegfx::B2DRectangle aDefaultBounds( 0.0,0.0,1.0,1.0 ); 308cdf0e10cSrcweir 309cdf0e10cSrcweir // perform the cheapest check first 310cdf0e10cSrcweir if( rSubsets.empty() ) 311cdf0e10cSrcweir { 312cdf0e10cSrcweir // if subset contains the whole shape, no need to call 313cdf0e10cSrcweir // the somewhat expensive bound calculation, since as 314cdf0e10cSrcweir // long as the subset is empty, this branch will be 315cdf0e10cSrcweir // taken. 316cdf0e10cSrcweir return aDefaultBounds; 317cdf0e10cSrcweir } 318cdf0e10cSrcweir else 319cdf0e10cSrcweir { 320cdf0e10cSrcweir OSL_ENSURE( rSubsets.size() != 1 || 321cdf0e10cSrcweir !rSubsets.front().isEmpty(), 322cdf0e10cSrcweir "DrawShape::getActualUnitShapeBounds() expects a " 323cdf0e10cSrcweir "_non-empty_ subset vector for a subsetted shape!" ); 324cdf0e10cSrcweir 325cdf0e10cSrcweir // are the cached bounds still valid? 326cdf0e10cSrcweir if( !maCurrentShapeUnitBounds ) 327cdf0e10cSrcweir { 328cdf0e10cSrcweir // no, (re)generate them 329cdf0e10cSrcweir // ===================== 330cdf0e10cSrcweir 331cdf0e10cSrcweir // setup cached values to defaults (might fail to 332cdf0e10cSrcweir // retrieve true bounds below) 333cdf0e10cSrcweir maCurrentShapeUnitBounds.reset( aDefaultBounds ); 334cdf0e10cSrcweir 335cdf0e10cSrcweir // TODO(P2): the subset of the master shape (that from 336cdf0e10cSrcweir // which the subsets are subtracted) changes 337cdf0e10cSrcweir // relatively often (every time a subset shape is 338cdf0e10cSrcweir // added or removed). Maybe we should exclude it here, 339cdf0e10cSrcweir // always assuming full bounds? 340cdf0e10cSrcweir 341cdf0e10cSrcweir ::cppcanvas::CanvasSharedPtr pDestinationCanvas( 342cdf0e10cSrcweir maViewShapes.front()->getViewLayer()->getCanvas() ); 343cdf0e10cSrcweir 344cdf0e10cSrcweir // TODO(Q2): Although this _is_ currently 345cdf0e10cSrcweir // view-agnostic, it might not stay like 346cdf0e10cSrcweir // that. Maybe this method should again be moved 347cdf0e10cSrcweir // to the ViewShape 348cdf0e10cSrcweir ::cppcanvas::RendererSharedPtr pRenderer( 349cdf0e10cSrcweir maViewShapes.front()->getRenderer( 350cdf0e10cSrcweir pDestinationCanvas, mpCurrMtf, mpAttributeLayer ) ); 351cdf0e10cSrcweir 352cdf0e10cSrcweir // If we cannot not prefetch, be defensive and assume 353cdf0e10cSrcweir // full shape size 354cdf0e10cSrcweir if( pRenderer ) 355cdf0e10cSrcweir { 356cdf0e10cSrcweir // temporarily, switch total transformation to identity 357cdf0e10cSrcweir // (need the bounds in the [0,1]x[0,1] unit coordinate 358cdf0e10cSrcweir // system. 359cdf0e10cSrcweir ::basegfx::B2DHomMatrix aEmptyTransformation; 360cdf0e10cSrcweir 361cdf0e10cSrcweir ::basegfx::B2DHomMatrix aOldTransform( pDestinationCanvas->getTransformation() ); 362cdf0e10cSrcweir pDestinationCanvas->setTransformation( aEmptyTransformation ); 363cdf0e10cSrcweir pRenderer->setTransformation( aEmptyTransformation ); 364cdf0e10cSrcweir 365cdf0e10cSrcweir // restore old transformation when leaving the scope 366cdf0e10cSrcweir const ::comphelper::ScopeGuard aGuard( 367cdf0e10cSrcweir boost::bind( &::cppcanvas::Canvas::setTransformation, 368cdf0e10cSrcweir pDestinationCanvas, aOldTransform ) ); 369cdf0e10cSrcweir 370cdf0e10cSrcweir 371cdf0e10cSrcweir // retrieve bounds for subset of whole metafile 372cdf0e10cSrcweir // -------------------------------------------- 373cdf0e10cSrcweir 374cdf0e10cSrcweir ::basegfx::B2DRange aTotalBounds; 375cdf0e10cSrcweir 376cdf0e10cSrcweir // cannot use ::boost::bind, ::basegfx::B2DRange::expand() 377cdf0e10cSrcweir // is overloaded. 378cdf0e10cSrcweir VectorOfDocTreeNodes::const_iterator aCurr( rSubsets.begin() ); 379cdf0e10cSrcweir const VectorOfDocTreeNodes::const_iterator aEnd( rSubsets.end() ); 380cdf0e10cSrcweir while( aCurr != aEnd ) 381cdf0e10cSrcweir { 382cdf0e10cSrcweir aTotalBounds.expand( pRenderer->getSubsetArea( 383cdf0e10cSrcweir aCurr->getStartIndex(), 384cdf0e10cSrcweir aCurr->getEndIndex() ) ); 385cdf0e10cSrcweir ++aCurr; 386cdf0e10cSrcweir } 387cdf0e10cSrcweir 388cdf0e10cSrcweir OSL_ENSURE( aTotalBounds.getMinX() >= -0.1 && 389cdf0e10cSrcweir aTotalBounds.getMinY() >= -0.1 && 390cdf0e10cSrcweir aTotalBounds.getMaxX() <= 1.1 && 391cdf0e10cSrcweir aTotalBounds.getMaxY() <= 1.1, 392cdf0e10cSrcweir "DrawShape::getActualUnitShapeBounds(): bounds noticeably larger than original shape - clipping!" ); 393cdf0e10cSrcweir 394cdf0e10cSrcweir // really make sure no shape appears larger than its 395cdf0e10cSrcweir // original bounds (there _are_ some pathologic cases, 396cdf0e10cSrcweir // especially when imported from PPT, that have 397cdf0e10cSrcweir // e.g. obscenely large polygon bounds) 398cdf0e10cSrcweir aTotalBounds.intersect( 399cdf0e10cSrcweir ::basegfx::B2DRange( 0.0, 0.0, 400cdf0e10cSrcweir 1.0, 1.0 )); 401cdf0e10cSrcweir 402cdf0e10cSrcweir maCurrentShapeUnitBounds.reset( aTotalBounds ); 403cdf0e10cSrcweir } 404cdf0e10cSrcweir } 405cdf0e10cSrcweir 406cdf0e10cSrcweir return *maCurrentShapeUnitBounds; 407cdf0e10cSrcweir } 408cdf0e10cSrcweir } 409cdf0e10cSrcweir DrawShape(const uno::Reference<drawing::XShape> & xShape,const uno::Reference<drawing::XDrawPage> & xContainingPage,double nPrio,bool bForeignSource,const SlideShowContext & rContext)410cdf0e10cSrcweir DrawShape::DrawShape( const uno::Reference< drawing::XShape >& xShape, 411cdf0e10cSrcweir const uno::Reference< drawing::XDrawPage >& xContainingPage, 412cdf0e10cSrcweir double nPrio, 413cdf0e10cSrcweir bool bForeignSource, 414cdf0e10cSrcweir const SlideShowContext& rContext ) : 415cdf0e10cSrcweir mxShape( xShape ), 416cdf0e10cSrcweir mxPage( xContainingPage ), 417cdf0e10cSrcweir maAnimationFrames(), // empty, we don't have no intrinsic animation 418cdf0e10cSrcweir mnCurrFrame(0), 419cdf0e10cSrcweir mpCurrMtf(), 420cdf0e10cSrcweir mnCurrMtfLoadFlags( bForeignSource 421cdf0e10cSrcweir ? MTF_LOAD_FOREIGN_SOURCE : MTF_LOAD_NONE ), 422cdf0e10cSrcweir maCurrentShapeUnitBounds(), 423cdf0e10cSrcweir mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ), 424cdf0e10cSrcweir maBounds( getAPIShapeBounds( xShape ) ), 425cdf0e10cSrcweir mpAttributeLayer(), 426cdf0e10cSrcweir mpIntrinsicAnimationActivity(), 427cdf0e10cSrcweir mnAttributeTransformationState(0), 428cdf0e10cSrcweir mnAttributeClipState(0), 429cdf0e10cSrcweir mnAttributeAlphaState(0), 430cdf0e10cSrcweir mnAttributePositionState(0), 431cdf0e10cSrcweir mnAttributeContentState(0), 432cdf0e10cSrcweir mnAttributeVisibilityState(0), 433cdf0e10cSrcweir maViewShapes(), 434cdf0e10cSrcweir mxComponentContext( rContext.mxComponentContext ), 435cdf0e10cSrcweir maHyperlinkIndices(), 436cdf0e10cSrcweir maHyperlinkRegions(), 437cdf0e10cSrcweir maSubsetting(), 438cdf0e10cSrcweir mnIsAnimatedCount(0), 439cdf0e10cSrcweir mnAnimationLoopCount(0), 440cdf0e10cSrcweir meCycleMode(CYCLE_LOOP), 441cdf0e10cSrcweir mbIsVisible( true ), 442cdf0e10cSrcweir mbForceUpdate( false ), 443cdf0e10cSrcweir mbAttributeLayerRevoked( false ), 444cdf0e10cSrcweir mbDrawingLayerAnim( false ) 445cdf0e10cSrcweir { 446cdf0e10cSrcweir ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" ); 447cdf0e10cSrcweir ENSURE_OR_THROW( mxPage.is(), "DrawShape::DrawShape(): Invalid containing page" ); 448cdf0e10cSrcweir 449cdf0e10cSrcweir // check for drawing layer animations: 450cdf0e10cSrcweir drawing::TextAnimationKind eKind = drawing::TextAnimationKind_NONE; 451cdf0e10cSrcweir uno::Reference<beans::XPropertySet> xPropSet( mxShape, 452cdf0e10cSrcweir uno::UNO_QUERY ); 453cdf0e10cSrcweir if( xPropSet.is() ) 454cdf0e10cSrcweir getPropertyValue( eKind, xPropSet, 455cdf0e10cSrcweir OUSTR("TextAnimationKind") ); 456cdf0e10cSrcweir mbDrawingLayerAnim = (eKind != drawing::TextAnimationKind_NONE); 457cdf0e10cSrcweir 458cdf0e10cSrcweir // must NOT be called from within initializer list, uses 459cdf0e10cSrcweir // state from mnCurrMtfLoadFlags! 460cdf0e10cSrcweir mpCurrMtf.reset( new GDIMetaFile ); 461*78d93489SArmin Le Grand getMetaFile( 462cdf0e10cSrcweir uno::Reference<lang::XComponent>(xShape, uno::UNO_QUERY), 463cdf0e10cSrcweir xContainingPage, *mpCurrMtf, mnCurrMtfLoadFlags, 464cdf0e10cSrcweir mxComponentContext ); 465cdf0e10cSrcweir ENSURE_OR_THROW( mpCurrMtf, 466cdf0e10cSrcweir "DrawShape::DrawShape(): Invalid metafile" ); 467cdf0e10cSrcweir maSubsetting.reset( mpCurrMtf ); 468cdf0e10cSrcweir 469cdf0e10cSrcweir prepareHyperlinkIndices(); 470cdf0e10cSrcweir } 471cdf0e10cSrcweir DrawShape(const uno::Reference<drawing::XShape> & xShape,const uno::Reference<drawing::XDrawPage> & xContainingPage,double nPrio,const Graphic & rGraphic,const SlideShowContext & rContext)472cdf0e10cSrcweir DrawShape::DrawShape( const uno::Reference< drawing::XShape >& xShape, 473cdf0e10cSrcweir const uno::Reference< drawing::XDrawPage >& xContainingPage, 474cdf0e10cSrcweir double nPrio, 475cdf0e10cSrcweir const Graphic& rGraphic, 476cdf0e10cSrcweir const SlideShowContext& rContext ) : 477cdf0e10cSrcweir mxShape( xShape ), 478cdf0e10cSrcweir mxPage( xContainingPage ), 479cdf0e10cSrcweir maAnimationFrames(), 480cdf0e10cSrcweir mnCurrFrame(0), 481cdf0e10cSrcweir mpCurrMtf(), 482cdf0e10cSrcweir mnCurrMtfLoadFlags( MTF_LOAD_NONE ), 483cdf0e10cSrcweir maCurrentShapeUnitBounds(), 484cdf0e10cSrcweir mnPriority( nPrio ), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ), 485cdf0e10cSrcweir maBounds( getAPIShapeBounds( xShape ) ), 486cdf0e10cSrcweir mpAttributeLayer(), 487cdf0e10cSrcweir mpIntrinsicAnimationActivity(), 488cdf0e10cSrcweir mnAttributeTransformationState(0), 489cdf0e10cSrcweir mnAttributeClipState(0), 490cdf0e10cSrcweir mnAttributeAlphaState(0), 491cdf0e10cSrcweir mnAttributePositionState(0), 492cdf0e10cSrcweir mnAttributeContentState(0), 493cdf0e10cSrcweir mnAttributeVisibilityState(0), 494cdf0e10cSrcweir maViewShapes(), 495cdf0e10cSrcweir mxComponentContext( rContext.mxComponentContext ), 496cdf0e10cSrcweir maHyperlinkIndices(), 497cdf0e10cSrcweir maHyperlinkRegions(), 498cdf0e10cSrcweir maSubsetting(), 499cdf0e10cSrcweir mnIsAnimatedCount(0), 500cdf0e10cSrcweir mnAnimationLoopCount(0), 501cdf0e10cSrcweir meCycleMode(CYCLE_LOOP), 502cdf0e10cSrcweir mbIsVisible( true ), 503cdf0e10cSrcweir mbForceUpdate( false ), 504cdf0e10cSrcweir mbAttributeLayerRevoked( false ), 505cdf0e10cSrcweir mbDrawingLayerAnim( false ) 506cdf0e10cSrcweir { 507cdf0e10cSrcweir ENSURE_OR_THROW( rGraphic.IsAnimated(), 508cdf0e10cSrcweir "DrawShape::DrawShape(): Graphic is no animation" ); 509cdf0e10cSrcweir 510cdf0e10cSrcweir getAnimationFromGraphic( maAnimationFrames, 511cdf0e10cSrcweir mnAnimationLoopCount, 512cdf0e10cSrcweir meCycleMode, 513cdf0e10cSrcweir rGraphic ); 514cdf0e10cSrcweir 515cdf0e10cSrcweir ENSURE_OR_THROW( !maAnimationFrames.empty() && 516cdf0e10cSrcweir maAnimationFrames.front().mpMtf, 517cdf0e10cSrcweir "DrawShape::DrawShape(): " ); 518cdf0e10cSrcweir mpCurrMtf = maAnimationFrames.front().mpMtf; 519cdf0e10cSrcweir 520cdf0e10cSrcweir ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" ); 521cdf0e10cSrcweir ENSURE_OR_THROW( mxPage.is(), "DrawShape::DrawShape(): Invalid containing page" ); 522cdf0e10cSrcweir ENSURE_OR_THROW( mpCurrMtf, "DrawShape::DrawShape(): Invalid metafile" ); 523cdf0e10cSrcweir } 524cdf0e10cSrcweir DrawShape(const DrawShape & rSrc,const DocTreeNode & rTreeNode,double nPrio)525cdf0e10cSrcweir DrawShape::DrawShape( const DrawShape& rSrc, 526cdf0e10cSrcweir const DocTreeNode& rTreeNode, 527cdf0e10cSrcweir double nPrio ) : 528cdf0e10cSrcweir mxShape( rSrc.mxShape ), 529cdf0e10cSrcweir mxPage( rSrc.mxPage ), 530cdf0e10cSrcweir maAnimationFrames(), // don't copy animations for subsets, 531cdf0e10cSrcweir // only the current frame! 532cdf0e10cSrcweir mnCurrFrame(0), 533cdf0e10cSrcweir mpCurrMtf( rSrc.mpCurrMtf ), 534cdf0e10cSrcweir mnCurrMtfLoadFlags( rSrc.mnCurrMtfLoadFlags ), 535cdf0e10cSrcweir maCurrentShapeUnitBounds(), 536cdf0e10cSrcweir mnPriority( nPrio ), 537cdf0e10cSrcweir maBounds( rSrc.maBounds ), 538cdf0e10cSrcweir mpAttributeLayer(), 539cdf0e10cSrcweir mpIntrinsicAnimationActivity(), 540cdf0e10cSrcweir mnAttributeTransformationState(0), 541cdf0e10cSrcweir mnAttributeClipState(0), 542cdf0e10cSrcweir mnAttributeAlphaState(0), 543cdf0e10cSrcweir mnAttributePositionState(0), 544cdf0e10cSrcweir mnAttributeContentState(0), 545cdf0e10cSrcweir mnAttributeVisibilityState(0), 546cdf0e10cSrcweir maViewShapes(), 547cdf0e10cSrcweir mxComponentContext( rSrc.mxComponentContext ), 548cdf0e10cSrcweir maHyperlinkIndices(), 549cdf0e10cSrcweir maHyperlinkRegions(), 550cdf0e10cSrcweir maSubsetting( rTreeNode, mpCurrMtf ), 551cdf0e10cSrcweir mnIsAnimatedCount(0), 552cdf0e10cSrcweir mnAnimationLoopCount(0), 553cdf0e10cSrcweir meCycleMode(CYCLE_LOOP), 554cdf0e10cSrcweir mbIsVisible( rSrc.mbIsVisible ), 555cdf0e10cSrcweir mbForceUpdate( false ), 556cdf0e10cSrcweir mbAttributeLayerRevoked( false ), 557cdf0e10cSrcweir mbDrawingLayerAnim( false ) 558cdf0e10cSrcweir { 559cdf0e10cSrcweir ENSURE_OR_THROW( mxShape.is(), "DrawShape::DrawShape(): Invalid XShape" ); 560cdf0e10cSrcweir ENSURE_OR_THROW( mpCurrMtf, "DrawShape::DrawShape(): Invalid metafile" ); 561cdf0e10cSrcweir 562cdf0e10cSrcweir // xxx todo: currently not implemented for subsetted shapes; 563cdf0e10cSrcweir // would mean modifying set of hyperlink regions when 564cdf0e10cSrcweir // subsetting text portions. N.B.: there's already an 565cdf0e10cSrcweir // issue for this #i72828# 566cdf0e10cSrcweir } 567cdf0e10cSrcweir 568cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 569cdf0e10cSrcweir // 570cdf0e10cSrcweir // Public methods 571cdf0e10cSrcweir // 572cdf0e10cSrcweir ////////////////////////////////////////////////////////////////////// 573cdf0e10cSrcweir create(const uno::Reference<drawing::XShape> & xShape,const uno::Reference<drawing::XDrawPage> & xContainingPage,double nPrio,bool bForeignSource,const SlideShowContext & rContext)574cdf0e10cSrcweir DrawShapeSharedPtr DrawShape::create( 575cdf0e10cSrcweir const uno::Reference< drawing::XShape >& xShape, 576cdf0e10cSrcweir const uno::Reference< drawing::XDrawPage >& xContainingPage, 577cdf0e10cSrcweir double nPrio, 578cdf0e10cSrcweir bool bForeignSource, 579cdf0e10cSrcweir const SlideShowContext& rContext ) 580cdf0e10cSrcweir { 581cdf0e10cSrcweir DrawShapeSharedPtr pShape( new DrawShape(xShape, 582cdf0e10cSrcweir xContainingPage, 583cdf0e10cSrcweir nPrio, 584cdf0e10cSrcweir bForeignSource, 585cdf0e10cSrcweir rContext) ); 586cdf0e10cSrcweir 587cdf0e10cSrcweir if( pShape->hasIntrinsicAnimation() ) 588cdf0e10cSrcweir { 589cdf0e10cSrcweir OSL_ASSERT( pShape->maAnimationFrames.empty() ); 590cdf0e10cSrcweir if( pShape->getNumberOfTreeNodes( 591cdf0e10cSrcweir DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH) > 0 ) 592cdf0e10cSrcweir { 593cdf0e10cSrcweir pShape->mpIntrinsicAnimationActivity = 594cdf0e10cSrcweir createDrawingLayerAnimActivity( 595cdf0e10cSrcweir rContext, 596cdf0e10cSrcweir pShape); 597cdf0e10cSrcweir } 598cdf0e10cSrcweir } 599cdf0e10cSrcweir 600cdf0e10cSrcweir if( pShape->hasHyperlinks() ) 601cdf0e10cSrcweir rContext.mpSubsettableShapeManager->addHyperlinkArea( pShape ); 602cdf0e10cSrcweir 603cdf0e10cSrcweir return pShape; 604cdf0e10cSrcweir } 605cdf0e10cSrcweir create(const uno::Reference<drawing::XShape> & xShape,const uno::Reference<drawing::XDrawPage> & xContainingPage,double nPrio,const Graphic & rGraphic,const SlideShowContext & rContext)606cdf0e10cSrcweir DrawShapeSharedPtr DrawShape::create( 607cdf0e10cSrcweir const uno::Reference< drawing::XShape >& xShape, 608cdf0e10cSrcweir const uno::Reference< drawing::XDrawPage >& xContainingPage, 609cdf0e10cSrcweir double nPrio, 610cdf0e10cSrcweir const Graphic& rGraphic, 611cdf0e10cSrcweir const SlideShowContext& rContext ) 612cdf0e10cSrcweir { 613cdf0e10cSrcweir DrawShapeSharedPtr pShape( new DrawShape(xShape, 614cdf0e10cSrcweir xContainingPage, 615cdf0e10cSrcweir nPrio, 616cdf0e10cSrcweir rGraphic, 617cdf0e10cSrcweir rContext) ); 618cdf0e10cSrcweir 619cdf0e10cSrcweir if( pShape->hasIntrinsicAnimation() ) 620cdf0e10cSrcweir { 621cdf0e10cSrcweir OSL_ASSERT( !pShape->maAnimationFrames.empty() ); 622cdf0e10cSrcweir 623cdf0e10cSrcweir std::vector<double> aTimeout; 624cdf0e10cSrcweir std::transform( 625cdf0e10cSrcweir pShape->maAnimationFrames.begin(), 626cdf0e10cSrcweir pShape->maAnimationFrames.end(), 627cdf0e10cSrcweir std::back_insert_iterator< std::vector<double> >( aTimeout ), 628cdf0e10cSrcweir boost::mem_fn(&MtfAnimationFrame::getDuration) ); 629cdf0e10cSrcweir 630cdf0e10cSrcweir WakeupEventSharedPtr pWakeupEvent( 631cdf0e10cSrcweir new WakeupEvent( rContext.mrEventQueue.getTimer(), 632cdf0e10cSrcweir rContext.mrActivitiesQueue ) ); 633cdf0e10cSrcweir 634cdf0e10cSrcweir ActivitySharedPtr pActivity = 635cdf0e10cSrcweir createIntrinsicAnimationActivity( 636cdf0e10cSrcweir rContext, 637cdf0e10cSrcweir pShape, 638cdf0e10cSrcweir pWakeupEvent, 639cdf0e10cSrcweir aTimeout, 640cdf0e10cSrcweir pShape->mnAnimationLoopCount, 641cdf0e10cSrcweir pShape->meCycleMode); 642cdf0e10cSrcweir 643cdf0e10cSrcweir pWakeupEvent->setActivity( pActivity ); 644cdf0e10cSrcweir pShape->mpIntrinsicAnimationActivity = pActivity; 645cdf0e10cSrcweir } 646cdf0e10cSrcweir 647cdf0e10cSrcweir OSL_ENSURE( !pShape->hasHyperlinks(), 648cdf0e10cSrcweir "DrawShape::create(): graphic-only shapes must not have hyperlinks!" ); 649cdf0e10cSrcweir 650cdf0e10cSrcweir return pShape; 651cdf0e10cSrcweir } 652cdf0e10cSrcweir ~DrawShape()653cdf0e10cSrcweir DrawShape::~DrawShape() 654cdf0e10cSrcweir { 655cdf0e10cSrcweir try 656cdf0e10cSrcweir { 657cdf0e10cSrcweir // dispose intrinsic animation activity, else, it will 658cdf0e10cSrcweir // linger forever 659cdf0e10cSrcweir ActivitySharedPtr pActivity( mpIntrinsicAnimationActivity.lock() ); 660cdf0e10cSrcweir if( pActivity ) 661cdf0e10cSrcweir pActivity->dispose(); 662cdf0e10cSrcweir } 663cdf0e10cSrcweir catch (uno::Exception &) 664cdf0e10cSrcweir { 665cdf0e10cSrcweir OSL_ENSURE( false, rtl::OUStringToOString( 666cdf0e10cSrcweir comphelper::anyToString( 667cdf0e10cSrcweir cppu::getCaughtException() ), 668cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 ).getStr() ); 669cdf0e10cSrcweir } 670cdf0e10cSrcweir } 671cdf0e10cSrcweir getXShape() const672cdf0e10cSrcweir uno::Reference< drawing::XShape > DrawShape::getXShape() const 673cdf0e10cSrcweir { 674cdf0e10cSrcweir return mxShape; 675cdf0e10cSrcweir } 676cdf0e10cSrcweir addViewLayer(const ViewLayerSharedPtr & rNewLayer,bool bRedrawLayer)677cdf0e10cSrcweir void DrawShape::addViewLayer( const ViewLayerSharedPtr& rNewLayer, 678cdf0e10cSrcweir bool bRedrawLayer ) 679cdf0e10cSrcweir { 680cdf0e10cSrcweir ViewShapeVector::iterator aEnd( maViewShapes.end() ); 681cdf0e10cSrcweir 682cdf0e10cSrcweir // already added? 683cdf0e10cSrcweir if( ::std::find_if( maViewShapes.begin(), 684cdf0e10cSrcweir aEnd, 685cdf0e10cSrcweir ::boost::bind<bool>( 686cdf0e10cSrcweir ::std::equal_to< ViewLayerSharedPtr >(), 687cdf0e10cSrcweir ::boost::bind( &ViewShape::getViewLayer, 688cdf0e10cSrcweir _1 ), 689cdf0e10cSrcweir ::boost::cref( rNewLayer ) ) ) != aEnd ) 690cdf0e10cSrcweir { 691cdf0e10cSrcweir // yes, nothing to do 692cdf0e10cSrcweir return; 693cdf0e10cSrcweir } 694cdf0e10cSrcweir 695cdf0e10cSrcweir ViewShapeSharedPtr pNewShape( new ViewShape( rNewLayer ) ); 696cdf0e10cSrcweir 697cdf0e10cSrcweir maViewShapes.push_back( pNewShape ); 698cdf0e10cSrcweir 699cdf0e10cSrcweir // pass on animation state 700cdf0e10cSrcweir if( mnIsAnimatedCount ) 701cdf0e10cSrcweir { 702cdf0e10cSrcweir for( int i=0; i<mnIsAnimatedCount; ++i ) 703cdf0e10cSrcweir pNewShape->enterAnimationMode(); 704cdf0e10cSrcweir } 705cdf0e10cSrcweir 706cdf0e10cSrcweir // render the Shape on the newly added ViewLayer 707cdf0e10cSrcweir if( bRedrawLayer ) 708cdf0e10cSrcweir { 709cdf0e10cSrcweir pNewShape->update( mpCurrMtf, 710cdf0e10cSrcweir getViewRenderArgs(), 711cdf0e10cSrcweir ViewShape::FORCE, 712cdf0e10cSrcweir isVisible() ); 713cdf0e10cSrcweir } 714cdf0e10cSrcweir } 715cdf0e10cSrcweir removeViewLayer(const ViewLayerSharedPtr & rLayer)716cdf0e10cSrcweir bool DrawShape::removeViewLayer( const ViewLayerSharedPtr& rLayer ) 717cdf0e10cSrcweir { 718cdf0e10cSrcweir const ViewShapeVector::iterator aEnd( maViewShapes.end() ); 719cdf0e10cSrcweir 720cdf0e10cSrcweir OSL_ENSURE( ::std::count_if(maViewShapes.begin(), 721cdf0e10cSrcweir aEnd, 722cdf0e10cSrcweir ::boost::bind<bool>( 723cdf0e10cSrcweir ::std::equal_to< ViewLayerSharedPtr >(), 724cdf0e10cSrcweir ::boost::bind( &ViewShape::getViewLayer, 725cdf0e10cSrcweir _1 ), 726cdf0e10cSrcweir ::boost::cref( rLayer ) ) ) < 2, 727cdf0e10cSrcweir "DrawShape::removeViewLayer(): Duplicate ViewLayer entries!" ); 728cdf0e10cSrcweir 729cdf0e10cSrcweir ViewShapeVector::iterator aIter; 730cdf0e10cSrcweir 731cdf0e10cSrcweir if( (aIter=::std::remove_if( maViewShapes.begin(), 732cdf0e10cSrcweir aEnd, 733cdf0e10cSrcweir ::boost::bind<bool>( 734cdf0e10cSrcweir ::std::equal_to< ViewLayerSharedPtr >(), 735cdf0e10cSrcweir ::boost::bind( &ViewShape::getViewLayer, 736cdf0e10cSrcweir _1 ), 737cdf0e10cSrcweir ::boost::cref( rLayer ) ) )) == aEnd ) 738cdf0e10cSrcweir { 739cdf0e10cSrcweir // view layer seemingly was not added, failed 740cdf0e10cSrcweir return false; 741cdf0e10cSrcweir } 742cdf0e10cSrcweir 743cdf0e10cSrcweir // actually erase from container 744cdf0e10cSrcweir maViewShapes.erase( aIter, aEnd ); 745cdf0e10cSrcweir 746cdf0e10cSrcweir return true; 747cdf0e10cSrcweir } 748cdf0e10cSrcweir clearAllViewLayers()749cdf0e10cSrcweir bool DrawShape::clearAllViewLayers() 750cdf0e10cSrcweir { 751cdf0e10cSrcweir maViewShapes.clear(); 752cdf0e10cSrcweir return true; 753cdf0e10cSrcweir } 754cdf0e10cSrcweir update() const755cdf0e10cSrcweir bool DrawShape::update() const 756cdf0e10cSrcweir { 757cdf0e10cSrcweir if( mbForceUpdate ) 758cdf0e10cSrcweir { 759cdf0e10cSrcweir return render(); 760cdf0e10cSrcweir } 761cdf0e10cSrcweir else 762cdf0e10cSrcweir { 763cdf0e10cSrcweir return implRender( getUpdateFlags() ); 764cdf0e10cSrcweir } 765cdf0e10cSrcweir } 766cdf0e10cSrcweir render() const767cdf0e10cSrcweir bool DrawShape::render() const 768cdf0e10cSrcweir { 769cdf0e10cSrcweir // force redraw. Have to also pass on the update flags, 770cdf0e10cSrcweir // because e.g. content update (regeneration of the 771cdf0e10cSrcweir // metafile renderer) is normally not performed. A simple 772cdf0e10cSrcweir // ViewShape::FORCE would only paint the metafile in its 773cdf0e10cSrcweir // old state. 774cdf0e10cSrcweir return implRender( ViewShape::FORCE | getUpdateFlags() ); 775cdf0e10cSrcweir } 776cdf0e10cSrcweir isContentChanged() const777cdf0e10cSrcweir bool DrawShape::isContentChanged() const 778cdf0e10cSrcweir { 779cdf0e10cSrcweir return mbForceUpdate ? 780cdf0e10cSrcweir true : 781cdf0e10cSrcweir getUpdateFlags() != ViewShape::NONE; 782cdf0e10cSrcweir } 783cdf0e10cSrcweir 784cdf0e10cSrcweir getBounds() const785cdf0e10cSrcweir ::basegfx::B2DRectangle DrawShape::getBounds() const 786cdf0e10cSrcweir { 787cdf0e10cSrcweir // little optimization: for non-modified shapes, we don't 788cdf0e10cSrcweir // create an ShapeAttributeStack, and therefore also don't 789cdf0e10cSrcweir // have to check it. 790cdf0e10cSrcweir return getShapePosSize( maBounds, 791cdf0e10cSrcweir mpAttributeLayer ); 792cdf0e10cSrcweir } 793cdf0e10cSrcweir getDomBounds() const794cdf0e10cSrcweir ::basegfx::B2DRectangle DrawShape::getDomBounds() const 795cdf0e10cSrcweir { 796cdf0e10cSrcweir return maBounds; 797cdf0e10cSrcweir } 798cdf0e10cSrcweir 799cdf0e10cSrcweir namespace 800cdf0e10cSrcweir { 801cdf0e10cSrcweir /** Functor expanding AA border for each passed ViewShape 802cdf0e10cSrcweir 803cdf0e10cSrcweir Could not use ::boost::bind here, since 804cdf0e10cSrcweir B2DRange::expand is overloaded (which yields one or 805cdf0e10cSrcweir the other template type deduction ambiguous) 806cdf0e10cSrcweir */ 807cdf0e10cSrcweir class Expander 808cdf0e10cSrcweir { 809cdf0e10cSrcweir public: Expander(::basegfx::B2DSize & rBounds)810cdf0e10cSrcweir Expander( ::basegfx::B2DSize& rBounds ) : 811cdf0e10cSrcweir mrBounds( rBounds ) 812cdf0e10cSrcweir { 813cdf0e10cSrcweir } 814cdf0e10cSrcweir operator ()(const ViewShapeSharedPtr & rShape) const815cdf0e10cSrcweir void operator()( const ViewShapeSharedPtr& rShape ) const 816cdf0e10cSrcweir { 817cdf0e10cSrcweir const ::basegfx::B2DSize& rShapeBorder( rShape->getAntialiasingBorder() ); 818cdf0e10cSrcweir 819cdf0e10cSrcweir mrBounds.setX( 820cdf0e10cSrcweir ::std::max( 821cdf0e10cSrcweir rShapeBorder.getX(), 822cdf0e10cSrcweir mrBounds.getX() ) ); 823cdf0e10cSrcweir mrBounds.setY( 824cdf0e10cSrcweir ::std::max( 825cdf0e10cSrcweir rShapeBorder.getY(), 826cdf0e10cSrcweir mrBounds.getY() ) ); 827cdf0e10cSrcweir } 828cdf0e10cSrcweir 829cdf0e10cSrcweir private: 830cdf0e10cSrcweir ::basegfx::B2DSize& mrBounds; 831cdf0e10cSrcweir }; 832cdf0e10cSrcweir } 833cdf0e10cSrcweir getUpdateArea() const834cdf0e10cSrcweir ::basegfx::B2DRectangle DrawShape::getUpdateArea() const 835cdf0e10cSrcweir { 836cdf0e10cSrcweir ::basegfx::B2DRectangle aBounds; 837cdf0e10cSrcweir 838cdf0e10cSrcweir // an already empty shape bound need no further 839cdf0e10cSrcweir // treatment. In fact, any changes applied below would 840cdf0e10cSrcweir // actually remove the special empty state, thus, don't 841cdf0e10cSrcweir // change! 842cdf0e10cSrcweir if( !maBounds.isEmpty() ) 843cdf0e10cSrcweir { 844cdf0e10cSrcweir basegfx::B2DRectangle aUnitBounds(0.0,0.0,1.0,1.0); 845cdf0e10cSrcweir 846cdf0e10cSrcweir if( !maViewShapes.empty() ) 847cdf0e10cSrcweir aUnitBounds = getActualUnitShapeBounds(); 848cdf0e10cSrcweir 849cdf0e10cSrcweir if( !aUnitBounds.isEmpty() ) 850cdf0e10cSrcweir { 851cdf0e10cSrcweir if( mpAttributeLayer ) 852cdf0e10cSrcweir { 853cdf0e10cSrcweir // calc actual shape area (in user coordinate 854cdf0e10cSrcweir // space) from the transformation as given by the 855cdf0e10cSrcweir // shape attribute layer 856cdf0e10cSrcweir aBounds = getShapeUpdateArea( aUnitBounds, 857cdf0e10cSrcweir getShapeTransformation( getBounds(), 858cdf0e10cSrcweir mpAttributeLayer ), 859cdf0e10cSrcweir mpAttributeLayer ); 860cdf0e10cSrcweir } 861cdf0e10cSrcweir else 862cdf0e10cSrcweir { 863cdf0e10cSrcweir // no attribute layer, thus, the true shape bounds 864cdf0e10cSrcweir // can be directly derived from the XShape bound 865cdf0e10cSrcweir // attribute 866cdf0e10cSrcweir aBounds = getShapeUpdateArea( aUnitBounds, 867cdf0e10cSrcweir maBounds ); 868cdf0e10cSrcweir } 869cdf0e10cSrcweir 870cdf0e10cSrcweir if( !maViewShapes.empty() ) 871cdf0e10cSrcweir { 872cdf0e10cSrcweir // determine border needed for antialiasing the shape 873cdf0e10cSrcweir ::basegfx::B2DSize aAABorder(0.0,0.0); 874cdf0e10cSrcweir 875cdf0e10cSrcweir // for every view, get AA border and 'expand' aAABorder 876cdf0e10cSrcweir // appropriately. 877cdf0e10cSrcweir ::std::for_each( maViewShapes.begin(), 878cdf0e10cSrcweir maViewShapes.end(), 879cdf0e10cSrcweir Expander( aAABorder ) ); 880cdf0e10cSrcweir 881cdf0e10cSrcweir // add calculated AA border to aBounds 882cdf0e10cSrcweir aBounds = ::basegfx::B2DRectangle( aBounds.getMinX() - aAABorder.getX(), 883cdf0e10cSrcweir aBounds.getMinY() - aAABorder.getY(), 884cdf0e10cSrcweir aBounds.getMaxX() + aAABorder.getX(), 885cdf0e10cSrcweir aBounds.getMaxY() + aAABorder.getY() ); 886cdf0e10cSrcweir } 887cdf0e10cSrcweir } 888cdf0e10cSrcweir } 889cdf0e10cSrcweir 890cdf0e10cSrcweir return aBounds; 891cdf0e10cSrcweir } 892cdf0e10cSrcweir isVisible() const893cdf0e10cSrcweir bool DrawShape::isVisible() const 894cdf0e10cSrcweir { 895cdf0e10cSrcweir bool bIsVisible( mbIsVisible ); 896cdf0e10cSrcweir 897cdf0e10cSrcweir if( mpAttributeLayer ) 898cdf0e10cSrcweir { 899cdf0e10cSrcweir // check whether visibility and alpha are not default 900cdf0e10cSrcweir // (mpAttributeLayer->isVisibilityValid() returns true 901cdf0e10cSrcweir // then): bVisible becomes true, if shape visibility 902cdf0e10cSrcweir // is on and alpha is not 0.0 (fully transparent) 903cdf0e10cSrcweir if( mpAttributeLayer->isVisibilityValid() ) 904cdf0e10cSrcweir bIsVisible = mpAttributeLayer->getVisibility(); 905cdf0e10cSrcweir 906cdf0e10cSrcweir // only touch bIsVisible, if the shape is still 907cdf0e10cSrcweir // visible - if getVisibility already made us 908cdf0e10cSrcweir // invisible, no alpha value will make us appear 909cdf0e10cSrcweir // again. 910cdf0e10cSrcweir if( bIsVisible && mpAttributeLayer->isAlphaValid() ) 911cdf0e10cSrcweir bIsVisible = !::basegfx::fTools::equalZero( mpAttributeLayer->getAlpha() ); 912cdf0e10cSrcweir } 913cdf0e10cSrcweir 914cdf0e10cSrcweir return bIsVisible; 915cdf0e10cSrcweir } 916cdf0e10cSrcweir getPriority() const917cdf0e10cSrcweir double DrawShape::getPriority() const 918cdf0e10cSrcweir { 919cdf0e10cSrcweir return mnPriority; 920cdf0e10cSrcweir } 921cdf0e10cSrcweir isBackgroundDetached() const922cdf0e10cSrcweir bool DrawShape::isBackgroundDetached() const 923cdf0e10cSrcweir { 924cdf0e10cSrcweir return mnIsAnimatedCount > 0; 925cdf0e10cSrcweir } 926cdf0e10cSrcweir hasIntrinsicAnimation() const927cdf0e10cSrcweir bool DrawShape::hasIntrinsicAnimation() const 928cdf0e10cSrcweir { 929cdf0e10cSrcweir return (!maAnimationFrames.empty() || mbDrawingLayerAnim); 930cdf0e10cSrcweir } 931cdf0e10cSrcweir setIntrinsicAnimationFrame(::std::size_t nCurrFrame)932cdf0e10cSrcweir bool DrawShape::setIntrinsicAnimationFrame( ::std::size_t nCurrFrame ) 933cdf0e10cSrcweir { 934cdf0e10cSrcweir ENSURE_OR_RETURN_FALSE( nCurrFrame < maAnimationFrames.size(), 935cdf0e10cSrcweir "DrawShape::setIntrinsicAnimationFrame(): frame index out of bounds" ); 936cdf0e10cSrcweir 937cdf0e10cSrcweir if( mnCurrFrame != nCurrFrame ) 938cdf0e10cSrcweir { 939cdf0e10cSrcweir mnCurrFrame = nCurrFrame; 940cdf0e10cSrcweir mpCurrMtf = maAnimationFrames[ mnCurrFrame ].mpMtf; 941cdf0e10cSrcweir mbForceUpdate = true; 942cdf0e10cSrcweir } 943cdf0e10cSrcweir 944cdf0e10cSrcweir return true; 945cdf0e10cSrcweir } 946cdf0e10cSrcweir 947cdf0e10cSrcweir // hyperlink support prepareHyperlinkIndices() const948cdf0e10cSrcweir void DrawShape::prepareHyperlinkIndices() const 949cdf0e10cSrcweir { 950cdf0e10cSrcweir if ( !maHyperlinkIndices.empty()) 951cdf0e10cSrcweir { 952cdf0e10cSrcweir maHyperlinkIndices.clear(); 953cdf0e10cSrcweir maHyperlinkRegions.clear(); 954cdf0e10cSrcweir } 955cdf0e10cSrcweir 956cdf0e10cSrcweir sal_Int32 nIndex = 0; 957cdf0e10cSrcweir for ( MetaAction * pCurrAct = mpCurrMtf->FirstAction(); 958cdf0e10cSrcweir pCurrAct != 0; pCurrAct = mpCurrMtf->NextAction() ) 959cdf0e10cSrcweir { 960cdf0e10cSrcweir if (pCurrAct->GetType() == META_COMMENT_ACTION) { 961cdf0e10cSrcweir MetaCommentAction * pAct = 962cdf0e10cSrcweir static_cast<MetaCommentAction *>(pCurrAct); 963cdf0e10cSrcweir // skip comment if not a special XTEXT comment 964cdf0e10cSrcweir if (pAct->GetComment().CompareIgnoreCaseToAscii( 965cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_BEGIN") ) == 966cdf0e10cSrcweir COMPARE_EQUAL && 967cdf0e10cSrcweir // e.g. date field doesn't have data! 968cdf0e10cSrcweir // currently assuming that only url field, this is 969cdf0e10cSrcweir // somehow fragile! xxx todo if possible 970cdf0e10cSrcweir pAct->GetData() != 0 && 971cdf0e10cSrcweir pAct->GetDataSize() > 0) 972cdf0e10cSrcweir { 973cdf0e10cSrcweir if (!maHyperlinkIndices.empty() && 974cdf0e10cSrcweir maHyperlinkIndices.back().second == -1) { 975cdf0e10cSrcweir OSL_ENSURE( false, "### pending FIELD_SEQ_END!" ); 976cdf0e10cSrcweir maHyperlinkIndices.pop_back(); 977cdf0e10cSrcweir maHyperlinkRegions.pop_back(); 978cdf0e10cSrcweir } 979cdf0e10cSrcweir maHyperlinkIndices.push_back( 980cdf0e10cSrcweir HyperlinkIndexPair( nIndex + 1, 981cdf0e10cSrcweir -1 /* to be filled below */ ) ); 982cdf0e10cSrcweir maHyperlinkRegions.push_back( 983cdf0e10cSrcweir HyperlinkRegion( 984cdf0e10cSrcweir basegfx::B2DRectangle(), 985cdf0e10cSrcweir rtl::OUString( 986cdf0e10cSrcweir reinterpret_cast<sal_Unicode const*>( 987cdf0e10cSrcweir pAct->GetData()), 988cdf0e10cSrcweir pAct->GetDataSize() / sizeof(sal_Unicode) ) 989cdf0e10cSrcweir ) ); 990cdf0e10cSrcweir } 991cdf0e10cSrcweir else if (pAct->GetComment().CompareIgnoreCaseToAscii( 992cdf0e10cSrcweir RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_END")) == 993cdf0e10cSrcweir COMPARE_EQUAL && 994cdf0e10cSrcweir // pending end is expected: 995cdf0e10cSrcweir !maHyperlinkIndices.empty() && 996cdf0e10cSrcweir maHyperlinkIndices.back().second == -1) 997cdf0e10cSrcweir { 998cdf0e10cSrcweir maHyperlinkIndices.back().second = nIndex; 999cdf0e10cSrcweir } 1000cdf0e10cSrcweir ++nIndex; 1001cdf0e10cSrcweir } 1002cdf0e10cSrcweir else 1003cdf0e10cSrcweir nIndex += getNextActionOffset(pCurrAct); 1004cdf0e10cSrcweir } 1005cdf0e10cSrcweir if (!maHyperlinkIndices.empty() && 1006cdf0e10cSrcweir maHyperlinkIndices.back().second == -1) { 1007cdf0e10cSrcweir OSL_ENSURE( false, "### pending FIELD_SEQ_END!" ); 1008cdf0e10cSrcweir maHyperlinkIndices.pop_back(); 1009cdf0e10cSrcweir maHyperlinkRegions.pop_back(); 1010cdf0e10cSrcweir } 1011cdf0e10cSrcweir OSL_ASSERT( maHyperlinkIndices.size() == maHyperlinkRegions.size()); 1012cdf0e10cSrcweir } 1013cdf0e10cSrcweir hasHyperlinks() const1014cdf0e10cSrcweir bool DrawShape::hasHyperlinks() const 1015cdf0e10cSrcweir { 1016cdf0e10cSrcweir return ! maHyperlinkRegions.empty(); 1017cdf0e10cSrcweir } 1018cdf0e10cSrcweir getHyperlinkRegions() const1019cdf0e10cSrcweir HyperlinkArea::HyperlinkRegions DrawShape::getHyperlinkRegions() const 1020cdf0e10cSrcweir { 1021cdf0e10cSrcweir OSL_ASSERT( !maViewShapes.empty() ); 1022cdf0e10cSrcweir 1023cdf0e10cSrcweir if( !isVisible() ) 1024cdf0e10cSrcweir return HyperlinkArea::HyperlinkRegions(); 1025cdf0e10cSrcweir 1026cdf0e10cSrcweir // late init, determine regions: 1027cdf0e10cSrcweir if( !maHyperlinkRegions.empty() && 1028cdf0e10cSrcweir !maViewShapes.empty() && 1029cdf0e10cSrcweir // region already inited? 1030cdf0e10cSrcweir maHyperlinkRegions.front().first.getWidth() == 0 && 1031cdf0e10cSrcweir maHyperlinkRegions.front().first.getHeight() == 0 && 1032cdf0e10cSrcweir maHyperlinkRegions.size() == maHyperlinkIndices.size() ) 1033cdf0e10cSrcweir { 1034cdf0e10cSrcweir // TODO(Q2): Although this _is_ currently 1035cdf0e10cSrcweir // view-agnostic, it might not stay like that. 1036cdf0e10cSrcweir ViewShapeSharedPtr const& pViewShape = maViewShapes.front(); 1037cdf0e10cSrcweir cppcanvas::CanvasSharedPtr const pCanvas( 1038cdf0e10cSrcweir pViewShape->getViewLayer()->getCanvas() ); 1039cdf0e10cSrcweir 1040cdf0e10cSrcweir // reuse Renderer of first view shape: 1041cdf0e10cSrcweir cppcanvas::RendererSharedPtr const pRenderer( 1042cdf0e10cSrcweir pViewShape->getRenderer( 1043cdf0e10cSrcweir pCanvas, mpCurrMtf, mpAttributeLayer ) ); 1044cdf0e10cSrcweir 1045cdf0e10cSrcweir OSL_ASSERT( pRenderer ); 1046cdf0e10cSrcweir 1047cdf0e10cSrcweir if (pRenderer) 1048cdf0e10cSrcweir { 1049cdf0e10cSrcweir basegfx::B2DHomMatrix const aOldTransform( 1050cdf0e10cSrcweir pCanvas->getTransformation() ); 1051cdf0e10cSrcweir basegfx::B2DHomMatrix aTransform; 1052cdf0e10cSrcweir pCanvas->setTransformation( aTransform /* empty */ ); 1053cdf0e10cSrcweir 1054cdf0e10cSrcweir comphelper::ScopeGuard const resetOldTransformation( 1055cdf0e10cSrcweir boost::bind( &cppcanvas::Canvas::setTransformation, 1056cdf0e10cSrcweir pCanvas.get(), 1057cdf0e10cSrcweir boost::cref(aOldTransform) )); 1058cdf0e10cSrcweir 1059cdf0e10cSrcweir aTransform.scale( maBounds.getWidth(), 1060cdf0e10cSrcweir maBounds.getHeight() ); 1061cdf0e10cSrcweir pRenderer->setTransformation( aTransform ); 1062cdf0e10cSrcweir pRenderer->setClip(); 1063cdf0e10cSrcweir 1064cdf0e10cSrcweir for( std::size_t pos = maHyperlinkRegions.size(); pos--; ) 1065cdf0e10cSrcweir { 1066cdf0e10cSrcweir // get region: 1067cdf0e10cSrcweir HyperlinkIndexPair const& rIndices = maHyperlinkIndices[pos]; 1068cdf0e10cSrcweir basegfx::B2DRectangle const region( 1069cdf0e10cSrcweir pRenderer->getSubsetArea( rIndices.first, 1070cdf0e10cSrcweir rIndices.second )); 1071cdf0e10cSrcweir maHyperlinkRegions[pos].first = region; 1072cdf0e10cSrcweir } 1073cdf0e10cSrcweir } 1074cdf0e10cSrcweir } 1075cdf0e10cSrcweir 1076cdf0e10cSrcweir // shift shape-relative hyperlink regions to 1077cdf0e10cSrcweir // slide-absolute position 1078cdf0e10cSrcweir 1079cdf0e10cSrcweir HyperlinkRegions aTranslatedRegions; 1080cdf0e10cSrcweir const basegfx::B2DPoint& rOffset(getBounds().getMinimum()); 1081cdf0e10cSrcweir HyperlinkRegions::const_iterator aIter( maHyperlinkRegions.begin() ); 1082cdf0e10cSrcweir HyperlinkRegions::const_iterator const aEnd ( maHyperlinkRegions.end() ); 1083cdf0e10cSrcweir while( aIter != aEnd ) 1084cdf0e10cSrcweir { 1085cdf0e10cSrcweir basegfx::B2DRange const& relRegion( aIter->first ); 1086cdf0e10cSrcweir aTranslatedRegions.push_back( 1087cdf0e10cSrcweir std::make_pair( 1088cdf0e10cSrcweir basegfx::B2DRange( 1089cdf0e10cSrcweir relRegion.getMinimum() + rOffset, 1090cdf0e10cSrcweir relRegion.getMaximum() + rOffset), 1091cdf0e10cSrcweir aIter->second) ); 1092cdf0e10cSrcweir ++aIter; 1093cdf0e10cSrcweir } 1094cdf0e10cSrcweir 1095cdf0e10cSrcweir return aTranslatedRegions; 1096cdf0e10cSrcweir } 1097cdf0e10cSrcweir getHyperlinkPriority() const1098cdf0e10cSrcweir double DrawShape::getHyperlinkPriority() const 1099cdf0e10cSrcweir { 1100cdf0e10cSrcweir return getPriority(); 1101cdf0e10cSrcweir } 1102cdf0e10cSrcweir 1103cdf0e10cSrcweir 1104cdf0e10cSrcweir // AnimatableShape methods 1105cdf0e10cSrcweir // ====================================================== 1106cdf0e10cSrcweir enterAnimationMode()1107cdf0e10cSrcweir void DrawShape::enterAnimationMode() 1108cdf0e10cSrcweir { 1109cdf0e10cSrcweir OSL_ENSURE( !maViewShapes.empty(), 1110cdf0e10cSrcweir "DrawShape::enterAnimationMode(): called on DrawShape without views" ); 1111cdf0e10cSrcweir 1112cdf0e10cSrcweir if( mnIsAnimatedCount == 0 ) 1113cdf0e10cSrcweir { 1114cdf0e10cSrcweir // notify all ViewShapes, by calling their enterAnimationMode method. 1115cdf0e10cSrcweir // We're now entering animation mode 1116cdf0e10cSrcweir ::std::for_each( maViewShapes.begin(), 1117cdf0e10cSrcweir maViewShapes.end(), 1118cdf0e10cSrcweir ::boost::mem_fn( &ViewShape::enterAnimationMode ) ); 1119cdf0e10cSrcweir } 1120cdf0e10cSrcweir 1121cdf0e10cSrcweir ++mnIsAnimatedCount; 1122cdf0e10cSrcweir } 1123cdf0e10cSrcweir leaveAnimationMode()1124cdf0e10cSrcweir void DrawShape::leaveAnimationMode() 1125cdf0e10cSrcweir { 1126cdf0e10cSrcweir OSL_ENSURE( !maViewShapes.empty(), 1127cdf0e10cSrcweir "DrawShape::leaveAnimationMode(): called on DrawShape without views" ); 1128cdf0e10cSrcweir 1129cdf0e10cSrcweir --mnIsAnimatedCount; 1130cdf0e10cSrcweir 1131cdf0e10cSrcweir if( mnIsAnimatedCount == 0 ) 1132cdf0e10cSrcweir { 1133cdf0e10cSrcweir // notify all ViewShapes, by calling their leaveAnimationMode method. 1134cdf0e10cSrcweir // we're now leaving animation mode 1135cdf0e10cSrcweir ::std::for_each( maViewShapes.begin(), 1136cdf0e10cSrcweir maViewShapes.end(), 1137cdf0e10cSrcweir ::boost::mem_fn( &ViewShape::leaveAnimationMode ) ); 1138cdf0e10cSrcweir } 1139cdf0e10cSrcweir } 1140cdf0e10cSrcweir 1141cdf0e10cSrcweir 1142cdf0e10cSrcweir // AttributableShape methods 1143cdf0e10cSrcweir // ====================================================== 1144cdf0e10cSrcweir createAttributeLayer()1145cdf0e10cSrcweir ShapeAttributeLayerSharedPtr DrawShape::createAttributeLayer() 1146cdf0e10cSrcweir { 1147cdf0e10cSrcweir // create new layer, with last as its new child 1148cdf0e10cSrcweir mpAttributeLayer.reset( new ShapeAttributeLayer( mpAttributeLayer ) ); 1149cdf0e10cSrcweir 1150cdf0e10cSrcweir // Update the local state ids to reflect those of the new layer. 1151cdf0e10cSrcweir updateStateIds(); 1152cdf0e10cSrcweir 1153cdf0e10cSrcweir return mpAttributeLayer; 1154cdf0e10cSrcweir } 1155cdf0e10cSrcweir revokeAttributeLayer(const ShapeAttributeLayerSharedPtr & rLayer)1156cdf0e10cSrcweir bool DrawShape::revokeAttributeLayer( const ShapeAttributeLayerSharedPtr& rLayer ) 1157cdf0e10cSrcweir { 1158cdf0e10cSrcweir if( !mpAttributeLayer ) 1159cdf0e10cSrcweir return false; // no layers 1160cdf0e10cSrcweir 1161cdf0e10cSrcweir if( mpAttributeLayer == rLayer ) 1162cdf0e10cSrcweir { 1163cdf0e10cSrcweir // it's the toplevel layer 1164cdf0e10cSrcweir mpAttributeLayer = mpAttributeLayer->getChildLayer(); 1165cdf0e10cSrcweir 1166cdf0e10cSrcweir // force content redraw, all state variables have 1167cdf0e10cSrcweir // possibly changed 1168cdf0e10cSrcweir mbAttributeLayerRevoked = true; 1169cdf0e10cSrcweir 1170cdf0e10cSrcweir return true; 1171cdf0e10cSrcweir } 1172cdf0e10cSrcweir else 1173cdf0e10cSrcweir { 1174cdf0e10cSrcweir // pass on to the layer, to try its children 1175cdf0e10cSrcweir return mpAttributeLayer->revokeChildLayer( rLayer ); 1176cdf0e10cSrcweir } 1177cdf0e10cSrcweir } 1178cdf0e10cSrcweir getTopmostAttributeLayer() const1179cdf0e10cSrcweir ShapeAttributeLayerSharedPtr DrawShape::getTopmostAttributeLayer() const 1180cdf0e10cSrcweir { 1181cdf0e10cSrcweir return mpAttributeLayer; 1182cdf0e10cSrcweir } 1183cdf0e10cSrcweir setVisibility(bool bVisible)1184cdf0e10cSrcweir void DrawShape::setVisibility( bool bVisible ) 1185cdf0e10cSrcweir { 1186cdf0e10cSrcweir if( mbIsVisible != bVisible ) 1187cdf0e10cSrcweir { 1188cdf0e10cSrcweir mbIsVisible = bVisible; 1189cdf0e10cSrcweir mbForceUpdate = true; 1190cdf0e10cSrcweir } 1191cdf0e10cSrcweir } 1192cdf0e10cSrcweir getTreeNodeSupplier() const1193cdf0e10cSrcweir const DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier() const 1194cdf0e10cSrcweir { 1195cdf0e10cSrcweir return *this; 1196cdf0e10cSrcweir } 1197cdf0e10cSrcweir getTreeNodeSupplier()1198cdf0e10cSrcweir DocTreeNodeSupplier& DrawShape::getTreeNodeSupplier() 1199cdf0e10cSrcweir { 1200cdf0e10cSrcweir return *this; 1201cdf0e10cSrcweir } 1202cdf0e10cSrcweir getSubsetNode() const1203cdf0e10cSrcweir DocTreeNode DrawShape::getSubsetNode() const 1204cdf0e10cSrcweir { 1205cdf0e10cSrcweir ensureVerboseMtfComments(); 1206cdf0e10cSrcweir 1207cdf0e10cSrcweir // forward to delegate 1208cdf0e10cSrcweir return maSubsetting.getSubsetNode(); 1209cdf0e10cSrcweir } 1210cdf0e10cSrcweir getSubset(const DocTreeNode & rTreeNode) const1211cdf0e10cSrcweir AttributableShapeSharedPtr DrawShape::getSubset( const DocTreeNode& rTreeNode ) const 1212cdf0e10cSrcweir { 1213cdf0e10cSrcweir ENSURE_OR_THROW( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0, 1214cdf0e10cSrcweir "DrawShape::getSubset(): subset query on shape with apparently no subsets" ); 1215cdf0e10cSrcweir 1216cdf0e10cSrcweir // forward to delegate 1217cdf0e10cSrcweir return maSubsetting.getSubsetShape( rTreeNode ); 1218cdf0e10cSrcweir } 1219cdf0e10cSrcweir createSubset(AttributableShapeSharedPtr & o_rSubset,const DocTreeNode & rTreeNode)1220cdf0e10cSrcweir bool DrawShape::createSubset( AttributableShapeSharedPtr& o_rSubset, 1221cdf0e10cSrcweir const DocTreeNode& rTreeNode ) 1222cdf0e10cSrcweir { 1223cdf0e10cSrcweir ENSURE_OR_THROW( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0, 1224cdf0e10cSrcweir "DrawShape::createSubset(): subset query on shape with apparently no subsets" ); 1225cdf0e10cSrcweir 1226cdf0e10cSrcweir // subset shape already created for this DocTreeNode? 1227cdf0e10cSrcweir AttributableShapeSharedPtr pSubset( maSubsetting.getSubsetShape( rTreeNode ) ); 1228cdf0e10cSrcweir 1229cdf0e10cSrcweir // when true, this method has created a new subset 1230cdf0e10cSrcweir // DrawShape 1231cdf0e10cSrcweir bool bNewlyCreated( false ); 1232cdf0e10cSrcweir 1233cdf0e10cSrcweir if( pSubset ) 1234cdf0e10cSrcweir { 1235cdf0e10cSrcweir o_rSubset = pSubset; 1236cdf0e10cSrcweir 1237cdf0e10cSrcweir // reusing existing subset 1238cdf0e10cSrcweir } 1239cdf0e10cSrcweir else 1240cdf0e10cSrcweir { 1241cdf0e10cSrcweir // not yet created, init entry 1242cdf0e10cSrcweir o_rSubset.reset( new DrawShape( *this, 1243cdf0e10cSrcweir rTreeNode, 1244cdf0e10cSrcweir // TODO(Q3): That's a 1245cdf0e10cSrcweir // hack. We assume 1246cdf0e10cSrcweir // that start and end 1247cdf0e10cSrcweir // index will always 1248cdf0e10cSrcweir // be less than 65535 1249cdf0e10cSrcweir mnPriority + 1250cdf0e10cSrcweir rTreeNode.getStartIndex()/double(SAL_MAX_INT16) )); 1251cdf0e10cSrcweir 1252cdf0e10cSrcweir bNewlyCreated = true; // subset newly created 1253cdf0e10cSrcweir } 1254cdf0e10cSrcweir 1255cdf0e10cSrcweir // always register shape at DrawShapeSubsetting, to keep 1256cdf0e10cSrcweir // refcount up-to-date 1257cdf0e10cSrcweir maSubsetting.addSubsetShape( o_rSubset ); 1258cdf0e10cSrcweir 1259cdf0e10cSrcweir // flush bounds cache 1260cdf0e10cSrcweir maCurrentShapeUnitBounds.reset(); 1261cdf0e10cSrcweir 1262cdf0e10cSrcweir return bNewlyCreated; 1263cdf0e10cSrcweir } 1264cdf0e10cSrcweir revokeSubset(const AttributableShapeSharedPtr & rShape)1265cdf0e10cSrcweir bool DrawShape::revokeSubset( const AttributableShapeSharedPtr& rShape ) 1266cdf0e10cSrcweir { 1267cdf0e10cSrcweir ENSURE_OR_THROW( (mnCurrMtfLoadFlags & MTF_LOAD_VERBOSE_COMMENTS) != 0, 1268cdf0e10cSrcweir "DrawShape::createSubset(): subset query on shape with apparently no subsets" ); 1269cdf0e10cSrcweir 1270cdf0e10cSrcweir // flush bounds cache 1271cdf0e10cSrcweir maCurrentShapeUnitBounds.reset(); 1272cdf0e10cSrcweir 1273cdf0e10cSrcweir // forward to delegate 1274cdf0e10cSrcweir if( maSubsetting.revokeSubsetShape( rShape ) ) 1275cdf0e10cSrcweir { 1276cdf0e10cSrcweir // force redraw, our content has possibly changed (as 1277cdf0e10cSrcweir // one of the subsets now display within our shape 1278cdf0e10cSrcweir // again). 1279cdf0e10cSrcweir mbForceUpdate = true; 1280cdf0e10cSrcweir 1281cdf0e10cSrcweir // #i47428# TEMP FIX: synchronize visibility of subset 1282cdf0e10cSrcweir // with parent. 1283cdf0e10cSrcweir 1284cdf0e10cSrcweir // TODO(F3): Remove here, and implement 1285cdf0e10cSrcweir // TEXT_ONLY/BACKGROUND_ONLY with the proverbial 1286cdf0e10cSrcweir // additional level of indirection: create a 1287cdf0e10cSrcweir // persistent subset, containing all text/only the 1288cdf0e10cSrcweir // background respectively. From _that_ object, 1289cdf0e10cSrcweir // generate the temporary character subset shapes. 1290cdf0e10cSrcweir const ShapeAttributeLayerSharedPtr& rAttrLayer( 1291cdf0e10cSrcweir rShape->getTopmostAttributeLayer() ); 1292cdf0e10cSrcweir if( rAttrLayer && 1293cdf0e10cSrcweir rAttrLayer->isVisibilityValid() && 1294cdf0e10cSrcweir rAttrLayer->getVisibility() != isVisible() ) 1295cdf0e10cSrcweir { 1296cdf0e10cSrcweir const bool bVisibility( rAttrLayer->getVisibility() ); 1297cdf0e10cSrcweir 1298cdf0e10cSrcweir // visibilities differ - adjust ours, then 1299cdf0e10cSrcweir if( mpAttributeLayer ) 1300cdf0e10cSrcweir mpAttributeLayer->setVisibility( bVisibility ); 1301cdf0e10cSrcweir else 1302cdf0e10cSrcweir mbIsVisible = bVisibility; 1303cdf0e10cSrcweir } 1304cdf0e10cSrcweir 1305cdf0e10cSrcweir // END TEMP FIX 1306cdf0e10cSrcweir 1307cdf0e10cSrcweir return true; 1308cdf0e10cSrcweir } 1309cdf0e10cSrcweir 1310cdf0e10cSrcweir return false; 1311cdf0e10cSrcweir } 1312cdf0e10cSrcweir getNumberOfTreeNodes(DocTreeNode::NodeType eNodeType) const1313cdf0e10cSrcweir sal_Int32 DrawShape::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException 1314cdf0e10cSrcweir { 1315cdf0e10cSrcweir ensureVerboseMtfComments(); 1316cdf0e10cSrcweir 1317cdf0e10cSrcweir return maSubsetting.getNumberOfTreeNodes( eNodeType ); 1318cdf0e10cSrcweir } 1319cdf0e10cSrcweir getTreeNode(sal_Int32 nNodeIndex,DocTreeNode::NodeType eNodeType) const1320cdf0e10cSrcweir DocTreeNode DrawShape::getTreeNode( sal_Int32 nNodeIndex, 1321cdf0e10cSrcweir DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException 1322cdf0e10cSrcweir { 1323cdf0e10cSrcweir ensureVerboseMtfComments(); 1324cdf0e10cSrcweir 1325cdf0e10cSrcweir if ( hasHyperlinks()) 1326cdf0e10cSrcweir { 1327cdf0e10cSrcweir prepareHyperlinkIndices(); 1328cdf0e10cSrcweir } 1329cdf0e10cSrcweir 1330cdf0e10cSrcweir return maSubsetting.getTreeNode( nNodeIndex, eNodeType ); 1331cdf0e10cSrcweir } 1332cdf0e10cSrcweir getNumberOfSubsetTreeNodes(const DocTreeNode & rParentNode,DocTreeNode::NodeType eNodeType) const1333cdf0e10cSrcweir sal_Int32 DrawShape::getNumberOfSubsetTreeNodes ( const DocTreeNode& rParentNode, 1334cdf0e10cSrcweir DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException 1335cdf0e10cSrcweir { 1336cdf0e10cSrcweir ensureVerboseMtfComments(); 1337cdf0e10cSrcweir 1338cdf0e10cSrcweir return maSubsetting.getNumberOfSubsetTreeNodes( rParentNode, eNodeType ); 1339cdf0e10cSrcweir } 1340cdf0e10cSrcweir getSubsetTreeNode(const DocTreeNode & rParentNode,sal_Int32 nNodeIndex,DocTreeNode::NodeType eNodeType) const1341cdf0e10cSrcweir DocTreeNode DrawShape::getSubsetTreeNode( const DocTreeNode& rParentNode, 1342cdf0e10cSrcweir sal_Int32 nNodeIndex, 1343cdf0e10cSrcweir DocTreeNode::NodeType eNodeType ) const // throw ShapeLoadFailedException 1344cdf0e10cSrcweir { 1345cdf0e10cSrcweir ensureVerboseMtfComments(); 1346cdf0e10cSrcweir 1347cdf0e10cSrcweir return maSubsetting.getSubsetTreeNode( rParentNode, nNodeIndex, eNodeType ); 1348cdf0e10cSrcweir } 1349cdf0e10cSrcweir } 1350cdf0e10cSrcweir } 1351