xref: /AOO41X/main/slideshow/source/engine/shapes/drawshapesubsetting.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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/math.hxx>
37*cdf0e10cSrcweir #include <rtl/logfile.hxx>
38*cdf0e10cSrcweir 
39*cdf0e10cSrcweir #include <vcl/metaact.hxx>
40*cdf0e10cSrcweir #include <vcl/gdimtf.hxx>
41*cdf0e10cSrcweir #include <basegfx/numeric/ftools.hxx>
42*cdf0e10cSrcweir 
43*cdf0e10cSrcweir #include "drawshapesubsetting.hxx"
44*cdf0e10cSrcweir #include "drawshape.hxx"
45*cdf0e10cSrcweir 
46*cdf0e10cSrcweir #include <boost/bind.hpp>
47*cdf0e10cSrcweir 
48*cdf0e10cSrcweir #include <algorithm>
49*cdf0e10cSrcweir #include <functional>
50*cdf0e10cSrcweir #include <limits>
51*cdf0e10cSrcweir 
52*cdf0e10cSrcweir using namespace ::com::sun::star;
53*cdf0e10cSrcweir 
54*cdf0e10cSrcweir 
55*cdf0e10cSrcweir namespace slideshow
56*cdf0e10cSrcweir {
57*cdf0e10cSrcweir     namespace internal
58*cdf0e10cSrcweir     {
59*cdf0e10cSrcweir 
60*cdf0e10cSrcweir         //////////////////////////////////////////////////////////////////////
61*cdf0e10cSrcweir         //
62*cdf0e10cSrcweir         // Private methods
63*cdf0e10cSrcweir         //
64*cdf0e10cSrcweir         //////////////////////////////////////////////////////////////////////
65*cdf0e10cSrcweir 
66*cdf0e10cSrcweir         void DrawShapeSubsetting::ensureInitializedNodeTree() const
67*cdf0e10cSrcweir         {
68*cdf0e10cSrcweir             ENSURE_OR_THROW( mpMtf,
69*cdf0e10cSrcweir                               "DrawShapeSubsetting::ensureInitializedNodeTree(): Invalid mtf" );
70*cdf0e10cSrcweir 
71*cdf0e10cSrcweir             if( mbNodeTreeInitialized )
72*cdf0e10cSrcweir                 return; // done, already initialized.
73*cdf0e10cSrcweir 
74*cdf0e10cSrcweir             // init doctree vector
75*cdf0e10cSrcweir             maActionClassVector.clear();
76*cdf0e10cSrcweir             maActionClassVector.reserve( mpMtf->GetActionCount() );
77*cdf0e10cSrcweir 
78*cdf0e10cSrcweir             // search metafile for text output
79*cdf0e10cSrcweir             MetaAction* pCurrAct;
80*cdf0e10cSrcweir 
81*cdf0e10cSrcweir             sal_Int32 nActionIndex(0);
82*cdf0e10cSrcweir             sal_Int32 nLastTextActionIndex(0);
83*cdf0e10cSrcweir             for( pCurrAct = mpMtf->FirstAction(); pCurrAct; pCurrAct = mpMtf->NextAction() )
84*cdf0e10cSrcweir             {
85*cdf0e10cSrcweir                 // check for one of our special text doctree comments
86*cdf0e10cSrcweir                 switch( pCurrAct->GetType() )
87*cdf0e10cSrcweir                 {
88*cdf0e10cSrcweir                     case META_COMMENT_ACTION:
89*cdf0e10cSrcweir                     {
90*cdf0e10cSrcweir                         MetaCommentAction* pAct = static_cast<MetaCommentAction*>(pCurrAct);
91*cdf0e10cSrcweir 
92*cdf0e10cSrcweir                         // skip comment if not a special XTEXT comment
93*cdf0e10cSrcweir                         if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT", 5 ) == COMPARE_EQUAL )
94*cdf0e10cSrcweir                         {
95*cdf0e10cSrcweir                             // fill classification vector with NOOPs,
96*cdf0e10cSrcweir                             // then insert corresponding classes at
97*cdf0e10cSrcweir                             // the given index
98*cdf0e10cSrcweir                             maActionClassVector.resize( nActionIndex+1, CLASS_NOOP );
99*cdf0e10cSrcweir 
100*cdf0e10cSrcweir                             if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOC" ) == COMPARE_EQUAL )
101*cdf0e10cSrcweir                             {
102*cdf0e10cSrcweir                                 // special, because can happen
103*cdf0e10cSrcweir                                 // in-between of portions - set
104*cdf0e10cSrcweir                                 // character-end classificator at
105*cdf0e10cSrcweir                                 // given index (relative to last text
106*cdf0e10cSrcweir                                 // action).
107*cdf0e10cSrcweir                                 const sal_Int32 nIndex( nLastTextActionIndex + pAct->GetValue() );
108*cdf0e10cSrcweir 
109*cdf0e10cSrcweir                                 ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex) < maActionClassVector.size(),
110*cdf0e10cSrcweir                                                   "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
111*cdf0e10cSrcweir 
112*cdf0e10cSrcweir                                 maActionClassVector[ nIndex ] = CLASS_CHARACTER_CELL_END;
113*cdf0e10cSrcweir                             }
114*cdf0e10cSrcweir                             else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOW" ) == COMPARE_EQUAL )
115*cdf0e10cSrcweir                             {
116*cdf0e10cSrcweir                                 // special, because can happen
117*cdf0e10cSrcweir                                 // in-between of portions - set
118*cdf0e10cSrcweir                                 // word-end classificator at given
119*cdf0e10cSrcweir                                 // index (relative to last text
120*cdf0e10cSrcweir                                 // action).
121*cdf0e10cSrcweir                                 const sal_Int32 nIndex( nLastTextActionIndex + pAct->GetValue() );
122*cdf0e10cSrcweir 
123*cdf0e10cSrcweir                                 ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex) < maActionClassVector.size(),
124*cdf0e10cSrcweir                                                   "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
125*cdf0e10cSrcweir 
126*cdf0e10cSrcweir                                 maActionClassVector[ nIndex ] = CLASS_WORD_END;
127*cdf0e10cSrcweir                             }
128*cdf0e10cSrcweir                             else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOS" ) == COMPARE_EQUAL )
129*cdf0e10cSrcweir                             {
130*cdf0e10cSrcweir                                 // special, because can happen
131*cdf0e10cSrcweir                                 // in-between of portions - set
132*cdf0e10cSrcweir                                 // sentence-end classificator at given
133*cdf0e10cSrcweir                                 // index (relative to last text
134*cdf0e10cSrcweir                                 // action).
135*cdf0e10cSrcweir                                 const sal_Int32 nIndex( nLastTextActionIndex + pAct->GetValue() );
136*cdf0e10cSrcweir 
137*cdf0e10cSrcweir                                 ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex) < maActionClassVector.size(),
138*cdf0e10cSrcweir                                                   "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
139*cdf0e10cSrcweir 
140*cdf0e10cSrcweir                                 maActionClassVector[ nIndex ] = CLASS_SENTENCE_END;
141*cdf0e10cSrcweir                             }
142*cdf0e10cSrcweir                             else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOL" ) == COMPARE_EQUAL )
143*cdf0e10cSrcweir                             {
144*cdf0e10cSrcweir                                 maActionClassVector[ nActionIndex ] = CLASS_LINE_END;
145*cdf0e10cSrcweir                             }
146*cdf0e10cSrcweir                             else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_EOP" ) == COMPARE_EQUAL )
147*cdf0e10cSrcweir                             {
148*cdf0e10cSrcweir                                 maActionClassVector[ nActionIndex ] = CLASS_PARAGRAPH_END;
149*cdf0e10cSrcweir                             }
150*cdf0e10cSrcweir                             else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_PAINTSHAPE_END" ) == COMPARE_EQUAL )
151*cdf0e10cSrcweir                             {
152*cdf0e10cSrcweir                                 maActionClassVector[ nActionIndex ] = CLASS_SHAPE_END;
153*cdf0e10cSrcweir                             }
154*cdf0e10cSrcweir                             else if( pAct->GetComment().CompareIgnoreCaseToAscii( "XTEXT_PAINTSHAPE_BEGIN" ) == COMPARE_EQUAL )
155*cdf0e10cSrcweir                             {
156*cdf0e10cSrcweir                                 maActionClassVector[ nActionIndex ] = CLASS_SHAPE_START;
157*cdf0e10cSrcweir                             }
158*cdf0e10cSrcweir                         }
159*cdf0e10cSrcweir                         ++nActionIndex;
160*cdf0e10cSrcweir                         break;
161*cdf0e10cSrcweir                     }
162*cdf0e10cSrcweir                     case META_TEXT_ACTION:
163*cdf0e10cSrcweir                     case META_TEXTARRAY_ACTION:
164*cdf0e10cSrcweir                     case META_STRETCHTEXT_ACTION:
165*cdf0e10cSrcweir                         nLastTextActionIndex = nActionIndex;
166*cdf0e10cSrcweir                         // fallthrough intended
167*cdf0e10cSrcweir                     default:
168*cdf0e10cSrcweir                         // comment action and all actions not
169*cdf0e10cSrcweir                         // explicitely handled here:
170*cdf0e10cSrcweir                         nActionIndex += getNextActionOffset(pCurrAct);
171*cdf0e10cSrcweir                         break;
172*cdf0e10cSrcweir                 }
173*cdf0e10cSrcweir             }
174*cdf0e10cSrcweir 
175*cdf0e10cSrcweir             mbNodeTreeInitialized = true;
176*cdf0e10cSrcweir         }
177*cdf0e10cSrcweir 
178*cdf0e10cSrcweir         void DrawShapeSubsetting::updateSubsetBounds( const SubsetEntry& rSubsetEntry )
179*cdf0e10cSrcweir         {
180*cdf0e10cSrcweir             // TODO(F1): This removes too much from non-contiguous subsets
181*cdf0e10cSrcweir             mnMinSubsetActionIndex = ::std::min(
182*cdf0e10cSrcweir                 mnMinSubsetActionIndex,
183*cdf0e10cSrcweir                 rSubsetEntry.mnStartActionIndex );
184*cdf0e10cSrcweir             mnMaxSubsetActionIndex = ::std::max(
185*cdf0e10cSrcweir                 mnMaxSubsetActionIndex,
186*cdf0e10cSrcweir                 rSubsetEntry.mnEndActionIndex );
187*cdf0e10cSrcweir         }
188*cdf0e10cSrcweir 
189*cdf0e10cSrcweir         void DrawShapeSubsetting::updateSubsets()
190*cdf0e10cSrcweir         {
191*cdf0e10cSrcweir             maCurrentSubsets.clear();
192*cdf0e10cSrcweir 
193*cdf0e10cSrcweir             if( !maSubsetShapes.empty() )
194*cdf0e10cSrcweir             {
195*cdf0e10cSrcweir                 if( maSubset.isEmpty() )
196*cdf0e10cSrcweir                 {
197*cdf0e10cSrcweir                     // non-subsetted node, with some child subsets
198*cdf0e10cSrcweir                     // that subtract from it
199*cdf0e10cSrcweir                     maCurrentSubsets.push_back( DocTreeNode( 0,
200*cdf0e10cSrcweir                                                              mnMinSubsetActionIndex,
201*cdf0e10cSrcweir                                                              DocTreeNode::NODETYPE_INVALID ) );
202*cdf0e10cSrcweir                     maCurrentSubsets.push_back( DocTreeNode( mnMaxSubsetActionIndex,
203*cdf0e10cSrcweir                                                              maActionClassVector.size(),
204*cdf0e10cSrcweir                                                              DocTreeNode::NODETYPE_INVALID ) );
205*cdf0e10cSrcweir                 }
206*cdf0e10cSrcweir                 else
207*cdf0e10cSrcweir                 {
208*cdf0e10cSrcweir                     // subsetted node, from which some further child
209*cdf0e10cSrcweir                     // subsets subtract content
210*cdf0e10cSrcweir                     maCurrentSubsets.push_back( DocTreeNode( maSubset.getStartIndex(),
211*cdf0e10cSrcweir                                                              mnMinSubsetActionIndex,
212*cdf0e10cSrcweir                                                              DocTreeNode::NODETYPE_INVALID ) );
213*cdf0e10cSrcweir                     maCurrentSubsets.push_back( DocTreeNode( mnMaxSubsetActionIndex,
214*cdf0e10cSrcweir                                                              maSubset.getEndIndex(),
215*cdf0e10cSrcweir                                                              DocTreeNode::NODETYPE_INVALID ) );
216*cdf0e10cSrcweir                 }
217*cdf0e10cSrcweir             }
218*cdf0e10cSrcweir             else
219*cdf0e10cSrcweir             {
220*cdf0e10cSrcweir                 // no further child subsets, simply add our subset (if any)
221*cdf0e10cSrcweir                 if( !maSubset.isEmpty() )
222*cdf0e10cSrcweir                 {
223*cdf0e10cSrcweir                     // subsetted node, without any subset children
224*cdf0e10cSrcweir                     maCurrentSubsets.push_back( maSubset );
225*cdf0e10cSrcweir                 }
226*cdf0e10cSrcweir             }
227*cdf0e10cSrcweir         }
228*cdf0e10cSrcweir 
229*cdf0e10cSrcweir         //////////////////////////////////////////////////////////////////////
230*cdf0e10cSrcweir         //
231*cdf0e10cSrcweir         // Public methods
232*cdf0e10cSrcweir         //
233*cdf0e10cSrcweir         //////////////////////////////////////////////////////////////////////
234*cdf0e10cSrcweir 
235*cdf0e10cSrcweir         DrawShapeSubsetting::DrawShapeSubsetting() :
236*cdf0e10cSrcweir             maActionClassVector(),
237*cdf0e10cSrcweir             mpMtf(),
238*cdf0e10cSrcweir             maSubset(),
239*cdf0e10cSrcweir             maSubsetShapes(),
240*cdf0e10cSrcweir             mnMinSubsetActionIndex( SAL_MAX_INT32 ),
241*cdf0e10cSrcweir             mnMaxSubsetActionIndex(0),
242*cdf0e10cSrcweir             maCurrentSubsets(),
243*cdf0e10cSrcweir             mbNodeTreeInitialized( false )
244*cdf0e10cSrcweir         {
245*cdf0e10cSrcweir         }
246*cdf0e10cSrcweir 
247*cdf0e10cSrcweir         DrawShapeSubsetting::DrawShapeSubsetting( const GDIMetaFileSharedPtr& rMtf ) :
248*cdf0e10cSrcweir             maActionClassVector(),
249*cdf0e10cSrcweir             mpMtf( rMtf ),
250*cdf0e10cSrcweir             maSubset(),
251*cdf0e10cSrcweir             maSubsetShapes(),
252*cdf0e10cSrcweir             mnMinSubsetActionIndex( SAL_MAX_INT32 ),
253*cdf0e10cSrcweir             mnMaxSubsetActionIndex(0),
254*cdf0e10cSrcweir             maCurrentSubsets(),
255*cdf0e10cSrcweir             mbNodeTreeInitialized( false )
256*cdf0e10cSrcweir         {
257*cdf0e10cSrcweir             ENSURE_OR_THROW( mpMtf,
258*cdf0e10cSrcweir                               "DrawShapeSubsetting::DrawShapeSubsetting(): Invalid metafile" );
259*cdf0e10cSrcweir 
260*cdf0e10cSrcweir             initCurrentSubsets();
261*cdf0e10cSrcweir         }
262*cdf0e10cSrcweir 
263*cdf0e10cSrcweir         DrawShapeSubsetting::DrawShapeSubsetting( const DocTreeNode&			rShapeSubset,
264*cdf0e10cSrcweir                                                   const GDIMetaFileSharedPtr&	rMtf ) :
265*cdf0e10cSrcweir             maActionClassVector(),
266*cdf0e10cSrcweir             mpMtf( rMtf ),
267*cdf0e10cSrcweir             maSubset( rShapeSubset ),
268*cdf0e10cSrcweir             maSubsetShapes(),
269*cdf0e10cSrcweir             mnMinSubsetActionIndex( SAL_MAX_INT32 ),
270*cdf0e10cSrcweir             mnMaxSubsetActionIndex(0),
271*cdf0e10cSrcweir             maCurrentSubsets(),
272*cdf0e10cSrcweir             mbNodeTreeInitialized( false )
273*cdf0e10cSrcweir         {
274*cdf0e10cSrcweir             ENSURE_OR_THROW( mpMtf,
275*cdf0e10cSrcweir                               "DrawShapeSubsetting::DrawShapeSubsetting(): Invalid metafile" );
276*cdf0e10cSrcweir 
277*cdf0e10cSrcweir             initCurrentSubsets();
278*cdf0e10cSrcweir         }
279*cdf0e10cSrcweir 
280*cdf0e10cSrcweir         void DrawShapeSubsetting::reset()
281*cdf0e10cSrcweir         {
282*cdf0e10cSrcweir             maActionClassVector.clear();
283*cdf0e10cSrcweir             mpMtf.reset();
284*cdf0e10cSrcweir             maSubset.reset();
285*cdf0e10cSrcweir             maSubsetShapes.clear();
286*cdf0e10cSrcweir             mnMinSubsetActionIndex = SAL_MAX_INT32;
287*cdf0e10cSrcweir             mnMaxSubsetActionIndex = 0;
288*cdf0e10cSrcweir             maCurrentSubsets.clear();
289*cdf0e10cSrcweir             mbNodeTreeInitialized = false;
290*cdf0e10cSrcweir         }
291*cdf0e10cSrcweir 
292*cdf0e10cSrcweir         void DrawShapeSubsetting::reset( const ::boost::shared_ptr< GDIMetaFile >& rMtf )
293*cdf0e10cSrcweir         {
294*cdf0e10cSrcweir             reset();
295*cdf0e10cSrcweir             mpMtf = rMtf;
296*cdf0e10cSrcweir 
297*cdf0e10cSrcweir             initCurrentSubsets();
298*cdf0e10cSrcweir         }
299*cdf0e10cSrcweir 
300*cdf0e10cSrcweir         void DrawShapeSubsetting::reset( const DocTreeNode&                          rShapeSubset,
301*cdf0e10cSrcweir                                          const ::boost::shared_ptr< GDIMetaFile >&   rMtf )
302*cdf0e10cSrcweir         {
303*cdf0e10cSrcweir             reset();
304*cdf0e10cSrcweir             mpMtf = rMtf;
305*cdf0e10cSrcweir             maSubset = rShapeSubset;
306*cdf0e10cSrcweir 
307*cdf0e10cSrcweir             initCurrentSubsets();
308*cdf0e10cSrcweir         }
309*cdf0e10cSrcweir 
310*cdf0e10cSrcweir         void DrawShapeSubsetting::initCurrentSubsets()
311*cdf0e10cSrcweir         {
312*cdf0e10cSrcweir             // only add subset to vector, if it's not empty - that's
313*cdf0e10cSrcweir             // because the vector's content is later literally used
314*cdf0e10cSrcweir             // for e.g. painting.
315*cdf0e10cSrcweir             if( !maSubset.isEmpty() )
316*cdf0e10cSrcweir                 maCurrentSubsets.push_back( maSubset );
317*cdf0e10cSrcweir         }
318*cdf0e10cSrcweir 
319*cdf0e10cSrcweir         DocTreeNode DrawShapeSubsetting::getSubsetNode() const
320*cdf0e10cSrcweir         {
321*cdf0e10cSrcweir             return maSubset;
322*cdf0e10cSrcweir         }
323*cdf0e10cSrcweir 
324*cdf0e10cSrcweir         bool DrawShapeSubsetting::hasSubsetShapes() const
325*cdf0e10cSrcweir         {
326*cdf0e10cSrcweir             return !maSubsetShapes.empty();
327*cdf0e10cSrcweir         }
328*cdf0e10cSrcweir 
329*cdf0e10cSrcweir         AttributableShapeSharedPtr DrawShapeSubsetting::getSubsetShape( const DocTreeNode& rTreeNode ) const
330*cdf0e10cSrcweir         {
331*cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShapeSubsetting::getSubsetShape()" );
332*cdf0e10cSrcweir 
333*cdf0e10cSrcweir             // subset shape already created for this DocTreeNode?
334*cdf0e10cSrcweir             SubsetEntry aEntry;
335*cdf0e10cSrcweir 
336*cdf0e10cSrcweir             aEntry.mnStartActionIndex 	= rTreeNode.getStartIndex();
337*cdf0e10cSrcweir             aEntry.mnEndActionIndex 	= rTreeNode.getEndIndex();
338*cdf0e10cSrcweir 
339*cdf0e10cSrcweir             ShapeSet::const_iterator aIter;
340*cdf0e10cSrcweir             if( (aIter=maSubsetShapes.find( aEntry )) != maSubsetShapes.end() )
341*cdf0e10cSrcweir             {
342*cdf0e10cSrcweir                 // already created, return found entry
343*cdf0e10cSrcweir                 return aIter->mpShape;
344*cdf0e10cSrcweir             }
345*cdf0e10cSrcweir 
346*cdf0e10cSrcweir             return AttributableShapeSharedPtr();
347*cdf0e10cSrcweir         }
348*cdf0e10cSrcweir 
349*cdf0e10cSrcweir         void DrawShapeSubsetting::addSubsetShape( const AttributableShapeSharedPtr& rShape )
350*cdf0e10cSrcweir         {
351*cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShapeSubsetting::addSubsetShape()" );
352*cdf0e10cSrcweir 
353*cdf0e10cSrcweir             // subset shape already created for this DocTreeNode?
354*cdf0e10cSrcweir             SubsetEntry aEntry;
355*cdf0e10cSrcweir             const DocTreeNode& rEffectiveSubset( rShape->getSubsetNode() );
356*cdf0e10cSrcweir 
357*cdf0e10cSrcweir             aEntry.mnStartActionIndex 	= rEffectiveSubset.getStartIndex();
358*cdf0e10cSrcweir             aEntry.mnEndActionIndex 	= rEffectiveSubset.getEndIndex();
359*cdf0e10cSrcweir 
360*cdf0e10cSrcweir             ShapeSet::const_iterator aIter;
361*cdf0e10cSrcweir             if( (aIter=maSubsetShapes.find( aEntry )) != maSubsetShapes.end() )
362*cdf0e10cSrcweir             {
363*cdf0e10cSrcweir                 // already created, increment use count and return
364*cdf0e10cSrcweir 
365*cdf0e10cSrcweir                 // safe cast, since set order does not depend on
366*cdf0e10cSrcweir                 // mnSubsetQueriedCount
367*cdf0e10cSrcweir                 const_cast<SubsetEntry&>(*aIter).mnSubsetQueriedCount++;
368*cdf0e10cSrcweir             }
369*cdf0e10cSrcweir             else
370*cdf0e10cSrcweir             {
371*cdf0e10cSrcweir                 // not yet created, init entry
372*cdf0e10cSrcweir                 aEntry.mnSubsetQueriedCount = 1;
373*cdf0e10cSrcweir                 aEntry.mpShape = rShape;
374*cdf0e10cSrcweir 
375*cdf0e10cSrcweir                 maSubsetShapes.insert( aEntry );
376*cdf0e10cSrcweir 
377*cdf0e10cSrcweir                 // update cached subset borders
378*cdf0e10cSrcweir                 updateSubsetBounds( aEntry );
379*cdf0e10cSrcweir                 updateSubsets();
380*cdf0e10cSrcweir             }
381*cdf0e10cSrcweir         }
382*cdf0e10cSrcweir 
383*cdf0e10cSrcweir         bool DrawShapeSubsetting::revokeSubsetShape( const AttributableShapeSharedPtr& rShape )
384*cdf0e10cSrcweir         {
385*cdf0e10cSrcweir             RTL_LOGFILE_CONTEXT( aLog, "::presentation::internal::DrawShapeSubsetting::revokeSubsetShape()" );
386*cdf0e10cSrcweir 
387*cdf0e10cSrcweir             // lookup subset shape
388*cdf0e10cSrcweir             SubsetEntry aEntry;
389*cdf0e10cSrcweir             const DocTreeNode& rEffectiveSubset( rShape->getSubsetNode() );
390*cdf0e10cSrcweir 
391*cdf0e10cSrcweir             aEntry.mnStartActionIndex 	= rEffectiveSubset.getStartIndex();
392*cdf0e10cSrcweir             aEntry.mnEndActionIndex 	= rEffectiveSubset.getEndIndex();
393*cdf0e10cSrcweir 
394*cdf0e10cSrcweir             ShapeSet::iterator aIter;
395*cdf0e10cSrcweir             if( (aIter=maSubsetShapes.find( aEntry )) == maSubsetShapes.end() )
396*cdf0e10cSrcweir                 return false; // not found, subset was never queried
397*cdf0e10cSrcweir 
398*cdf0e10cSrcweir             // last client of the subset revoking?
399*cdf0e10cSrcweir             if( aIter->mnSubsetQueriedCount > 1 )
400*cdf0e10cSrcweir             {
401*cdf0e10cSrcweir                 // no, still clients out there. Just decrement use count
402*cdf0e10cSrcweir                 // safe cast, since order does not depend on mnSubsetQueriedCount
403*cdf0e10cSrcweir                 const_cast<SubsetEntry&>(*aIter).mnSubsetQueriedCount--;
404*cdf0e10cSrcweir 
405*cdf0e10cSrcweir                 VERBOSE_TRACE( "Subset summary: shape 0x%X, %d open subsets, revoked subset has refcount %d",
406*cdf0e10cSrcweir                                this,
407*cdf0e10cSrcweir                                maSubsetShapes.size(),
408*cdf0e10cSrcweir                                aIter->mnSubsetQueriedCount );
409*cdf0e10cSrcweir 
410*cdf0e10cSrcweir                 return false; // not the last client
411*cdf0e10cSrcweir             }
412*cdf0e10cSrcweir 
413*cdf0e10cSrcweir             VERBOSE_TRACE( "Subset summary: shape 0x%X, %d open subsets, cleared subset has range [%d,%d]",
414*cdf0e10cSrcweir                            this,
415*cdf0e10cSrcweir                            maSubsetShapes.size(),
416*cdf0e10cSrcweir                            aEntry.mnStartActionIndex,
417*cdf0e10cSrcweir                            aEntry.mnEndActionIndex );
418*cdf0e10cSrcweir 
419*cdf0e10cSrcweir             // yes, remove from set
420*cdf0e10cSrcweir             maSubsetShapes.erase( aIter );
421*cdf0e10cSrcweir 
422*cdf0e10cSrcweir 
423*cdf0e10cSrcweir             // update currently active subset for _our_ shape (the
424*cdf0e10cSrcweir             // part of this shape that is visible, i.e. not displayed
425*cdf0e10cSrcweir             // in subset shapes)
426*cdf0e10cSrcweir             // ======================================================
427*cdf0e10cSrcweir 
428*cdf0e10cSrcweir             // init bounds
429*cdf0e10cSrcweir             mnMinSubsetActionIndex = SAL_MAX_INT32;
430*cdf0e10cSrcweir             mnMaxSubsetActionIndex = 0;
431*cdf0e10cSrcweir 
432*cdf0e10cSrcweir             // TODO(P2): This is quite expensive, when
433*cdf0e10cSrcweir             // after every subset effect end, we have to scan
434*cdf0e10cSrcweir             // the whole shape set
435*cdf0e10cSrcweir 
436*cdf0e10cSrcweir             // determine new subset range
437*cdf0e10cSrcweir             ::std::for_each( maSubsetShapes.begin(),
438*cdf0e10cSrcweir                              maSubsetShapes.end(),
439*cdf0e10cSrcweir                              ::boost::bind(&DrawShapeSubsetting::updateSubsetBounds,
440*cdf0e10cSrcweir                                            this,
441*cdf0e10cSrcweir                                            _1 ) );
442*cdf0e10cSrcweir 
443*cdf0e10cSrcweir             updateSubsets();
444*cdf0e10cSrcweir 
445*cdf0e10cSrcweir             return true;
446*cdf0e10cSrcweir         }
447*cdf0e10cSrcweir 
448*cdf0e10cSrcweir         namespace
449*cdf0e10cSrcweir         {
450*cdf0e10cSrcweir             /** Iterate over all action classification entries in the
451*cdf0e10cSrcweir                 given range, pass each element range found to the
452*cdf0e10cSrcweir                 given functor.
453*cdf0e10cSrcweir 
454*cdf0e10cSrcweir                 This method extracts, for each of the different action
455*cdf0e10cSrcweir                 classifications, the count and the ranges for each of
456*cdf0e10cSrcweir                 them, and calls the provided functor with that
457*cdf0e10cSrcweir                 information.
458*cdf0e10cSrcweir 
459*cdf0e10cSrcweir                 @tpl FunctorT
460*cdf0e10cSrcweir                 This is the functor's operator() calling signature,
461*cdf0e10cSrcweir                 with eCurrElemClassification denoting the current
462*cdf0e10cSrcweir                 classification type the functor is called for,
463*cdf0e10cSrcweir                 nCurrElemCount the running total of elements visited
464*cdf0e10cSrcweir                 for the given class (starting from 0), and
465*cdf0e10cSrcweir                 rCurrElemBegin/rCurrElemEnd the range of the current
466*cdf0e10cSrcweir                 element (i.e. the iterators from the start to the end
467*cdf0e10cSrcweir                 of this element).
468*cdf0e10cSrcweir                 <pre>
469*cdf0e10cSrcweir                 bool operator()( IndexClassificator								 eCurrElemClassification
470*cdf0e10cSrcweir                 				 sal_Int32										 nCurrElemCount,
471*cdf0e10cSrcweir 								 const IndexClassificatorVector::const_iterator& rCurrElemBegin,
472*cdf0e10cSrcweir 								 const IndexClassificatorVector::const_iterator& rCurrElemEnd );
473*cdf0e10cSrcweir                 </pre>
474*cdf0e10cSrcweir                 If the functor returns false, iteration over the
475*cdf0e10cSrcweir                 shapes is immediately stopped.
476*cdf0e10cSrcweir 
477*cdf0e10cSrcweir                 @param io_pFunctor
478*cdf0e10cSrcweir                 This functor is called for every shape found.
479*cdf0e10cSrcweir 
480*cdf0e10cSrcweir                 @param rBegin
481*cdf0e10cSrcweir                 Start of range to iterate over
482*cdf0e10cSrcweir 
483*cdf0e10cSrcweir                 @param rEnd
484*cdf0e10cSrcweir                 End of range to iterate over
485*cdf0e10cSrcweir 
486*cdf0e10cSrcweir                 @return the number of shapes found in the metafile
487*cdf0e10cSrcweir              */
488*cdf0e10cSrcweir             template< typename FunctorT > void iterateActionClassifications(
489*cdf0e10cSrcweir                 FunctorT& 															 io_rFunctor,
490*cdf0e10cSrcweir                 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rBegin,
491*cdf0e10cSrcweir                 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rEnd )
492*cdf0e10cSrcweir             {
493*cdf0e10cSrcweir                 sal_Int32 nCurrShapeCount( 0 );
494*cdf0e10cSrcweir                 sal_Int32 nCurrParaCount( 0 );
495*cdf0e10cSrcweir                 sal_Int32 nCurrLineCount( 0 );
496*cdf0e10cSrcweir                 sal_Int32 nCurrSentenceCount( 0 );
497*cdf0e10cSrcweir                 sal_Int32 nCurrWordCount( 0 );
498*cdf0e10cSrcweir                 sal_Int32 nCurrCharCount( 0 );
499*cdf0e10cSrcweir 
500*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastShapeStart(rBegin);
501*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastParaStart(rBegin);
502*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastLineStart(rBegin);
503*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastSentenceStart(rBegin);
504*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastWordStart(rBegin);
505*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aLastCharStart(rBegin);
506*cdf0e10cSrcweir 
507*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aNext;
508*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aCurr( rBegin );
509*cdf0e10cSrcweir                 while( aCurr != rEnd )
510*cdf0e10cSrcweir                 {
511*cdf0e10cSrcweir                     // aNext will hold an iterator to the next element
512*cdf0e10cSrcweir                     // (or the past-the-end iterator, if aCurr
513*cdf0e10cSrcweir                     // references the last element). Used to pass a
514*cdf0e10cSrcweir                     // valid half-open range to the functors.
515*cdf0e10cSrcweir                     aNext = aCurr;
516*cdf0e10cSrcweir                     ++aNext;
517*cdf0e10cSrcweir 
518*cdf0e10cSrcweir                     switch( *aCurr )
519*cdf0e10cSrcweir                     {
520*cdf0e10cSrcweir                         default:
521*cdf0e10cSrcweir                             ENSURE_OR_THROW( false,
522*cdf0e10cSrcweir                                               "Unexpected type in iterateDocShapes()" );
523*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_NOOP:
524*cdf0e10cSrcweir                             // ignore NOOP actions
525*cdf0e10cSrcweir                             break;
526*cdf0e10cSrcweir 
527*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_SHAPE_START:
528*cdf0e10cSrcweir                             // regardless of ending action
529*cdf0e10cSrcweir                             // classifications before: a new shape
530*cdf0e10cSrcweir                             // always also starts contained elements
531*cdf0e10cSrcweir                             // anew
532*cdf0e10cSrcweir                             aLastShapeStart    =
533*cdf0e10cSrcweir                             aLastParaStart     =
534*cdf0e10cSrcweir                             aLastLineStart     =
535*cdf0e10cSrcweir                             aLastSentenceStart =
536*cdf0e10cSrcweir                             aLastWordStart     =
537*cdf0e10cSrcweir                             aLastCharStart     = aCurr;
538*cdf0e10cSrcweir                             break;
539*cdf0e10cSrcweir 
540*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_SHAPE_END:
541*cdf0e10cSrcweir                             if( !io_rFunctor( DrawShapeSubsetting::CLASS_SHAPE_END,
542*cdf0e10cSrcweir                                               nCurrShapeCount,
543*cdf0e10cSrcweir                                               aLastShapeStart,
544*cdf0e10cSrcweir                                               aNext ) )
545*cdf0e10cSrcweir                             {
546*cdf0e10cSrcweir                                 return;
547*cdf0e10cSrcweir                             }
548*cdf0e10cSrcweir 
549*cdf0e10cSrcweir                             ++nCurrShapeCount;
550*cdf0e10cSrcweir                             // FALLTHROUGH intended: shape end also
551*cdf0e10cSrcweir                             // ends lines
552*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_PARAGRAPH_END:
553*cdf0e10cSrcweir                             if( !io_rFunctor( DrawShapeSubsetting::CLASS_PARAGRAPH_END,
554*cdf0e10cSrcweir                                               nCurrParaCount,
555*cdf0e10cSrcweir                                               aLastParaStart,
556*cdf0e10cSrcweir                                               aNext ) )
557*cdf0e10cSrcweir                             {
558*cdf0e10cSrcweir                                 return;
559*cdf0e10cSrcweir                             }
560*cdf0e10cSrcweir 
561*cdf0e10cSrcweir                             ++nCurrParaCount;
562*cdf0e10cSrcweir                             aLastParaStart = aNext;
563*cdf0e10cSrcweir                             // FALLTHROUGH intended: para end also
564*cdf0e10cSrcweir                             // ends line
565*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_LINE_END:
566*cdf0e10cSrcweir                             if( !io_rFunctor( DrawShapeSubsetting::CLASS_LINE_END,
567*cdf0e10cSrcweir                                               nCurrLineCount,
568*cdf0e10cSrcweir                                               aLastLineStart,
569*cdf0e10cSrcweir                                               aNext ) )
570*cdf0e10cSrcweir                             {
571*cdf0e10cSrcweir                                 return;
572*cdf0e10cSrcweir                             }
573*cdf0e10cSrcweir 
574*cdf0e10cSrcweir                             ++nCurrLineCount;
575*cdf0e10cSrcweir                             aLastLineStart = aNext;
576*cdf0e10cSrcweir 
577*cdf0e10cSrcweir                             if( *aCurr == DrawShapeSubsetting::CLASS_LINE_END )
578*cdf0e10cSrcweir                             {
579*cdf0e10cSrcweir                                 // DON'T fall through here, as a line
580*cdf0e10cSrcweir                                 // does NOT end neither a sentence,
581*cdf0e10cSrcweir                                 // nor a word. OTOH, all parent
582*cdf0e10cSrcweir                                 // structures (paragraph and shape),
583*cdf0e10cSrcweir                                 // which itself fall through to this
584*cdf0e10cSrcweir                                 // code, DO end word, sentence and
585*cdf0e10cSrcweir                                 // character cell.
586*cdf0e10cSrcweir 
587*cdf0e10cSrcweir                                 // TODO(F1): Maybe a line should end a
588*cdf0e10cSrcweir                                 // character cell, OTOH?
589*cdf0e10cSrcweir                                 break;
590*cdf0e10cSrcweir                             }
591*cdf0e10cSrcweir                             // FALLTHROUGH intended
592*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_SENTENCE_END:
593*cdf0e10cSrcweir                             if( !io_rFunctor( DrawShapeSubsetting::CLASS_SENTENCE_END,
594*cdf0e10cSrcweir                                               nCurrSentenceCount,
595*cdf0e10cSrcweir                                               aLastSentenceStart,
596*cdf0e10cSrcweir                                               aNext ) )
597*cdf0e10cSrcweir                             {
598*cdf0e10cSrcweir                                 return;
599*cdf0e10cSrcweir                             }
600*cdf0e10cSrcweir 
601*cdf0e10cSrcweir                             ++nCurrSentenceCount;
602*cdf0e10cSrcweir                             aLastSentenceStart = aNext;
603*cdf0e10cSrcweir                             // FALLTHROUGH intended
604*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_WORD_END:
605*cdf0e10cSrcweir                             if( !io_rFunctor( DrawShapeSubsetting::CLASS_WORD_END,
606*cdf0e10cSrcweir                                               nCurrWordCount,
607*cdf0e10cSrcweir                                               aLastWordStart,
608*cdf0e10cSrcweir                                               aNext ) )
609*cdf0e10cSrcweir                             {
610*cdf0e10cSrcweir                                 return;
611*cdf0e10cSrcweir                             }
612*cdf0e10cSrcweir 
613*cdf0e10cSrcweir                             ++nCurrWordCount;
614*cdf0e10cSrcweir                             aLastWordStart = aNext;
615*cdf0e10cSrcweir                             // FALLTHROUGH intended
616*cdf0e10cSrcweir                         case DrawShapeSubsetting::CLASS_CHARACTER_CELL_END:
617*cdf0e10cSrcweir                             if( !io_rFunctor( DrawShapeSubsetting::CLASS_CHARACTER_CELL_END,
618*cdf0e10cSrcweir                                               nCurrCharCount,
619*cdf0e10cSrcweir                                               aLastCharStart,
620*cdf0e10cSrcweir                                               aNext ) )
621*cdf0e10cSrcweir                             {
622*cdf0e10cSrcweir                                 return;
623*cdf0e10cSrcweir                             }
624*cdf0e10cSrcweir 
625*cdf0e10cSrcweir                             ++nCurrCharCount;
626*cdf0e10cSrcweir                             aLastCharStart = aNext;
627*cdf0e10cSrcweir                             break;
628*cdf0e10cSrcweir                     }
629*cdf0e10cSrcweir 
630*cdf0e10cSrcweir                     aCurr = aNext;
631*cdf0e10cSrcweir                 }
632*cdf0e10cSrcweir             }
633*cdf0e10cSrcweir 
634*cdf0e10cSrcweir             DrawShapeSubsetting::IndexClassificator mapDocTreeNode( DocTreeNode::NodeType eNodeType )
635*cdf0e10cSrcweir             {
636*cdf0e10cSrcweir                 switch( eNodeType )
637*cdf0e10cSrcweir                 {
638*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_INVALID:
639*cdf0e10cSrcweir                         // FALLTHROUGH intended
640*cdf0e10cSrcweir                     default:
641*cdf0e10cSrcweir                         OSL_ENSURE(false,
642*cdf0e10cSrcweir                                    "DrawShapeSubsetting::mapDocTreeNode(): unexpected node type");
643*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_NOOP;
644*cdf0e10cSrcweir 
645*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_LOGICAL_SHAPE:
646*cdf0e10cSrcweir                         // FALLTHROUGH intended
647*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_FORMATTING_SHAPE:
648*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_SHAPE_END;
649*cdf0e10cSrcweir 
650*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_FORMATTING_LINE:
651*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_LINE_END;
652*cdf0e10cSrcweir 
653*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH:
654*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_PARAGRAPH_END;
655*cdf0e10cSrcweir 
656*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_LOGICAL_SENTENCE:
657*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_SENTENCE_END;
658*cdf0e10cSrcweir 
659*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_LOGICAL_WORD:
660*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_WORD_END;
661*cdf0e10cSrcweir 
662*cdf0e10cSrcweir                     case DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL:
663*cdf0e10cSrcweir                         return DrawShapeSubsetting::CLASS_CHARACTER_CELL_END;
664*cdf0e10cSrcweir                 };
665*cdf0e10cSrcweir             }
666*cdf0e10cSrcweir 
667*cdf0e10cSrcweir             /// Counts number of class occurences
668*cdf0e10cSrcweir             class CountClassFunctor
669*cdf0e10cSrcweir             {
670*cdf0e10cSrcweir             public:
671*cdf0e10cSrcweir                 CountClassFunctor( DrawShapeSubsetting::IndexClassificator eClass ) :
672*cdf0e10cSrcweir                     meClass( eClass ),
673*cdf0e10cSrcweir                     mnCurrCount(0)
674*cdf0e10cSrcweir                 {
675*cdf0e10cSrcweir                 }
676*cdf0e10cSrcweir 
677*cdf0e10cSrcweir                 bool operator()( DrawShapeSubsetting::IndexClassificator								eCurrElemClassification,
678*cdf0e10cSrcweir                 				 sal_Int32																/*nCurrElemCount*/,
679*cdf0e10cSrcweir 								 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator&	/*rCurrElemBegin*/,
680*cdf0e10cSrcweir 								 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator&	/*rCurrElemEnd*/ )
681*cdf0e10cSrcweir                 {
682*cdf0e10cSrcweir                     if( eCurrElemClassification == meClass )
683*cdf0e10cSrcweir                         ++mnCurrCount;
684*cdf0e10cSrcweir 
685*cdf0e10cSrcweir                     return true; // never stop, count all occurences
686*cdf0e10cSrcweir                 }
687*cdf0e10cSrcweir 
688*cdf0e10cSrcweir                 sal_Int32 getCount() const
689*cdf0e10cSrcweir                 {
690*cdf0e10cSrcweir                     return mnCurrCount;
691*cdf0e10cSrcweir                 }
692*cdf0e10cSrcweir 
693*cdf0e10cSrcweir             private:
694*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificator meClass;
695*cdf0e10cSrcweir                 sal_Int32								mnCurrCount;
696*cdf0e10cSrcweir             };
697*cdf0e10cSrcweir         }
698*cdf0e10cSrcweir 
699*cdf0e10cSrcweir         sal_Int32 DrawShapeSubsetting::implGetNumberOfTreeNodes( const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rBegin,
700*cdf0e10cSrcweir                                                                  const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rEnd,
701*cdf0e10cSrcweir                                                                  DocTreeNode::NodeType 												  eNodeType ) const
702*cdf0e10cSrcweir         {
703*cdf0e10cSrcweir             const IndexClassificator eRequestedClass(
704*cdf0e10cSrcweir                 mapDocTreeNode( eNodeType ) );
705*cdf0e10cSrcweir 
706*cdf0e10cSrcweir             // create a counting functor for the requested class of
707*cdf0e10cSrcweir             // actions
708*cdf0e10cSrcweir             CountClassFunctor aFunctor( eRequestedClass );
709*cdf0e10cSrcweir 
710*cdf0e10cSrcweir             // count all occurences in the given range
711*cdf0e10cSrcweir             iterateActionClassifications( aFunctor, rBegin, rEnd );
712*cdf0e10cSrcweir 
713*cdf0e10cSrcweir             return aFunctor.getCount();
714*cdf0e10cSrcweir         }
715*cdf0e10cSrcweir 
716*cdf0e10cSrcweir         sal_Int32 DrawShapeSubsetting::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType ) const
717*cdf0e10cSrcweir         {
718*cdf0e10cSrcweir             ensureInitializedNodeTree();
719*cdf0e10cSrcweir 
720*cdf0e10cSrcweir             return implGetNumberOfTreeNodes( maActionClassVector.begin(),
721*cdf0e10cSrcweir                                              maActionClassVector.end(),
722*cdf0e10cSrcweir                                              eNodeType );
723*cdf0e10cSrcweir         }
724*cdf0e10cSrcweir 
725*cdf0e10cSrcweir         namespace
726*cdf0e10cSrcweir         {
727*cdf0e10cSrcweir             /** This functor finds the nth occurrence of a given
728*cdf0e10cSrcweir                 action class.
729*cdf0e10cSrcweir 
730*cdf0e10cSrcweir                 The operator() compares the given index value with the
731*cdf0e10cSrcweir                 requested index, as given on the functor's
732*cdf0e10cSrcweir                 constructor. Then, the operator() returns false,
733*cdf0e10cSrcweir                 denoting that the requested action is found.
734*cdf0e10cSrcweir              */
735*cdf0e10cSrcweir             class FindNthElementFunctor
736*cdf0e10cSrcweir             {
737*cdf0e10cSrcweir             public:
738*cdf0e10cSrcweir                 FindNthElementFunctor( sal_Int32 								nNodeIndex,
739*cdf0e10cSrcweir                                        DrawShapeSubsetting::IndexClassificator	eClass ) :
740*cdf0e10cSrcweir                     mnNodeIndex( nNodeIndex ),
741*cdf0e10cSrcweir                     meClass( eClass )
742*cdf0e10cSrcweir                 {
743*cdf0e10cSrcweir                 }
744*cdf0e10cSrcweir 
745*cdf0e10cSrcweir                 bool operator()( DrawShapeSubsetting::IndexClassificator								eCurrElemClassification,
746*cdf0e10cSrcweir                 				 sal_Int32																nCurrElemCount,
747*cdf0e10cSrcweir 								 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator&	rCurrElemBegin,
748*cdf0e10cSrcweir 								 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator&	rCurrElemEnd )
749*cdf0e10cSrcweir                 {
750*cdf0e10cSrcweir                     if( eCurrElemClassification == meClass &&
751*cdf0e10cSrcweir                         nCurrElemCount == mnNodeIndex )
752*cdf0e10cSrcweir                     {
753*cdf0e10cSrcweir                         maLastBegin = rCurrElemBegin;
754*cdf0e10cSrcweir                         maLastEnd = rCurrElemEnd;
755*cdf0e10cSrcweir 
756*cdf0e10cSrcweir                         return false; // abort iteration, we've
757*cdf0e10cSrcweir                                       // already found what we've been
758*cdf0e10cSrcweir                                       // looking for
759*cdf0e10cSrcweir                     }
760*cdf0e10cSrcweir 
761*cdf0e10cSrcweir                     return true; // keep on truckin'
762*cdf0e10cSrcweir                 }
763*cdf0e10cSrcweir 
764*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator getBeginElement() const
765*cdf0e10cSrcweir                 {
766*cdf0e10cSrcweir                     return maLastBegin;
767*cdf0e10cSrcweir                 }
768*cdf0e10cSrcweir 
769*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator getEndElement() const
770*cdf0e10cSrcweir                 {
771*cdf0e10cSrcweir                     return maLastEnd;
772*cdf0e10cSrcweir                 }
773*cdf0e10cSrcweir 
774*cdf0e10cSrcweir             private:
775*cdf0e10cSrcweir                 sal_Int32														mnNodeIndex;
776*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator	maLastBegin;
777*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificatorVector::const_iterator	maLastEnd;
778*cdf0e10cSrcweir                 DrawShapeSubsetting::IndexClassificator							meClass;
779*cdf0e10cSrcweir             };
780*cdf0e10cSrcweir 
781*cdf0e10cSrcweir             DocTreeNode makeTreeNode( const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rBegin,
782*cdf0e10cSrcweir                                       const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rStart,
783*cdf0e10cSrcweir                                       const DrawShapeSubsetting::IndexClassificatorVector::const_iterator& rEnd,
784*cdf0e10cSrcweir                                       DocTreeNode::NodeType												   eNodeType )
785*cdf0e10cSrcweir             {
786*cdf0e10cSrcweir                 return DocTreeNode( ::std::distance(rBegin,
787*cdf0e10cSrcweir                                                     rStart),
788*cdf0e10cSrcweir                                     ::std::distance(rBegin,
789*cdf0e10cSrcweir                                                     rEnd),
790*cdf0e10cSrcweir                                     eNodeType );
791*cdf0e10cSrcweir             }
792*cdf0e10cSrcweir         }
793*cdf0e10cSrcweir 
794*cdf0e10cSrcweir         DocTreeNode DrawShapeSubsetting::implGetTreeNode( const IndexClassificatorVector::const_iterator&	rBegin,
795*cdf0e10cSrcweir                                                           const IndexClassificatorVector::const_iterator&	rEnd,
796*cdf0e10cSrcweir                                                           sal_Int32											nNodeIndex,
797*cdf0e10cSrcweir                                                           DocTreeNode::NodeType								eNodeType ) const
798*cdf0e10cSrcweir         {
799*cdf0e10cSrcweir             const IndexClassificator eRequestedClass(
800*cdf0e10cSrcweir                 mapDocTreeNode( eNodeType ) );
801*cdf0e10cSrcweir 
802*cdf0e10cSrcweir             // create a nth element functor for the requested class of
803*cdf0e10cSrcweir             // actions, and nNodeIndex as the target index
804*cdf0e10cSrcweir             FindNthElementFunctor aFunctor( nNodeIndex,
805*cdf0e10cSrcweir                                             eRequestedClass );
806*cdf0e10cSrcweir 
807*cdf0e10cSrcweir             // find given index in the given range
808*cdf0e10cSrcweir             iterateActionClassifications( aFunctor, rBegin, rEnd );
809*cdf0e10cSrcweir 
810*cdf0e10cSrcweir             return makeTreeNode( maActionClassVector.begin(),
811*cdf0e10cSrcweir                                  aFunctor.getBeginElement(),
812*cdf0e10cSrcweir                                  aFunctor.getEndElement(),
813*cdf0e10cSrcweir                                  eNodeType );
814*cdf0e10cSrcweir         }
815*cdf0e10cSrcweir 
816*cdf0e10cSrcweir         DocTreeNode DrawShapeSubsetting::getTreeNode( sal_Int32				nNodeIndex,
817*cdf0e10cSrcweir                                                       DocTreeNode::NodeType	eNodeType ) const
818*cdf0e10cSrcweir         {
819*cdf0e10cSrcweir             ensureInitializedNodeTree();
820*cdf0e10cSrcweir 
821*cdf0e10cSrcweir             return implGetTreeNode( maActionClassVector.begin(),
822*cdf0e10cSrcweir                                     maActionClassVector.end(),
823*cdf0e10cSrcweir                                     nNodeIndex,
824*cdf0e10cSrcweir                                     eNodeType );
825*cdf0e10cSrcweir         }
826*cdf0e10cSrcweir 
827*cdf0e10cSrcweir         sal_Int32 DrawShapeSubsetting::getNumberOfSubsetTreeNodes( const DocTreeNode&  		rParentNode,
828*cdf0e10cSrcweir                                                                    DocTreeNode::NodeType	eNodeType ) const
829*cdf0e10cSrcweir         {
830*cdf0e10cSrcweir             ensureInitializedNodeTree();
831*cdf0e10cSrcweir 
832*cdf0e10cSrcweir             // convert from vector indices to vector iterators
833*cdf0e10cSrcweir             const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aBegin( maActionClassVector.begin() );
834*cdf0e10cSrcweir             const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentBegin( aBegin + rParentNode.getStartIndex() );
835*cdf0e10cSrcweir             const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentEnd( aBegin + rParentNode.getEndIndex() );
836*cdf0e10cSrcweir 
837*cdf0e10cSrcweir             return implGetNumberOfTreeNodes( aParentBegin,
838*cdf0e10cSrcweir                                              aParentEnd,
839*cdf0e10cSrcweir                                              eNodeType );
840*cdf0e10cSrcweir         }
841*cdf0e10cSrcweir 
842*cdf0e10cSrcweir         DocTreeNode DrawShapeSubsetting::getSubsetTreeNode( const DocTreeNode& 		rParentNode,
843*cdf0e10cSrcweir                                                             sal_Int32				nNodeIndex,
844*cdf0e10cSrcweir                                                             DocTreeNode::NodeType	eNodeType ) const
845*cdf0e10cSrcweir         {
846*cdf0e10cSrcweir             ensureInitializedNodeTree();
847*cdf0e10cSrcweir 
848*cdf0e10cSrcweir             // convert from vector indices to vector iterators
849*cdf0e10cSrcweir             const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aBegin( maActionClassVector.begin() );
850*cdf0e10cSrcweir             const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentBegin( aBegin + rParentNode.getStartIndex() );
851*cdf0e10cSrcweir             const DrawShapeSubsetting::IndexClassificatorVector::const_iterator aParentEnd( aBegin + rParentNode.getEndIndex() );
852*cdf0e10cSrcweir 
853*cdf0e10cSrcweir             return implGetTreeNode( aParentBegin,
854*cdf0e10cSrcweir                                     aParentEnd,
855*cdf0e10cSrcweir                                     nNodeIndex,
856*cdf0e10cSrcweir                                     eNodeType );
857*cdf0e10cSrcweir         }
858*cdf0e10cSrcweir 
859*cdf0e10cSrcweir         const VectorOfDocTreeNodes& DrawShapeSubsetting::getActiveSubsets() const
860*cdf0e10cSrcweir         {
861*cdf0e10cSrcweir             return maCurrentSubsets;
862*cdf0e10cSrcweir         }
863*cdf0e10cSrcweir 
864*cdf0e10cSrcweir     }
865*cdf0e10cSrcweir }
866