1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: drawshape.cxx,v $
10 * $Revision: 1.7.12.1 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_slideshow.hxx"
35 #include <canvas/debug.hxx>
36 #include <tools/diagnose_ex.h>
37 #include <canvas/verbosetrace.hxx>
39 #include <rtl/logfile.hxx>
40 #include <osl/diagnose.hxx>
41 #include <com/sun/star/awt/Rectangle.hpp>
42 #include <com/sun/star/beans/XPropertySet.hpp>
43 #include <com/sun/star/awt/FontWeight.hpp>
44 #include <comphelper/anytostring.hxx>
45 #include <cppuhelper/exc_hlp.hxx>
47 #include <vcl/metaact.hxx>
48 #include <vcl/gdimtf.hxx>
49 #include <vcl/wrkwin.hxx>
51 #include <basegfx/numeric/ftools.hxx>
52 #include <basegfx/range/rangeexpander.hxx>
54 #include <rtl/math.hxx>
56 #include <com/sun/star/drawing/TextAnimationKind.hpp>
58 #include <vcl/svapp.hxx>
59 #include <vcl/window.hxx>
60 #include <tools/stream.hxx>
61 #include <com/sun/star/frame/XModel.hpp>
62 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
63 #include <com/sun/star/datatransfer/XTransferable.hpp>
65 #include <comphelper/scopeguard.hxx>
66 #include <canvas/canvastools.hxx>
68 #include <cmath> // for trigonometry and fabs
73 #include "drawshapesubsetting.hxx"
74 #include "drawshape.hxx"
75 #include "eventqueue.hxx"
76 #include "wakeupevent.hxx"
77 #include "subsettableshapemanager.hxx"
78 #include "intrinsicanimationactivity.hxx"
79 #include "slideshowexceptions.hxx"
81 #include "gdimtftools.hxx"
82 #include "drawinglayeranimation.hxx"
84 #include <boost/bind.hpp>
87 using namespace ::com::sun::star
;
94 //#i75867# poor quality of ole's alternative view with 3D scenes and zoomfactors besides 100%
95 //metafiles are resolution dependent when bitmaps are contained with is the case for 3D scenes for example
96 //in addition a chart has resolution dependent content as it might skip points that are not visible for a given resolution (this is done for performance reasons)
97 bool local_getMetafileForChart( const uno::Reference
< lang::XComponent
>& xSource
,
98 const uno::Reference
< drawing::XDrawPage
>& xContainingPage
,
101 //get the chart model
102 uno::Reference
< beans::XPropertySet
> xPropSet( xSource
, uno::UNO_QUERY
);
103 uno::Reference
< frame::XModel
> xChartModel
;
104 getPropertyValue( xChartModel
, xPropSet
, OUSTR("Model"));
105 uno::Reference
< lang::XMultiServiceFactory
> xFact( xChartModel
, uno::UNO_QUERY
);
106 OSL_ENSURE( xFact
.is(), "Chart cannot be painted pretty!\n" );
111 uno::Reference
< datatransfer::XTransferable
> xChartViewTransferable(
112 xFact
->createInstance( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.ChartView" ) ) ), uno::UNO_QUERY
);
113 uno::Reference
< beans::XPropertySet
> xChartViewProp( xChartViewTransferable
, uno::UNO_QUERY
);
114 OSL_ENSURE( xChartViewProp
.is(), "Chart cannot be painted pretty!\n" );
115 if( !xChartViewProp
.is() )
118 //estimate zoom and resolution (this is only a workaround, correct would be to know and use the exact zoom and resoltion during slideshow display)
119 sal_Int32 nScaleXNumerator
= 100;//zoom factor -> exact values are important for the quality of the created bitmap especially for 3D charts
120 sal_Int32 nScaleYNumerator
= 100;
121 sal_Int32 nScaleXDenominator
= 100;
122 sal_Int32 nScaleYDenominator
= 100;
123 awt::Size
aPixelPerChart( 1000, 1000 );//when data points happen to be on the same pixel as their predecessor no shape is created to safe performance
125 Window
* pActiveTopWindow( Application::GetActiveTopWindow() );
126 WorkWindow
* pWorkWindow( dynamic_cast<WorkWindow
*>(pActiveTopWindow
));
127 if( pWorkWindow
&& pWorkWindow
->IsPresentationMode() )
129 Size
aPixScreenSize( pActiveTopWindow
->GetOutputSizePixel() );
130 aPixelPerChart
= awt::Size( aPixScreenSize
.getWidth(), aPixScreenSize
.getHeight() );//this is still to much (but costs only seldom performance), correct would be pixel per chart object
132 uno::Reference
< beans::XPropertySet
> xPageProp( xContainingPage
, uno::UNO_QUERY
);
133 sal_Int32 nLogicPageWidth
=1;
134 sal_Int32 nLogicPageHeight
=1;
135 if( getPropertyValue( nLogicPageWidth
, xPageProp
, OUSTR("Width")) &&
136 getPropertyValue( nLogicPageHeight
, xPageProp
, OUSTR("Height")) )
138 Size
aLogicScreenSize( pActiveTopWindow
->PixelToLogic( aPixScreenSize
, MAP_100TH_MM
) );
139 nScaleXNumerator
= aLogicScreenSize
.getWidth();
140 nScaleYNumerator
= aLogicScreenSize
.getHeight();
141 nScaleXDenominator
= nLogicPageWidth
;
142 nScaleYDenominator
= nLogicPageHeight
;
147 long nMaxPixWidth
= 0;
148 long nMaxPixHeight
= 0;
149 unsigned int nScreenCount( Application::GetScreenCount() );
150 for( unsigned int nScreen
=0; nScreen
<nScreenCount
; nScreen
++ )
152 Rectangle
aCurScreenRect( Application::GetScreenPosSizePixel( nScreen
) );
153 if( aCurScreenRect
.GetWidth() > nMaxPixWidth
)
154 nMaxPixWidth
= aCurScreenRect
.GetWidth();
155 if( aCurScreenRect
.GetHeight() > nMaxPixHeight
)
156 nMaxPixHeight
= aCurScreenRect
.GetHeight();
158 if(nMaxPixWidth
>1 && nMaxPixHeight
>1)
159 aPixelPerChart
= awt::Size( nMaxPixWidth
, nMaxPixHeight
);//this is still to much (but costs only seldom performance), correct would be pixel per chart object
164 uno::Sequence
< beans::PropertyValue
> aZoomFactors(4);
165 aZoomFactors
[0].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleXNumerator") );
166 aZoomFactors
[0].Value
= uno::makeAny( nScaleXNumerator
);
167 aZoomFactors
[1].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleXDenominator") );
168 aZoomFactors
[1].Value
= uno::makeAny( nScaleXDenominator
);
169 aZoomFactors
[2].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleYNumerator") );
170 aZoomFactors
[2].Value
= uno::makeAny( nScaleYNumerator
);
171 aZoomFactors
[3].Name
= ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ScaleYDenominator") );
172 aZoomFactors
[3].Value
= uno::makeAny( nScaleYDenominator
);
174 xChartViewProp
->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("ZoomFactors") ), uno::makeAny( aZoomFactors
));
175 xChartViewProp
->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Resolution") ), uno::makeAny( aPixelPerChart
));
177 catch (uno::Exception
&)
179 OSL_ENSURE( false, rtl::OUStringToOString(
180 comphelper::anyToString(
181 cppu::getCaughtException() ),
182 RTL_TEXTENCODING_UTF8
).getStr() );
185 //get a metafile from the prepared chart view
186 datatransfer::DataFlavor
aDataFlavor(
187 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("application/x-openoffice-gdimetafile;windows_formatname=\"GDIMetaFile\"") ),
188 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "GDIMetaFile" ) ),
189 ::getCppuType( (const uno::Sequence
< sal_Int8
>*) 0 ) );
190 uno::Any
aData( xChartViewTransferable
->getTransferData( aDataFlavor
) );
191 uno::Sequence
< sal_Int8
> aSeq
;
194 ::std::auto_ptr
< SvMemoryStream
> pSrcStm( new SvMemoryStream( (char*) aSeq
.getConstArray(), aSeq
.getLength(), STREAM_WRITE
| STREAM_TRUNC
) );
195 *(pSrcStm
.get() ) >> rMtf
;
201 //same as getMetafile with an exception for charts
202 //for charts a metafile with a higher resolution is created, because charts have resolution dependent content
203 bool local_getMetaFile_WithSpecialChartHandling( const uno::Reference
< lang::XComponent
>& xSource
,
204 const uno::Reference
< drawing::XDrawPage
>& xContainingPage
,
207 const uno::Reference
< uno::XComponentContext
>& rxContext
)
209 uno::Reference
<beans::XPropertySet
> xProp( xSource
, uno::UNO_QUERY
);
210 rtl::OUString sCLSID
;
211 getPropertyValue( sCLSID
, xProp
, OUSTR("CLSID"));
212 if( sCLSID
.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("12DCAE26-281F-416F-a234-c3086127382e")) && local_getMetafileForChart( xSource
, xContainingPage
, rMtf
) )
214 return getMetaFile( xSource
, xContainingPage
, rMtf
, mtfLoadFlags
, rxContext
);
218 //////////////////////////////////////////////////////////////////////
222 //////////////////////////////////////////////////////////////////////
224 GDIMetaFileSharedPtr
DrawShape::forceScrollTextMetaFile()
226 if ((mnCurrMtfLoadFlags
& MTF_LOAD_SCROLL_TEXT_MTF
) != MTF_LOAD_SCROLL_TEXT_MTF
)
228 // reload with added flags:
229 mpCurrMtf
.reset( new GDIMetaFile
);
230 mnCurrMtfLoadFlags
|= MTF_LOAD_SCROLL_TEXT_MTF
;
231 local_getMetaFile_WithSpecialChartHandling(
232 uno::Reference
<lang::XComponent
>(mxShape
, uno::UNO_QUERY
),
233 mxPage
, *mpCurrMtf
, mnCurrMtfLoadFlags
,
234 mxComponentContext
);
236 // TODO(F1): Currently, the scroll metafile will
237 // never contain any verbose text comments. Thus,
238 // can only display the full mtf content, no
240 maSubsetting
.reset( mpCurrMtf
);
242 // adapt maBounds. the requested scroll text metafile
243 // will typically have dimension different from the
245 ::basegfx::B2DRectangle aScrollRect
, aPaintRect
;
246 ENSURE_OR_THROW( getRectanglesFromScrollMtf( aScrollRect
,
249 "DrawShape::forceScrollTextMetaFile(): Could "
250 "not extract scroll anim rectangles from mtf" );
252 // take the larger one of the two rectangles (that
253 // should be the bound rect of the retrieved
255 if( aScrollRect
.isInside( aPaintRect
) )
256 maBounds
= aScrollRect
;
258 maBounds
= aPaintRect
;
263 void DrawShape::updateStateIds() const
265 // Update the states, we've just redrawn or created a new
267 if( mpAttributeLayer
)
269 mnAttributeTransformationState
= mpAttributeLayer
->getTransformationState();
270 mnAttributeClipState
= mpAttributeLayer
->getClipState();
271 mnAttributeAlphaState
= mpAttributeLayer
->getAlphaState();
272 mnAttributePositionState
= mpAttributeLayer
->getPositionState();
273 mnAttributeContentState
= mpAttributeLayer
->getContentState();
274 mnAttributeVisibilityState
= mpAttributeLayer
->getVisibilityState();
278 void DrawShape::ensureVerboseMtfComments() const
280 // TODO(F1): Text effects don't currently work for drawing
283 // only touch mpCurrMtf, if we're not a DrawingLayer
285 if( (mnCurrMtfLoadFlags
& MTF_LOAD_VERBOSE_COMMENTS
) == 0 &&
286 maAnimationFrames
.empty() )
288 ENSURE_OR_THROW( !maSubsetting
.hasSubsetShapes(),
289 "DrawShape::ensureVerboseMtfComments(): reloading the metafile "
290 "with active child subsets will wreak havoc on the view!" );
291 ENSURE_OR_THROW( maSubsetting
.getSubsetNode().isEmpty(),
292 "DrawShape::ensureVerboseMtfComments(): reloading the metafile "
293 "for an ALREADY SUBSETTED shape is not possible!" );
295 // re-fetch metafile with comments
296 // note that, in case of shapes without text, the new
297 // metafile might still not provide any useful
298 // subsetting information!
299 mpCurrMtf
.reset( new GDIMetaFile
);
300 mnCurrMtfLoadFlags
|= MTF_LOAD_VERBOSE_COMMENTS
;
301 local_getMetaFile_WithSpecialChartHandling(
302 uno::Reference
<lang::XComponent
>(mxShape
, uno::UNO_QUERY
),
303 mxPage
, *mpCurrMtf
, mnCurrMtfLoadFlags
,
304 mxComponentContext
);
306 maSubsetting
.reset( maSubsetting
.getSubsetNode(),
311 ViewShape::RenderArgs
DrawShape::getViewRenderArgs() const
313 return ViewShape::RenderArgs(
317 getActualUnitShapeBounds(),
319 maSubsetting
.getActiveSubsets(),
323 bool DrawShape::implRender( int nUpdateFlags
) const
325 RTL_LOGFILE_CONTEXT( aLog
, "::presentation::internal::DrawShape::implRender()" );
326 RTL_LOGFILE_CONTEXT_TRACE1( aLog
, "::presentation::internal::DrawShape: 0x%X", this );
328 // will perform the update now, clear update-enforcing
330 mbForceUpdate
= false;
331 mbAttributeLayerRevoked
= false;
333 ENSURE_OR_RETURN( !maViewShapes
.empty(),
334 "DrawShape::implRender(): render called on DrawShape without views" );
336 if( maBounds
.isEmpty() )
338 // zero-sized shapes are effectively invisible,
339 // thus, we save us the rendering...
343 // redraw all view shapes, by calling their update() method
344 if( ::std::count_if( maViewShapes
.begin(),
347 ::boost::mem_fn( &ViewShape::update
), // though _theoretically_,
348 // bind should eat this even
349 // with _1 being a shared_ptr,
350 // it does _not_ for MSVC without
351 // the extra mem_fn. WTF.
353 ::boost::cref( mpCurrMtf
),
355 getViewRenderArgs() ),
358 != static_cast<ViewShapeVector::difference_type
>(maViewShapes
.size()) )
360 // at least one of the ViewShape::update() calls did return
361 // false - update failed on at least one ViewLayer
365 // successfully redrawn - update state IDs to detect next changes
371 int DrawShape::getUpdateFlags() const
373 // default: update nothing, unless ShapeAttributeStack
374 // tells us below, or if the attribute layer was revoked
375 int nUpdateFlags(ViewShape::NONE
);
377 // possibly the whole shape content changed
378 if( mbAttributeLayerRevoked
)
379 nUpdateFlags
= ViewShape::CONTENT
;
382 // determine what has to be updated
383 // --------------------------------
385 // do we have an attribute layer?
386 if( mpAttributeLayer
)
388 // Prevent nUpdateFlags to be modified when the shape is not
389 // visible, except when it just was hidden.
390 if (mpAttributeLayer
->getVisibility()
391 || mpAttributeLayer
->getVisibilityState() != mnAttributeVisibilityState
)
393 if (mpAttributeLayer
->getVisibilityState() != mnAttributeVisibilityState
)
395 // Change of the visibility state is mapped to
396 // content change because when the visibility
397 // changes then usually a sprite is shown or hidden
398 // and the background under has to be painted once.
399 nUpdateFlags
|= ViewShape::CONTENT
;
402 // TODO(P1): This can be done without conditional branching.
404 if( mpAttributeLayer
->getPositionState() != mnAttributePositionState
)
406 nUpdateFlags
|= ViewShape::POSITION
;
408 if( mpAttributeLayer
->getAlphaState() != mnAttributeAlphaState
)
410 nUpdateFlags
|= ViewShape::ALPHA
;
412 if( mpAttributeLayer
->getClipState() != mnAttributeClipState
)
414 nUpdateFlags
|= ViewShape::CLIP
;
416 if( mpAttributeLayer
->getTransformationState() != mnAttributeTransformationState
)
418 nUpdateFlags
|= ViewShape::TRANSFORMATION
;
420 if( mpAttributeLayer
->getContentState() != mnAttributeContentState
)
422 nUpdateFlags
|= ViewShape::CONTENT
;
430 ::basegfx::B2DRectangle
DrawShape::getActualUnitShapeBounds() const
432 ENSURE_OR_THROW( !maViewShapes
.empty(),
433 "DrawShape::getActualUnitShapeBounds(): called on DrawShape without views" );
435 const VectorOfDocTreeNodes
& rSubsets(
436 maSubsetting
.getActiveSubsets() );
438 const ::basegfx::B2DRectangle
aDefaultBounds( 0.0,0.0,1.0,1.0 );
440 // perform the cheapest check first
441 if( rSubsets
.empty() )
443 // if subset contains the whole shape, no need to call
444 // the somewhat expensive bound calculation, since as
445 // long as the subset is empty, this branch will be
447 return aDefaultBounds
;
451 OSL_ENSURE( rSubsets
.size() != 1 ||
452 !rSubsets
.front().isEmpty(),
453 "DrawShape::getActualUnitShapeBounds() expects a "
454 "_non-empty_ subset vector for a subsetted shape!" );
456 // are the cached bounds still valid?
457 if( !maCurrentShapeUnitBounds
)
459 // no, (re)generate them
460 // =====================
462 // setup cached values to defaults (might fail to
463 // retrieve true bounds below)
464 maCurrentShapeUnitBounds
.reset( aDefaultBounds
);
466 // TODO(P2): the subset of the master shape (that from
467 // which the subsets are subtracted) changes
468 // relatively often (every time a subset shape is
469 // added or removed). Maybe we should exclude it here,
470 // always assuming full bounds?
472 ::cppcanvas::CanvasSharedPtr
pDestinationCanvas(
473 maViewShapes
.front()->getViewLayer()->getCanvas() );
475 // TODO(Q2): Although this _is_ currently
476 // view-agnostic, it might not stay like
477 // that. Maybe this method should again be moved
479 ::cppcanvas::RendererSharedPtr
pRenderer(
480 maViewShapes
.front()->getRenderer(
481 pDestinationCanvas
, mpCurrMtf
, mpAttributeLayer
) );
483 // If we cannot not prefetch, be defensive and assume
487 // temporarily, switch total transformation to identity
488 // (need the bounds in the [0,1]x[0,1] unit coordinate
490 ::basegfx::B2DHomMatrix aEmptyTransformation
;
492 ::basegfx::B2DHomMatrix
aOldTransform( pDestinationCanvas
->getTransformation() );
493 pDestinationCanvas
->setTransformation( aEmptyTransformation
);
494 pRenderer
->setTransformation( aEmptyTransformation
);
496 // restore old transformation when leaving the scope
497 const ::comphelper::ScopeGuard
aGuard(
498 boost::bind( &::cppcanvas::Canvas::setTransformation
,
499 pDestinationCanvas
, aOldTransform
) );
502 // retrieve bounds for subset of whole metafile
503 // --------------------------------------------
505 ::basegfx::B2DRange aTotalBounds
;
507 // cannot use ::boost::bind, ::basegfx::B2DRange::expand()
509 VectorOfDocTreeNodes::const_iterator
aCurr( rSubsets
.begin() );
510 const VectorOfDocTreeNodes::const_iterator
aEnd( rSubsets
.end() );
511 while( aCurr
!= aEnd
)
513 aTotalBounds
.expand( pRenderer
->getSubsetArea(
514 aCurr
->getStartIndex(),
515 aCurr
->getEndIndex() ) );
519 OSL_ENSURE( aTotalBounds
.getMinX() >= -0.1 &&
520 aTotalBounds
.getMinY() >= -0.1 &&
521 aTotalBounds
.getMaxX() <= 1.1 &&
522 aTotalBounds
.getMaxY() <= 1.1,
523 "DrawShape::getActualUnitShapeBounds(): bounds noticeably larger than original shape - clipping!" );
525 // really make sure no shape appears larger than its
526 // original bounds (there _are_ some pathologic cases,
527 // especially when imported from PPT, that have
528 // e.g. obscenely large polygon bounds)
529 aTotalBounds
.intersect(
530 ::basegfx::B2DRange( 0.0, 0.0,
533 maCurrentShapeUnitBounds
.reset( aTotalBounds
);
537 return *maCurrentShapeUnitBounds
;
541 DrawShape::DrawShape( const uno::Reference
< drawing::XShape
>& xShape
,
542 const uno::Reference
< drawing::XDrawPage
>& xContainingPage
,
545 const SlideShowContext
& rContext
) :
547 mxPage( xContainingPage
),
548 maAnimationFrames(), // empty, we don't have no intrinsic animation
551 mnCurrMtfLoadFlags( bForeignSource
552 ? MTF_LOAD_FOREIGN_SOURCE
: MTF_LOAD_NONE
),
553 maCurrentShapeUnitBounds(),
554 mnPriority( nPrio
), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
555 maBounds( getAPIShapeBounds( xShape
) ),
557 mpIntrinsicAnimationActivity(),
558 mnAttributeTransformationState(0),
559 mnAttributeClipState(0),
560 mnAttributeAlphaState(0),
561 mnAttributePositionState(0),
562 mnAttributeContentState(0),
563 mnAttributeVisibilityState(0),
565 mxComponentContext( rContext
.mxComponentContext
),
566 maHyperlinkIndices(),
567 maHyperlinkRegions(),
569 mnIsAnimatedCount(0),
570 mnAnimationLoopCount(0),
571 meCycleMode(CYCLE_LOOP
),
573 mbForceUpdate( false ),
574 mbAttributeLayerRevoked( false ),
575 mbDrawingLayerAnim( false )
577 ENSURE_OR_THROW( mxShape
.is(), "DrawShape::DrawShape(): Invalid XShape" );
578 ENSURE_OR_THROW( mxPage
.is(), "DrawShape::DrawShape(): Invalid containing page" );
580 // check for drawing layer animations:
581 drawing::TextAnimationKind eKind
= drawing::TextAnimationKind_NONE
;
582 uno::Reference
<beans::XPropertySet
> xPropSet( mxShape
,
585 getPropertyValue( eKind
, xPropSet
,
586 OUSTR("TextAnimationKind") );
587 mbDrawingLayerAnim
= (eKind
!= drawing::TextAnimationKind_NONE
);
589 // must NOT be called from within initializer list, uses
590 // state from mnCurrMtfLoadFlags!
591 mpCurrMtf
.reset( new GDIMetaFile
);
592 local_getMetaFile_WithSpecialChartHandling(
593 uno::Reference
<lang::XComponent
>(xShape
, uno::UNO_QUERY
),
594 xContainingPage
, *mpCurrMtf
, mnCurrMtfLoadFlags
,
595 mxComponentContext
);
596 ENSURE_OR_THROW( mpCurrMtf
,
597 "DrawShape::DrawShape(): Invalid metafile" );
598 maSubsetting
.reset( mpCurrMtf
);
600 prepareHyperlinkIndices();
603 DrawShape::DrawShape( const uno::Reference
< drawing::XShape
>& xShape
,
604 const uno::Reference
< drawing::XDrawPage
>& xContainingPage
,
606 const Graphic
& rGraphic
,
607 const SlideShowContext
& rContext
) :
609 mxPage( xContainingPage
),
613 mnCurrMtfLoadFlags( MTF_LOAD_NONE
),
614 maCurrentShapeUnitBounds(),
615 mnPriority( nPrio
), // TODO(F1): When ZOrder someday becomes usable: make this ( getAPIShapePrio( xShape ) ),
616 maBounds( getAPIShapeBounds( xShape
) ),
618 mpIntrinsicAnimationActivity(),
619 mnAttributeTransformationState(0),
620 mnAttributeClipState(0),
621 mnAttributeAlphaState(0),
622 mnAttributePositionState(0),
623 mnAttributeContentState(0),
624 mnAttributeVisibilityState(0),
626 mxComponentContext( rContext
.mxComponentContext
),
627 maHyperlinkIndices(),
628 maHyperlinkRegions(),
630 mnIsAnimatedCount(0),
631 mnAnimationLoopCount(0),
632 meCycleMode(CYCLE_LOOP
),
634 mbForceUpdate( false ),
635 mbAttributeLayerRevoked( false ),
636 mbDrawingLayerAnim( false )
638 ENSURE_OR_THROW( rGraphic
.IsAnimated(),
639 "DrawShape::DrawShape(): Graphic is no animation" );
641 getAnimationFromGraphic( maAnimationFrames
,
642 mnAnimationLoopCount
,
646 ENSURE_OR_THROW( !maAnimationFrames
.empty() &&
647 maAnimationFrames
.front().mpMtf
,
648 "DrawShape::DrawShape(): " );
649 mpCurrMtf
= maAnimationFrames
.front().mpMtf
;
651 ENSURE_OR_THROW( mxShape
.is(), "DrawShape::DrawShape(): Invalid XShape" );
652 ENSURE_OR_THROW( mxPage
.is(), "DrawShape::DrawShape(): Invalid containing page" );
653 ENSURE_OR_THROW( mpCurrMtf
, "DrawShape::DrawShape(): Invalid metafile" );
656 DrawShape::DrawShape( const DrawShape
& rSrc
,
657 const DocTreeNode
& rTreeNode
,
659 mxShape( rSrc
.mxShape
),
660 mxPage( rSrc
.mxPage
),
661 maAnimationFrames(), // don't copy animations for subsets,
662 // only the current frame!
664 mpCurrMtf( rSrc
.mpCurrMtf
),
665 mnCurrMtfLoadFlags( rSrc
.mnCurrMtfLoadFlags
),
666 maCurrentShapeUnitBounds(),
668 maBounds( rSrc
.maBounds
),
670 mpIntrinsicAnimationActivity(),
671 mnAttributeTransformationState(0),
672 mnAttributeClipState(0),
673 mnAttributeAlphaState(0),
674 mnAttributePositionState(0),
675 mnAttributeContentState(0),
676 mnAttributeVisibilityState(0),
678 mxComponentContext( rSrc
.mxComponentContext
),
679 maHyperlinkIndices(),
680 maHyperlinkRegions(),
681 maSubsetting( rTreeNode
, mpCurrMtf
),
682 mnIsAnimatedCount(0),
683 mnAnimationLoopCount(0),
684 meCycleMode(CYCLE_LOOP
),
685 mbIsVisible( rSrc
.mbIsVisible
),
686 mbForceUpdate( false ),
687 mbAttributeLayerRevoked( false ),
688 mbDrawingLayerAnim( false )
690 ENSURE_OR_THROW( mxShape
.is(), "DrawShape::DrawShape(): Invalid XShape" );
691 ENSURE_OR_THROW( mpCurrMtf
, "DrawShape::DrawShape(): Invalid metafile" );
693 // xxx todo: currently not implemented for subsetted shapes;
694 // would mean modifying set of hyperlink regions when
695 // subsetting text portions. N.B.: there's already an
696 // issue for this #i72828#
699 //////////////////////////////////////////////////////////////////////
703 //////////////////////////////////////////////////////////////////////
705 DrawShapeSharedPtr
DrawShape::create(
706 const uno::Reference
< drawing::XShape
>& xShape
,
707 const uno::Reference
< drawing::XDrawPage
>& xContainingPage
,
710 const SlideShowContext
& rContext
)
712 DrawShapeSharedPtr
pShape( new DrawShape(xShape
,
718 if( pShape
->hasIntrinsicAnimation() )
720 OSL_ASSERT( pShape
->maAnimationFrames
.empty() );
721 if( pShape
->getNumberOfTreeNodes(
722 DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH
) > 0 )
724 pShape
->mpIntrinsicAnimationActivity
=
725 createDrawingLayerAnimActivity(
731 if( pShape
->hasHyperlinks() )
732 rContext
.mpSubsettableShapeManager
->addHyperlinkArea( pShape
);
737 DrawShapeSharedPtr
DrawShape::create(
738 const uno::Reference
< drawing::XShape
>& xShape
,
739 const uno::Reference
< drawing::XDrawPage
>& xContainingPage
,
741 const Graphic
& rGraphic
,
742 const SlideShowContext
& rContext
)
744 DrawShapeSharedPtr
pShape( new DrawShape(xShape
,
750 if( pShape
->hasIntrinsicAnimation() )
752 OSL_ASSERT( !pShape
->maAnimationFrames
.empty() );
754 std::vector
<double> aTimeout
;
756 pShape
->maAnimationFrames
.begin(),
757 pShape
->maAnimationFrames
.end(),
758 std::back_insert_iterator
< std::vector
<double> >( aTimeout
),
759 boost::mem_fn(&MtfAnimationFrame::getDuration
) );
761 WakeupEventSharedPtr
pWakeupEvent(
762 new WakeupEvent( rContext
.mrEventQueue
.getTimer(),
763 rContext
.mrActivitiesQueue
) );
765 ActivitySharedPtr pActivity
=
766 createIntrinsicAnimationActivity(
771 pShape
->mnAnimationLoopCount
,
772 pShape
->meCycleMode
);
774 pWakeupEvent
->setActivity( pActivity
);
775 pShape
->mpIntrinsicAnimationActivity
= pActivity
;
778 OSL_ENSURE( !pShape
->hasHyperlinks(),
779 "DrawShape::create(): graphic-only shapes must not have hyperlinks!" );
784 DrawShape::~DrawShape()
788 // dispose intrinsic animation activity, else, it will
790 ActivitySharedPtr
pActivity( mpIntrinsicAnimationActivity
.lock() );
792 pActivity
->dispose();
794 catch (uno::Exception
&)
796 OSL_ENSURE( false, rtl::OUStringToOString(
797 comphelper::anyToString(
798 cppu::getCaughtException() ),
799 RTL_TEXTENCODING_UTF8
).getStr() );
803 uno::Reference
< drawing::XShape
> DrawShape::getXShape() const
808 void DrawShape::addViewLayer( const ViewLayerSharedPtr
& rNewLayer
,
811 ViewShapeVector::iterator
aEnd( maViewShapes
.end() );
814 if( ::std::find_if( maViewShapes
.begin(),
817 ::std::equal_to
< ViewLayerSharedPtr
>(),
818 ::boost::bind( &ViewShape::getViewLayer
,
820 ::boost::cref( rNewLayer
) ) ) != aEnd
)
822 // yes, nothing to do
826 ViewShapeSharedPtr
pNewShape( new ViewShape( rNewLayer
) );
828 maViewShapes
.push_back( pNewShape
);
830 // pass on animation state
831 if( mnIsAnimatedCount
)
833 for( int i
=0; i
<mnIsAnimatedCount
; ++i
)
834 pNewShape
->enterAnimationMode();
837 // render the Shape on the newly added ViewLayer
840 pNewShape
->update( mpCurrMtf
,
847 bool DrawShape::removeViewLayer( const ViewLayerSharedPtr
& rLayer
)
849 const ViewShapeVector::iterator
aEnd( maViewShapes
.end() );
851 OSL_ENSURE( ::std::count_if(maViewShapes
.begin(),
854 ::std::equal_to
< ViewLayerSharedPtr
>(),
855 ::boost::bind( &ViewShape::getViewLayer
,
857 ::boost::cref( rLayer
) ) ) < 2,
858 "DrawShape::removeViewLayer(): Duplicate ViewLayer entries!" );
860 ViewShapeVector::iterator aIter
;
862 if( (aIter
=::std::remove_if( maViewShapes
.begin(),
865 ::std::equal_to
< ViewLayerSharedPtr
>(),
866 ::boost::bind( &ViewShape::getViewLayer
,
868 ::boost::cref( rLayer
) ) )) == aEnd
)
870 // view layer seemingly was not added, failed
874 // actually erase from container
875 maViewShapes
.erase( aIter
, aEnd
);
880 bool DrawShape::clearAllViewLayers()
882 maViewShapes
.clear();
886 bool DrawShape::update() const
894 return implRender( getUpdateFlags() );
898 bool DrawShape::render() const
900 // force redraw. Have to also pass on the update flags,
901 // because e.g. content update (regeneration of the
902 // metafile renderer) is normally not performed. A simple
903 // ViewShape::FORCE would only paint the metafile in its
905 return implRender( ViewShape::FORCE
| getUpdateFlags() );
908 bool DrawShape::isContentChanged() const
910 return mbForceUpdate
?
912 getUpdateFlags() != ViewShape::NONE
;
916 ::basegfx::B2DRectangle
DrawShape::getBounds() const
918 // little optimization: for non-modified shapes, we don't
919 // create an ShapeAttributeStack, and therefore also don't
921 return getShapePosSize( maBounds
,
925 ::basegfx::B2DRectangle
DrawShape::getDomBounds() const
932 /** Functor expanding AA border for each passed ViewShape
934 Could not use ::boost::bind here, since
935 B2DRange::expand is overloaded (which yields one or
936 the other template type deduction ambiguous)
941 Expander( ::basegfx::B2DSize
& rBounds
) :
946 void operator()( const ViewShapeSharedPtr
& rShape
) const
948 const ::basegfx::B2DSize
& rShapeBorder( rShape
->getAntialiasingBorder() );
961 ::basegfx::B2DSize
& mrBounds
;
965 ::basegfx::B2DRectangle
DrawShape::getUpdateArea() const
967 ::basegfx::B2DRectangle aBounds
;
969 // an already empty shape bound need no further
970 // treatment. In fact, any changes applied below would
971 // actually remove the special empty state, thus, don't
973 if( !maBounds
.isEmpty() )
975 basegfx::B2DRectangle
aUnitBounds(0.0,0.0,1.0,1.0);
977 if( !maViewShapes
.empty() )
978 aUnitBounds
= getActualUnitShapeBounds();
980 if( !aUnitBounds
.isEmpty() )
982 if( mpAttributeLayer
)
984 // calc actual shape area (in user coordinate
985 // space) from the transformation as given by the
986 // shape attribute layer
987 aBounds
= getShapeUpdateArea( aUnitBounds
,
988 getShapeTransformation( getBounds(),
994 // no attribute layer, thus, the true shape bounds
995 // can be directly derived from the XShape bound
997 aBounds
= getShapeUpdateArea( aUnitBounds
,
1001 if( !maViewShapes
.empty() )
1003 // determine border needed for antialiasing the shape
1004 ::basegfx::B2DSize
aAABorder(0.0,0.0);
1006 // for every view, get AA border and 'expand' aAABorder
1008 ::std::for_each( maViewShapes
.begin(),
1010 Expander( aAABorder
) );
1012 // add calculated AA border to aBounds
1013 aBounds
= ::basegfx::B2DRectangle( aBounds
.getMinX() - aAABorder
.getX(),
1014 aBounds
.getMinY() - aAABorder
.getY(),
1015 aBounds
.getMaxX() + aAABorder
.getX(),
1016 aBounds
.getMaxY() + aAABorder
.getY() );
1024 bool DrawShape::isVisible() const
1026 bool bIsVisible( mbIsVisible
);
1028 if( mpAttributeLayer
)
1030 // check whether visibility and alpha are not default
1031 // (mpAttributeLayer->isVisibilityValid() returns true
1032 // then): bVisible becomes true, if shape visibility
1033 // is on and alpha is not 0.0 (fully transparent)
1034 if( mpAttributeLayer
->isVisibilityValid() )
1035 bIsVisible
= mpAttributeLayer
->getVisibility();
1037 // only touch bIsVisible, if the shape is still
1038 // visible - if getVisibility already made us
1039 // invisible, no alpha value will make us appear
1041 if( bIsVisible
&& mpAttributeLayer
->isAlphaValid() )
1042 bIsVisible
= !::basegfx::fTools::equalZero( mpAttributeLayer
->getAlpha() );
1048 double DrawShape::getPriority() const
1053 bool DrawShape::isBackgroundDetached() const
1055 return mnIsAnimatedCount
> 0;
1058 bool DrawShape::hasIntrinsicAnimation() const
1060 return (!maAnimationFrames
.empty() || mbDrawingLayerAnim
);
1063 bool DrawShape::setIntrinsicAnimationFrame( ::std::size_t nCurrFrame
)
1065 ENSURE_OR_RETURN( nCurrFrame
< maAnimationFrames
.size(),
1066 "DrawShape::setIntrinsicAnimationFrame(): frame index out of bounds" );
1068 if( mnCurrFrame
!= nCurrFrame
)
1070 mnCurrFrame
= nCurrFrame
;
1071 mpCurrMtf
= maAnimationFrames
[ mnCurrFrame
].mpMtf
;
1072 mbForceUpdate
= true;
1078 // hyperlink support
1079 void DrawShape::prepareHyperlinkIndices() const
1081 if ( !maHyperlinkIndices
.empty())
1083 maHyperlinkIndices
.clear();
1084 maHyperlinkRegions
.clear();
1087 sal_Int32 nIndex
= 0;
1088 for ( MetaAction
* pCurrAct
= mpCurrMtf
->FirstAction();
1089 pCurrAct
!= 0; pCurrAct
= mpCurrMtf
->NextAction() )
1091 if (pCurrAct
->GetType() == META_COMMENT_ACTION
) {
1092 MetaCommentAction
* pAct
=
1093 static_cast<MetaCommentAction
*>(pCurrAct
);
1094 // skip comment if not a special XTEXT comment
1095 if (pAct
->GetComment().CompareIgnoreCaseToAscii(
1096 RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_BEGIN") ) ==
1098 // e.g. date field doesn't have data!
1099 // currently assuming that only url field, this is
1100 // somehow fragile! xxx todo if possible
1101 pAct
->GetData() != 0 &&
1102 pAct
->GetDataSize() > 0)
1104 if (!maHyperlinkIndices
.empty() &&
1105 maHyperlinkIndices
.back().second
== -1) {
1106 OSL_ENSURE( false, "### pending FIELD_SEQ_END!" );
1107 maHyperlinkIndices
.pop_back();
1108 maHyperlinkRegions
.pop_back();
1110 maHyperlinkIndices
.push_back(
1111 HyperlinkIndexPair( nIndex
+ 1,
1112 -1 /* to be filled below */ ) );
1113 maHyperlinkRegions
.push_back(
1115 basegfx::B2DRectangle(),
1117 reinterpret_cast<sal_Unicode
const*>(
1119 pAct
->GetDataSize() / sizeof(sal_Unicode
) )
1122 else if (pAct
->GetComment().CompareIgnoreCaseToAscii(
1123 RTL_CONSTASCII_STRINGPARAM("FIELD_SEQ_END")) ==
1125 // pending end is expected:
1126 !maHyperlinkIndices
.empty() &&
1127 maHyperlinkIndices
.back().second
== -1)
1129 maHyperlinkIndices
.back().second
= nIndex
;
1134 nIndex
+= getNextActionOffset(pCurrAct
);
1136 if (!maHyperlinkIndices
.empty() &&
1137 maHyperlinkIndices
.back().second
== -1) {
1138 OSL_ENSURE( false, "### pending FIELD_SEQ_END!" );
1139 maHyperlinkIndices
.pop_back();
1140 maHyperlinkRegions
.pop_back();
1142 OSL_ASSERT( maHyperlinkIndices
.size() == maHyperlinkRegions
.size());
1145 bool DrawShape::hasHyperlinks() const
1147 return ! maHyperlinkRegions
.empty();
1150 HyperlinkArea::HyperlinkRegions
DrawShape::getHyperlinkRegions() const
1152 OSL_ASSERT( !maViewShapes
.empty() );
1155 return HyperlinkArea::HyperlinkRegions();
1157 // late init, determine regions:
1158 if( !maHyperlinkRegions
.empty() &&
1159 !maViewShapes
.empty() &&
1160 // region already inited?
1161 maHyperlinkRegions
.front().first
.getWidth() == 0 &&
1162 maHyperlinkRegions
.front().first
.getHeight() == 0 &&
1163 maHyperlinkRegions
.size() == maHyperlinkIndices
.size() )
1165 // TODO(Q2): Although this _is_ currently
1166 // view-agnostic, it might not stay like that.
1167 ViewShapeSharedPtr
const& pViewShape
= maViewShapes
.front();
1168 cppcanvas::CanvasSharedPtr
const pCanvas(
1169 pViewShape
->getViewLayer()->getCanvas() );
1171 // reuse Renderer of first view shape:
1172 cppcanvas::RendererSharedPtr
const pRenderer(
1173 pViewShape
->getRenderer(
1174 pCanvas
, mpCurrMtf
, mpAttributeLayer
) );
1176 OSL_ASSERT( pRenderer
);
1180 basegfx::B2DHomMatrix
const aOldTransform(
1181 pCanvas
->getTransformation() );
1182 basegfx::B2DHomMatrix aTransform
;
1183 pCanvas
->setTransformation( aTransform
/* empty */ );
1185 comphelper::ScopeGuard
const resetOldTransformation(
1186 boost::bind( &cppcanvas::Canvas::setTransformation
,
1188 boost::cref(aOldTransform
) ));
1190 aTransform
.scale( maBounds
.getWidth(),
1191 maBounds
.getHeight() );
1192 pRenderer
->setTransformation( aTransform
);
1193 pRenderer
->setClip();
1195 for( std::size_t pos
= maHyperlinkRegions
.size(); pos
--; )
1198 HyperlinkIndexPair
const& rIndices
= maHyperlinkIndices
[pos
];
1199 basegfx::B2DRectangle
const region(
1200 pRenderer
->getSubsetArea( rIndices
.first
,
1202 maHyperlinkRegions
[pos
].first
= region
;
1207 // shift shape-relative hyperlink regions to
1208 // slide-absolute position
1210 HyperlinkRegions aTranslatedRegions
;
1211 const basegfx::B2DPoint
& rOffset(getBounds().getMinimum());
1212 HyperlinkRegions::const_iterator
aIter( maHyperlinkRegions
.begin() );
1213 HyperlinkRegions::const_iterator
const aEnd ( maHyperlinkRegions
.end() );
1214 while( aIter
!= aEnd
)
1216 basegfx::B2DRange
const& relRegion( aIter
->first
);
1217 aTranslatedRegions
.push_back(
1220 relRegion
.getMinimum() + rOffset
,
1221 relRegion
.getMaximum() + rOffset
),
1226 return aTranslatedRegions
;
1229 double DrawShape::getHyperlinkPriority() const
1231 return getPriority();
1235 // AnimatableShape methods
1236 // ======================================================
1238 void DrawShape::enterAnimationMode()
1240 OSL_ENSURE( !maViewShapes
.empty(),
1241 "DrawShape::enterAnimationMode(): called on DrawShape without views" );
1243 if( mnIsAnimatedCount
== 0 )
1245 // notify all ViewShapes, by calling their enterAnimationMode method.
1246 // We're now entering animation mode
1247 ::std::for_each( maViewShapes
.begin(),
1249 ::boost::mem_fn( &ViewShape::enterAnimationMode
) );
1252 ++mnIsAnimatedCount
;
1255 void DrawShape::leaveAnimationMode()
1257 OSL_ENSURE( !maViewShapes
.empty(),
1258 "DrawShape::leaveAnimationMode(): called on DrawShape without views" );
1260 --mnIsAnimatedCount
;
1262 if( mnIsAnimatedCount
== 0 )
1264 // notify all ViewShapes, by calling their leaveAnimationMode method.
1265 // we're now leaving animation mode
1266 ::std::for_each( maViewShapes
.begin(),
1268 ::boost::mem_fn( &ViewShape::leaveAnimationMode
) );
1273 // AttributableShape methods
1274 // ======================================================
1276 ShapeAttributeLayerSharedPtr
DrawShape::createAttributeLayer()
1278 // create new layer, with last as its new child
1279 mpAttributeLayer
.reset( new ShapeAttributeLayer( mpAttributeLayer
) );
1281 // Update the local state ids to reflect those of the new layer.
1284 return mpAttributeLayer
;
1287 bool DrawShape::revokeAttributeLayer( const ShapeAttributeLayerSharedPtr
& rLayer
)
1289 if( !mpAttributeLayer
)
1290 return false; // no layers
1292 if( mpAttributeLayer
== rLayer
)
1294 // it's the toplevel layer
1295 mpAttributeLayer
= mpAttributeLayer
->getChildLayer();
1297 // force content redraw, all state variables have
1299 mbAttributeLayerRevoked
= true;
1305 // pass on to the layer, to try its children
1306 return mpAttributeLayer
->revokeChildLayer( rLayer
);
1310 ShapeAttributeLayerSharedPtr
DrawShape::getTopmostAttributeLayer() const
1312 return mpAttributeLayer
;
1315 void DrawShape::setVisibility( bool bVisible
)
1317 if( mbIsVisible
!= bVisible
)
1319 mbIsVisible
= bVisible
;
1320 mbForceUpdate
= true;
1324 const DocTreeNodeSupplier
& DrawShape::getTreeNodeSupplier() const
1329 DocTreeNodeSupplier
& DrawShape::getTreeNodeSupplier()
1334 DocTreeNode
DrawShape::getSubsetNode() const
1336 ensureVerboseMtfComments();
1338 // forward to delegate
1339 return maSubsetting
.getSubsetNode();
1342 AttributableShapeSharedPtr
DrawShape::getSubset( const DocTreeNode
& rTreeNode
) const
1344 ENSURE_OR_THROW( (mnCurrMtfLoadFlags
& MTF_LOAD_VERBOSE_COMMENTS
) != 0,
1345 "DrawShape::getSubset(): subset query on shape with apparently no subsets" );
1347 // forward to delegate
1348 return maSubsetting
.getSubsetShape( rTreeNode
);
1351 bool DrawShape::createSubset( AttributableShapeSharedPtr
& o_rSubset
,
1352 const DocTreeNode
& rTreeNode
)
1354 ENSURE_OR_THROW( (mnCurrMtfLoadFlags
& MTF_LOAD_VERBOSE_COMMENTS
) != 0,
1355 "DrawShape::createSubset(): subset query on shape with apparently no subsets" );
1357 // subset shape already created for this DocTreeNode?
1358 AttributableShapeSharedPtr
pSubset( maSubsetting
.getSubsetShape( rTreeNode
) );
1360 // when true, this method has created a new subset
1362 bool bNewlyCreated( false );
1366 o_rSubset
= pSubset
;
1368 // reusing existing subset
1372 // not yet created, init entry
1373 o_rSubset
.reset( new DrawShape( *this,
1375 // TODO(Q3): That's a
1377 // that start and end
1378 // index will always
1379 // be less than 65535
1381 rTreeNode
.getStartIndex()/double(SAL_MAX_INT16
) ));
1383 bNewlyCreated
= true; // subset newly created
1386 // always register shape at DrawShapeSubsetting, to keep
1387 // refcount up-to-date
1388 maSubsetting
.addSubsetShape( o_rSubset
);
1390 // flush bounds cache
1391 maCurrentShapeUnitBounds
.reset();
1393 return bNewlyCreated
;
1396 bool DrawShape::revokeSubset( const AttributableShapeSharedPtr
& rShape
)
1398 ENSURE_OR_THROW( (mnCurrMtfLoadFlags
& MTF_LOAD_VERBOSE_COMMENTS
) != 0,
1399 "DrawShape::createSubset(): subset query on shape with apparently no subsets" );
1401 // flush bounds cache
1402 maCurrentShapeUnitBounds
.reset();
1404 // forward to delegate
1405 if( maSubsetting
.revokeSubsetShape( rShape
) )
1407 // force redraw, our content has possibly changed (as
1408 // one of the subsets now display within our shape
1410 mbForceUpdate
= true;
1412 // #i47428# TEMP FIX: synchronize visibility of subset
1415 // TODO(F3): Remove here, and implement
1416 // TEXT_ONLY/BACKGROUND_ONLY with the proverbial
1417 // additional level of indirection: create a
1418 // persistent subset, containing all text/only the
1419 // background respectively. From _that_ object,
1420 // generate the temporary character subset shapes.
1421 const ShapeAttributeLayerSharedPtr
& rAttrLayer(
1422 rShape
->getTopmostAttributeLayer() );
1424 rAttrLayer
->isVisibilityValid() &&
1425 rAttrLayer
->getVisibility() != isVisible() )
1427 const bool bVisibility( rAttrLayer
->getVisibility() );
1429 // visibilities differ - adjust ours, then
1430 if( mpAttributeLayer
)
1431 mpAttributeLayer
->setVisibility( bVisibility
);
1433 mbIsVisible
= bVisibility
;
1444 sal_Int32
DrawShape::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType
) const // throw ShapeLoadFailedException
1446 ensureVerboseMtfComments();
1448 return maSubsetting
.getNumberOfTreeNodes( eNodeType
);
1451 DocTreeNode
DrawShape::getTreeNode( sal_Int32 nNodeIndex
,
1452 DocTreeNode::NodeType eNodeType
) const // throw ShapeLoadFailedException
1454 ensureVerboseMtfComments();
1456 if ( hasHyperlinks())
1458 prepareHyperlinkIndices();
1461 return maSubsetting
.getTreeNode( nNodeIndex
, eNodeType
);
1464 sal_Int32
DrawShape::getNumberOfSubsetTreeNodes ( const DocTreeNode
& rParentNode
,
1465 DocTreeNode::NodeType eNodeType
) const // throw ShapeLoadFailedException
1467 ensureVerboseMtfComments();
1469 return maSubsetting
.getNumberOfSubsetTreeNodes( rParentNode
, eNodeType
);
1472 DocTreeNode
DrawShape::getSubsetTreeNode( const DocTreeNode
& rParentNode
,
1473 sal_Int32 nNodeIndex
,
1474 DocTreeNode::NodeType eNodeType
) const // throw ShapeLoadFailedException
1476 ensureVerboseMtfComments();
1478 return maSubsetting
.getSubsetTreeNode( rParentNode
, nNodeIndex
, eNodeType
);