blob: 563dcc45c5c79577519998cd23f9a01bad2405a1 [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 if (!resList)
292 return;
that0f425062015-03-04 23:05:00 +0100293
294 for (xml_node<>* child = resList->first_node(); child; child = child->next_sibling())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200295 {
that0f425062015-03-04 23:05:00 +0100296 std::string type = child->name();
297 if (type == "resource") {
298 // legacy format : <resource type="...">
299 xml_attribute<>* attr = child->first_attribute("type");
300 type = attr ? attr->value() : "*unspecified*";
301 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400302
that74ac6062015-03-04 22:39:34 +0100303 bool error = false;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200304 if (type == "font")
305 {
that74ac6062015-03-04 22:39:34 +0100306 FontResource* res = new FontResource(child, pZip);
307 if (res->GetResource())
308 mFonts.push_back(res);
309 else {
310 error = true;
311 delete res;
312 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200313 }
314 else if (type == "image")
315 {
Ethan Yonker63e414f2015-02-06 15:44:39 -0600316 int retain = 0;
317 xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect");
318 if (retain_aspect_ratio)
319 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 +0100320 ImageResource* res = new ImageResource(child, pZip, retain);
321 if (res->GetResource())
322 mImages.push_back(res);
323 else {
324 error = true;
325 delete res;
326 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200327 }
328 else if (type == "animation")
329 {
Ethan Yonker63e414f2015-02-06 15:44:39 -0600330 int retain = 0;
331 xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect");
332 if (retain_aspect_ratio)
333 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 +0100334 AnimationResource* res = new AnimationResource(child, pZip, retain);
335 if (res->GetResourceCount())
336 mAnimations.push_back(res);
337 else {
338 error = true;
339 delete res;
340 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200341 }
342 else
343 {
344 LOGERR("Resource type (%s) not supported.\n", type.c_str());
that74ac6062015-03-04 22:39:34 +0100345 error = true;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200346 }
thatf6ed8fc2015-02-14 20:23:16 +0100347
that74ac6062015-03-04 22:39:34 +0100348 if (error)
thatf74ac872015-01-18 12:00:02 +0100349 {
350 std::string res_name;
351 if (child->first_attribute("name"))
352 res_name = child->first_attribute("name")->value();
353 if (res_name.empty() && child->first_attribute("filename"))
354 res_name = child->first_attribute("filename")->value();
355
356 if (!res_name.empty()) {
357 LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
358 } else
359 LOGERR("Resource type (%s) failed to load\n", type.c_str());
thatf74ac872015-01-18 12:00:02 +0100360 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200361 }
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}