Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 02ec6b88 authored by Doug Zongker's avatar Doug Zongker
Browse files

add simple text to recovery UI

- recovery takes a --locale argument, which will be passed by the main
  system

- the locale is saved in cache, in case the --locale argument is
  missing (eg, when recovery is started from fastboot)

- we include images that have prerendered text for many locales

- we split the background states into four (installing update,
  erasing, no command, error) so that appropriate text can be shown.

Change-Id: I731b8108e83d5ccc09a4aacfc1dbf7e86b397aaf
parent a3ccba6d
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -277,7 +277,7 @@ exit:
static int
really_install_package(const char *path, int* wipe_cache)
{
    ui->SetBackground(RecoveryUI::INSTALLING);
    ui->SetBackground(RecoveryUI::INSTALLING_UPDATE);
    ui->Print("Finding update package...\n");
    ui->SetProgressType(RecoveryUI::INDETERMINATE);
    LOGI("Update location: %s\n", path);
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@
extern "C" {
#endif

enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT };
enum { INSTALL_SUCCESS, INSTALL_ERROR, INSTALL_CORRUPT, INSTALL_NONE };
// Install the package specified by root_path.  If INSTALL_SUCCESS is
// returned and *wipe_cache is true on exit, caller should wipe the
// cache partition.
+16 −0
Original line number Diff line number Diff line
@@ -244,6 +244,22 @@ int gr_text(int x, int y, const char *s)
    return x;
}

void gr_texticon(int x, int y, gr_surface icon) {
    GGLContext* gl = gr_context;

    gl->bindTexture(gl, (GGLSurface*) icon);
    gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE);
    gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
    gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_ONE_TO_ONE);
    gl->enable(gl, GGL_TEXTURE_2D);

    int w = gr_get_width(icon);
    int h = gr_get_height(icon);

    gl->texCoord2i(gl, -x, -y);
    gl->recti(gl, x, y, x+gr_get_width(icon), y+gr_get_height(icon));
}

void gr_fill(int x, int y, int w, int h)
{
    GGLContext *gl = gr_context;
+2 −0
Original line number Diff line number Diff line
@@ -38,6 +38,7 @@ void gr_fb_blank(bool blank);
void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a);
void gr_fill(int x, int y, int w, int h);
int gr_text(int x, int y, const char *s);
 void gr_texticon(int x, int y, gr_surface icon);
int gr_measure(const char *s);
void gr_font_size(int *x, int *y);

@@ -71,6 +72,7 @@ void ev_dispatch(void);

// Returns 0 if no error, else negative.
int res_create_surface(const char* name, gr_surface* pSurface);
int res_create_localized_surface(const char* name, gr_surface* pSurface);
void res_free_surface(gr_surface surface);

#ifdef __cplusplus
+150 −0
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@

#include "minui.h"

extern char* locale;

// libpng gives "undefined reference to 'pow'" errors, and I have no
// idea how to convince the build system to link with -lm.  We don't
// need this functionality (it's used for gamma adjustment) so provide
@@ -173,6 +175,154 @@ exit:
    return result;
}

static int matches_locale(const char* loc) {
    if (locale == NULL) return 0;

    printf("matching loc=[%s] vs locale=[%s]\n", loc, locale);

    if (strcmp(loc, locale) == 0) return 1;

    // if loc does *not* have an underscore, and it matches the start
    // of locale, and the next character in locale *is* an underscore,
    // that's a match.  For instance, loc == "en" matches locale ==
    // "en_US".

    int i;
    for (i = 0; loc[i] != 0 && loc[i] != '_'; ++i);
    if (loc[i] == '_') return 0;
    printf("  partial match possible; i = %d\n", i);

    return (strncmp(locale, loc, i) == 0 && locale[i] == '_');
}

int res_create_localized_surface(const char* name, gr_surface* pSurface) {
    char resPath[256];
    GGLSurface* surface = NULL;
    int result = 0;
    unsigned char header[8];
    png_structp png_ptr = NULL;
    png_infop info_ptr = NULL;

    *pSurface = NULL;

    snprintf(resPath, sizeof(resPath)-1, "/res/images/%s.png", name);
    resPath[sizeof(resPath)-1] = '\0';
    FILE* fp = fopen(resPath, "rb");
    if (fp == NULL) {
        result = -1;
        goto exit;
    }

    size_t bytesRead = fread(header, 1, sizeof(header), fp);
    if (bytesRead != sizeof(header)) {
        result = -2;
        goto exit;
    }

    if (png_sig_cmp(header, 0, sizeof(header))) {
        result = -3;
        goto exit;
    }

    png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
    if (!png_ptr) {
        result = -4;
        goto exit;
    }

    info_ptr = png_create_info_struct(png_ptr);
    if (!info_ptr) {
        result = -5;
        goto exit;
    }

    if (setjmp(png_jmpbuf(png_ptr))) {
        result = -6;
        goto exit;
    }

    png_init_io(png_ptr, fp);
    png_set_sig_bytes(png_ptr, sizeof(header));
    png_read_info(png_ptr, info_ptr);

    size_t width = info_ptr->width;
    size_t height = info_ptr->height;
    size_t stride = 4 * width;

    printf("image size is %d x %d\n", width, height);

    int color_type = info_ptr->color_type;
    int bit_depth = info_ptr->bit_depth;
    int channels = info_ptr->channels;
    printf("color_type %d bit_depth %d channels %d\n",
           color_type, bit_depth, channels);

    if (!(bit_depth == 8 &&
          (channels == 1 && color_type == PNG_COLOR_TYPE_GRAY))) {
        return -7;
        printf("exiting -7\n");
        goto exit;
    }

    unsigned char* row = malloc(width);
    int y;
    for (y = 0; y < height; ++y) {
        png_read_row(png_ptr, row, NULL);
        int w = (row[1] << 8) | row[0];
        int h = (row[3] << 8) | row[2];
        int len = row[4];
        char* loc = row+5;

        printf("row %d: %s %d x %d\n", y, loc, w, h);

        if (y+1+h >= height || matches_locale(loc)) {
            printf("  taking this one\n");

            surface = malloc(sizeof(GGLSurface));
            if (surface == NULL) {
                result = -8;
                goto exit;
            }
            unsigned char* pData = malloc(w*h);

            surface->version = sizeof(GGLSurface);
            surface->width = w;
            surface->height = h;
            surface->stride = w; /* Yes, pixels, not bytes */
            surface->data = pData;
            surface->format = GGL_PIXEL_FORMAT_A_8;

            int i;
            for (i = 0; i < h; ++i, ++y) {
                png_read_row(png_ptr, row, NULL);
                memcpy(pData + i*w, row, w);
            }

            *pSurface = (gr_surface) surface;
            break;
        } else {
            printf("   skipping\n");
            int i;
            for (i = 0; i < h; ++i, ++y) {
                png_read_row(png_ptr, row, NULL);
            }
        }
    }

exit:
    png_destroy_read_struct(&png_ptr, &info_ptr, NULL);

    if (fp != NULL) {
        fclose(fp);
    }
    if (result < 0) {
        if (surface) {
            free(surface);
        }
    }
    return result;
}

void res_free_surface(gr_surface surface) {
    GGLSurface* pSurface = (GGLSurface*) surface;
    if (pSurface) {
Loading