From 9e07ef2b0adb8fca7e5a9e516397e533653f8836 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Tue, 15 Nov 2011 14:11:08 +0000 Subject: Use buflib for all skin engine allocations. Massive thanks to Michael Chicoine and other testers for finding the early bugs. This removes all skin memory limitations git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30991 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_render.c | 209 ++++++++++++++++++++++--------------- 1 file changed, 122 insertions(+), 87 deletions(-) (limited to 'apps/gui/skin_engine/skin_render.c') diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c index 4d41a6f9b7..e408caaa1e 100644 --- a/apps/gui/skin_engine/skin_render.c +++ b/apps/gui/skin_engine/skin_render.c @@ -27,6 +27,7 @@ #include "strlcat.h" #include "config.h" +#include "core_alloc.h" #include "kernel.h" #ifdef HAVE_ALBUMART #include "albumart.h" @@ -81,6 +82,18 @@ static void skin_render_playlistviewer(struct playlistviewer* viewer, unsigned long refresh_type); #endif +static char* skin_buffer; +/* hack alert: fix skin_parser.c's skin_buffer pointer */ +void skinparser_set_buffer(char* pointer); + +static inline struct skin_element* +get_child(OFFSETTYPE(struct skin_element**) children, int child) +{ + OFFSETTYPE(struct skin_element*) *kids = SKINOFFSETTOPTR(skin_buffer, children); + return SKINOFFSETTOPTR(skin_buffer, kids[child]); +} + + static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, struct skin_element *element, struct viewport* vp) { @@ -88,7 +101,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, (void)vp; /* silence warnings */ (void)info; #endif - struct wps_token *token = (struct wps_token *)element->data; + struct wps_token *token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, element->data); #ifdef HAVE_LCD_BITMAP struct wps_data *data = gwps->data; @@ -99,14 +112,16 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) case SKIN_TOKEN_VIEWPORT_FGCOLOUR: { - struct viewport_colour *col = token->value.data; - col->vp->fg_pattern = col->colour; + struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data); + struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, col->vp); + vp->fg_pattern = col->colour; } break; case SKIN_TOKEN_VIEWPORT_BGCOLOUR: { - struct viewport_colour *col = token->value.data; - col->vp->bg_pattern = col->colour; + struct viewport_colour *col = SKINOFFSETTOPTR(skin_buffer, token->value.data); + struct viewport *vp = SKINOFFSETTOPTR(skin_buffer, col->vp); + vp->bg_pattern = col->colour; } break; case SKIN_TOKEN_VIEWPORT_TEXTSTYLE: @@ -116,7 +131,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, #ifdef HAVE_LCD_COLOR case SKIN_TOKEN_VIEWPORT_GRADIENT_SETUP: { - struct gradient_config *cfg = token->value.data; + struct gradient_config *cfg = SKINOFFSETTOPTR(skin_buffer, token->value.data); vp->lss_pattern = cfg->start; vp->lse_pattern = cfg->end; vp->lst_pattern = cfg->text; @@ -125,14 +140,18 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, #endif case SKIN_TOKEN_VIEWPORT_ENABLE: { - char *label = token->value.data; + char *label = SKINOFFSETTOPTR(skin_buffer, token->value.data); char temp = VP_DRAW_HIDEABLE; - struct skin_element *viewport = gwps->data->tree; + struct skin_element *viewport = SKINOFFSETTOPTR(skin_buffer, gwps->data->tree); while (viewport) { - struct skin_viewport *skinvp = (struct skin_viewport*)viewport->data; - if (skinvp->label && !skinvp->is_infovp && - !strcmp(skinvp->label, label)) + struct skin_viewport *skinvp = SKINOFFSETTOPTR(skin_buffer, viewport->data); + + char *vplabel = SKINOFFSETTOPTR(skin_buffer, skinvp->label); + if (skinvp->label == VP_DEFAULT_LABEL) + vplabel = VP_DEFAULT_LABEL_STRING; + if (vplabel && !skinvp->is_infovp && + !strcmp(vplabel, label)) { if (skinvp->hidden_flags&VP_DRAW_HIDDEN) { @@ -140,7 +159,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, } skinvp->hidden_flags = temp; } - viewport = viewport->next; + viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next); } } break; @@ -148,11 +167,10 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, case SKIN_TOKEN_LIST_ITEM_CFG: if (do_refresh) skinlist_set_cfg(gwps->display->screen_type, - token->value.data); + SKINOFFSETTOPTR(skin_buffer, token->value.data)); break; case SKIN_TOKEN_UIVIEWPORT_ENABLE: - sb_set_info_vp(gwps->display->screen_type, - token->value.data); + sb_set_info_vp(gwps->display->screen_type, token->value.data); break; case SKIN_TOKEN_PEAKMETER: data->peak_meter_enabled = true; @@ -173,7 +191,7 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, case SKIN_TOKEN_TUNER_RSSI_BAR: case SKIN_TOKEN_LIST_SCROLLBAR: { - struct progressbar *bar = (struct progressbar*)token->value.data; + struct progressbar *bar = (struct progressbar*)SKINOFFSETTOPTR(skin_buffer, token->value.data); if (do_refresh) draw_progressbar(gwps, info->line_number, bar); } @@ -183,12 +201,12 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, case SKIN_TOKEN_IMAGE_DISPLAY_LISTICON: case SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY: { - struct image_display *id = token->value.data; - const char* label = id->label; + struct image_display *id = SKINOFFSETTOPTR(skin_buffer, token->value.data); + const char* label = SKINOFFSETTOPTR(skin_buffer, id->label); struct gui_img *img = skin_find_item(label,SKIN_FIND_IMAGE, data); if (img && img->loaded) { - if (id->token == NULL) + if (SKINOFFSETTOPTR(skin_buffer, id->token) == NULL) { img->display = id->subimage; } @@ -197,8 +215,8 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, char buf[16]; const char *out; int a = img->num_subimages; - out = get_token_value(gwps, id->token, info->offset, - buf, sizeof(buf), &a); + out = get_token_value(gwps, SKINOFFSETTOPTR(skin_buffer, id->token), + info->offset, buf, sizeof(buf), &a); /* NOTE: get_token_value() returns values starting at 1! */ if (a == -1) @@ -224,29 +242,32 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, } #ifdef HAVE_ALBUMART case SKIN_TOKEN_ALBUMART_DISPLAY: + { + struct skin_albumart *aa = SKINOFFSETTOPTR(skin_buffer, data->albumart); /* now draw the AA */ - if (do_refresh && data->albumart) + if (do_refresh && aa) { int handle = playback_current_aa_hid(data->playback_aa_slot); #if CONFIG_TUNER if (in_radio_screen() || (get_radio_status() != FMRADIO_OFF)) { - struct dim dim = {data->albumart->width, data->albumart->height}; + struct dim dim = {aa->width, aa->height}; handle = radio_get_art_hid(&dim); } #endif - data->albumart->draw_handle = handle; + aa->draw_handle = handle; } break; + } #endif case SKIN_TOKEN_DRAW_INBUILTBAR: gui_statusbar_draw(&(statusbars.statusbars[gwps->display->screen_type]), info->refresh_type == SKIN_REFRESH_ALL, - token->value.data); + SKINOFFSETTOPTR(skin_buffer, token->value.data)); break; case SKIN_TOKEN_VIEWPORT_CUSTOMLIST: if (do_refresh) - skin_render_playlistviewer(token->value.data, gwps, + skin_render_playlistviewer(SKINOFFSETTOPTR(skin_buffer, token->value.data), gwps, info->skin_vp, info->refresh_type); break; @@ -255,23 +276,24 @@ static bool do_non_text_tags(struct gui_wps *gwps, struct skin_draw_info *info, case SKIN_TOKEN_VAR_SET: if (do_refresh) { - struct skin_var_changer *data = token->value.data; + struct skin_var_changer *data = SKINOFFSETTOPTR(skin_buffer, token->value.data); + struct skin_var *var = SKINOFFSETTOPTR(skin_buffer, data->var); if (data->direct) - data->var->value = data->newval; + var->value = data->newval; else { - data->var->value += data->newval; + var->value += data->newval; if (data->max) { - if (data->var->value > data->max) - data->var->value = 1; - else if (data->var->value < 1) - data->var->value = data->max; + if (var->value > data->max) + var->value = 1; + else if (var->value < 1) + var->value = data->max; } } - if (data->var->value < 1) - data->var->value = 1; - data->var->last_changed = current_tick; + if (var->value < 1) + var->value = 1; + var->last_changed = current_tick; } break; #endif @@ -289,7 +311,7 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, #ifdef HAVE_LCD_BITMAP struct gui_wps *gwps = info->gwps; struct wps_data *data = gwps->data; -#endif +#endif /* Tags here are ones which need to be "turned off" or cleared * if they are in a conditional branch which isnt being used */ if (branch->type == LINE_ALTERNATOR) @@ -297,12 +319,12 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, int i; for (i=0; ichildren_count; i++) { - do_tags_in_hidden_conditional(branch->children[i], info); + do_tags_in_hidden_conditional(get_child(branch->children, i), info); } } else if (branch->type == LINE && branch->children_count) { - struct skin_element *child = branch->children[0]; + struct skin_element *child = get_child(branch->children, 0); #if defined(HAVE_LCD_BITMAP) || defined(HAVE_ALBUMART) struct wps_token *token; #endif @@ -313,25 +335,25 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, int i; for (i=0; ichildren_count; i++) { - do_tags_in_hidden_conditional(child->children[i], info); + do_tags_in_hidden_conditional(get_child(child->children, i), info); } - child = child->next; + child = SKINOFFSETTOPTR(skin_buffer, child->next); continue; } - else if (child->type != TAG || !child->data) + else if (child->type != TAG || !SKINOFFSETTOPTR(skin_buffer, child->data)) { - child = child->next; + child = SKINOFFSETTOPTR(skin_buffer, child->next); continue; } #if defined(HAVE_LCD_BITMAP) || defined(HAVE_ALBUMART) - token = (struct wps_token *)child->data; + token = (struct wps_token *)SKINOFFSETTOPTR(skin_buffer, child->data); #endif #ifdef HAVE_LCD_BITMAP /* clear all pictures in the conditional and nested ones */ if (token->type == SKIN_TOKEN_IMAGE_PRELOAD_DISPLAY) { - struct image_display *id = token->value.data; - struct gui_img *img = skin_find_item(id->label, + struct image_display *id = SKINOFFSETTOPTR(skin_buffer, token->value.data); + struct gui_img *img = skin_find_item(SKINOFFSETTOPTR(skin_buffer, id->label), SKIN_FIND_IMAGE, data); clear_image_pos(gwps, img); } @@ -341,14 +363,18 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, } else if (token->type == SKIN_TOKEN_VIEWPORT_ENABLE) { - char *label = token->value.data; + char *label = SKINOFFSETTOPTR(skin_buffer, token->value.data); struct skin_element *viewport; - for (viewport = data->tree; + for (viewport = SKINOFFSETTOPTR(skin_buffer, data->tree); viewport; - viewport = viewport->next) + viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next)) { - struct skin_viewport *skin_viewport = (struct skin_viewport*)viewport->data; - if (skin_viewport->label && strcmp(skin_viewport->label, label)) + struct skin_viewport *skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data); + + char *vplabel = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label); + if (skin_viewport->label == VP_DEFAULT_LABEL) + vplabel = VP_DEFAULT_LABEL_STRING; + if (vplabel && strcmp(vplabel, label)) continue; if (skin_viewport->hidden_flags&VP_NEVER_VISIBLE) { @@ -377,7 +403,7 @@ static void do_tags_in_hidden_conditional(struct skin_element* branch, playback_current_aa_hid(data->playback_aa_slot), true); } #endif - child = child->next; + child = SKINOFFSETTOPTR(skin_buffer, child->next); } } } @@ -433,7 +459,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i if (line->children_count == 0) return false; /* empty line, do nothing */ - struct skin_element *child = line->children[0]; + struct skin_element *child = get_child(line->children, 0); struct conditional *conditional; skin_render_func func = skin_render_line; int old_refresh_mode = info->refresh_type; @@ -442,7 +468,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i switch (child->type) { case CONDITIONAL: - conditional = (struct conditional*)child->data; + conditional = SKINOFFSETTOPTR(skin_buffer, child->data); last_value = conditional->last_value; value = evaluate_conditional(info->gwps, info->offset, conditional, child->children_count); @@ -456,20 +482,20 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i { /* we are in a false branch of a %?aa conditional */ if (last_value == 0) - do_tags_in_hidden_conditional(child->children[0], info); + do_tags_in_hidden_conditional(get_child(child->children, 0), info); break; } } else { if (last_value >= 0 && value != last_value && last_value < child->children_count) - do_tags_in_hidden_conditional(child->children[last_value], info); + do_tags_in_hidden_conditional(get_child(child->children, last_value), info); } - if (child->children[value]->type == LINE_ALTERNATOR) + if (get_child(child->children, value)->type == LINE_ALTERNATOR) { func = skin_render_alternator; } - else if (child->children[value]->type == LINE) + else if (get_child(child->children, value)->type == LINE) func = skin_render_line; if (value != last_value) @@ -478,7 +504,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i info->force_redraw = true; } - if (func(child->children[value], info)) + if (func(get_child(child->children, value), info)) needs_update = true; else needs_update = needs_update || (last_value != value); @@ -493,14 +519,14 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i fix_line_alignment(info, child); - if (!child->data) + if (!SKINOFFSETTOPTR(skin_buffer, child->data)) { break; } if (!do_non_text_tags(info->gwps, info, child, &info->skin_vp->vp)) { static char tempbuf[128]; - const char *valuestr = get_token_value(info->gwps, child->data, + const char *valuestr = get_token_value(info->gwps, SKINOFFSETTOPTR(skin_buffer, child->data), info->offset, tempbuf, sizeof(tempbuf), NULL); if (valuestr) @@ -517,7 +543,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i } break; case TEXT: - strlcat(info->cur_align_start, child->data, + strlcat(info->cur_align_start, SKINOFFSETTOPTR(skin_buffer, child->data), info->buf_size - (info->cur_align_start-info->buf)); needs_update = needs_update || (info->refresh_type&SKIN_REFRESH_STATIC) != 0; @@ -527,7 +553,7 @@ static bool skin_render_line(struct skin_element* line, struct skin_draw_info *i break; } - child = child->next; + child = SKINOFFSETTOPTR(skin_buffer, child->next); } return needs_update; } @@ -541,29 +567,29 @@ static int get_subline_timeout(struct gui_wps *gwps, struct skin_element* line) { if (element->children_count == 0) return retval; /* empty line, so force redraw */ - element = element->children[0]; + element = get_child(element->children, 0); } while (element) { if (element->type == TAG && element->tag->type == SKIN_TOKEN_SUBLINE_TIMEOUT ) { - token = element->data; + token = SKINOFFSETTOPTR(skin_buffer, element->data); return token->value.i; } else if (element->type == CONDITIONAL) { - struct conditional *conditional = element->data; + struct conditional *conditional = SKINOFFSETTOPTR(skin_buffer, element->data); int val = evaluate_conditional(gwps, 0, conditional, element->children_count); if (val >= 0) { - retval = get_subline_timeout(gwps, element->children[val]); + retval = get_subline_timeout(gwps, get_child(element->children, val)); if (retval >= 0) return retval; } } - element = element->next; + element = SKINOFFSETTOPTR(skin_buffer, element->next); } return retval; } @@ -571,7 +597,7 @@ static int get_subline_timeout(struct gui_wps *gwps, struct skin_element* line) bool skin_render_alternator(struct skin_element* element, struct skin_draw_info *info) { bool changed_lines = false; - struct line_alternator *alternator = (struct line_alternator*)element->data; + struct line_alternator *alternator = SKINOFFSETTOPTR(skin_buffer, element->data); unsigned old_refresh = info->refresh_type; if (info->refresh_type == SKIN_REFRESH_ALL) { @@ -597,11 +623,11 @@ bool skin_render_alternator(struct skin_element* element, struct skin_draw_info try_line++; if (try_line >= element->children_count) try_line = 0; - if (element->children[try_line]->children_count != 0) + if (get_child(element->children, try_line)->children_count != 0) { - current_line = element->children[try_line]; + current_line = get_child(element->children, try_line); rettimeout = get_subline_timeout(info->gwps, - current_line->children[0]); + get_child(current_line->children, 0)); if (rettimeout > 0) { suitable = true; @@ -619,7 +645,7 @@ bool skin_render_alternator(struct skin_element* element, struct skin_draw_info info->refresh_type = SKIN_REFRESH_ALL; info->force_redraw = true; } - bool ret = skin_render_line(element->children[alternator->current_line], info); + bool ret = skin_render_line(get_child(element->children, alternator->current_line), info); info->refresh_type = old_refresh; return changed_lines || ret; } @@ -646,14 +672,17 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, struct align_pos * align = &info.align; bool needs_update; + skin_buffer = get_skin_buffer(gwps->data); + skinparser_set_buffer(skin_buffer); #ifdef HAVE_LCD_BITMAP /* Set images to not to be displayed */ - struct skin_token_list *imglist = gwps->data->images; + struct skin_token_list *imglist = SKINOFFSETTOPTR(skin_buffer, gwps->data->images); while (imglist) { - struct gui_img *img = (struct gui_img *)imglist->token->value.data; + struct wps_token *token = SKINOFFSETTOPTR(skin_buffer, imglist->token); + struct gui_img *img = (struct gui_img *)SKINOFFSETTOPTR(skin_buffer, token->value.data); img->display = -1; - imglist = imglist->next; + imglist = SKINOFFSETTOPTR(skin_buffer, imglist->next); } /* fix font ID's */ @@ -716,7 +745,7 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, } if (!info.no_line_break) info.line_number++; - line = line->next; + line = SKINOFFSETTOPTR(skin_buffer, line->next); } #ifdef HAVE_LCD_BITMAP wps_display_images(gwps, &skin_viewport->vp); @@ -730,8 +759,11 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) struct skin_element* viewport; struct skin_viewport* skin_viewport; + char *label; int old_refresh_mode = refresh_mode; + skin_buffer = get_skin_buffer(gwps->data); + skinparser_set_buffer(skin_buffer); #ifdef HAVE_LCD_CHARCELLS int i; @@ -741,18 +773,21 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) data->wps_progress_pat[i] = display->get_locked_pattern(); } #endif - viewport = data->tree; - skin_viewport = (struct skin_viewport *)viewport->data; - if (skin_viewport->label && viewport->next && - !strcmp(skin_viewport->label,VP_DEFAULT_LABEL)) + viewport = SKINOFFSETTOPTR(skin_buffer, data->tree); + skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data); + label = SKINOFFSETTOPTR(skin_buffer, skin_viewport->label); + if (skin_viewport->label == VP_DEFAULT_LABEL) + label = VP_DEFAULT_LABEL_STRING; + if (label && SKINOFFSETTOPTR(skin_buffer, viewport->next) && + !strcmp(label,VP_DEFAULT_LABEL_STRING)) refresh_mode = 0; - for (viewport = data->tree; + for (viewport = SKINOFFSETTOPTR(skin_buffer, data->tree); viewport; - viewport = viewport->next) + viewport = SKINOFFSETTOPTR(skin_buffer, viewport->next)) { /* SETUP */ - skin_viewport = (struct skin_viewport*)viewport->data; + skin_viewport = SKINOFFSETTOPTR(skin_buffer, viewport->data); unsigned vp_refresh_mode = refresh_mode; #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) skin_viewport->vp.fg_pattern = skin_viewport->start_fgcolour; @@ -789,7 +824,7 @@ void skin_render(struct gui_wps *gwps, unsigned refresh_mode) } /* render */ if (viewport->children_count) - skin_render_viewport(viewport->children[0], gwps, + skin_render_viewport(get_child(viewport->children, 0), gwps, skin_viewport, vp_refresh_mode); refresh_mode = old_refresh_mode; } @@ -826,7 +861,7 @@ void skin_render_playlistviewer(struct playlistviewer* viewer, struct align_pos * align = &info.align; bool needs_update; int cur_pos, start_item, max; - int nb_lines = viewport_get_nb_lines(viewer->vp); + int nb_lines = viewport_get_nb_lines(SKINOFFSETTOPTR(skin_buffer, viewer->vp)); #if CONFIG_TUNER if (get_current_activity() == ACTIVITY_FM) { @@ -848,7 +883,7 @@ void skin_render_playlistviewer(struct playlistviewer* viewer, if (max-start_item > nb_lines) max = start_item + nb_lines; - line = viewer->line; + line = SKINOFFSETTOPTR(skin_buffer, viewer->line); while (start_item < max) { linebuf[0] = '\0'; -- cgit v1.2.3