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_PROCESSOR2D_BASEPROCESSOR2D_HXX 25 #define INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX 26 27 #include <drawinglayer/drawinglayerdllapi.h> 28 #include <drawinglayer/primitive2d/baseprimitive2d.hxx> 29 #include <drawinglayer/geometry/viewinformation2d.hxx> 30 31 ////////////////////////////////////////////////////////////////////////////// 32 33 namespace drawinglayer 34 { 35 namespace processor2d 36 { 37 /** BaseProcessor2D class 38 39 Baseclass for all C++ implementations of instances which process 40 primitives. 41 42 Instances which process primitives can be renderers, but also stuff 43 for HitTests, BoundRect calculations and/or animation processing. The 44 main usage are renderers, but they are supposed to handle any primitive 45 processing. 46 47 The base implementation is constructed with a ViewInformation2D which 48 is accessible throughout the processor implementations. The idea is 49 to construct any processor with a given ViewInformation2D. To be able 50 to handle primitives which need to change the current transformation 51 (as e.g. TransformPrimitive2D) it is allowed for the processor implementation 52 to change tis local value using updateViewInformation. 53 54 The basic processing method is process(..) which gets handed over the 55 sequence of primitives to process. For convenience of the C++ implementations, 56 the default implementation of process(..) maps all accesses to primitives to 57 single calls to processBasePrimitive2D(..) where the primitive in question is 58 already casted to the C++ implementation class. 59 60 The process(..) implementation makes a complete iteration over the given 61 sequence of primitives. If the Primitive is not derived from BasePrimitive2D 62 and thus not part of the C++ implementations, it converts ViewInformation2D 63 to the corresponding API implementation (an uno::Sequence< beans::PropertyValue >) 64 and recursively calls the method process(..) at the primitive with the decomposition 65 derived from that primitive. This is the preparation to handle unknown implementations 66 of the com::sun::star::graphic::XPrimitive2D interface in the future. 67 68 So, to implement a basic processor, it is necessary to overload and implement the 69 processBasePrimitive2D(..) method. A minimal renderer has to support the 70 Basic Primitives (see baseprimitive2d.hxx) and the Grouping Primitives (see 71 groupprimitive2d.hxx). These are (currently): 72 73 Basic Primitives: 74 75 - BitmapPrimitive2D (bitmap data, evtl. with transparence) 76 - PointArrayPrimitive2D (single points) 77 - PolygonHairlinePrimitive2D (hairline curves/polygons) 78 - PolyPolygonColorPrimitive2D (colored polygons) 79 80 Grouping Primitives: 81 82 - TransparencePrimitive2D (objects with freely defined transparence) 83 - InvertPrimitive2D (for XOR) 84 - MaskPrimitive2D (for masking) 85 - ModifiedColorPrimitive2D (for a stack of color modifications) 86 - TransformPrimitive2D (for a transformation stack) 87 88 A processor doing so is a minimal processor. Of course a processor may 89 handle any higher-level prmitive (that has a decomposition implementation) 90 for more direct data access or performance reasons, too. 91 92 The main part of a processBasePrimitive2D implementation is a switch..case 93 construct, looking like the following: 94 95 void foo::processBasePrimitive2D(const BasePrimitive2D& rCandidate) 96 { 97 switch(rCandidate.getPrimitive2DID()) 98 { 99 case PRIMITIVE2D_ID_??? : 100 { 101 // process PRIMITIVE2D_ID_??? here... 102 103 ... 104 105 break; 106 } 107 108 ... 109 110 default : 111 { 112 // process recursively 113 process(rCandidate.get2DDecomposition(getViewInformation2D())); 114 break; 115 } 116 } 117 } 118 119 The default case makes the processor work with all complex primitives 120 by recursively using their decomposition. 121 122 You can also add a case for ignoring primitives by using: 123 124 case PRIMITIVE2D_ID_...IGNORE.A.. : 125 case PRIMITIVE2D_ID_...IGNORE.B.. : 126 case PRIMITIVE2D_ID_...IGNORE.C.. : 127 { 128 // ignore these primitives by neither processing nor 129 // recursively processing their decomposition 130 break; 131 } 132 133 Another useful case is embedding the processing of a complex primitive by 134 bracketing it with some actions: 135 136 case PRIMITIVE2D_ID_SOME_TEXT : 137 { 138 // encapsulate e.g. with changing local varibles, e.g. 139 // sometimes it's good to know if a basic primitive is 140 // part of a text, especially when not handling the text 141 // self but by purpose want to handle the decomposed 142 // geometries in the processor 143 startText(); 144 process(rCandidate.get2DDecomposition(getViewInformation2D())); 145 endText(); 146 break; 147 } 148 149 As an example a processor collecting the outlines of a sequence of primitives 150 only needs to handle some Basic Primitives and create outline and collect 151 outline polygons e.g. for primitives with area like BitmapPrimitive2D (a 152 rectangle) and PolyPolygonColorPrimitive2D. When also handling the Grouping 153 Primitives MaskPrimitive2D (e.g. ignoring it's content, using the mask polyPolygon) 154 and TransformPrimitive2D (to have the correct local transformation), a processor 155 creating the outline can be written using just four (4) primitives. As a tipp, it can 156 be helpful to add many for the purpose not interesting higher level primitives 157 to not force their decomposition to be created and/or parsed. 158 */ 159 class DRAWINGLAYER_DLLPUBLIC BaseProcessor2D 160 { 161 private: 162 /// The ViewInformation2D itself. It's private to isolate accesses to it 163 geometry::ViewInformation2D maViewInformation2D; 164 165 protected: 166 /* access method to allow the implementations to change the current 167 ViewInformation2D if needed. This allows isolating these accesses 168 later if needed 169 */ updateViewInformation(const geometry::ViewInformation2D & rViewInformation2D)170 void updateViewInformation(const geometry::ViewInformation2D& rViewInformation2D) 171 { 172 maViewInformation2D = rViewInformation2D; 173 } 174 175 /* as tooling, the process() implementation takes over API handling and calls this 176 virtual render method when the primitive implementation is BasePrimitive2D-based. 177 Default implementation does nothing 178 */ 179 virtual void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate); 180 181 public: 182 /// constructor/destructor 183 BaseProcessor2D(const geometry::ViewInformation2D& rViewInformation); 184 virtual ~BaseProcessor2D(); 185 186 /// the central processing method 187 virtual void process(const primitive2d::Primitive2DSequence& rSource); 188 189 /// data read access getViewInformation2D() const190 const geometry::ViewInformation2D& getViewInformation2D() const { return maViewInformation2D; } 191 }; 192 } // end of namespace processor2d 193 } // end of namespace drawinglayer 194 195 ////////////////////////////////////////////////////////////////////////////// 196 197 #endif //INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX 198 199 // eof 200