1 /*
2 * Copyright (c) 2021 - 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 "tvgCommon.h"
27 #include "tvgSaveModule.h"
28 #include "tvgPaint.h"
29
30 #ifdef THORVG_TVG_SAVER_SUPPORT
31 #include "tvgTvgSaver.h"
32 #endif
33 #ifdef THORVG_GIF_SAVER_SUPPORT
34 #include "tvgGifSaver.h"
35 #endif
36
37 /************************************************************************/
38 /* Internal Class Implementation */
39 /************************************************************************/
40
41 struct Saver::Impl
42 {
43 SaveModule* saveModule = nullptr;
44 Paint* bg = nullptr;
45
~ImplSaver::Impl46 ~Impl()
47 {
48 delete(saveModule);
49 delete(bg);
50 }
51 };
52
53
_find(FileType type)54 static SaveModule* _find(FileType type)
55 {
56 switch(type) {
57 case FileType::Tvg: {
58 #ifdef THORVG_TVG_SAVER_SUPPORT
59 return new TvgSaver;
60 #endif
61 break;
62 }
63 case FileType::Gif: {
64 #ifdef THORVG_GIF_SAVER_SUPPORT
65 return new GifSaver;
66 #endif
67 break;
68 }
69 default: {
70 break;
71 }
72 }
73
74 #ifdef THORVG_LOG_ENABLED
75 const char *format;
76 switch(type) {
77 case FileType::Tvg: {
78 format = "TVG";
79 break;
80 }
81 case FileType::Gif: {
82 format = "GIF";
83 break;
84 }
85 default: {
86 format = "???";
87 break;
88 }
89 }
90 TVGLOG("RENDERER", "%s format is not supported", format);
91 #endif
92 return nullptr;
93 }
94
95
_find(const string & path)96 static SaveModule* _find(const string& path)
97 {
98 auto ext = path.substr(path.find_last_of(".") + 1);
99 if (!ext.compare("tvg")) {
100 return _find(FileType::Tvg);
101 } else if (!ext.compare("gif")) {
102 return _find(FileType::Gif);
103 }
104 return nullptr;
105 }
106
107
108 /************************************************************************/
109 /* External Class Implementation */
110 /************************************************************************/
111
Saver()112 Saver::Saver() : pImpl(new Impl())
113 {
114 }
115
116
~Saver()117 Saver::~Saver()
118 {
119 delete(pImpl);
120 }
121
122
save(std::unique_ptr<Paint> paint,const string & path,bool compress)123 Result Saver::save(std::unique_ptr<Paint> paint, const string& path, bool compress) noexcept
124 {
125 auto p = paint.release();
126 if (!p) return Result::MemoryCorruption;
127
128 //Already on saving another resource.
129 if (pImpl->saveModule) {
130 if (P(p)->refCnt == 0) delete(p);
131 return Result::InsufficientCondition;
132 }
133
134 if (auto saveModule = _find(path)) {
135 if (saveModule->save(p, path, compress)) {
136 pImpl->saveModule = saveModule;
137 return Result::Success;
138 } else {
139 if (P(p)->refCnt == 0) delete(p);
140 delete(saveModule);
141 return Result::Unknown;
142 }
143 }
144 if (P(p)->refCnt == 0) delete(p);
145 return Result::NonSupport;
146 }
147
148
background(unique_ptr<Paint> paint)149 Result Saver::background(unique_ptr<Paint> paint) noexcept
150 {
151 delete(pImpl->bg);
152 pImpl->bg = paint.release();
153
154 return Result::Success;
155 }
156
157
save(unique_ptr<Animation> animation,const string & path,uint32_t quality,uint32_t fps)158 Result Saver::save(unique_ptr<Animation> animation, const string& path, uint32_t quality, uint32_t fps) noexcept
159 {
160 auto a = animation.release();
161 if (!a) return Result::MemoryCorruption;
162
163 //animation holds the picture, it must be 1 at the bottom.
164 auto remove = PP(a->picture())->refCnt <= 1 ? true : false;
165
166 if (tvg::zero(a->totalFrame())) {
167 if (remove) delete(a);
168 return Result::InsufficientCondition;
169 }
170
171 //Already on saving another resource.
172 if (pImpl->saveModule) {
173 if (remove) delete(a);
174 return Result::InsufficientCondition;
175 }
176
177 if (auto saveModule = _find(path)) {
178 if (saveModule->save(a, pImpl->bg, path, quality, fps)) {
179 pImpl->saveModule = saveModule;
180 return Result::Success;
181 } else {
182 if (remove) delete(a);
183 delete(saveModule);
184 return Result::Unknown;
185 }
186 }
187 if (remove) delete(a);
188 return Result::NonSupport;
189 }
190
191
sync()192 Result Saver::sync() noexcept
193 {
194 if (!pImpl->saveModule) return Result::InsufficientCondition;
195 pImpl->saveModule->close();
196 delete(pImpl->saveModule);
197 pImpl->saveModule = nullptr;
198
199 return Result::Success;
200 }
201
202
gen()203 unique_ptr<Saver> Saver::gen() noexcept
204 {
205 return unique_ptr<Saver>(new Saver);
206 }
207
208 #endif /* LV_USE_THORVG_INTERNAL */
209
210