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