common: nothing was rendered after an empty masked node came across
[platform/core/graphics/tizenvg.git] / src / lib / tvgPictureImpl.h
1 /*
2  * Copyright (c) 2020-2021 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_PICTURE_IMPL_H_
23 #define _TVG_PICTURE_IMPL_H_
24
25 #include <string>
26 #include "tvgPaint.h"
27 #include "tvgLoader.h"
28
29 /************************************************************************/
30 /* Internal Class Implementation                                        */
31 /************************************************************************/
32
33 struct PictureIterator : Iterator
34 {
35     Paint* paint = nullptr;
36     Paint* ptr = nullptr;
37
38     PictureIterator(Paint* p) : paint(p) {}
39
40     const Paint* next() override
41     {
42         if (!ptr) ptr = paint;
43         else ptr = nullptr;
44         return ptr;
45     }
46
47     uint32_t count() override
48     {
49         if (paint) return 1;
50         else return 0;
51     }
52
53     void begin() override
54     {
55         ptr = nullptr;
56     }
57 };
58
59
60 struct Picture::Impl
61 {
62     shared_ptr<LoadModule> loader = nullptr;
63     Paint* paint = nullptr;
64     uint32_t* pixels = nullptr;
65     Picture* picture = nullptr;
66     void* rdata = nullptr;            //engine data
67     float w = 0, h = 0;
68     bool resizing = false;
69
70     Impl(Picture* p) : picture(p)
71     {
72     }
73
74     ~Impl()
75     {
76         if (paint) delete(paint);
77     }
78
79     bool dispose(RenderMethod& renderer)
80     {
81         bool ret = true;
82         if (paint) {
83             ret = paint->pImpl->dispose(renderer);
84         } else if (pixels) {
85             ret =  renderer.dispose(rdata);
86             rdata = nullptr;
87         }
88         return ret;
89     }
90
91     uint32_t reload()
92     {
93         if (loader) {
94             if (!paint) {
95                 if (auto p = loader->paint()) {
96                     paint = p.release();
97                     loader->close();
98                     if (w != loader->w || h != loader->h) {
99                         loader->resize(paint, w, h);
100                         resizing = false;
101                     }
102                     if (paint) return RenderUpdateFlag::None;
103                 }
104             }
105             if (!pixels) {
106                 pixels = const_cast<uint32_t*>(loader->pixels());
107                 loader->close();
108                 if (pixels) return RenderUpdateFlag::Image;
109             }
110         }
111         return RenderUpdateFlag::None;
112     }
113
114     RenderTransform resizeTransform(const RenderTransform* pTransform)
115     {
116         //Overriding Transformation by the desired image size
117         auto sx = w / loader->w;
118         auto sy = h / loader->h;
119         auto scale = sx < sy ? sx : sy;
120
121         RenderTransform tmp;
122         tmp.m = {scale, 0, 0, 0, scale, 0, 0, 0, 1};
123
124         if (!pTransform) return tmp;
125         else return RenderTransform(pTransform, &tmp);
126     }
127
128     void* update(RenderMethod &renderer, const RenderTransform* pTransform, uint32_t opacity, Array<RenderData>& clips, RenderUpdateFlag pFlag)
129     {
130         auto flag = reload();
131
132         if (pixels) {
133             auto transform = resizeTransform(pTransform);
134             rdata = renderer.prepare(*picture, rdata, &transform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
135         } else if (paint) {
136             if (resizing) {
137                 loader->resize(paint, w, h);
138                 resizing = false;
139             }
140             rdata = paint->pImpl->update(renderer, pTransform, opacity, clips, static_cast<RenderUpdateFlag>(pFlag | flag));
141         }
142         return rdata;
143     }
144
145     bool render(RenderMethod &renderer)
146     {
147         if (pixels) return renderer.renderImage(rdata);
148         else if (paint) return paint->pImpl->render(renderer);
149         return false;
150     }
151
152     bool viewbox(float* x, float* y, float* w, float* h) const
153     {
154         if (!loader) return false;
155         if (x) *x = loader->vx;
156         if (y) *y = loader->vy;
157         if (w) *w = loader->vw;
158         if (h) *h = loader->vh;
159         return true;
160     }
161
162     bool size(float w, float h)
163     {
164         this->w = w;
165         this->h = h;
166         resizing = true;
167         return true;
168     }
169
170     bool bounds(float* x, float* y, float* w, float* h)
171     {
172         if (x) *x = 0;
173         if (y) *y = 0;
174         if (w) *w = this->w;
175         if (h) *h = this->h;
176  
177         return true;
178     }
179
180     RenderRegion bounds(RenderMethod& renderer)
181     {
182         if (rdata) return renderer.region(rdata);
183         if (paint) return paint->pImpl->bounds(renderer);
184         return {0, 0, 0, 0};
185     }
186
187     Result load(const string& path)
188     {
189         if (paint || pixels) return Result::InsufficientCondition;
190         if (loader) loader->close();
191         bool invalid;  //Invalid Path
192         loader = LoaderMgr::loader(path, &invalid);
193         if (!loader) {
194             if (invalid) return Result::InvalidArguments;
195             return Result::NonSupport;
196         }
197         if (!loader->read()) return Result::Unknown;
198         w = loader->w;
199         h = loader->h;
200         return Result::Success;
201     }
202
203     Result load(const char* data, uint32_t size, const string& mimeType, bool copy)
204     {
205         if (paint || pixels) return Result::InsufficientCondition;
206         if (loader) loader->close();
207         loader = LoaderMgr::loader(data, size, mimeType, copy);
208         if (!loader) return Result::NonSupport;
209         if (!loader->read()) return Result::Unknown;
210         w = loader->w;
211         h = loader->h;
212         return Result::Success;
213     }
214
215     Result load(uint32_t* data, uint32_t w, uint32_t h, bool copy)
216     {
217         if (paint || pixels) return Result::InsufficientCondition;
218         if (loader) loader->close();
219         loader = LoaderMgr::loader(data, w, h, copy);
220         if (!loader) return Result::NonSupport;
221         this->w = loader->w;
222         this->h = loader->h;
223         return Result::Success;
224     }
225
226     Paint* duplicate()
227     {
228         reload();
229
230         auto ret = Picture::gen();
231         if (!ret) return nullptr;
232
233         auto dup = ret.get()->pImpl;
234         if (paint) dup->paint = paint->duplicate();
235
236         dup->loader = loader;
237         dup->pixels = pixels;
238         dup->w = w;
239         dup->h = h;
240         dup->resizing = resizing;
241
242         return ret.release();
243     }
244
245     Iterator* iterator()
246     {
247         reload();
248         return new PictureIterator(paint);
249     }
250 };
251
252 #endif //_TVG_PICTURE_IMPL_H_