common composite: code refactoring
[platform/core/graphics/tizenvg.git] / src / lib / tvgPaint.h
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
3
4  * Permission is hereby granted, free of charge, to any person obtaining a copy
5  * of this software and associated documentation files (the "Software"), to deal
6  * in the Software without restriction, including without limitation the rights
7  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8  * copies of the Software, and to permit persons to whom the Software is
9  * furnished to do so, subject to the following conditions:
10
11  * The above copyright notice and this permission notice shall be included in all
12  * copies or substantial portions of the Software.
13
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20  * SOFTWARE.
21  */
22 #ifndef _TVG_PAINT_H_
23 #define _TVG_PAINT_H_
24
25 #include <float.h>
26 #include <math.h>
27 #include "tvgRender.h"
28
29
30 namespace tvg
31 {
32     struct StrategyMethod
33     {
34         virtual ~StrategyMethod() {}
35
36         virtual bool dispose(RenderMethod& renderer) = 0;
37         virtual void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag) = 0;   //Return engine data if it has.
38         virtual bool render(RenderMethod& renderer) = 0;
39         virtual bool bounds(float* x, float* y, float* w, float* h) const = 0;
40         virtual bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const = 0;
41         virtual Paint* duplicate() = 0;
42     };
43
44     struct Paint::Impl
45     {
46         StrategyMethod* smethod = nullptr;
47         RenderTransform *rTransform = nullptr;
48         uint32_t flag = RenderUpdateFlag::None;
49
50         Paint* compTarget = nullptr;
51         CompositeMethod compMethod = CompositeMethod::None;
52
53         uint8_t opacity = 255;
54
55         ~Impl() {
56             if (compTarget) delete(compTarget);
57             if (smethod) delete(smethod);
58             if (rTransform) delete(rTransform);
59         }
60
61         void method(StrategyMethod* method)
62         {
63             smethod = method;
64         }
65
66         bool rotate(float degree)
67         {
68             if (rTransform) {
69                 if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true;
70             } else {
71                 if (fabsf(degree) <= FLT_EPSILON) return true;
72                 rTransform = new RenderTransform();
73                 if (!rTransform) return false;
74             }
75             rTransform->degree = degree;
76             if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
77
78             return true;
79         }
80
81         bool scale(float factor)
82         {
83             if (rTransform) {
84                 if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true;
85             } else {
86                 if (fabsf(factor) <= FLT_EPSILON) return true;
87                 rTransform = new RenderTransform();
88                 if (!rTransform) return false;
89             }
90             rTransform->scale = factor;
91             if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
92
93             return true;
94         }
95
96         bool translate(float x, float y)
97         {
98             if (rTransform) {
99                 if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true;
100             } else {
101                 if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true;
102                 rTransform = new RenderTransform();
103                 if (!rTransform) return false;
104             }
105             rTransform->x = x;
106             rTransform->y = y;
107             if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
108
109             return true;
110         }
111
112         bool transform(const Matrix& m)
113         {
114             if (!rTransform) {
115                 rTransform = new RenderTransform();
116                 if (!rTransform) return false;
117             }
118             rTransform->override(m);
119             flag |= RenderUpdateFlag::Transform;
120
121             return true;
122         }
123
124         bool bounds(float* x, float* y, float* w, float* h) const
125         {
126             return smethod->bounds(x, y, w, h);
127         }
128
129         bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const
130         {
131             return smethod->bounds(renderer, x, y, w, h);
132         }
133
134         bool dispose(RenderMethod& renderer)
135         {
136             if (compTarget) compTarget->pImpl->dispose(renderer);
137             return smethod->dispose(renderer);
138         }
139
140         void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, uint32_t pFlag)
141         {
142             if (flag & RenderUpdateFlag::Transform) {
143                 if (!rTransform) return nullptr;
144                 if (!rTransform->update()) {
145                     delete(rTransform);
146                     rTransform = nullptr;
147                 }
148             }
149
150             void *compdata = nullptr;
151
152             if (compTarget) {
153                 compdata = compTarget->pImpl->update(renderer, pTransform, opacity, clips, pFlag);
154                 if (compMethod == CompositeMethod::ClipPath) clips.push(compdata);
155             }
156
157             void *edata = nullptr;
158             auto newFlag = static_cast<RenderUpdateFlag>(pFlag | flag);
159             flag = RenderUpdateFlag::None;
160             opacity = (opacity * this->opacity) / 255;
161
162             if (rTransform && pTransform) {
163                 RenderTransform outTransform(pTransform, rTransform);
164                 edata = smethod->update(renderer, &outTransform, opacity, clips, newFlag);
165             } else {
166                 auto outTransform = pTransform ? pTransform : rTransform;
167                 edata = smethod->update(renderer, outTransform, opacity, clips, newFlag);
168             }
169
170             if (compdata) clips.pop();
171
172             return edata;
173         }
174
175         bool render(RenderMethod& renderer)
176         {
177             void* cmp = nullptr;
178
179             /* Note: only ClipPath is processed in update() step */
180             if (compTarget && compMethod != CompositeMethod::ClipPath) {
181                 uint32_t x, y, w, h;
182                 if (!compTarget->pImpl->bounds(renderer, &x, &y, &w, &h)) return false;
183                 cmp = renderer.addCompositor(compMethod, x, y, w, h, 255);
184                 compTarget->pImpl->render(renderer);
185             }
186
187             auto ret = smethod->render(renderer);
188
189             renderer.delCompositor(cmp);
190
191             return ret;
192         }
193
194         Paint* duplicate()
195         {
196             auto ret = smethod->duplicate();
197
198             //duplicate Transform
199             if (ret && rTransform) {
200                 ret->pImpl->rTransform = new RenderTransform();
201                 if (ret->pImpl->rTransform) {
202                     *ret->pImpl->rTransform = *rTransform;
203                     ret->pImpl->flag |= RenderUpdateFlag::Transform;
204                 }
205             }
206
207             ret->pImpl->opacity = opacity;
208
209             return ret;
210         }
211
212         bool composite(Paint* target, CompositeMethod method)
213         {
214             if (!target && method != CompositeMethod::None) return false;
215             if (target && method == CompositeMethod::None) return false;
216             compTarget = target;
217             compMethod = method;
218             return true;
219         }
220     };
221
222
223     template<class T>
224     struct PaintMethod : StrategyMethod
225     {
226         T* inst = nullptr;
227
228         PaintMethod(T* _inst) : inst(_inst) {}
229         ~PaintMethod() {}
230
231         bool bounds(float* x, float* y, float* w, float* h) const override
232         {
233             return inst->bounds(x, y, w, h);
234         }
235
236         bool bounds(RenderMethod& renderer, uint32_t* x, uint32_t* y, uint32_t* w, uint32_t* h) const override
237         {
238             return inst->bounds(renderer, x, y, w, h);
239         }
240
241         bool dispose(RenderMethod& renderer) override
242         {
243             return inst->dispose(renderer);
244         }
245
246         void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag flag) override
247         {
248             return inst->update(renderer, transform, opacity, clips, flag);
249         }
250
251         bool render(RenderMethod& renderer) override
252         {
253             return inst->render(renderer);
254         }
255
256         Paint* duplicate() override
257         {
258             return inst->duplicate();
259         }
260     };
261 }
262
263 #endif //_TVG_PAINT_H_