Files
android_bootable_recovery/gui/resources.cpp
Ethan Yonker 619a721a30 Improve resource error logging
Actually display the name of the item or the filename of the item
that we were unable to load in the log to make it easier to
determine what went wrong.

Change-Id: I027b35aab286e4d0f1957bcfb28ed40d81f9bbb2
2014-12-12 17:10:20 +01:00

348 lines
7.3 KiB
C++

// resource.cpp - Source to manage GUI resources
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/reboot.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <time.h>
#include <unistd.h>
#include <stdlib.h>
#include <string>
#include <sstream>
#include <iostream>
#include <iomanip>
extern "C" {
#include "../twcommon.h"
#include "../minuitwrp/minui.h"
}
#include "rapidxml.hpp"
#include "objects.hpp"
#define TMP_RESOURCE_NAME "/tmp/extract.bin"
Resource::Resource(xml_node<>* node, ZipArchive* pZip)
{
if (node && node->first_attribute("name"))
mName = node->first_attribute("name")->value();
}
int Resource::ExtractResource(ZipArchive* pZip, std::string folderName, std::string fileName, std::string fileExtn, std::string destFile)
{
if (!pZip)
return -1;
std::string src = folderName + "/" + fileName + fileExtn;
const ZipEntry* binary = mzFindZipEntry(pZip, src.c_str());
if (binary == NULL) {
return -1;
}
unlink(destFile.c_str());
int fd = creat(destFile.c_str(), 0666);
if (fd < 0)
return -1;
int ret = 0;
if (!mzExtractZipEntryToFile(pZip, binary, fd))
ret = -1;
close(fd);
return ret;
}
FontResource::FontResource(xml_node<>* node, ZipArchive* pZip)
: Resource(node, pZip)
{
std::string file;
xml_attribute<>* attr;
mFont = NULL;
if (!node)
return;
attr = node->first_attribute("filename");
if (!attr)
return;
file = attr->value();
#ifndef TW_DISABLE_TTF
if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
{
m_type = TYPE_TTF;
attr = node->first_attribute("size");
if(!attr)
return;
int size = atoi(attr->value());
int dpi = 300;
attr = node->first_attribute("dpi");
if(attr)
dpi = atoi(attr->value());
if (ExtractResource(pZip, "fonts", file, "", TMP_RESOURCE_NAME) == 0)
{
mFont = gr_ttf_loadFont(TMP_RESOURCE_NAME, size, dpi);
unlink(TMP_RESOURCE_NAME);
}
else
{
file = std::string("/res/fonts/") + file;
mFont = gr_ttf_loadFont(file.c_str(), size, dpi);
}
}
else
#endif
{
m_type = TYPE_TWRP;
if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
{
attr = node->first_attribute("fallback");
if (!attr)
return;
file = attr->value();
}
if (ExtractResource(pZip, "fonts", file, ".dat", TMP_RESOURCE_NAME) == 0)
{
mFont = gr_loadFont(TMP_RESOURCE_NAME);
unlink(TMP_RESOURCE_NAME);
}
else
{
mFont = gr_loadFont(file.c_str());
}
}
}
FontResource::~FontResource()
{
if(mFont)
{
#ifndef TW_DISABLE_TTF
if(m_type == TYPE_TTF)
gr_ttf_freeFont(mFont);
else
#endif
gr_freeFont(mFont);
}
}
ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip)
: Resource(node, pZip)
{
std::string file;
mSurface = NULL;
if (!node) {
LOGERR("ImageResource node is NULL\n");
return;
}
if (node->first_attribute("filename"))
file = node->first_attribute("filename")->value();
if (ExtractResource(pZip, "images", file, ".png", TMP_RESOURCE_NAME) == 0)
{
res_create_surface(TMP_RESOURCE_NAME, &mSurface);
unlink(TMP_RESOURCE_NAME);
}
else if (ExtractResource(pZip, "images", file, "", TMP_RESOURCE_NAME) == 0)
{
// JPG includes the .jpg extension in the filename so extension should be blank
res_create_surface(TMP_RESOURCE_NAME, &mSurface);
unlink(TMP_RESOURCE_NAME);
}
else
res_create_surface(file.c_str(), &mSurface);
}
ImageResource::~ImageResource()
{
if (mSurface)
res_free_surface(mSurface);
}
AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip)
: Resource(node, pZip)
{
std::string file;
int fileNum = 1;
if (!node)
return;
if (node->first_attribute("filename"))
file = node->first_attribute("filename")->value();
for (;;)
{
std::ostringstream fileName;
fileName << file << std::setfill ('0') << std::setw (3) << fileNum;
gr_surface surface;
if (pZip)
{
if (ExtractResource(pZip, "images", fileName.str(), ".png", TMP_RESOURCE_NAME) != 0)
break;
if (res_create_surface(TMP_RESOURCE_NAME, &surface))
break;
unlink(TMP_RESOURCE_NAME);
}
else
{
if (res_create_surface(fileName.str().c_str(), &surface))
break;
}
mSurfaces.push_back(surface);
fileNum++;
}
}
AnimationResource::~AnimationResource()
{
std::vector<gr_surface>::iterator it;
for (it = mSurfaces.begin(); it != mSurfaces.end(); ++it)
res_free_surface(*it);
mSurfaces.clear();
}
Resource* ResourceManager::FindResource(std::string name)
{
std::vector<Resource*>::iterator iter;
for (iter = mResources.begin(); iter != mResources.end(); iter++)
{
if (name == (*iter)->GetName())
return (*iter);
}
return NULL;
}
ResourceManager::ResourceManager(xml_node<>* resList, ZipArchive* pZip)
{
LoadResources(resList, pZip);
}
void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip)
{
xml_node<>* child;
if (!resList)
return;
child = resList->first_node("resource");
while (child != NULL)
{
xml_attribute<>* attr = child->first_attribute("type");
if (!attr)
break;
std::string type = attr->value();
if (type == "font")
{
FontResource* res = new FontResource(child, pZip);
if (res == NULL || res->GetResource() == NULL)
{
std::string res_name;
if (child->first_attribute("name"))
res_name = child->first_attribute("name")->value();
if (res_name.empty() && child->first_attribute("filename"))
res_name = child->first_attribute("filename")->value();
if (!res_name.empty()) {
LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
} else
LOGERR("Resource type (%s) failed to load\n", type.c_str());
delete res;
}
else
{
mResources.push_back((Resource*) res);
}
}
else if (type == "image")
{
ImageResource* res = new ImageResource(child, pZip);
if (res == NULL || res->GetResource() == NULL)
{
std::string res_name;
if (child->first_attribute("name"))
res_name = child->first_attribute("name")->value();
if (res_name.empty() && child->first_attribute("filename"))
res_name = child->first_attribute("filename")->value();
if (!res_name.empty()) {
LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
} else
LOGERR("Resource type (%s) failed to load\n", type.c_str());
delete res;
}
else
{
mResources.push_back((Resource*) res);
}
}
else if (type == "animation")
{
AnimationResource* res = new AnimationResource(child, pZip);
if (res == NULL || res->GetResource() == NULL)
{
std::string res_name;
if (child->first_attribute("name"))
res_name = child->first_attribute("name")->value();
if (res_name.empty() && child->first_attribute("filename"))
res_name = child->first_attribute("filename")->value();
if (!res_name.empty()) {
LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
} else
LOGERR("Resource type (%s) failed to load\n", type.c_str());
delete res;
}
else
{
mResources.push_back((Resource*) res);
}
}
else
{
LOGERR("Resource type (%s) not supported.\n", type.c_str());
}
child = child->next_sibling("resource");
}
}
ResourceManager::~ResourceManager()
{
std::vector<Resource*>::iterator iter;
for (iter = mResources.begin(); iter != mResources.end(); iter++)
delete *iter;
mResources.clear();
}