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 proccess 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 prooved, 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 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