1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef INCLUDED_SLIDESHOW_DRAWSHAPESUBSETTING_HXX
29 #define INCLUDED_SLIDESHOW_DRAWSHAPESUBSETTING_HXX
30 
31 #include <boost/shared_ptr.hpp>
32 #include <boost/noncopyable.hpp>
33 
34 #include "doctreenode.hxx"
35 #include "attributableshape.hxx"
36 
37 
38 class GDIMetaFile;
39 
40 namespace slideshow
41 {
42     namespace internal
43     {
44         /** This class encapsulates the subsetting aspects of a
45             DrawShape.
46          */
47         class DrawShapeSubsetting : private boost::noncopyable
48         {
49         public:
50             /** Create empty shape subset handling.
51 
52             	This method creates a subset handler which contains no
53             	subset information. All methods will return default
54             	values.
55 
56                 @param rMtf
57                 Metafile to retrieve subset info from (must have been
58                 generated with verbose text comments switched on).
59              */
60             DrawShapeSubsetting();
61 
62             /** Create new shape subset handling.
63 
64             	This method creates a subset handler which initially
65             	displays the whole shape.
66 
67                 @param rMtf
68                 Metafile to retrieve subset info from (must have been
69                 generated with verbose text comments switched on).
70              */
71             explicit DrawShapeSubsetting( const ::boost::shared_ptr< GDIMetaFile >& rMtf );
72 
73             /** Create new shape subset handling.
74 
75             	@param rShapeSubset
76                 The subset this object represents (can be empty, then
77                 denoting 'represents a whole shape')
78 
79                 @param rMtf
80                 Metafile to retrieve subset info from (must have been
81                 generated with verbose text comments switched on).
82              */
83             DrawShapeSubsetting( const DocTreeNode&			 				rShapeSubset,
84                                  const ::boost::shared_ptr< GDIMetaFile >&	rMtf );
85 
86             /** Reset metafile.
87 
88                 Use this method to completely reset the
89                 ShapeSubsetting, with a new metafile. Note that any
90                 information previously set will be lost, including
91                 added subset shapes!
92 
93                 @param rMtf
94                 Metafile to retrieve subset info from (must have been
95                 generated with verbose text comments switched on).
96              */
97             void reset( const ::boost::shared_ptr< GDIMetaFile >&   rMtf );
98 
99             /** Reset metafile and subset.
100 
101                 Use this method to completely reset the
102                 ShapeSubsetting, with a new metafile and subset
103                 range. Note that any information previously set will
104                 be lost, including added subset shapes!
105 
106             	@param rShapeSubset
107                 The subset this object represents (can be empty, then
108                 denoting 'represents a whole shape')
109 
110                 @param rMtf
111                 Metafile to retrieve subset info from (must have been
112                 generated with verbose text comments switched on).
113              */
114             void reset( const DocTreeNode&                          rShapeSubset,
115                         const ::boost::shared_ptr< GDIMetaFile >&   rMtf );
116 
117 
118             // Shape subsetting methods
119             // ========================================================
120 
121             /// Return subset node for this shape
122             DocTreeNode 				getSubsetNode		() const;
123 
124             /// Return true, if any child subset shapes exist
125             bool		 				hasSubsetShapes		() const;
126 
127             /// Get subset shape for given node, if any
128             AttributableShapeSharedPtr 	getSubsetShape		( const DocTreeNode& rTreeNode ) const;
129 
130             /// Add child subset shape (or increase use count, if already existent)
131             void 						addSubsetShape		( const AttributableShapeSharedPtr& rShape );
132 
133             /** Revoke subset shape
134 
135             	This method revokes a subset shape, decrementing the
136             	use count for this subset by one. If the use count
137             	reaches zero (i.e. when the number of addSubsetShape()
138             	matches the number of revokeSubsetShape() calls for
139             	the same subset), the subset entry is removed from the
140             	internal list, and subsequent getSubsetShape() calls
141             	will return the empty pointer for this subset.
142 
143                 @return true, if the subset shape was physically
144                 removed from the list (false is returned, when nothing
145                 was removed, either because only the use count was
146                 decremented, or there was no such subset found, in the
147                 first place).
148              */
149             bool 						revokeSubsetShape	( const AttributableShapeSharedPtr& rShape );
150 
151 
152             // Doc tree methods
153             // ========================================================
154 
155             /// Return overall number of nodes for given type
156             sal_Int32 	getNumberOfTreeNodes		( DocTreeNode::NodeType eNodeType ) const;
157 
158             /// Return tree node of given index and given type
159             DocTreeNode getTreeNode					( sal_Int32				nNodeIndex,
160                                                       DocTreeNode::NodeType	eNodeType ) const;
161 
162             /// Return number of nodes of given type, below parent node
163             sal_Int32 	getNumberOfSubsetTreeNodes	( const DocTreeNode& 	rParentNode,
164                                                       DocTreeNode::NodeType eNodeType ) const;
165 
166             /// Return tree node of given index and given type, relative to parent node
167             DocTreeNode getSubsetTreeNode			( const DocTreeNode& 	rParentNode,
168                                                       sal_Int32				nNodeIndex,
169                                                       DocTreeNode::NodeType	eNodeType ) const;
170 
171             // Helper
172             // ========================================================
173 
174             /** Return a vector of currently active subsets.
175 
176             	Needed when rendering a shape, this method provides a
177             	vector of subsets currently visible (the range as
178             	returned by getEffectiveSubset(), minus the parts that
179             	are currently hidden, because displayed by child
180             	shapes).
181              */
182             const VectorOfDocTreeNodes& getActiveSubsets() const;
183 
184             /** This enum classifies each action index in the
185                 metafile.
186 
187                 Of interest are, of course, the places where
188                 structural shape and/or text elements end. The
189                 remainder of the action gets classified as 'noop'
190              */
191             enum IndexClassificator
192             {
193                 CLASS_NOOP,
194                 CLASS_SHAPE_START,
195                 CLASS_SHAPE_END,
196 
197                 CLASS_LINE_END,
198                 CLASS_PARAGRAPH_END,
199                 CLASS_SENTENCE_END,
200                 CLASS_WORD_END,
201                 CLASS_CHARACTER_CELL_END
202             };
203 
204             typedef ::std::vector< IndexClassificator > IndexClassificatorVector;
205 
206         private:
207             /** Entry for subset shape
208 
209             	This struct contains data for every subset shape
210             	generated. Note that for a given start/end action
211             	index combination, only one subset instance is
212             	generated (and reused for subsequent queries).
213              */
214             struct SubsetEntry
215             {
216                 AttributableShapeSharedPtr	mpShape;
217                 sal_Int32					mnStartActionIndex;
218                 sal_Int32					mnEndActionIndex;
219 
220                 /// Number of times this subset was queried, and not yet revoked
221                 int							mnSubsetQueriedCount;
222 
223                 sal_Int32 getHashValue() const
224                 {
225                     // TODO(Q3): That's a hack. We assume that start
226                     // index will always be less than 65535 (if this
227                     // assumption is violated, hash map performance
228                     // will degrade severely)
229                     return mnStartActionIndex*SAL_MAX_INT16 + mnEndActionIndex;
230                 }
231 
232                 /// The shape set is ordered according to this method
233                 bool operator<(const SubsetEntry& rOther) const
234                 {
235                     return getHashValue() < rOther.getHashValue();
236                 }
237 
238             };
239 
240             typedef ::std::set< SubsetEntry > 		ShapeSet;
241 
242             void ensureInitializedNodeTree() const;
243             void updateSubsetBounds( const SubsetEntry& rSubsetEntry );
244             void updateSubsets();
245             void initCurrentSubsets();
246             void reset();
247 
248             sal_Int32 	implGetNumberOfTreeNodes( const IndexClassificatorVector::const_iterator&	rBegin,
249                                                   const IndexClassificatorVector::const_iterator&	rEnd,
250                                                   DocTreeNode::NodeType 							eNodeType ) const;
251             DocTreeNode implGetTreeNode( const IndexClassificatorVector::const_iterator&	rBegin,
252                                          const IndexClassificatorVector::const_iterator&	rEnd,
253                                          sal_Int32			 								nNodeIndex,
254                                          DocTreeNode::NodeType								eNodeType ) const;
255 
256             mutable IndexClassificatorVector	maActionClassVector;
257 
258             /// Metafile to retrieve subset info from
259             ::boost::shared_ptr< GDIMetaFile >	mpMtf;
260 
261             /// Subset of the metafile represented by this object
262             DocTreeNode                         maSubset;
263 
264             /// the list of subset shapes spawned from this one.
265             ShapeSet							maSubsetShapes;
266 
267             /// caches minimal subset index from maSubsetShapes
268             sal_Int32							mnMinSubsetActionIndex;
269 
270             /// caches maximal subset index from maSubsetShapes
271             sal_Int32							mnMaxSubsetActionIndex;
272 
273             /** Current number of subsets to render (calculated from
274                 maSubset and mnMin/MaxSubsetActionIndex).
275 
276                 Note that this is generally _not_ equivalent to
277                 maSubset, as it excludes all active subset children!
278              */
279             mutable VectorOfDocTreeNodes		maCurrentSubsets;
280 
281             /// Whether the shape's doc tree has been initialized successfully, or not
282             mutable bool						mbNodeTreeInitialized;
283         };
284 
285     }
286 }
287 
288 #endif /* INCLUDED_SLIDESHOW_DRAWSHAPESUBSETTING_HXX */
289