sw_engine: implement linear gradient feature
[platform/core/graphics/tizenvg.git] / src / lib / tvgSceneImpl.h
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *  Licensed under the Apache License, Version 2.0 (the "License");
5  *  you may not use this file except in compliance with the License.
6  *  You may obtain a copy of the License at
7  *
8  *               http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *  Unless required by applicable law or agreed to in writing, software
11  *  distributed under the License is distributed on an "AS IS" BASIS,
12  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *  See the License for the specific language governing permissions and
14  *  limitations under the License.
15  *
16  */
17 #ifndef _TVG_SCENE_IMPL_H_
18 #define _TVG_SCENE_IMPL_H_
19
20 #include "tvgCommon.h"
21
22 /************************************************************************/
23 /* Internal Class Implementation                                        */
24 /************************************************************************/
25
26 struct Scene::Impl
27 {
28     vector<Paint*> paints;
29     RenderTransform *transform = nullptr;
30     uint32_t flag = RenderUpdateFlag::None;
31
32     ~Impl()
33     {
34         //Are you sure clear() prior to this?
35         assert(paints.empty());
36         if (transform) delete(transform);
37     }
38
39     bool clear(RenderMethod& renderer)
40     {
41         for (auto paint : paints) {
42             if (paint->id() == PAINT_ID_SCENE) {
43                 //We know renderer type, avoid dynamic_cast for performance.
44                 auto scene = static_cast<Scene*>(paint);
45                 if (!SCENE_IMPL->clear(renderer)) return false;
46             } else {
47                 auto shape = static_cast<Shape*>(paint);
48                 if (!SHAPE_IMPL->dispose(*shape, renderer)) return false;
49             }
50             delete(paint);
51         }
52         paints.clear();
53
54         return true;
55     }
56
57     bool updateInternal(RenderMethod &renderer, const RenderTransform* transform, uint32_t flag)
58     {
59         for(auto paint: paints) {
60             if (paint->id() == PAINT_ID_SCENE) {
61                 //We know renderer type, avoid dynamic_cast for performance.
62                 auto scene = static_cast<Scene*>(paint);
63                 if (!SCENE_IMPL->update(renderer, transform, flag)) return false;
64             } else {
65                 auto shape = static_cast<Shape*>(paint);
66                 if (!SHAPE_IMPL->update(*shape, renderer, transform, flag)) return false;
67             }
68         }
69         return true;
70     }
71
72     bool update(RenderMethod &renderer, const RenderTransform* pTransform = nullptr, uint32_t pFlag = 0)
73     {
74         if (flag & RenderUpdateFlag::Transform) {
75             if (!transform) return false;
76             if (!transform->update()) {
77                 delete(transform);
78                 transform = nullptr;
79             }
80         }
81
82         auto ret = true;
83
84         if (transform && pTransform) {
85             RenderTransform outTransform(pTransform, transform);
86             ret = updateInternal(renderer, &outTransform, pFlag | flag);
87         } else {
88             auto outTransform = pTransform ? pTransform : transform;
89             ret = updateInternal(renderer, outTransform, pFlag | flag);
90         }
91
92         flag = RenderUpdateFlag::None;
93
94         return ret;
95     }
96
97     bool render(RenderMethod &renderer)
98     {
99         for(auto paint: paints) {
100             if (paint->id() == PAINT_ID_SCENE) {
101                 //We know renderer type, avoid dynamic_cast for performance.
102                 auto scene = static_cast<Scene*>(paint);
103                 if(!SCENE_IMPL->render(renderer)) return false;
104             } else {
105                 auto shape = static_cast<Shape*>(paint);
106                 if(!SHAPE_IMPL->render(*shape, renderer)) return false;
107             }
108         }
109         return true;
110     }
111
112     bool bounds(float* px, float* py, float* pw, float* ph)
113     {
114         auto x = FLT_MAX;
115         auto y = FLT_MAX;
116         auto w = 0.0f;
117         auto h = 0.0f;
118
119         for(auto paint: paints) {
120             auto x2 = FLT_MAX;
121             auto y2 = FLT_MAX;
122             auto w2 = 0.0f;
123             auto h2 = 0.0f;
124
125             if (paint->id() == PAINT_ID_SCENE) {
126                 //We know renderer type, avoid dynamic_cast for performance.
127                 auto scene = static_cast<Scene*>(paint);
128                 if (!SCENE_IMPL->bounds(&x2, &y2, &w2, &h2)) return false;
129             } else {
130                 auto shape = static_cast<Shape*>(paint);
131                 if (!SHAPE_IMPL->bounds(&x2, &y2, &w2, &h2)) return false;
132             }
133
134             //Merge regions
135             if (x2 < x) x = x2;
136             if (x + w < x2 + w2) w = (x2 + w2) - x;
137             if (y2 < y) y = x2;
138             if (y + h < y2 + h2) h = (y2 + h2) - y;
139         }
140
141         if (px) *px = x;
142         if (py) *py = y;
143         if (pw) *pw = w;
144         if (ph) *ph = h;
145
146         return true;
147     }
148
149     bool scale(float factor)
150     {
151         if (transform) {
152             if (fabsf(factor - transform->factor) <= FLT_EPSILON) return true;
153         } else {
154             if (fabsf(factor) <= FLT_EPSILON) return true;
155             transform = new RenderTransform();
156             if (!transform) return false;
157         }
158         transform->factor = factor;
159         flag |= RenderUpdateFlag::Transform;
160
161         return true;
162     }
163
164     bool rotate(float degree)
165     {
166         if (transform) {
167             if (fabsf(degree - transform->degree) <= FLT_EPSILON) return true;
168         } else {
169             if (fabsf(degree) <= FLT_EPSILON) return true;
170             transform = new RenderTransform();
171             if (!transform) return false;
172         }
173         transform->degree = degree;
174         flag |= RenderUpdateFlag::Transform;
175
176         return true;
177     }
178
179     bool translate(float x, float y)
180     {
181         if (transform) {
182             if (fabsf(x - transform->x) <= FLT_EPSILON && fabsf(y - transform->y) <= FLT_EPSILON) return true;
183         } else {
184             if (fabsf(x) <= FLT_EPSILON && fabsf(y) <= FLT_EPSILON) return true;
185             transform = new RenderTransform();
186             if (!transform) return false;
187         }
188         transform->x = x;
189         transform->y = y;
190         flag |= RenderUpdateFlag::Transform;
191
192         return true;
193     }
194 };
195
196 #endif //_TVG_SCENE_IMPL_H_