From 07cfb8fe799901948afd6af05ef4674173713bcb Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Fri, 10 Apr 2015 13:12:05 -0700 Subject: Switch minui over to C++. Change-Id: I59e08a304ae514a3fdb6fab58721f11670bc1b01 --- minui/graphics.cpp | 406 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 406 insertions(+) create mode 100644 minui/graphics.cpp (limited to 'minui/graphics.cpp') diff --git a/minui/graphics.cpp b/minui/graphics.cpp new file mode 100644 index 000000000..d7d6e8d5a --- /dev/null +++ b/minui/graphics.cpp @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2007 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +#include + +#include "font_10x18.h" +#include "minui.h" +#include "graphics.h" + +struct GRFont { + GRSurface* texture; + int cwidth; + int cheight; +}; + +static GRFont* gr_font = NULL; +static minui_backend* gr_backend = NULL; + +static int overscan_percent = OVERSCAN_PERCENT; +static int overscan_offset_x = 0; +static int overscan_offset_y = 0; + +static unsigned char gr_current_r = 255; +static unsigned char gr_current_g = 255; +static unsigned char gr_current_b = 255; +static unsigned char gr_current_a = 255; + +static GRSurface* gr_draw = NULL; + +static bool outside(int x, int y) +{ + return x < 0 || x >= gr_draw->width || y < 0 || y >= gr_draw->height; +} + +int gr_measure(const char *s) +{ + return gr_font->cwidth * strlen(s); +} + +void gr_font_size(int *x, int *y) +{ + *x = gr_font->cwidth; + *y = gr_font->cheight; +} + +static void text_blend(unsigned char* src_p, int src_row_bytes, + unsigned char* dst_p, int dst_row_bytes, + int width, int height) +{ + for (int j = 0; j < height; ++j) { + unsigned char* sx = src_p; + unsigned char* px = dst_p; + for (int i = 0; i < width; ++i) { + unsigned char a = *sx++; + if (gr_current_a < 255) a = ((int)a * gr_current_a) / 255; + if (a == 255) { + *px++ = gr_current_r; + *px++ = gr_current_g; + *px++ = gr_current_b; + px++; + } else if (a > 0) { + *px = (*px * (255-a) + gr_current_r * a) / 255; + ++px; + *px = (*px * (255-a) + gr_current_g * a) / 255; + ++px; + *px = (*px * (255-a) + gr_current_b * a) / 255; + ++px; + ++px; + } else { + px += 4; + } + } + src_p += src_row_bytes; + dst_p += dst_row_bytes; + } +} + +void gr_text(int x, int y, const char *s, int bold) +{ + GRFont* font = gr_font; + + if (!font->texture || gr_current_a == 0) return; + + bold = bold && (font->texture->height != font->cheight); + + x += overscan_offset_x; + y += overscan_offset_y; + + unsigned char ch; + while ((ch = *s++)) { + if (outside(x, y) || outside(x+font->cwidth-1, y+font->cheight-1)) break; + + if (ch < ' ' || ch > '~') { + ch = '?'; + } + + unsigned char* src_p = font->texture->data + ((ch - ' ') * font->cwidth) + + (bold ? font->cheight * font->texture->row_bytes : 0); + unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes; + + text_blend(src_p, font->texture->row_bytes, + dst_p, gr_draw->row_bytes, + font->cwidth, font->cheight); + + x += font->cwidth; + } +} + +void gr_texticon(int x, int y, GRSurface* icon) { + if (icon == NULL) return; + + if (icon->pixel_bytes != 1) { + printf("gr_texticon: source has wrong format\n"); + return; + } + + x += overscan_offset_x; + y += overscan_offset_y; + + if (outside(x, y) || outside(x+icon->width-1, y+icon->height-1)) return; + + unsigned char* src_p = icon->data; + unsigned char* dst_p = gr_draw->data + y*gr_draw->row_bytes + x*gr_draw->pixel_bytes; + + text_blend(src_p, icon->row_bytes, + dst_p, gr_draw->row_bytes, + icon->width, icon->height); +} + +void gr_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a) +{ +#if defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) + gr_current_r = b; + gr_current_g = g; + gr_current_b = r; + gr_current_a = a; +#else + gr_current_r = r; + gr_current_g = g; + gr_current_b = b; + gr_current_a = a; +#endif +} + +void gr_clear() +{ + if (gr_current_r == gr_current_g && gr_current_r == gr_current_b) { + memset(gr_draw->data, gr_current_r, gr_draw->height * gr_draw->row_bytes); + } else { + unsigned char* px = gr_draw->data; + for (int y = 0; y < gr_draw->height; ++y) { + for (int x = 0; x < gr_draw->width; ++x) { + *px++ = gr_current_r; + *px++ = gr_current_g; + *px++ = gr_current_b; + px++; + } + px += gr_draw->row_bytes - (gr_draw->width * gr_draw->pixel_bytes); + } + } +} + +void gr_fill(int x1, int y1, int x2, int y2) +{ + x1 += overscan_offset_x; + y1 += overscan_offset_y; + + x2 += overscan_offset_x; + y2 += overscan_offset_y; + + if (outside(x1, y1) || outside(x2-1, y2-1)) return; + + unsigned char* p = gr_draw->data + y1 * gr_draw->row_bytes + x1 * gr_draw->pixel_bytes; + if (gr_current_a == 255) { + int x, y; + for (y = y1; y < y2; ++y) { + unsigned char* px = p; + for (x = x1; x < x2; ++x) { + *px++ = gr_current_r; + *px++ = gr_current_g; + *px++ = gr_current_b; + px++; + } + p += gr_draw->row_bytes; + } + } else if (gr_current_a > 0) { + int x, y; + for (y = y1; y < y2; ++y) { + unsigned char* px = p; + for (x = x1; x < x2; ++x) { + *px = (*px * (255-gr_current_a) + gr_current_r * gr_current_a) / 255; + ++px; + *px = (*px * (255-gr_current_a) + gr_current_g * gr_current_a) / 255; + ++px; + *px = (*px * (255-gr_current_a) + gr_current_b * gr_current_a) / 255; + ++px; + ++px; + } + p += gr_draw->row_bytes; + } + } +} + +void gr_blit(GRSurface* source, int sx, int sy, int w, int h, int dx, int dy) { + if (source == NULL) return; + + if (gr_draw->pixel_bytes != source->pixel_bytes) { + printf("gr_blit: source has wrong format\n"); + return; + } + + dx += overscan_offset_x; + dy += overscan_offset_y; + + if (outside(dx, dy) || outside(dx+w-1, dy+h-1)) return; + + unsigned char* src_p = source->data + sy*source->row_bytes + sx*source->pixel_bytes; + unsigned char* dst_p = gr_draw->data + dy*gr_draw->row_bytes + dx*gr_draw->pixel_bytes; + + int i; + for (i = 0; i < h; ++i) { + memcpy(dst_p, src_p, w * source->pixel_bytes); + src_p += source->row_bytes; + dst_p += gr_draw->row_bytes; + } +} + +unsigned int gr_get_width(GRSurface* surface) { + if (surface == NULL) { + return 0; + } + return surface->width; +} + +unsigned int gr_get_height(GRSurface* surface) { + if (surface == NULL) { + return 0; + } + return surface->height; +} + +static void gr_init_font(void) +{ + gr_font = reinterpret_cast(calloc(sizeof(*gr_font), 1)); + + int res = res_create_alpha_surface("font", &(gr_font->texture)); + if (res == 0) { + // The font image should be a 96x2 array of character images. The + // columns are the printable ASCII characters 0x20 - 0x7f. The + // top row is regular text; the bottom row is bold. + gr_font->cwidth = gr_font->texture->width / 96; + gr_font->cheight = gr_font->texture->height / 2; + } else { + printf("failed to read font: res=%d\n", res); + + // fall back to the compiled-in font. + gr_font->texture = reinterpret_cast(malloc(sizeof(*gr_font->texture))); + gr_font->texture->width = font.width; + gr_font->texture->height = font.height; + gr_font->texture->row_bytes = font.width; + gr_font->texture->pixel_bytes = 1; + + unsigned char* bits = reinterpret_cast(malloc(font.width * font.height)); + gr_font->texture->data = reinterpret_cast(bits); + + unsigned char data; + unsigned char* in = font.rundata; + while((data = *in++)) { + memset(bits, (data & 0x80) ? 255 : 0, data & 0x7f); + bits += (data & 0x7f); + } + + gr_font->cwidth = font.cwidth; + gr_font->cheight = font.cheight; + } +} + +#if 0 +// Exercises many of the gr_*() functions; useful for testing. +static void gr_test() { + GRSurface** images; + int frames; + int result = res_create_multi_surface("icon_installing", &frames, &images); + if (result < 0) { + printf("create surface %d\n", result); + gr_exit(); + return; + } + + time_t start = time(NULL); + int x; + for (x = 0; x <= 1200; ++x) { + if (x < 400) { + gr_color(0, 0, 0, 255); + } else { + gr_color(0, (x-400)%128, 0, 255); + } + gr_clear(); + + gr_color(255, 0, 0, 255); + gr_surface frame = images[x%frames]; + gr_blit(frame, 0, 0, frame->width, frame->height, x, 0); + + gr_color(255, 0, 0, 128); + gr_fill(400, 150, 600, 350); + + gr_color(255, 255, 255, 255); + gr_text(500, 225, "hello, world!", 0); + gr_color(255, 255, 0, 128); + gr_text(300+x, 275, "pack my box with five dozen liquor jugs", 1); + + gr_color(0, 0, 255, 128); + gr_fill(gr_draw->width - 200 - x, 300, gr_draw->width - x, 500); + + gr_draw = gr_backend->flip(gr_backend); + } + printf("getting end time\n"); + time_t end = time(NULL); + printf("got end time\n"); + printf("start %ld end %ld\n", (long)start, (long)end); + if (end > start) { + printf("%.2f fps\n", ((double)x) / (end-start)); + } +} +#endif + +void gr_flip() { + gr_draw = gr_backend->flip(gr_backend); +} + +int gr_init(void) +{ + gr_init_font(); + + gr_backend = open_adf(); + if (gr_backend) { + gr_draw = gr_backend->init(gr_backend); + if (!gr_draw) { + gr_backend->exit(gr_backend); + } + } + + if (!gr_draw) { + gr_backend = open_fbdev(); + gr_draw = gr_backend->init(gr_backend); + if (gr_draw == NULL) { + return -1; + } + } + + overscan_offset_x = gr_draw->width * overscan_percent / 100; + overscan_offset_y = gr_draw->height * overscan_percent / 100; + + gr_flip(); + gr_flip(); + + return 0; +} + +void gr_exit(void) +{ + gr_backend->exit(gr_backend); +} + +int gr_fb_width(void) +{ + return gr_draw->width - 2*overscan_offset_x; +} + +int gr_fb_height(void) +{ + return gr_draw->height - 2*overscan_offset_y; +} + +void gr_fb_blank(bool blank) +{ + gr_backend->blank(gr_backend, blank); +} -- cgit v1.2.3 From 8fd86d77f1a2f15c6fa95bc390bcbe646374873a Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Mon, 13 Apr 2015 14:36:02 -0700 Subject: Move the menu header out of the menu. This makes it easier for us to deal with arbitrary information at the top, and means that headers added by specific commands don't overwrite the default ones. Add the fingerprint back, but broken up so it fits even on sprout's display. Change-Id: Id71da79ab1aa455a611d72756a3100a97ceb4c1c --- minui/graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'minui/graphics.cpp') diff --git a/minui/graphics.cpp b/minui/graphics.cpp index d7d6e8d5a..f240f4bbd 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -103,7 +103,7 @@ static void text_blend(unsigned char* src_p, int src_row_bytes, } } -void gr_text(int x, int y, const char *s, int bold) +void gr_text(int x, int y, const char *s, bool bold) { GRFont* font = gr_font; -- cgit v1.2.3 From 0a5cb0c7cd995ae0330a7d54a8d0db5d892a48a9 Mon Sep 17 00:00:00 2001 From: Elliott Hughes Date: Wed, 15 Apr 2015 10:58:56 -0700 Subject: Don't use typedefs that hide *s. gr_surface was causing confusion for no good reason. Change-Id: If7120187f9a00dd16297877fc49352185a4d4ea6 --- minui/graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'minui/graphics.cpp') diff --git a/minui/graphics.cpp b/minui/graphics.cpp index f240f4bbd..f09f1c6b0 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -326,7 +326,7 @@ static void gr_test() { gr_clear(); gr_color(255, 0, 0, 255); - gr_surface frame = images[x%frames]; + GRSurface* frame = images[x%frames]; gr_blit(frame, 0, 0, frame->width, frame->height, x, 0); gr_color(255, 0, 0, 128); -- cgit v1.2.3 From 1a92c4458dcc983f624a60fb75f9679c213e6814 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Marchesin?= Date: Mon, 29 Jun 2015 20:05:48 -0700 Subject: Add drm support to minui MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: 22231636 Change-Id: I103c8e906b7dd9862b7bb89d8642268e9a3006b4 Signed-off-by: Stéphane Marchesin --- minui/graphics.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'minui/graphics.cpp') diff --git a/minui/graphics.cpp b/minui/graphics.cpp index f09f1c6b0..c0eea9e38 100644 --- a/minui/graphics.cpp +++ b/minui/graphics.cpp @@ -368,6 +368,11 @@ int gr_init(void) } } + if (!gr_draw) { + gr_backend = open_drm(); + gr_draw = gr_backend->init(gr_backend); + } + if (!gr_draw) { gr_backend = open_fbdev(); gr_draw = gr_backend->init(gr_backend); -- cgit v1.2.3