1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
22 #include <canvas/debug.hxx>
23 #include <tools/diagnose_ex.h>
24 #include <canvas/verbosetrace.hxx>
26 #include <rtl/math.hxx>
28 #include <vcl/metaact.hxx>
29 #include <vcl/gdimtf.hxx>
30 #include <basegfx/numeric/ftools.hxx>
32 #include "drawshapesubsetting.hxx"
33 #include "drawshape.hxx"
35 #include <boost/bind.hpp>
41 using namespace ::com::sun::star
;
55 void DrawShapeSubsetting::ensureInitializedNodeTree() const
57 ENSURE_OR_THROW( mpMtf
,
58 "DrawShapeSubsetting::ensureInitializedNodeTree(): Invalid mtf" );
60 if( mbNodeTreeInitialized
)
61 return; // done, already initialized.
63 // init doctree vector
64 maActionClassVector
.clear();
65 maActionClassVector
.reserve( mpMtf
->GetActionSize() );
67 // search metafile for text output
70 sal_Int32
nActionIndex(0);
71 sal_Int32
nLastTextActionIndex(0);
72 for( pCurrAct
= mpMtf
->FirstAction(); pCurrAct
; pCurrAct
= mpMtf
->NextAction() )
74 // check for one of our special text doctree comments
75 switch( pCurrAct
->GetType() )
77 case MetaActionType::COMMENT
:
79 MetaCommentAction
* pAct
= static_cast<MetaCommentAction
*>(pCurrAct
);
81 // skip comment if not a special XTEXT... comment
82 if( pAct
->GetComment().matchIgnoreAsciiCase( OString("XTEXT"), 0 ) )
84 // fill classification vector with NOOPs,
85 // then insert corresponding classes at
87 maActionClassVector
.resize( nActionIndex
+1, CLASS_NOOP
);
89 if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_EOC") )
91 // special, because can happen
92 // in-between of portions - set
93 // character-end classificator at
94 // given index (relative to last text
96 const sal_Int32
nIndex( nLastTextActionIndex
+ pAct
->GetValue() );
98 ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex
) < maActionClassVector
.size(),
99 "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
101 maActionClassVector
[ nIndex
] = CLASS_CHARACTER_CELL_END
;
103 else if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_EOW") )
105 // special, because can happen
106 // in-between of portions - set
107 // word-end classificator at given
108 // index (relative to last text
110 const sal_Int32
nIndex( nLastTextActionIndex
+ pAct
->GetValue() );
112 ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex
) < maActionClassVector
.size(),
113 "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
115 maActionClassVector
[ nIndex
] = CLASS_WORD_END
;
117 else if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_EOS") )
119 // special, because can happen
120 // in-between of portions - set
121 // sentence-end classificator at given
122 // index (relative to last text
124 const sal_Int32
nIndex( nLastTextActionIndex
+ pAct
->GetValue() );
126 ENSURE_OR_THROW( static_cast< ::std::size_t >(nIndex
) < maActionClassVector
.size(),
127 "DrawShapeSubsetting::ensureInitializedNodeTree(): sentence index out of range" );
129 maActionClassVector
[ nIndex
] = CLASS_SENTENCE_END
;
131 else if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_EOL") )
133 maActionClassVector
[ nActionIndex
] = CLASS_LINE_END
;
135 else if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_EOP") )
137 maActionClassVector
[ nActionIndex
] = CLASS_PARAGRAPH_END
;
139 else if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_PAINTSHAPE_END") )
141 maActionClassVector
[ nActionIndex
] = CLASS_SHAPE_END
;
143 else if( pAct
->GetComment().equalsIgnoreAsciiCase("XTEXT_PAINTSHAPE_BEGIN") )
145 maActionClassVector
[ nActionIndex
] = CLASS_SHAPE_START
;
150 "Shape text structure: " << pAct
->GetComment()
151 << " at action #" << nActionIndex
);
155 case MetaActionType::TEXT
:
156 case MetaActionType::TEXTARRAY
:
157 case MetaActionType::STRETCHTEXT
:
158 nLastTextActionIndex
= nActionIndex
;
159 #if OSL_DEBUG_LEVEL > 1
161 MetaTextAction
* pText
= static_cast<MetaTextAction
*>(pCurrAct
);
162 VERBOSE_TRACE( "Shape text \"%s\" at action #%d",
163 OUStringToOString(pText
->GetText(),
164 RTL_TEXTENCODING_ISO_8859_1
).getStr(),
168 // fallthrough intended
170 // comment action and all actions not
171 // explicitly handled here:
172 nActionIndex
+= getNextActionOffset(pCurrAct
);
177 mbNodeTreeInitialized
= true;
180 void DrawShapeSubsetting::updateSubsetBounds( const SubsetEntry
& rSubsetEntry
)
182 // TODO(F1): This removes too much from non-contiguous subsets
183 mnMinSubsetActionIndex
= ::std::min(
184 mnMinSubsetActionIndex
,
185 rSubsetEntry
.mnStartActionIndex
);
186 mnMaxSubsetActionIndex
= ::std::max(
187 mnMaxSubsetActionIndex
,
188 rSubsetEntry
.mnEndActionIndex
);
191 void DrawShapeSubsetting::updateSubsets()
193 maCurrentSubsets
.clear();
195 if( !maSubsetShapes
.empty() )
197 if( maSubset
.isEmpty() )
199 // non-subsetted node, with some child subsets
200 // that subtract from it
201 maCurrentSubsets
.push_back( DocTreeNode( 0,
202 mnMinSubsetActionIndex
,
203 DocTreeNode::NODETYPE_INVALID
) );
204 maCurrentSubsets
.push_back( DocTreeNode( mnMaxSubsetActionIndex
,
205 maActionClassVector
.size(),
206 DocTreeNode::NODETYPE_INVALID
) );
210 // subsetted node, from which some further child
211 // subsets subtract content
212 maCurrentSubsets
.push_back( DocTreeNode( maSubset
.getStartIndex(),
213 mnMinSubsetActionIndex
,
214 DocTreeNode::NODETYPE_INVALID
) );
215 maCurrentSubsets
.push_back( DocTreeNode( mnMaxSubsetActionIndex
,
216 maSubset
.getEndIndex(),
217 DocTreeNode::NODETYPE_INVALID
) );
222 // no further child subsets, simply add our subset (if any)
223 if( !maSubset
.isEmpty() )
225 // subsetted node, without any subset children
226 maCurrentSubsets
.push_back( maSubset
);
237 DrawShapeSubsetting::DrawShapeSubsetting() :
238 maActionClassVector(),
242 mnMinSubsetActionIndex( SAL_MAX_INT32
),
243 mnMaxSubsetActionIndex(0),
245 mbNodeTreeInitialized( false )
249 DrawShapeSubsetting::DrawShapeSubsetting( const DocTreeNode
& rShapeSubset
,
250 const GDIMetaFileSharedPtr
& rMtf
) :
251 maActionClassVector(),
253 maSubset( rShapeSubset
),
255 mnMinSubsetActionIndex( SAL_MAX_INT32
),
256 mnMaxSubsetActionIndex(0),
258 mbNodeTreeInitialized( false )
260 ENSURE_OR_THROW( mpMtf
,
261 "DrawShapeSubsetting::DrawShapeSubsetting(): Invalid metafile" );
263 initCurrentSubsets();
266 void DrawShapeSubsetting::reset()
268 maActionClassVector
.clear();
271 maSubsetShapes
.clear();
272 mnMinSubsetActionIndex
= SAL_MAX_INT32
;
273 mnMaxSubsetActionIndex
= 0;
274 maCurrentSubsets
.clear();
275 mbNodeTreeInitialized
= false;
278 void DrawShapeSubsetting::reset( const ::boost::shared_ptr
< GDIMetaFile
>& rMtf
)
283 initCurrentSubsets();
286 void DrawShapeSubsetting::initCurrentSubsets()
288 // only add subset to vector, if it's not empty - that's
289 // because the vector's content is later literally used
290 // for e.g. painting.
291 if( !maSubset
.isEmpty() )
292 maCurrentSubsets
.push_back( maSubset
);
295 DocTreeNode
DrawShapeSubsetting::getSubsetNode() const
300 AttributableShapeSharedPtr
DrawShapeSubsetting::getSubsetShape( const DocTreeNode
& rTreeNode
) const
302 SAL_INFO( "slideshow", "::presentation::internal::DrawShapeSubsetting::getSubsetShape()" );
304 // subset shape already created for this DocTreeNode?
307 aEntry
.mnStartActionIndex
= rTreeNode
.getStartIndex();
308 aEntry
.mnEndActionIndex
= rTreeNode
.getEndIndex();
310 ShapeSet::const_iterator aIter
;
311 if( (aIter
=maSubsetShapes
.find( aEntry
)) != maSubsetShapes
.end() )
313 // already created, return found entry
314 return aIter
->mpShape
;
317 return AttributableShapeSharedPtr();
320 void DrawShapeSubsetting::addSubsetShape( const AttributableShapeSharedPtr
& rShape
)
322 SAL_INFO( "slideshow", "::presentation::internal::DrawShapeSubsetting::addSubsetShape()" );
324 // subset shape already created for this DocTreeNode?
326 const DocTreeNode
& rEffectiveSubset( rShape
->getSubsetNode() );
328 aEntry
.mnStartActionIndex
= rEffectiveSubset
.getStartIndex();
329 aEntry
.mnEndActionIndex
= rEffectiveSubset
.getEndIndex();
331 ShapeSet::const_iterator aIter
;
332 if( (aIter
=maSubsetShapes
.find( aEntry
)) != maSubsetShapes
.end() )
334 // already created, increment use count and return
336 // safe cast, since set order does not depend on
337 // mnSubsetQueriedCount
338 const_cast<SubsetEntry
&>(*aIter
).mnSubsetQueriedCount
++;
342 // not yet created, init entry
343 aEntry
.mnSubsetQueriedCount
= 1;
344 aEntry
.mpShape
= rShape
;
346 maSubsetShapes
.insert( aEntry
);
348 // update cached subset borders
349 updateSubsetBounds( aEntry
);
354 bool DrawShapeSubsetting::revokeSubsetShape( const AttributableShapeSharedPtr
& rShape
)
356 SAL_INFO( "slideshow", "::presentation::internal::DrawShapeSubsetting::revokeSubsetShape()" );
358 // lookup subset shape
360 const DocTreeNode
& rEffectiveSubset( rShape
->getSubsetNode() );
362 aEntry
.mnStartActionIndex
= rEffectiveSubset
.getStartIndex();
363 aEntry
.mnEndActionIndex
= rEffectiveSubset
.getEndIndex();
365 ShapeSet::iterator aIter
;
366 if( (aIter
=maSubsetShapes
.find( aEntry
)) == maSubsetShapes
.end() )
367 return false; // not found, subset was never queried
369 // last client of the subset revoking?
370 if( aIter
->mnSubsetQueriedCount
> 1 )
372 // no, still clients out there. Just decrement use count
373 // safe cast, since order does not depend on mnSubsetQueriedCount
374 const_cast<SubsetEntry
&>(*aIter
).mnSubsetQueriedCount
--;
378 "Subset summary: shape " << this << ", "
379 << maSubsetShapes
.size()
380 << " open subsets, revoked subset has refcount "
381 << aIter
->mnSubsetQueriedCount
);
383 return false; // not the last client
388 "Subset summary: shape " << this << ", "
389 << maSubsetShapes
.size()
390 << " open subsets, cleared subset has range ["
391 << aEntry
.mnStartActionIndex
<< ","
392 << aEntry
.mnEndActionIndex
<< "]");
394 // yes, remove from set
395 maSubsetShapes
.erase( aIter
);
398 // update currently active subset for _our_ shape (the
399 // part of this shape that is visible, i.e. not displayed
404 mnMinSubsetActionIndex
= SAL_MAX_INT32
;
405 mnMaxSubsetActionIndex
= 0;
407 // TODO(P2): This is quite expensive, when
408 // after every subset effect end, we have to scan
409 // the whole shape set
411 // determine new subset range
412 ::std::for_each( maSubsetShapes
.begin(),
413 maSubsetShapes
.end(),
414 ::boost::bind(&DrawShapeSubsetting::updateSubsetBounds
,
425 /** Iterate over all action classification entries in the
426 given range, pass each element range found to the
429 This method extracts, for each of the different action
430 classifications, the count and the ranges for each of
431 them, and calls the provided functor with that
435 This is the functor's operator() calling signature,
436 with eCurrElemClassification denoting the current
437 classification type the functor is called for,
438 nCurrElemCount the running total of elements visited
439 for the given class (starting from 0), and
440 rCurrElemBegin/rCurrElemEnd the range of the current
441 element (i.e. the iterators from the start to the end
444 bool operator()( IndexClassificator eCurrElemClassification
445 sal_Int32 nCurrElemCount,
446 const IndexClassificatorVector::const_iterator& rCurrElemBegin,
447 const IndexClassificatorVector::const_iterator& rCurrElemEnd );
449 If the functor returns false, iteration over the
450 shapes is immediately stopped.
453 This functor is called for every shape found.
456 Start of range to iterate over
459 End of range to iterate over
461 @return the number of shapes found in the metafile
463 template< typename FunctorT
> void iterateActionClassifications(
464 FunctorT
& io_rFunctor
,
465 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rBegin
,
466 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rEnd
)
468 sal_Int32
nCurrShapeCount( 0 );
469 sal_Int32
nCurrParaCount( 0 );
470 sal_Int32
nCurrLineCount( 0 );
471 sal_Int32
nCurrSentenceCount( 0 );
472 sal_Int32
nCurrWordCount( 0 );
473 sal_Int32
nCurrCharCount( 0 );
475 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastShapeStart(rBegin
);
476 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastParaStart(rBegin
);
477 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastLineStart(rBegin
);
478 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastSentenceStart(rBegin
);
479 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastWordStart(rBegin
);
480 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastCharStart(rBegin
);
482 DrawShapeSubsetting::IndexClassificatorVector::const_iterator aNext
;
483 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aCurr( rBegin
);
484 while( aCurr
!= rEnd
)
486 // aNext will hold an iterator to the next element
487 // (or the past-the-end iterator, if aCurr
488 // references the last element). Used to pass a
489 // valid half-open range to the functors.
496 ENSURE_OR_THROW( false,
497 "Unexpected type in iterateDocShapes()" );
498 case DrawShapeSubsetting::CLASS_NOOP
:
499 // ignore NOOP actions
502 case DrawShapeSubsetting::CLASS_SHAPE_START
:
503 // regardless of ending action
504 // classifications before: a new shape
505 // always also starts contained elements
512 aLastCharStart
= aCurr
;
515 case DrawShapeSubsetting::CLASS_SHAPE_END
:
516 if( !io_rFunctor( DrawShapeSubsetting::CLASS_SHAPE_END
,
525 // FALLTHROUGH intended: shape end also
527 case DrawShapeSubsetting::CLASS_PARAGRAPH_END
:
528 if( !io_rFunctor( DrawShapeSubsetting::CLASS_PARAGRAPH_END
,
537 aLastParaStart
= aNext
;
538 // FALLTHROUGH intended: para end also
540 case DrawShapeSubsetting::CLASS_LINE_END
:
541 if( !io_rFunctor( DrawShapeSubsetting::CLASS_LINE_END
,
550 aLastLineStart
= aNext
;
552 if( *aCurr
== DrawShapeSubsetting::CLASS_LINE_END
)
554 // DON'T fall through here, as a line
555 // does NOT end neither a sentence,
556 // nor a word. OTOH, all parent
557 // structures (paragraph and shape),
558 // which itself fall through to this
559 // code, DO end word, sentence and
562 // TODO(F1): Maybe a line should end a
563 // character cell, OTOH?
566 // FALLTHROUGH intended
567 case DrawShapeSubsetting::CLASS_SENTENCE_END
:
568 if( !io_rFunctor( DrawShapeSubsetting::CLASS_SENTENCE_END
,
576 ++nCurrSentenceCount
;
577 aLastSentenceStart
= aNext
;
578 // FALLTHROUGH intended
579 case DrawShapeSubsetting::CLASS_WORD_END
:
580 if( !io_rFunctor( DrawShapeSubsetting::CLASS_WORD_END
,
589 aLastWordStart
= aNext
;
590 // FALLTHROUGH intended
591 case DrawShapeSubsetting::CLASS_CHARACTER_CELL_END
:
592 if( !io_rFunctor( DrawShapeSubsetting::CLASS_CHARACTER_CELL_END
,
601 aLastCharStart
= aNext
;
609 DrawShapeSubsetting::IndexClassificator
mapDocTreeNode( DocTreeNode::NodeType eNodeType
)
613 case DocTreeNode::NODETYPE_INVALID
:
614 // FALLTHROUGH intended
616 SAL_WARN( "slideshow", "DrawShapeSubsetting::mapDocTreeNode(): unexpected node type");
617 return DrawShapeSubsetting::CLASS_NOOP
;
619 case DocTreeNode::NODETYPE_LOGICAL_SHAPE
:
620 // FALLTHROUGH intended
621 case DocTreeNode::NODETYPE_FORMATTING_SHAPE
:
622 return DrawShapeSubsetting::CLASS_SHAPE_END
;
624 case DocTreeNode::NODETYPE_FORMATTING_LINE
:
625 return DrawShapeSubsetting::CLASS_LINE_END
;
627 case DocTreeNode::NODETYPE_LOGICAL_PARAGRAPH
:
628 return DrawShapeSubsetting::CLASS_PARAGRAPH_END
;
630 case DocTreeNode::NODETYPE_LOGICAL_SENTENCE
:
631 return DrawShapeSubsetting::CLASS_SENTENCE_END
;
633 case DocTreeNode::NODETYPE_LOGICAL_WORD
:
634 return DrawShapeSubsetting::CLASS_WORD_END
;
636 case DocTreeNode::NODETYPE_LOGICAL_CHARACTER_CELL
:
637 return DrawShapeSubsetting::CLASS_CHARACTER_CELL_END
;
641 /// Counts number of class occurrences
642 class CountClassFunctor
645 CountClassFunctor( DrawShapeSubsetting::IndexClassificator eClass
) :
651 bool operator()( DrawShapeSubsetting::IndexClassificator eCurrElemClassification
,
652 sal_Int32
/*nCurrElemCount*/,
653 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& /*rCurrElemBegin*/,
654 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& /*rCurrElemEnd*/ )
656 if( eCurrElemClassification
== meClass
)
659 return true; // never stop, count all occurrences
662 sal_Int32
getCount() const
668 DrawShapeSubsetting::IndexClassificator meClass
;
669 sal_Int32 mnCurrCount
;
673 sal_Int32
DrawShapeSubsetting::implGetNumberOfTreeNodes( const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rBegin
,
674 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rEnd
,
675 DocTreeNode::NodeType eNodeType
)
677 const IndexClassificator
eRequestedClass(
678 mapDocTreeNode( eNodeType
) );
680 // create a counting functor for the requested class of
682 CountClassFunctor
aFunctor( eRequestedClass
);
684 // count all occurrences in the given range
685 iterateActionClassifications( aFunctor
, rBegin
, rEnd
);
687 return aFunctor
.getCount();
690 sal_Int32
DrawShapeSubsetting::getNumberOfTreeNodes( DocTreeNode::NodeType eNodeType
) const
692 ensureInitializedNodeTree();
694 return implGetNumberOfTreeNodes( maActionClassVector
.begin(),
695 maActionClassVector
.end(),
701 /** This functor finds the nth occurrence of a given
704 The operator() compares the given index value with the
705 requested index, as given on the functor's
706 constructor. Then, the operator() returns false,
707 denoting that the requested action is found.
709 class FindNthElementFunctor
712 FindNthElementFunctor( sal_Int32 nNodeIndex
,
713 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rLastBegin
,
714 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rLastEnd
,
715 DrawShapeSubsetting::IndexClassificator eClass
) :
716 mnNodeIndex( nNodeIndex
),
717 mrLastBegin( rLastBegin
),
718 mrLastEnd( rLastEnd
),
723 bool operator()( DrawShapeSubsetting::IndexClassificator eCurrElemClassification
,
724 sal_Int32 nCurrElemCount
,
725 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rCurrElemBegin
,
726 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rCurrElemEnd
)
728 if( eCurrElemClassification
== meClass
&&
729 nCurrElemCount
== mnNodeIndex
)
731 mrLastBegin
= rCurrElemBegin
;
732 mrLastEnd
= rCurrElemEnd
;
734 return false; // abort iteration, we've
735 // already found what we've been
739 return true; // keep on truckin'
743 sal_Int32 mnNodeIndex
;
744 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& mrLastBegin
;
745 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& mrLastEnd
;
746 DrawShapeSubsetting::IndexClassificator meClass
;
749 DocTreeNode
makeTreeNode( const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rBegin
,
750 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rStart
,
751 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
& rEnd
,
752 DocTreeNode::NodeType eNodeType
)
754 return DocTreeNode( ::std::distance(rBegin
,
756 ::std::distance(rBegin
,
762 DocTreeNode
DrawShapeSubsetting::implGetTreeNode( const IndexClassificatorVector::const_iterator
& rBegin
,
763 const IndexClassificatorVector::const_iterator
& rEnd
,
764 sal_Int32 nNodeIndex
,
765 DocTreeNode::NodeType eNodeType
) const
767 const IndexClassificator
eRequestedClass(
768 mapDocTreeNode( eNodeType
) );
770 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastBegin(rEnd
);
771 DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aLastEnd(rEnd
);
773 // create a nth element functor for the requested class of
774 // actions, and nNodeIndex as the target index
775 FindNthElementFunctor
aFunctor( nNodeIndex
,
780 // find given index in the given range
781 iterateActionClassifications( aFunctor
, rBegin
, rEnd
);
783 return makeTreeNode( maActionClassVector
.begin(),
784 aLastBegin
, aLastEnd
,
788 DocTreeNode
DrawShapeSubsetting::getTreeNode( sal_Int32 nNodeIndex
,
789 DocTreeNode::NodeType eNodeType
) const
791 ensureInitializedNodeTree();
793 return implGetTreeNode( maActionClassVector
.begin(),
794 maActionClassVector
.end(),
799 sal_Int32
DrawShapeSubsetting::getNumberOfSubsetTreeNodes( const DocTreeNode
& rParentNode
,
800 DocTreeNode::NodeType eNodeType
) const
802 ensureInitializedNodeTree();
804 // convert from vector indices to vector iterators
805 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aBegin( maActionClassVector
.begin() );
806 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aParentBegin( aBegin
+ rParentNode
.getStartIndex() );
807 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aParentEnd( aBegin
+ rParentNode
.getEndIndex() );
809 return implGetNumberOfTreeNodes( aParentBegin
,
814 DocTreeNode
DrawShapeSubsetting::getSubsetTreeNode( const DocTreeNode
& rParentNode
,
815 sal_Int32 nNodeIndex
,
816 DocTreeNode::NodeType eNodeType
) const
818 ensureInitializedNodeTree();
820 // convert from vector indices to vector iterators
821 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aBegin( maActionClassVector
.begin() );
822 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aParentBegin( aBegin
+ rParentNode
.getStartIndex() );
823 const DrawShapeSubsetting::IndexClassificatorVector::const_iterator
aParentEnd( aBegin
+ rParentNode
.getEndIndex() );
825 return implGetTreeNode( aParentBegin
,
835 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */