blob: e0016fc7bf90fd89bdafa41dd02e24e080645e14 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001// resource.cpp - Source to manage GUI resources
2
3#include <stdarg.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include <fcntl.h>
8#include <sys/reboot.h>
9#include <sys/stat.h>
10#include <sys/time.h>
11#include <sys/mman.h>
12#include <sys/types.h>
13#include <sys/ioctl.h>
14#include <time.h>
15#include <unistd.h>
16#include <stdlib.h>
17
18#include <string>
19#include <sstream>
20#include <iostream>
21#include <iomanip>
22
23extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000024#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040025#include "../minuitwrp/minui.h"
Ethan Yonker63e414f2015-02-06 15:44:39 -060026#include "gui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040027}
28
29#include "rapidxml.hpp"
30#include "objects.hpp"
31
32#define TMP_RESOURCE_NAME "/tmp/extract.bin"
33
34Resource::Resource(xml_node<>* node, ZipArchive* pZip)
35{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020036 if (node && node->first_attribute("name"))
37 mName = node->first_attribute("name")->value();
Dees_Troy51a0e822012-09-05 15:24:24 -040038}
39
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020040int Resource::ExtractResource(ZipArchive* pZip, std::string folderName, std::string fileName, std::string fileExtn, std::string destFile)
Dees_Troy51a0e822012-09-05 15:24:24 -040041{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020042 if (!pZip)
43 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040044
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020045 std::string src = folderName + "/" + fileName + fileExtn;
Dees_Troy51a0e822012-09-05 15:24:24 -040046
47 const ZipEntry* binary = mzFindZipEntry(pZip, src.c_str());
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020048 if (binary == NULL) {
49 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040050 }
51
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020052 unlink(destFile.c_str());
53 int fd = creat(destFile.c_str(), 0666);
54 if (fd < 0)
55 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040056
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020057 int ret = 0;
58 if (!mzExtractZipEntryToFile(pZip, binary, fd))
59 ret = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -040060
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020061 close(fd);
62 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -040063}
64
Ethan Yonker63e414f2015-02-06 15:44:39 -060065void Resource::LoadImage(ZipArchive* pZip, std::string file, gr_surface* source)
66{
67 if (ExtractResource(pZip, "images", file, ".png", TMP_RESOURCE_NAME) == 0)
68 {
69 res_create_surface(TMP_RESOURCE_NAME, source);
70 unlink(TMP_RESOURCE_NAME);
71 }
72 else if (ExtractResource(pZip, "images", file, "", TMP_RESOURCE_NAME) == 0)
73 {
74 // JPG includes the .jpg extension in the filename so extension should be blank
75 res_create_surface(TMP_RESOURCE_NAME, source);
76 unlink(TMP_RESOURCE_NAME);
77 }
78 else if (!pZip)
79 {
80 // File name in xml may have included .png so try without adding .png
81 res_create_surface(file.c_str(), source);
82 }
83}
84
85void Resource::CheckAndScaleImage(gr_surface source, gr_surface* destination, int retain_aspect)
86{
87 if (!source) {
88 *destination = NULL;
89 return;
90 }
91 if (get_scale_w() != 0 && get_scale_h() != 0) {
92 float scale_w = get_scale_w(), scale_h = get_scale_h();
93 if (retain_aspect) {
94 if (scale_w < scale_h)
95 scale_h = scale_w;
96 else
97 scale_w = scale_h;
98 }
99 if (res_scale_surface(source, destination, scale_w, scale_h)) {
100 LOGINFO("Error scaling image, using regular size.\n");
101 *destination = source;
102 }
103 } else {
104 *destination = source;
105 }
106}
107
Dees_Troy51a0e822012-09-05 15:24:24 -0400108FontResource::FontResource(xml_node<>* node, ZipArchive* pZip)
109 : Resource(node, pZip)
110{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200111 std::string file;
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200112 xml_attribute<>* attr;
Dees_Troy51a0e822012-09-05 15:24:24 -0400113
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200114 mFont = NULL;
115 if (!node)
116 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400117
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200118 attr = node->first_attribute("filename");
119 if (!attr)
120 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400121
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200122 file = attr->value();
123
124#ifndef TW_DISABLE_TTF
125 if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200126 {
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200127 m_type = TYPE_TTF;
128
129 attr = node->first_attribute("size");
130 if(!attr)
131 return;
132
Ethan Yonker63e414f2015-02-06 15:44:39 -0600133 int size = scale_theme_min(atoi(attr->value()));
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200134 int dpi = 300;
135
136 attr = node->first_attribute("dpi");
137 if(attr)
138 dpi = atoi(attr->value());
139
140 if (ExtractResource(pZip, "fonts", file, "", TMP_RESOURCE_NAME) == 0)
141 {
142 mFont = gr_ttf_loadFont(TMP_RESOURCE_NAME, size, dpi);
143 unlink(TMP_RESOURCE_NAME);
144 }
145 else
146 {
Dees Troy3454ade2015-01-20 19:21:04 +0000147 file = std::string(TWRES "fonts/") + file;
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200148 mFont = gr_ttf_loadFont(file.c_str(), size, dpi);
149 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200150 }
151 else
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200152#endif
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200153 {
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200154 m_type = TYPE_TWRP;
155
156 if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
157 {
158 attr = node->first_attribute("fallback");
159 if (!attr)
160 return;
161
162 file = attr->value();
163 }
164
165 if (ExtractResource(pZip, "fonts", file, ".dat", TMP_RESOURCE_NAME) == 0)
166 {
167 mFont = gr_loadFont(TMP_RESOURCE_NAME);
168 unlink(TMP_RESOURCE_NAME);
169 }
170 else
171 {
172 mFont = gr_loadFont(file.c_str());
173 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200174 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400175}
176
177FontResource::~FontResource()
178{
Vojtech Bocek76ee9032014-09-07 15:01:56 +0200179 if(mFont)
180 {
181#ifndef TW_DISABLE_TTF
182 if(m_type == TYPE_TTF)
183 gr_ttf_freeFont(mFont);
184 else
185#endif
186 gr_freeFont(mFont);
187 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400188}
189
Ethan Yonker63e414f2015-02-06 15:44:39 -0600190ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip, int retain_aspect)
Dees_Troy51a0e822012-09-05 15:24:24 -0400191 : Resource(node, pZip)
192{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200193 std::string file;
Ethan Yonker63e414f2015-02-06 15:44:39 -0600194 gr_surface temp_surface = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400195
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200196 mSurface = NULL;
Ethan Yonker619a7212014-12-03 16:47:37 -0600197 if (!node) {
198 LOGERR("ImageResource node is NULL\n");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200199 return;
Ethan Yonker619a7212014-12-03 16:47:37 -0600200 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400201
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200202 if (node->first_attribute("filename"))
203 file = node->first_attribute("filename")->value();
Ethan Yonker63e414f2015-02-06 15:44:39 -0600204 else {
205 LOGERR("No filename specified for image resource.\n");
206 return;
207 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400208
Ethan Yonker63e414f2015-02-06 15:44:39 -0600209 LoadImage(pZip, file, &temp_surface);
210 CheckAndScaleImage(temp_surface, &mSurface, retain_aspect);
Dees_Troy51a0e822012-09-05 15:24:24 -0400211}
212
213ImageResource::~ImageResource()
214{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200215 if (mSurface)
216 res_free_surface(mSurface);
Dees_Troy51a0e822012-09-05 15:24:24 -0400217}
218
Ethan Yonker63e414f2015-02-06 15:44:39 -0600219AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip, int retain_aspect)
Dees_Troy51a0e822012-09-05 15:24:24 -0400220 : Resource(node, pZip)
221{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200222 std::string file;
223 int fileNum = 1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400224
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200225 if (!node)
226 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400227
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200228 if (node->first_attribute("filename"))
229 file = node->first_attribute("filename")->value();
Ethan Yonker63e414f2015-02-06 15:44:39 -0600230 else {
231 LOGERR("No filename specified for image resource.\n");
232 return;
233 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400234
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200235 for (;;)
236 {
237 std::ostringstream fileName;
238 fileName << file << std::setfill ('0') << std::setw (3) << fileNum;
Dees_Troy51a0e822012-09-05 15:24:24 -0400239
Ethan Yonker63e414f2015-02-06 15:44:39 -0600240 gr_surface surface, temp_surface = NULL;
241 LoadImage(pZip, fileName.str(), &temp_surface);
242 CheckAndScaleImage(temp_surface, &surface, retain_aspect);
243 if (surface) {
244 mSurfaces.push_back(surface);
245 fileNum++;
246 } else
247 break; // Done loading animation images
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200248 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400249}
250
251AnimationResource::~AnimationResource()
252{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200253 std::vector<gr_surface>::iterator it;
Dees_Troy51a0e822012-09-05 15:24:24 -0400254
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200255 for (it = mSurfaces.begin(); it != mSurfaces.end(); ++it)
256 res_free_surface(*it);
257
258 mSurfaces.clear();
Dees_Troy51a0e822012-09-05 15:24:24 -0400259}
260
261Resource* ResourceManager::FindResource(std::string name)
262{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200263 std::vector<Resource*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400264
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200265 for (iter = mResources.begin(); iter != mResources.end(); iter++)
266 {
267 if (name == (*iter)->GetName())
268 return (*iter);
269 }
270 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400271}
272
273ResourceManager::ResourceManager(xml_node<>* resList, ZipArchive* pZip)
274{
Ethan Yonker780cd392014-07-21 15:24:39 -0500275 LoadResources(resList, pZip);
276}
277
278void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip)
279{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200280 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400281
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200282 if (!resList)
283 return;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200284 child = resList->first_node("resource");
285 while (child != NULL)
286 {
287 xml_attribute<>* attr = child->first_attribute("type");
288 if (!attr)
289 break;
Dees_Troy51a0e822012-09-05 15:24:24 -0400290
thatf74ac872015-01-18 12:00:02 +0100291 Resource* res = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400292 std::string type = attr->value();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200293 if (type == "font")
294 {
thatf74ac872015-01-18 12:00:02 +0100295 res = new FontResource(child, pZip);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200296 }
297 else if (type == "image")
298 {
Ethan Yonker63e414f2015-02-06 15:44:39 -0600299 int retain = 0;
300 xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect");
301 if (retain_aspect_ratio)
302 retain = 1; // the value does not matter, if retainaspect is present, we assume that we want to retain it
303 res = new ImageResource(child, pZip, retain);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200304 }
305 else if (type == "animation")
306 {
Ethan Yonker63e414f2015-02-06 15:44:39 -0600307 int retain = 0;
308 xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect");
309 if (retain_aspect_ratio)
310 retain = 1; // the value does not matter, if retainaspect is present, we assume that we want to retain it
311 res = new AnimationResource(child, pZip, retain);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200312 }
313 else
314 {
315 LOGERR("Resource type (%s) not supported.\n", type.c_str());
316 }
thatf6ed8fc2015-02-14 20:23:16 +0100317
318 if (res == NULL || !res->loadedOK())
thatf74ac872015-01-18 12:00:02 +0100319 {
320 std::string res_name;
321 if (child->first_attribute("name"))
322 res_name = child->first_attribute("name")->value();
323 if (res_name.empty() && child->first_attribute("filename"))
324 res_name = child->first_attribute("filename")->value();
325
326 if (!res_name.empty()) {
327 LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
328 } else
329 LOGERR("Resource type (%s) failed to load\n", type.c_str());
330
331 delete res;
332 }
333 else
334 {
335 mResources.push_back(res);
336 }
337
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200338 child = child->next_sibling("resource");
339 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400340}
341
342ResourceManager::~ResourceManager()
343{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200344 std::vector<Resource*>::iterator iter;
Dees_Troy51a0e822012-09-05 15:24:24 -0400345
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200346 for (iter = mResources.begin(); iter != mResources.end(); iter++)
347 delete *iter;
348
349 mResources.clear();
Dees_Troy51a0e822012-09-05 15:24:24 -0400350}