From 6a5cc0bd25bd468c79e453fa49f353edd824141a Mon Sep 17 00:00:00 2001 From: Jonathan Gordon Date: Mon, 16 Apr 2007 09:14:36 +0000 Subject: Customizable icons for all bitmap targets. (FS#7013) http://www.rockbox.org/twiki/bin/view/Main/CustomIcons for info on format and how to load them git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13177 a1c6a512-1295-4272-9138-f99709370657 --- apps/gui/color_picker.c | 14 ++- apps/gui/icon.c | 261 ++++++++++++++++++++++++++++++++++++++++++++---- apps/gui/icon.h | 80 ++++++++++++--- apps/gui/list.c | 49 +++++---- apps/gui/list.h | 8 +- 5 files changed, 347 insertions(+), 65 deletions(-) (limited to 'apps/gui') diff --git a/apps/gui/color_picker.c b/apps/gui/color_picker.c index 2d0dba1221..1739f3fd61 100644 --- a/apps/gui/color_picker.c +++ b/apps/gui/color_picker.c @@ -31,7 +31,7 @@ #include "lang.h" #include "splash.h" #include "action.h" -#include "icons.h" +#include "icon.h" /* structure for color info */ struct rgb_pick @@ -220,13 +220,11 @@ static void draw_screen(struct screen *display, char *title, /* Draw "> <" around sliders */ int top = text_top + (display->char_height - SELECTOR_HEIGHT) / 2; - display->mono_bitmap(bitmap_icons_6x8[Icon_Cursor], - MARGIN_LEFT, top, - SELECTOR_WIDTH, SELECTOR_HEIGHT); - display->mono_bitmap(bitmap_icons_6x8[Icon_Reverse_Cursor], - display->width - MARGIN_RIGHT - - SELECTOR_WIDTH, top, SELECTOR_WIDTH, - SELECTOR_HEIGHT); + screen_put_iconxy(display, MARGIN_LEFT, top, Icon_Cursor); + screen_put_iconxy(display, + display->width - MARGIN_RIGHT - + get_icon_width(display->screen_type), + top, Icon_Cursor); } if (display->depth >= 16) diff --git a/apps/gui/icon.c b/apps/gui/icon.c index ef6f61f94e..2cb0035ad7 100644 --- a/apps/gui/icon.c +++ b/apps/gui/icon.c @@ -7,7 +7,7 @@ * \/ \/ \/ \/ \/ * $Id$ * - * Copyright (C) Robert E. Hak(2002) + * Copyright (C) 2007 Jonathan Gordon * * All files in this archive are subject to the GNU General Public License. * See the file COPYING in the source tree root for full license agreement. @@ -16,42 +16,265 @@ * KIND, either express or implied. * ****************************************************************************/ - +#include +#include +#include +#include "inttypes.h" #include "config.h" #include "icon.h" #include "screen_access.h" #include "icons.h" +#include "settings.h" +#include "bmp.h" +#include "filetypes.h" + +/* Quick and Dirty hack untill lcd bitmap drawing is fixed */ +#ifdef HAVE_REMOTE_LCD +#include "lcd-remote.h" +#endif + + +#include +#ifdef HAVE_REMOTE_LCD +#include +#endif + +#define DEFAULT_VIEWER_BMP ICON_DIR "/viewers.bmp" +#define DEFAULT_REMOTE_VIEWER_BMP ICON_DIR "/remote_viewers.bmp" + +/* These should robably be moved to config-.h */ +#define MAX_ICON_HEIGHT 24 +#define MAX_ICON_WIDTH 24 + + +/* We dont actually do anything with these pointers, + but they need to be grouped like this to save code + so storing them as void* is ok. (stops compile warning) */ +static const void * inbuilt_icons[NB_SCREENS] = { + (void*)default_icons +#ifdef HAVE_REMOTE_LCD + , (void*)remote_default_icons +#endif +}; -/* Count in letter positions, NOT pixels */ -void screen_put_iconxy(struct screen * display, int x, int y, ICON icon) +static const int default_width[NB_SCREENS] = { + BMPWIDTH_default_icons +#ifdef HAVE_REMOTE_LCD + , BMPWIDTH_remote_default_icons +#endif +}; + +/* height of whole file */ +static const int default_height[NB_SCREENS] = { + BMPHEIGHT_default_icons +#ifdef HAVE_REMOTE_LCD + , BMPHEIGHT_remote_default_icons +#endif +}; + +#define IMG_BUFSIZE (MAX_ICON_HEIGHT * MAX_ICON_WIDTH * \ + Icon_Last_Themeable *LCD_DEPTH/8) +static unsigned char icon_buffer[IMG_BUFSIZE][NB_SCREENS]; +static bool custom_icons_loaded[NB_SCREENS] = {false}; +static struct bitmap user_iconset[NB_SCREENS]; + +static unsigned char viewer_icon_buffer[IMG_BUFSIZE][NB_SCREENS]; +static bool viewer_icons_loaded[NB_SCREENS] = {false}; +static struct bitmap viewer_iconset[NB_SCREENS]; + + +#define ICON_HEIGHT(screen) (!custom_icons_loaded[screen]? \ + default_height[screen] : \ + user_iconset[screen].height) \ + / Icon_Last_Themeable + +#define ICON_WIDTH(screen) (!custom_icons_loaded[screen]? \ + default_width[screen] : \ + user_iconset[screen].width) + +/* x,y in letters, not pixles */ +void screen_put_icon(struct screen * display, + int x, int y, enum themable_icons icon) +{ + screen_put_icon_with_offset(display, x, y, 0, 0, icon); +} + +void screen_put_icon_with_offset(struct screen * display, + int x, int y, int off_x, int off_y, + enum themable_icons icon) { -#ifdef HAVE_LCD_BITMAP - int width, height; int xpos, ypos; + int width, height; + int screen = display->screen_type; display->getstringsize((unsigned char *)"M", &width, &height); - xpos = x*CURSOR_WIDTH; - ypos = y*height + display->getymargin(); + xpos = x*ICON_WIDTH(screen) + off_x; + ypos = y*height + display->getymargin() + off_y; + + if ( height > ICON_HEIGHT(screen) )/* center the cursor */ + ypos += (height - ICON_HEIGHT(screen)) / 2; + screen_put_iconxy(display, xpos, ypos, icon); +} - if ( height > CURSOR_HEIGHT )/* center the cursor */ - ypos += (height - CURSOR_HEIGHT) / 2; - if(icon==0)/* Don't display invalid icons */ - screen_clear_area(display, xpos, ypos, CURSOR_WIDTH, CURSOR_HEIGHT); +/* x,y in pixels */ +typedef void (*lcd_draw_func)(const fb_data *src, int src_x, int src_y, + int stride, int x, int y, int width, int height); +void screen_put_iconxy(struct screen * display, + int xpos, int ypos, enum themable_icons icon) +{ + fb_data *data; + int screen = display->screen_type; + lcd_draw_func draw_func = NULL; + + if (icon == Icon_NOICON) + { + screen_clear_area(display, xpos, ypos, + ICON_WIDTH(screen), ICON_HEIGHT(screen)); + return; + } + else if (icon >= Icon_Last_Themeable) + { + icon -= Icon_Last_Themeable; + if (!viewer_icons_loaded[screen] || + (icon*ICON_HEIGHT(screen) > viewer_iconset[screen].height)) + { + screen_clear_area(display, xpos, ypos, + ICON_WIDTH(screen), ICON_HEIGHT(screen)); + return; + } + data = (fb_data *)viewer_iconset[screen].data; + } + else if (custom_icons_loaded[screen]) + { + data = (fb_data *)user_iconset[screen].data; + } else - display->mono_bitmap(icon, xpos, ypos, CURSOR_WIDTH, CURSOR_HEIGHT); -#else - if(icon==-1) - display->putc(x, y, ' '); + { + data = (fb_data *)inbuilt_icons[screen]; + } + /* add some left padding to the icons if they are on the edge */ + if (xpos == 0) + xpos++; + +#ifdef HAVE_REMOTE_LCD + if (display->screen_type == SCREEN_REMOTE) + { + /* Quick and Dirty hack untill lcd bitmap drawing is fixed */ + draw_func = (lcd_draw_func)lcd_remote_bitmap_part; + } else - display->putc(x, y, icon); #endif +#if LCD_DEPTH == 16 + draw_func = display->transparent_bitmap_part; +#else /* LCD_DEPTH < 16 */ + draw_func = display->bitmap_part; +#endif /* LCD_DEPTH == 16 */ + + draw_func( (const fb_data *)data, + 0, ICON_HEIGHT(screen)*icon, + ICON_WIDTH(screen), xpos, ypos, + ICON_WIDTH(screen), ICON_HEIGHT(screen)); } void screen_put_cursorxy(struct screen * display, int x, int y, bool on) { #ifdef HAVE_LCD_BITMAP - screen_put_iconxy(display, x, y, on?bitmap_icons_6x8[Icon_Cursor]:0); + screen_put_icon(display, x, y, on?Icon_Cursor:0); #else - screen_put_iconxy(display, x, y, on?CURSOR_CHAR:-1); + screen_put_icon(display, x, y, on?CURSOR_CHAR:-1); #endif } +enum Iconset { + Iconset_Mainscreen, + Iconset_Mainscreen_viewers, +#ifdef HAVE_REMOTE_LCD + Iconset_Remotescreen, + Iconset_Remotescreen_viewers, +#endif +}; + +static void load_icons(const char* filename, enum Iconset iconset) +{ + int size_read; + bool *loaded_ok = NULL; + struct bitmap *bmp = NULL; + + switch (iconset) + { + case Iconset_Mainscreen: + loaded_ok = &custom_icons_loaded[SCREEN_MAIN]; + bmp = &user_iconset[SCREEN_MAIN]; + bmp->data = icon_buffer[SCREEN_MAIN]; + break; + case Iconset_Mainscreen_viewers: + loaded_ok = &viewer_icons_loaded[SCREEN_MAIN]; + bmp = &viewer_iconset[SCREEN_MAIN]; + bmp->data = viewer_icon_buffer[SCREEN_MAIN]; + break; +#ifdef HAVE_REMOTE_LCD + case Iconset_Remotescreen: + loaded_ok = &custom_icons_loaded[SCREEN_MAIN]; + bmp = &user_iconset[SCREEN_MAIN]; + bmp->data = icon_buffer[SCREEN_MAIN]; + break; + case Iconset_Remotescreen_viewers: + loaded_ok = &viewer_icons_loaded[SCREEN_REMOTE]; + bmp = &viewer_iconset[SCREEN_REMOTE]; + bmp->data = viewer_icon_buffer[SCREEN_REMOTE]; + break; +#endif + } + + *loaded_ok = false; + if (filename != NULL) + { + size_read = read_bmp_file((char*)filename, bmp, IMG_BUFSIZE, + FORMAT_NATIVE | FORMAT_DITHER); + if (size_read > 0) + { + *loaded_ok = true; + } + } +} + + +void icons_init(void) +{ + char path[MAX_PATH]; + if (global_settings.icon_file[0]) + { + snprintf(path, MAX_PATH, "%s/%s.bmp", + ICON_DIR, global_settings.icon_file); + load_icons(path, Iconset_Mainscreen); + } + if (global_settings.viewers_icon_file[0]) + { + snprintf(path, MAX_PATH, "%s/%s.bmp", + ICON_DIR, global_settings.viewers_icon_file); + load_icons(path, Iconset_Mainscreen_viewers); + read_viewer_theme_file(); + } + else + load_icons(DEFAULT_VIEWER_BMP, Iconset_Mainscreen_viewers); +#ifdef HAVE_REMOTE_LCD + if (global_settings.remote_icon_file[0]) + { + snprintf(path, MAX_PATH, "%s/%s.bmp", + ICON_DIR, global_settings.remote_icon_file); + load_icons(path, Iconset_Remotescreen); + } + if (global_settings.remote_viewers_icon_file[0]) + { + snprintf(path, MAX_PATH, "%s/%s.bmp", + ICON_DIR, global_settings.remote_viewers_icon_file); + load_icons(path, Iconset_Remotescreen_viewers); + } + else + load_icons(DEFAULT_REMOTE_VIEWER_BMP, Iconset_Mainscreen_viewers); +#endif +} + +int get_icon_width(enum screen_type screen_type) +{ + return ICON_WIDTH(screen_type); +} diff --git a/apps/gui/icon.h b/apps/gui/icon.h index c717bbc6ea..fa6919030f 100644 --- a/apps/gui/icon.h +++ b/apps/gui/icon.h @@ -24,19 +24,51 @@ * char-based displays and bitmap displays */ #ifdef HAVE_LCD_BITMAP typedef const unsigned char * ICON; -typedef unsigned char * ICON_NO_CONST; -#define NOICON NULL +#define NOICON Icon_NOICON #else typedef long ICON; -#define ICON_NO_CONST ICON -#define NOICON -1 +#define NOICON Icon_NOICON #endif -#define Icon_NOICON -1 - -#define CURSOR_CHAR 0xe10c -#define CURSOR_WIDTH 6 -#define CURSOR_HEIGHT 8 +#define FORCE_INBUILT_ICON 0x80000000 +/* Don't #ifdef icon values, or we wont be able to use the same + cmp for every target. */ +enum themable_icons { + Icon_NOICON = -1, /* Dont put this in a .bmp */ + Icon_Audio, + Icon_Folder, + Icon_Playlist, + Icon_Cursor, + Icon_Wps, + Icon_Firmware, + Icon_Font, + Icon_Language, + Icon_Config, + Icon_Plugin, + Icon_Bookmark, + Icon_Preset, + Icon_Queued, + Icon_Moving, + Icon_Keyboard, + Icon_Reverse_Cursor, + Icon_Questionmark, + Icon_Menu_setting, + Icon_Menu_functioncall, + Icon_Submenu, + Icon_Submenu_Entered, + Icon_Recording, + Icon_Voice, + Icon_General_settings_menu, + Icon_System_menu, + Icon_Playback_menu, + Icon_Display_menu, + Icon_Remote_Display_menu, + Icon_Radio_screen, + Icon_file_view_menu, + Icon_EQ, + Icon_Rockbox, + Icon_Last_Themeable, +}; /* * Draws a cursor at a given position, if th @@ -49,12 +81,36 @@ extern void screen_put_cursorxy(struct screen * screen, int x, int y, bool on); /* * Put an icon on a screen at a given position * (the position is given in characters) - * If the given icon is null (HAVE_LCD_BITMAP) or -1 otherwise, the icon + * If the given icon is Icon_blank, the icon * at the given position will be erased * - screen : the screen where we put our icon - * - x, y : the position, in character, not in pixel !! + * - x, y : the position, pixel value !! * - icon : the icon to put */ -extern void screen_put_iconxy(struct screen * screen, int x, int y, ICON icon); +extern void screen_put_iconxy(struct screen * screen, + int x, int y, enum themable_icons icon); +#ifdef HAVE_LCD_CHARCELLS +# define screen_put_icon(s, x, y, i) screen_put_iconxy(s, x, y, i) +# define screen_put_icon_with_offset(s, x, y, w, h, i) screen_put_icon(s, x, y, i) +#else +/* For both of these, the icon will be placed in the center of the rectangle */ +/* as above, but x,y are letter position, NOT PIXEL */ +extern void screen_put_icon(struct screen * screen, + int x, int y, enum themable_icons icon); +/* as above (x,y are letter pos), but with a pxiel offset for both */ +extern void screen_put_icon_with_offset(struct screen * display, + int x, int y, int off_x, int off_y, + enum themable_icons icon); +#endif + +void icons_init(void); + + +#ifdef HAVE_LCD_CHARCELLS +# define CURSOR_CHAR 0xe10c +# define get_icon_width(a) 6 +#else +int get_icon_width(enum screen_type screen_type); +#endif #endif /*_GUI_ICON_H_*/ diff --git a/apps/gui/list.c b/apps/gui/list.c index e3b0d6afe5..c93210e0eb 100644 --- a/apps/gui/list.c +++ b/apps/gui/list.c @@ -92,7 +92,7 @@ static void gui_list_init(struct gui_list * gui_list, gui_list->selected_size=selected_size; gui_list->title = NULL; gui_list->title_width = 0; - gui_list->title_icon = NOICON; + gui_list->title_icon = Icon_NOICON; gui_list->last_displayed_selected_item = -1 ; gui_list->last_displayed_start_item = -1 ; @@ -230,8 +230,6 @@ static int gui_list_get_item_offset(struct gui_list * gui_list, int item_width, static void gui_list_draw_smart(struct gui_list *gui_list) { struct screen * display=gui_list->display; - int cursor_pos = 0; - int icon_pos = 1; int text_pos; bool draw_icons = (gui_list->callback_get_item_icon != NULL && global_settings.show_icons); bool draw_cursor; @@ -288,9 +286,9 @@ static void gui_list_draw_smart(struct gui_list *gui_list) { if (gui_list->title_icon != NOICON && draw_icons) { - screen_put_iconxy(display, 0, 0, gui_list->title_icon); + screen_put_icon(display, 0, 0, gui_list->title_icon); #ifdef HAVE_LCD_BITMAP - text_pos = 8; /* pixels */ + text_pos = get_icon_width(display->screen_type)+2; /* pixels */ #else text_pos = 1; /* chars */ #endif @@ -327,17 +325,13 @@ static void gui_list_draw_smart(struct gui_list *gui_list) if(draw_scrollbar || SHOW_LIST_TITLE) /* indent if there's a title */ { - cursor_pos++; - icon_pos++; text_pos += SCROLLBAR_WIDTH; } - if(!draw_cursor) - icon_pos--; - else - text_pos += CURSOR_WIDTH; + if(draw_cursor) + text_pos += get_icon_width(display->screen_type) + 2; if(draw_icons) - text_pos += 8; + text_pos += get_icon_width(display->screen_type) + 2; #else draw_cursor = true; if(draw_icons) @@ -413,7 +407,12 @@ static void gui_list_draw_smart(struct gui_list *gui_list) #endif if (draw_cursor) - screen_put_cursorxy(display, cursor_pos, i, true); + { + screen_put_icon_with_offset(display, 0, i, + (draw_scrollbar || SHOW_LIST_TITLE)? + SCROLLBAR_WIDTH: 0, + 0, Icon_Cursor); + } } else {/* normal item */ @@ -437,12 +436,19 @@ static void gui_list_draw_smart(struct gui_list *gui_list) /* Icons display */ if(draw_icons) { - ICON icon; - gui_list->callback_get_item_icon(current_item, - gui_list->data, - &icon); - if(icon) - screen_put_iconxy(display, icon_pos, i, icon); + enum themable_icons icon; + icon = gui_list->callback_get_item_icon(current_item, gui_list->data); + if(icon > Icon_NOICON) + { +#ifdef HAVE_LCD_BITMAP + int x = draw_cursor?1:0; + int x_off = (draw_scrollbar || SHOW_LIST_TITLE) ? SCROLLBAR_WIDTH: 0; + screen_put_icon_with_offset(display, x, i, + x_off, 0, icon); +#else + screen_put_icon(display, 1, i, icon); +#endif + } } } @@ -737,7 +743,8 @@ void gui_list_screen_scroll_out_of_view(bool enable) * Set the title and title icon of the list. Setting title to NULL disables * both the title and icon. Use NOICON if there is no icon. */ -static void gui_list_set_title(struct gui_list * gui_list, char * title, ICON icon) +static void gui_list_set_title(struct gui_list * gui_list, + char * title, enum themable_icons icon) { gui_list->title = title; gui_list->title_icon = icon; @@ -870,7 +877,7 @@ void gui_synclist_limit_scroll(struct gui_synclist * lists, bool scroll) } void gui_synclist_set_title(struct gui_synclist * lists, - char * title, ICON icon) + char * title, enum themable_icons icon) { int i; FOR_NB_SCREENS(i) diff --git a/apps/gui/list.h b/apps/gui/list.h index bd43edf7ef..283676d631 100644 --- a/apps/gui/list.h +++ b/apps/gui/list.h @@ -49,9 +49,7 @@ enum list_wrap { * the icon after the function returns. * Note : we use the ICON type because the real type depends of the plateform */ -typedef void list_get_icon(int selected_item, - void * data, - ICON * icon); +typedef enum themable_icons list_get_icon(int selected_item, void * data); /* * Text callback * - selected_item : an integer that tells the number of the item to display @@ -101,7 +99,7 @@ struct gui_list /* The optional title, set to NULL for none */ char * title; /* Optional title icon */ - ICON title_icon; + enum themable_icons title_icon; }; /* @@ -190,7 +188,7 @@ extern void gui_synclist_del_item(struct gui_synclist * lists); extern void gui_synclist_limit_scroll(struct gui_synclist * lists, bool scroll); extern void gui_synclist_flash(struct gui_synclist * lists); extern void gui_synclist_set_title(struct gui_synclist * lists, char * title, - ICON icon); + int icon); /* * Do the action implied by the given button, -- cgit v1.2.3