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