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