fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / slideshow / source / engine / shapes / drawshapesubsetting.cxx
blob953f97bdfe749abacefded4b798bd8ed50bea7ed
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
21 // must be first
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>
37 #include <algorithm>
38 #include <functional>
39 #include <limits>
41 using namespace ::com::sun::star;
44 namespace slideshow
46 namespace internal
51 // Private methods
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
68 MetaAction* pCurrAct;
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
86 // the given index
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
95 // action).
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
109 // action).
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
123 // action).
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;
148 SAL_INFO(
149 "slideshow",
150 "Shape text structure: " << pAct->GetComment()
151 << " at action #" << nActionIndex);
152 ++nActionIndex;
153 break;
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(),
165 nActionIndex );
167 #endif
168 // fallthrough intended
169 default:
170 // comment action and all actions not
171 // explicitly handled here:
172 nActionIndex += getNextActionOffset(pCurrAct);
173 break;
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 ) );
208 else
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 ) );
220 else
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 );
233 // Public methods
237 DrawShapeSubsetting::DrawShapeSubsetting() :
238 maActionClassVector(),
239 mpMtf(),
240 maSubset(),
241 maSubsetShapes(),
242 mnMinSubsetActionIndex( SAL_MAX_INT32 ),
243 mnMaxSubsetActionIndex(0),
244 maCurrentSubsets(),
245 mbNodeTreeInitialized( false )
249 DrawShapeSubsetting::DrawShapeSubsetting( const DocTreeNode& rShapeSubset,
250 const GDIMetaFileSharedPtr& rMtf ) :
251 maActionClassVector(),
252 mpMtf( rMtf ),
253 maSubset( rShapeSubset ),
254 maSubsetShapes(),
255 mnMinSubsetActionIndex( SAL_MAX_INT32 ),
256 mnMaxSubsetActionIndex(0),
257 maCurrentSubsets(),
258 mbNodeTreeInitialized( false )
260 ENSURE_OR_THROW( mpMtf,
261 "DrawShapeSubsetting::DrawShapeSubsetting(): Invalid metafile" );
263 initCurrentSubsets();
266 void DrawShapeSubsetting::reset()
268 maActionClassVector.clear();
269 mpMtf.reset();
270 maSubset.reset();
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 )
280 reset();
281 mpMtf = 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
297 return maSubset;
300 AttributableShapeSharedPtr DrawShapeSubsetting::getSubsetShape( const DocTreeNode& rTreeNode ) const
302 SAL_INFO( "slideshow", "::presentation::internal::DrawShapeSubsetting::getSubsetShape()" );
304 // subset shape already created for this DocTreeNode?
305 SubsetEntry aEntry;
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?
325 SubsetEntry aEntry;
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++;
340 else
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 );
350 updateSubsets();
354 bool DrawShapeSubsetting::revokeSubsetShape( const AttributableShapeSharedPtr& rShape )
356 SAL_INFO( "slideshow", "::presentation::internal::DrawShapeSubsetting::revokeSubsetShape()" );
358 // lookup subset shape
359 SubsetEntry aEntry;
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--;
376 SAL_INFO(
377 "slideshow",
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
386 SAL_INFO(
387 "slideshow",
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
400 // in subset shapes)
403 // init bounds
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,
415 this,
416 _1 ) );
418 updateSubsets();
420 return true;
423 namespace
425 /** Iterate over all action classification entries in the
426 given range, pass each element range found to the
427 given functor.
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
432 information.
434 @tpl FunctorT
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
442 of this element).
443 <pre>
444 bool operator()( IndexClassificator eCurrElemClassification
445 sal_Int32 nCurrElemCount,
446 const IndexClassificatorVector::const_iterator& rCurrElemBegin,
447 const IndexClassificatorVector::const_iterator& rCurrElemEnd );
448 </pre>
449 If the functor returns false, iteration over the
450 shapes is immediately stopped.
452 @param io_pFunctor
453 This functor is called for every shape found.
455 @param rBegin
456 Start of range to iterate over
458 @param rEnd
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.
490 aNext = aCurr;
491 ++aNext;
493 switch( *aCurr )
495 default:
496 ENSURE_OR_THROW( false,
497 "Unexpected type in iterateDocShapes()" );
498 case DrawShapeSubsetting::CLASS_NOOP:
499 // ignore NOOP actions
500 break;
502 case DrawShapeSubsetting::CLASS_SHAPE_START:
503 // regardless of ending action
504 // classifications before: a new shape
505 // always also starts contained elements
506 // anew
507 aLastShapeStart =
508 aLastParaStart =
509 aLastLineStart =
510 aLastSentenceStart =
511 aLastWordStart =
512 aLastCharStart = aCurr;
513 break;
515 case DrawShapeSubsetting::CLASS_SHAPE_END:
516 if( !io_rFunctor( DrawShapeSubsetting::CLASS_SHAPE_END,
517 nCurrShapeCount,
518 aLastShapeStart,
519 aNext ) )
521 return;
524 ++nCurrShapeCount;
525 // FALLTHROUGH intended: shape end also
526 // ends lines
527 case DrawShapeSubsetting::CLASS_PARAGRAPH_END:
528 if( !io_rFunctor( DrawShapeSubsetting::CLASS_PARAGRAPH_END,
529 nCurrParaCount,
530 aLastParaStart,
531 aNext ) )
533 return;
536 ++nCurrParaCount;
537 aLastParaStart = aNext;
538 // FALLTHROUGH intended: para end also
539 // ends line
540 case DrawShapeSubsetting::CLASS_LINE_END:
541 if( !io_rFunctor( DrawShapeSubsetting::CLASS_LINE_END,
542 nCurrLineCount,
543 aLastLineStart,
544 aNext ) )
546 return;
549 ++nCurrLineCount;
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
560 // character cell.
562 // TODO(F1): Maybe a line should end a
563 // character cell, OTOH?
564 break;
566 // FALLTHROUGH intended
567 case DrawShapeSubsetting::CLASS_SENTENCE_END:
568 if( !io_rFunctor( DrawShapeSubsetting::CLASS_SENTENCE_END,
569 nCurrSentenceCount,
570 aLastSentenceStart,
571 aNext ) )
573 return;
576 ++nCurrSentenceCount;
577 aLastSentenceStart = aNext;
578 // FALLTHROUGH intended
579 case DrawShapeSubsetting::CLASS_WORD_END:
580 if( !io_rFunctor( DrawShapeSubsetting::CLASS_WORD_END,
581 nCurrWordCount,
582 aLastWordStart,
583 aNext ) )
585 return;
588 ++nCurrWordCount;
589 aLastWordStart = aNext;
590 // FALLTHROUGH intended
591 case DrawShapeSubsetting::CLASS_CHARACTER_CELL_END:
592 if( !io_rFunctor( DrawShapeSubsetting::CLASS_CHARACTER_CELL_END,
593 nCurrCharCount,
594 aLastCharStart,
595 aNext ) )
597 return;
600 ++nCurrCharCount;
601 aLastCharStart = aNext;
602 break;
605 aCurr = aNext;
609 DrawShapeSubsetting::IndexClassificator mapDocTreeNode( DocTreeNode::NodeType eNodeType )
611 switch( eNodeType )
613 case DocTreeNode::NODETYPE_INVALID:
614 // FALLTHROUGH intended
615 default:
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
644 public:
645 CountClassFunctor( DrawShapeSubsetting::IndexClassificator eClass ) :
646 meClass( eClass ),
647 mnCurrCount(0)
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 )
657 ++mnCurrCount;
659 return true; // never stop, count all occurrences
662 sal_Int32 getCount() const
664 return mnCurrCount;
667 private:
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
681 // actions
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(),
696 eNodeType );
699 namespace
701 /** This functor finds the nth occurrence of a given
702 action class.
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
711 public:
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 ),
719 meClass( eClass )
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
736 // looking for
739 return true; // keep on truckin'
742 private:
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,
755 rStart),
756 ::std::distance(rBegin,
757 rEnd),
758 eNodeType );
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,
776 aLastBegin,
777 aLastEnd,
778 eRequestedClass );
780 // find given index in the given range
781 iterateActionClassifications( aFunctor, rBegin, rEnd );
783 return makeTreeNode( maActionClassVector.begin(),
784 aLastBegin, aLastEnd,
785 eNodeType );
788 DocTreeNode DrawShapeSubsetting::getTreeNode( sal_Int32 nNodeIndex,
789 DocTreeNode::NodeType eNodeType ) const
791 ensureInitializedNodeTree();
793 return implGetTreeNode( maActionClassVector.begin(),
794 maActionClassVector.end(),
795 nNodeIndex,
796 eNodeType );
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,
810 aParentEnd,
811 eNodeType );
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,
826 aParentEnd,
827 nNodeIndex,
828 eNodeType );
835 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */