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