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_DRAWINGLAYER_PRIMITIVE2D_BASEPRIMITIVE2D_HXX
25 #define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BASEPRIMITIVE2D_HXX
26 
27 #include <drawinglayer/drawinglayerdllapi.h>
28 #include <cppuhelper/compbase1.hxx>
29 #include <boost/utility.hpp>
30 #include <com/sun/star/graphic/XPrimitive2D.hpp>
31 #include <comphelper/broadcasthelper.hxx>
32 #include <basegfx/range/b2drange.hxx>
33 
34 //////////////////////////////////////////////////////////////////////////////
35 /** defines for DeclPrimitrive2DIDBlock and ImplPrimitrive2DIDBlock
36     Added to be able to simply change identification stuff later, e.g. add
37     a identification string and/or ID to the interface and to the implementation
38     ATM used to delclare implement getPrimitive2DID()
39 */
40 
41 #define DeclPrimitrive2DIDBlock() \
42 	virtual sal_uInt32 getPrimitive2DID() const;
43 
44 #define ImplPrimitrive2DIDBlock(TheClass, TheID) \
45 	sal_uInt32 TheClass::getPrimitive2DID() const { return TheID; }
46 
47 //////////////////////////////////////////////////////////////////////////////
48 // predefines
49 
50 namespace drawinglayer { namespace geometry {
51 	class ViewInformation2D;
52 }}
53 
54 namespace drawinglayer { namespace primitive2d {
55 	/// typedefs for basePrimitive2DImplBase, Primitive2DSequence and Primitive2DReference
56 	typedef cppu::WeakComponentImplHelper1< ::com::sun::star::graphic::XPrimitive2D > BasePrimitive2DImplBase;
57 	typedef ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XPrimitive2D > Primitive2DReference;
58 	typedef ::com::sun::star::uno::Sequence< Primitive2DReference > Primitive2DSequence;
59 }}
60 
61 //////////////////////////////////////////////////////////////////////////////
62 // basePrimitive2D class
63 
64 namespace drawinglayer
65 {
66 	namespace primitive2d
67 	{
68         /** BasePrimitive2D class
69 
70             Baseclass for all C++ implementations of com::sun::star::graphic::XPrimitive2D
71 
72             This class is strongly virtual due to the lack of getPrimitiveID() implementation.
73             This is by purpose, this base class shall not be incarnated and be used directly as
74             a XPrimitive2D.
75 
76             Is is derived from boost::noncopyable to make clear that a primitive is a read-only
77             instance and copying or changing values is not intended. The idea is to hold all data
78             needed for visualisation of this primitive in unchangeable form.
79 
80             It is derived from comphelper::OBaseMutex to have a Mutex at hand; in a base
81             implementation this may not be needed, but e.g. when buffering at last decomposition
82             in a local member, multiple threads may try to decompose at the same time, so locking
83             is needed to avoid race conditions seen from the UNO object implementation.
84 
85             A method to get a simplified representation is provided by get2DDecomposition. The
86             default implementation returns an empty sequence. The idea is that processors
87             using this primitive and do not know it, may get the decomposition and process
88             these instead. An example is e.g. a fat line, who's decomposition may contain
89             the geometric representation of that line using filled polygon prmimitives. When
90             the renderer knows how to handle fat lines, he may process this primitive directly;
91             if not he can use the decomposition. With this functionality, renderers may operate by
92             knowing only a small set of primitives.
93 
94             When a primitive does not implement get2DDecomposition, it is called a 'Basic Primitive' and
95             belongs to the set of primitives which a processor should be able to handle. Practice
96             will define this minimal sets of primitives. When defined and the concept is proved,
97             unique UNO APIs may be defined/implemented for these set to allow more intense work
98             with primitives using UNO.
99 
100             Current Basic 2D Primitives are:
101 
102             - BitmapPrimitive2D (bitmap data, evtl. with transparence)
103             - PointArrayPrimitive2D (single points)
104             - PolygonHairlinePrimitive2D (hairline curves/polygons)
105             - PolyPolygonColorPrimitive2D (colored polygons)
106 
107             UPDATE: MetafilePrimitive2D (VCL Metafile) is taken off this list since
108             it is implemented with the integration of CWS aw078 into DV300m69.
109 
110             All other implemented primitives have a defined decomposition and can thus be
111             decomposed down to this small set.
112 
113             A renderer implementing support for this minimal set of primitives can completely
114             render primitive-based visualisations. Of course, he also has to take states into account
115             which are representated by GroupPrimitive2D derivations, see groupprimitive2d.hxx
116 
117             To support getting the geometric BoundRect, getB2DRange is used. The default
118             implementation will use the get2DDecomposition result and merge a range from the
119             entries. Thus, an implementation is only necessary for the Basic Primitives, but
120             of course speedups are possible (and are used) by implementing the method at higher-level
121             primitives.
122 
123             For primitive identification, getPrimitiveID is used currently in this implementations
124             to allow a fast switch/case processing. This needs a unique identifier mechanism which
125             currently uses defines (see drawinglayer_primitivetypes2d.hxx). For UNO prmitive API
126             it will be needed to add a unique descriptor (Name?) later to the API.
127 
128             This base implementation provides mappings from the methods from XPrimitive2D
129             (getDecomposition/getRange) to the appropriate methods in the C++ implementations
130             (get2DDecomposition/getB2DRange). The PropertyValue ViewParameters is converted to
131             the appropriate C++ implementation class ViewInformation2D.
132 
133             This base class does not implement any buffering; e.g. buffering the decompositon
134             and/or the range. These may be buffered anytime since the definition is that the primitive
135             is read-only and thus unchangeable. This implies that the decomposition and/or getting
136             the range will lead to the same result as last time, under the precondition that
137             the parameter ViewInformation2D is the same as the last one. This is usually the case
138             for view-independent primitives which are defined by not using ViewInformation2D
139             in their get2DDecomposition/getB2DRange implementations.
140          */
141 		class DRAWINGLAYER_DLLPUBLIC BasePrimitive2D
142 		:	private boost::noncopyable,
143 			protected comphelper::OBaseMutex,
144 			public BasePrimitive2DImplBase
145 		{
146 		private:
147 		protected:
148 		public:
149 			// constructor/destructor
150 			BasePrimitive2D();
151             virtual ~BasePrimitive2D();
152 
153 			/** the ==operator is mainly needed to allow testing newly-created primitives against their last
154 			    incarnation which buffers/holds the made decompositions. The default implementation
155 			    uses getPrimitive2DID()-calls to test if it's the same ID at last. Overloaded implementation are then
156 			    based on this implementation
157              */
158 			virtual bool operator==( const BasePrimitive2D& rPrimitive ) const;
operator !=(const BasePrimitive2D & rPrimitive) const159 			bool operator!=( const BasePrimitive2D& rPrimitive ) const { return !operator==(rPrimitive); }
160 
161 			/// The default implementation will use getDecomposition results to create the range
162 			virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const;
163 
164 			/** provide unique ID for fast identifying of known primitive implementations in renderers. These use
165 			    the defines from primitivetypes2d.hxx to define unique IDs.
166 			    This method is normally defined using DeclPrimitrive2DIDBlock()
167              */
168 			virtual sal_uInt32 getPrimitive2DID() const = 0;
169 
170 			/// The default implementation will return an empty sequence
171 			virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
172 
173 			//
174 			// Methods from XPrimitive2D
175 			//
176 
177 			/** The getDecomposition implementation for UNO API will use getDecomposition from this implementation. It
178 			    will construct a ViewInformation2D from the ViewParameters for that purpose
179              */
180 			virtual Primitive2DSequence SAL_CALL getDecomposition( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rViewParameters ) throw ( ::com::sun::star::uno::RuntimeException );
181 
182 			/** The getRange implementation for UNO API will use getRange from this implementation. It
183 			    will construct a ViewInformation2D from the ViewParameters for that purpose
184              */
185 			virtual ::com::sun::star::geometry::RealRectangle2D SAL_CALL getRange( const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rViewParameters ) throw ( ::com::sun::star::uno::RuntimeException );
186 		};
187 	} // end of namespace primitive2d
188 } // end of namespace drawinglayer
189 
190 //////////////////////////////////////////////////////////////////////////////
191 // BufferedDecompositionPrimitive2D class
192 
193 namespace drawinglayer
194 {
195 	namespace primitive2d
196 	{
197         /** BufferedDecompositionPrimitive2D class
198 
199             Baseclass for all C++ implementations of com::sun::star::graphic::XPrimitive2D
200             which want to buffer the decomoposition result
201 
202             Buffering the decomposition is the most-used buffering and is thus used my most
203             primitive implementations which support a decomposition as base class.
204 
205             The buffering is done by holding the last decomposition in the local parameter
206             maBuffered2DDecomposition. The default implementation of get2DDecomposition checks
207             if maBuffered2DDecomposition is empty. If yes, it uses create2DDecomposition
208             to create the content. In all cases, maBuffered2DDecomposition is returned.
209 
210             For view-dependent primitives derived from Primitive2DBufferDecomposition more needs
211             to be done when the decomposition depends on parts of the parameter ViewInformation2D.
212             This defines a standard method for processing these:
213 
214             Implement a view-dependent get2DDecomposition doing te following steps:
215             (a) Locally extract needed parameters from ViewInformation2D to new, local parameters
216                 (this may be a complete local copy of ViewInformation2D)
217             (b) If a buffered decomposition exists, ckeck if one of the new local parameters
218                 differs from the corresponding locally remembered (as member) ones. If yes,
219                 clear maBuffered2DDecomposition
220             (d) call baseclass::get2DDecomposition which will use create2DDecomposition
221                 to fill maBuffered2DDecomposition if it's empty
222             (e) copy the new local parameters to the corresponding locally remembered ones
223                 to identify if a new decomposition is needed at the next call
224             (f) return maBuffered2DDecomposition
225          */
226 		class DRAWINGLAYER_DLLPUBLIC BufferedDecompositionPrimitive2D
227 		:	public BasePrimitive2D
228 		{
229 		private:
230 			/// a sequence used for buffering the last create2DDecomposition() result
231 			Primitive2DSequence								maBuffered2DDecomposition;
232 
233 		protected:
234 			/** access methods to maBuffered2DDecomposition. The usage of this methods may allow
235 			    later thread-safe stuff to be added if needed. Only to be used by getDecomposition()
236 			    implementations for buffering the last decomposition.
237              */
getBuffered2DDecomposition() const238 			const Primitive2DSequence& getBuffered2DDecomposition() const { return maBuffered2DDecomposition; }
setBuffered2DDecomposition(const Primitive2DSequence & rNew)239 			void setBuffered2DDecomposition(const Primitive2DSequence& rNew) { maBuffered2DDecomposition = rNew; }
240 
241 			/** method which is to be used to implement the local decomposition of a 2D primitive. The default
242 			    implementation will just return an empty decomposition
243              */
244 			virtual Primitive2DSequence create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
245 
246 		public:
247 			// constructor/destructor
248 			BufferedDecompositionPrimitive2D();
249 
250 			/** The getDecomposition default implementation will on demand use create2DDecomposition() if
251                 maBuffered2DDecomposition is empty. It will set maBuffered2DDecomposition to this obtained decomposition
252                 to buffer it. If the decomposition is also ViewInformation2D-dependent, this method needs to be
253                 overloaded and the ViewInformation2D for the last decomposition need to be remembered, too, and
254                 be used in the next call to decide if the buffered decomposition may be reused or not.
255              */
256 			virtual Primitive2DSequence get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const;
257 		};
258 	} // end of namespace primitive2d
259 } // end of namespace drawinglayer
260 
261 //////////////////////////////////////////////////////////////////////////////
262 // tooling
263 
264 namespace drawinglayer
265 {
266 	namespace primitive2d
267 	{
268         /// support to handle a sequence of primitives as stl vector and convert it during creation
269 	    typedef ::std::vector< BasePrimitive2D* > Primitive2DVector;
270         Primitive2DSequence DRAWINGLAYER_DLLPUBLIC Primitive2DVectorToPrimitive2DSequence(const Primitive2DVector& rSource, bool bInvert = false);
271 
272         /// get B2DRange from a given Primitive2DReference
273 		basegfx::B2DRange DRAWINGLAYER_DLLPUBLIC getB2DRangeFromPrimitive2DReference(const Primitive2DReference& rCandidate, const geometry::ViewInformation2D& aViewInformation);
274 
275 		/// get B2DRange from a given Primitive2DSequence
276 		basegfx::B2DRange DRAWINGLAYER_DLLPUBLIC getB2DRangeFromPrimitive2DSequence(const Primitive2DSequence& rCandidate, const geometry::ViewInformation2D& aViewInformation);
277 
278 		/** compare two Primitive2DReferences for equality, including trying to get implementations (BasePrimitive2D)
279 		    and using compare operator
280          */
281 		bool DRAWINGLAYER_DLLPUBLIC arePrimitive2DReferencesEqual(const Primitive2DReference& rA, const Primitive2DReference& rB);
282 
283 		/// compare two Primitive2DReferences for equality, uses arePrimitive2DReferencesEqual internally
284 		bool DRAWINGLAYER_DLLPUBLIC arePrimitive2DSequencesEqual(const Primitive2DSequence& rA, const Primitive2DSequence& rB);
285 
286 		/// concatenate sequence
287 		void DRAWINGLAYER_DLLPUBLIC appendPrimitive2DSequenceToPrimitive2DSequence(Primitive2DSequence& rDest, const Primitive2DSequence& rSource);
288 
289 		/// concatenate single Primitive2D
290 		void DRAWINGLAYER_DLLPUBLIC appendPrimitive2DReferenceToPrimitive2DSequence(Primitive2DSequence& rDest, const Primitive2DReference& rSource);
291 
292 	} // end of namespace primitive2d
293 } // end of namespace drawinglayer
294 
295 //////////////////////////////////////////////////////////////////////////////
296 
297 #endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_BASEPRIMITIVE2D_HXX
298 
299 //////////////////////////////////////////////////////////////////////////////
300 // eof
301