1 /*
2 * Copyright (c) 2020 - 2024 the ThorVG project. 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
23 #include "../../lv_conf_internal.h"
24 #if LV_USE_THORVG_INTERNAL
25
26 #include "tvgPaint.h"
27 #include "tvgPicture.h"
28
29 /************************************************************************/
30 /* Internal Class Implementation */
31 /************************************************************************/
32
load()33 RenderUpdateFlag Picture::Impl::load()
34 {
35 if (loader) {
36 if (paint) {
37 loader->sync();
38 } else {
39 paint = loader->paint();
40 if (paint) {
41 if (w != loader->w || h != loader->h) {
42 if (!resizing) {
43 w = loader->w;
44 h = loader->h;
45 }
46 loader->resize(paint, w, h);
47 resizing = false;
48 }
49 return RenderUpdateFlag::None;
50 }
51 }
52 if (!surface) {
53 if ((surface = loader->bitmap())) {
54 return RenderUpdateFlag::Image;
55 }
56 }
57 }
58 return RenderUpdateFlag::None;
59 }
60
61
needComposition(uint8_t opacity)62 bool Picture::Impl::needComposition(uint8_t opacity)
63 {
64 //In this case, paint(scene) would try composition itself.
65 if (opacity < 255) return false;
66
67 //Composition test
68 const Paint* target;
69 auto method = picture->composite(&target);
70 if (!target || method == tvg::CompositeMethod::ClipPath) return false;
71 if (target->pImpl->opacity == 255 || target->pImpl->opacity == 0) return false;
72
73 return true;
74 }
75
76
render(RenderMethod * renderer)77 bool Picture::Impl::render(RenderMethod* renderer)
78 {
79 bool ret = false;
80 renderer->blend(PP(picture)->blendMethod);
81
82 if (surface) return renderer->renderImage(rd);
83 else if (paint) {
84 RenderCompositor* cmp = nullptr;
85 if (needComp) {
86 cmp = renderer->target(bounds(renderer), renderer->colorSpace());
87 renderer->beginComposite(cmp, CompositeMethod::None, 255);
88 }
89 ret = paint->pImpl->render(renderer);
90 if (cmp) renderer->endComposite(cmp);
91 }
92 return ret;
93 }
94
95
size(float w,float h)96 bool Picture::Impl::size(float w, float h)
97 {
98 this->w = w;
99 this->h = h;
100 resizing = true;
101 return true;
102 }
103
104
bounds(RenderMethod * renderer)105 RenderRegion Picture::Impl::bounds(RenderMethod* renderer)
106 {
107 if (rd) return renderer->region(rd);
108 if (paint) return paint->pImpl->bounds(renderer);
109 return {0, 0, 0, 0};
110 }
111
112
load(ImageLoader * loader)113 Result Picture::Impl::load(ImageLoader* loader)
114 {
115 //Same resource has been loaded.
116 if (this->loader == loader) {
117 this->loader->sharing--; //make it sure the reference counting.
118 return Result::Success;
119 } else if (this->loader) {
120 LoaderMgr::retrieve(this->loader);
121 }
122
123 this->loader = loader;
124
125 if (!loader->read()) return Result::Unknown;
126
127 this->w = loader->w;
128 this->h = loader->h;
129
130 return Result::Success;
131 }
132
133
134
135 /************************************************************************/
136 /* External Class Implementation */
137 /************************************************************************/
138
Picture()139 Picture::Picture() : pImpl(new Impl(this))
140 {
141 }
142
143
~Picture()144 Picture::~Picture()
145 {
146 delete(pImpl);
147 }
148
149
gen()150 unique_ptr<Picture> Picture::gen() noexcept
151 {
152 return unique_ptr<Picture>(new Picture);
153 }
154
155
identifier()156 TVG_DEPRECATED uint32_t Picture::identifier() noexcept
157 {
158 return (uint32_t) Type::Picture;
159 }
160
161
type() const162 Type Picture::type() const noexcept
163 {
164 return Type::Picture;
165 }
166
167
load(const std::string & path)168 Result Picture::load(const std::string& path) noexcept
169 {
170 if (path.empty()) return Result::InvalidArguments;
171
172 return pImpl->load(path);
173 }
174
175
load(const char * data,uint32_t size,const string & mimeType,bool copy)176 Result Picture::load(const char* data, uint32_t size, const string& mimeType, bool copy) noexcept
177 {
178 if (!data || size <= 0) return Result::InvalidArguments;
179
180 return pImpl->load(data, size, mimeType, copy);
181 }
182
183
load(const char * data,uint32_t size,bool copy)184 TVG_DEPRECATED Result Picture::load(const char* data, uint32_t size, bool copy) noexcept
185 {
186 return load(data, size, "", copy);
187 }
188
189
load(uint32_t * data,uint32_t w,uint32_t h,bool copy)190 Result Picture::load(uint32_t* data, uint32_t w, uint32_t h, bool copy) noexcept
191 {
192 if (!data || w <= 0 || h <= 0) return Result::InvalidArguments;
193
194 return pImpl->load(data, w, h, copy);
195 }
196
197
size(float w,float h)198 Result Picture::size(float w, float h) noexcept
199 {
200 if (pImpl->size(w, h)) return Result::Success;
201 return Result::InsufficientCondition;
202 }
203
204
size(float * w,float * h) const205 Result Picture::size(float* w, float* h) const noexcept
206 {
207 if (!pImpl->loader) return Result::InsufficientCondition;
208 if (w) *w = pImpl->w;
209 if (h) *h = pImpl->h;
210 return Result::Success;
211 }
212
213
paint(uint32_t id)214 const Paint* Picture::paint(uint32_t id) noexcept
215 {
216 struct Value
217 {
218 uint32_t id;
219 const Paint* ret;
220 } value = {id, nullptr};
221
222 auto cb = [](const tvg::Paint* paint, void* data) -> bool
223 {
224 auto p = static_cast<Value*>(data);
225 if (p->id == paint->id) {
226 p->ret = paint;
227 return false;
228 }
229 return true;
230 };
231
232 tvg::Accessor::gen()->set(this, cb, &value);
233 return value.ret;
234 }
235
236 #endif /* LV_USE_THORVG_INTERNAL */
237
238