common sw_engine: code refactoring & stabilizing.
[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<Composite>& compList, 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 Paint* duplicate() = 0;
41     };
42
43     struct Paint::Impl
44     {
45         StrategyMethod* smethod = nullptr;
46         RenderTransform *rTransform = nullptr;
47         uint32_t flag = RenderUpdateFlag::None;
48
49         Paint* compTarget = nullptr;
50         CompositeMethod compMethod = CompositeMethod::None;
51
52         uint8_t opacity = 255;
53
54         ~Impl() {
55             if (compTarget) delete(compTarget);
56             if (smethod) delete(smethod);
57             if (rTransform) delete(rTransform);
58         }
59
60         void method(StrategyMethod* method)
61         {
62             smethod = method;
63         }
64
65         bool rotate(float degree)
66         {
67             if (rTransform) {
68                 if (fabsf(degree - rTransform->degree) <= FLT_EPSILON) return true;
69             } else {
70                 if (fabsf(degree) <= FLT_EPSILON) return true;
71                 rTransform = new RenderTransform();
72                 if (!rTransform) return false;
73             }
74             rTransform->degree = degree;
75             if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
76
77             return true;
78         }
79
80         bool scale(float factor)
81         {
82             if (rTransform) {
83                 if (fabsf(factor - rTransform->scale) <= FLT_EPSILON) return true;
84             } else {
85                 if (fabsf(factor) <= FLT_EPSILON) return true;
86                 rTransform = new RenderTransform();
87                 if (!rTransform) return false;
88             }
89             rTransform->scale = factor;
90             if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
91
92             return true;
93         }
94
95         bool translate(float x, float y)
96         {
97             if (rTransform) {
98                 if (fabsf(x - rTransform->x) <= FLT_EPSILON && fabsf(y - rTransform->y) <= FLT_EPSILON) return true;
99             } else {
100                 if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true;
101                 rTransform = new RenderTransform();
102                 if (!rTransform) return false;
103             }
104             rTransform->x = x;
105             rTransform->y = y;
106             if (!rTransform->overriding) flag |= RenderUpdateFlag::Transform;
107
108             return true;
109         }
110
111         bool transform(const Matrix& m)
112         {
113             if (!rTransform) {
114                 rTransform = new RenderTransform();
115                 if (!rTransform) return false;
116             }
117             rTransform->override(m);
118             flag |= RenderUpdateFlag::Transform;
119
120             return true;
121         }
122
123         bool bounds(float* x, float* y, float* w, float* h) const
124         {
125             return smethod->bounds(x, y, w, h);
126         }
127
128         bool dispose(RenderMethod& renderer)
129         {
130             if (compTarget) compTarget->pImpl->dispose(renderer);
131             return smethod->dispose(renderer);
132         }
133
134         void* update(RenderMethod& renderer, const RenderTransform* pTransform, uint32_t opacity, Array<Composite>& compList, uint32_t pFlag)
135         {
136             if (flag & RenderUpdateFlag::Transform) {
137                 if (!rTransform) return nullptr;
138                 if (!rTransform->update()) {
139                     delete(rTransform);
140                     rTransform = nullptr;
141                 }
142             }
143
144             void *compdata = nullptr;
145
146             if (compTarget && compMethod == CompositeMethod::ClipPath) {
147                 compdata = compTarget->pImpl->update(renderer, pTransform, opacity, compList, pFlag);
148                 if (compdata) compList.push({compdata, compMethod});
149             }
150
151             void *edata = nullptr;
152             auto newFlag = static_cast<RenderUpdateFlag>(pFlag | flag);
153             flag = RenderUpdateFlag::None;
154             opacity = (opacity * this->opacity) / 255;
155
156             if (rTransform && pTransform) {
157                 RenderTransform outTransform(pTransform, rTransform);
158                 edata = smethod->update(renderer, &outTransform, opacity, compList, newFlag);
159             } else {
160                 auto outTransform = pTransform ? pTransform : rTransform;
161                 edata = smethod->update(renderer, outTransform, opacity, compList, newFlag);
162             }
163
164             if (compdata) compList.pop();
165
166             return edata;
167         }
168
169         bool render(RenderMethod& renderer)
170         {
171             return smethod->render(renderer);
172         }
173
174         Paint* duplicate()
175         {
176             auto ret = smethod->duplicate();
177
178             //duplicate Transform
179             if (ret && rTransform) {
180                 ret->pImpl->rTransform = new RenderTransform();
181                 if (ret->pImpl->rTransform) {
182                     *ret->pImpl->rTransform = *rTransform;
183                     ret->pImpl->flag |= RenderUpdateFlag::Transform;
184                 }
185             }
186
187             ret->pImpl->opacity = opacity;
188
189             return ret;
190         }
191
192         bool composite(Paint* target, CompositeMethod method)
193         {
194             if (!target && method != CompositeMethod::None) return false;
195             compTarget = target;
196             compMethod = method;
197             return true;
198         }
199     };
200
201
202     template<class T>
203     struct PaintMethod : StrategyMethod
204     {
205         T* inst = nullptr;
206
207         PaintMethod(T* _inst) : inst(_inst) {}
208         ~PaintMethod() {}
209
210         bool bounds(float* x, float* y, float* w, float* h) const override
211         {
212             return inst->bounds(x, y, w, h);
213         }
214
215         bool dispose(RenderMethod& renderer) override
216         {
217             return inst->dispose(renderer);
218         }
219
220         void* update(RenderMethod& renderer, const RenderTransform* transform, uint32_t opacity, Array<Composite>& compList, RenderUpdateFlag flag) override
221         {
222             return inst->update(renderer, transform, opacity, compList, flag);
223         }
224
225         bool render(RenderMethod& renderer) override
226         {
227             return inst->render(renderer);
228         }
229
230         Paint* duplicate() override
231         {
232             return inst->duplicate();
233         }
234     };
235 }
236
237 #endif //_TVG_PAINT_H_