diff options
Diffstat (limited to '')
-rw-r--r-- | screen_ui.cpp | 188 |
1 files changed, 152 insertions, 36 deletions
diff --git a/screen_ui.cpp b/screen_ui.cpp index b8f6ea28b..c8fb5aa75 100644 --- a/screen_ui.cpp +++ b/screen_ui.cpp @@ -14,6 +14,8 @@ * limitations under the License. */ +#include "screen_ui.h" + #include <dirent.h> #include <errno.h> #include <fcntl.h> @@ -29,18 +31,19 @@ #include <time.h> #include <unistd.h> +#include <memory> #include <string> +#include <unordered_map> #include <vector> #include <android-base/logging.h> #include <android-base/properties.h> -#include <android-base/strings.h> #include <android-base/stringprintf.h> +#include <android-base/strings.h> +#include <minui/minui.h> #include "common.h" #include "device.h" -#include "minui/minui.h" -#include "screen_ui.h" #include "ui.h" // Return the current time as a double (including fractions of a second). @@ -54,7 +57,7 @@ ScreenRecoveryUI::ScreenRecoveryUI() : kMarginWidth(RECOVERY_UI_MARGIN_WIDTH), kMarginHeight(RECOVERY_UI_MARGIN_HEIGHT), kAnimationFps(RECOVERY_UI_ANIMATION_FPS), - density_(static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f), + kDensity(static_cast<float>(android::base::GetIntProperty("ro.sf.lcd_density", 160)) / 160.f), currentIcon(NONE), progressBarType(EMPTY), progressScopeStart(0), @@ -66,7 +69,6 @@ ScreenRecoveryUI::ScreenRecoveryUI() text_(nullptr), text_col_(0), text_row_(0), - text_top_(0), show_text(false), show_text_ever(false), menu_headers_(nullptr), @@ -80,6 +82,8 @@ ScreenRecoveryUI::ScreenRecoveryUI() intro_done(false), stage(-1), max_stage(-1), + locale_(""), + rtl_locale_(false), updateMutex(PTHREAD_MUTEX_INITIALIZER) {} GRSurface* ScreenRecoveryUI::GetCurrentFrame() const { @@ -105,7 +109,7 @@ GRSurface* ScreenRecoveryUI::GetCurrentText() const { } int ScreenRecoveryUI::PixelsFromDp(int dp) const { - return dp * density_; + return dp * kDensity; } // Here's the intended layout: @@ -145,8 +149,8 @@ int ScreenRecoveryUI::GetProgressBaseline() const { int elements_sum = gr_get_height(loopFrames[0]) + PixelsFromDp(kLayouts[layout_][ICON]) + gr_get_height(installing_text) + PixelsFromDp(kLayouts[layout_][TEXT]) + gr_get_height(progressBarFill); - int bottom_gap = (gr_fb_height() - elements_sum) / 2; - return gr_fb_height() - bottom_gap - gr_get_height(progressBarFill); + int bottom_gap = (ScreenHeight() - elements_sum) / 2; + return ScreenHeight() - bottom_gap - gr_get_height(progressBarFill); } // Clear the screen and draw the currently selected background icon (if any). @@ -155,25 +159,24 @@ void ScreenRecoveryUI::draw_background_locked() { pagesIdentical = false; gr_color(0, 0, 0, 255); gr_clear(); - if (currentIcon != NONE) { if (max_stage != -1) { int stage_height = gr_get_height(stageMarkerEmpty); int stage_width = gr_get_width(stageMarkerEmpty); - int x = (gr_fb_width() - max_stage * gr_get_width(stageMarkerEmpty)) / 2; - int y = gr_fb_height() - stage_height; + int x = (ScreenWidth() - max_stage * gr_get_width(stageMarkerEmpty)) / 2; + int y = ScreenHeight() - stage_height - kMarginHeight; for (int i = 0; i < max_stage; ++i) { GRSurface* stage_surface = (i < stage) ? stageMarkerFill : stageMarkerEmpty; - gr_blit(stage_surface, 0, 0, stage_width, stage_height, x, y); + DrawSurface(stage_surface, 0, 0, stage_width, stage_height, x, y); x += stage_width; } } GRSurface* text_surface = GetCurrentText(); - int text_x = (gr_fb_width() - gr_get_width(text_surface)) / 2; + int text_x = (ScreenWidth() - gr_get_width(text_surface)) / 2; int text_y = GetTextBaseline(); gr_color(255, 255, 255, 255); - gr_texticon(text_x, text_y, text_surface); + DrawTextIcon(text_x, text_y, text_surface); } } @@ -184,21 +187,21 @@ void ScreenRecoveryUI::draw_foreground_locked() { GRSurface* frame = GetCurrentFrame(); int frame_width = gr_get_width(frame); int frame_height = gr_get_height(frame); - int frame_x = (gr_fb_width() - frame_width) / 2; + int frame_x = (ScreenWidth() - frame_width) / 2; int frame_y = GetAnimationBaseline(); - gr_blit(frame, 0, 0, frame_width, frame_height, frame_x, frame_y); + DrawSurface(frame, 0, 0, frame_width, frame_height, frame_x, frame_y); } if (progressBarType != EMPTY) { int width = gr_get_width(progressBarEmpty); int height = gr_get_height(progressBarEmpty); - int progress_x = (gr_fb_width() - width) / 2; + int progress_x = (ScreenWidth() - width) / 2; int progress_y = GetProgressBaseline(); // Erase behind the progress bar (in case this was a progress-only update) gr_color(0, 0, 0, 255); - gr_fill(progress_x, progress_y, width, height); + DrawFill(progress_x, progress_y, width, height); if (progressBarType == DETERMINATE) { float p = progressScopeStart + progress * progressScopeSize; @@ -207,19 +210,19 @@ void ScreenRecoveryUI::draw_foreground_locked() { if (rtl_locale_) { // Fill the progress bar from right to left. if (pos > 0) { - gr_blit(progressBarFill, width - pos, 0, pos, height, progress_x + width - pos, - progress_y); + DrawSurface(progressBarFill, width - pos, 0, pos, height, progress_x + width - pos, + progress_y); } if (pos < width - 1) { - gr_blit(progressBarEmpty, 0, 0, width - pos, height, progress_x, progress_y); + DrawSurface(progressBarEmpty, 0, 0, width - pos, height, progress_x, progress_y); } } else { // Fill the progress bar from left to right. if (pos > 0) { - gr_blit(progressBarFill, 0, 0, pos, height, progress_x, progress_y); + DrawSurface(progressBarFill, 0, 0, pos, height, progress_x, progress_y); } if (pos < width - 1) { - gr_blit(progressBarEmpty, pos, 0, width - pos, height, progress_x + pos, progress_y); + DrawSurface(progressBarEmpty, pos, 0, width - pos, height, progress_x + pos, progress_y); } } } @@ -256,8 +259,96 @@ void ScreenRecoveryUI::SetColor(UIElement e) const { } } +void ScreenRecoveryUI::SelectAndShowBackgroundText(const std::vector<std::string>& locales_entries, + size_t sel) { + SetLocale(locales_entries[sel]); + std::vector<std::string> text_name = { "erasing_text", "error_text", "installing_text", + "installing_security_text", "no_command_text" }; + std::unordered_map<std::string, std::unique_ptr<GRSurface, decltype(&free)>> surfaces; + for (const auto& name : text_name) { + GRSurface* text_image = nullptr; + LoadLocalizedBitmap(name.c_str(), &text_image); + if (!text_image) { + Print("Failed to load %s\n", name.c_str()); + return; + } + surfaces.emplace(name, std::unique_ptr<GRSurface, decltype(&free)>(text_image, &free)); + } + + pthread_mutex_lock(&updateMutex); + gr_color(0, 0, 0, 255); + gr_clear(); + + int text_y = kMarginHeight; + int text_x = kMarginWidth; + int line_spacing = gr_sys_font()->char_height; // Put some extra space between images. + // Write the header and descriptive texts. + SetColor(INFO); + std::string header = "Show background text image"; + text_y += DrawTextLine(text_x, text_y, header.c_str(), true); + std::string locale_selection = android::base::StringPrintf( + "Current locale: %s, %zu/%zu", locales_entries[sel].c_str(), sel, locales_entries.size()); + const char* instruction[] = { locale_selection.c_str(), + "Use volume up/down to switch locales and power to exit.", + nullptr }; + text_y += DrawWrappedTextLines(text_x, text_y, instruction); + + // Iterate through the text images and display them in order for the current locale. + for (const auto& p : surfaces) { + text_y += line_spacing; + SetColor(LOG); + text_y += DrawTextLine(text_x, text_y, p.first.c_str(), false); + gr_color(255, 255, 255, 255); + gr_texticon(text_x, text_y, p.second.get()); + text_y += gr_get_height(p.second.get()); + } + // Update the whole screen. + gr_flip(); + pthread_mutex_unlock(&updateMutex); +} + +void ScreenRecoveryUI::CheckBackgroundTextImages(const std::string& saved_locale) { + // Load a list of locales embedded in one of the resource files. + std::vector<std::string> locales_entries = get_locales_in_png("installing_text"); + if (locales_entries.empty()) { + Print("Failed to load locales from the resource files\n"); + return; + } + size_t selected = 0; + SelectAndShowBackgroundText(locales_entries, selected); + + FlushKeys(); + while (true) { + int key = WaitKey(); + if (key == KEY_POWER || key == KEY_ENTER) { + break; + } else if (key == KEY_UP || key == KEY_VOLUMEUP) { + selected = (selected == 0) ? locales_entries.size() - 1 : selected - 1; + SelectAndShowBackgroundText(locales_entries, selected); + } else if (key == KEY_DOWN || key == KEY_VOLUMEDOWN) { + selected = (selected == locales_entries.size() - 1) ? 0 : selected + 1; + SelectAndShowBackgroundText(locales_entries, selected); + } + } + + SetLocale(saved_locale); +} + +int ScreenRecoveryUI::ScreenWidth() const { + return gr_fb_width(); +} + +int ScreenRecoveryUI::ScreenHeight() const { + return gr_fb_height(); +} + +void ScreenRecoveryUI::DrawSurface(GRSurface* surface, int sx, int sy, int w, int h, int dx, + int dy) const { + gr_blit(surface, sx, sy, w, h, dx, dy); +} + int ScreenRecoveryUI::DrawHorizontalRule(int y) const { - gr_fill(0, y + 4, gr_fb_width(), y + 6); + gr_fill(0, y + 4, ScreenWidth(), y + 6); return 8; } @@ -265,6 +356,14 @@ void ScreenRecoveryUI::DrawHighlightBar(int x, int y, int width, int height) con gr_fill(x, y, x + width, y + height); } +void ScreenRecoveryUI::DrawFill(int x, int y, int w, int h) const { + gr_fill(x, y, w, h); +} + +void ScreenRecoveryUI::DrawTextIcon(int x, int y, GRSurface* surface) const { + gr_texticon(x, y, surface); +} + int ScreenRecoveryUI::DrawTextLine(int x, int y, const char* line, bool bold) const { gr_text(gr_sys_font(), x, y, line, bold); return char_height_ + 4; @@ -353,7 +452,7 @@ void ScreenRecoveryUI::draw_screen_locked() { if (i == menu_sel) { // Draw the highlight bar. SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG); - DrawHighlightBar(0, y - 2, gr_fb_width(), char_height_ + 4); + DrawHighlightBar(0, y - 2, ScreenWidth(), char_height_ + 4); // Bold white text for the selected item. SetColor(MENU_SEL_FG); y += DrawTextLine(x, y, menu_[i].c_str(), true); @@ -368,9 +467,9 @@ void ScreenRecoveryUI::draw_screen_locked() { // Display from the bottom up, until we hit the top of the screen, the bottom of the menu, or // we've displayed the entire text buffer. SetColor(LOG); - int row = (text_top_ + text_rows_ - 1) % text_rows_; + int row = text_row_; size_t count = 0; - for (int ty = gr_fb_height() - kMarginHeight - char_height_; ty >= y && count < text_rows_; + for (int ty = ScreenHeight() - kMarginHeight - char_height_; ty >= y && count < text_rows_; ty -= char_height_, ++count) { DrawTextLine(kMarginWidth, ty, text_[row], false); --row; @@ -490,13 +589,14 @@ bool ScreenRecoveryUI::InitTextParams() { } gr_font_size(gr_sys_font(), &char_width_, &char_height_); - text_rows_ = (gr_fb_height() - kMarginHeight * 2) / char_height_; - text_cols_ = (gr_fb_width() - kMarginWidth * 2) / char_width_; + text_rows_ = (ScreenHeight() - kMarginHeight * 2) / char_height_; + text_cols_ = (ScreenWidth() - kMarginWidth * 2) / char_width_; return true; } bool ScreenRecoveryUI::Init(const std::string& locale) { RecoveryUI::Init(locale); + if (!InitTextParams()) { return false; } @@ -510,7 +610,9 @@ bool ScreenRecoveryUI::Init(const std::string& locale) { file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1); text_col_ = text_row_ = 0; - text_top_ = 1; + + // Set up the locale info. + SetLocale(locale); LoadBitmap("icon_error", &error_icon); @@ -643,7 +745,6 @@ void ScreenRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) text_[text_row_][text_col_] = '\0'; text_col_ = 0; text_row_ = (text_row_ + 1) % text_rows_; - if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_; } if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr; } @@ -673,8 +774,6 @@ void ScreenRecoveryUI::PutChar(char ch) { if (ch == '\n' || text_col_ >= text_cols_) { text_col_ = 0; ++text_row_; - - if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_; } pthread_mutex_unlock(&updateMutex); } @@ -683,7 +782,6 @@ void ScreenRecoveryUI::ClearText() { pthread_mutex_lock(&updateMutex); text_col_ = 0; text_row_ = 0; - text_top_ = 1; for (size_t i = 0; i < text_rows_; ++i) { memset(text_[i], 0, text_cols_ + 1); } @@ -750,7 +848,6 @@ void ScreenRecoveryUI::ShowFile(const char* filename) { char** old_text = text_; size_t old_text_col = text_col_; size_t old_text_row = text_row_; - size_t old_text_top = text_top_; // Swap in the alternate screen and clear it. text_ = file_viewer_text_; @@ -762,7 +859,6 @@ void ScreenRecoveryUI::ShowFile(const char* filename) { text_ = old_text; text_col_ = old_text_col; text_row_ = old_text_row; - text_top_ = old_text_top; } void ScreenRecoveryUI::StartMenu(const char* const* headers, const char* const* items, @@ -841,3 +937,23 @@ void ScreenRecoveryUI::KeyLongPress(int) { // will change color to indicate a successful long press. Redraw(); } + +void ScreenRecoveryUI::SetLocale(const std::string& new_locale) { + locale_ = new_locale; + rtl_locale_ = false; + + if (!new_locale.empty()) { + size_t underscore = new_locale.find('_'); + // lang has the language prefix prior to '_', or full string if '_' doesn't exist. + std::string lang = new_locale.substr(0, underscore); + + // A bit cheesy: keep an explicit list of supported RTL languages. + if (lang == "ar" || // Arabic + lang == "fa" || // Persian (Farsi) + lang == "he" || // Hebrew (new language code) + lang == "iw" || // Hebrew (old language code) + lang == "ur") { // Urdu + rtl_locale_ = true; + } + } +} |