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