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