From aa0f4a4bbe370032d8166628f456709be1330118 Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Sat, 24 Sep 2011 13:19:34 +0000 Subject: [PATCH] FS#12273 - use buflib for font storage. thanks to the testers :) git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30589 a1c6a512-1295-4272-9138-f99709370657 --- apps/SOURCES | 3 - apps/filetree.c | 18 +- apps/gui/skin_engine/skin_engine.c | 5 +- apps/gui/skin_engine/skin_engine.h | 4 +- apps/gui/skin_engine/skin_fonts.c | 142 --------- apps/gui/skin_engine/skin_fonts.h | 50 ---- apps/gui/skin_engine/skin_parser.c | 78 +++-- apps/gui/skin_engine/skin_render.c | 5 + apps/gui/skin_engine/wps_internals.h | 3 + apps/gui/statusbar-skinned.c | 4 + apps/gui/usb_screen.c | 9 +- apps/gui/viewport.c | 7 +- apps/main.c | 9 + apps/menus/theme_menu.c | 1 + apps/plugin.c | 5 +- apps/plugin.h | 3 +- apps/plugins/beatbox/beatbox.c | 2 +- apps/plugins/doom/rockdoom.c | 4 +- apps/plugins/lua/rocklib.c | 5 + apps/plugins/midi/midiplay.c | 2 +- apps/plugins/mikmod/mikmod.c | 4 +- apps/plugins/rockboy/menu.c | 2 +- apps/plugins/rockboy/rockboy.c | 2 +- apps/plugins/rockpaint.c | 15 +- apps/plugins/text_viewer/tv_display.c | 18 +- apps/plugins/text_viewer/tv_preferences.c | 10 +- apps/plugins/text_viewer/tv_preferences.h | 4 +- apps/plugins/text_viewer/tv_settings.c | 2 +- apps/plugins/text_viewer/tv_text_processor.c | 2 +- apps/recorder/albumart.c | 1 + apps/screen_access.c | 20 +- apps/screen_access.h | 2 + apps/settings.c | 46 ++- apps/settings.h | 3 + firmware/export/font.h | 23 +- firmware/font.c | 294 ++++++++++++------- firmware/include/core_alloc.h | 7 + 37 files changed, 410 insertions(+), 404 deletions(-) delete mode 100644 apps/gui/skin_engine/skin_fonts.c delete mode 100644 apps/gui/skin_engine/skin_fonts.h diff --git a/apps/SOURCES b/apps/SOURCES index 6b72d6ad09..443b42fedc 100644 --- a/apps/SOURCES +++ b/apps/SOURCES @@ -105,9 +105,6 @@ gui/viewport.c gui/skin_engine/skin_backdrops.c gui/skin_engine/skin_display.c gui/skin_engine/skin_engine.c -#ifdef HAVE_LCD_BITMAP -gui/skin_engine/skin_fonts.c -#endif gui/skin_engine/skin_parser.c gui/skin_engine/skin_render.c gui/skin_engine/skin_tokens.c diff --git a/apps/filetree.c b/apps/filetree.c index 35bb2a8fd0..59e7343600 100644 --- a/apps/filetree.c +++ b/apps/filetree.c @@ -404,27 +404,31 @@ int ft_load(struct tree_context* c, const char* tempdir) #ifdef HAVE_LCD_BITMAP static void ft_load_font(char *file) { + int current_font_id; + enum screen_type screen = SCREEN_MAIN; #if NB_SCREENS > 1 MENUITEM_STRINGLIST(menu, ID2P(LANG_CUSTOM_FONT), NULL, ID2P(LANG_MAIN_SCREEN), ID2P(LANG_REMOTE_SCREEN)) switch (do_menu(&menu, NULL, NULL, false)) { - case 0: /* main lcd */ - splash(0, ID2P(LANG_WAIT)); - font_load(NULL, file); + case 0: /* main lcd */ + screen = SCREEN_MAIN; set_file(file, (char *)global_settings.font_file, MAX_FILENAME); break; case 1: /* remote */ - splash(0, ID2P(LANG_WAIT)); - font_load_remoteui(file); + screen = SCREEN_REMOTE; set_file(file, (char *)global_settings.remote_font_file, MAX_FILENAME); break; } #else - splash(0, ID2P(LANG_WAIT)); - font_load(NULL, file); set_file(file, (char *)global_settings.font_file, MAX_FILENAME); #endif + splash(0, ID2P(LANG_WAIT)); + current_font_id = global_status.font_id[screen]; + if (current_font_id >= 0) + font_unload(current_font_id); + global_status.font_id[screen] = font_load(file); + viewportmanager_theme_changed(THEME_UI_VIEWPORT); } #endif diff --git a/apps/gui/skin_engine/skin_engine.c b/apps/gui/skin_engine/skin_engine.c index 7a9a10ec57..069c3467a9 100644 --- a/apps/gui/skin_engine/skin_engine.c +++ b/apps/gui/skin_engine/skin_engine.c @@ -107,9 +107,9 @@ void settings_apply_skins(void) { int i, j; - for (i=0; i ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 Jonathan Gordon - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include -#include -#include - -#include "file.h" -#include "settings.h" -#include "font.h" -#include "skin_buffer.h" -#include "skin_fonts.h" - -static struct skin_font_info { - struct font font; - int font_id; - char name[MAX_PATH]; - char *buffer; - int ref_count; /* how many times has this font been loaded? */ -} font_table[MAXUSERFONTS]; - -/* need this to know if we should be closing font fd's on the next init */ -static bool first_load = true; - -void skin_font_init(void) -{ - int i; - for(i=0;i= 0 && !strcmp(font_table[i].name, filename)) - { - font_table[i].ref_count++; - return font_table[i].font_id; - } - else if (!font && font_table[i].font_id == -1) - { - font = &font_table[i]; - strcpy(font_table[i].name, filename); - } - } - if (!font) - return -1; /* too many fonts loaded */ - - pf = &font->font; - if (!font->buffer) - { - if (!glyphs) - glyphs = GLYPHS_TO_CACHE; -#ifndef __PCTOOL__ - skin_font_size = font_glyphs_to_bufsize(filename, glyphs); -#else - skin_font_size = 1; -#endif - if ( !skin_font_size ) - return -1; - pf->buffer_start = (char*)skin_buffer_alloc(skin_font_size); - if (!pf->buffer_start) - return -1; - font->buffer = pf->buffer_start; - pf->buffer_size = skin_font_size; - } - else - { - pf->buffer_start = font->buffer; - } - - pf->fd = -1; - font->font_id = font_load(pf, filename); - - if (font->font_id < 0) - return -1; - font->ref_count = 1; - - return font->font_id; -} -/* unload a skin font. If a font has been loaded more than once it wont actually - * be unloaded untill all references have been unloaded */ -void skin_font_unload(int font_id) -{ - int i; - for(i=0;i ) \___| < | \_\ ( <_> > < < - * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ - * \/ \/ \/ \/ \/ - * $Id$ - * - * Copyright (C) 2010 Jonathan Gordon - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ****************************************************************************/ - -#include "config.h" -#include -#include -#include - -#include "file.h" -#include "settings.h" -#include "font.h" - -#ifndef _SKINFONTS_H_ -#define _SKINFONTS_H_ - -#if LCD_HEIGHT > 160 -#define SKIN_FONT_SIZE (1024*10) -#else -#define SKIN_FONT_SIZE (1024*3) -#endif -#define GLYPHS_TO_CACHE 256 - -void skin_font_init(void); - -/* load a font into the skin buffer. return the font id. - * reserve room for glyphs glyphs */ -int skin_font_load(char* font_name, int glyphs); - -/* unload a skin font. If a font has been loaded more than once it wont actually - * be unloaded untill all references have been unloaded */ -void skin_font_unload(int font_id); -#endif diff --git a/apps/gui/skin_engine/skin_parser.c b/apps/gui/skin_engine/skin_parser.c index 9c73c3e682..8c87553be3 100644 --- a/apps/gui/skin_engine/skin_parser.c +++ b/apps/gui/skin_engine/skin_parser.c @@ -62,7 +62,6 @@ #include "radio.h" #include "tuner.h" #endif -#include "skin_fonts.h" #ifdef HAVE_LCD_BITMAP #include "bmp.h" @@ -77,6 +76,12 @@ #define WPS_ERROR_INVALID_PARAM -1 +#if LCD_HEIGHT > 160 +#define SKIN_FONT_SIZE (1024*10) +#else +#define SKIN_FONT_SIZE (1024*3) +#endif +#define GLYPHS_TO_CACHE 256 static bool isdefault(struct skin_tag_parameter *param) { @@ -415,8 +420,13 @@ static int parse_font_load(struct skin_element *element, glyphs = element->params[2].data.number; else glyphs = GLYPHS_TO_CACHE; + if (id < 2) + { + DEBUGF("font id must be >= 2\n"); + return 1; + } #if defined(DEBUG) || defined(SIMULATOR) - if (skinfonts[id-FONT_FIRSTUSERFONT].name != NULL) + if (skinfonts[id-2].name != NULL) { DEBUGF("font id %d already being used\n", id); } @@ -426,9 +436,9 @@ static int parse_font_load(struct skin_element *element, ptr = strchr(filename, '.'); if (!ptr || strncmp(ptr, ".fnt", 4)) return WPS_ERROR_INVALID_PARAM; - skinfonts[id-FONT_FIRSTUSERFONT].id = -1; - skinfonts[id-FONT_FIRSTUSERFONT].name = filename; - skinfonts[id-FONT_FIRSTUSERFONT].glyphs = glyphs; + skinfonts[id-2].id = -1; + skinfonts[id-2].name = filename; + skinfonts[id-2].glyphs = glyphs; return 0; } @@ -1442,6 +1452,11 @@ void skin_data_free_buflib_allocs(struct wps_data *wps_data) core_free(img->buflib_handle); list = list->next; } + if (wps_data->font_ids != NULL) + { + while (wps_data->font_count > 0) + font_unload(wps_data->font_ids[--wps_data->font_count]); + } #endif #endif } @@ -1617,6 +1632,8 @@ static bool load_skin_bitmaps(struct wps_data *wps_data, char *bmpdir) static bool skin_load_fonts(struct wps_data *data) { /* don't spit out after the first failue to aid debugging */ + int id_array[MAXUSERFONTS]; + int font_count = 0; bool success = true; struct skin_element *vp_list; int font_id; @@ -1628,19 +1645,20 @@ static bool skin_load_fonts(struct wps_data *data) (struct skin_viewport*)vp_list->data; struct viewport *vp = &skin_vp->vp; - - if (vp->font <= FONT_UI) + font_id = skin_vp->parsed_fontid; + if (font_id == 1) { /* the usual case -> built-in fonts */ -#ifdef HAVE_REMOTE_LCD - if (vp->font == FONT_UI) - vp->font += curr_screen; -#endif + vp->font = global_status.font_id[curr_screen]; + continue; + } + else if (font_id <= 0) + { + vp->font = FONT_SYSFIXED; continue; } - font_id = vp->font; /* now find the corresponding skin_font */ - struct skin_font *font = &skinfonts[font_id-FONT_FIRSTUSERFONT]; + struct skin_font *font = &skinfonts[font_id-2]; if (!font->name) { if (success) @@ -1655,10 +1673,12 @@ static bool skin_load_fonts(struct wps_data *data) * multiple viewports use the same */ if (font->id < 0) { - char *dot = strchr(font->name, '.'); - *dot = '\0'; - font->id = skin_font_load(font->name, - skinfonts[font_id-FONT_FIRSTUSERFONT].glyphs); + char path[MAX_PATH]; + snprintf(path, sizeof path, FONT_DIR "/%s", font->name); + font->id = font_load(path/*, + skinfonts[font_id-FONT_FIRSTUSERFONT].glyphs*/); + //printf("[%d] %s -> %d\n",font_id, font->name, font->id); + id_array[font_count++] = font->id; } if (font->id < 0) @@ -1667,13 +1687,24 @@ static bool skin_load_fonts(struct wps_data *data) font_id, font->name); font->name = NULL; /* to stop trying to load it again if we fail */ success = false; - font->name = NULL; continue; } /* finally, assign the font_id to the viewport */ vp->font = font->id; } + if (success) + { + data->font_ids = skin_buffer_alloc(font_count * sizeof(int)); + if (data->font_ids == NULL) + { + while (font_count > 0) + font_unload(id_array[--font_count]); + return false; + } + memcpy(data->font_ids, id_array, sizeof(int)*font_count); + data->font_count = font_count; + } return success; } @@ -1690,17 +1721,12 @@ static int convert_viewport(struct wps_data *data, struct skin_element* element) skin_vp->hidden_flags = 0; skin_vp->label = NULL; skin_vp->is_infovp = false; + skin_vp->parsed_fontid = 1; element->data = skin_vp; curr_vp = skin_vp; curr_viewport_element = element; viewport_set_defaults(&skin_vp->vp, curr_screen); -#ifdef HAVE_REMOTE_LCD - /* viewport_set_defaults() sets the font to FONT_UI+curr_screen. - * This parser requires font 1 to always be the UI font, - * so force it back to FONT_UI and handle the screen number at the end */ - skin_vp->vp.font = FONT_UI; -#endif #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) skin_vp->start_fgcolour = skin_vp->vp.fg_pattern; @@ -1788,9 +1814,7 @@ static int convert_viewport(struct wps_data *data, struct skin_element* element) #ifdef HAVE_LCD_BITMAP /* font */ if (!isdefault(param)) - { - skin_vp->vp.font = param->data.number; - } + skin_vp->parsed_fontid = param->data.number; #endif if ((unsigned) skin_vp->vp.x >= (unsigned) display->lcdwidth || skin_vp->vp.width + skin_vp->vp.x > display->lcdwidth || diff --git a/apps/gui/skin_engine/skin_render.c b/apps/gui/skin_engine/skin_render.c index 994ca23553..5a64be17dc 100644 --- a/apps/gui/skin_engine/skin_render.c +++ b/apps/gui/skin_engine/skin_render.c @@ -31,6 +31,7 @@ #ifdef HAVE_ALBUMART #include "albumart.h" #endif +#include "settings.h" #include "skin_display.h" #include "skin_engine.h" #include "skin_parser.h" @@ -650,6 +651,10 @@ void skin_render_viewport(struct skin_element* viewport, struct gui_wps *gwps, img->display = -1; imglist = imglist->next; } + + /* fix font ID's */ + if (skin_viewport->parsed_fontid == 1) + skin_viewport->vp.font = global_status.font_id[display->screen_type]; #endif while (line) diff --git a/apps/gui/skin_engine/wps_internals.h b/apps/gui/skin_engine/wps_internals.h index 244d08595e..c16191c41d 100644 --- a/apps/gui/skin_engine/wps_internals.h +++ b/apps/gui/skin_engine/wps_internals.h @@ -182,6 +182,7 @@ struct skin_viewport { char hidden_flags; bool is_infovp; char* label; + int parsed_fontid; #if LCD_DEPTH > 1 unsigned start_fgcolour; unsigned start_bgcolour; @@ -325,6 +326,8 @@ struct wps_data struct skin_element *tree; #ifdef HAVE_LCD_BITMAP struct skin_token_list *images; + int *font_ids; + int font_count; #endif #if LCD_DEPTH > 1 || defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 struct { diff --git a/apps/gui/statusbar-skinned.c b/apps/gui/statusbar-skinned.c index 3f914bd922..ad9a391e4c 100644 --- a/apps/gui/statusbar-skinned.c +++ b/apps/gui/statusbar-skinned.c @@ -125,6 +125,10 @@ struct viewport *sb_skin_get_info_vp(enum screen_type screen) viewportmanager_theme_undo(screen, true); } vp = skin_find_item(infovp_label[screen], SKIN_FIND_UIVP, data); + if (!vp) + return NULL; + if (vp->parsed_fontid == 1) + vp->vp.font = global_status.font_id[screen]; return &vp->vp; } diff --git a/apps/gui/usb_screen.c b/apps/gui/usb_screen.c index 66b7094760..2b3355021d 100644 --- a/apps/gui/usb_screen.c +++ b/apps/gui/usb_screen.c @@ -41,7 +41,6 @@ #ifdef HAVE_LCD_BITMAP #include "bitmaps/usblogo.h" -#include "skin_engine/skin_fonts.h" #endif #ifdef HAVE_REMOTE_LCD @@ -265,11 +264,9 @@ void gui_usb_screen_run(bool early_usb) { /* The font system leaves the .fnt fd's open, so we need for force close them all */ #ifdef HAVE_LCD_BITMAP - font_reset(NULL); -#ifdef HAVE_REMOTE_LCD - font_load_remoteui(NULL); -#endif - skin_font_init(); /* unload all the skin fonts */ + FOR_NB_SCREENS(i) + font_unload(global_status.font_id[i]); + // FIXME skin_font_init(); /* unload all the skin fonts */ #endif } diff --git a/apps/gui/viewport.c b/apps/gui/viewport.c index 34ebbf9043..df8093d581 100644 --- a/apps/gui/viewport.c +++ b/apps/gui/viewport.c @@ -272,13 +272,10 @@ void viewportmanager_theme_changed(const int which) screens[SCREEN_MAIN].has_buttonbar = global_settings.buttonbar; } #endif - if (which & THEME_UI_VIEWPORT) - { - } if (which & THEME_LANGUAGE) { } - if (which & THEME_STATUSBAR) + if (which & (THEME_STATUSBAR|THEME_UI_VIEWPORT)) { FOR_NB_SCREENS(i) { @@ -324,7 +321,7 @@ void viewport_set_fullscreen(struct viewport *vp, #ifndef __PCTOOL__ set_default_align_flags(vp); #endif - vp->font = FONT_UI + screen; /* default to UI to discourage SYSFONT use */ + vp->font = global_status.font_id[screen]; vp->drawmode = DRMODE_SOLID; #if LCD_DEPTH > 1 #ifdef HAVE_REMOTE_LCD diff --git a/apps/main.c b/apps/main.c index 07a8bba44c..ae666adc06 100644 --- a/apps/main.c +++ b/apps/main.c @@ -336,6 +336,7 @@ static void init_tagcache(void) static void init(void) { + int i; system_init(); core_allocator_init(); kernel_init(); @@ -347,7 +348,11 @@ static void init(void) #ifdef HAVE_REMOTE_LCD lcd_remote_init(); #endif +#ifdef HAVE_LCD_BITMAP + FOR_NB_SCREENS(i) + global_status.font_id[i] = FONT_SYSFIXED; font_init(); +#endif show_logo(); button_init(); powermgmt_init(); @@ -451,7 +456,11 @@ static void init(void) #ifdef HAVE_REMOTE_LCD lcd_remote_init(); #endif +#ifdef HAVE_LCD_BITMAP + FOR_NB_SCREENS(rc) + global_status.font_id[rc] = FONT_SYSFIXED; font_init(); +#endif CHART(">show_logo"); show_logo(); diff --git a/apps/menus/theme_menu.c b/apps/menus/theme_menu.c index b483a7ef11..078691e1a8 100644 --- a/apps/menus/theme_menu.c +++ b/apps/menus/theme_menu.c @@ -19,6 +19,7 @@ * ****************************************************************************/ +#include #include #include #include diff --git a/apps/plugin.c b/apps/plugin.c index 2517a7183f..7c75a43080 100644 --- a/apps/plugin.c +++ b/apps/plugin.c @@ -174,7 +174,7 @@ static const struct plugin_api rockbox_api = { lcd_update_rect, lcd_set_drawmode, lcd_get_drawmode, - lcd_setfont, + screen_helper_setfont, lcd_drawpixel, lcd_drawline, lcd_hline, @@ -230,6 +230,7 @@ static const struct plugin_api rockbox_api = { #endif font_get_bits, font_load, + font_unload, font_get, font_getstringsize, font_get_width, @@ -905,7 +906,7 @@ int plugin_load(const char* plugin, const void* parameter) #endif #ifdef HAVE_LCD_BITMAP - lcd_setfont(FONT_UI); + screen_helper_setfont(FONT_UI); #if LCD_DEPTH > 1 #ifdef HAVE_LCD_COLOR lcd_set_drawinfo(DRMODE_SOLID, global_settings.fg_color, diff --git a/apps/plugin.h b/apps/plugin.h index a33089bece..e0ee951185 100644 --- a/apps/plugin.h +++ b/apps/plugin.h @@ -272,7 +272,8 @@ struct plugin_api { bool (*is_diacritic)(const unsigned short char_code, bool *is_rtl); #endif const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code ); - int (*font_load)(struct font*, const char *path); + int (*font_load)(const char *path); + void (*font_unload)(int font_id); struct font* (*font_get)(int font); int (*font_getstringsize)(const unsigned char *str, int *w, int *h, int fontnumber); diff --git a/apps/plugins/beatbox/beatbox.c b/apps/plugins/beatbox/beatbox.c index b09464ab14..8ecbabd1e5 100644 --- a/apps/plugins/beatbox/beatbox.c +++ b/apps/plugins/beatbox/beatbox.c @@ -265,7 +265,7 @@ enum plugin_status plugin_start(const void* parameter) { int retval = 0; - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); diff --git a/apps/plugins/doom/rockdoom.c b/apps/plugins/doom/rockdoom.c index 1c2777a8ad..85e3225af8 100644 --- a/apps/plugins/doom/rockdoom.c +++ b/apps/plugins/doom/rockdoom.c @@ -667,7 +667,7 @@ enum plugin_status plugin_start(const void* parameter) rb->cpu_boost(true); #endif - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); // We're using doom's memory management since it implements a proper free (and re-uses the memory) // and now with prboom's code: realloc and calloc @@ -712,7 +712,7 @@ enum plugin_status plugin_start(const void* parameter) Dhandle_ver( namemap[ result ] ); - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); rb->lcd_clear_display(); diff --git a/apps/plugins/lua/rocklib.c b/apps/plugins/lua/rocklib.c index 46572014f0..ddd4081371 100644 --- a/apps/plugins/lua/rocklib.c +++ b/apps/plugins/lua/rocklib.c @@ -433,6 +433,11 @@ RB_WRAP(font_getstringsize) int fontnumber = luaL_checkint(L, 2); int w, h; + if (fontnumber == FONT_UI) + fontnumber = rb->global_status->font_id[SCREEN_MAIN]; + else + fontnumber = FONT_SYSFIXED; + int result = rb->font_getstringsize(str, &w, &h, fontnumber); lua_pushinteger(L, result); lua_pushinteger(L, w); diff --git a/apps/plugins/midi/midiplay.c b/apps/plugins/midi/midiplay.c index 9bf4d50822..16d153a1ba 100644 --- a/apps/plugins/midi/midiplay.c +++ b/apps/plugins/midi/midiplay.c @@ -470,7 +470,7 @@ enum plugin_status plugin_start(const void* parameter) rb->splash(HZ*2, " Play .MID file "); return PLUGIN_OK; } - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); #if defined(HAVE_ADJUSTABLE_CPU_FREQ) rb->cpu_boost(true); diff --git a/apps/plugins/mikmod/mikmod.c b/apps/plugins/mikmod/mikmod.c index 5f19b43759..a7eeb5019f 100644 --- a/apps/plugins/mikmod/mikmod.c +++ b/apps/plugins/mikmod/mikmod.c @@ -823,7 +823,7 @@ int playfile(char* filename) retval = menureturn; } } - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); screenupdated = false; break; @@ -877,7 +877,7 @@ enum plugin_status plugin_start(const void* parameter) return PLUGIN_OK; } - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); rb->pcm_play_stop(); #if INPUT_SRC_CAPS != 0 diff --git a/apps/plugins/rockboy/menu.c b/apps/plugins/rockboy/menu.c index 54a0db76f5..3cd231c06c 100644 --- a/apps/plugins/rockboy/menu.c +++ b/apps/plugins/rockboy/menu.c @@ -125,7 +125,7 @@ int do_user_menu(void) { } } - rb->lcd_setfont(0); /* Reset the font */ + rb->lcd_setfont(FONT_SYSFIXED); /* Reset the font */ rb->lcd_clear_display(); /* Clear display for screen size changes */ /* Keep the RTC in sync */ diff --git a/apps/plugins/rockboy/rockboy.c b/apps/plugins/rockboy/rockboy.c index 4dc88fdf5a..88828815aa 100644 --- a/apps/plugins/rockboy/rockboy.c +++ b/apps/plugins/rockboy/rockboy.c @@ -409,7 +409,7 @@ static int gnuboy_main(const char *rom) /* this is the plugin entry point */ enum plugin_status plugin_start(const void* parameter) { - rb->lcd_setfont(0); + rb->lcd_setfont(FONT_SYSFIXED); rb->lcd_clear_display(); diff --git a/apps/plugins/rockpaint.c b/apps/plugins/rockpaint.c index d1cc8f272a..7938273ba0 100644 --- a/apps/plugins/rockpaint.c +++ b/apps/plugins/rockpaint.c @@ -1016,7 +1016,6 @@ static bool browse_fonts( char *dst, int dst_size ) size_t siz; reset_font = true; rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", e->name ); - rb->font_load(NULL, bbuf ); rb->font_getstringsize( e->name, &fw, &fh, FONT_UI ); if( fw > LCD_WIDTH ) fw = LCD_WIDTH; siz = (sizeof(struct font_preview) + fw*fh*FB_DATA_SZ+3) & ~3; @@ -1083,7 +1082,7 @@ static bool browse_fonts( char *dst, int dst_size ) li = tree->filesindir-1; if( reset_font ) { - rb->font_load(NULL, bbuf_s ); + // fixme rb->font_load(NULL, bbuf_s ); reset_font = false; } if( lvi-fvi+1 < tree->filesindir ) @@ -1636,6 +1635,7 @@ static void show_grid( bool update ) static void draw_text( int x, int y ) { int selected = 0; + int current_font_id = rb->global_status->font_id[SCREEN_MAIN]; buffer->text.text[0] = '\0'; buffer->text.font[0] = '\0'; while( 1 ) @@ -1648,9 +1648,12 @@ static void draw_text( int x, int y ) break; case TEXT_MENU_FONT: - if( browse_fonts( buffer->text.font, MAX_PATH ) ) + if (current_font_id != rb->global_status->font_id[SCREEN_MAIN]) + rb->font_unload(current_font_id); + if(browse_fonts( buffer->text.font, MAX_PATH ) ) { - rb->font_load(NULL, buffer->text.font ); + current_font_id = rb->font_load(buffer->text.font ); + rb->lcd_setfont(current_font_id); } break; @@ -1704,7 +1707,9 @@ static void draw_text( int x, int y ) rb->snprintf( buffer->text.font, MAX_PATH, FONT_DIR "/%s.fnt", rb->global_settings->font_file ); - rb->font_load(NULL, buffer->text.font ); + if (current_font_id != rb->global_status->font_id[SCREEN_MAIN]) + rb->font_unload(current_font_id); + rb->lcd_setfont(FONT_UI); } return; } diff --git a/apps/plugins/text_viewer/tv_display.c b/apps/plugins/text_viewer/tv_display.c index d38f1b514c..2cf240db0e 100644 --- a/apps/plugins/text_viewer/tv_display.c +++ b/apps/plugins/text_viewer/tv_display.c @@ -255,7 +255,7 @@ void tv_set_layout(bool show_scrollbar) int scrollbar_height = (show_scrollbar && preferences->horizontal_scrollbar)? TV_SCROLLBAR_HEIGHT + 1 : 0; - row_height = preferences->font->height; + row_height = rb->font_get(preferences->font_id)->height; header.x = 0; header.y = 0; @@ -282,6 +282,7 @@ void tv_set_layout(bool show_scrollbar) vp_text.y += vertical_scrollbar.y; vp_text.width = horizontal_scrollbar.w; vp_text.height = vertical_scrollbar.h; + vp_text.font = preferences->font_id; #else (void) show_scrollbar; @@ -334,16 +335,20 @@ static void tv_change_viewport(void) static bool tv_set_font(const unsigned char *font) { unsigned char path[MAX_PATH]; - if (font != NULL && *font != '\0') { rb->snprintf(path, MAX_PATH, "%s/%s.fnt", FONT_DIR, font); - if (rb->font_load(NULL, path) < 0) + if (preferences->font_id >= 0 && + (preferences->font_id != rb->global_status->font_id[SCREEN_MAIN])) + rb->font_unload(preferences->font_id); + tv_change_fontid(rb->font_load(path)); + if (preferences->font_id < 0) { rb->splash(HZ/2, "font load failed"); return false; } } + vp_text.font = preferences->font_id; return true; } #endif @@ -375,7 +380,7 @@ static int tv_change_preferences(const struct tv_preferences *oldp) return (tv_set_preferences(&new_prefs))? TV_CALLBACK_STOP : TV_CALLBACK_ERROR; } - col_width = 2 * rb->font_get_width(preferences->font, ' '); + col_width = 2 * rb->font_get_width(rb->font_get(preferences->font_id), ' '); font_changing = false; } #else @@ -402,9 +407,10 @@ void tv_finalize_display(void) { #ifdef HAVE_LCD_BITMAP /* restore font */ - if (rb->strcmp(rb->global_settings->font_file, preferences->font_name)) + if (preferences->font_id >= 0 && + (preferences->font_id != rb->global_status->font_id[SCREEN_MAIN])) { - tv_set_font(rb->global_settings->font_file); + rb->font_unload(preferences->font_id); } /* undo viewport */ diff --git a/apps/plugins/text_viewer/tv_preferences.c b/apps/plugins/text_viewer/tv_preferences.c index 6d5c1127fc..86719ae16b 100644 --- a/apps/plugins/text_viewer/tv_preferences.c +++ b/apps/plugins/text_viewer/tv_preferences.c @@ -114,7 +114,7 @@ void tv_set_default_preferences(struct tv_preferences *p) p->footer_mode = true; p->statusbar = true; rb->strlcpy(p->font_name, rb->global_settings->font_file, MAX_PATH); - p->font = rb->font_get(FONT_UI); + p->font_id = rb->global_status->font_id[SCREEN_MAIN]; #else p->header_mode = false; p->footer_mode = false; @@ -133,3 +133,11 @@ void tv_add_preferences_change_listner(int (*listner)(const struct tv_preference if (listner_count < TV_MAX_LISTNERS) listners[listner_count++] = listner; } + +void tv_change_fontid(int id) +{ + (void)id; +#ifdef HAVE_LCD_BITMAP + prefs.font_id = id; +#endif +} diff --git a/apps/plugins/text_viewer/tv_preferences.h b/apps/plugins/text_viewer/tv_preferences.h index bb448b0f4b..f3b2aebfa6 100644 --- a/apps/plugins/text_viewer/tv_preferences.h +++ b/apps/plugins/text_viewer/tv_preferences.h @@ -95,7 +95,7 @@ struct tv_preferences { #ifdef HAVE_LCD_BITMAP unsigned char font_name[MAX_PATH]; - struct font *font; + int font_id; #endif unsigned char file_name[MAX_PATH]; }; @@ -151,4 +151,6 @@ void tv_set_default_preferences(struct tv_preferences *p); */ void tv_add_preferences_change_listner(int (*listner)(const struct tv_preferences *oldp)); + +void tv_change_fontid(int id); #endif diff --git a/apps/plugins/text_viewer/tv_settings.c b/apps/plugins/text_viewer/tv_settings.c index 3ed1576dc5..895f162ebb 100644 --- a/apps/plugins/text_viewer/tv_settings.c +++ b/apps/plugins/text_viewer/tv_settings.c @@ -218,7 +218,7 @@ static bool tv_read_preferences(int pfd, int version, struct tv_preferences *pre #ifdef HAVE_LCD_BITMAP rb->strlcpy(prefs->font_name, buf + read_size - MAX_PATH, MAX_PATH); - prefs->font = rb->font_get(FONT_UI); + prefs->font_id = rb->global_status->font_id[SCREEN_MAIN]; #endif return true; diff --git a/apps/plugins/text_viewer/tv_text_processor.c b/apps/plugins/text_viewer/tv_text_processor.c index edb2ad0483..d027a9a13a 100644 --- a/apps/plugins/text_viewer/tv_text_processor.c +++ b/apps/plugins/text_viewer/tv_text_processor.c @@ -95,7 +95,7 @@ static int tv_glyph_width(int ch) if (rb->is_diacritic(ch, NULL)) return 0; - return rb->font_get_width(preferences->font, ch); + return rb->font_get_width(rb->font_get(preferences->font_id), ch); #else return 1; #endif diff --git a/apps/recorder/albumart.c b/apps/recorder/albumart.c index 5acb492412..43f18cd163 100644 --- a/apps/recorder/albumart.c +++ b/apps/recorder/albumart.c @@ -19,6 +19,7 @@ * ****************************************************************************/ +#include #include "string-extra.h" #include "system.h" #include "albumart.h" diff --git a/apps/screen_access.c b/apps/screen_access.c index b83e842de8..0b206a668a 100644 --- a/apps/screen_access.c +++ b/apps/screen_access.c @@ -67,6 +67,15 @@ static int screen_helper_getnblines(void) return height / screens[0].getcharheight(); } +void screen_helper_setfont(int font) +{ +#ifdef HAVE_LCD_BITMAP + if (font == FONT_UI) + font = global_status.font_id[SCREEN_MAIN]; + lcd_setfont(font); +#endif +} + #if NB_SCREENS == 2 static int screen_helper_remote_getcharwidth(void) { @@ -99,6 +108,13 @@ static int screen_helper_remote_getnblines(void) #endif return height / screens[1].getcharheight(); } + +void screen_helper_remote_setfont(int font) +{ + if (font == FONT_UI) + font = global_status.font_id[SCREEN_REMOTE]; + lcd_remote_setfont(font); +} #endif struct screen screens[NB_SCREENS] = @@ -129,7 +145,7 @@ struct screen screens[NB_SCREENS] = .getheight=&lcd_getheight, .getstringsize=&lcd_getstringsize, #ifdef HAVE_LCD_BITMAP - .setfont=&lcd_setfont, + .setfont=screen_helper_setfont, .getfont=&lcd_getfont, .mono_bitmap=&lcd_mono_bitmap, .mono_bitmap_part=&lcd_mono_bitmap_part, @@ -229,7 +245,7 @@ struct screen screens[NB_SCREENS] = .getheight=&lcd_remote_getheight, .getstringsize=&lcd_remote_getstringsize, #if 1 /* all remote LCDs are bitmapped so far */ - .setfont=&lcd_remote_setfont, + .setfont=screen_helper_setfont, .getfont=&lcd_remote_getfont, .mono_bitmap=&lcd_remote_mono_bitmap, .mono_bitmap_part=&lcd_remote_mono_bitmap_part, diff --git a/apps/screen_access.h b/apps/screen_access.h index efe232b50e..31ec34f2b6 100644 --- a/apps/screen_access.h +++ b/apps/screen_access.h @@ -28,9 +28,11 @@ #if defined(HAVE_REMOTE_LCD) && !defined (ROCKBOX_HAS_LOGF) #define NB_SCREENS 2 +void screen_helper_remote_setfont(int font); #else #define NB_SCREENS 1 #endif +void screen_helper_setfont(int font); #if NB_SCREENS == 1 #define FOR_NB_SCREENS(i) i = 0; diff --git a/apps/settings.c b/apps/settings.c index 258facee38..14217ed1ae 100644 --- a/apps/settings.c +++ b/apps/settings.c @@ -876,30 +876,38 @@ void settings_apply(bool read_disk) /* fonts need to be loaded before the WPS */ if (global_settings.font_file[0] && global_settings.font_file[0] != '-') { + const char* loaded_font = font_filename(global_status.font_id[SCREEN_MAIN]); snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", global_settings.font_file); - CHART2(">font_load ", global_settings.font_file); - rc = font_load(NULL, buf); - CHART2("font_load ", global_settings.font_file); + if (global_status.font_id[SCREEN_MAIN] >= 0) + font_unload(global_status.font_id[SCREEN_MAIN]); + rc = font_load(buf); + CHART2("font_load_remoteui ", global_settings.remote_font_file); - rc = font_load_remoteui(buf); - CHART2("font_load_remoteui ", global_settings.remote_font_file); + if (global_status.font_id[SCREEN_REMOTE] >= 0) + font_unload(global_status.font_id[SCREEN_REMOTE]); + rc = font_load(buf); + CHART2(" FONT_SYSFIXED) + { + font_unload(global_status.font_id[i]); + global_status.font_id[i] = FONT_SYSFIXED; + } + } +#endif } /** Changing setting values **/ diff --git a/apps/settings.h b/apps/settings.h index d7a72268e6..36e403be1b 100644 --- a/apps/settings.h +++ b/apps/settings.h @@ -278,6 +278,9 @@ struct system_status signed char last_screen; int viewer_icon_count; int last_volume_change; /* tick the last volume change happened. skins use this */ +#ifdef HAVE_LCD_BITMAP + int font_id[NB_SCREENS]; /* font id of the settings font for each screen */ +#endif }; struct user_settings diff --git a/firmware/export/font.h b/firmware/export/font.h index a85f95e6ae..6c9e6163af 100644 --- a/firmware/export/font.h +++ b/firmware/export/font.h @@ -22,6 +22,7 @@ #define _FONT_H #include "inttypes.h" +#include "stdbool.h" /* * Incore font and image definitions @@ -46,18 +47,14 @@ * Fonts are specified in firmware/font.c. */ enum { - FONT_SYSFIXED, /* system fixed pitch font*/ - FONT_UI, /* system porportional font*/ -#ifdef HAVE_REMOTE_LCD - FONT_UI_REMOTE, /* UI font for remote LCD */ -#endif - SYSTEMFONTCOUNT, /* Number of fonts reserved for the system and ui */ - FONT_FIRSTUSERFONT = 2 + FONT_SYSFIXED = -1, /* system fixed pitch font*/ + FONT_FIRSTUSERFONT = 0, /* first id for the user fonts */ }; #define MAXUSERFONTS 8 /* SYSFONT, FONT_UI, FONT_UI_REMOTE + MAXUSERFONTS fonts in skins */ -#define MAXFONTS (SYSTEMFONTCOUNT + MAXUSERFONTS) +#define MAXFONTS (FONT_FIRSTUSERFONT + MAXUSERFONTS) +#define FONT_UI MAXFONTS /* * .fnt loadable font file format definition @@ -105,7 +102,7 @@ struct font { unsigned char *buffer_start; /* buffer to store the font in */ unsigned char *buffer_position; /* position in the buffer */ unsigned char *buffer_end; /* end of the buffer */ - int buffer_size; /* size of the buffer in bytes */ + int buffer_size; /* size of the buffer in bytes */ #ifndef __PCTOOL__ struct font_cache cache; uint32_t file_width_offset; /* offset to file width data */ @@ -117,17 +114,13 @@ struct font { /* font routines*/ void font_init(void) INIT_ATTR; -#ifdef HAVE_REMOTE_LCD -/* Load a font into the special remote ui font slot */ -int font_load_remoteui(const char* path); -#endif -int font_load(struct font* pf, const char *path); +const char* font_filename(int font_id); +int font_load(const char *path); int font_glyphs_to_bufsize(const char *path, int glyphs); void font_unload(int font_id); struct font* font_get(int font); -void font_reset(struct font *pf); int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); int font_get_width(struct font* ft, unsigned short ch); const unsigned char * font_get_bits(struct font* ft, unsigned short ch); diff --git a/firmware/font.c b/firmware/font.c index 0f9f453ae2..fea210a3f1 100644 --- a/firmware/font.c +++ b/firmware/font.c @@ -34,6 +34,7 @@ #include "system.h" #include "font.h" #include "file.h" +#include "core_alloc.h" #include "debug.h" #include "panic.h" #include "rbunicode.h" @@ -74,19 +75,58 @@ extern struct font sysfont; #ifndef BOOTLOADER -/* structure filled in by font_load */ -static struct font font_ui; -/* static buffer allocation structures */ -static unsigned char main_buf[MAX_FONT_SIZE] CACHEALIGN_ATTR; -#ifdef HAVE_REMOTE_LCD -#define REMOTE_FONT_SIZE 10000 -static struct font remote_font_ui; -static unsigned char remote_buf[REMOTE_FONT_SIZE] CACHEALIGN_ATTR; -#endif +struct buflib_alloc_data { + struct font font; + bool handle_locked; /* is the buflib handle currently locked? */ + int refcount; /* how many times has this font been loaded? */ + unsigned char buffer[MAX_FONT_SIZE]; +}; +static int buflib_allocations[MAXFONTS]; +static int handle_for_glyphcache; -/* system font table, in order of FONT_xxx definition */ -static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui, NULL}; +static int buflibmove_callback(int handle, void* current, void* new) +{ + (void)handle; + struct buflib_alloc_data *alloc = (struct buflib_alloc_data*)current; + size_t diff = new - current; + if (alloc->handle_locked) + return BUFLIB_CB_CANNOT_MOVE; + + alloc->font.bits += diff; + alloc->font.offset += diff; + if (alloc->font.width) + alloc->font.width += diff; + + alloc->font.buffer_start += diff; + alloc->font.buffer_end += diff; + alloc->font.buffer_position += diff; + + alloc->font.cache._index += diff; + + return BUFLIB_CB_OK; +} +static void lock_font_handle(int handle, bool lock) +{ + struct buflib_alloc_data *alloc = core_get_data(handle); + alloc->handle_locked = lock; +} + +static struct buflib_callbacks buflibops = {buflibmove_callback, NULL }; + +static inline struct font *pf_from_handle(int handle) +{ + struct buflib_alloc_data *alloc = core_get_data(handle); + struct font *pf = &alloc->font; + return pf; +} + +static inline unsigned char *buffer_from_handle(int handle) +{ + struct buflib_alloc_data *alloc = core_get_data(handle); + unsigned char* buffer = alloc->buffer; + return buffer; +} /* Font cache structures */ static void cache_create(struct font* pf); @@ -95,13 +135,10 @@ static void glyph_cache_load(struct font* pf); void font_init(void) { - int i = SYSTEMFONTCOUNT; + int i = 0; while (iheight + 7) / 8); } -void font_reset(struct font *pf) -{ - unsigned char* buffer = NULL; - size_t buf_size = 0; - if (pf == NULL) - pf = &font_ui; - else - { - buffer = pf->buffer_start; - buf_size = pf->buffer_size; - } - memset(pf, 0, sizeof(struct font)); - pf->fd = -1; - if (buffer) - { - pf->buffer_start = buffer; - pf->buffer_size = buf_size; - } -} - static struct font* font_load_header(struct font *pf) { /* Check we have enough data */ @@ -320,18 +337,27 @@ static struct font* font_load_cached(struct font* pf) return pf; } -static bool internal_load_font(struct font* pf, const char *path, +static void font_reset(int font_id) +{ + struct font *pf = pf_from_handle(buflib_allocations[font_id]); + // fixme + memset(pf, 0, sizeof(struct font)); + pf->fd = -1; +} + + +static bool internal_load_font(int font_id, const char *path, char *buf, size_t buf_size) { int size; - + struct font* pf = pf_from_handle(buflib_allocations[font_id]); /* save loaded glyphs */ glyph_cache_save(pf); /* Close font file handle */ if (pf->fd >= 0) close(pf->fd); - font_reset(pf); + font_reset(font_id); /* open and read entire font file*/ pf->fd = open(path, O_RDONLY|O_BINARY); @@ -393,80 +419,117 @@ static bool internal_load_font(struct font* pf, const char *path, return true; } -#ifdef HAVE_REMOTE_LCD -/* Load a font into the special remote ui font slot */ -int font_load_remoteui(const char* path) +static int find_font_index(const char* path) { - struct font* pf = &remote_font_ui; - if (!path) - { - if (sysfonts[FONT_UI_REMOTE] && sysfonts[FONT_UI_REMOTE] != sysfonts[FONT_UI]) - font_unload(FONT_UI_REMOTE); - sysfonts[FONT_UI_REMOTE] = NULL; - return FONT_UI; - } - if (!internal_load_font(pf, path, remote_buf, REMOTE_FONT_SIZE)) - { - sysfonts[FONT_UI_REMOTE] = NULL; - return -1; - } - - sysfonts[FONT_UI_REMOTE] = pf; - return FONT_UI_REMOTE; -} -#endif + int index = 0, handle; + while (index < MAXFONTS) + { + handle = buflib_allocations[index]; + if (handle > 0 && !strcmp(core_get_name(handle), path)) + return index; + index++; + } + return FONT_SYSFIXED; +} + +static int alloc_and_init(int font_idx, const char* name) +{ + int *phandle = &buflib_allocations[font_idx]; + int handle = *phandle; + struct buflib_alloc_data *pdata; + struct font *pf; + if (handle > 0) + return handle; + *phandle = core_alloc_ex(name, sizeof(struct buflib_alloc_data), &buflibops); + handle = *phandle; + if (handle < 0) + return handle; + pdata = core_get_data(handle); + pf = &pdata->font; + font_reset(font_idx); + pdata->handle_locked = false; + pdata->refcount = 1; + pf->buffer_position = pf->buffer_start = buffer_from_handle(handle); + pf->buffer_size = MAX_FONT_SIZE; + return handle; +} + +const char* font_filename(int font_id) +{ + int handle = buflib_allocations[font_id]; + if (handle > 0) + return core_get_name(handle); + return NULL; +} + /* read and load font into incore font structure, * returns the font number on success, -1 on failure */ -int font_load(struct font* pf, const char *path) +int font_load(const char *path) { - int font_id = -1; + int font_id = find_font_index(path); char *buffer; size_t buffer_size; - if (pf == NULL) + int *handle; + + if (font_id > FONT_SYSFIXED) { - pf = &font_ui; - font_id = FONT_UI; + /* already loaded, no need to reload */ + struct buflib_alloc_data *pd = core_get_data(buflib_allocations[font_id]); + pd->refcount++; + //printf("reusing handle %d for %s (count: %d)\n", font_id, path, pd->refcount); + return font_id; } - else + + for (font_id = FONT_FIRSTUSERFONT; font_id < MAXFONTS; font_id++) { - for (font_id = SYSTEMFONTCOUNT; font_id < MAXFONTS; font_id++) + handle = &buflib_allocations[font_id]; + if (*handle < 0) { - if (sysfonts[font_id] == NULL) - break; + break; } - if (font_id == MAXFONTS) - return -1; /* too many fonts */ } - - if (font_id == FONT_UI) - { - /* currently, font loading replaces earlier font allocation*/ - buffer = (unsigned char *)(((intptr_t)main_buf + 3) & ~3); - /* make sure above doesn't exceed */ - buffer_size = MAX_FONT_SIZE-3; - } - else - { - buffer = pf->buffer_start; - buffer_size = pf->buffer_size; - } - - if (!internal_load_font(pf, path, buffer, buffer_size)) + handle = &buflib_allocations[font_id]; + *handle = alloc_and_init(font_id, path); + if (*handle < 0) return -1; + + if (handle_for_glyphcache < 0) + handle_for_glyphcache = *handle; + + buffer = buffer_from_handle(*handle); + buffer_size = MAX_FONT_SIZE; //FIXME + lock_font_handle(*handle, true); + + if (!internal_load_font(font_id, path, buffer, buffer_size)) + { + lock_font_handle(*handle, false); + core_free(*handle); + *handle = -1; + return -1; + } - sysfonts[font_id] = pf; + lock_font_handle(*handle, false); + //printf("%s -> [%d] -> %d\n", path, font_id, *handle); return font_id; /* success!*/ } void font_unload(int font_id) { - struct font* pf = sysfonts[font_id]; - if (font_id >= SYSTEMFONTCOUNT && pf) + int *handle = &buflib_allocations[font_id]; + struct buflib_alloc_data *pdata = core_get_data(*handle); + struct font* pf = &pdata->font; + pdata->refcount--; + if (pdata->refcount < 1) { - if (pf->fd >= 0) + //printf("freeing id: %d %s\n", font_id, core_get_name(*handle)); + if (pf && pf->fd >= 0) close(pf->fd); - sysfonts[font_id] = NULL; + if (*handle > 0) + core_free(*handle); + if (handle_for_glyphcache == *handle) + handle_for_glyphcache = -1; // should find the next available handle + *handle = -1; } } @@ -478,16 +541,37 @@ void font_unload(int font_id) struct font* font_get(int font) { struct font* pf; + if (font == FONT_UI) + font = MAXFONTS-1; + if (font <= FONT_SYSFIXED) + return &sysfont; while (1) { - pf = sysfonts[font]; + struct buflib_alloc_data *alloc = core_get_data(buflib_allocations[font]); + pf = &alloc->font; if (pf && pf->height) return pf; if (--font < 0) - panicf("No font!"); + return &sysfont; } } +static int pf_to_handle(struct font* pf) +{ + int i; + for (i=0; i 0) + { + struct buflib_alloc_data *pdata = core_get_data(handle); + if (pf == &pdata->font) + return handle; + } + } + return -1; +} + /* * Reads an entry into cache entry */ @@ -495,9 +579,12 @@ static void load_cache_entry(struct font_cache_entry* p, void* callback_data) { struct font* pf = callback_data; + int handle = pf_to_handle(pf); unsigned short char_code = p->_char_code; unsigned char tmp[2]; + if (handle > 0) + lock_font_handle(handle, true); if (pf->file_width_offset) { int width_offset = pf->file_width_offset + char_code; @@ -531,6 +618,9 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data) lseek(pf->fd, file_offset, SEEK_SET); int src_bytes = glyph_bytes(pf, p->width); read(pf->fd, p->bitmap, src_bytes); + + if (handle > 0) + lock_font_handle(handle, false); } /* @@ -572,7 +662,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code) if (pf->fd >= 0 && pf != &sysfont) { bits = - (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->bitmap; + (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry, pf)->bitmap; } else { @@ -594,7 +684,8 @@ static int cache_fd; static void glyph_file_write(void* data) { struct font_cache_entry* p = data; - struct font* pf = &font_ui; + int handle = handle_for_glyphcache; + struct font* pf = pf_from_handle(handle); unsigned short ch; unsigned char tmp[2]; @@ -617,9 +708,9 @@ static void glyph_file_write(void* data) /* save the char codes of the loaded glyphs to a file */ void glyph_cache_save(struct font* pf) { - if (!pf) - pf = &font_ui; - if (pf->fd >= 0 && pf == &font_ui) + if (pf != pf_from_handle(handle_for_glyphcache)) + return; + if (pf->fd >= 0) { cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666); if (cache_fd < 0) @@ -675,9 +766,10 @@ static int ushortcmp(const void *a, const void *b) } static void glyph_cache_load(struct font* pf) { - + if (handle_for_glyphcache <= 0) + return; #define MAX_SORT 256 - if (pf->fd >= 0) { + if (pf->fd >= 0 && pf == pf_from_handle(handle_for_glyphcache)) { int fd; int i, size; unsigned char tmp[2]; diff --git a/firmware/include/core_alloc.h b/firmware/include/core_alloc.h index f5206c9db9..b2edec5377 100644 --- a/firmware/include/core_alloc.h +++ b/firmware/include/core_alloc.h @@ -33,4 +33,11 @@ static inline void* core_get_data(int handle) extern struct buflib_context core_ctx; return buflib_get_data(&core_ctx, handle); } + +static inline const char* core_get_name(int handle) +{ + extern struct buflib_context core_ctx; + return buflib_get_name(&core_ctx, handle); +} + #endif /* __CORE_ALLOC_H__ */