/src/libreoffice/include/drawinglayer/processor2d/baseprocessor2d.hxx
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ |
2 | | /* |
3 | | * This file is part of the LibreOffice project. |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * This file incorporates work covered by the following license notice: |
10 | | * |
11 | | * Licensed to the Apache Software Foundation (ASF) under one or more |
12 | | * contributor license agreements. See the NOTICE file distributed |
13 | | * with this work for additional information regarding copyright |
14 | | * ownership. The ASF licenses this file to you under the Apache |
15 | | * License, Version 2.0 (the "License"); you may not use this file |
16 | | * except in compliance with the License. You may obtain a copy of |
17 | | * the License at http://www.apache.org/licenses/LICENSE-2.0 . |
18 | | */ |
19 | | |
20 | | #ifndef INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX |
21 | | #define INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX |
22 | | |
23 | | #include <drawinglayer/drawinglayerdllapi.h> |
24 | | |
25 | | #include <drawinglayer/primitive2d/Primitive2DVisitor.hxx> |
26 | | #include <drawinglayer/geometry/viewinformation2d.hxx> |
27 | | |
28 | | namespace drawinglayer::primitive2d { class BasePrimitive2D; } |
29 | | namespace drawinglayer::primitive2d { class Primitive2DContainer; } |
30 | | |
31 | | namespace drawinglayer::processor2d |
32 | | { |
33 | | /** BaseProcessor2D class |
34 | | |
35 | | Base class for all C++ implementations of instances which process |
36 | | primitives. |
37 | | |
38 | | Instances which process primitives can be renderers, but also stuff |
39 | | for HitTests, BoundRect calculations and/or animation processing. The |
40 | | main usage are renderers, but they are supposed to handle any primitive |
41 | | processing. |
42 | | |
43 | | The base implementation is constructed with a ViewInformation2D which |
44 | | is accessible throughout the processor implementations. The idea is |
45 | | to construct any processor with a given ViewInformation2D. To be able |
46 | | to handle primitives which need to change the current transformation |
47 | | (as e.g. TransformPrimitive2D) it is allowed for the processor implementation |
48 | | to change its local value using setViewInformation2D. |
49 | | |
50 | | The basic processing method is process(..) which gets handed over the |
51 | | sequence of primitives to process. For convenience of the C++ implementations, |
52 | | the default implementation of process(..) maps all accesses to primitives to |
53 | | single calls to processBasePrimitive2D(..) where the primitive in question is |
54 | | already casted to the C++ implementation class. |
55 | | |
56 | | The process(..) implementation makes a complete iteration over the given |
57 | | sequence of primitives. If the Primitive is not derived from BasePrimitive2D |
58 | | and thus not part of the C++ implementations, it converts ViewInformation2D |
59 | | to the corresponding API implementation (a uno::Sequence< beans::PropertyValue >) |
60 | | and recursively calls the method process(..) at the primitive with the decomposition |
61 | | derived from that primitive. This is the preparation to handle unknown implementations |
62 | | of the css::graphic::XPrimitive2D interface in the future. |
63 | | |
64 | | So, to implement a basic processor, it is necessary to override and implement the |
65 | | processBasePrimitive2D(..) method. A minimal renderer has to support the |
66 | | Basic Primitives (see baseprimitive2d.hxx) and the Grouping Primitives (see |
67 | | groupprimitive2d.hxx). These are (currently): |
68 | | |
69 | | Basic Primitives: |
70 | | |
71 | | - BitmapPrimitive2D (bitmap data, possibly with transparency) |
72 | | - PointArrayPrimitive2D (single points) |
73 | | - PolygonHairlinePrimitive2D (hairline curves/polygons) |
74 | | - PolyPolygonColorPrimitive2D (colored polygons) |
75 | | |
76 | | Grouping Primitives: |
77 | | |
78 | | - TransparencePrimitive2D (objects with freely defined transparence) |
79 | | - InvertPrimitive2D (for XOR) |
80 | | - MaskPrimitive2D (for masking) |
81 | | - ModifiedColorPrimitive2D (for a stack of color modifications) |
82 | | - TransformPrimitive2D (for a transformation stack) |
83 | | |
84 | | A processor doing so is a minimal processor. Of course a processor may |
85 | | handle any higher-level primitive (that has a decomposition implementation) |
86 | | for more direct data access or performance reasons, too. |
87 | | |
88 | | The main part of a processBasePrimitive2D implementation is a switch..case |
89 | | construct, looking like the following: |
90 | | |
91 | | void foo::processBasePrimitive2D(const BasePrimitive2D& rCandidate) |
92 | | { |
93 | | switch(rCandidate.getPrimitive2DID()) |
94 | | { |
95 | | case PRIMITIVE2D_ID_??? : |
96 | | { |
97 | | // process PRIMITIVE2D_ID_??? here... |
98 | | |
99 | | ... |
100 | | |
101 | | break; |
102 | | } |
103 | | |
104 | | ... |
105 | | |
106 | | default : |
107 | | { |
108 | | // process recursively |
109 | | process(rCandidate.get2DDecomposition(getViewInformation2D())); |
110 | | break; |
111 | | } |
112 | | } |
113 | | } |
114 | | |
115 | | The default case makes the processor work with all complex primitives |
116 | | by recursively using their decomposition. |
117 | | |
118 | | You can also add a case for ignoring primitives by using: |
119 | | |
120 | | case PRIMITIVE2D_ID_...IGNORE.A.. : |
121 | | case PRIMITIVE2D_ID_...IGNORE.B.. : |
122 | | case PRIMITIVE2D_ID_...IGNORE.C.. : |
123 | | { |
124 | | // ignore these primitives by neither processing nor |
125 | | // recursively processing their decomposition |
126 | | break; |
127 | | } |
128 | | |
129 | | Another useful case is embedding the processing of a complex primitive by |
130 | | bracketing it with some actions: |
131 | | |
132 | | case PRIMITIVE2D_ID_SOME_TEXT : |
133 | | { |
134 | | // encapsulate e.g. with changing local variables, e.g. |
135 | | // sometimes it's good to know if a basic primitive is |
136 | | // part of a text, especially when not handling the text |
137 | | // self but by purpose want to handle the decomposed |
138 | | // geometries in the processor |
139 | | startText(); |
140 | | process(rCandidate.get2DDecomposition(getViewInformation2D())); |
141 | | endText(); |
142 | | break; |
143 | | } |
144 | | |
145 | | As an example a processor collecting the outlines of a sequence of primitives |
146 | | only needs to handle some Basic Primitives and create outline and collect |
147 | | outline polygons e.g. for primitives with area like BitmapPrimitive2D (a |
148 | | rectangle) and PolyPolygonColorPrimitive2D. When also handling the Grouping |
149 | | Primitives MaskPrimitive2D (e.g. ignoring its content, using the mask polyPolygon) |
150 | | and TransformPrimitive2D (to have the correct local transformation), a processor |
151 | | creating the outline can be written using just four (4) primitives. As a tipp, it can |
152 | | be helpful to add many for the purpose not interesting higher level primitives |
153 | | to not force their decomposition to be created and/or parsed. |
154 | | */ |
155 | | class DRAWINGLAYER_DLLPUBLIC BaseProcessor2D : public drawinglayer::primitive2d::Primitive2DDecompositionVisitor |
156 | | { |
157 | | private: |
158 | | /// The ViewInformation2D itself. It's private to isolate accesses to it |
159 | | geometry::ViewInformation2D maViewInformation2D; |
160 | | |
161 | | protected: |
162 | | /* callback method to allow the implementations to react on changes |
163 | | to the current ViewInformation2D if needed (e.g. when your impl/ |
164 | | derivation needs to react on AA change) |
165 | | */ |
166 | 0 | virtual void onViewInformation2DChanged() {} |
167 | | |
168 | | /* as tooling, the process() implementation takes over API handling and calls this |
169 | | virtual render method when the primitive implementation is BasePrimitive2D-based. |
170 | | Default implementation does nothing |
171 | | */ |
172 | | virtual void processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate); |
173 | | |
174 | | void process(const primitive2d::BasePrimitive2D& rCandidate); |
175 | | |
176 | | // Primitive2DDecompositionVisitor |
177 | | virtual void visit(const primitive2d::Primitive2DReference&) override final; |
178 | | virtual void visit(const primitive2d::Primitive2DContainer&) override final; |
179 | | virtual void visit(primitive2d::Primitive2DContainer&&) override final; |
180 | | |
181 | | public: |
182 | | /// constructor/destructor |
183 | | explicit BaseProcessor2D(geometry::ViewInformation2D aViewInformation); |
184 | | virtual ~BaseProcessor2D(); |
185 | | |
186 | | /// the central processing method |
187 | | void process(const primitive2d::Primitive2DContainer& rSource); |
188 | | |
189 | | /// data read/write access to ViewInformation2D |
190 | 378k | const geometry::ViewInformation2D& getViewInformation2D() const { return maViewInformation2D; } |
191 | | void setViewInformation2D(const geometry::ViewInformation2D& rNew); |
192 | | }; |
193 | | |
194 | | } // end of namespace drawinglayer::processor2d |
195 | | |
196 | | |
197 | | #endif //INCLUDED_DRAWINGLAYER_PROCESSOR2D_BASEPROCESSOR2D_HXX |
198 | | |
199 | | /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |