From 014a08cabb856b2360419aac404744029ee4748c Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Thu, 15 Mar 2012 22:50:17 +1100 Subject: [PATCH] skin_engine: New tag to draw a rectangle (optionally with a gradient) %dr(x, y, width, height, [colour1[, colour2]]): x,y - viewport relative pixel coordinates to start the rectangle. width, height - obvious. can be '-' to fill the viewport if both colours are left out the viewports foreground colour will be used if one colour is specified it will fill the rectangle that colour. if both colours are specified it will gradient fill the rectangle. Change-Id: Iad451e99ded663bc7c5d182443659db7d909b388 --- apps/gui/skin_engine/skin_parser.c | 48 ++++++++++++++++++++++++++++++++++++ apps/gui/skin_engine/skin_render.c | 23 ++++++++++++++++- apps/gui/skin_engine/wps_internals.h | 9 +++++++ apps/screen_access.c | 3 +++ apps/screen_access.h | 4 +++ firmware/drivers/lcd-bitmap-common.c | 14 +++++++---- lib/skin_parser/tag_table.c | 1 + lib/skin_parser/tag_table.h | 2 ++ manual/appendix/wps_tags.tex | 7 ++++++ 9 files changed, 105 insertions(+), 6 deletions(-) diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 2d9d7cd807..49373eca32 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -638,6 +638,51 @@ static int parse_viewporttextstyle(struct skin_element *element, return 0; } +static int parse_drawrectangle( struct skin_element *element, + struct wps_token *token, + struct wps_data *wps_data) +{ + (void)wps_data; + struct draw_rectangle *rect = + (struct draw_rectangle *)skin_buffer_alloc(sizeof(struct draw_rectangle)); + + if (!rect) + return -1; + + rect->x = get_param(element, 0)->data.number; + rect->y = get_param(element, 1)->data.number; + + if (isdefault(get_param(element, 2))) + rect->width = curr_vp->vp.width - rect->x; + else + rect->width = get_param(element, 2)->data.number; + + if (isdefault(get_param(element, 3))) + rect->height = curr_vp->vp.height - rect->y; + else + rect->height = get_param(element, 3)->data.number; + + rect->start_colour = curr_vp->vp.fg_pattern; + rect->end_colour = curr_vp->vp.fg_pattern; + + if (element->params_count > 4) + { + if (!parse_color(curr_screen, get_param_text(element, 4), + &rect->start_colour)) + return -1; + rect->end_colour = rect->start_colour; + } + if (element->params_count > 5) + { + if (!parse_color(curr_screen, get_param_text(element, 5), + &rect->end_colour)) + return -1; + } + token->value.data = PTRTOSKINOFFSET(skin_buffer, rect); + + return 0; +} + static int parse_viewportcolour(struct skin_element *element, struct wps_token *token, struct wps_data *wps_data) @@ -2013,6 +2058,9 @@ static int skin_element_callback(struct skin_element* element, void* data) sb_skin_has_title(curr_screen); #endif break; + case SKIN_TOKEN_DRAWRECTANGLE: + function = parse_drawrectangle; + break; #endif case SKIN_TOKEN_FILE_DIRECTORY: token->value.i = get_param(element, 0)->data.number; diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c index 80d8c83d27..7ceb0bce17 100644 --- a/apps/gui/skin_engine/skin_render.c +++ b/apps/gui/skin_engine/skin_render.c @@ -176,8 +176,29 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, if (do_refresh) draw_peakmeters(gwps, info->line_number, vp); break; + case SKIN_TOKEN_DRAWRECTANGLE: + if (do_refresh) + { + struct draw_rectangle *rect = + SKINOFFSETTOPTR(skin_buffer, token->value.data); +#ifdef HAVE_LCD_COLOR + if (rect->start_colour != rect->end_colour && + gwps->display->screen_type == SCREEN_MAIN) + { + gwps->display->gradient_fillrect(rect->x, rect->y, rect->width, + rect->height, rect->start_colour, rect->end_colour); + } + else #endif -#ifdef HAVE_LCD_BITMAP + { + unsigned backup = vp->fg_pattern; + vp->fg_pattern = rect->start_colour; + gwps->display->fillrect(rect->x, rect->y, rect->width, + rect->height); + vp->fg_pattern = backup; + } + } + break; case SKIN_TOKEN_PEAKMETER_LEFTBAR: case SKIN_TOKEN_PEAKMETER_RIGHTBAR: data->peak_meter_enabled = true; diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index 3b1d7cf054..3788712c9d 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -113,6 +113,15 @@ struct progressbar { bool horizontal; OFFSETTYPE(struct gui_img *) backdrop; }; + +struct draw_rectangle { + int x; + int y; + int width; + int height; + unsigned start_colour; + unsigned end_colour; +}; #endif diff --git a/apps/screen_access.c b/apps/screen_access.c index 43000e1360..fc92210981 100644 --- a/apps/screen_access.c +++ b/apps/screen_access.c @@ -264,6 +264,9 @@ struct screen screens[NB_SCREENS] = #endif #if defined(HAVE_LCD_BITMAP) .set_framebuffer = (void*)lcd_set_framebuffer, +#if defined(HAVE_LCD_COLOR) + .gradient_fillrect = lcd_gradient_fillrect, +#endif #endif }, #if NB_SCREENS == 2 diff --git a/apps/screen_access.h b/apps/screen_access.h index 343829b915..ab2ef4f14d 100644 --- a/apps/screen_access.h +++ b/apps/screen_access.h @@ -162,6 +162,10 @@ struct screen #endif #if defined(HAVE_LCD_BITMAP) void (*set_framebuffer)(void *framebuffer); +#if defined(HAVE_LCD_COLOR) + void (*gradient_fillrect)(int x, int y, int width, int height, + unsigned start, unsigned end); +#endif #endif }; diff --git a/firmware/drivers/lcd-bitmap-common.c b/firmware/drivers/lcd-bitmap-common.c index 80796b392b..0bae790e58 100644 --- a/firmware/drivers/lcd-bitmap-common.c +++ b/firmware/drivers/lcd-bitmap-common.c @@ -41,14 +41,18 @@ #endif #if defined(MAIN_LCD) && defined(HAVE_LCD_COLOR) -void lcd_gradient_fillrect(int x1, int x2, int y1, int y2, +void lcd_gradient_fillrect(int x, int y, int width, int height, unsigned start_rgb, unsigned end_rgb) { int old_pattern = current_vp->fg_pattern; int step_mul, i; - if (y2 - y1 == 0) return; + int x1, x2; + x1 = x; + x2 = x + width; + + if (height == 0) return; - step_mul = (1 << 16) / (y2 - y1); + step_mul = (1 << 16) / height; int h_r = RGB_UNPACK_RED(start_rgb); int h_g = RGB_UNPACK_GREEN(start_rgb); int h_b = RGB_UNPACK_BLUE(start_rgb); @@ -59,7 +63,7 @@ void lcd_gradient_fillrect(int x1, int x2, int y1, int y2, h_g = (h_g << 16) + (1 << 15); h_b = (h_b << 16) + (1 << 15); - for(i = y1; i < y2; i++) { + for(i = y; i < y + height; i++) { current_vp->fg_pattern = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); lcd_hline(x1, x2, i); h_r -= rstep; @@ -108,7 +112,7 @@ static void lcd_do_gradient_line(int x1, int x2, int y, unsigned h, h_g -= h * gstep; h_b -= h * bstep; end_rgb = LCD_RGBPACK(h_r >> 16, h_g >> 16, h_b >> 16); - lcd_gradient_fillrect(x1, x2, y, y + h, start_rgb, end_rgb); + lcd_gradient_fillrect(x1, y, x2 - x1, h, start_rgb, end_rgb); } #endif diff --git a/lib/skin_parser/tag_table.c b/lib/skin_parser/tag_table.c index fb61da501b..1842cb9f70 100644 --- a/lib/skin_parser/tag_table.c +++ b/lib/skin_parser/tag_table.c @@ -244,6 +244,7 @@ static const struct tag_info legal_tags[] = { SKIN_TOKEN_VAR_TIMEOUT, "vl", "S|D", SKIN_REFRESH_DYNAMIC }, { SKIN_TOKEN_SUBSTRING, "ss", "IiT|s", SKIN_REFRESH_DYNAMIC }, + { SKIN_TOKEN_DRAWRECTANGLE, "dr", "IIii|ss", SKIN_REFRESH_STATIC }, { SKIN_TOKEN_UNKNOWN, "" , "", 0 } /* Keep this here to mark the end of the table */ }; diff --git a/lib/skin_parser/tag_table.h b/lib/skin_parser/tag_table.h index cf0096f28d..932f4a5ffd 100644 --- a/lib/skin_parser/tag_table.h +++ b/lib/skin_parser/tag_table.h @@ -288,6 +288,8 @@ enum skin_token_type { SKIN_TOKEN_VAR_TIMEOUT, SKIN_TOKEN_SUBSTRING, + + SKIN_TOKEN_DRAWRECTANGLE, }; /* diff --git a/manual/appendix/wps_tags.tex b/manual/appendix/wps_tags.tex index f1a661c2da..4aa9472e74 100644 --- a/manual/appendix/wps_tags.tex +++ b/manual/appendix/wps_tags.tex @@ -100,6 +100,13 @@ show the information for the next song to be played. \config{\%Fl('id',filename)} & See section \ref{ref:multifont}.\\ \end{tagmap} + \section{Misc Coloring Tags} + \begin{tagmap} + \config{\%dr(x,y,width,height,[color1,color2])} & Color a rectangle. \\ + \end{tagmap} + width and height can be - to fill the viewport. If no color is + specified the viewports foreground color will be used. If two + colors are specified it will do a gradient fill. } \section{Power Related Information} -- 2.11.4.GIT