blob: 1e2e7f9c6624bb2b8fd884adefdf6f5861a6efdf [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
that74ac6062015-03-04 22:39:34 +0100261FontResource* ResourceManager::FindFont(const std::string& name) const
Dees_Troy51a0e822012-09-05 15:24:24 -0400262{
that74ac6062015-03-04 22:39:34 +0100263 for (std::vector<FontResource*>::const_iterator it = mFonts.begin(); it != mFonts.end(); ++it)
264 if (name == (*it)->GetName())
265 return *it;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200266 return NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -0400267}
268
that74ac6062015-03-04 22:39:34 +0100269ImageResource* ResourceManager::FindImage(const std::string& name) const
Dees_Troy51a0e822012-09-05 15:24:24 -0400270{
that74ac6062015-03-04 22:39:34 +0100271 for (std::vector<ImageResource*>::const_iterator it = mImages.begin(); it != mImages.end(); ++it)
272 if (name == (*it)->GetName())
273 return *it;
274 return NULL;
275}
276
277AnimationResource* ResourceManager::FindAnimation(const std::string& name) const
278{
279 for (std::vector<AnimationResource*>::const_iterator it = mAnimations.begin(); it != mAnimations.end(); ++it)
280 if (name == (*it)->GetName())
281 return *it;
282 return NULL;
283}
284
285ResourceManager::ResourceManager()
286{
Ethan Yonker780cd392014-07-21 15:24:39 -0500287}
288
289void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip)
290{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200291 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -0400292
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200293 if (!resList)
294 return;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200295 child = resList->first_node("resource");
296 while (child != NULL)
297 {
298 xml_attribute<>* attr = child->first_attribute("type");
Dees_Troy51a0e822012-09-05 15:24:24 -0400299
that74ac6062015-03-04 22:39:34 +0100300 bool error = false;
301 std::string type = attr ? attr->value() : "*unspecified*";
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200302 if (type == "font")
303 {
that74ac6062015-03-04 22:39:34 +0100304 FontResource* res = new FontResource(child, pZip);
305 if (res->GetResource())
306 mFonts.push_back(res);
307 else {
308 error = true;
309 delete res;
310 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200311 }
312 else if (type == "image")
313 {
Ethan Yonker63e414f2015-02-06 15:44:39 -0600314 int retain = 0;
315 xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect");
316 if (retain_aspect_ratio)
317 retain = 1; // the value does not matter, if retainaspect is present, we assume that we want to retain it
that74ac6062015-03-04 22:39:34 +0100318 ImageResource* res = new ImageResource(child, pZip, retain);
319 if (res->GetResource())
320 mImages.push_back(res);
321 else {
322 error = true;
323 delete res;
324 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200325 }
326 else if (type == "animation")
327 {
Ethan Yonker63e414f2015-02-06 15:44:39 -0600328 int retain = 0;
329 xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect");
330 if (retain_aspect_ratio)
331 retain = 1; // the value does not matter, if retainaspect is present, we assume that we want to retain it
that74ac6062015-03-04 22:39:34 +0100332 AnimationResource* res = new AnimationResource(child, pZip, retain);
333 if (res->GetResourceCount())
334 mAnimations.push_back(res);
335 else {
336 error = true;
337 delete res;
338 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200339 }
340 else
341 {
342 LOGERR("Resource type (%s) not supported.\n", type.c_str());
that74ac6062015-03-04 22:39:34 +0100343 error = true;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200344 }
thatf6ed8fc2015-02-14 20:23:16 +0100345
that74ac6062015-03-04 22:39:34 +0100346 if (error)
thatf74ac872015-01-18 12:00:02 +0100347 {
348 std::string res_name;
349 if (child->first_attribute("name"))
350 res_name = child->first_attribute("name")->value();
351 if (res_name.empty() && child->first_attribute("filename"))
352 res_name = child->first_attribute("filename")->value();
353
354 if (!res_name.empty()) {
355 LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
356 } else
357 LOGERR("Resource type (%s) failed to load\n", type.c_str());
thatf74ac872015-01-18 12:00:02 +0100358 }
359
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200360 child = child->next_sibling("resource");
361 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400362}
363
364ResourceManager::~ResourceManager()
365{
that74ac6062015-03-04 22:39:34 +0100366 for (std::vector<FontResource*>::iterator it = mFonts.begin(); it != mFonts.end(); ++it)
367 delete *it;
Dees_Troy51a0e822012-09-05 15:24:24 -0400368
that74ac6062015-03-04 22:39:34 +0100369 for (std::vector<ImageResource*>::iterator it = mImages.begin(); it != mImages.end(); ++it)
370 delete *it;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200371
that74ac6062015-03-04 22:39:34 +0100372 for (std::vector<AnimationResource*>::iterator it = mAnimations.begin(); it != mAnimations.end(); ++it)
373 delete *it;
Dees_Troy51a0e822012-09-05 15:24:24 -0400374}