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