From 04d80f573bdd3b9825c526bd019c2969e993d346 Mon Sep 17 00:00:00 2001 From: kugel Date: Sat, 27 Feb 2010 16:51:51 +0000 Subject: [PATCH] Store the list of fonts in a linked list instead of in a static array (together with the base filename) and load all fonts in a second step. This aids debugging missing fonts, skips fonts that are not used in viewports, and is preparation of a resizable (on boot) skin buffer. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24943 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/skin_engine/skin_fonts.c | 4 +- apps/gui/skin_engine/skin_parser.c | 109 ++++++++++++++++++++++++++++++----- apps/gui/skin_engine/wps_internals.h | 7 +++ 3 files changed, 104 insertions(+), 16 deletions(-) diff --git a/apps/gui/skin_engine/skin_fonts.c b/apps/gui/skin_engine/skin_fonts.c index 0376803d2..882c04038 100644 --- a/apps/gui/skin_engine/skin_fonts.c +++ b/apps/gui/skin_engine/skin_fonts.c @@ -32,7 +32,7 @@ #define FONT_SIZE 10000 -static struct skin_font { +static struct skin_font_info { struct font font; int font_id; char name[MAX_PATH]; @@ -63,7 +63,7 @@ int skin_font_load(char* font_name) { int i; struct font *pf; - struct skin_font *font = NULL; + struct skin_font_info *font = NULL; char filename[MAX_PATH]; if (!strcmp(font_name, global_settings.font_file)) diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 7fbf63bfe..8f802a12a 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -430,6 +430,19 @@ struct gui_img* find_image(char label, struct wps_data *data) } return NULL; } + +struct skin_font* find_font(int id, struct wps_data *data) +{ + struct skin_token_list *list = data->fonts; + while (list) + { + struct skin_font *f = (struct skin_font*)list->token->value.data; + if (f->id == id) + return f; + list = list->next; + } + return NULL; +} #endif /* traverse the viewport linked list for a viewport */ @@ -696,14 +709,14 @@ static int parse_image_load(const char *wps_bufptr, /* this array acts as a simple mapping between the id the user uses for a font * and the id the font actually gets from the font loader. * font id 2 is always the first skin font (regardless of how many screens */ -static int font_ids[MAXUSERFONTS]; static int parse_font_load(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data) { (void)wps_data; (void)token; const char *ptr = wps_bufptr; int id; - char *filename, buf[MAX_PATH]; + char *filename; + struct skin_font *font; if (*ptr != '|') return WPS_ERROR_INVALID_PARAM; @@ -719,13 +732,25 @@ static int parse_font_load(const char *wps_bufptr, if (id <= FONT_UI || id >= MAXFONTS-1) return WPS_ERROR_INVALID_PARAM; - id -= FONT_UI; - - memcpy(buf, filename, ptr-filename); - buf[ptr-filename] = '\0'; - font_ids[id] = skin_font_load(buf); - - return font_ids[id] >= 0 ? skip_end_of_line(wps_bufptr) : WPS_ERROR_INVALID_PARAM; + + font = skin_buffer_alloc(sizeof(struct skin_font)); + int len = ptr-filename+1; + char* name = skin_buffer_alloc(len); + if (!font || !name) + return WPS_ERROR_INVALID_PARAM; + + strlcpy(name, filename, len); + font->id = id; + font->font_id = -1; + font->name = name; + + struct skin_token_list *item = new_skin_token_list_item(NULL, font); + + if (!item) + return WPS_ERROR_INVALID_PARAM; + add_to_ll_chain(&wps_data->fonts, item); + + return skip_end_of_line(wps_bufptr); } @@ -931,13 +956,13 @@ static int parse_viewport(const char *wps_bufptr, else vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */ + /* increment because font=2 and FONT_UI_REMOTE is ambiguous */ + if (vp->font > FONT_UI) + vp->font++; #ifdef HAVE_REMOTE_LCD if (vp->font == FONT_UI && curr_screen == SCREEN_REMOTE) vp->font = FONT_UI_REMOTE; - else #endif - if (vp->font > FONT_UI) - vp->font = font_ids[vp->font - FONT_UI]; struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp); if (!list) @@ -1949,8 +1974,7 @@ static bool wps_parse(struct wps_data *data, const char *wps_bufptr, bool debug) static void skin_data_reset(struct wps_data *wps_data) { #ifdef HAVE_LCD_BITMAP - wps_data->images = NULL; - wps_data->progressbars = NULL; + wps_data->images = wps_data->progressbars = wps_data->fonts = NULL; #endif #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 wps_data->backdrop = NULL; @@ -2073,6 +2097,57 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) return retval; } +static bool skin_load_fonts(struct wps_data *data) +{ + /* don't spit out after the first failue to aid debugging */ + bool success = true; + struct skin_token_list *vp_list; + /* walk though each viewport and assign its font */ + for(vp_list = data->viewports; vp_list; vp_list = vp_list->next) + { + /* first, find the viewports that have a non-sys/ui-font font */ + struct skin_viewport *skin_vp = + (struct skin_viewport*)vp_list->token->value.data; + struct viewport *vp = &skin_vp->vp; + + + if (vp->font < SYSTEMFONTCOUNT) + { /* the usual case -> built-in fonts */ + continue; + } + + /* decrement, because font has been incremented in viewport parsing + * due to the FONT_UI_REMOTE ambiguity */ + int skin_font_id = vp->font-1; + + /* now find the corresponding skin_font */ + struct skin_font *font = find_font(skin_font_id, data); + if (!font) + { + DEBUGF("Could not find font %d\n", skin_font_id); + success = false; + continue; + } + + /* load the font - will handle loading the same font again if + * multiple viewports use the same */ + if (font->font_id < 0) + font->font_id = skin_font_load(font->name); + + if (font->font_id < 0) + { + DEBUGF("Unable to load font %d: '%s.fnt'\n", + skin_font_id, font->name); + success = false; + continue; + } + + /* finally, assign the font_id to the viewport */ + vp->font = font->font_id; + } + return success; +} + #endif /* HAVE_LCD_BITMAP */ /* to setup up the wps-data from a format-buffer (isfile = false) @@ -2188,6 +2263,12 @@ bool skin_data_load(enum screen_type screen, struct wps_data *wps_data, wps_data->wps_loaded = false; return false; } + if (!skin_load_fonts(wps_data)) + { + skin_data_reset(wps_data); + wps_data->wps_loaded = false; + return false; + } #endif #if defined(HAVE_ALBUMART) && !defined(__PCTOOL__) status = audio_status(); diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index f6c746380..aa99804fd 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -264,6 +264,12 @@ struct skin_albumart { }; #endif +struct skin_font { + int id; /* the id used in the %V tags */ + int font_id; /* the id returned by font_load */ + char *name; /* filename without path and extension */ +}; + /* wps_data this struct holds all necessary data which describes the viewable content of a wps */ @@ -272,6 +278,7 @@ struct wps_data #ifdef HAVE_LCD_BITMAP struct skin_token_list *images; struct skin_token_list *progressbars; + struct skin_token_list *fonts; #endif #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 char *backdrop; -- 2.11.4.GIT