FS#10984 - multifont! 2 major additions:

1) seperate UI font for the remote and main displays
2) allow individual skins to load additional fonts for use in the skin (Uo to 7 extra in this first version) see CustomWPS for info on how to load a font in the skins.

Code should always use FONT_UI+screen_number to get the correct user font


git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24644 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Jonathan Gordon 2010-02-14 06:26:16 +00:00
parent ed21ab1c8c
commit 1c2aa35371
20 changed files with 643 additions and 205 deletions

View file

@ -90,6 +90,9 @@ gui/viewport.c
gui/skin_engine/skin_buffer.c gui/skin_engine/skin_buffer.c
gui/skin_engine/wps_debug.c gui/skin_engine/wps_debug.c
gui/skin_engine/skin_display.c gui/skin_engine/skin_display.c
#ifdef HAVE_LCD_BITMAP
gui/skin_engine/skin_fonts.c
#endif
gui/skin_engine/skin_parser.c gui/skin_engine/skin_parser.c
gui/skin_engine/skin_tokens.c gui/skin_engine/skin_tokens.c

View file

@ -379,6 +379,32 @@ int ft_load(struct tree_context* c, const char* tempdir)
return 0; return 0;
} }
#ifdef HAVE_LCD_BITMAP
static void ft_load_font(char *file)
{
#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);
set_file(file, (char *)global_settings.font_file, MAX_FILENAME);
break;
case 1: /* remote */
splash(0, ID2P(LANG_WAIT));
font_load_remoteui(file);
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
}
#endif
int ft_enter(struct tree_context* c) int ft_enter(struct tree_context* c)
{ {
@ -547,9 +573,7 @@ int ft_enter(struct tree_context* c)
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
case FILE_ATTR_FONT: case FILE_ATTR_FONT:
splash(0, ID2P(LANG_WAIT)); ft_load_font(buf);
font_load(buf);
set_file(buf, (char *)global_settings.font_file, MAX_FILENAME);
break; break;
case FILE_ATTR_KBD: case FILE_ATTR_KBD:

View file

@ -0,0 +1,139 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: skin_tokens.c 24526 2010-02-05 23:58:53Z jdgordon $
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "file.h"
#include "settings.h"
#include "font.h"
#include "skin_buffer.h"
#include "skin_fonts.h"
#define FONT_SIZE 10000
static struct skin_font {
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<MAXUSERFONTS;i++)
{
if (!first_load)
font_unload(font_table[i].font_id);
font_table[i].font_id = -1;
font_table[i].name[0] = '\0';
font_table[i].buffer = NULL;
font_table[i].ref_count = 0;
}
}
/* load a font into the skin buffer. return the font id. */
int skin_font_load(char* font_name)
{
int i;
struct font *pf;
struct skin_font *font = NULL;
char filename[MAX_PATH];
if (!strcmp(font_name, global_settings.font_file))
return FONT_UI;
#ifdef HAVE_REMOTE_LCD
if (!strcmp(font_name, global_settings.remote_font_file))
return FONT_UI_REMOTE;
#endif
for(i=0;i<MAXUSERFONTS;i++)
{
if (font_table[i].font_id >= 0 && !strcmp(font_table[i].name, font_name))
{
font_table[i].ref_count++;
return font_table[i].font_id;
}
else if (!font && font_table[i].font_id == -1)
{
font = &font_table[i];
}
}
if (!font)
return -1; /* too many fonts loaded */
pf = &font->font;
if (!font->buffer)
{
pf->buffer_start = skin_buffer_alloc(FONT_SIZE);
if (!pf->buffer_start)
return -1;
font->buffer = pf->buffer_start;
}
else
{
pf->buffer_start = font->buffer;
}
pf->buffer_size = FONT_SIZE;
snprintf(filename, MAX_PATH, FONT_DIR "/%s.fnt", font_name);
strcpy(font->name, font_name);
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<MAXUSERFONTS;i++)
{
if (font_table[i].font_id == font_id)
{
if (--font_table[i].ref_count == 0)
{
font_unload(font_id);
font_table[i].font_id = -1;
font_table[i].name[0] = '\0';
}
return;
}
}
}

View file

@ -0,0 +1,46 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id: skin_tokens.c 24526 2010-02-05 23:58:53Z jdgordon $
*
* 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 <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "file.h"
#include "settings.h"
#include "font.h"
#include "skin_buffer.h"
#ifndef _SKINFONTS_H_
#define _SKINFONTS_H_
#define MAXUSERFONTS (MAXFONTS - SYSTEMFONTCOUNT)
void skin_font_init(void);
/* load a font into the skin buffer. return the font id. */
int skin_font_load(char* font_name);
/* 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

View file

@ -52,6 +52,7 @@
#include "skin_engine.h" #include "skin_engine.h"
#include "settings.h" #include "settings.h"
#include "settings_list.h" #include "settings_list.h"
#include "skin_fonts.h"
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
#include "bmp.h" #include "bmp.h"
@ -157,6 +158,8 @@ static int parse_image_display(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data); struct wps_token *token, struct wps_data *wps_data);
static int parse_image_load(const char *wps_bufptr, static int parse_image_load(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data); struct wps_token *token, struct wps_data *wps_data);
static int parse_font_load(const char *wps_bufptr,
struct wps_token *token, struct wps_data *wps_data);
#endif /*HAVE_LCD_BITMAP */ #endif /*HAVE_LCD_BITMAP */
#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1)) #if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1))
static int parse_image_special(const char *wps_bufptr, static int parse_image_special(const char *wps_bufptr,
@ -353,6 +356,7 @@ static const struct wps_tag all_tags[] = {
parse_image_display }, parse_image_display },
{ WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load }, { WPS_TOKEN_IMAGE_DISPLAY, "x", 0, parse_image_load },
{ WPS_NO_TOKEN, "Fl", 0, parse_font_load },
#ifdef HAVE_ALBUMART #ifdef HAVE_ALBUMART
{ WPS_NO_TOKEN, "Cl", 0, parse_albumart_load }, { WPS_NO_TOKEN, "Cl", 0, parse_albumart_load },
{ WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_STATIC, parse_albumart_display }, { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_STATIC, parse_albumart_display },
@ -688,6 +692,39 @@ static int parse_image_load(const char *wps_bufptr,
return skip_end_of_line(wps_bufptr); return skip_end_of_line(wps_bufptr);
} }
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];
if (*ptr != '|')
return WPS_ERROR_INVALID_PARAM;
ptr++;
if (!(ptr = parse_list("ds", NULL, '|', ptr, &id, &filename)))
return WPS_ERROR_INVALID_PARAM;
/* Check there is a terminating | */
if (*ptr != '|')
return WPS_ERROR_INVALID_PARAM;
if (id <= FONT_UI || id >= MAXFONTS-1)
return WPS_ERROR_INVALID_PARAM;
id -= SYSTEMFONTCOUNT;
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;
}
static int parse_viewport_display(const char *wps_bufptr, static int parse_viewport_display(const char *wps_bufptr,
struct wps_token *token, struct wps_token *token,
struct wps_data *wps_data) struct wps_data *wps_data)
@ -890,7 +927,8 @@ static int parse_viewport(const char *wps_bufptr,
else else
vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */ vp->flags &= ~VP_FLAG_ALIGN_RIGHT; /* ignore right-to-left languages */
if (vp->font >= SYSTEMFONTCOUNT)
vp->font = font_ids[vp->font - SYSTEMFONTCOUNT];
struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp); struct skin_token_list *list = new_skin_token_list_item(NULL, skin_vp);
if (!list) if (!list)

View file

@ -32,6 +32,7 @@
#include "statusbar.h" #include "statusbar.h"
#include "statusbar-skinned.h" #include "statusbar-skinned.h"
#include "debug.h" #include "debug.h"
#include "font.h"
/* currently only one wps_state is needed */ /* currently only one wps_state is needed */
@ -183,7 +184,8 @@ void sb_create_from_settings(enum screen_type screen)
default: default:
height = screens[screen].lcdheight; height = screens[screen].lcdheight;
} }
len = snprintf(ptr, remaining, "%%ax%%Vi|0|%d|-|%d|1|-|-|\n", y, height); len = snprintf(ptr, remaining, "%%ax%%Vi|0|%d|-|%d|%d|-|-|\n",
y, height, FONT_UI + screen);
} }
sb_skin_data_load(screen, buf, false); sb_skin_data_load(screen, buf, false);
} }

View file

@ -315,7 +315,7 @@ void viewport_set_fullscreen(struct viewport *vp,
#ifndef __PCTOOL__ #ifndef __PCTOOL__
set_default_align_flags(vp); set_default_align_flags(vp);
#endif #endif
vp->font = FONT_UI; /* default to UI to discourage SYSFONT use */ vp->font = FONT_UI + screen; /* default to UI to discourage SYSFONT use */
vp->drawmode = DRMODE_SOLID; vp->drawmode = DRMODE_SOLID;
#if LCD_DEPTH > 1 #if LCD_DEPTH > 1
#ifdef HAVE_REMOTE_LCD #ifdef HAVE_REMOTE_LCD
@ -453,11 +453,15 @@ const char* viewport_parse_viewport(struct viewport *vp,
return NULL; return NULL;
} }
/* Default to using the user font if the font was an invalid number or '-'*/ /* Default to using the user font if the font was an invalid number or '-'
if (((vp->font != FONT_SYSFIXED) && (vp->font != FONT_UI)) * font 1 is *always* the UI font for the current screen
|| !LIST_VALUE_PARSED(set, PL_FONT) * 2 is always the first extra font */
) if (!LIST_VALUE_PARSED(set, PL_FONT))
vp->font = FONT_UI; vp->font = FONT_UI + screen;
#ifdef HAVE_REMOTE_LCD
else if (vp->font == FONT_UI && screen == SCREEN_REMOTE)
vp->font = FONT_UI_REMOTE;
#endif
/* Set the defaults for fields not user-specified */ /* Set the defaults for fields not user-specified */
vp->drawmode = DRMODE_SOLID; vp->drawmode = DRMODE_SOLID;

View file

@ -13315,3 +13315,37 @@
lcd_bitmap: "Remote Base Skin" lcd_bitmap: "Remote Base Skin"
</voice> </voice>
</phrase> </phrase>
<phrase>
id: LANG_MAIN_SCREEN
desc: in the main menu
user: core
<source>
*:none
remote: "Main Screen"
</source>
<dest>
*:none
remote: "Main Screen"
</dest>
<voice>
*:none
remote: "Main Screen"
</voice>
</phrase>
<phrase>
id: LANG_REMOTE_SCREEN
desc: in the main menu
user: core
<source>
*:none
remote: "Remote Screen"
</source>
<dest>
*:none
remote: "Remote Screen"
</dest>
<voice>
*:none
remote: "Remote Screen"
</voice>
</phrase>

View file

@ -247,6 +247,10 @@ static const struct plugin_api rockbox_api = {
lcd_remote_bitmap, lcd_remote_bitmap,
#endif #endif
viewport_set_defaults, viewport_set_defaults,
#ifdef HAVE_LCD_BITMAP
viewportmanager_theme_enable,
viewportmanager_theme_undo,
#endif
/* list */ /* list */
gui_synclist_init, gui_synclist_init,
@ -292,6 +296,7 @@ static const struct plugin_api rockbox_api = {
#endif /* HAVE_BUTTON_LIGHT */ #endif /* HAVE_BUTTON_LIGHT */
/* file */ /* file */
open_utf8,
#ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE #ifdef HAVE_PLUGIN_CHECK_OPEN_CLOSE
(open_func)open_wrapper, (open_func)open_wrapper,
close_wrapper, close_wrapper,
@ -325,6 +330,7 @@ static const struct plugin_api rockbox_api = {
create_numbered_filename, create_numbered_filename,
file_exists, file_exists,
strip_extension, strip_extension,
crc_32,
/* dir */ /* dir */
opendir, opendir,
@ -432,6 +438,7 @@ static const struct plugin_api rockbox_api = {
atoi, atoi,
strchr, strchr,
strcat, strcat,
strlcat,
memchr, memchr,
memcmp, memcmp,
strcasestr, strcasestr,
@ -476,6 +483,7 @@ static const struct plugin_api rockbox_api = {
pcm_get_peak_buffer, pcm_get_peak_buffer,
pcm_play_lock, pcm_play_lock,
pcm_play_unlock, pcm_play_unlock,
pcmbuf_beep,
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
&rec_freq_sampr[0], &rec_freq_sampr[0],
pcm_init_recording, pcm_init_recording,
@ -588,6 +596,9 @@ static const struct plugin_api rockbox_api = {
#endif #endif
/* misc */ /* misc */
#if !defined(SIMULATOR) || defined(__MINGW32__) || defined(__CYGWIN__)
&errno,
#endif
srand, srand,
rand, rand,
(qsort_func)qsort, (qsort_func)qsort,
@ -698,19 +709,6 @@ static const struct plugin_api rockbox_api = {
appsversion, appsversion,
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ the API gets incompatible */
#if (CONFIG_CODEC == SWCODEC)
pcmbuf_beep,
#endif
crc_32,
open_utf8,
#ifdef HAVE_LCD_BITMAP
viewportmanager_theme_enable,
viewportmanager_theme_undo,
#endif
#if !defined(SIMULATOR) || defined(__MINGW32__) || defined(__CYGWIN__)
&errno,
#endif
strlcat,
}; };
int plugin_load(const char* plugin, const void* parameter) int plugin_load(const char* plugin, const void* parameter)

View file

@ -135,12 +135,12 @@ void* plugin_get_buffer(size_t *buffer_size);
#define PLUGIN_MAGIC 0x526F634B /* RocK */ #define PLUGIN_MAGIC 0x526F634B /* RocK */
/* increase this every time the api struct changes */ /* increase this every time the api struct changes */
#define PLUGIN_API_VERSION 180 #define PLUGIN_API_VERSION 181
/* update this to latest version if a change to the api struct breaks /* update this to latest version if a change to the api struct breaks
backwards compatibility (and please take the opportunity to sort in any backwards compatibility (and please take the opportunity to sort in any
new function which are "waiting" at the end of the function table) */ new function which are "waiting" at the end of the function table) */
#define PLUGIN_MIN_API_VERSION 180 #define PLUGIN_MIN_API_VERSION 181
/* plugin return codes */ /* plugin return codes */
enum plugin_status { enum plugin_status {
@ -250,7 +250,7 @@ struct plugin_api {
#endif #endif
unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation ); unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation );
const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code ); const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code );
struct font* (*font_load)(const char *path); int (*font_load)(struct font*, const char *path);
struct font* (*font_get)(int font); struct font* (*font_get)(int font);
int (*font_getstringsize)(const unsigned char *str, int *w, int *h, int (*font_getstringsize)(const unsigned char *str, int *w, int *h,
int fontnumber); int fontnumber);
@ -336,7 +336,12 @@ struct plugin_api {
int width, int height); int width, int height);
#endif #endif
void (*viewport_set_defaults)(struct viewport *vp, void (*viewport_set_defaults)(struct viewport *vp,
const enum screen_type screen); const enum screen_type screen);
#ifdef HAVE_LCD_BITMAP
void (*viewportmanager_theme_enable)(enum screen_type screen, bool enable,
struct viewport *viewport);
void (*viewportmanager_theme_undo)(enum screen_type screen, bool force_redraw);
#endif
/* list */ /* list */
void (*gui_synclist_init)(struct gui_synclist * lists, void (*gui_synclist_init)(struct gui_synclist * lists,
list_get_name callback_get_item_name, void * data, list_get_name callback_get_item_name, void * data,
@ -390,6 +395,7 @@ struct plugin_api {
#endif /* HAVE_BUTTON_LIGHT */ #endif /* HAVE_BUTTON_LIGHT */
/* file */ /* file */
int (*open_utf8)(const char* pathname, int flags);
int (*open)(const char* pathname, int flags); int (*open)(const char* pathname, int flags);
int (*close)(int fd); int (*close)(int fd);
ssize_t (*read)(int fd, void* buf, size_t count); ssize_t (*read)(int fd, void* buf, size_t count);
@ -416,6 +422,7 @@ struct plugin_api {
int numberlen IF_CNFN_NUM_(, int *num)); int numberlen IF_CNFN_NUM_(, int *num));
bool (*file_exists)(const char *file); bool (*file_exists)(const char *file);
char* (*strip_extension)(char* buffer, int buffer_size, const char *filename); char* (*strip_extension)(char* buffer, int buffer_size, const char *filename);
unsigned (*crc_32)(const void *src, unsigned len, unsigned crc32);
/* dir */ /* dir */
@ -537,6 +544,7 @@ struct plugin_api {
int (*atoi)(const char *str); int (*atoi)(const char *str);
char *(*strchr)(const char *s, int c); char *(*strchr)(const char *s, int c);
char *(*strcat)(char *s1, const char *s2); char *(*strcat)(char *s1, const char *s2);
size_t (*strlcat)(char *dst, const char *src, size_t length);
void *(*memchr)(const void *s1, int c, size_t n); void *(*memchr)(const void *s1, int c, size_t n);
int (*memcmp)(const void *s1, const void *s2, size_t n); int (*memcmp)(const void *s1, const void *s2, size_t n);
char *(*strcasestr) (const char* phaystack, const char* pneedle); char *(*strcasestr) (const char* phaystack, const char* pneedle);
@ -583,6 +591,9 @@ struct plugin_api {
const void* (*pcm_get_peak_buffer)(int *count); const void* (*pcm_get_peak_buffer)(int *count);
void (*pcm_play_lock)(void); void (*pcm_play_lock)(void);
void (*pcm_play_unlock)(void); void (*pcm_play_unlock)(void);
void (*pcmbuf_beep)(unsigned int frequency,
size_t duration,
int amplitude);
#ifdef HAVE_RECORDING #ifdef HAVE_RECORDING
const unsigned long *rec_freq_sampr; const unsigned long *rec_freq_sampr;
void (*pcm_init_recording)(void); void (*pcm_init_recording)(void);
@ -716,6 +727,9 @@ struct plugin_api {
#endif #endif
/* misc */ /* misc */
#if !defined(SIMULATOR) || defined(__MINGW32__) || defined(__CYGWIN__)
int* __errno;
#endif
void (*srand)(unsigned int seed); void (*srand)(unsigned int seed);
int (*rand)(void); int (*rand)(void);
void (*qsort)(void *base, size_t nmemb, size_t size, void (*qsort)(void *base, size_t nmemb, size_t size,
@ -848,23 +862,6 @@ struct plugin_api {
const char *appsversion; const char *appsversion;
/* new stuff at the end, sort into place next time /* new stuff at the end, sort into place next time
the API gets incompatible */ the API gets incompatible */
#if (CONFIG_CODEC == SWCODEC)
void (*pcmbuf_beep)(unsigned int frequency,
size_t duration,
int amplitude);
#endif
unsigned (*crc_32)(const void *src, unsigned len, unsigned crc32);
int (*open_utf8)(const char* pathname, int flags);
#ifdef HAVE_LCD_BITMAP
void (*viewportmanager_theme_enable)(enum screen_type screen, bool enable,
struct viewport *viewport);
void (*viewportmanager_theme_undo)(enum screen_type screen, bool force_redraw);
#endif
#if !defined(SIMULATOR) || defined(__MINGW32__) || defined(__CYGWIN__)
int* __errno;
#endif
size_t (*strlcat)(char *dst, const char *src, size_t length);
}; };
/* plugin header */ /* plugin header */

View file

@ -854,7 +854,7 @@ static bool browse_fonts( char *dst, int dst_size )
continue; continue;
rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s",
de->d_name ); de->d_name );
rb->font_load( bbuf ); rb->font_load(NULL, bbuf );
rb->font_getstringsize( de->d_name, &fw, &fh, FONT_UI ); rb->font_getstringsize( de->d_name, &fw, &fh, FONT_UI );
if( nvih > 0 ) if( nvih > 0 )
{ {
@ -887,12 +887,12 @@ static bool browse_fonts( char *dst, int dst_size )
{ {
rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s",
de->d_name ); de->d_name );
rb->font_load( bbuf ); rb->font_load(NULL, bbuf );
rb->font_getstringsize( de->d_name, NULL, &fh, FONT_UI ); rb->font_getstringsize( de->d_name, NULL, &fh, FONT_UI );
nvih = fh; nvih = fh;
} }
} }
rb->font_load( buffer.text.old_font ); rb->font_load(NULL, buffer.text.old_font );
rb->closedir( d ); rb->closedir( d );
} }
@ -1526,7 +1526,7 @@ static void draw_text( int x, int y )
case TEXT_MENU_FONT: case TEXT_MENU_FONT:
if( browse_fonts( buffer.text.font, MAX_PATH ) ) if( browse_fonts( buffer.text.font, MAX_PATH ) )
{ {
rb->font_load( buffer.text.font ); rb->font_load(NULL, buffer.text.font );
} }
break; break;
@ -1583,7 +1583,7 @@ static void draw_text( int x, int y )
case TEXT_MENU_CANCEL: case TEXT_MENU_CANCEL:
default: default:
restore_screen(); restore_screen();
rb->font_load( buffer.text.old_font ); rb->font_load(NULL, buffer.text.old_font );
return; return;
} }
} }

View file

@ -68,6 +68,7 @@
#endif #endif
#include "wps.h" #include "wps.h"
#include "skin_engine/skin_engine.h" #include "skin_engine/skin_engine.h"
#include "skin_engine/skin_fonts.h"
#include "viewport.h" #include "viewport.h"
#include "statusbar-skinned.h" #include "statusbar-skinned.h"
@ -740,6 +741,7 @@ void settings_apply_skins(void)
/* re-initialize the skin buffer before we start reloading skins */ /* re-initialize the skin buffer before we start reloading skins */
skin_buffer_init(); skin_buffer_init();
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
skin_font_init();
if ( global_settings.sbs_file[0] && if ( global_settings.sbs_file[0] &&
global_settings.sbs_file[0] != 0xff ) global_settings.sbs_file[0] != 0xff )
{ {
@ -887,18 +889,26 @@ void settings_apply(bool read_disk)
if (read_disk) if (read_disk)
{ {
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
/* fonts need to be loaded before the WPS */ /* fonts need to be loaded before the WPS */
if ( global_settings.font_file[0]) { if ( global_settings.font_file[0]) {
snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
global_settings.font_file); global_settings.font_file);
if (font_load(buf) == NULL) if (font_load(NULL, buf) < 0)
font_reset(); font_reset(NULL);
} }
else else
font_reset(); font_reset(NULL);
#ifdef HAVE_REMOTE_LCD
if ( global_settings.remote_font_file[0]) {
snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt",
global_settings.remote_font_file);
if (font_load_remoteui(buf) < 0)
font_load_remoteui(NULL);
}
else
font_load_remoteui(NULL);
#endif
if ( global_settings.kbd_file[0]) { if ( global_settings.kbd_file[0]) {
snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd", snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd",
global_settings.kbd_file); global_settings.kbd_file);

View file

@ -681,6 +681,9 @@ struct user_settings
unsigned char icon_file[MAX_FILENAME+1]; unsigned char icon_file[MAX_FILENAME+1];
unsigned char viewers_icon_file[MAX_FILENAME+1]; unsigned char viewers_icon_file[MAX_FILENAME+1];
unsigned char font_file[MAX_FILENAME+1]; /* last font */ unsigned char font_file[MAX_FILENAME+1]; /* last font */
#ifdef HAVE_REMOTE_LCD
unsigned char remote_font_file[MAX_FILENAME+1]; /* last font */
#endif
unsigned char kbd_file[MAX_FILENAME+1]; /* last keyboard */ unsigned char kbd_file[MAX_FILENAME+1]; /* last keyboard */
#endif /* HAVE_LCD_BITMAP */ #endif /* HAVE_LCD_BITMAP */

View file

@ -1431,6 +1431,10 @@ const struct settings_list settings[] = {
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
TEXT_SETTING(F_THEMESETTING, font_file, "font", TEXT_SETTING(F_THEMESETTING, font_file, "font",
DEFAULT_FONTNAME, FONT_DIR "/", ".fnt"), DEFAULT_FONTNAME, FONT_DIR "/", ".fnt"),
#endif
#ifdef HAVE_REMOTE_LCD
TEXT_SETTING(F_THEMESETTING, remote_font_file, "remote font",
"", FONT_DIR "/", ".fnt"),
#endif #endif
TEXT_SETTING(F_THEMESETTING,wps_file, "wps", TEXT_SETTING(F_THEMESETTING,wps_file, "wps",
DEFAULT_WPSNAME, WPS_DIR "/", ".wps"), DEFAULT_WPSNAME, WPS_DIR "/", ".wps"),

View file

@ -30,6 +30,7 @@
#if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR) #if defined(HAVE_LCD_BITMAP) || defined(SIMULATOR)
#ifndef __PCTOOL__ #ifndef __PCTOOL__
#include "font_cache.h"
#include "sysfont.h" #include "sysfont.h"
#endif #endif
@ -47,9 +48,14 @@
enum { enum {
FONT_SYSFIXED, /* system fixed pitch font*/ FONT_SYSFIXED, /* system fixed pitch font*/
FONT_UI, /* system porportional font*/ FONT_UI, /* system porportional font*/
MAXFONTS #ifdef HAVE_REMOTE_LCD
FONT_UI_REMOTE, /* UI font for remote LCD */
#endif
SYSTEMFONTCOUNT /* Number of fonts reserved for the system and ui */
}; };
#define MAXFONTS 10
/* /*
* .fnt loadable font file format definition * .fnt loadable font file format definition
* *
@ -89,17 +95,38 @@ struct font {
const unsigned char *width; /* character widths or NULL if fixed*/ const unsigned char *width; /* character widths or NULL if fixed*/
int defaultchar; /* default char (not glyph index)*/ int defaultchar; /* default char (not glyph index)*/
int32_t bits_size; /* # bytes of glyph bits*/ int32_t bits_size; /* # bytes of glyph bits*/
/* file, buffer and cache management */
int fd; /* fd for the font file. >= 0 if cached */
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 */
#ifndef __PCTOOL__
struct font_cache cache;
uint32_t file_width_offset; /* offset to file width data */
uint32_t file_offset_offset; /* offset to file offset data */
int long_offset;
#endif
}; };
/* font routines*/ /* font routines*/
void font_init(void); void font_init(void);
struct font* font_load(const char *path); #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);
void font_unload(int font_id);
struct font* font_get(int font); struct font* font_get(int font);
void font_reset(void);
void font_reset(struct font *pf);
int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber); int font_getstringsize(const unsigned char *str, int *w, int *h, int fontnumber);
int font_get_width(struct font* ft, unsigned short ch); int font_get_width(struct font* ft, unsigned short ch);
const unsigned char * font_get_bits(struct font* ft, unsigned short ch); const unsigned char * font_get_bits(struct font* ft, unsigned short ch);
void glyph_cache_save(void); void glyph_cache_save(struct font* pf);
#else /* HAVE_LCD_BITMAP */ #else /* HAVE_LCD_BITMAP */

View file

@ -75,64 +75,77 @@ extern struct font sysfont;
/* structure filled in by font_load */ /* structure filled in by font_load */
static struct font font_ui; static struct font font_ui;
/* static buffer allocation structures */
static unsigned char main_buf[MAX_FONT_SIZE];
#ifdef HAVE_REMOTE_LCD
#define REMOTE_FONT_SIZE 10000
static struct font remote_font_ui;
static unsigned char remote_buf[REMOTE_FONT_SIZE];
#endif
/* system font table, in order of FONT_xxx definition */ /* system font table, in order of FONT_xxx definition */
static struct font* const sysfonts[MAXFONTS] = { &sysfont, &font_ui }; static struct font* sysfonts[MAXFONTS] = { &sysfont, &font_ui, NULL};
/* static buffer allocation structures */
static unsigned char mbuf[MAX_FONT_SIZE];
static unsigned char *freeptr = mbuf;
static unsigned char *fileptr;
static unsigned char *eofptr;
/* Font cache structures */ /* Font cache structures */
static struct font_cache font_cache_ui; static void cache_create(struct font* pf, int maxwidth, int height);
static int fnt_file = -1; /* >=0 if font is cached */ static void glyph_cache_load(struct font* pf);
static uint32_t file_width_offset; /* offset to file width data */
static uint32_t file_offset_offset; /* offset to file offset data */
static void cache_create(int maxwidth, int height);
static int long_offset = 0;
static int glyph_file;
/* End Font cache structures */ /* End Font cache structures */
static void glyph_cache_load(void);
void font_init(void) void font_init(void)
{ {
memset(&font_ui, 0, sizeof(struct font)); int i = SYSTEMFONTCOUNT;
while (i<MAXFONTS)
sysfonts[i++] = NULL;
font_reset(NULL);
} }
/* Check if we have x bytes left in the file buffer */ /* Check if we have x bytes left in the file buffer */
#define HAVEBYTES(x) (fileptr + (x) <= eofptr) #define HAVEBYTES(x) (pf->buffer_position + (x) <= pf->buffer_end)
/* Helper functions to read big-endian unaligned short or long from /* Helper functions to read big-endian unaligned short or long from
the file buffer. Bounds-checking must be done in the calling the file buffer. Bounds-checking must be done in the calling
function. function.
*/ */
static short readshort(void) static short readshort(struct font *pf)
{ {
unsigned short s; unsigned short s;
s = *fileptr++ & 0xff; s = *pf->buffer_position++ & 0xff;
s |= (*fileptr++ << 8); s |= (*pf->buffer_position++ << 8);
return s; return s;
} }
static int32_t readlong(void) static int32_t readlong(struct font *pf)
{ {
uint32_t l; uint32_t l;
l = *fileptr++ & 0xff; l = *pf->buffer_position++ & 0xff;
l |= *fileptr++ << 8; l |= *pf->buffer_position++ << 8;
l |= ((uint32_t)(*fileptr++)) << 16; l |= ((uint32_t)(*pf->buffer_position++)) << 16;
l |= ((uint32_t)(*fileptr++)) << 24; l |= ((uint32_t)(*pf->buffer_position++)) << 24;
return l; return l;
} }
void font_reset(void) void font_reset(struct font *pf)
{ {
memset(&font_ui, 0, sizeof(struct font)); 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) static struct font* font_load_header(struct font *pf)
@ -142,23 +155,23 @@ static struct font* font_load_header(struct font *pf)
return NULL; return NULL;
/* read magic and version #*/ /* read magic and version #*/
if (memcmp(fileptr, VERSION, 4) != 0) if (memcmp(pf->buffer_position, VERSION, 4) != 0)
return NULL; return NULL;
fileptr += 4; pf->buffer_position += 4;
/* font info*/ /* font info*/
pf->maxwidth = readshort(); pf->maxwidth = readshort(pf);
pf->height = readshort(); pf->height = readshort(pf);
pf->ascent = readshort(); pf->ascent = readshort(pf);
fileptr += 2; /* Skip padding */ pf->buffer_position += 2; /* Skip padding */
pf->firstchar = readlong(); pf->firstchar = readlong(pf);
pf->defaultchar = readlong(); pf->defaultchar = readlong(pf);
pf->size = readlong(); pf->size = readlong(pf);
/* get variable font data sizes*/ /* get variable font data sizes*/
/* # words of bitmap_t*/ /* # words of bitmap_t*/
pf->bits_size = readlong(); pf->bits_size = readlong(pf);
return pf; return pf;
} }
@ -171,32 +184,32 @@ static struct font* font_load_in_memory(struct font* pf)
return NULL; return NULL;
/* # longs of offset*/ /* # longs of offset*/
noffset = readlong(); noffset = readlong(pf);
/* # bytes of width*/ /* # bytes of width*/
nwidth = readlong(); nwidth = readlong(pf);
/* variable font data*/ /* variable font data*/
pf->bits = (unsigned char *)fileptr; pf->bits = (unsigned char *)pf->buffer_position;
fileptr += pf->bits_size*sizeof(unsigned char); pf->buffer_position += pf->bits_size*sizeof(unsigned char);
if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
{ {
/* pad to 16-bit boundary */ /* pad to 16-bit boundary */
fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1);
} }
else else
{ {
/* pad to 32-bit boundary*/ /* pad to 32-bit boundary*/
fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3);
} }
if (noffset) if (noffset)
{ {
if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
{ {
long_offset = 0; pf->long_offset = 0;
pf->offset = (uint16_t*)fileptr; pf->offset = (uint16_t*)pf->buffer_position;
/* Check we have sufficient buffer */ /* Check we have sufficient buffer */
if (!HAVEBYTES(noffset * sizeof(uint16_t))) if (!HAVEBYTES(noffset * sizeof(uint16_t)))
@ -204,13 +217,13 @@ static struct font* font_load_in_memory(struct font* pf)
for (i=0; i<noffset; ++i) for (i=0; i<noffset; ++i)
{ {
((uint16_t*)(pf->offset))[i] = (uint16_t)readshort(); ((uint16_t*)(pf->offset))[i] = (uint16_t)readshort(pf);
} }
} }
else else
{ {
long_offset = 1; pf->long_offset = 1;
pf->offset = (uint16_t*)fileptr; pf->offset = (uint16_t*)pf->buffer_position;
/* Check we have sufficient buffer */ /* Check we have sufficient buffer */
if (!HAVEBYTES(noffset * sizeof(int32_t))) if (!HAVEBYTES(noffset * sizeof(int32_t)))
@ -218,7 +231,7 @@ static struct font* font_load_in_memory(struct font* pf)
for (i=0; i<noffset; ++i) for (i=0; i<noffset; ++i)
{ {
((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(); ((uint32_t*)(pf->offset))[i] = (uint32_t)readlong(pf);
} }
} }
} }
@ -226,13 +239,13 @@ static struct font* font_load_in_memory(struct font* pf)
pf->offset = NULL; pf->offset = NULL;
if (nwidth) { if (nwidth) {
pf->width = (unsigned char *)fileptr; pf->width = (unsigned char *)pf->buffer_position;
fileptr += nwidth*sizeof(unsigned char); pf->buffer_position += nwidth*sizeof(unsigned char);
} }
else else
pf->width = NULL; pf->width = NULL;
if (fileptr > eofptr) if (pf->buffer_position > pf->buffer_end)
return NULL; return NULL;
return pf; /* success!*/ return pf; /* success!*/
@ -242,135 +255,203 @@ static struct font* font_load_in_memory(struct font* pf)
static struct font* font_load_cached(struct font* pf) static struct font* font_load_cached(struct font* pf)
{ {
uint32_t noffset, nwidth; uint32_t noffset, nwidth;
unsigned char* oldfileptr = fileptr; unsigned char* oldfileptr = pf->buffer_position;
if (!HAVEBYTES(2 * sizeof(int32_t))) if (!HAVEBYTES(2 * sizeof(int32_t)))
return NULL; return NULL;
/* # longs of offset*/ /* # longs of offset*/
noffset = readlong(); noffset = readlong(pf);
/* # bytes of width*/ /* # bytes of width*/
nwidth = readlong(); nwidth = readlong(pf);
/* We are now at the bitmap data, this is fixed at 36.. */ /* We are now at the bitmap data, this is fixed at 36.. */
pf->bits = NULL; pf->bits = NULL;
/* Calculate offset to offset data */ /* Calculate offset to offset data */
fileptr += pf->bits_size * sizeof(unsigned char); pf->buffer_position += pf->bits_size * sizeof(unsigned char);
if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
{ {
long_offset = 0; pf->long_offset = 0;
/* pad to 16-bit boundary */ /* pad to 16-bit boundary */
fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 1) & ~1);
} }
else else
{ {
long_offset = 1; pf->long_offset = 1;
/* pad to 32-bit boundary*/ /* pad to 32-bit boundary*/
fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); pf->buffer_position = (unsigned char *)(((intptr_t)pf->buffer_position + 3) & ~3);
} }
if (noffset) if (noffset)
file_offset_offset = (uint32_t)(fileptr - freeptr); pf->file_offset_offset = (uint32_t)(pf->buffer_position - pf->buffer_start);
else else
file_offset_offset = 0; pf->file_offset_offset = 0;
/* Calculate offset to widths data */ /* Calculate offset to widths data */
if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS) if (pf->bits_size < MAX_FONTSIZE_FOR_16_BIT_OFFSETS)
fileptr += noffset * sizeof(uint16_t); pf->buffer_position += noffset * sizeof(uint16_t);
else else
fileptr += noffset * sizeof(uint32_t); pf->buffer_position += noffset * sizeof(uint32_t);
if (nwidth) if (nwidth)
file_width_offset = (uint32_t)(fileptr - freeptr); pf->file_width_offset = (uint32_t)(pf->buffer_position - pf->buffer_start);
else else
file_width_offset = 0; pf->file_width_offset = 0;
fileptr = oldfileptr; pf->buffer_position = oldfileptr;
/* Create the cache */ /* Create the cache */
cache_create(pf->maxwidth, pf->height); cache_create(pf, pf->maxwidth, pf->height);
return pf; return pf;
} }
/* read and load font into incore font structure*/ static bool internal_load_font(struct font* pf, const char *path,
struct font* font_load(const char *path) char *buf, size_t buf_size)
{ {
int size; int size;
struct font* pf = &font_ui;
/* save loaded glyphs */ /* save loaded glyphs */
glyph_cache_save(); glyph_cache_save(pf);
/* Close font file handle */ /* Close font file handle */
if (fnt_file >= 0) if (pf->fd >= 0)
close(fnt_file); close(pf->fd);
font_reset(pf);
/* open and read entire font file*/ /* open and read entire font file*/
fnt_file = open(path, O_RDONLY|O_BINARY); pf->fd = open(path, O_RDONLY|O_BINARY);
if (fnt_file < 0) { if (pf->fd < 0) {
DEBUGF("Can't open font: %s\n", path); DEBUGF("Can't open font: %s\n", path);
return NULL; return false;
} }
/* Check file size */ /* Check file size */
size = filesize(fnt_file); size = filesize(pf->fd);
pf->buffer_start = buf;
font_reset(); pf->buffer_size = buf_size;
/* currently, font loading replaces earlier font allocation*/ pf->buffer_position = buf;
freeptr = (unsigned char *)(((intptr_t)mbuf + 3) & ~3);
fileptr = freeptr; if (size > pf->buffer_size)
if (size > MAX_FONT_SIZE)
{ {
read(fnt_file, fileptr, FONT_HEADER_SIZE); read(pf->fd, pf->buffer_position, FONT_HEADER_SIZE);
eofptr = fileptr + FONT_HEADER_SIZE; pf->buffer_end = pf->buffer_position + FONT_HEADER_SIZE;
if (!font_load_header(pf)) if (!font_load_header(pf))
{ {
DEBUGF("Failed font header load"); DEBUGF("Failed font header load");
return NULL; return false;
} }
if (!font_load_cached(pf)) if (!font_load_cached(pf))
{ {
DEBUGF("Failed font cache load"); DEBUGF("Failed font cache load");
return NULL; return false;
} }
glyph_cache_load(); glyph_cache_load(pf);
} }
else else
{ {
read(fnt_file, fileptr, MAX_FONT_SIZE); read(pf->fd, pf->buffer_position, pf->buffer_size);
eofptr = fileptr + size; pf->buffer_end = pf->buffer_position + size;
close(fnt_file); close(pf->fd);
fnt_file = -1; pf->fd = -1;
if (!font_load_header(pf)) if (!font_load_header(pf))
{ {
DEBUGF("Failed font header load"); DEBUGF("Failed font header load");
return NULL; return false;
} }
if (!font_load_in_memory(pf)) if (!font_load_in_memory(pf))
{ {
DEBUGF("Failed mem load"); DEBUGF("Failed mem load");
return NULL; return false;
} }
} }
return true;
}
#ifdef HAVE_REMOTE_LCD
/* Load a font into the special remote ui font slot */
int font_load_remoteui(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
/* no need for multiple font loads currently*/ /* read and load font into incore font structure,
/*freeptr += filesize;*/ * returns the font number on success, -1 on failure */
/*freeptr = (unsigned char *)(freeptr + 3) & ~3;*/ /* pad freeptr*/ int font_load(struct font* pf, const char *path)
{
int font_id = -1;
char *buffer;
size_t buffer_size;
if (pf == NULL)
{
pf = &font_ui;
font_id = FONT_UI;
}
else
{
for (font_id = SYSTEMFONTCOUNT; font_id < MAXFONTS; font_id++)
{
if (sysfonts[font_id] == NULL)
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);
buffer_size = MAX_FONT_SIZE;
}
else
{
buffer = pf->buffer_start;
buffer_size = pf->buffer_size;
}
if (!internal_load_font(pf, path, buffer, buffer_size))
return -1;
sysfonts[font_id] = pf;
return font_id; /* success!*/
}
return pf; /* success!*/ void font_unload(int font_id)
{
struct font* pf = sysfonts[font_id];
if (font_id >= SYSTEMFONTCOUNT && pf)
{
if (pf->fd >= 0)
close(pf->fd);
sysfonts[font_id] = NULL;
}
} }
/* /*
@ -382,9 +463,6 @@ struct font* font_get(int font)
{ {
struct font* pf; struct font* pf;
if (font >= MAXFONTS)
font = 0;
while (1) { while (1) {
pf = sysfonts[font]; pf = sysfonts[font];
if (pf && pf->height) if (pf && pf->height)
@ -404,11 +482,11 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data)
unsigned short char_code = p->_char_code; unsigned short char_code = p->_char_code;
unsigned char tmp[2]; unsigned char tmp[2];
if (file_width_offset) if (pf->file_width_offset)
{ {
int width_offset = file_width_offset + char_code; int width_offset = pf->file_width_offset + char_code;
lseek(fnt_file, width_offset, SEEK_SET); lseek(pf->fd, width_offset, SEEK_SET);
read(fnt_file, &(p->width), 1); read(pf->fd, &(p->width), 1);
} }
else else
{ {
@ -417,14 +495,14 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data)
int32_t bitmap_offset = 0; int32_t bitmap_offset = 0;
if (file_offset_offset) if (pf->file_offset_offset)
{ {
int32_t offset = file_offset_offset + char_code * (long_offset ? sizeof(int32_t) : sizeof(int16_t)); int32_t offset = pf->file_offset_offset + char_code * (pf->long_offset ? sizeof(int32_t) : sizeof(int16_t));
lseek(fnt_file, offset, SEEK_SET); lseek(pf->fd, offset, SEEK_SET);
read (fnt_file, tmp, 2); read (pf->fd, tmp, 2);
bitmap_offset = tmp[0] | (tmp[1] << 8); bitmap_offset = tmp[0] | (tmp[1] << 8);
if (long_offset) { if (pf->long_offset) {
read (fnt_file, tmp, 2); read (pf->fd, tmp, 2);
bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24); bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24);
} }
} }
@ -434,22 +512,22 @@ load_cache_entry(struct font_cache_entry* p, void* callback_data)
} }
int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset;
lseek(fnt_file, file_offset, SEEK_SET); lseek(pf->fd, file_offset, SEEK_SET);
int src_bytes = p->width * ((pf->height + 7) / 8); int src_bytes = p->width * ((pf->height + 7) / 8);
read(fnt_file, p->bitmap, src_bytes); read(pf->fd, p->bitmap, src_bytes);
} }
/* /*
* Converts cbuf into a font cache * Converts cbuf into a font cache
*/ */
static void cache_create(int maxwidth, int height) static void cache_create(struct font* pf, int maxwidth, int height)
{ {
/* maximum size of rotated bitmap */ /* maximum size of rotated bitmap */
int bitmap_size = maxwidth * ((height + 7) / 8); int bitmap_size = maxwidth * ((height + 7) / 8);
/* Initialise cache */ /* Initialise cache */
font_cache_create(&font_cache_ui, mbuf, MAX_FONT_SIZE, bitmap_size); font_cache_create(&pf->cache, pf->buffer_start, pf->buffer_size, bitmap_size);
} }
/* /*
@ -462,8 +540,8 @@ int font_get_width(struct font* pf, unsigned short char_code)
char_code = pf->defaultchar; char_code = pf->defaultchar;
char_code -= pf->firstchar; char_code -= pf->firstchar;
return (fnt_file >= 0 && pf != &sysfont)? return (pf->fd >= 0 && pf != &sysfont)?
font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->width: font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->width:
pf->width? pf->width[char_code]: pf->maxwidth; pf->width? pf->width[char_code]: pf->maxwidth;
} }
@ -476,10 +554,10 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
char_code = pf->defaultchar; char_code = pf->defaultchar;
char_code -= pf->firstchar; char_code -= pf->firstchar;
if (fnt_file >= 0 && pf != &sysfont) if (pf->fd >= 0 && pf != &sysfont)
{ {
bits = bits =
(unsigned char*)font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->bitmap; (unsigned char*)font_cache_get(&pf->cache,char_code,load_cache_entry,pf)->bitmap;
} }
else else
{ {
@ -497,7 +575,7 @@ const unsigned char* font_get_bits(struct font* pf, unsigned short char_code)
return bits; return bits;
} }
static int cache_fd;
static void glyph_file_write(void* data) static void glyph_file_write(void* data)
{ {
struct font_cache_entry* p = data; struct font_cache_entry* p = data;
@ -507,45 +585,48 @@ static void glyph_file_write(void* data)
ch = p->_char_code + pf->firstchar; ch = p->_char_code + pf->firstchar;
if (ch != 0xffff && glyph_file >= 0) { if (ch != 0xffff && cache_fd >= 0) {
tmp[0] = ch >> 8; tmp[0] = ch >> 8;
tmp[1] = ch & 0xff; tmp[1] = ch & 0xff;
if (write(glyph_file, tmp, 2) != 2) { if (write(cache_fd, tmp, 2) != 2) {
close(glyph_file); close(cache_fd);
glyph_file = -1; cache_fd = -1;
} }
} }
return; return;
} }
/* save the char codes of the loaded glyphs to a file */ /* save the char codes of the loaded glyphs to a file */
void glyph_cache_save(void) void glyph_cache_save(struct font* pf)
{ {
if (!pf)
if (fnt_file >= 0) { pf = &font_ui;
if (pf->fd >= 0 && pf == &font_ui)
{
#ifdef WPSEDITOR #ifdef WPSEDITOR
glyph_file = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC); cache_fd = open(GLYPH_CACHE_FILE, O_WRONLY|O_CREAT|O_TRUNC);
#else #else
glyph_file = creat(GLYPH_CACHE_FILE); cache_fd = creat(GLYPH_CACHE_FILE);
#endif #endif
if (glyph_file < 0) return; if (cache_fd < 0) return;
lru_traverse(&font_cache_ui._lru, glyph_file_write); lru_traverse(&pf->cache._lru, glyph_file_write);
if (glyph_file >= 0) if (cache_fd < 0)
close(glyph_file); {
close(cache_fd);
cache_fd = -1;
}
} }
return; return;
} }
static void glyph_cache_load(void) static void glyph_cache_load(struct font* pf)
{ {
if (fnt_file >= 0) { if (pf->fd >= 0) {
int fd; int fd;
unsigned char tmp[2]; unsigned char tmp[2];
unsigned short ch; unsigned short ch;
struct font* pf = &font_ui;
fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY);

View file

@ -744,7 +744,7 @@ void shutdown_hw(void)
if (battery_level_safe()) { /* do not save on critical battery */ if (battery_level_safe()) { /* do not save on critical battery */
#ifdef HAVE_LCD_BITMAP #ifdef HAVE_LCD_BITMAP
glyph_cache_save(); glyph_cache_save(NULL);
#endif #endif
/* Commit pending writes if needed. Even though we don't do write caching, /* Commit pending writes if needed. Even though we don't do write caching,

View file

@ -1,6 +1,9 @@
../../apps/gui/skin_engine/wps_debug.c ../../apps/gui/skin_engine/wps_debug.c
../../apps/gui/skin_engine/skin_parser.c ../../apps/gui/skin_engine/skin_parser.c
../../apps/gui/skin_engine/skin_buffer.c ../../apps/gui/skin_engine/skin_buffer.c
#ifdef HAVE_LCD_BITMAP
../../apps/gui/skin_engine/skin_fonts.c
#endif
../../apps/gui/viewport.c ../../apps/gui/viewport.c
../../apps/misc.c ../../apps/misc.c
../../firmware/common/strlcpy.c ../../firmware/common/strlcpy.c

View file

@ -31,6 +31,7 @@
#include "settings.h" #include "settings.h"
#include "viewport.h" #include "viewport.h"
#include "file.h" #include "file.h"
#include "font.h"
bool debug_wps = true; bool debug_wps = true;
int wps_verbose_level = 0; int wps_verbose_level = 0;
@ -236,6 +237,21 @@ void screen_clear_area(struct screen * display, int xstart, int ystart,
} }
#endif #endif
#ifdef HAVE_LCD_BITMAP
static int loaded_fonts = 0;
int font_load(struct font* pf, const char *path)
{
int id = SYSTEMFONTCOUNT + loaded_fonts;
loaded_fonts++;
return id;
}
void font_unload(int font_id)
{
(void)font_id;
}
#endif
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
int res; int res;

View file

@ -1393,7 +1393,16 @@ int gen_c_source(struct font* pf, char *path)
" %s /* offset */\n" " %s /* offset */\n"
" %s\n" " %s\n"
" %d, /* defaultchar */\n" " %d, /* defaultchar */\n"
" %d /* bits_size */\n" " %d, /* bits_size */\n"
" -1, /* font fd */\n"
" 0, /* buffer start */\n"
" 0, /* ^ position */\n"
" 0, /* ^ end */\n"
" 0, /* ^ size */\n"
" {{0,0,0,0,0},0,0,0}, /* cache */\n"
" 0, /* */\n"
" 0, /* */\n"
" 0, /* */\n"
"};\n" "};\n"
"#endif /* HAVE_LCD_BITMAP */\n", "#endif /* HAVE_LCD_BITMAP */\n",
pf->maxwidth, pf->height, pf->maxwidth, pf->height,