| /*************************************************************************** |
| * __________ __ ___. |
| * 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 <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #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 <default_icons.h> |
| #if defined(HAVE_REMOTE_LCD) && (NB_SCREENS > 1) |
| #include <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 should probably be moved to config-<target>.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 |
| #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); |
| 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; |
| } |
| else if (custom_icons_loaded[screen]) |
| { |
| data = user_iconset[screen].data; |
| } |
| else |
| { |
| data = inbuilt_icons[screen]; |
| } |
| /* 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, width, 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); |
| 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); |
| } |