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