From 63e414fc8a7ec04a0710a05ac9ce610fbb15f1e5 Mon Sep 17 00:00:00 2001 From: Ethan Yonker Date: Fri, 6 Feb 2015 15:44:39 -0600 Subject: Scale the GUI to fit the screen With this patch set, if needed, we scale the images during early boot. TTF support is needed to properly scale the font. No font scaling is done on the old style fixed width font used in the console. Special thanks to _that for figuring out the scaling and blending function calls to make this possible. Change-Id: If2f79bef16d6db2e1298bfc3d00c9bcca2bee37a --- gui/Android.mk | 3 + gui/devices/1024x600/res/ui.xml | 10 +-- gui/devices/1024x768/res/ui.xml | 10 +-- gui/devices/1080x1920/res/ui.xml | 10 +-- gui/devices/1200x1920/res/ui.xml | 10 +-- gui/devices/1280x800/res/ui.xml | 10 +-- gui/devices/1440x2560/res/ui.xml | 10 +-- gui/devices/1600x2560/res/ui.xml | 10 +-- gui/devices/1920x1200/res/ui.xml | 10 +-- gui/devices/240x240/res/images/cursor.png | Bin 0 -> 1452 bytes gui/devices/240x240/res/ui.xml | 10 +-- gui/devices/2560x1600/res/ui.xml | 10 +-- gui/devices/280x280/res/images/cursor.png | Bin 0 -> 1452 bytes gui/devices/280x280/res/ui.xml | 10 +-- gui/devices/320x320/res/images/cursor.png | Bin 0 -> 1452 bytes gui/devices/320x320/res/ui.xml | 10 +-- gui/devices/320x480/res/ui.xml | 10 +-- gui/devices/480x800/res/ui.xml | 10 +-- gui/devices/480x854/res/ui.xml | 10 +-- gui/devices/540x960/res/ui.xml | 10 +-- gui/devices/720x1280/res/ui.xml | 10 +-- gui/devices/800x1280/res/ui.xml | 10 +-- gui/devices/800x480/res/ui.xml | 10 +-- gui/gui.cpp | 64 ++++++++++++++++- gui/gui.h | 8 +++ gui/input.cpp | 2 +- gui/keyboard.cpp | 7 +- gui/pages.cpp | 56 +++++++++++++++ gui/resources.cpp | 113 ++++++++++++++++++++---------- gui/resources.hpp | 6 +- gui/scrolllist.cpp | 14 ++-- gui/slidervalue.cpp | 8 +-- minuitwrp/minui.h | 2 + minuitwrp/resources.c | 76 +++++++++++++++++++- 34 files changed, 399 insertions(+), 150 deletions(-) create mode 100644 gui/devices/240x240/res/images/cursor.png create mode 100644 gui/devices/280x280/res/images/cursor.png create mode 100644 gui/devices/320x320/res/images/cursor.png diff --git a/gui/Android.mk b/gui/Android.mk index 93913f55a..0b5afe1d8 100644 --- a/gui/Android.mk +++ b/gui/Android.mk @@ -63,6 +63,9 @@ endif ifneq ($(TW_Y_OFFSET),) LOCAL_CFLAGS += -DTW_Y_OFFSET=$(TW_Y_OFFSET) endif +ifeq ($(TW_ROUND_SCREEN), true) + LOCAL_CFLAGS += -DTW_ROUND_SCREEN +endif ifeq ($(DEVICE_RESOLUTION),) $(warning ********************************************************************************) diff --git a/gui/devices/1024x600/res/ui.xml b/gui/devices/1024x600/res/ui.xml index 1669d4586..e76cc950c 100644 --- a/gui/devices/1024x600/res/ui.xml +++ b/gui/devices/1024x600/res/ui.xml @@ -22,10 +22,10 @@ - - - - + + + + @@ -42,7 +42,7 @@ - + diff --git a/gui/devices/1024x768/res/ui.xml b/gui/devices/1024x768/res/ui.xml index 253ae07e5..cfaf48e00 100644 --- a/gui/devices/1024x768/res/ui.xml +++ b/gui/devices/1024x768/res/ui.xml @@ -22,10 +22,10 @@ - - - - + + + + @@ -42,7 +42,7 @@ - + diff --git a/gui/devices/1080x1920/res/ui.xml b/gui/devices/1080x1920/res/ui.xml index ddab4f317..f38462c40 100644 --- a/gui/devices/1080x1920/res/ui.xml +++ b/gui/devices/1080x1920/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/1200x1920/res/ui.xml b/gui/devices/1200x1920/res/ui.xml index c02032fbd..782f0bd44 100644 --- a/gui/devices/1200x1920/res/ui.xml +++ b/gui/devices/1200x1920/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/1280x800/res/ui.xml b/gui/devices/1280x800/res/ui.xml index 94d0bf981..0c7ecf0b9 100644 --- a/gui/devices/1280x800/res/ui.xml +++ b/gui/devices/1280x800/res/ui.xml @@ -22,10 +22,10 @@ - - - - + + + + @@ -42,7 +42,7 @@ - + diff --git a/gui/devices/1440x2560/res/ui.xml b/gui/devices/1440x2560/res/ui.xml index 52bf20776..35bd4c624 100644 --- a/gui/devices/1440x2560/res/ui.xml +++ b/gui/devices/1440x2560/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/1600x2560/res/ui.xml b/gui/devices/1600x2560/res/ui.xml index b85803bb3..8c35ef8a8 100644 --- a/gui/devices/1600x2560/res/ui.xml +++ b/gui/devices/1600x2560/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/1920x1200/res/ui.xml b/gui/devices/1920x1200/res/ui.xml index 4bd85a27a..05a3ee62b 100644 --- a/gui/devices/1920x1200/res/ui.xml +++ b/gui/devices/1920x1200/res/ui.xml @@ -22,10 +22,10 @@ - - - - + + + + @@ -42,7 +42,7 @@ - + diff --git a/gui/devices/240x240/res/images/cursor.png b/gui/devices/240x240/res/images/cursor.png new file mode 100644 index 000000000..32c8ae1ca Binary files /dev/null and b/gui/devices/240x240/res/images/cursor.png differ diff --git a/gui/devices/240x240/res/ui.xml b/gui/devices/240x240/res/ui.xml index f1cd46110..9c3037354 100644 --- a/gui/devices/240x240/res/ui.xml +++ b/gui/devices/240x240/res/ui.xml @@ -3,6 +3,7 @@
+ masteroftime TWRP x201 tDPI Smartwatch Theme @@ -25,10 +26,10 @@ - - - - + + + + @@ -43,6 +44,7 @@ + diff --git a/gui/devices/2560x1600/res/ui.xml b/gui/devices/2560x1600/res/ui.xml index 6da373e56..57945cb77 100644 --- a/gui/devices/2560x1600/res/ui.xml +++ b/gui/devices/2560x1600/res/ui.xml @@ -22,10 +22,10 @@ - - - - + + + + @@ -42,7 +42,7 @@ - + diff --git a/gui/devices/280x280/res/images/cursor.png b/gui/devices/280x280/res/images/cursor.png new file mode 100644 index 000000000..32c8ae1ca Binary files /dev/null and b/gui/devices/280x280/res/images/cursor.png differ diff --git a/gui/devices/280x280/res/ui.xml b/gui/devices/280x280/res/ui.xml index 24e6e4ce5..5eaf1a9a7 100644 --- a/gui/devices/280x280/res/ui.xml +++ b/gui/devices/280x280/res/ui.xml @@ -3,6 +3,7 @@
+ TeamWin Backup Naowz Default basic theme @@ -25,10 +26,10 @@ - - - - + + + + @@ -43,6 +44,7 @@ + diff --git a/gui/devices/320x320/res/images/cursor.png b/gui/devices/320x320/res/images/cursor.png new file mode 100644 index 000000000..32c8ae1ca Binary files /dev/null and b/gui/devices/320x320/res/images/cursor.png differ diff --git a/gui/devices/320x320/res/ui.xml b/gui/devices/320x320/res/ui.xml index 6558d0b23..69d9cbd61 100644 --- a/gui/devices/320x320/res/ui.xml +++ b/gui/devices/320x320/res/ui.xml @@ -3,6 +3,7 @@
+ TeamWin Backup Naowz Default basic theme @@ -25,10 +26,10 @@ - - - - + + + + @@ -43,6 +44,7 @@ + diff --git a/gui/devices/320x480/res/ui.xml b/gui/devices/320x480/res/ui.xml index 70d33e601..d91df4207 100644 --- a/gui/devices/320x480/res/ui.xml +++ b/gui/devices/320x480/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/480x800/res/ui.xml b/gui/devices/480x800/res/ui.xml index 895cfaa48..b1880bad6 100644 --- a/gui/devices/480x800/res/ui.xml +++ b/gui/devices/480x800/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/480x854/res/ui.xml b/gui/devices/480x854/res/ui.xml index c4ce65f35..52a9f4b19 100644 --- a/gui/devices/480x854/res/ui.xml +++ b/gui/devices/480x854/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/540x960/res/ui.xml b/gui/devices/540x960/res/ui.xml index eb6d671bc..5abe640ec 100644 --- a/gui/devices/540x960/res/ui.xml +++ b/gui/devices/540x960/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/720x1280/res/ui.xml b/gui/devices/720x1280/res/ui.xml index 3020daa4f..714ca4c61 100644 --- a/gui/devices/720x1280/res/ui.xml +++ b/gui/devices/720x1280/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/800x1280/res/ui.xml b/gui/devices/800x1280/res/ui.xml index 6f49bf7ff..e4d8b299d 100644 --- a/gui/devices/800x1280/res/ui.xml +++ b/gui/devices/800x1280/res/ui.xml @@ -25,10 +25,10 @@ - - - - + + + + @@ -43,7 +43,7 @@ - + diff --git a/gui/devices/800x480/res/ui.xml b/gui/devices/800x480/res/ui.xml index b80ed3be1..faa0878b7 100644 --- a/gui/devices/800x480/res/ui.xml +++ b/gui/devices/800x480/res/ui.xml @@ -22,10 +22,10 @@ - - - - + + + + @@ -42,7 +42,7 @@ - + diff --git a/gui/gui.cpp b/gui/gui.cpp index 8bdd4251c..35b33b10c 100644 --- a/gui/gui.cpp +++ b/gui/gui.cpp @@ -75,6 +75,8 @@ static TWAtomicInt gForceRender; const int gNoAnimation = 1; blanktimer blankTimer; int ors_read_fd = -1; +static float scale_theme_w = 1; +static float scale_theme_h = 1; // Needed by pages.cpp too int gGuiRunning = 0; @@ -767,13 +769,26 @@ extern "C" int gui_init(void) { gr_init(); std::string curtain_path = TWRES "images/curtain.jpg"; + gr_surface source_Surface = NULL; - if (res_create_surface(curtain_path.c_str(), &gCurtain)) + if (res_create_surface(curtain_path.c_str(), &source_Surface)) { - printf - ("Unable to locate '%s'\nDid you set a DEVICE_RESOLUTION in your config files?\n", curtain_path.c_str()); + printf("Unable to locate '%s'\nDid you set a DEVICE_RESOLUTION in your config files?\n", curtain_path.c_str()); return -1; } + if (gr_get_width(source_Surface) != gr_fb_width() || gr_get_height(source_Surface) != gr_fb_height()) { + // We need to scale the curtain to fit the screen + float scale_w = (float)gr_fb_width() / (float)gr_get_width(source_Surface); + float scale_h = (float)gr_fb_height() / (float)gr_get_height(source_Surface); + if (res_scale_surface(source_Surface, &gCurtain, scale_w, scale_h)) { + LOGINFO("Failed to scale curtain\n"); + gCurtain = source_Surface; + } else { + LOGINFO("Scaling the curtain width %fx and height %fx\n", scale_w, scale_h); + } + } else { + gCurtain = source_Surface; + } curtainSet(); @@ -965,3 +980,46 @@ extern "C" int gui_console_only(void) return 0; } + +extern "C" void set_scale_values(float w, float h) +{ + scale_theme_w = w; + scale_theme_h = h; +} + +extern "C" int scale_theme_x(int initial_x) +{ + if (scale_theme_w != 1) { + return (int) ((float)initial_x * scale_theme_w); + } + return initial_x; +} + +extern "C" int scale_theme_y(int initial_y) +{ + if (scale_theme_h != 1) { + return (int) ((float)initial_y * scale_theme_h); + } + return initial_y; +} + +extern "C" int scale_theme_min(int initial_value) +{ + if (scale_theme_w != 1 || scale_theme_h != 1) { + if (scale_theme_w < scale_theme_h) + return scale_theme_x(initial_value); + else + return scale_theme_y(initial_value); + } + return initial_value; +} + +extern "C" float get_scale_w() +{ + return scale_theme_w; +} + +extern "C" float get_scale_h() +{ + return scale_theme_h; +} diff --git a/gui/gui.h b/gui/gui.h index 5b2cdec18..37d205408 100644 --- a/gui/gui.h +++ b/gui/gui.h @@ -31,5 +31,13 @@ void gui_print(const char *fmt, ...); void gui_print_color(const char *color, const char *fmt, ...); void gui_set_FILE(FILE* f); +void set_scale_values(float w, float h); +int scale_theme_x(int initial_x); +int scale_theme_y(int initial_y); +int scale_theme_min(int initial_value); +float get_scale_w(); +float get_scale_h(); +float get_scale_h(); + #endif // _GUI_HEADER diff --git a/gui/input.cpp b/gui/input.cpp index 21b1f0b86..e89333575 100644 --- a/gui/input.cpp +++ b/gui/input.cpp @@ -127,7 +127,7 @@ GUIInput::GUIInput(xml_node<>* node) if (attr) { std::string cwidth = gui_parse_text(attr->value()); - CursorWidth = atoi(cwidth.c_str()); + CursorWidth = scale_theme_x(atoi(cwidth.c_str())); } } DrawCursor = HasInputFocus; diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp index bbc6ed2d8..db968aee0 100644 --- a/gui/keyboard.cpp +++ b/gui/keyboard.cpp @@ -37,6 +37,7 @@ extern "C" { #include "../twcommon.h" #include "../minuitwrp/minui.h" +#include "gui.h" } #include "rapidxml.hpp" @@ -131,12 +132,12 @@ GUIKeyboard::GUIKeyboard(xml_node<>* node) if (child) { attr = child->first_attribute("height"); if (attr) - keyHeight = atoi(attr->value()); + keyHeight = scale_theme_y(atoi(attr->value())); else keyHeight = 0; attr = child->first_attribute("width"); if (attr) - keyWidth = atoi(attr->value()); + keyWidth = scale_theme_x(atoi(attr->value())); else keyWidth = 0; attr = child->first_attribute("capslock"); @@ -234,7 +235,7 @@ int GUIKeyboard::ParseKey(const char* keyinfo, keyboard_key_class& key, int& Xin keychar = keyinfo[0]; } else { // This key has extra data: {keywidth}:{what_the_key_does} - keyWidth = atoi(keyinfo); + keyWidth = scale_theme_x(atoi(keyinfo)); const char* ptr = keyinfo; while (*ptr > 32 && *ptr != ':') diff --git a/gui/pages.cpp b/gui/pages.cpp index 8fef7b4c8..47e2edde8 100644 --- a/gui/pages.cpp +++ b/gui/pages.cpp @@ -41,6 +41,7 @@ extern "C" { #include "../minuitwrp/minui.h" #include "../minzip/SysUtil.h" #include "../minzip/Zip.h" +#include "gui.h" } #include "rapidxml.hpp" @@ -113,6 +114,7 @@ bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h value = node->first_attribute("x")->value(); DataManager::GetValue(value, value); *x = atol(value.c_str()); + *x = scale_theme_x(*x); *x += tw_x_offset; } @@ -121,6 +123,7 @@ bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h value = node->first_attribute("y")->value(); DataManager::GetValue(value, value); *y = atol(value.c_str()); + *y = scale_theme_y(*y); *y += tw_y_offset; } @@ -129,6 +132,7 @@ bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h value = node->first_attribute("w")->value(); DataManager::GetValue(value, value); *w = atol(value.c_str()); + *w = scale_theme_x(*w); } if (h && node->first_attribute("h")) @@ -136,6 +140,7 @@ bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h value = node->first_attribute("h")->value(); DataManager::GetValue(value, value); *h = atol(value.c_str()); + *h = scale_theme_y(*h); } if (placement && node->first_attribute("placement")) @@ -581,7 +586,58 @@ int PageSet::Load(ZipArchive* package) if (!parent) parent = mDoc.first_node("install"); + set_scale_values(1, 1); // Reset any previous scaling values + // Now, let's parse the XML + LOGINFO("Checking resolution...\n"); + child = parent->first_node("details"); + if (child) { + xml_node<>* resolution = child->first_node("resolution"); + if (resolution) { + xml_attribute<>* width_attr = resolution->first_attribute("width"); + xml_attribute<>* height_attr = resolution->first_attribute("height"); + xml_attribute<>* noscale_attr = resolution->first_attribute("noscaling"); + if (width_attr && height_attr && !noscale_attr) { + int width = atoi(width_attr->value()); + int height = atoi(height_attr->value()); + int offx = 0, offy = 0; +#ifdef TW_ROUND_SCREEN + xml_node<>* roundscreen = child->first_node("roundscreen"); + if (roundscreen) { + LOGINFO("TW_ROUND_SCREEN := true, using round screen XML settings.\n"); + xml_attribute<>* offx_attr = roundscreen->first_attribute("offset_x"); + xml_attribute<>* offy_attr = roundscreen->first_attribute("offset_y"); + if (offx_attr) { + offx = atoi(offx_attr->value()); + } + if (offy_attr) { + offy = atoi(offy_attr->value()); + } + } +#endif + if (width != 0 && height != 0) { + float scale_w = ((float)gr_fb_width() - ((float)offx * 2.0)) / (float)width; + float scale_h = ((float)gr_fb_height() - ((float)offy * 2.0)) / (float)height; +#ifdef TW_ROUND_SCREEN + float scale_off_w = (float)gr_fb_width() / (float)width; + float scale_off_h = (float)gr_fb_height() / (float)height; + tw_x_offset = offx * scale_off_w; + tw_y_offset = offy * scale_off_h; +#endif + if (scale_w != 1 || scale_h != 1) { + LOGINFO("Scaling theme width %fx and height %fx, offsets x: %i y: %i\n", scale_w, scale_h, tw_x_offset, tw_y_offset); + set_scale_values(scale_w, scale_h); + } + } + } else { + LOGINFO("XML does not contain width and height, no scaling will be applied\n"); + } + } else { + LOGINFO("XML contains no resolution tag, no scaling will be applied.\n"); + } + } else { + LOGINFO("XML contains no details tag, no scaling will be applied.\n"); + } LOGINFO("Loading resources...\n"); child = parent->first_node("resources"); if (child) diff --git a/gui/resources.cpp b/gui/resources.cpp index d769c17eb..d9f2741d7 100644 --- a/gui/resources.cpp +++ b/gui/resources.cpp @@ -23,6 +23,7 @@ extern "C" { #include "../twcommon.h" #include "../minuitwrp/minui.h" +#include "gui.h" } #include "rapidxml.hpp" @@ -61,6 +62,49 @@ int Resource::ExtractResource(ZipArchive* pZip, std::string folderName, std::str return ret; } +void Resource::LoadImage(ZipArchive* pZip, std::string file, gr_surface* source) +{ + if (ExtractResource(pZip, "images", file, ".png", TMP_RESOURCE_NAME) == 0) + { + res_create_surface(TMP_RESOURCE_NAME, source); + 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, source); + unlink(TMP_RESOURCE_NAME); + } + else if (!pZip) + { + // File name in xml may have included .png so try without adding .png + res_create_surface(file.c_str(), source); + } +} + +void Resource::CheckAndScaleImage(gr_surface source, gr_surface* destination, int retain_aspect) +{ + if (!source) { + *destination = NULL; + return; + } + if (get_scale_w() != 0 && get_scale_h() != 0) { + float scale_w = get_scale_w(), scale_h = get_scale_h(); + if (retain_aspect) { + if (scale_w < scale_h) + scale_h = scale_w; + else + scale_w = scale_h; + } + if (res_scale_surface(source, destination, scale_w, scale_h)) { + LOGINFO("Error scaling image, using regular size.\n"); + *destination = source; + } + } else { + *destination = source; + } +} + FontResource::FontResource(xml_node<>* node, ZipArchive* pZip) : Resource(node, pZip) { @@ -86,7 +130,7 @@ FontResource::FontResource(xml_node<>* node, ZipArchive* pZip) if(!attr) return; - int size = atoi(attr->value()); + int size = scale_theme_min(atoi(attr->value())); int dpi = 300; attr = node->first_attribute("dpi"); @@ -143,10 +187,11 @@ FontResource::~FontResource() } } -ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip) +ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip, int retain_aspect) : Resource(node, pZip) { std::string file; + gr_surface temp_surface = NULL; mSurface = NULL; if (!node) { @@ -156,20 +201,13 @@ ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip) 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 { + LOGERR("No filename specified for image resource.\n"); + return; } - else - res_create_surface(file.c_str(), &mSurface); + + LoadImage(pZip, file, &temp_surface); + CheckAndScaleImage(temp_surface, &mSurface, retain_aspect); } ImageResource::~ImageResource() @@ -178,7 +216,7 @@ ImageResource::~ImageResource() res_free_surface(mSurface); } -AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip) +AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip, int retain_aspect) : Resource(node, pZip) { std::string file; @@ -189,30 +227,24 @@ AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip) if (node->first_attribute("filename")) file = node->first_attribute("filename")->value(); + else { + LOGERR("No filename specified for image resource.\n"); + return; + } 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++; + gr_surface surface, temp_surface = NULL; + LoadImage(pZip, fileName.str(), &temp_surface); + CheckAndScaleImage(temp_surface, &surface, retain_aspect); + if (surface) { + mSurfaces.push_back(surface); + fileNum++; + } else + break; // Done loading animation images } } @@ -264,17 +296,24 @@ void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip) } else if (type == "image") { - res = new ImageResource(child, pZip); + int retain = 0; + xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect"); + if (retain_aspect_ratio) + retain = 1; // the value does not matter, if retainaspect is present, we assume that we want to retain it + res = new ImageResource(child, pZip, retain); } else if (type == "animation") { - res = new AnimationResource(child, pZip); + int retain = 0; + xml_attribute<>* retain_aspect_ratio = child->first_attribute("retainaspect"); + if (retain_aspect_ratio) + retain = 1; // the value does not matter, if retainaspect is present, we assume that we want to retain it + res = new AnimationResource(child, pZip, retain); } else { LOGERR("Resource type (%s) not supported.\n", type.c_str()); } - if (res == NULL || res->GetResource() == NULL) { std::string res_name; diff --git a/gui/resources.hpp b/gui/resources.hpp index 603b1c958..cc5e7b6ff 100644 --- a/gui/resources.hpp +++ b/gui/resources.hpp @@ -25,6 +25,8 @@ private: protected: static int ExtractResource(ZipArchive* pZip, std::string folderName, std::string fileName, std::string fileExtn, std::string destFile); + static void LoadImage(ZipArchive* pZip, std::string file, gr_surface* source); + static void CheckAndScaleImage(gr_surface source, gr_surface* destination, int retain_aspect); }; class FontResource : public Resource @@ -52,7 +54,7 @@ protected: class ImageResource : public Resource { public: - ImageResource(xml_node<>* node, ZipArchive* pZip); + ImageResource(xml_node<>* node, ZipArchive* pZip, int retain_aspect); virtual ~ImageResource(); public: @@ -65,7 +67,7 @@ protected: class AnimationResource : public Resource { public: - AnimationResource(xml_node<>* node, ZipArchive* pZip); + AnimationResource(xml_node<>* node, ZipArchive* pZip, int retain_aspect); virtual ~AnimationResource(); public: diff --git a/gui/scrolllist.cpp b/gui/scrolllist.cpp index 3010d3a71..eb66de8e5 100644 --- a/gui/scrolllist.cpp +++ b/gui/scrolllist.cpp @@ -91,7 +91,7 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) attr = child->first_attribute("separatorheight"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mHeaderSeparatorH = atoi(parsevalue.c_str()); + mHeaderSeparatorH = scale_theme_y(atoi(parsevalue.c_str())); header_separator_height_specified = -1; } } @@ -156,7 +156,7 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) attr = child->first_attribute("spacing"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mItemSpacing = atoi(parsevalue.c_str()); + mItemSpacing = scale_theme_y(atoi(parsevalue.c_str())); } attr = child->first_attribute("highlightcolor"); @@ -185,7 +185,7 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) attr = child->first_attribute("height"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mSeparatorH = atoi(parsevalue.c_str()); + mSeparatorH = scale_theme_y(atoi(parsevalue.c_str())); if (!header_separator_height_specified) mHeaderSeparatorH = mSeparatorH; } @@ -206,25 +206,25 @@ GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node) attr = child->first_attribute("w"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mFastScrollW = atoi(parsevalue.c_str()); + mFastScrollW = scale_theme_x(atoi(parsevalue.c_str())); } attr = child->first_attribute("linew"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mFastScrollLineW = atoi(parsevalue.c_str()); + mFastScrollLineW = scale_theme_x(atoi(parsevalue.c_str())); } attr = child->first_attribute("rectw"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mFastScrollRectW = atoi(parsevalue.c_str()); + mFastScrollRectW = scale_theme_x(atoi(parsevalue.c_str())); } attr = child->first_attribute("recth"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mFastScrollRectH = atoi(parsevalue.c_str()); + mFastScrollRectH = scale_theme_y(atoi(parsevalue.c_str())); } } diff --git a/gui/slidervalue.cpp b/gui/slidervalue.cpp index 3ae6b9855..7c38e329e 100644 --- a/gui/slidervalue.cpp +++ b/gui/slidervalue.cpp @@ -173,14 +173,14 @@ GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node) if (attr) { string parsevalue = gui_parse_text(attr->value()); - mLineH = atoi(parsevalue.c_str()); + mLineH = scale_theme_y(atoi(parsevalue.c_str())); } attr = child->first_attribute("linepadding"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mPadding = atoi(parsevalue.c_str()); + mPadding = scale_theme_x(atoi(parsevalue.c_str())); mLinePadding = mPadding; } @@ -188,14 +188,14 @@ GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node) if (attr) { string parsevalue = gui_parse_text(attr->value()); - mSliderW = atoi(parsevalue.c_str()); + mSliderW = scale_theme_x(atoi(parsevalue.c_str())); } attr = child->first_attribute("sliderh"); if (attr) { string parsevalue = gui_parse_text(attr->value()); - mSliderH = atoi(parsevalue.c_str()); + mSliderH = scale_theme_y(atoi(parsevalue.c_str())); } } diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h index 3aa486511..fff7ddb97 100644 --- a/minuitwrp/minui.h +++ b/minuitwrp/minui.h @@ -67,6 +67,7 @@ unsigned int gr_get_height(gr_surface surface); int gr_get_surface(gr_surface* surface); int gr_free_surface(gr_surface surface); +// Functions in graphics_utils.c int gr_save_screenshot(const char *dest); // input event structure, include for the definition. @@ -83,6 +84,7 @@ int ev_has_mouse(void); // Returns 0 if no error, else negative. int res_create_surface(const char* name, gr_surface* pSurface); void res_free_surface(gr_surface surface); +int res_scale_surface(gr_surface source, gr_surface* destination, float scale_w, float scale_h); // Needed for AOSP: int ev_wait(int timeout); diff --git a/minuitwrp/resources.c b/minuitwrp/resources.c index 2e58311af..eef5713a1 100644 --- a/minuitwrp/resources.c +++ b/minuitwrp/resources.c @@ -347,7 +347,7 @@ int res_create_surface(const char* name, gr_surface* pSurface) { if (!name) return -1; if (strlen(name) > 4 && strcmp(name + strlen(name) - 4, ".jpg") == 0) - return res_create_surface_jpg(name,pSurface); + return res_create_surface_jpg(name,pSurface); ret = res_create_surface_png(name,pSurface); if (ret < 0) @@ -362,3 +362,77 @@ void res_free_surface(gr_surface surface) { free(pSurface); } } + +// Scale image function +int res_scale_surface(gr_surface source, gr_surface* destination, float scale_w, float scale_h) { + GGLContext *sc_context = 0; + gglInit(&sc_context); + GGLContext *gl = sc_context; + GGLSurface* sc_mem_surface = NULL; + *destination = NULL; + GGLSurface *surface = (GGLSurface*)source; + int w = gr_get_width(source), h = gr_get_height(source); + int sx = 0, sy = 0, dx = 0, dy = 0; + float dw = (float)w * scale_w; + float dh = (float)h * scale_h; + + // Create a new surface that is the appropriate size + sc_mem_surface = init_display_surface((int)dw, (int)dh); + if (!sc_mem_surface) { + printf("gr_scale_surface failed to init_display_surface\n"); + return -1; + } + sc_mem_surface->format = surface->format; + + // Finish initializing the context + gl->colorBuffer(gl, sc_mem_surface); + gl->activeTexture(gl, 0); + + // Enable or disable blending based on source surface format + if (surface->format == GGL_PIXEL_FORMAT_RGBX_8888) { + gl->disable(gl, GGL_BLEND); + } else { + gl->enable(gl, GGL_BLEND); + gl->blendFunc(gl, GGL_ONE, GGL_ZERO); + } + + // Bind our source surface to the context + gl->bindTexture(gl, surface); + + // Deal with the scaling + gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_MIN_FILTER, GGL_LINEAR); + gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_MAG_FILTER, GGL_LINEAR); + gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP); + gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); + gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); + gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); + gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); + gl->enable(gl, GGL_TEXTURE_2D); + + int32_t grad[8]; + memset(grad, 0, sizeof(grad)); + // s, dsdx, dsdy, scale, t, dtdx, dtdy, tscale <- this is wrong! + // This api uses block floating-point for S and T texture coordinates. + // All values are given in 16.16, scaled by 'scale'. In other words, + // set scale to 0, for 16.16 values. + + // s, dsdx, dsdy, t, dtdx, dtdy, sscale, tscale + float dsdx = (float)w / dw; + float dtdy = (float)h / dh; + grad[0] = ((float)sx - (dsdx * dx)) * 65536; + grad[1] = dsdx * 65536; + grad[3] = ((float)sy - (dtdy * dy)) * 65536; + grad[5] = dtdy * 65536; +// printf("blit: w=%d h=%d dx=%d dy=%d dw=%f dh=%f dsdx=%f dtdy=%f s0=%x dsdx=%x t0=%x dtdy=%x\n", +// w, h, dx, dy, dw, dh, dsdx, dtdy, grad[0], grad[1], grad[3], grad[5]); + gl->texCoordGradScale8xv(gl, 0 /*tmu*/, grad); + + // draw / scale the source surface to our target context + gl->recti(gl, dx, dy, dx + dw, dy + dh); + // put the scaled surface in our destination + *destination = (gr_surface*) sc_mem_surface; + // free memory used in the source + res_free_surface(source); + source = NULL; + return 0; +} -- cgit v1.2.3