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