/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * $Id$ * * Copyright (C) 2007 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 #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" #include "bitmaps/default_icons.h" #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) #include "bitmaps/remote_default_icons.h" #endif /* These are just the file names, the full path is snprint'ed when used */ #define DEFAULT_VIEWER_BMP "viewers" #define DEFAULT_REMOTE_VIEWER_BMP "remote_viewers" /* These can be defined in config-.h, if it is not provide defaults */ #if !defined(MAX_ICON_HEIGHT) #define MAX_ICON_HEIGHT 24 #endif #if !defined(MAX_ICON_WIDTH) #define MAX_ICON_WIDTH 24 #endif /* 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 #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) , (void*)remote_default_icons #endif }; static const int default_width[NB_SCREENS] = { BMPWIDTH_default_icons #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) , BMPWIDTH_remote_default_icons #endif }; /* height of whole file */ static const int default_height[NB_SCREENS] = { BMPHEIGHT_default_icons #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) , 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[NB_SCREENS][IMG_BUFSIZE]; static bool custom_icons_loaded[NB_SCREENS] = {false}; static struct bitmap user_iconset[NB_SCREENS]; static unsigned char viewer_icon_buffer[NB_SCREENS][IMG_BUFSIZE]; 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) { int xpos, ypos; int width, height; int screen = display->screen_type; display->getstringsize((unsigned char *)"M", &width, &height); xpos = x*ICON_WIDTH(screen) + off_x; ypos = y*height + off_y; if ( height > ICON_HEIGHT(screen) )/* center the cursor */ ypos += (height - ICON_HEIGHT(screen)) / 2; screen_put_iconxy(display, xpos, ypos, icon); } /* x,y in pixels */ void screen_put_iconxy(struct screen * display, int xpos, int ypos, enum themable_icons icon) { const void *data; int screen = display->screen_type; int width = ICON_WIDTH(screen); int height = ICON_HEIGHT(screen); int stride; screen_bitmap_part_func *draw_func = NULL; if (icon == Icon_NOICON) { screen_clear_area(display, xpos, ypos, width, height); return; } else if (icon >= Icon_Last_Themeable) { icon -= Icon_Last_Themeable; if (!viewer_icons_loaded[screen] || (global_status.viewer_icon_count*height > viewer_iconset[screen].height) || (icon * height > viewer_iconset[screen].height)) { screen_put_iconxy(display, xpos, ypos, Icon_Questionmark); return; } data = viewer_iconset[screen].data; stride = STRIDE( viewer_iconset[screen].width, viewer_iconset[screen].height); } else if (custom_icons_loaded[screen]) { data = user_iconset[screen].data; stride = STRIDE( user_iconset[screen].width, user_iconset[screen].height); } else { data = inbuilt_icons[screen]; stride = STRIDE(BMPWIDTH_default_icons, BMPHEIGHT_default_icons); } /* add some left padding to the icons if they are on the edge */ if (xpos == 0) xpos++; #if (LCD_DEPTH == 16) || defined(LCD_REMOTE_DEPTH) && (LCD_REMOTE_DEPTH == 16) if (display->depth == 16) draw_func = display->transparent_bitmap_part; else #endif draw_func = display->bitmap_part; draw_func(data, 0, height * icon, stride, xpos, ypos, width, height); } void screen_put_cursorxy(struct screen * display, int x, int y, bool on) { #ifdef HAVE_LCD_BITMAP screen_put_icon(display, x, y, on?Icon_Cursor:0); #else screen_put_icon(display, x, y, on?CURSOR_CHAR:-1); #endif } enum Iconset { Iconset_Mainscreen, Iconset_Mainscreen_viewers, #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) Iconset_Remotescreen, Iconset_Remotescreen_viewers, #endif }; static void load_icons(const char* filename, enum Iconset iconset, bool allow_disable) { int size_read; bool *loaded_ok = NULL; struct bitmap *bmp = NULL; int bmpformat = (FORMAT_NATIVE|FORMAT_DITHER); 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; #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) case Iconset_Remotescreen: loaded_ok = &custom_icons_loaded[SCREEN_REMOTE]; bmp = &user_iconset[SCREEN_REMOTE]; bmp->data = icon_buffer[SCREEN_REMOTE]; bmpformat |= FORMAT_REMOTE; break; case Iconset_Remotescreen_viewers: loaded_ok = &viewer_icons_loaded[SCREEN_REMOTE]; bmp = &viewer_iconset[SCREEN_REMOTE]; bmp->data = viewer_icon_buffer[SCREEN_REMOTE]; bmpformat |= FORMAT_REMOTE; break; #endif } *loaded_ok = false; if (!allow_disable || (filename[0] && filename[0] != '-')) { char path[MAX_PATH]; snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, filename); size_read = read_bmp_file(path, bmp, IMG_BUFSIZE, bmpformat, NULL); if (size_read > 0) { *loaded_ok = true; } } } void icons_init(void) { load_icons(global_settings.icon_file, Iconset_Mainscreen, true); if (*global_settings.viewers_icon_file) { load_icons(global_settings.viewers_icon_file, Iconset_Mainscreen_viewers, true); read_viewer_theme_file(); } else { load_icons(DEFAULT_VIEWER_BMP, Iconset_Mainscreen_viewers, false); } #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) load_icons(global_settings.remote_icon_file, Iconset_Remotescreen, true); if (*global_settings.remote_viewers_icon_file) { load_icons(global_settings.remote_viewers_icon_file, Iconset_Remotescreen_viewers, true); } else { load_icons(DEFAULT_REMOTE_VIEWER_BMP, Iconset_Remotescreen_viewers, false); } #endif } int get_icon_width(enum screen_type screen_type) { return ICON_WIDTH(screen_type); }