Index: apps/screen_access.c =================================================================== --- apps/screen_access.c (revision 16159) +++ apps/screen_access.c (working copy) @@ -230,9 +230,6 @@ int i; FOR_NB_SCREENS(i) { -#ifdef HAVE_LCD_BITMAP - ((struct screen*)&screens[i])->setfont(FONT_UI); -#endif gui_textarea_update_nblines(&screens[i]); } } Index: apps/playlist.c =================================================================== --- apps/playlist.c (revision 16159) +++ apps/playlist.c (working copy) @@ -3634,3 +3634,17 @@ return result; } + +/* + * Check if a folder exists, if not try to create it + * return 0 if it exists, <0 otherwise + */ +int playlist_check_dir(const char* dirname) +{ + DIR* dir = opendir(dirname); + if(dir) + closedir(dir); + else + return mkdir(dirname); + return 0; +} Index: apps/screens.c =================================================================== --- apps/screens.c (revision 16159) +++ apps/screens.c (working copy) @@ -631,7 +631,6 @@ #if CONFIG_CODEC == SWCODEC pcmbuf_set_low_latency(false); #endif - lcd_setfont(FONT_UI); return 0; } #endif /* HAVE_PITCHSCREEN */ Index: apps/playlist.h =================================================================== --- apps/playlist.h (revision 16159) +++ apps/playlist.h (working copy) @@ -30,6 +30,7 @@ #define PLAYLIST_ATTR_SKIPPED 0x04 #define PLAYLIST_MAX_CACHE 16 +#define DEFAULT_PLAYLIST_DIR "/Playlists" #define DEFAULT_DYNAMIC_PLAYLIST_NAME "/dynamic.m3u8" enum playlist_command { @@ -127,6 +128,7 @@ int playlist_update_resume_info(const struct mp3entry* id3); int playlist_get_display_index(void); int playlist_amount(void); +int playlist_check_dir(const char*); /* Exported functions for all playlists. Pass NULL for playlist_info structure to work with current playlist. */ Index: apps/recorder/bmp.c =================================================================== --- apps/recorder/bmp.c (revision 16159) +++ apps/recorder/bmp.c (working copy) @@ -51,6 +51,7 @@ #pragma pack (push, 2) #endif +#define FACT_SCALE 1000 /* BMP header structure */ struct bmp_header { uint16_t type; /* signature - 'BM' */ @@ -81,6 +82,12 @@ uint32_t raw; }; +/* maximum bitmap width which can be read: */ +#define MAX_WIDTH 1280 +/* Buffer for one line */ +//static uint32_t bmpbuf[MAX_WIDTH]; +static union rgb_union bmpbuf[MAX_WIDTH]; + /* masks for supported BI_BITFIELDS encodings (16/32 bit), little endian */ static const unsigned char bitfields[3][12] = { { 0x00,0x7c,0x00,0, 0xe0,0x03,0x00,0, 0x1f,0x00,0x00,0 }, /* 15 bit */ @@ -137,59 +144,104 @@ + (unsigned)color.blue) / 10; } -/****************************************************************************** - * read_bmp_file() - * - * Reads a BMP file and puts the data in rockbox format in *bitmap. - * - *****************************************************************************/ -int read_bmp_file(const char* filename, - struct bitmap *bm, - int maxsize, - int format) + +static void set_pixel(int format, + unsigned char *bitmap, + bool dither, + union rgb_union color, + int dst_padded_width, + int dst_x, + int dst_y) { - int fd, ret; - fd = open(filename, O_RDONLY); +#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + bool remote = format & FORMAT_REMOTE; + format &= ~FORMAT_REMOTE; +#endif - /* Exit if file opening failed */ - if (fd < 0) { - DEBUGF("read_bmp_file: can't open '%s', rc: %d\n", filename, fd); - return fd * 10 - 1; +#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) + if (format == FORMAT_NATIVE) + { +# if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + if (remote) + { +# if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) + int delta = (dither)?dither_matrix[dst_y & 0xf][dst_x & 0xf]:127; + unsigned bright = brightness(color); + bright = (3 * bright + (bright >> 6) + delta) >> 8; + ((fb_remote_data *)bitmap)[dst_padded_width*(dst_y >> 3)+dst_x] |= + remote_pattern[bright] << (dst_y & 7); +# endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ + } + else +# endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ + { + int delta = (dither)?dither_matrix[dst_y & 0xf][dst_x & 0xf]:127; +# if LCD_DEPTH == 2 + unsigned bright = brightness(color); + bright = (3 * bright + (bright >> 6) + delta) >> 8; +# if LCD_PIXELFORMAT == VERTICAL_PACKING + /* iriver H1x0 */ + ((fb_data *)bitmap)[dst_padded_width * (dst_y >> 2)+dst_x] |= + (~bright & 3) << (2 * (dst_y & 3)); +# else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ + /* greyscale iPods */ + ((fb_data *)bitmap)[dst_padded_width * dst_y + (dst_x >> 2)] |= + (~bright & 3) << (6 - 2 * (dst_x & 3)); +# endif /* LCD_PIXELFORMAT */ +# elif LCD_DEPTH == 16 + /* iriver h300, colour iPods, X5 */ + unsigned r = (31 * color.red + (color.red >> 3) + delta) >> 8; + unsigned g = (63 * color.green + (color.green >> 2) + delta) >> 8; + unsigned b = (31 * color.blue + (color.blue >> 3) + delta) >> 8; + ((fb_data *)bitmap)[dst_padded_width * dst_y + dst_x] = + LCD_RGBPACK_LCD(r, g, b); +# endif /* LCD_DEPTH */ + } } - - ret = read_bmp_fd(fd, bm, maxsize, format); - close(fd); - return ret; + else +#else /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + (void) format; + (void) dither; +#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ + { + if (brightness(color) < 128) + bitmap[dst_padded_width * (dst_y >> 3)+dst_x] |= 1 << (dst_y & 7); + } } /****************************************************************************** - * read_bmp_fd() + * read_bmp_file() * - * Reads a BMP file in an open file descriptor and puts the data in rockbox - * format in *bitmap. + * Reads a BMP file and puts the data in rockbox format in *bitmap. * *****************************************************************************/ -int read_bmp_fd(int fd, - struct bitmap *bm, - int maxsize, - int format) +int read_bmp_fd( int fd, + struct bitmap *bm, + int maxsize, + int format, + int dst_maxwidth, + int dst_maxheight, + int flags) { struct bmp_header bmph; - int width, height, padded_width; - int dst_height, dst_width; + int src_w, src_h, src_padded_width; + int dst_w, dst_h, dst_padded_width, dst_padded_height; + int row, ret; + int fact_w = FACT_SCALE; + int fact_h = FACT_SCALE; + int top = 0,decrement_y = 0; + int left = 0,decrement_x = 0; int depth, numcolors, compression, totalsize; - int row, col, ret; int rowstart, rowstop, rowstep; unsigned char *bitmap = bm->data; - uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ - uint32_t palette[256]; + union rgb_union palette[256]; + bool dither = false; #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) bool transparent = false; - bool dither = false; #ifdef HAVE_REMOTE_LCD bool remote = false; - + if (format & FORMAT_REMOTE) { remote = true; #if LCD_REMOTE_DEPTH == 1 @@ -209,7 +261,7 @@ } #else - (void)format; + format = FORMAT_MONO; #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ /* read fileheader */ @@ -223,27 +275,131 @@ return -3; } - width = readlong(&bmph.width); - if (width > LCD_WIDTH) { - DEBUGF("read_bmp_fd: Bitmap too wide (%d pixels, max is %d)\n", - width, LCD_WIDTH); + /* check bitmap file signature */ + if (readshort(&bmph.type)!=0x4d42) { + DEBUGF("read_bmp_fd: wring signature."); + return -3; + } + /* read the source dimensions */ + src_w = readlong(&bmph.width); + src_h = readlong(&bmph.height); + + /* Exit if too wide */ + if (((flags & BMP_RESIZE_NONE)==0 && (src_w > MAX_WIDTH)) || + ((flags & BMP_RESIZE_NONE) && (src_w > LCD_WIDTH))) + { + DEBUGF("read_bmp_fd: Bitmap is too wide (%d pixels, max is %d)\n", + src_w, MAX_WIDTH); return -4; } - height = readlong(&bmph.height); - if (height < 0) { /* Top-down BMP file */ - height = -height; - rowstart = 0; - rowstop = height; - rowstep = 1; - } else { /* normal BMP */ - rowstart = height - 1; - rowstop = -1; - rowstep = -1; + + /* Calculate resize factors and image size */ + if (dst_maxwidth<=0 || dst_maxheight<=0) + { + dst_w = src_w; + dst_h = src_h; } + else + { + dst_w = dst_maxwidth; + dst_h = dst_maxheight; + if (flags & BMP_RESIZE_FILL) + { + int aspect_src = src_w*FACT_SCALE/src_h; + int aspect_dst = dst_maxwidth*FACT_SCALE/dst_maxheight; + if (aspect_dst >= aspect_src) /* adjust height */ + decrement_y = (dst_maxheight * aspect_dst / aspect_src) + - dst_maxheight; + else /* adjust width */ + decrement_x = (dst_maxwidth * aspect_src / aspect_dst) + - dst_maxwidth; + if ((flags & BMP_RESIZE_INCREASE) == 0 && + (src_w < dst_w || src_h < dst_h)) + { + if ((decrement_x = (src_w-dst_w)) < 0) + decrement_x = 0; + if ((decrement_y = (src_h-dst_h)) < 0) + decrement_y = 0; + } + left = decrement_x / 2; + top = decrement_y / 2; + flags |= BMP_RESIZE_DECREASE; + } + if (flags & (BMP_RESIZE_DECREASE | BMP_RESIZE_INCREASE)) + { + int fact; + if (dst_w > 0) + { + fact = (src_w * FACT_SCALE) / (dst_w + decrement_x); + /* decrease allowed and increase allowed */ + if ((fact < FACT_SCALE && (flags & BMP_RESIZE_DECREASE)) || + (fact > FACT_SCALE && (flags & BMP_RESIZE_INCREASE))) + fact_w = fact; + } + + if (dst_h > 0) + { + fact = (src_h * FACT_SCALE) / (dst_h + decrement_y); + /* decrease allowed and increase allowed */ + if ((fact < FACT_SCALE && (flags & BMP_RESIZE_DECREASE)) || + (fact > FACT_SCALE && (flags & BMP_RESIZE_INCREASE))) + fact_h = fact; + } + + if ((flags & BMP_RESIZE_IGNORE_ASPECT)==0) + { + /* keep aspect ratio of source */ + if (fact_w < fact_h) + fact_w = fact_h; + else + fact_h = fact_w; + /* don't resize */ + if (fact_w <= 0 || fact_h <= 0) + fact_h = fact_w = FACT_SCALE; + } + while (true) + { + dst_w = ((src_w * FACT_SCALE) / fact_w) - decrement_x; + if (dst_w <= dst_maxwidth) + break; + fact_w++; + } + while (true) + { + dst_h = ((src_h * FACT_SCALE) / fact_h) - decrement_y; + if (dst_h <= dst_maxheight) + break; + fact_h++; + } + } + } + + /* returning image size */ + bm->width = dst_w; + bm->height = dst_h; + + DEBUGF("read_bmp_fd: src=%d/%d, dst=%d/%d max=%d/%d (fact=%d/%d)" + " dec=%d/%d\n", + src_w, src_h, + dst_w, dst_h, + dst_maxwidth, dst_maxheight, + fact_w, fact_h, + decrement_x,decrement_y); + + /* Exit if too big for screen */ + if ((flags & BMP_RESIZE_NONE)==0 && + (dst_w > LCD_WIDTH || dst_h > LCD_HEIGHT)) + { + DEBUGF("read_bmp_fd: error - Bitmap is too big" + " (%d x %d pixels, screen is %d x %d)\n", + dst_w, dst_h, LCD_WIDTH, LCD_HEIGHT); + return -5; + } + depth = readshort(&bmph.bit_count); - padded_width = ((width * depth + 31) >> 3) & ~3; /* 4-byte boundary aligned */ + src_padded_width = ((src_w * depth + 31) >> 3) & ~3; /* 4-byte boundary aligned */ #if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) if (format == FORMAT_ANY) { @@ -253,49 +409,44 @@ format = FORMAT_NATIVE; } bm->format = format; -#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ - /* returning image size */ - bm->width = width; - bm->height = height; - -#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) if (format == FORMAT_NATIVE) { -#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 +# if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 if (remote) { -#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) - dst_width = width; - dst_height = (height + 7) >> 3; -#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ - totalsize = dst_width * dst_height * sizeof(fb_remote_data); +# if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) + dst_padded_width = dst_w; + dst_padded_height = (dst_h + 7) >> 3; +# endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ + totalsize = dst_padded_width * dst_padded_height * sizeof(fb_remote_data); } else -#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ +# endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ { -#if LCD_DEPTH == 2 -#if LCD_PIXELFORMAT == VERTICAL_PACKING - dst_width = width; - dst_height = (height + 3) >> 2; -#else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ - dst_width = (width + 3) >> 2; - dst_height = height; -#endif /* LCD_PIXELFORMAT */ -#elif LCD_DEPTH == 16 - dst_width = width; - dst_height = height; -#endif /* LCD_DEPTH */ - totalsize = dst_width * dst_height * sizeof(fb_data); +# if LCD_DEPTH == 2 +# if LCD_PIXELFORMAT == VERTICAL_PACKING + dst_padded_width = dst_w; + dst_padded_height = (dst_h + 3) >> 2; +# else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ + dst_padded_width = (dst_w + 3) >> 2; + dst_padded_height = dst_h; +# endif /* LCD_PIXELFORMAT */ +# elif LCD_DEPTH == 16 + dst_padded_width = dst_w; + dst_padded_height = dst_h; +# endif /* LCD_DEPTH */ + totalsize = dst_padded_width * dst_padded_height * sizeof(fb_data); } } else #endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ { - dst_width = width; - dst_height = (height + 7) >> 3; - totalsize = dst_width * dst_height; + dst_padded_width = dst_w; + dst_padded_height = (dst_h + 7) >> 3; + totalsize = dst_padded_width * dst_padded_height; } /* Check if this fits the buffer */ if (totalsize > maxsize) { - DEBUGF("read_bmp_fd: Bitmap too large for buffer: " - "%d bytes.\n", totalsize); + DEBUGF("read_bmp_fd: error - Bitmap is too large to fit the supplied buffer: " + "%d bytes.%d:%d\n", (dst_padded_height * dst_padded_width), + totalsize, maxsize); return -6; } @@ -306,7 +457,7 @@ numcolors = 1 << depth; } else numcolors = (compression == 3) ? 3 : 0; - + if (numcolors > 0 && numcolors <= 256) { if (read(fd, palette, numcolors * sizeof(uint32_t)) != numcolors * (int)sizeof(uint32_t)) @@ -357,31 +508,64 @@ memset(bitmap, 0, totalsize); +#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 + if (remote) + format |= FORMAT_REMOTE; // set remote flag if it is necessary +#endif + /* loop to read rows and put them to buffer */ - for (row = rowstart; row != rowstop; row += rowstep) { + for (row = src_h - 1; row >= 0; row--) + { + /* read one row */ + int dst_y, num_rows = 0; + if (fact_h >= FACT_SCALE) + { + /* + * decrease vertically or just transport the pixels + * -> put only every "fact" row to the dest buffer + */ + if ((row % (fact_h / FACT_SCALE)) == 0) + { + dst_y = (row * FACT_SCALE) / fact_h - top; + if (dst_y >= 0 && dst_y < dst_h) + num_rows = 1; + } + } + else + { + /* + * increase + * -> duplicate src-pixel for not existing dst_rows/cols + */ + dst_y = MAX(row * FACT_SCALE / fact_h - top,0); + num_rows = MIN((row + 1) * FACT_SCALE / fact_h - top, dst_h)-dst_y; + } + if (num_rows<=0) + { + /* if we are not going to process data - just skip reading */ + ret = lseek(fd, src_padded_width, SEEK_CUR ); + continue; + } + ret = read(fd, bmpbuf, src_padded_width); + if (ret != src_padded_width) { + DEBUGF("read_bmp_fd: error reading image, read returned: %d " + "expected: %d\n", ret, src_padded_width); + return -9; + } unsigned data, mask; unsigned char *p; uint16_t *p2; uint32_t *rp; - union rgb_union *qp; - union rgb_union q0, q1; + union rgb_union q0, q1; - /* read one row */ - ret = read(fd, bmpbuf, padded_width); - if (ret != padded_width) { - DEBUGF("read_bmp_fd: error reading image, read returned: %d " - "expected: %d\n", ret, padded_width); - return -9; - } - /* convert whole line in-place to XRGB8888 (little endian) */ - rp = bmpbuf + width; + rp = (uint32_t *)(bmpbuf + src_w); switch (depth) { case 1: - q0.raw = palette[0]; - q1.raw = palette[1]; - p = (unsigned char*)bmpbuf + ((width + 7) >> 3); - mask = 0x80 >> ((width + 7) & 7); + q0.raw = palette[0].raw; + q1.raw = palette[1].raw; + p = (unsigned char*)bmpbuf + ((src_w + 7) >> 3); + mask = 0x80 >> ((src_w + 7) & 7); while (p > (unsigned char*)bmpbuf) { data = *(--p); for (; mask <= 0x80; mask <<= 1) @@ -391,25 +575,25 @@ break; case 4: - if (width & 1) + if (src_w & 1) rp++; - p = (unsigned char*)bmpbuf + ((width + 1) >> 1); + p = (unsigned char*)bmpbuf + ((src_w + 1) >> 1); while (p > (unsigned char*)bmpbuf) { data = *(--p); - *(--rp) = palette[data & 0x0f]; - *(--rp) = palette[data >> 4]; + *(--rp) = palette[data & 0x0f].raw; + *(--rp) = palette[data >> 4].raw; } break; case 8: - p = (unsigned char*)bmpbuf + width; + p = (unsigned char*)bmpbuf + src_w; while (p > (unsigned char*)bmpbuf) - *(--rp) = palette[*(--p)]; + *(--rp) = palette[*(--p)].raw; break; - + case 15: case 16: - p2 = (uint16_t *)bmpbuf + width; + p2 = (uint16_t *)bmpbuf + src_w; while (p2 > (uint16_t *)bmpbuf) { unsigned component, rgb; @@ -455,7 +639,7 @@ break; case 24: - p = (unsigned char*)bmpbuf + 3 * width; + p = (unsigned char*)bmpbuf + 3 * src_w; while (p > (unsigned char*)bmpbuf) { data = *(--p); data = (data << 8) | *(--p); @@ -467,99 +651,63 @@ case 32: /* already in desired format */ break; } - + /* Convert to destination format */ - qp = (union rgb_union *)bmpbuf; -#if (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) - if (format == FORMAT_NATIVE) { -#if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 - if (remote) { -#if (LCD_REMOTE_DEPTH == 2) && (LCD_REMOTE_PIXELFORMAT == VERTICAL_INTERLEAVED) - fb_remote_data *dest = (fb_remote_data *)bitmap - + dst_width * (row >> 3); - int shift = row & 7; - int delta = 127; - unsigned bright; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - bright = brightness(*qp++); - bright = (3 * bright + (bright >> 6) + delta) >> 8; - *dest++ |= remote_pattern[bright] << shift; + while (--num_rows>=0) { + int src_col, dst_x; + if (fact_w >= FACT_SCALE) + { + /* decrease horizontally or just transport the pixels */ + for (dst_x = 0; dst_x < dst_w; dst_x++) { + src_col = ((dst_x + left) * fact_w) / FACT_SCALE; + set_pixel(format,bitmap,dither,bmpbuf[src_col], + dst_padded_width,dst_x,dst_y); } -#endif /* LCD_REMOTE_DEPTH / LCD_REMOTE_PIXELFORMAT */ - } else -#endif /* defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 */ + } + else /*if (fact_w < FACT_SCALE)*/ { -#if LCD_DEPTH == 2 -#if LCD_PIXELFORMAT == VERTICAL_PACKING - /* iriver H1x0 */ - fb_data *dest = (fb_data *)bitmap + dst_width * (row >> 2); - int shift = 2 * (row & 3); - int delta = 127; - unsigned bright; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - bright = brightness(*qp++); - bright = (3 * bright + (bright >> 6) + delta) >> 8; - *dest++ |= (~bright & 3) << shift; - } -#else /* LCD_PIXELFORMAT == HORIZONTAL_PACKING */ - /* greyscale iPods */ - fb_data *dest = (fb_data *)bitmap + dst_width * row; - int shift = 6; - int delta = 127; - unsigned bright; - unsigned data = 0; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - bright = brightness(*qp++); - bright = (3 * bright + (bright >> 6) + delta) >> 8; - data |= (~bright & 3) << shift; - shift -= 2; - if (shift < 0) { - *dest++ = data; - data = 0; - shift = 6; + /* increase horizontally */ + for (src_col = 0; src_col < src_w; src_col++) { + int num_col; + dst_x = MAX(src_col * FACT_SCALE / fact_w - left,0); + num_col = MIN((src_col + 1) * FACT_SCALE / fact_w + - left,dst_w) - dst_x; + q0 = bmpbuf[src_col]; + while (--num_col>=0) { + set_pixel(format,bitmap,dither,q0,dst_padded_width, + dst_x,dst_y); + dst_x++; } } - if (shift < 6) - *dest++ = data; -#endif /* LCD_PIXELFORMAT */ -#elif LCD_DEPTH == 16 - /* iriver h300, colour iPods, X5 */ - fb_data *dest = (fb_data *)bitmap + dst_width * row; - int delta = 127; - unsigned r, g, b; - - for (col = 0; col < width; col++) { - if (dither) - delta = dither_matrix[row & 0xf][col & 0xf]; - q0 = *qp++; - r = (31 * q0.red + (q0.red >> 3) + delta) >> 8; - g = (63 * q0.green + (q0.green >> 2) + delta) >> 8; - b = (31 * q0.blue + (q0.blue >> 3) + delta) >> 8; - *dest++ = LCD_RGBPACK_LCD(r, g, b); - } -#endif /* LCD_DEPTH */ } - } else -#endif /* (LCD_DEPTH > 1) || defined(HAVE_REMOTE_LCD) && (LCD_REMOTE_DEPTH > 1) */ - { - p = bitmap + dst_width * (row >> 3); - mask = 1 << (row & 7); - - for (col = 0; col < width; col++, p++) - if (brightness(*qp++) < 128) - *p |= mask; + dst_y++; } } - DEBUGF("totalsize: %d\n", totalsize); + DEBUGF("read_bmp_fd: totalsize=%d, width=%d, height=%d depth=%d" + " compression=%d numcolors=%d\n", + totalsize, dst_w, dst_h, depth, compression, numcolors); + return totalsize; /* return the used buffer size. */ } + +int read_bmp_file(const char* filename, + struct bitmap *bm, + int maxsize, + int format, + int dst_maxwidth, + int dst_maxheight, + int flags) +{ + int fd = open(filename, O_RDONLY); + int ret; + /* Exit if file opening failed */ + if (fd < 0) { + DEBUGF("read_bmp_fd: can't open '%s', rc: %d\n", filename, fd); + return fd * 10 - 1; + } + ret = read_bmp_fd(fd, bm, maxsize, format, dst_maxwidth, dst_maxheight, + flags); + close(fd); + return ret; +} Index: apps/recorder/radio.c =================================================================== --- apps/recorder/radio.c (revision 16159) +++ apps/recorder/radio.c (working copy) @@ -466,13 +466,14 @@ global_settings.statusbar = true; FOR_NB_SCREENS(i) { + screens[i].setfont(FONT_TUNER); gui_textarea_clear(&screens[i]); screen_set_xmargin(&screens[i],0); } gui_syncstatusbar_draw(&statusbars,true); - fh = font_get(FONT_UI)->height; + fh = font_get(FONT_TUNER)->height; /* Adjust for font size, trying to center the information vertically */ if(fh < 10) @@ -888,7 +889,7 @@ int freq; FOR_NB_SCREENS(i) - screens[i].setfont(FONT_UI); + screens[i].setfont(FONT_TUNER); snprintf(buf, 128, curr_preset >= 0 ? "%d. %s" : " ", curr_preset + 1, presets[curr_preset].name); Index: apps/recorder/keyboard.c =================================================================== --- apps/recorder/keyboard.c (revision 16159) +++ apps/recorder/keyboard.c (working copy) @@ -372,7 +372,7 @@ } else { - pm->curfont = FONT_UI; + pm->curfont = FONT_MENU; } } @@ -398,14 +398,14 @@ /* find max width of keyboard glyphs */ for (i = 0; i < pm->nchars; i++) { - w = font_get_width(pm->font, pm->kbd_buf[i]); + w = font_get_width(pm->font, pm->kbd_buf[i], param[l].curfont); if ( w > pm->font_w ) pm->font_w = w; } /* Since we're going to be adding spaces, make sure that we check * their width too */ - w = font_get_width( pm->font, ' ' ); + w = font_get_width( pm->font, ' ', param[l].curfont ); if ( w > pm->font_w ) pm->font_w = w; } @@ -473,7 +473,7 @@ while (*utf8) { - int w = font_get_width(pm->font, ch); + int w = font_get_width(pm->font, ch, param[l].curfont); utf8 = (unsigned char*)utf8decode(utf8, &ch); if (w > text_w) @@ -765,8 +765,6 @@ switch ( button ) { case ACTION_KBD_ABORT: - FOR_NB_SCREENS(l) - screens[l].setfont(FONT_UI); #ifdef HAS_BUTTONBAR global_settings.buttonbar=buttonbar_config; Index: apps/recorder/bmp.h =================================================================== --- apps/recorder/bmp.h (revision 16159) +++ apps/recorder/bmp.h (working copy) @@ -22,21 +22,34 @@ #include "config.h" #include "lcd.h" +#define BMP_RESIZE_NONE 1 +#define BMP_RESIZE_INCREASE 2 +#define BMP_RESIZE_DECREASE 4 +#define BMP_RESIZE_IGNORE_ASPECT 8 +#define BMP_RESIZE_FILL 16 + /********************************************************************* * read_bmp_file() * * Reads a 8bit BMP file and puts the data in a 1-pixel-per-byte - * array. + * array. * Returns < 0 for error, or number of bytes used from the bitmap buffer * **********************************************/ +int read_bmp_fd (int fd, + struct bitmap *bm, + int maxsize, + int format, + int dst_maxwidth, /* = 0 */ + int dst_maxheight,/* = 0 */ + int flags); /* BMP_RESIZE_NONE */ + int read_bmp_file(const char* filename, struct bitmap *bm, int maxsize, - int format); + int format, + int dst_maxwidth, /* = 0 */ + int dst_maxheight,/* = 0 */ + int flags); /* BMP_RESIZE_NONE */ -int read_bmp_fd(int fd, - struct bitmap *bm, - int maxsize, - int format); #endif Index: apps/recorder/recording.c =================================================================== --- apps/recorder/recording.c (revision 16159) +++ apps/recorder/recording.c (working copy) @@ -949,7 +949,7 @@ FOR_NB_SCREENS(i) { - screens[i].setfont(FONT_SYSFIXED); + screens[i].setfont(FONT_RECORD); screens[i].getstringsize("M", &w, &h); screens[i].setmargins(global_settings.cursor_style ? 0 : w, 8); filename_offset[i] = ((screens[i].height >= 80) ? 1 : 0); @@ -1355,7 +1355,7 @@ FOR_NB_SCREENS(i) { - screens[i].setfont(FONT_SYSFIXED); + screens[i].setfont(FONT_RECORD); screens[i].setmargins( global_settings.cursor_style ? 0 : w, 8); } @@ -1435,7 +1435,7 @@ #endif FOR_NB_SCREENS(i) - screens[i].setfont(FONT_SYSFIXED); + screens[i].setfont(FONT_RECORD); seconds = audio_recorded_time() / HZ; @@ -1942,9 +1942,6 @@ rec_status &= ~RCSTAT_IN_RECSCREEN; sound_settings_apply(); - FOR_NB_SCREENS(i) - screens[i].setfont(FONT_UI); - /* if the directory was created or recording happened, make sure the browser is updated */ if (rec_status & (RCSTAT_CREATED_DIRECTORY | RCSTAT_HAVE_RECORDED)) @@ -1981,7 +1978,7 @@ FOR_NB_SCREENS(i) { - screens[i].setfont(FONT_SYSFIXED); + screens[i].setfont(FONT_RECORD); screens[i].getstringsize("A",&w,&h); } @@ -2094,8 +2091,6 @@ set_gain(); settings_save(); - FOR_NB_SCREENS(i) - screens[i].setfont(FONT_UI); return false; } @@ -2116,7 +2111,7 @@ FOR_NB_SCREENS(i) { - screens[i].setfont(FONT_SYSFIXED); + screens[i].setfont(FONT_RECORD); screens[i].getstringsize("A",&w,&h); } @@ -2191,8 +2186,6 @@ set_gain(); settings_save(); - FOR_NB_SCREENS(i) - screens[i].setfont(FONT_UI); return false; } Index: apps/recorder/peakmeter.c =================================================================== --- apps/recorder/peakmeter.c (revision 16159) +++ apps/recorder/peakmeter.c (working copy) @@ -919,14 +919,14 @@ void peak_meter_screen(struct screen *display, int x, int y, int height) { peak_meter_draw(display, &scales[display->screen_type], x, y, - display->width - x, height); + display->getwidth() - x, height); } /** * Draws a peak meter in the specified size at the specified position. * @param int x - The x coordinate. - * Make sure that 0 <= x and x + width < display->width + * Make sure that 0 <= x and x + width < display->getwidth() * @param int y - The y coordinate. - * Make sure that 0 <= y and y + height < display->height + * Make sure that 0 <= y and y + height < display->getheight() * @param int width - The width of the peak meter. Note that for display * of clips a 3 pixel wide area is used -> * width > 3 @@ -1105,7 +1105,7 @@ start_trigx = x+peak_meter_scale_value(trig_strt_threshold,meterwidth); display->vline(start_trigx, ycenter - 2, ycenter); start_trigx ++; - if (start_trigx < display->width ) display->drawpixel(start_trigx, ycenter - 1); + if (start_trigx < display->getwidth() ) display->drawpixel(start_trigx, ycenter - 1); stop_trigx = x + peak_meter_scale_value(trig_stp_threshold,meterwidth); display->vline(stop_trigx, ycenter - 2, ycenter); Index: apps/tree.c =================================================================== --- apps/tree.c (revision 16159) +++ apps/tree.c (working copy) @@ -311,8 +311,7 @@ gui_synclist_set_voice_callback(&tree_lists, tree_voice_cb); gui_synclist_set_icon_callback(&tree_lists, &tree_get_fileicon); #ifdef HAVE_LCD_COLOR - gui_list_set_color_callback(&tree_lists, - &tree_get_filecolor); + gui_synclist_set_color_callback(&tree_lists, &tree_get_filecolor); #endif } @@ -994,7 +993,9 @@ pltick = current_tick; snprintf(filename, sizeof filename, "%s.m3u8", - tc.currdir[1] ? tc.currdir : "/root"); + tc.currdir[1] ? tc.currdir : + playlist_check_dir(DEFAULT_PLAYLIST_DIR)==0 ? + DEFAULT_PLAYLIST_DIR"/root" : "/root/"); FOR_NB_SCREENS(i) { gui_textarea_clear(&screens[i]); Index: apps/plugins/mp3_encoder.c =================================================================== --- apps/plugins/mp3_encoder.c (revision 16159) +++ apps/plugins/mp3_encoder.c (working copy) @@ -2409,7 +2409,7 @@ rb->sleep(5*HZ); } - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); #ifdef HAVE_ADJUSTABLE_CPU_FREQ rb->cpu_boost(false); #endif Index: apps/plugins/xobox.c =================================================================== --- apps/plugins/xobox.c (revision 16159) +++ apps/plugins/xobox.c (working copy) @@ -947,7 +947,7 @@ /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(rb); /* backlight control in lib/helper.c */ - rb->lcd_setfont (FONT_UI); + rb->lcd_setfont (FONT_PLUGIN); return ret; } Index: apps/plugins/zxbox/zxbox_keyb.c =================================================================== --- apps/plugins/zxbox/zxbox_keyb.c (revision 16159) +++ apps/plugins/zxbox/zxbox_keyb.c (working copy) @@ -198,13 +198,13 @@ rb->screens[l]->setfont(param[l].curfont); /* find max width of keyboard glyphs */ for (i=0; ifont_get_width(param[l].font, param[l].kbd_buf[i]); + w = rb->font_get_width(param[l].font, param[l].kbd_buf[i], FONT_PLUGIN); if (w > param[l].font_w) param[l].font_w = w; } /* Since we're going to be adding spaces, make sure that we check * their width too */ - w = rb->font_get_width( param[l].font, ' ' ); + w = rb->font_get_width( param[l].font, ' ', FONT_PLUGIN ); if( w > param[l].font_w ) param[l].font_w = w; } @@ -256,7 +256,7 @@ text_w = param[l].font_w; while (*utf8) { utf8 = (unsigned char*)rb->utf8decode(utf8, &ch); - w = rb->font_get_width(param[l].font, ch); + w = rb->font_get_width(param[l].font, ch, FONT_SYSFIXED); if (w > text_w) text_w = w; } @@ -387,7 +387,7 @@ case KBD_ABORT: FOR_NB_SCREENS(l) - rb->screens[l]->setfont(FONT_UI); + rb->screens[l]->setfont(FONT_SYSFIXED); return -1; break; @@ -506,6 +506,6 @@ } } FOR_NB_SCREENS(l) - rb->screens[l]->setfont(FONT_UI); + rb->screens[l]->setfont(FONT_SYSFIXED); return 0; } Index: apps/plugins/rockblox.c =================================================================== --- apps/plugins/rockblox.c (revision 16159) +++ apps/plugins/rockblox.c (working copy) @@ -1112,7 +1112,7 @@ ret = rockblox_loop (); #ifdef HAVE_LCD_BITMAP - rb->lcd_setfont (FONT_UI); + rb->lcd_setfont (FONT_BROWSER); #else pgfx_release(); #endif Index: apps/plugins/mpegplayer/mpegplayer.c =================================================================== --- apps/plugins/mpegplayer/mpegplayer.c (revision 16159) +++ apps/plugins/mpegplayer/mpegplayer.c (working copy) @@ -482,14 +482,14 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = rb->font_get_width(pf, ch); + width = rb->font_get_width(pf, ch, FONT_PLUGIN); if (ofs > width) { ofs -= width; continue; } - bits = rb->font_get_bits(pf, ch); + bits = rb->font_get_bits(pf, ch, FONT_PLUGIN); draw_oriented_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: apps/plugins/pictureflow.c =================================================================== --- apps/plugins/pictureflow.c (revision 16159) +++ apps/plugins/pictureflow.c (working copy) @@ -175,14 +175,20 @@ {pictureflow_logo, BMPWIDTH_pictureflow_logo, BMPHEIGHT_pictureflow_logo}, }; +enum show_album_name_values { album_name_hide = 0, album_name_bottom , album_name_top }; + struct config_data { long avg_album_width; int spacing_between_slides; int extra_spacing_for_center_slide; int show_slides; int zoom; + enum show_album_name_values show_album_name; }; +const int track_list_offset = ((LCD_HEIGHT > 100) ? 30 : 20); /* make the moving of the tracklist due to the album name moving more usable on small LCDs */ + + /** below we allocate the memory we want to use **/ static fb_data *buffer; /* for now it always points to the lcd framebuffer */ @@ -606,7 +612,7 @@ input_bmp.data = (char *)input_bmp_buffer; ret = rb->read_bmp_file(tmp_path_name, &input_bmp, sizeof(fb_data)*MAX_IMG_WIDTH*MAX_IMG_HEIGHT, - FORMAT_NATIVE); + FORMAT_NATIVE,PREFERRED_IMG_WIDTH, PREFERRED_IMG_HEIGHT,0); if (ret <= 0) { rb->splash(HZ, "Could not read bmp"); continue; /* skip missing/broken files */ @@ -1529,22 +1535,39 @@ return true; } +/** + Shows the album name setting menu +*/ +int album_name_menu(void) { + void reset_track_list(void); + int selection = config.show_album_name; + MENUITEM_STRINGLIST(album_name_menu,"Show album title",NULL, + "Hide album title", "Show at the bottom", "Show at the top"); + rb->do_menu(&album_name_menu,&selection); + config.show_album_name = selection; + reset_track_list(); + return GO_TO_PREVIOUS; +} + + /** Shows the settings menu */ int settings_menu(void) { int selection = 0; + void reset_track_list(void); MENUITEM_STRINGLIST(settings_menu, "PictureFlow Settings", NULL, "Show FPS", "Spacing", "Center margin", "Number of slides", "Zoom", - "Rebuild cache"); + "Show album titles", "Rebuild cache"); do { selection=rb->do_menu(&settings_menu,&selection); switch(selection) { case 0: rb->set_bool("Show FPS", &show_fps); + reset_track_list(); break; case 1: @@ -1571,13 +1594,17 @@ break; case 4: - rb->set_int("Number of slides", "", 1, &(config.zoom), + rb->set_int("Zoom", "", 1, &(config.zoom), NULL, 1, 10, 300, NULL ); recalc_table(); reset_slides(); break; - case 5: + album_name_menu(); + recalc_table(); + reset_slides(); + break; + case 6: rb->remove(CACHE_PREFIX "/ready"); rb->remove(EMPTY_SLIDE); rb->splash(HZ, "Cache will be rebuilt on next restart"); @@ -1635,6 +1662,7 @@ config.show_slides = 3; config.avg_album_width = 0; config.zoom = 100; + config.show_album_name = album_name_bottom; } /** @@ -1743,7 +1771,17 @@ const char* albumtxt = get_album_name(center_index); rb->lcd_getstringsize(albumtxt, &albumtxt_w, &albumtxt_h); const int height = LCD_HEIGHT-albumtxt_h-10; - track_list_visible_entries = fmin( height/albumtxt_h , track_count ); + switch (config.show_album_name) { + case album_name_hide: + track_list_visible_entries = fmin((LCD_HEIGHT-(show_fps ? + track_list_offset : 0))/albumtxt_h, track_count); + break; + case album_name_bottom: + case album_name_top: + track_list_visible_entries = fmin((height-(show_fps ? + track_list_offset : 0))/albumtxt_h, track_count); + break; + } start_index_track_list = 0; track_scroll_index = 0; track_scroll_dir = 1; @@ -1761,7 +1799,10 @@ reset_track_list(); } static int titletxt_w, titletxt_h, titletxt_y, titletxt_x, i, color; - titletxt_y = 0; + /* adjust track list a bit downwards whem album title is set to be shown at the top + OR fps show fps is enabled */ + titletxt_y = ((config.show_album_name == album_name_top || show_fps) ? + track_list_offset : 0); int track_i; for (i=0; i < track_list_visible_entries; i++) { track_i = i+start_index_track_list; @@ -1844,8 +1885,8 @@ albumtxt_dir = -1; prev_center_index = center_index; } - albumtxt_y = LCD_HEIGHT-albumtxt_h-10; - + albumtxt_y = ((config.show_album_name == album_name_bottom) ? + (LCD_HEIGHT-albumtxt_h-10) : 10); if (albumtxt_w > LCD_WIDTH ) { rb->lcd_putsxy(albumtxt_x, albumtxt_y , albumtxt); if ( pf_state == pf_idle || pf_state == pf_show_tracks ) { @@ -1945,6 +1986,7 @@ reset_slides(); char fpstxt[10]; + int fpstxt_w, fpstxt_h; int button; #ifdef HAVE_ADJUSTABLE_CPU_FREQ @@ -1991,6 +2033,7 @@ break; } + rb->lcd_getstringsize(fpstxt, &fpstxt_w, &fpstxt_h); /* Calculate FPS */ if (current_update - last_update > update_interval) { fps = frames * HZ / (current_update - last_update); @@ -2002,10 +2045,14 @@ if (show_fps) { rb->lcd_set_foreground(LCD_RGBPACK(255, 0, 0)); rb->snprintf(fpstxt, sizeof(fpstxt), "FPS: %d", fps); - rb->lcd_putsxy(0, 0, fpstxt); + /* move fps text to the bottom, when the album + titles are set to be shown at the top */ + rb->lcd_putsxy(0, (config.show_album_name == album_name_top ? + (LCD_HEIGHT-fpstxt_h) : 0), fpstxt); } - draw_album_text(); + if (config.show_album_name) /* Don't draw when album names are hidden */ + draw_album_text(); /* Copy offscreen buffer to LCD and give time to other threads */ Index: apps/plugins/bounce.c =================================================================== --- apps/plugins/bounce.c (revision 16159) +++ apps/plugins/bounce.c (working copy) @@ -538,7 +538,7 @@ } while(h > 0); rb->lcd_set_drawmode(DRMODE_SOLID); - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); return (h == 0) ? PLUGIN_OK : PLUGIN_USB_CONNECTED; } Index: apps/plugins/lib/bmp.h =================================================================== --- apps/plugins/lib/bmp.h (revision 16159) +++ apps/plugins/lib/bmp.h (working copy) @@ -21,6 +21,7 @@ #include "lcd.h" #include "plugin.h" +#include "recorder/bmp.h" /** * Save bitmap to file Index: apps/plugins/jpeg.c =================================================================== --- apps/plugins/jpeg.c (revision 16159) +++ apps/plugins/jpeg.c (working copy) @@ -3041,7 +3041,7 @@ rb->lcd_puts(0,3,"Left/Right: Skip File."); rb->lcd_puts(0,4,"Off: Quit."); rb->lcd_update(); - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); rb->button_clear_queue(); Index: apps/plugins/spacerocks.c =================================================================== --- apps/plugins/spacerocks.c (revision 16159) +++ apps/plugins/spacerocks.c (working copy) @@ -1960,7 +1960,7 @@ iohiscore(); retval = start_game(); iohiscore(); - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(rb); /* backlight control in lib/helper.c */ return retval; Index: apps/plugins/brickmania.c =================================================================== --- apps/plugins/brickmania.c (revision 16159) +++ apps/plugins/brickmania.c (working copy) @@ -1975,7 +1975,7 @@ configfile_save(HIGH_SCORE,config,1,0); /* Restore user's original backlight setting */ - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); /* Turn on backlight timeout (revert to settings) */ backlight_use_settings(rb); /* backlight control in lib/helper.c */ Index: apps/plugins/viewer.c =================================================================== --- apps/plugins/viewer.c (revision 16159) +++ apps/plugins/viewer.c (working copy) @@ -320,7 +320,7 @@ ch = ' '; #ifdef HAVE_LCD_BITMAP - return rb->font_get_width(pf, ch); + return rb->font_get_width(pf, ch, FONT_BROWSER); #else return 1; #endif @@ -1029,9 +1029,10 @@ static bool viewer_init(void) { #ifdef HAVE_LCD_BITMAP + // MWE + rb->lcd_setfont(FONT_BROWSER); + pf = rb->font_get(FONT_BROWSER); - pf = rb->font_get(FONT_UI); - display_lines = LCD_HEIGHT / pf->height; draw_columns = display_columns = LCD_WIDTH; #else Index: apps/plugins/stopwatch.c =================================================================== --- apps/plugins/stopwatch.c (revision 16159) +++ apps/plugins/stopwatch.c (working copy) @@ -195,7 +195,7 @@ #ifdef HAVE_LCD_BITMAP int h; - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); rb->lcd_getstringsize("M", NULL, &h); lines = (LCD_HEIGHT / h) - (LAP_Y); #else Index: apps/plugins/bubbles.c =================================================================== --- apps/plugins/bubbles.c (revision 16159) +++ apps/plugins/bubbles.c (working copy) @@ -2664,7 +2664,7 @@ break; case BB_USB: - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); return PLUGIN_USB_CONNECTED; case BB_QUIT: @@ -2680,7 +2680,7 @@ } } - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); return PLUGIN_OK; } Index: apps/plugins/robotfindskitten.c =================================================================== --- apps/plugins/robotfindskitten.c (revision 16159) +++ apps/plugins/robotfindskitten.c (working copy) @@ -629,6 +629,6 @@ play_game(); - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); return PLUGIN_OK; } Index: apps/plugins/jewels.c =================================================================== --- apps/plugins/jewels.c (revision 16159) +++ apps/plugins/jewels.c (working copy) @@ -1832,7 +1832,7 @@ break; case BJ_USB: - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); return PLUGIN_USB_CONNECTED; case BJ_QUIT: @@ -1862,7 +1862,7 @@ } } - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); return PLUGIN_OK; } Index: apps/plugins/rockpaint.c =================================================================== --- apps/plugins/rockpaint.c (revision 16159) +++ apps/plugins/rockpaint.c (working copy) @@ -402,10 +402,13 @@ { unsigned short ch; unsigned short *ucs; + int curfont=FONT_PLUGIN; - struct font *pf = rb->font_get( FONT_UI ); - if( !pf ) pf = rb->font_get( FONT_SYSFIXED ); - + struct font *pf = rb->font_get( FONT_PLUGIN ); + if( !pf ) { + pf = rb->font_get( FONT_SYSFIXED ); + curfont=FONT_SYSFIXED; + } ucs = rb->bidi_l2v( str, 1 ); while( (ch = *ucs++) != 0 && x < buf_width ) @@ -414,7 +417,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = rb->font_get_width( pf, ch ); + width = rb->font_get_width( pf, ch, curfont ); if( ofs > width ) { @@ -422,7 +425,7 @@ continue; } - bits = rb->font_get_bits( pf, ch ); + bits = rb->font_get_bits( pf, ch, curfont ); buffer_mono_bitmap_part( buf, buf_width, buf_height, bits, ofs, 0, width, x, y, width - ofs, pf->height); @@ -843,7 +846,7 @@ rb->snprintf( old_font, MAX_PATH, FONT_DIR "/%s.fnt", - rb->global_settings->font_file ); + rb->global_settings->browserfont ); while( 1 ) { @@ -897,8 +900,8 @@ continue; rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", de->d_name ); - rb->font_load( bbuf ); - rb->font_getstringsize( de->d_name, &fw, &fh, FONT_UI ); + rb->font_load( bbuf, FONT_PLUGIN ); + rb->font_getstringsize( de->d_name, &fw, &fh, FONT_PLUGIN ); if( nvih > 0 ) { nvih -= fh; @@ -932,12 +935,12 @@ { rb->snprintf( bbuf, MAX_PATH, FONT_DIR "/%s", de->d_name ); - rb->font_load( bbuf ); - rb->font_getstringsize( de->d_name, NULL, &fh, FONT_UI ); + rb->font_load( bbuf, FONT_PLUGIN ); + rb->font_getstringsize( de->d_name, NULL, &fh, FONT_PLUGIN ); nvih = fh; } } - rb->font_load( old_font ); + rb->font_load( old_font, FONT_PLUGIN ); rb->closedir( d ); } @@ -1083,7 +1086,7 @@ rb->lcd_putsxy( left + 117, top + 60, str ); rb->snprintf( str, 6, "%d", blue ); rb->lcd_putsxy( left + 117, top + 70, str ); - rb->lcd_setfont( FONT_UI ); + rb->lcd_setfont( FONT_PLUGIN ); #define CURSOR( l ) \ rb->lcd_bitmap_transparent_part( rockpaint_hsvrgb, 1, 1, 16, left+l+1, top+20, 6, 58 ); \ @@ -1479,7 +1482,7 @@ buffer.text.text[0] = '\0'; rb->snprintf( buffer.text.old_font, MAX_PATH, FONT_DIR "/%s.fnt", - rb->global_settings->font_file ); + rb->global_settings->browserfont ); while( 1 ) { int m = TEXT_MENU_TEXT; @@ -1493,7 +1496,7 @@ case TEXT_MENU_FONT: if( browse_fonts( buffer.text.font, MAX_PATH ) ) { - rb->font_load( buffer.text.font ); + rb->font_load( buffer.text.font, FONT_PLUGIN ); } break; @@ -1545,7 +1548,7 @@ buffer.text.text ); case TEXT_MENU_CANCEL: restore_screen(); - rb->font_load( buffer.text.old_font ); + rb->font_load( buffer.text.old_font, FONT_PLUGIN ); return; } } @@ -2305,7 +2308,7 @@ rb->lcd_setfont( FONT_SYSFIXED ); rb->lcd_putsxy( TB_MENU_LEFT, TOP+TB_MENU_TOP, "Menu" ); - rb->lcd_setfont( FONT_UI ); + rb->lcd_setfont( FONT_PLUGIN ); #undef TOP if( update ) rb->lcd_update(); @@ -2916,7 +2919,9 @@ bm.data = (char*)save_buffer; ret = rb->read_bmp_file( file, &bm, ROWS*COLS*sizeof( fb_data ), - FORMAT_NATIVE ); + FORMAT_NATIVE, + COLS, ROWS, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); if((bm.width > COLS ) || ( bm.height > ROWS )) return -1; Index: apps/plugins/credits.c =================================================================== --- apps/plugins/credits.c (revision 16159) +++ apps/plugins/credits.c (working copy) @@ -163,7 +163,7 @@ /* control if scrolling is automatic (with animation) or manual */ bool manual_scroll = false; - rb->lcd_setfont(FONT_UI); + rb->lcd_setfont(FONT_PLUGIN); rb->lcd_clear_display(); rb->lcd_update(); Index: apps/settings.c =================================================================== --- apps/settings.c (revision 16159) +++ apps/settings.c (working copy) @@ -263,6 +263,32 @@ return false; } +/** reset some settings when loading a wps file + * to keep backward compatibility **/ +void theme_settings_reset(void) +{ + /* multifont settings */ + global_settings.font_file[0] = '\0'; + global_settings.browserfont[0] = '\0'; + global_settings.wpsfont[0] = '\0'; + global_settings.menufont[0] = '\0'; +#ifdef CONFIG_TUNER + global_settings.tunerfont[0] = '\0'; +#endif +#ifdef HAVE_RECORDING + global_settings.recordfont[0] = '\0'; +#endif + /* reset rpws setting */ +#ifdef HAVE_REMOTE_LCD + global_settings.rwps_file[0]='\0'; +#endif + /* reset color settings */ +#ifdef HAVE_LCD_COLOR + global_settings.fg_color=LCD_DEFAULT_FG; + global_settings.bg_color=LCD_DEFAULT_BG; +#endif +} + bool settings_load_config(const char* file, bool apply) { int fd; @@ -274,6 +300,11 @@ if (fd < 0) return false; + /* if loading a theme reset some settings for backward compatibility */ + if(strncmp(file, THEME_DIR, strlen(THEME_DIR))==0){ + theme_settings_reset(); + } + while (read_line(fd, line, sizeof line) > 0) { if (!settings_parseline(line, &name, &value)) @@ -732,6 +763,8 @@ #if CONFIG_CODEC == SWCODEC int i; #endif + /** backward comp **/ + bool useMultifont=false; DEBUGF( "settings_apply()\n" ); sound_settings_apply(); @@ -816,7 +849,7 @@ global_settings.wps_file[0] != 0xff ) { snprintf(buf, sizeof buf, WPS_DIR "/%s.wps", global_settings.wps_file); - wps_data_load(gui_wps[0].data, buf, true); + wps_data_load(gui_wps[0].data, &screens[0], buf, true); } else { @@ -853,7 +886,7 @@ if ( global_settings.rwps_file[0]) { snprintf(buf, sizeof buf, WPS_DIR "/%s.rwps", global_settings.rwps_file); - wps_data_load(gui_wps[1].data, buf, true); + wps_data_load(gui_wps[1].data, &screens[1], buf, true); } else { @@ -863,14 +896,154 @@ #endif #ifdef HAVE_LCD_BITMAP - if ( global_settings.font_file[0]) { + /* Load all the fonts */ + if ( global_settings.browserfont[0] && + global_settings.browserfont[0] != 0xff ) { + useMultifont=true; + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.browserfont); + font_load(buf, FONT_BROWSER); + } + else + font_reset(FONT_BROWSER); + + if ( global_settings.wpsfont[0] && + global_settings.wpsfont[0] != 0xff ) { + useMultifont=true; + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.wpsfont); + font_load(buf, FONT_WPS); + } + else + font_reset(FONT_WPS); + + if ( global_settings.menufont[0] && + global_settings.menufont[0] != 0xff ) { + useMultifont=true; + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.menufont); + font_load(buf, FONT_MENU); + } + else + font_reset(FONT_MENU); + +#ifdef CONFIG_TUNER + if ( global_settings.tunerfont[0] && + global_settings.tunerfont[0] != 0xff ) { + useMultifont=true; + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.tunerfont); + font_load(buf, FONT_TUNER); + } + else + font_reset(FONT_TUNER); +#endif /* CONFIG_TUNER */ + +#ifdef HAVE_RECORDING + if ( global_settings.recordfont[0] && + global_settings.recordfont[0] != 0xff ) { + useMultifont=true; + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.recordfont); + font_load(buf, FONT_RECORD); + } + else + font_reset(FONT_RECORD); +#endif /* HAVE_RECORDING */ + + /** backward comp **/ + if(!useMultifont){ + if ( global_settings.font_file[0] && + global_settings.font_file[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.font_file); + font_load(buf, FONT_BROWSER); + font_load(buf, FONT_WPS); + font_load(buf, FONT_MENU); +#ifdef CONFIG_TUNER + font_load(buf, FONT_TUNER); +#endif +#ifdef HAVE_RECORDING + font_load(buf, FONT_RECORD); +#endif + } + else { + font_reset(FONT_BROWSER); + font_reset(FONT_WPS); + font_reset(FONT_MENU); +#ifdef CONFIG_TUNER + font_reset(FONT_TUNER); +#endif +#ifdef HAVE_RECORDING + font_reset(FONT_RECORD); +#endif + } + } + + /* Load all user fonts */ + if ( global_settings.userfont1[0] && + global_settings.userfont1[0] != 0xff ) { snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", - global_settings.font_file); - font_load(buf); + global_settings.userfont1); + font_load(buf, FONT_USER1); } else - font_reset(); + font_reset(FONT_USER1); + if ( global_settings.userfont2[0] && + global_settings.userfont2[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont2); + font_load(buf, FONT_USER2); + } + else + font_reset(FONT_USER2); + + if ( global_settings.userfont3[0] && + global_settings.userfont3[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont3); + font_load(buf, FONT_USER3); + } + else + font_reset(FONT_USER3); + + if ( global_settings.userfont4[0] && + global_settings.userfont4[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont4); + font_load(buf, FONT_USER4); + } + else + font_reset(FONT_USER4); + + if ( global_settings.userfont5[0] && + global_settings.userfont5[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont5); + font_load(buf, FONT_USER5); + } + else + font_reset(FONT_USER5); + + if ( global_settings.userfont6[0] && + global_settings.userfont6[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont6); + font_load(buf, FONT_USER6); + } + else + font_reset(FONT_USER6); + + if ( global_settings.userfont7[0] && + global_settings.userfont7[0] != 0xff ) { + snprintf(buf, sizeof buf, FONT_DIR "/%s.fnt", + global_settings.userfont7); + font_load(buf, FONT_USER7); + } + else + font_reset(FONT_USER7); + if ( global_settings.kbd_file[0]) { snprintf(buf, sizeof buf, ROCKBOX_DIR "/%s.kbd", global_settings.kbd_file); @@ -945,7 +1118,7 @@ if (global_settings.colors_file) read_color_theme_file(); #endif - + list_init_viewports(); } @@ -983,6 +1156,13 @@ #if defined (HAVE_RECORDING) && CONFIG_CODEC == SWCODEC enc_global_settings_reset(); #endif + global_settings.userfont1[0] = '\0'; + global_settings.userfont2[0] = '\0'; + global_settings.userfont3[0] = '\0'; + global_settings.userfont4[0] = '\0'; + global_settings.userfont5[0] = '\0'; + global_settings.userfont6[0] = '\0'; + global_settings.userfont7[0] = '\0'; } /** Changing setting values **/ @@ -1057,14 +1237,15 @@ void set_file(char* filename, char* setting, int maxlen) { - char* fptr = strrchr(filename,'/'); + char *fptr = strrchr(filename,'/'); int len; int extlen = 0; - char* ptr; + char *ptr, *oldptr; if (!fptr) return; + oldptr = fptr; *fptr = 0; fptr++; Index: apps/gui/buttonbar.c =================================================================== --- apps/gui/buttonbar.c (revision 16159) +++ apps/gui/buttonbar.c (working copy) @@ -116,7 +116,8 @@ gui_buttonbar_draw_button(buttonbar, i); display->update_rect(0, display->height - BUTTONBAR_HEIGHT, display->width, BUTTONBAR_HEIGHT); - display->setfont(FONT_UI); + // MWE ? + display->setfont(FONT_BROWSER); } bool gui_buttonbar_isset(struct gui_buttonbar * buttonbar) Index: apps/gui/gwps-common.c =================================================================== --- apps/gui/gwps-common.c (revision 16159) +++ apps/gui/gwps-common.c (working copy) @@ -282,6 +282,7 @@ bool gui_wps_display(void) { int i; + if (!wps_state.id3 && !(audio_status() & AUDIO_STATUS_PLAY)) { global_status.resume_index = -1; @@ -295,6 +296,19 @@ { FOR_NB_SCREENS(i) { + /* Update the values in the first (default) viewport - in case the user + has modified the statusbar or colour settings */ +#ifdef HAVE_LCD_BITMAP + gui_wps[i].data->viewports[0].vp.ymargin = gui_wps[i].display->getymargin(); +#if LCD_DEPTH > 1 + if (gui_wps[i].display->depth > 1) + { + gui_wps[i].data->viewports[0].vp.fg_pattern = gui_wps[i].display->get_foreground(); + gui_wps[i].data->viewports[0].vp.bg_pattern = gui_wps[i].display->get_background(); + } +#endif +#endif + gui_wps[i].display->clear_display(); if (!gui_wps[i].data->wps_loaded) { if ( !gui_wps[i].data->num_tokens ) { @@ -306,6 +320,7 @@ unload_wps_backdrop(); #endif wps_data_load(gui_wps[i].data, + gui_wps[i].display, "%s%?it<%?in<%in. |>%it|%fn>\n" "%s%?ia<%ia|%?d2<%d2|(root)>>\n" "%s%?id<%id|%?d1<%d1|(root)>> %?iy<(%iy)|>\n" @@ -316,6 +331,7 @@ "%pm\n", false); #else wps_data_load(gui_wps[i].data, + gui_wps[i].display, "%s%pp/%pe: %?it<%it|%fn> - %?ia<%ia|%d2> - %?id<%id|%d1>\n" "%pc%?ps<*|/>%pt\n", false); #endif @@ -328,6 +344,7 @@ unload_remote_wps_backdrop(); #endif wps_data_load(gui_wps[i].data, + gui_wps[i].display, "%s%?ia<%ia|%?d2<%d2|(root)>>\n" "%s%?it<%?in<%in. |>%it|%fn>\n" "%al%pc/%pt%ar[%pp:%pe]\n" @@ -448,7 +465,7 @@ struct wps_data *data = gwps->data; struct screen *display = gwps->display; struct wps_state *state = gwps->state; - int h = font_get(FONT_UI)->height; + int h = font_get(FONT_WPS)->height; int sb_y; if (data->progress_top < 0) @@ -459,7 +476,7 @@ sb_y = data->progress_top; if (!data->progress_end) - data->progress_end=display->width; + data->progress_end=display->getwidth(); if (gwps->data->progressbar.have_bitmap_pb) gui_bitmap_scrollbar_draw(display, data->progressbar.bm, @@ -1449,7 +1466,7 @@ The return value indicates whether the line needs to be updated. */ static bool get_line(struct gui_wps *gwps, - int line, int subline, + int v, int line, int subline, struct align_pos *align, char *linebuf, int linebuf_size) @@ -1477,8 +1494,8 @@ #endif /* Process all tokens of the desired subline */ - last_token_idx = wps_last_token_index(data, line, subline); - for (i = wps_first_token_index(data, line, subline); + last_token_idx = wps_last_token_index(data, v, line, subline); + for (i = wps_first_token_index(data, v, line, subline); i <= last_token_idx; i++) { switch(data->tokens[i].type) @@ -1577,16 +1594,16 @@ return update; } -static void get_subline_timeout(struct gui_wps *gwps, int line, int subline) +static void get_subline_timeout(struct gui_wps *gwps, int v, int line, int subline) { struct wps_data *data = gwps->data; int i; - int subline_idx = wps_subline_index(data, line, subline); - int last_token_idx = wps_last_token_index(data, line, subline); + int subline_idx = wps_subline_index(data, v, line, subline); + int last_token_idx = wps_last_token_index(data, v, line, subline); data->sublines[subline_idx].time_mult = DEFAULT_SUBLINE_TIME_MULTIPLIER; - for (i = wps_first_token_index(data, line, subline); + for (i = wps_first_token_index(data, v, line, subline); i <= last_token_idx; i++) { switch(data->tokens[i].type) @@ -1614,7 +1631,7 @@ /* Calculates which subline should be displayed for the specified line Returns true iff the subline must be refreshed */ -static bool update_curr_subline(struct gui_wps *gwps, int line) +static bool update_curr_subline(struct gui_wps *gwps, int v, int line) { struct wps_data *data = gwps->data; @@ -1623,13 +1640,13 @@ bool new_subline_refresh; bool only_one_subline; - num_sublines = data->lines[line].num_sublines; - reset_subline = (data->lines[line].curr_subline == SUBLINE_RESET); + num_sublines = data->viewports[v].lines[line].num_sublines; + reset_subline = (data->viewports[v].lines[line].curr_subline == SUBLINE_RESET); new_subline_refresh = false; only_one_subline = false; /* if time to advance to next sub-line */ - if (TIME_AFTER(current_tick, data->lines[line].subline_expire_time - 1) || + if (TIME_AFTER(current_tick, data->viewports[v].lines[line].subline_expire_time - 1) || reset_subline) { /* search all sublines until the next subline with time > 0 @@ -1637,46 +1654,46 @@ if (reset_subline) search_start = 0; else - search_start = data->lines[line].curr_subline; + search_start = data->viewports[v].lines[line].curr_subline; for (search = 0; search < num_sublines; search++) { - data->lines[line].curr_subline++; + data->viewports[v].lines[line].curr_subline++; /* wrap around if beyond last defined subline or WPS_MAX_SUBLINES */ - if (data->lines[line].curr_subline == num_sublines) + if (data->viewports[v].lines[line].curr_subline == num_sublines) { - if (data->lines[line].curr_subline == 1) + if (data->viewports[v].lines[line].curr_subline == 1) only_one_subline = true; - data->lines[line].curr_subline = 0; + data->viewports[v].lines[line].curr_subline = 0; } /* if back where we started after search or only one subline is defined on the line */ if (((search > 0) && - (data->lines[line].curr_subline == search_start)) || + (data->viewports[v].lines[line].curr_subline == search_start)) || only_one_subline) { /* no other subline with a time > 0 exists */ - data->lines[line].subline_expire_time = (reset_subline ? + data->viewports[v].lines[line].subline_expire_time = (reset_subline ? current_tick : - data->lines[line].subline_expire_time) + 100 * HZ; + data->viewports[v].lines[line].subline_expire_time) + 100 * HZ; break; } else { /* get initial time multiplier for this subline */ - get_subline_timeout(gwps, line, data->lines[line].curr_subline); + get_subline_timeout(gwps, v, line, data->viewports[v].lines[line].curr_subline); - int subline_idx = wps_subline_index(data, line, - data->lines[line].curr_subline); + int subline_idx = wps_subline_index(data, v, line, + data->viewports[v].lines[line].curr_subline); /* only use this subline if subline time > 0 */ if (data->sublines[subline_idx].time_mult > 0) { new_subline_refresh = true; - data->lines[line].subline_expire_time = (reset_subline ? - current_tick : data->lines[line].subline_expire_time) + + data->viewports[v].lines[line].subline_expire_time = (reset_subline ? + current_tick : data->viewports[v].lines[line].subline_expire_time) + BASE_SUBLINE_TIME*data->sublines[subline_idx].time_mult; break; } @@ -1697,7 +1714,6 @@ int line, bool scroll) { - int left_width = 0, left_xpos; int center_width = 0, center_xpos; int right_width = 0, right_xpos; @@ -1724,10 +1740,10 @@ } left_xpos = display->getxmargin(); - right_xpos = (display->width - right_width); - center_xpos = (display->width + left_xpos - center_width) / 2; + right_xpos = (display->getwidth() - right_width); + center_xpos = (display->getwidth() + left_xpos - center_width) / 2; - scroll_width = display->width - left_xpos; + scroll_width = display->getwidth() - left_xpos; /* Checks for overlapping strings. If needed the overlapping strings will be merged, separated by a @@ -1767,7 +1783,7 @@ format_align->right = format_align->center; /* calculate the new width and position of the merged string */ right_width = center_width + space_width + right_width; - right_xpos = (display->width - right_width); + right_xpos = (display->getwidth() - right_width); /* there is no centered string anymore */ center_width = 0; } @@ -1778,7 +1794,7 @@ format_align->right = format_align->center; /* calculate the new width and position of the string */ right_width = center_width; - right_xpos = (display->width - right_width); + right_xpos = (display->getwidth() - right_width); /* there is no centered string anymore */ center_width = 0; } @@ -1823,7 +1839,7 @@ #ifdef HAVE_LCD_BITMAP /* clear the line first */ display->set_drawmode(DRMODE_SOLID|DRMODE_INVERSEVID); - display->fillrect(left_xpos, ypos, display->width, string_height); + display->fillrect(left_xpos, ypos, display->getwidth(), string_height); display->set_drawmode(DRMODE_SOLID); #endif @@ -1862,7 +1878,7 @@ if(!gwps || !data || !state || !display) return false; - int line, i, subline_idx; + int v, line, i, subline_idx; unsigned char flags; char linebuf[MAX_PATH]; @@ -1874,6 +1890,7 @@ bool update_line, new_subline_refresh; #ifdef HAVE_LCD_BITMAP + display->setfont(FONT_WPS); gui_wps_statusbar_draw(gwps, true); /* to find out wether the peak meter is enabled we @@ -1895,9 +1912,14 @@ /* reset to first subline if refresh all flag is set */ if (refresh_mode == WPS_REFRESH_ALL) { - for (i = 0; i < data->num_lines; i++) + display->clear_display(); + + for (v = 0; v < data->num_viewports; v++) { - data->lines[i].curr_subline = SUBLINE_RESET; + for (i = 0; i < data->viewports[v].num_lines; i++) + { + data->viewports[v].lines[i].curr_subline = SUBLINE_RESET; + } } } @@ -1917,83 +1939,91 @@ state->ff_rewind_count = ffwd_offset; - for (line = 0; line < data->num_lines; line++) + for (v = 0; v < data->num_viewports; v++) { - memset(linebuf, 0, sizeof(linebuf)); - update_line = false; + display->set_viewport(&data->viewports[v].vp); - /* get current subline for the line */ - new_subline_refresh = update_curr_subline(gwps, line); + for (line = 0; line < data->viewports[v].num_lines; line++) + { + memset(linebuf, 0, sizeof(linebuf)); + update_line = false; - subline_idx = wps_subline_index(data, line, - data->lines[line].curr_subline); - flags = data->sublines[subline_idx].line_type; + /* get current subline for the line */ + new_subline_refresh = update_curr_subline(gwps, v, line); - if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode) - || new_subline_refresh) - { - /* get_line tells us if we need to update the line */ - update_line = get_line(gwps, line, data->lines[line].curr_subline, - &align, linebuf, sizeof(linebuf)); - } + subline_idx = wps_subline_index(data, v, line, + data->viewports[v].lines[line].curr_subline); + flags = data->sublines[subline_idx].line_type; + if (refresh_mode == WPS_REFRESH_ALL || (flags & refresh_mode) + || new_subline_refresh) + { + /* get_line tells us if we need to update the line */ + update_line = get_line(gwps, v, line, data->viewports[v].lines[line].curr_subline, + &align, linebuf, sizeof(linebuf)); + } + #ifdef HAVE_LCD_BITMAP - /* progressbar */ - if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) - { - /* the progressbar should be alone on its line */ - update_line = false; - draw_progressbar(gwps, line); - } + /* progressbar */ + if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) + { + /* the progressbar should be alone on its line */ + update_line = false; + draw_progressbar(gwps, line); + } - /* peakmeter */ - if (flags & refresh_mode & WPS_REFRESH_PEAK_METER) - { - /* the peakmeter should be alone on its line */ - update_line = false; + /* peakmeter */ + if (flags & refresh_mode & WPS_REFRESH_PEAK_METER) + { + /* the peakmeter should be alone on its line */ + update_line = false; - int h = font_get(FONT_UI)->height; - int peak_meter_y = display->getymargin() + line * h; + int h = font_get(FONT_WPS)->height; + int peak_meter_y = display->getymargin() + line * h; - /* The user might decide to have the peak meter in the last - line so that it is only displayed if no status bar is - visible. If so we neither want do draw nor enable the - peak meter. */ - if (peak_meter_y + h <= display->height) { - /* found a line with a peak meter -> remember that we must - enable it later */ - enable_pm = true; - peak_meter_screen(gwps->display, 0, peak_meter_y, - MIN(h, display->height - peak_meter_y)); + /* The user might decide to have the peak meter in the last + line so that it is only displayed if no status bar is + visible. If so we neither want do draw nor enable the + peak meter. */ + if (peak_meter_y + h <= display->getheight()) { + /* found a line with a peak meter -> remember that we must + enable it later */ + enable_pm = true; + peak_meter_screen(gwps->display, 0, peak_meter_y, + MIN(h, display->getheight() - peak_meter_y)); + } } - } #else /* HAVE_LCD_CHARCELL */ - /* progressbar */ - if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) - { - if (data->full_line_progressbar) - draw_player_fullbar(gwps, linebuf, sizeof(linebuf)); - else - draw_player_progress(gwps); - } + /* progressbar */ + if (flags & refresh_mode & WPS_REFRESH_PLAYER_PROGRESS) + { + if (data->full_line_progressbar) + draw_player_fullbar(gwps, linebuf, sizeof(linebuf)); + else + draw_player_progress(gwps); + } #endif - if (update_line) - { - if (flags & WPS_REFRESH_SCROLL) + if (update_line) { - /* if the line is a scrolling one we don't want to update - too often, so that it has the time to scroll */ - if ((refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) - write_line(display, &align, line, true); + if (flags & WPS_REFRESH_SCROLL) + { + /* if the line is a scrolling one we don't want to update + too often, so that it has the time to scroll */ + if ((refresh_mode & WPS_REFRESH_SCROLL) || new_subline_refresh) + write_line(display, &align, line, true); + } + else + write_line(display, &align, line, false); } - else - write_line(display, &align, line, false); } } + /* Restore the default viewport for the images */ + display->set_viewport(NULL); + #ifdef HAVE_LCD_BITMAP data->peak_meter_enabled = enable_pm; wps_display_images(gwps); Index: apps/gui/statusbar.c =================================================================== --- apps/gui/statusbar.c (revision 16159) +++ apps/gui/statusbar.c (working copy) @@ -380,6 +380,7 @@ #if LCD_DEPTH > 1 unsigned int prevfg = 0; #endif + int oldfont; #if CONFIG_CHARGING if (batt_charge_step >= 0) @@ -405,15 +406,19 @@ if (global_settings.battery_display && (percent > -1)) { #endif /* Numeric display */ + snprintf(buffer, sizeof(buffer), "%3d", percent); + + /* remember to set back if font changed */ + oldfont=display->getfont(); + display->setfont(FONT_SYSFIXED); - snprintf(buffer, sizeof(buffer), "%3d", percent); display->getstringsize(buffer, &width, &height); if (height <= STATUSBAR_HEIGHT) display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2 - width/2, STATUSBAR_Y_POS, buffer); - display->setfont(FONT_UI); - + /* set back previous font */ + display->setfont(oldfont); } else { /* draw battery */ @@ -439,10 +444,14 @@ } if (percent == -1) { + /* remember to set back if font changed */ + oldfont=display->getfont(); + display->setfont(FONT_SYSFIXED); display->putsxy(STATUSBAR_BATTERY_X_POS + STATUSBAR_BATTERY_WIDTH / 2 - 4, STATUSBAR_Y_POS, "?"); - display->setfont(FONT_UI); + /* set back previous font */ + display->setfont(oldfont); } } @@ -487,8 +496,11 @@ /* display volume level numerical? */ if (type) { + snprintf(buffer, sizeof(buffer), "%2d", volume); + /* remember to set back if font changed */ + int oldFont=display->getfont(); + display->setfont(FONT_SYSFIXED); - snprintf(buffer, sizeof(buffer), "%2d", volume); display->getstringsize(buffer, &width, &height); if (height <= STATUSBAR_HEIGHT) { @@ -496,7 +508,7 @@ + STATUSBAR_VOLUME_WIDTH / 2 - width/2, STATUSBAR_Y_POS, buffer); } - display->setfont(FONT_UI); + display->setfont(oldFont); } else { /* display volume bar */ vol = (volume - minvol) * 14 / (maxvol - minvol); @@ -600,13 +612,16 @@ else { strncpy(buffer, "--:--", sizeof buffer); } + /* remember to set back if font changed */ + int oldfont=display->getfont(); + display->setfont(FONT_SYSFIXED); display->getstringsize(buffer, &width, &height); if (height <= STATUSBAR_HEIGHT) { display->putsxy(STATUSBAR_TIME_X_END(display->width) - width, STATUSBAR_Y_POS, buffer); } - display->setfont(FONT_UI); + display->setfont(oldfont); } #endif @@ -709,6 +724,9 @@ static void gui_statusbar_icon_recording_info(struct screen * display) { + /* remember to set back if font changed */ + int oldfont=display->getfont(); + #if CONFIG_CODEC != SWCODEC char buffer[3]; int width, height; @@ -771,6 +789,7 @@ STATUSBAR_RECCHANNELS_X_POS, STATUSBAR_Y_POS, STATUSBAR_RECCHANNELS_WIDTH, STATUSBAR_HEIGHT); } + display->setfont(oldfont); } #endif /* HAVE_RECORDING */ Index: apps/gui/list.c =================================================================== --- apps/gui/list.c (revision 16159) +++ apps/gui/list.c (working copy) @@ -37,6 +37,7 @@ #include "sound.h" #include "misc.h" #include "talk.h" +#include "viewport.h" #ifdef HAVE_LCD_CHARCELLS #define SCROLL_LIMIT 1 @@ -56,12 +57,136 @@ #endif static struct gui_synclist* last_list_displayed; -#define SHOW_LIST_TITLE ((gui_list->title != NULL) && \ - (display->nb_lines > 2)) - static void gui_list_select_at_offset(struct gui_synclist * gui_list, int offset); +void list_draw(struct screen *display, struct viewport *parent, struct gui_synclist *list); +#ifdef HAVE_LCD_BITMAP +static struct viewport parent[NB_SCREENS] = +{ + [SCREEN_MAIN] = { + .x = 0, + .y = 8, + .width = LCD_WIDTH, + .height = (LCD_HEIGHT-8), + .font = FONT_MENU, + .drawmode = DRMODE_SOLID, + .xmargin = 0, + .ymargin = 0, +#if LCD_DEPTH > 1 + .fg_pattern = LCD_DEFAULT_FG, + .bg_pattern = LCD_DEFAULT_BG, +#ifdef HAVE_LCD_COLOR + .lss_pattern = LCD_DEFAULT_BG, + .lse_pattern = LCD_DEFAULT_BG, + .lst_pattern = LCD_DEFAULT_BG, +#endif +#endif + }, +#if NB_SCREENS >1 + [SCREEN_REMOTE] = { + .x = 0, + .y = 8, + .width = LCD_REMOTE_WIDTH, + .height = (LCD_REMOTE_HEIGHT-8), + .font = FONT_MENU, + .drawmode = DRMODE_SOLID, + .xmargin = 0, + .ymargin = 0, + .fg_pattern = LCD_DEFAULT_FG, + .bg_pattern = LCD_DEFAULT_BG, + } +#endif +}; +void list_init_viewports(void) +{ + struct viewport *vp; + vp = &parent[SCREEN_MAIN]; + vp->x = 0; + vp->width = LCD_WIDTH; + if (!global_settings.statusbar) + { + vp->y = 0; + vp->height = LCD_HEIGHT +#ifdef HAS_BUTTONBAR + - BUTTONBAR_HEIGHT +#endif + ; + } + else + { + vp->y = STATUSBAR_HEIGHT; + vp->height = LCD_HEIGHT - STATUSBAR_HEIGHT +#ifdef HAS_BUTTONBAR + - BUTTONBAR_HEIGHT +#endif + ; + } + vp->drawmode = STYLE_DEFAULT; + +#ifdef HAVE_LCD_COLOR + vp->fg_pattern = global_settings.fg_color; + vp->bg_pattern = global_settings.bg_color; + vp->lss_pattern = global_settings.lss_color; + vp->lse_pattern = global_settings.lse_color; + vp->lst_pattern = global_settings.lst_color; +#endif + if (global_settings.list_vp_file[0]) + { + char filename[MAX_PATH]; + snprintf(filename, MAX_PATH, "%s/%s.vp", + THEME_DIR, global_settings.list_vp_file); + viewport_load_config(filename, vp); + } +#if NB_SCREENS > 1 + vp = &parent[SCREEN_REMOTE]; + vp->x = 0; + vp->width = LCD_REMOTE_WIDTH; + if (!global_settings.statusbar) + { + vp->y = 0; + vp->height = LCD_REMOTE_HEIGHT; + } + else + { + vp->y = STATUSBAR_HEIGHT; + vp->height = LCD_REMOTE_HEIGHT - STATUSBAR_HEIGHT; + } + vp->drawmode = STYLE_DEFAULT; + if (global_settings.remote_list_vp_file[0]) + { + char filename[MAX_PATH]; + snprintf(filename, MAX_PATH, "%s/%s.vp", + THEME_DIR, global_settings.remote_list_vp_file); + viewport_load_config(filename, vp); + } +#endif +} +#else +static struct viewport parent[NB_SCREENS] = +{ + [SCREEN_MAIN] = + { + .x = 0, + .y = 0, + .width = LCD_WIDTH, + .height = LCD_HEIGHT + }, +}; +void list_init_viewports(void) +{ +} +#endif + +#ifdef HAVE_LCD_BITMAP +bool list_display_title(struct gui_synclist *list, struct viewport *vp) +{ + return list->title != NULL && viewport_get_nb_lines(vp)>2; +} +#else +#define list_display_title(l,v) false +#endif + /* * Initializes a scrolling list * - gui_list : the list structure to initialize @@ -82,7 +207,7 @@ gui_list->callback_get_item_icon = NULL; gui_list->callback_get_item_name = callback_get_item_name; gui_list->callback_speak_item = NULL; - gui_list_set_nb_items(gui_list, 0); + gui_list->nb_items = 0; gui_list->selected_item = 0; FOR_NB_SCREENS(i) { @@ -91,6 +216,7 @@ #ifdef HAVE_LCD_BITMAP gui_list->offset_position[i] = 0; #endif + gui_list->parent[i] = &parent[i]; } gui_list->limit_scroll = false; gui_list->data=data; @@ -118,8 +244,10 @@ #ifdef HAVE_LCD_BITMAP -static int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width, - int text_pos, struct screen * display) +int list_title_height(struct gui_synclist *list, struct viewport *vp); + +int gui_list_get_item_offset(struct gui_synclist * gui_list, int item_width, + int text_pos, struct screen * display, struct viewport *vp) { int item_offset; @@ -130,7 +258,7 @@ else { /* if text is smaller then view */ - if (item_width <= display->width - text_pos) + if (item_width <= vp->width - text_pos) { item_offset = 0; } @@ -138,8 +266,8 @@ { /* if text got out of view */ if (gui_list->offset_position[display->screen_type] > - item_width - (display->width - text_pos)) - item_offset = item_width - (display->width - text_pos); + item_width - (vp->width - text_pos)) + item_offset = item_width - (vp->width - text_pos); else item_offset = gui_list->offset_position[display->screen_type]; } @@ -148,341 +276,32 @@ return item_offset; } #endif - /* - * Draws the list on the attached screen - * - gui_list : the list structure - */ -static void gui_list_draw_smart(struct gui_synclist *gui_list, struct screen * display) -{ - int text_pos; - bool draw_icons = (gui_list->callback_get_item_icon != NULL && global_settings.show_icons); - bool draw_cursor; - int i; - int lines; - static int last_lines[NB_SCREENS] = {0}; -#ifdef HAVE_LCD_BITMAP - int item_offset; - int old_margin = display->getxmargin(); -#endif - int start, end; - bool partial_draw = false; - -#ifdef HAVE_LCD_BITMAP - display->setfont(FONT_UI); - gui_textarea_update_nblines(display); -#endif - /* Speed up UI by drawing the changed contents only. */ - if (gui_list == last_list_displayed - && gui_list->last_displayed_start_item[display->screen_type] == gui_list->start_item[display->screen_type] - && gui_list->selected_size == 1) - { - partial_draw = true; - } - - lines = display->nb_lines - SHOW_LIST_TITLE; - if (last_lines[display->screen_type] != lines) - { - gui_list_select_at_offset(gui_list, 0); - last_lines[display->screen_type] = lines; - } - - if (partial_draw) - { - end = gui_list->last_displayed_selected_item - gui_list->start_item[display->screen_type]; - i = gui_list->selected_item - gui_list->start_item[display->screen_type]; - if (i < end ) - { - start = i; - end++; - } - else - { - start = end; - end = i + 1; - } - } - else - { - gui_textarea_clear(display); - start = 0; - end = display->nb_lines; - gui_list->last_displayed_start_item[display->screen_type] = gui_list->start_item[display->screen_type]; - last_list_displayed = gui_list; - } - - gui_list->last_displayed_selected_item = gui_list->selected_item; - - /* position and draw the list title & icon */ - if (SHOW_LIST_TITLE && !partial_draw) - { - if (gui_list->title_icon != NOICON && draw_icons) - { - screen_put_icon(display, 0, 0, gui_list->title_icon); -#ifdef HAVE_LCD_BITMAP - text_pos = get_icon_width(display->screen_type)+2; /* pixels */ -#else - text_pos = 1; /* chars */ -#endif - } - else - { - text_pos = 0; - } - -#ifdef HAVE_LCD_BITMAP - int title_style = STYLE_DEFAULT; -#ifdef HAVE_LCD_COLOR - if (gui_list->title_color >= 0) - { - title_style |= STYLE_COLORED; - title_style |= gui_list->title_color; - } -#endif - screen_set_xmargin(display, text_pos); /* margin for title */ - item_offset = gui_list_get_item_offset(gui_list, gui_list->title_width, - text_pos, display); - if (item_offset > gui_list->title_width - (display->width - text_pos)) - display->puts_style_offset(0, 0, gui_list->title, - title_style, item_offset); - else - display->puts_scroll_style_offset(0, 0, gui_list->title, - title_style, item_offset); -#else - display->puts_scroll(text_pos, 0, gui_list->title); -#endif - } - - /* Adjust the position of icon, cursor, text for the list */ -#ifdef HAVE_LCD_BITMAP - gui_textarea_update_nblines(display); - bool draw_scrollbar; - - draw_scrollbar = (global_settings.scrollbar && - lines < gui_list->nb_items); - - draw_cursor = !global_settings.cursor_style && - gui_list->show_selection_marker; - text_pos = 0; /* here it's in pixels */ - if(draw_scrollbar || SHOW_LIST_TITLE) /* indent if there's - a title */ - { - text_pos += SCROLLBAR_WIDTH; - } - if(draw_cursor) - text_pos += get_icon_width(display->screen_type) + 2; - - if(draw_icons) - text_pos += get_icon_width(display->screen_type) + 2; -#else - draw_cursor = true; - if(draw_icons) - text_pos = 2; /* here it's in chars */ - else - text_pos = 1; -#endif - -#ifdef HAVE_LCD_BITMAP - screen_set_xmargin(display, text_pos); /* margin for list */ -#endif - - if (SHOW_LIST_TITLE) - { - start++; - if (end < display->nb_lines) - end++; - } - -#ifdef HAVE_LCD_COLOR - unsigned char cur_line = 0; -#endif - for (i = start; i < end; i++) - { - unsigned char *s; - char entry_buffer[MAX_PATH]; - unsigned char *entry_name; - int current_item = gui_list->start_item[display->screen_type] + - (SHOW_LIST_TITLE ? i-1 : i); - - /* When there are less items to display than the - * current available space on the screen, we stop*/ - if(current_item >= gui_list->nb_items) - break; - s = gui_list->callback_get_item_name(current_item, - gui_list->data, - entry_buffer); - entry_name = P2STR(s); - -#ifdef HAVE_LCD_BITMAP - int style = STYLE_DEFAULT; - /* position the string at the correct offset place */ - int item_width,h; - display->getstringsize(entry_name, &item_width, &h); - item_offset = gui_list_get_item_offset(gui_list, item_width, - text_pos, display); -#endif - -#ifdef HAVE_LCD_COLOR - /* if the list has a color callback */ - if (gui_list->callback_get_item_color) - { - int color = gui_list->callback_get_item_color(current_item, - gui_list->data); - /* if color selected */ - if (color >= 0) - { - style |= STYLE_COLORED; - style |= color; - } - } -#endif - - if(gui_list->show_selection_marker && - current_item >= gui_list->selected_item && - current_item < gui_list->selected_item + gui_list->selected_size) - {/* The selected item must be displayed scrolling */ -#ifdef HAVE_LCD_BITMAP - if (global_settings.cursor_style == 1 -#ifdef HAVE_REMOTE_LCD - || display->screen_type == SCREEN_REMOTE -#endif - ) - { - /* Display inverted-line-style */ - style |= STYLE_INVERT; - } -#ifdef HAVE_LCD_COLOR - else if (global_settings.cursor_style == 2) - { - /* Display colour line selector */ - style |= STYLE_COLORBAR; - } - else if (global_settings.cursor_style == 3) - { - /* Display gradient line selector */ - style = STYLE_GRADIENT; - - /* Make the lcd driver know how many lines the gradient should - cover and current line number */ - /* number of selected lines */ - style |= NUMLN_PACK(gui_list->selected_size); - /* current line number, zero based */ - style |= CURLN_PACK(cur_line); - cur_line++; - } -#endif - else /* if (!global_settings.cursor_style) */ - { - if (current_item % gui_list->selected_size != 0) - draw_cursor = false; - } - /* if the text is smaller than the viewport size */ - if (item_offset > item_width - (display->width - text_pos)) - { - /* don't scroll */ - display->puts_style_offset(0, i, entry_name, - style, item_offset); - } - else - { - display->puts_scroll_style_offset(0, i, entry_name, - style, item_offset); - } -#else - display->puts_scroll(text_pos, i, entry_name); -#endif - - if (draw_cursor) - { - screen_put_icon_with_offset(display, 0, i, - (draw_scrollbar || SHOW_LIST_TITLE)? - SCROLLBAR_WIDTH: 0, - 0, Icon_Cursor); - } - } - else - {/* normal item */ - if(gui_list->scroll_all) - { -#ifdef HAVE_LCD_BITMAP - display->puts_scroll_style_offset(0, i, entry_name, - style, item_offset); -#else - display->puts_scroll(text_pos, i, entry_name); -#endif - } - else - { -#ifdef HAVE_LCD_BITMAP - display->puts_style_offset(0, i, entry_name, - style, item_offset); -#else - display->puts(text_pos, i, entry_name); -#endif - } - } - /* Icons display */ - if(draw_icons) - { - 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 - } - } - } - -#ifdef HAVE_LCD_BITMAP - /* Draw the scrollbar if needed*/ - if(draw_scrollbar) - { - int y_start = gui_textarea_get_ystart(display); - if (SHOW_LIST_TITLE) - y_start += display->char_height; - int scrollbar_y_end = display->char_height * - lines + y_start; - gui_scrollbar_draw(display, 0, y_start, SCROLLBAR_WIDTH-1, - scrollbar_y_end - y_start, gui_list->nb_items, - gui_list->start_item[display->screen_type], - gui_list->start_item[display->screen_type] + lines, VERTICAL); - } - - screen_set_xmargin(display, old_margin); -#endif - - gui_textarea_update(display); -} - -/* * Force a full screen update. */ + void gui_synclist_draw(struct gui_synclist *gui_list) { int i; FOR_NB_SCREENS(i) { last_list_displayed = NULL; - gui_list_draw_smart(gui_list, &screens[i]); + list_draw(&screens[i], gui_list->parent[i], gui_list); } } - - /* sets up the list so the selection is shown correctly on the screen */ static void gui_list_put_selection_on_screen(struct gui_synclist * gui_list, enum screen_type screen) { - struct screen *display = &screens[screen]; - int nb_lines = display->nb_lines - SHOW_LIST_TITLE; + int nb_lines; int difference = gui_list->selected_item - gui_list->start_item[screen]; + struct viewport vp = *gui_list->parent[screen]; +#ifndef HVE_LCD_CHARCELL + if (list_display_title(gui_list, gui_list->parent[screen])) + vp.height -= list_title_height(gui_list,gui_list->parent[screen]); +#endif + nb_lines = viewport_get_nb_lines(&vp); /* edge case,, selected last item */ if (gui_list->selected_item == gui_list->nb_items -1) @@ -576,8 +395,12 @@ int i, nb_lines, screen_top; FOR_NB_SCREENS(i) { - struct screen *display = &screens[i]; - nb_lines = display->nb_lines - SHOW_LIST_TITLE; + struct viewport vp = *gui_list->parent[i]; +#ifndef HVE_LCD_CHARCELL + if (list_display_title(gui_list, gui_list->parent[i])) + vp.height -= list_title_height(gui_list,gui_list->parent[i]); +#endif + nb_lines = viewport_get_nb_lines(&vp); if (offset > 0) { screen_top = gui_list->nb_items-nb_lines; @@ -616,23 +439,12 @@ */ void gui_synclist_del_item(struct gui_synclist * gui_list) { - int i; if(gui_list->nb_items > 0) { if (gui_list->selected_item == gui_list->nb_items-1) gui_list->selected_item--; - FOR_NB_SCREENS(i) - { - gui_textarea_update_nblines(&screens[i]); - int nb_lines = screens[i].nb_lines; - int dist_start_from_end = gui_list->nb_items - - gui_list->start_item[i] - 1; - - /* scroll the list if needed */ - if( (dist_start_from_end < nb_lines) && (gui_list->start_item[i] != 0) ) - gui_list->start_item[i]--; - } gui_list->nb_items--; + gui_synclist_select_item(gui_list, gui_list->selected_item); } } @@ -707,6 +519,14 @@ lists->callback_speak_item = voice_callback; } +#ifdef HAVE_LCD_COLOR +void gui_synclist_set_color_callback(struct gui_synclist * lists, + list_get_color color_callback) +{ + lists->callback_get_item_color = color_callback; +} +#endif + static void gui_synclist_select_next_page(struct gui_synclist * lists, enum screen_type screen) { Index: apps/gui/color_picker.c =================================================================== --- apps/gui/color_picker.c (revision 16159) +++ apps/gui/color_picker.c (working copy) @@ -268,6 +268,7 @@ } /* end for */ /* Draw color value in system font */ + int oldFont=display->getfont(); display->setfont(FONT_SYSFIXED); /* Format RGB: #rrggbb */ @@ -320,7 +321,7 @@ } } - display->setfont(FONT_UI); + display->setfont(oldFont); display->update(); /* Be sure screen mode is reset */ Index: apps/gui/quickscreen.c =================================================================== --- apps/gui/quickscreen.c (revision 16159) +++ apps/gui/quickscreen.c (working copy) @@ -61,6 +61,8 @@ if (display->height / display->char_height < 7) /* we need at leats 7 lines */ { display->setfont(FONT_SYSFIXED); + } else { + display->setfont(FONT_MENU); } display->getstringsize("A", NULL, &font_h); Index: apps/gui/wps_debug.c =================================================================== --- apps/gui/wps_debug.c (revision 16159) +++ apps/gui/wps_debug.c (working copy) @@ -493,40 +493,51 @@ static void print_line_info(struct wps_data *data) { - int i, j; + int i, j, v; struct wps_line *line; struct wps_subline *subline; if (wps_verbose_level > 0) { - DEBUGF("Number of lines : %d\n", data->num_lines); - DEBUGF("Number of sublines: %d\n", data->num_sublines); - DEBUGF("Number of tokens : %d\n", data->num_tokens); + DEBUGF("Number of viewports : %d\n", data->num_viewports); + for (v = 0; v < data->num_viewports; v++) + { + DEBUGF("vp %d: Number of lines: %d\n", v, data->viewports[v].num_lines); + } + DEBUGF("Number of sublines : %d\n", data->num_sublines); + DEBUGF("Number of tokens : %d\n", data->num_tokens); DEBUGF("\n"); } if (wps_verbose_level > 1) { - for (i = 0, line = data->lines; i < data->num_lines; i++,line++) + for (v = 0; v < data->num_viewports; v++) { - DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n", - i, line->num_sublines, line->first_subline_idx); - - for (j = 0, subline = data->sublines + line->first_subline_idx; - j < line->num_sublines; j++, subline++) + DEBUGF("Viewport %d - +%d+%d (%dx%d)\n",v,data->viewports[v].vp.x, + data->viewports[v].vp.y, + data->viewports[v].vp.width, + data->viewports[v].vp.height); + for (i = 0, line = data->viewports[v].lines; i < data->viewports[v].num_lines; i++,line++) { - DEBUGF(" Subline %d: first_token=%3d, last_token=%3d", - j, subline->first_token_idx, - wps_last_token_index(data, i, j)); + DEBUGF("Line %2d (num_sublines=%d, first_subline=%d)\n", + i, line->num_sublines, line->first_subline_idx); - if (subline->line_type & WPS_REFRESH_SCROLL) - DEBUGF(", scrolled"); - else if (subline->line_type & WPS_REFRESH_PLAYER_PROGRESS) - DEBUGF(", progressbar"); - else if (subline->line_type & WPS_REFRESH_PEAK_METER) - DEBUGF(", peakmeter"); + for (j = 0, subline = data->sublines + line->first_subline_idx; + j < line->num_sublines; j++, subline++) + { + DEBUGF(" Subline %d: first_token=%3d, last_token=%3d", + j, subline->first_token_idx, + wps_last_token_index(data, v, i, j)); - DEBUGF("\n"); + if (subline->line_type & WPS_REFRESH_SCROLL) + DEBUGF(", scrolled"); + else if (subline->line_type & WPS_REFRESH_PLAYER_PROGRESS) + DEBUGF(", progressbar"); + else if (subline->line_type & WPS_REFRESH_PEAK_METER) + DEBUGF(", peakmeter"); + + DEBUGF("\n"); + } } } Index: apps/gui/list.h =================================================================== --- apps/gui/list.h (revision 16159) +++ apps/gui/list.h (working copy) @@ -123,59 +123,10 @@ int title_color; list_get_color *callback_get_item_color; #endif + struct viewport *parent[NB_SCREENS]; }; -/* - * Sets the numbers of items the list can currently display - * note that the list's context like the currently pointed item is resetted - * - gui_list : the list structure - * - nb_items : the numbers of items you want - */ -#define gui_list_set_nb_items(gui_list, nb) \ - (gui_list)->nb_items = nb -/* - * Returns the numbers of items currently in the list - * - gui_list : the list structure - */ -#define gui_list_get_nb_items(gui_list) \ - (gui_list)->nb_items - -/* - * Sets the icon callback function - * - gui_list : the list structure - * - _callback : the callback function - */ -#define gui_list_set_icon_callback(gui_list, _callback) \ - (gui_list)->callback_get_item_icon=_callback - -/* - * Sets the voice callback function - * - gui_list : the list structure - * - _callback : the callback function - */ -#define gui_list_set_voice_callback(gui_list, _callback) \ - (gui_list)->callback_speak_item=_callback - -#ifdef HAVE_LCD_COLOR -/* - * Sets the color callback function - * - gui_list : the list structure - * - _callback : the callback function - */ -#define gui_list_set_color_callback(gui_list, _callback) \ - (gui_list)->callback_get_item_color=_callback -#endif - -/* - * Gives the position of the selected item - * - gui_list : the list structure - * Returns the position - */ -#define gui_list_get_sel_pos(gui_list) \ - (gui_list)->selected_item - - #ifdef HAVE_LCD_BITMAP /* parse global setting to static int */ extern void gui_list_screen_scroll_step(int ofs); @@ -183,17 +134,8 @@ /* parse global setting to static bool */ extern void gui_list_screen_scroll_out_of_view(bool enable); #endif /* HAVE_LCD_BITMAP */ -/* - * Tells the list wether it should stop when reaching the top/bottom - * or should continue (by going to bottom/top) - * - gui_list : the list structure - * - scroll : - * - true : stops when reaching top/bottom - * - false : continues to go to bottom/top when reaching top/bottom - */ -#define gui_list_limit_scroll(gui_list, scroll) \ - (gui_list)->limit_scroll=scroll +void list_init_viewports(void); extern void gui_synclist_init( struct gui_synclist * lists, @@ -205,6 +147,9 @@ extern void gui_synclist_set_nb_items(struct gui_synclist * lists, int nb_items); extern void gui_synclist_set_icon_callback(struct gui_synclist * lists, list_get_icon icon_callback); extern void gui_synclist_set_voice_callback(struct gui_synclist * lists, list_speak_item voice_callback); +#ifdef HAVE_LCD_COLOR +extern void gui_synclist_set_color_callback(struct gui_synclist * lists, list_get_color color_callback); +#endif extern void gui_synclist_speak_item(struct gui_synclist * lists); extern int gui_synclist_get_nb_items(struct gui_synclist * lists); Index: apps/gui/gwps.c =================================================================== --- apps/gui/gwps.c (revision 16159) +++ apps/gui/gwps.c (working copy) @@ -92,6 +92,11 @@ } #endif +static void gui_wps_set_font(struct gui_wps *gwps) +{ + gwps->display->setfont(FONT_WPS); +} + long gui_wps_show(void) { long button = 0; @@ -105,6 +110,12 @@ wps_state_init(); + /* Set WPS display font */ + FOR_NB_SCREENS(i) + { + gui_wps_set_font(&gui_wps[i]); + } + #ifdef HAVE_LCD_CHARCELLS status_set_audio(true); status_set_param(false); Index: apps/gui/gwps.h =================================================================== --- apps/gui/gwps.h (revision 16159) +++ apps/gui/gwps.h (working copy) @@ -86,6 +86,7 @@ #define IMG_BUFSIZE ((LCD_HEIGHT*LCD_WIDTH*LCD_DEPTH/8) \ + (2*LCD_HEIGHT*LCD_WIDTH/8)) +#define WPS_MAX_VIEWPORTS 16 #define WPS_MAX_LINES (LCD_HEIGHT/5+1) #define WPS_MAX_SUBLINES (WPS_MAX_LINES*3) #define WPS_MAX_TOKENS 1024 @@ -95,6 +96,7 @@ #else +#define WPS_MAX_VIEWPORTS 2 #define WPS_MAX_LINES 2 #define WPS_MAX_SUBLINES 12 #define WPS_MAX_TOKENS 64 @@ -315,7 +317,15 @@ long subline_expire_time; }; +struct wps_viewport { + struct viewport vp; /* The LCD viewport struct */ + /* Number of lines in this viewport. During WPS parsing, this is + the index of the line being parsed. */ + int num_lines; + struct wps_line lines[WPS_MAX_LINES]; +}; + /* wps_data this struct holds all necessary data which describes the viewable content of a wps */ @@ -360,10 +370,9 @@ bool remote_wps; #endif - /* Number of lines in the WPS. During WPS parsing, this is - the index of the line being parsed. */ - int num_lines; - struct wps_line lines[WPS_MAX_LINES]; + /* Number of viewports in the WPS */ + int num_viewports; + struct wps_viewport viewports[WPS_MAX_VIEWPORTS]; /* Total number of sublines in the WPS. During WPS parsing, this is the index of the subline where the parsed tokens are added to. */ @@ -388,26 +397,30 @@ /* to setup up the wps-data from a format-buffer (isfile = false) from a (wps-)file (isfile = true)*/ bool wps_data_load(struct wps_data *wps_data, + struct screen *display, const char *buf, bool isfile); /* Returns the index of the subline in the subline array + v - 0-based viewport number line - 0-based line number subline - 0-based subline number within the line */ -int wps_subline_index(struct wps_data *wps_data, int line, int subline); +int wps_subline_index(struct wps_data *wps_data, int v, int line, int subline); /* Returns the index of the first subline's token in the token array + v - 0-based viewport number line - 0-based line number subline - 0-based subline number within the line */ -int wps_first_token_index(struct wps_data *data, int line, int subline); +int wps_first_token_index(struct wps_data *data, int v, int line, int subline); /* Returns the index of the last subline's token in the token array. + v - 0-based viewport number line - 0-based line number subline - 0-based subline number within the line */ -int wps_last_token_index(struct wps_data *data, int line, int subline); +int wps_last_token_index(struct wps_data *data, int v, int line, int subline); /* wps_data end */ Index: apps/gui/backdrop.c =================================================================== --- apps/gui/backdrop.c (revision 16159) +++ apps/gui/backdrop.c (working copy) @@ -50,7 +50,9 @@ /* load the image */ bm.data=(char*)backdrop_buffer; ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), - FORMAT_NATIVE | FORMAT_DITHER); + FORMAT_NATIVE | FORMAT_DITHER, + LCD_WIDTH, LCD_HEIGHT, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); if ((ret > 0) && (bm.width == LCD_WIDTH) && (bm.height == LCD_HEIGHT)) { @@ -112,7 +114,9 @@ /* load the image */ bm.data=(char*)backdrop_buffer; ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), - FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE); + FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE, + LCD_WIDTH, LCD_HEIGHT, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); if ((ret > 0) && (bm.width == LCD_REMOTE_WIDTH) && (bm.height == LCD_REMOTE_HEIGHT)) { Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (revision 16159) +++ apps/gui/wps_parser.c (working copy) @@ -118,6 +118,8 @@ struct wps_token *token, struct wps_data *wps_data); #ifdef HAVE_LCD_BITMAP +static int parse_viewport(const char *wps_bufptr, + struct wps_token *token, struct wps_data *wps_data); static int parse_leftmargin(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); static int parse_image_special(const char *wps_bufptr, @@ -131,7 +133,6 @@ static int parse_image_load(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); #endif /*HAVE_LCD_BITMAP */ - #ifdef HAVE_ALBUMART static int parse_albumart_load(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data); @@ -311,6 +312,9 @@ { WPS_TOKEN_ALBUMART_DISPLAY, "C", WPS_REFRESH_STATIC, parse_albumart_conditional }, #endif + + { WPS_NO_TOKEN, "V", 0, parse_viewport }, + #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) { WPS_TOKEN_IMAGE_BACKDROP, "X", 0, parse_image_special }, #endif @@ -334,9 +338,11 @@ /* Starts a new subline in the current line during parsing */ static void wps_start_new_subline(struct wps_data *data) { + struct wps_viewport* vp = &data->viewports[data->num_viewports]; + data->num_sublines++; data->sublines[data->num_sublines].first_token_idx = data->num_tokens; - data->lines[data->num_lines].num_sublines++; + vp->lines[vp->num_lines].num_sublines++; } #ifdef HAVE_LCD_BITMAP @@ -375,7 +381,9 @@ int ret = read_bmp_file(filename, bm, wps_data->img_buf_free, - format); + format, + 0,0, + BMP_RESIZE_NONE); if (ret > 0) { @@ -506,6 +514,150 @@ return skip_end_of_line(wps_bufptr); } +static int parse_viewport(const char *wps_bufptr, + struct wps_token *token, + struct wps_data *wps_data) +{ + const char *ptr = wps_bufptr; + const char *pos = NULL; + const char *newline; + struct viewport* vp; +#if LCD_DEPTH > 2 + char hexbuf[7]; +#endif + int i; + int tmp[5]; + int depth; + + (void)token; /* Kill warnings */ + + /* format: %V|x|y|width|height|fg_pattern|bg_pattern| */ + + if (wps_data->num_viewports >= WPS_MAX_VIEWPORTS) + return WPS_ERROR_INVALID_PARAM; + + wps_data->num_viewports++; + vp = &wps_data->viewports[wps_data->num_viewports].vp; + + /* Set the defaults for fields not user-specified */ + vp->drawmode = DRMODE_SOLID; + vp->xmargin = 0; + vp->ymargin = 0; + + ptr = strchr(ptr, '|') + 1; + pos = strchr(ptr, '|'); + newline = strchr(ptr, '\n'); + + if (!pos || pos > newline) + return 0; + + /* Parse 5 integers */ + for (i=0; i< 5 ; i++) + { + pos = strchr(ptr, '|'); + if (pos && pos < newline) + tmp[i] = atoi(ptr); + else + return WPS_ERROR_INVALID_PARAM; + ptr = pos + 1; + } + + vp->x = tmp[0]; + vp->y = tmp[1]; + vp->width = tmp[2]; + vp->height = tmp[3]; + vp->font = tmp[4]; + + switch (vp->font){ + case 0: + vp->font = FONT_SYSFIXED; + break; + case 1: + vp->font = FONT_WPS; + break; + case 2: + vp->font = FONT_USER1; + break; + case 3: + vp->font = FONT_USER2; + break; + case 4: + vp->font = FONT_USER3; + break; + case 5: + vp->font = FONT_USER4; + break; + case 6: + vp->font = FONT_USER5; + break; + case 7: + vp->font = FONT_USER6; + break; + case 8: + vp->font = FONT_USER7; + break; + default: + vp->font = FONT_WPS; + break; + } + + /* TODO - try and make the following code simpler... */ + + /* Work out the depth of this display */ +#ifdef HAVE_REMOTE_LCD + if (wps_data->remote_wps) + depth = LCD_REMOTE_DEPTH; + else + depth = LCD_DEPTH; +#else + depth = LCD_DEPTH; +#endif + +#if (LCD_DEPTH > 1) || (defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1) + if (depth > 1) + { + /* Get 2 colours */ + for (i = 0; i < 2 ; i++) + { + /* get fg_pattern */ + pos = strchr(ptr, '|'); + if (pos && pos < newline) + { +#if LCD_DEPTH > 2 + if (depth > 2) + { + snprintf(hexbuf,7,"%s",ptr); + tmp[i] = hex_to_rgb(hexbuf); + } + else +#endif + tmp[i] = atoi(ptr); + } + else + return WPS_ERROR_INVALID_PARAM; + ptr = pos + 1; + } + + vp->fg_pattern = tmp[0]; + vp->bg_pattern = tmp[1]; + } +#endif + + wps_data->viewports[wps_data->num_viewports].num_lines = 0; + + if (wps_data->num_sublines < WPS_MAX_SUBLINES) + { + wps_data->viewports[wps_data->num_viewports].lines[0].first_subline_idx = + wps_data->num_sublines; + + wps_data->sublines[wps_data->num_sublines].first_token_idx = + wps_data->num_tokens; + } + + /* Skip the rest of the line */ + return skip_end_of_line(wps_bufptr); +} + static int parse_image_special(const char *wps_bufptr, struct wps_token *token, struct wps_data *wps_data) @@ -975,7 +1127,8 @@ level = -1; while(*wps_bufptr && !fail && data->num_tokens < WPS_MAX_TOKENS - 1 - && data->num_lines < WPS_MAX_LINES) + && data->num_viewports < WPS_MAX_VIEWPORTS + && data->viewports[data->num_viewports].num_lines < WPS_MAX_LINES) { switch(*wps_bufptr++) { @@ -1083,12 +1236,12 @@ line++; wps_start_new_subline(data); - data->num_lines++; /* Start a new line */ + data->viewports[data->num_viewports].num_lines++; /* Start a new line */ - if ((data->num_lines < WPS_MAX_LINES) && + if ((data->viewports[data->num_viewports].num_lines < WPS_MAX_LINES) && (data->num_sublines < WPS_MAX_SUBLINES)) { - data->lines[data->num_lines].first_subline_idx = + data->viewports[data->num_viewports].lines[data->viewports[data->num_viewports].num_lines].first_subline_idx = data->num_sublines; data->sublines[data->num_sublines].first_token_idx = @@ -1165,6 +1318,9 @@ if (!fail && level >= 0) /* there are unclosed conditionals */ fail = PARSE_FAIL_UNCLOSED_COND; + /* We have finished with the last viewport, so increment count */ + data->num_viewports++; + #ifdef DEBUG print_debug_info(data, fail, line); #endif @@ -1308,6 +1464,7 @@ /* to setup up the wps-data from a format-buffer (isfile = false) from a (wps-)file (isfile = true)*/ bool wps_data_load(struct wps_data *wps_data, + struct screen *display, const char *buf, bool isfile) { @@ -1316,6 +1473,24 @@ wps_reset(wps_data); + /* Initialise the first (default) viewport */ + wps_data->viewports[0].vp.x = 0; + wps_data->viewports[0].vp.y = 0; + wps_data->viewports[0].vp.width = display->width; + wps_data->viewports[0].vp.height = display->height; +#ifdef HAVE_LCD_BITMAP + wps_data->viewports[0].vp.font = FONT_WPS; + wps_data->viewports[0].vp.drawmode = DRMODE_SOLID; +#endif + wps_data->viewports[0].vp.xmargin = display->getxmargin(); + wps_data->viewports[0].vp.ymargin = display->getymargin(); +#if LCD_DEPTH > 1 + if (display->depth > 1) + { + wps_data->viewports[0].vp.fg_pattern = display->get_foreground(); + wps_data->viewports[0].vp.bg_pattern = display->get_background(); + } +#endif if (!isfile) { return wps_parse(wps_data, buf); @@ -1402,20 +1577,20 @@ } } -int wps_subline_index(struct wps_data *data, int line, int subline) +int wps_subline_index(struct wps_data *data, int v, int line, int subline) { - return data->lines[line].first_subline_idx + subline; + return data->viewports[v].lines[line].first_subline_idx + subline; } -int wps_first_token_index(struct wps_data *data, int line, int subline) +int wps_first_token_index(struct wps_data *data, int v, int line, int subline) { - int first_subline_idx = data->lines[line].first_subline_idx; + int first_subline_idx = data->viewports[v].lines[line].first_subline_idx; return data->sublines[first_subline_idx + subline].first_token_idx; } -int wps_last_token_index(struct wps_data *data, int line, int subline) +int wps_last_token_index(struct wps_data *data, int v, int line, int subline) { - int first_subline_idx = data->lines[line].first_subline_idx; + int first_subline_idx = data->viewports[v].lines[line].first_subline_idx; int idx = first_subline_idx + subline; if (idx < data->num_sublines - 1) { Index: apps/gui/icon.c =================================================================== --- apps/gui/icon.c (revision 16159) +++ apps/gui/icon.c (working copy) @@ -220,7 +220,9 @@ char path[MAX_PATH]; snprintf(path, sizeof(path), "%s/%s.bmp", ICON_DIR, filename); - size_read = read_bmp_file(path, bmp, IMG_BUFSIZE, bmpformat); + size_read = read_bmp_file(path, bmp, IMG_BUFSIZE, bmpformat, + 0, 0, + BMP_RESIZE_NONE); if (size_read > 0) { *loaded_ok = true; Index: apps/gui/splash.c =================================================================== --- apps/gui/splash.c (revision 16159) +++ apps/gui/splash.c (working copy) @@ -25,6 +25,7 @@ #include "lang.h" #include "settings.h" #include "talk.h" +#include "font.h" #ifndef MAX #define MAX(a, b) (((a)>(b))?(a):(b)) @@ -57,10 +58,12 @@ int space_w, w, h; #ifdef HAVE_LCD_BITMAP int maxw = 0; + int oldFont=screen->getfont(); #if LCD_DEPTH > 1 unsigned prevfg = 0; #endif + screen->setfont(FONT_MENU); screen->getstringsize(" ", &space_w, &h); #else /* HAVE_LCD_CHARCELLS */ @@ -75,8 +78,12 @@ /* break splash string into display lines, doing proper word wrap */ next = strtok_r(splash_buf, " ", &store); - if (!next) + if (!next){ +#ifdef HAVE_LCD_BITMAP + screen->setfont(oldFont); +#endif return; /* nothing to display */ + } lines[0] = next; while (true) @@ -127,6 +134,7 @@ screen->stop_scroll(); #ifdef HAVE_LCD_BITMAP + /* If we center the display, then just clear the box we need and put a nice little frame and put the text in there! */ y = (screen->height - y) / 2; /* height => y start position */ @@ -180,6 +188,7 @@ screen->set_foreground(prevfg); screen->set_drawmode(DRMODE_SOLID); } + screen->setfont(oldFont); #endif screen->update(); } Index: apps/gui/yesno.c =================================================================== --- apps/gui/yesno.c (revision 16159) +++ apps/gui/yesno.c (working copy) @@ -24,6 +24,7 @@ #include "lang.h" #include "action.h" #include "talk.h" +#include "font.h" /* * Initializes the yesno asker @@ -111,8 +112,13 @@ bool result_displayed; struct gui_yesno yn[NB_SCREENS]; long talked_tick = 0; + int old_font[NB_SCREENS]; FOR_NB_SCREENS(i) { +#ifdef HAVE_LCD_BITMAP + old_font[i]=screens[i].getfont(); + screens[i].setfont(FONT_MENU); +#endif gui_yesno_init(&(yn[i]), main_message, yes_message, no_message); gui_yesno_set_display(&(yn[i]), &(screens[i])); gui_yesno_draw(&(yn[i])); @@ -137,8 +143,15 @@ /* ignore some SYS events that can happen */ continue; default: - if(default_event_handler(button) == SYS_USB_CONNECTED) + if(default_event_handler(button) == SYS_USB_CONNECTED){ +#ifdef HAVE_LCD_BITMAP + FOR_NB_SCREENS(i) + { + screens[i].setfont(old_font[i]); + } +#endif return(YESNO_USB); + } result = YESNO_NO; } } @@ -154,5 +167,13 @@ } if(result_displayed) sleep(HZ); + +#ifdef HAVE_LCD_BITMAP + FOR_NB_SCREENS(i) + { + screens[i].setfont(old_font[i]); + } +#endif + return(result); } Index: apps/settings.h =================================================================== --- apps/settings.h (revision 16159) +++ apps/settings.h (working copy) @@ -416,9 +416,32 @@ #if CONFIG_TUNER unsigned char fmr_file[MAX_FILENAME+1]; /* last fmr preset */ #endif - unsigned char font_file[MAX_FILENAME+1]; /* last font */ + unsigned char font_file[MAX_FILENAME+1]; /* backward comp */ + + unsigned char browserfont[MAX_FILENAME+1]; /* UI fonts */ + unsigned char wpsfont[MAX_FILENAME+1]; + unsigned char menufont[MAX_FILENAME+1]; +#ifdef CONFIG_TUNER + unsigned char tunerfont[MAX_FILENAME+1]; +#endif +#ifdef HAVE_RECORDING + unsigned char recordfont[MAX_FILENAME+1]; +#endif + + unsigned char userfont1[MAX_FILENAME+1]; + unsigned char userfont2[MAX_FILENAME+1]; + unsigned char userfont3[MAX_FILENAME+1]; + unsigned char userfont4[MAX_FILENAME+1]; + unsigned char userfont5[MAX_FILENAME+1]; + unsigned char userfont6[MAX_FILENAME+1]; + unsigned char userfont7[MAX_FILENAME+1]; + unsigned char wps_file[MAX_FILENAME+1]; /* last wps */ unsigned char lang_file[MAX_FILENAME+1]; /* last language */ + unsigned char list_vp_file[MAX_FILENAME+1]; /* viewport file for the lists */ +#ifdef HAVE_REMOTE_LCD + unsigned char remote_list_vp_file[MAX_FILENAME+1]; /* viewport file for the lists */ +#endif /* misc options */ Index: apps/menus/playlist_menu.c =================================================================== --- apps/menus/playlist_menu.c (revision 16159) +++ apps/menus/playlist_menu.c (working copy) @@ -50,7 +50,12 @@ strcat(temp, "8"); if (len <= 5 || strcasecmp(&temp[len-5], ".m3u8")) - strcpy(temp, DEFAULT_DYNAMIC_PLAYLIST_NAME); + { + strcpy(temp, + playlist_check_dir(DEFAULT_PLAYLIST_DIR)==0 ? + DEFAULT_PLAYLIST_DIR DEFAULT_DYNAMIC_PLAYLIST_NAME : + DEFAULT_DYNAMIC_PLAYLIST_NAME); + } if (!kbd_input(temp, sizeof(temp))) { Index: apps/bitmaps/native/rockboxlogo.176x54x16.bmp =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Index: apps/settings_list.c =================================================================== --- apps/settings_list.c (revision 16159) +++ apps/settings_list.c (working copy) @@ -468,6 +468,13 @@ false, "force fm mono", toggle_mono_mode), SYSTEM_SETTING(NVRAM(4),last_frequency,0), #endif + FILENAME_SETTING(F_THEMESETTING,userfont1,"userfont1","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont2,"userfont2","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont3,"userfont3","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont4,"userfont4","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont5,"userfont5","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont6,"userfont6","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,userfont7,"userfont7","",FONT_DIR "/",".fnt",MAX_FILENAME+1), #if BATTERY_TYPES_COUNT > 1 CHOICE_SETTING(0, battery_type, LANG_BATTERY_TYPE, 0, @@ -1083,8 +1090,20 @@ FILENAME_SETTING(0, fmr_file, "fmr", "", FMPRESET_PATH "/", ".fmr", MAX_FILENAME+1), #endif - FILENAME_SETTING(F_THEMESETTING, font_file, "font", - "", FONT_DIR "/", ".fnt", MAX_FILENAME+1), + + /** backward comp **/ + FILENAME_SETTING(F_THEMESETTING,font_file,"font","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + + FILENAME_SETTING(F_THEMESETTING,browserfont,"browserfont","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,wpsfont,"wpsfont","",FONT_DIR "/",".fnt",MAX_FILENAME+1), + FILENAME_SETTING(F_THEMESETTING,menufont,"menufont","",FONT_DIR "/",".fnt",MAX_FILENAME+1), +#ifdef HAVE_RECORDING + FILENAME_SETTING(F_THEMESETTING,recordfont,"recordfont","",FONT_DIR "/",".fnt",MAX_FILENAME+1), +#endif +#ifdef CONFIG_TUNER + FILENAME_SETTING(F_THEMESETTING,tunerfont,"tunerfont","",FONT_DIR "/",".fnt",MAX_FILENAME+1), +#endif + FILENAME_SETTING(F_THEMESETTING,wps_file, "wps", "", WPS_DIR "/", ".wps", MAX_FILENAME+1), FILENAME_SETTING(0,lang_file,"lang","",LANG_DIR "/",".lng",MAX_FILENAME+1), @@ -1187,6 +1206,13 @@ ID2P(LANG_OFF), ID2P(LANG_WEAK), ID2P(LANG_MODERATE), ID2P(LANG_STRONG)), OFFON_SETTING(0, keyclick_repeats, LANG_KEYCLICK_REPEATS, false, "keyclick repeats", NULL), #endif /* CONFIG_CODEC == SWCODEC */ + + FILENAME_SETTING(F_THEMESETTING, list_vp_file, "list viewport file", "", + THEME_DIR "/", ".vp", MAX_FILENAME+1), +#ifdef HAVE_REMOTE_LCD + FILENAME_SETTING(F_THEMESETTING, remote_list_vp_file, "remote list viewport file", "", + THEME_DIR "/", ".vp", MAX_FILENAME+1), +#endif }; const int nb_settings = sizeof(settings)/sizeof(*settings); Index: apps/filetree.c =================================================================== --- apps/filetree.c (revision 16159) +++ apps/filetree.c (working copy) @@ -478,7 +478,7 @@ #if LCD_DEPTH > 1 unload_wps_backdrop(); #endif - wps_data_load(gui_wps[0].data, buf, true); + wps_data_load(gui_wps[0].data, &screens[0], buf, true); set_file(buf, (char *)global_settings.wps_file, MAX_FILENAME); break; @@ -490,7 +490,7 @@ #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 unload_remote_wps_backdrop(); #endif - wps_data_load(gui_wps[1].data, buf, true); + wps_data_load(gui_wps[1].data, &screens[1], buf, true); set_file(buf, (char *)global_settings.rwps_file, MAX_FILENAME); break; @@ -522,8 +522,34 @@ #ifdef HAVE_LCD_BITMAP case FILE_ATTR_FONT: gui_syncsplash(0, ID2P(LANG_WAIT)); - font_load(buf); - set_file(buf, (char *)global_settings.font_file, MAX_FILENAME); + /* If a font is chosen it overrides all theme settings */ + font_load(buf, FONT_BROWSER); + + /* set_file will change buf!!! + * so make a copy */ + char buf_copy[MAX_PATH]; + strcpy(buf_copy, buf); + set_file(buf_copy, (char *)global_settings.browserfont, MAX_FILENAME); + + font_load(buf, FONT_WPS); + strcpy(buf_copy, buf); + set_file(buf_copy, (char *)global_settings.wpsfont, MAX_FILENAME); + + font_load(buf, FONT_MENU); + strcpy(buf_copy, buf); + set_file(buf_copy, (char *)global_settings.menufont, MAX_FILENAME); + +#ifdef CONFIG_TUNER + font_load(buf, FONT_TUNER); + strcpy(buf_copy, buf); + set_file(buf_copy, (char *)global_settings.tunerfont, MAX_FILENAME); +#endif +#ifdef HAVE_RECORDING + font_load(buf, FONT_RECORD); + strcpy(buf_copy, buf); + set_file(buf_copy, (char *)global_settings.recordfont, MAX_FILENAME); +#endif + /* dont set userfonts because of the buffer problem */ break; case FILE_ATTR_KBD: Index: apps/plugin.c =================================================================== --- apps/plugin.c (revision 16159) +++ apps/plugin.c (working copy) @@ -94,6 +94,7 @@ lcd_set_drawmode, lcd_get_drawmode, lcd_setfont, + lcd_getfont, lcd_drawpixel, lcd_drawline, lcd_hline, @@ -148,6 +149,7 @@ lcd_remote_set_drawmode, lcd_remote_get_drawmode, lcd_remote_setfont, + lcd_remote_getfont, lcd_remote_getstringsize, lcd_remote_drawpixel, lcd_remote_drawline, Index: apps/SOURCES =================================================================== --- apps/SOURCES (revision 16159) +++ apps/SOURCES (working copy) @@ -53,6 +53,11 @@ gui/icon.c #endif gui/list.c +#ifdef HAVE_LCD_BITMAP +gui/bitmap/list.c +#else +gui/charcell/list.c +#endif gui/option_select.c gui/quickscreen.c gui/scrollbar.c @@ -62,6 +67,7 @@ gui/yesno.c gui/wps_debug.c gui/wps_parser.c +gui/viewport.c #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) gui/backdrop.c Index: apps/plugin.h =================================================================== --- apps/plugin.h (revision 16159) +++ apps/plugin.h (working copy) @@ -164,6 +164,7 @@ void (*lcd_set_drawmode)(int mode); int (*lcd_get_drawmode)(void); void (*lcd_setfont)(int font); + int (*lcd_getfont)(void); void (*lcd_drawpixel)(int x, int y); void (*lcd_drawline)(int x1, int y1, int x2, int y2); void (*lcd_hline)(int x1, int x2, int y); @@ -194,8 +195,8 @@ int width, int height); #endif unsigned short *(*bidi_l2v)( const unsigned char *str, int orientation ); - const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code ); - struct font* (*font_load)(const char *path); + const unsigned char *(*font_get_bits)( struct font *pf, unsigned short char_code, int font ); + struct font* (*font_load)(const char *path, int font); void (*lcd_puts_style)(int x, int y, const unsigned char *str, int style); void (*lcd_puts_scroll_style)(int x, int y, const unsigned char* string, int style); @@ -210,7 +211,7 @@ struct font* (*font_get)(int font); int (*font_getstringsize)(const unsigned char *str, int *w, int *h, int fontnumber); - int (*font_get_width)(struct font* pf, unsigned short char_code); + int (*font_get_width)(struct font* pf, unsigned short char_code, int font); void (*screen_clear_area)(struct screen * display, int xstart, int ystart, int width, int height); #endif @@ -233,6 +234,7 @@ void (*lcd_remote_set_drawmode)(int mode); int (*lcd_remote_get_drawmode)(void); void (*lcd_remote_setfont)(int font); + int (*lcd_remote_getfont)(void); int (*lcd_remote_getstringsize)(const unsigned char *str, int *w, int *h); void (*lcd_remote_drawpixel)(int x, int y); void (*lcd_remote_drawline)(int x1, int y1, int x2, int y2); @@ -615,7 +617,10 @@ #endif #ifdef HAVE_LCD_BITMAP int (*read_bmp_file)(const char* filename, struct bitmap *bm, int maxsize, - int format); + int format, + int dst_maxwidth, /* =0 */ + int dst_maxheight,/* =0 */ + int flags); /* =BMP_RESIZE_NONE */ void (*screen_dump_set_hook)(void (*hook)(int fh)); #endif int (*show_logo)(void); Index: apps/buffering.c =================================================================== --- apps/buffering.c (revision 16159) +++ apps/buffering.c (working copy) @@ -49,6 +49,7 @@ #include "pcmbuf.h" #include "buffer.h" #include "bmp.h" +#include "gwps.h" #ifdef SIMULATOR #define ata_disk_is_active() 1 @@ -840,7 +841,10 @@ #endif int free = (int)MIN(buffer_len - BUF_USED, buffer_len - buf_widx); - rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER); + rc = read_bmp_fd(fd, bmp, free, FORMAT_ANY|FORMAT_DITHER, + gui_wps->data->albumart_max_width, + gui_wps->data->albumart_max_height, + BMP_RESIZE_INCREASE | BMP_RESIZE_DECREASE); return rc + (rc > 0 ? sizeof(struct bitmap) : 0); } #endif Index: apps/main.c =================================================================== --- apps/main.c (revision 16159) +++ apps/main.c (working copy) @@ -125,7 +125,13 @@ static void app_main(void) #endif { + int i; init(); + FOR_NB_SCREENS(i) + { + screens[i].clear_display(); + screens[i].update(); + } tree_gui_init(); root_menu(); } Index: apps/playlist_catalog.c =================================================================== --- apps/playlist_catalog.c (revision 16159) +++ apps/playlist_catalog.c (working copy) @@ -41,7 +41,6 @@ #include "debug.h" #define PLAYLIST_CATALOG_CFG ROCKBOX_DIR "/playlist_catalog.config" -#define PLAYLIST_CATALOG_DEFAULT_DIR "/Playlists" #define MAX_PLAYLISTS 400 #define PLAYLIST_DISPLAY_COUNT 10 @@ -68,7 +67,6 @@ if (!initialized) { int f; - DIR* dir; bool default_dir = true; f = open(PLAYLIST_CATALOG_CFG, O_RDONLY); @@ -96,35 +94,25 @@ /* fall back to default directory if no or invalid config */ if (default_dir) - strncpy(playlist_dir, PLAYLIST_CATALOG_DEFAULT_DIR, - sizeof(playlist_dir)); + strncpy(playlist_dir, DEFAULT_PLAYLIST_DIR, sizeof(playlist_dir)); playlist_dir_length = strlen(playlist_dir); - - dir = opendir(playlist_dir); - if (dir) + playlist_dir_exists=false; + } + if(!playlist_dir_exists) + { + if(playlist_check_dir(playlist_dir)==0) { playlist_dir_exists = true; - closedir(dir); memset(most_recent_playlist, 0, sizeof(most_recent_playlist)); - initialized = true; + initialized = true; } - } - - if (!playlist_dir_exists) - { - if (mkdir(playlist_dir) < 0) { - gui_syncsplash(HZ*2, str(LANG_CATALOG_NO_DIRECTORY), - playlist_dir); + else + { + gui_syncsplash(HZ*2, str(LANG_CATALOG_NO_DIRECTORY), playlist_dir); return -1; } - else { - playlist_dir_exists = true; - memset(most_recent_playlist, 0, sizeof(most_recent_playlist)); - initialized = true; - } } - return 0; } /* Use the filetree functions to retrieve the list of playlists in the Index: firmware/export/font.h =================================================================== --- firmware/export/font.h (revision 16159) +++ firmware/export/font.h (working copy) @@ -46,8 +46,24 @@ #define FONT_HEADER_SIZE 36 #endif -#define GLYPH_CACHE_FILE "/.rockbox/.glyphcache" +#define GLYPH_CACHE_FILE_BRWSR "/.rockbox/.glyphcache-brwsr" +#define GLYPH_CACHE_FILE_WPS "/.rockbox/.glyphcache-wps" +#define GLYPH_CACHE_FILE_MENU "/.rockbox/.glyphcache-menu" +#ifdef CONFIG_TUNER +#define GLYPH_CACHE_FILE_TUNER "/.rockbox/.glyphcache-tuner" +#endif +#ifdef HAVE_RECORDING +#define GLYPH_CACHE_FILE_RECORD "/.rockbox/.glyphcache-record" +#endif +#define GLYPH_CACHE_FILE_USER1 "/.rockbox/.glyphcache-user1" +#define GLYPH_CACHE_FILE_USER2 "/.rockbox/.glyphcache-user2" +#define GLYPH_CACHE_FILE_USER3 "/.rockbox/.glyphcache-user3" +#define GLYPH_CACHE_FILE_USER4 "/.rockbox/.glyphcache-user4" +#define GLYPH_CACHE_FILE_USER5 "/.rockbox/.glyphcache-user5" +#define GLYPH_CACHE_FILE_USER6 "/.rockbox/.glyphcache-user6" +#define GLYPH_CACHE_FILE_USER7 "/.rockbox/.glyphcache-user7" + /* * Fonts are specified by number, and used for display * of menu information as well as mp3 filename data. @@ -60,10 +76,29 @@ */ enum { FONT_SYSFIXED, /* system fixed pitch font*/ - FONT_UI, /* system porportional font*/ + FONT_BROWSER, /* Browser font */ + FONT_WPS, /* WPS font */ + FONT_MENU, /* Settings/menu font */ +#ifdef CONFIG_TUNER + FONT_TUNER, /* FM/radio font */ +#endif +#ifdef HAVE_RECORDING + FONT_RECORD, /* Recording font */ +#endif + FONT_USER1, /* User custom fonts for use in wps */ + FONT_USER2, /* User custom fonts for use in wps */ + FONT_USER3, /* User custom fonts for use in wps */ + FONT_USER4, /* User custom fonts for use in wps */ + FONT_USER5, /* User custom fonts for use in wps */ + FONT_USER6, /* User custom fonts for use in wps */ + FONT_USER7, /* User custom fonts for use in wps */ MAXFONTS }; +/* FIXME: Hack to keep things compiling for now */ +#define FONT_PLUGIN FONT_SYSFIXED +#define FONT_UI FONT_SYSFIXED + /* * .fnt loadable font file format definition * @@ -106,13 +141,13 @@ /* font routines*/ void font_init(void); -struct font* font_load(const char *path); +struct font* font_load(const char *path, int font); struct font* font_get(int font); -void font_reset(void); -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); -void glyph_cache_save(void); +void font_reset(int font); +int font_getstringsize(const unsigned char *str, int *w, int *h, int font); +int font_get_width(struct font* ft, unsigned short ch, int font); +const unsigned char * font_get_bits(struct font* ft, unsigned short ch, int font); +void glyph_cache_save(int font); #else /* HAVE_LCD_BITMAP */ Index: firmware/font.c =================================================================== --- firmware/font.c (revision 16159) +++ firmware/font.c (working copy) @@ -46,35 +46,83 @@ /* compiled-in font */ extern struct font sysfont; -/* structure filled in by font_load */ -static struct font font_ui; +/* font structures filled in by font_load */ +static struct font browserfont; +static struct font wpsfont; +static struct font menufont; +#ifdef CONFIG_TUNER +static struct font tunerfont; +#endif +#ifdef HAVE_RECORDING +static struct font recordfont; +#endif +static struct font userfont1; +static struct font userfont2; +static struct font userfont3; +static struct font userfont4; +static struct font userfont5; +static struct font userfont6; +static struct font userfont7; /* system font table, in order of FONT_xxx definition */ -static struct font* const sysfonts[MAXFONTS] = { &sysfont, &font_ui }; +static struct font* sysfonts[MAXFONTS] = { + &sysfont, + &browserfont, + &wpsfont, + &menufont, +#ifdef CONFIG_TUNER + &tunerfont, +#endif +#ifdef HAVE_RECORDING + &recordfont, +#endif + &userfont1, + &userfont2, + &userfont3, + &userfont4, + &userfont5, + &userfont6, + &userfont7 + }; /* static buffer allocation structures */ -static unsigned char mbuf[MAX_FONT_SIZE]; -static unsigned char *freeptr = mbuf; -static unsigned char *fileptr; -static unsigned char *eofptr; +static unsigned char font_membuf[MAXCACHEFONTS][MAX_FONT_SIZE]; /* Sysfont is compiled-in, no need for buffer */ /* Font cache structures */ -static struct font_cache font_cache_ui; -static int fnt_file = -1; /* >=0 if font is cached */ -uint32_t file_width_offset; /* offset to file width data */ -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; +static struct font_cache sys_font_cache[MAXCACHEFONTS]; +static struct font_file_info fntfile[MAXCACHEFONTS]; +static void cache_create(int maxwidth, int height, int font); +static void font_cache_init(void); /* End Font cache structures */ -static void glyph_cache_load(void); +static void glyph_cache_load(int font); +/* Zero out all font structures */ void font_init(void) { - memset(&font_ui, 0, sizeof(struct font)); + int i = FONT_BROWSER; /* Skip sysfont */ + + while (i < MAXFONTS) + { + memset(sysfonts[i], 0, sizeof(struct font)); + i++; + } + + font_cache_init(); } +void font_cache_init(void) +{ + int i = 0; + + while (i < MAXCACHEFONTS) + { + fntfile[i].font_fd = -1; + i++; + } + return; +} + /* Check if we have x bytes left in the file buffer */ #define HAVEBYTES(x) (fileptr + (x) <= eofptr) @@ -82,126 +130,147 @@ the file buffer. Bounds-checking must be done in the calling function. */ - -static short readshort(void) + +static short readshort(unsigned short *sp, int font) { unsigned short s; - s = *fileptr++ & 0xff; - s |= (*fileptr++ << 8); - return s; + s = *fntfile[font].fileptr++ & 0xff; + *sp = (*fntfile[font].fileptr++ << 8) | s; + return (fntfile[font].fileptr <= fntfile[font].eofptr); } -static int32_t readlong(void) +static int32_t readlong(uint32_t *lp, int font) { uint32_t l; - l = *fileptr++ & 0xff; - l |= *fileptr++ << 8; - l |= ((uint32_t)(*fileptr++)) << 16; - l |= ((uint32_t)(*fileptr++)) << 24; - return l; + l = *fntfile[font].fileptr++ & 0xff; + l |= *fntfile[font].fileptr++ << 8; + l |= ((uint32_t)(*fntfile[font].fileptr++)) << 16; + l |= ((uint32_t)(*fntfile[font].fileptr++)) << 24; + *lp = l; + return (fntfile[font].fileptr <= fntfile[font].eofptr); } /* read count bytes*/ -static void readstr(char *buf, int count) +static int readstr(char *buf, int count, int font) { - while (count--) - *buf++ = *fileptr++; + int n = count; + + while (--n >= 0) + *buf++ = *fntfile[font].fileptr++; + + return (fntfile[font].fileptr <= fntfile[font].eofptr)? count: 0; } -void font_reset(void) +void font_reset(int font) { - memset(&font_ui, 0, sizeof(struct font)); + memset(sysfonts[font], 0, sizeof(struct font)); } -static struct font* font_load_header(struct font *pf) +static struct font* font_load_header(struct font *pf, int font) { char version[4+1]; + unsigned short maxwidth, height, ascent, pad; + uint32_t firstchar, defaultchar, size; + uint32_t nbits; - /* Check we have enough data */ - if (!HAVEBYTES(28)) - return NULL; - /* read magic and version #*/ memset(version, 0, sizeof(version)); - readstr(version, 4); + if (readstr(version, 4, font) != 4) + return NULL; if (strcmp(version, VERSION) != 0) return NULL; /* font info*/ - pf->maxwidth = readshort(); - pf->height = readshort(); - pf->ascent = readshort(); - fileptr += 2; /* Skip padding */ - pf->firstchar = readlong(); - pf->defaultchar = readlong(); - pf->size = readlong(); + if (!readshort(&maxwidth, font)) + return NULL; + pf->maxwidth = maxwidth; + if (!readshort(&height, font)) + return NULL; + pf->height = height; + + if (!readshort(&ascent, font)) + return NULL; + pf->ascent = ascent; + + if (!readshort(&pad, font)) + return NULL; + + if (!readlong(&firstchar, font)) + return NULL; + pf->firstchar = firstchar; + + if (!readlong(&defaultchar, font)) + return NULL; + pf->defaultchar = defaultchar; + + if (!readlong(&size, font)) + return NULL; + pf->size = size; + /* get variable font data sizes*/ /* # words of bitmap_t*/ - pf->bits_size = readlong(); + if (!readlong(&nbits, font)) + return NULL; + pf->bits_size = nbits; return pf; } /* Load memory font */ -static struct font* font_load_in_memory(struct font* pf) +static struct font* font_load_in_memory(struct font* pf, int font) { int32_t i, noffset, nwidth; - if (!HAVEBYTES(4)) + /* # longs of offset*/ + if (!readlong(&noffset, font)) return NULL; - /* # longs of offset*/ - noffset = readlong(); - /* # bytes of width*/ - nwidth = readlong(); + if (!readlong(&nwidth, font)) + return NULL; /* variable font data*/ - pf->bits = (unsigned char *)fileptr; - fileptr += pf->bits_size*sizeof(unsigned char); + pf->bits = (unsigned char *)fntfile[font].fileptr; + fntfile[font].fileptr += pf->bits_size*sizeof(unsigned char); if ( pf->bits_size < 0xFFDB ) { /* pad to 16-bit boundary */ - fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 1) & ~1); } else { /* pad to 32-bit boundary*/ - fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 3) & ~3); } if (noffset) { if ( pf->bits_size < 0xFFDB ) { - long_offset = 0; - pf->offset = (unsigned short *)fileptr; - - /* Check we have sufficient buffer */ - if (!HAVEBYTES(noffset * sizeof(short))) - return NULL; - + fntfile[font].long_offset = 0; + pf->offset = (unsigned short *)fntfile[font].fileptr; for (i=0; ioffset))[i] = (unsigned short)readshort(); + unsigned short offset; + if (!readshort(&offset, font)) + return NULL; + ((unsigned short*)(pf->offset))[i] = (unsigned short)offset; } } else { - long_offset = 1; - pf->offset = (unsigned short *)fileptr; - - /* Check we have sufficient buffer */ - if (!HAVEBYTES(noffset * sizeof(int32_t))) - return NULL; - + fntfile[font].long_offset = 1; + pf->offset = (unsigned short *)fntfile[font].fileptr; for (i=0; ioffset))[i] = (uint32_t)readlong(); + uint32_t offset; + if (!readlong(&offset, font)) + return NULL; + ((uint32_t*)(pf->offset))[i] = (uint32_t)offset; } } } @@ -209,140 +278,140 @@ pf->offset = NULL; if (nwidth) { - pf->width = (unsigned char *)fileptr; - fileptr += nwidth*sizeof(unsigned char); + pf->width = (unsigned char *)fntfile[font].fileptr; + fntfile[font].fileptr += nwidth*sizeof(unsigned char); } else pf->width = NULL; - if (fileptr > eofptr) + if (fntfile[font].fileptr > fntfile[font].eofptr) return NULL; return pf; /* success!*/ } /* Load cached font */ -static struct font* font_load_cached(struct font* pf) +static struct font* font_load_cached(struct font* pf, int font) { uint32_t noffset, nwidth; - unsigned char* oldfileptr = fileptr; + unsigned char* oldfileptr = fntfile[font].fileptr; - if (!HAVEBYTES(2 * sizeof(int32_t))) + /* # longs of offset*/ + if (!readlong(&noffset, font)) return NULL; - /* # longs of offset*/ - noffset = readlong(); - /* # bytes of width*/ - nwidth = readlong(); + if (!readlong(&nwidth, font)) + return NULL; /* We are now at the bitmap data, this is fixed at 36.. */ pf->bits = NULL; /* Calculate offset to offset data */ - fileptr += pf->bits_size * sizeof(unsigned char); + fntfile[font].fileptr += pf->bits_size * sizeof(unsigned char); if ( pf->bits_size < 0xFFDB ) { - long_offset = 0; + fntfile[font].long_offset = 0; /* pad to 16-bit boundary */ - fileptr = (unsigned char *)(((intptr_t)fileptr + 1) & ~1); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 1) & ~1); } else { - long_offset = 1; + fntfile[font].long_offset = 1; /* pad to 32-bit boundary*/ - fileptr = (unsigned char *)(((intptr_t)fileptr + 3) & ~3); + fntfile[font].fileptr = (unsigned char *)(((intptr_t)fntfile[font].fileptr + 3) & ~3); } if (noffset) - file_offset_offset = (uint32_t)(fileptr - freeptr); + fntfile[font].file_offset_offset = (uint32_t)(fntfile[font].fileptr - fntfile[font].freeptr); else - file_offset_offset = 0; + fntfile[font].file_offset_offset = 0; /* Calculate offset to widths data */ if ( pf->bits_size < 0xFFDB ) - fileptr += noffset * sizeof(unsigned short); + fntfile[font].fileptr += noffset * sizeof(unsigned short); else - fileptr += noffset * sizeof(uint32_t); + fntfile[font].fileptr += noffset * sizeof(uint32_t); if (nwidth) - file_width_offset = (uint32_t)(fileptr - freeptr); + fntfile[font].file_width_offset = (uint32_t)(fntfile[font].fileptr - fntfile[font].freeptr); else - file_width_offset = 0; + fntfile[font].file_width_offset = 0; - fileptr = oldfileptr; + fntfile[font].fileptr = oldfileptr; /* Create the cache */ - cache_create(pf->maxwidth, pf->height); + cache_create(pf->maxwidth, pf->height, font); return pf; } /* read and load font into incore font structure*/ -struct font* font_load(const char *path) +struct font* font_load(const char *path, int _font) { int size; - struct font* pf = &font_ui; + int font = _font - 1; /* cache index vs global font index */ + struct font* pf = sysfonts[_font]; /* save loaded glyphs */ - glyph_cache_save(); + glyph_cache_save(font); /* Close font file handle */ - if (fnt_file >= 0) - close(fnt_file); + if (fntfile[font].font_fd >= 0) + close(fntfile[font].font_fd); /* open and read entire font file*/ - fnt_file = open(path, O_RDONLY|O_BINARY); + fntfile[font].font_fd = open(path, O_RDONLY|O_BINARY); - if (fnt_file < 0) { + if (fntfile[font].font_fd < 0) { DEBUGF("Can't open font: %s\n", path); return NULL; } /* Check file size */ - size = filesize(fnt_file); + size = filesize(fntfile[font].font_fd); - font_reset(); + font_reset(_font); /* currently, font loading replaces earlier font allocation*/ - freeptr = (unsigned char *)(((intptr_t)mbuf + 3) & ~3); - fileptr = freeptr; + fntfile[font].freeptr = (unsigned char *)(((intptr_t)font_membuf[font] + 3) & ~3); + fntfile[font].fileptr = fntfile[font].freeptr; if (size > MAX_FONT_SIZE) { - read(fnt_file, fileptr, FONT_HEADER_SIZE); - eofptr = fileptr + FONT_HEADER_SIZE; + read(fntfile[font].font_fd, fntfile[font].fileptr, FONT_HEADER_SIZE); + fntfile[font].eofptr = fntfile[font].fileptr + FONT_HEADER_SIZE; - if (!font_load_header(pf)) + if (!font_load_header(pf, font)) { DEBUGF("Failed font header load"); return NULL; } - if (!font_load_cached(pf)) + if (!font_load_cached(pf, font)) { DEBUGF("Failed font cache load"); return NULL; } - glyph_cache_load(); + glyph_cache_load(font); } else { - read(fnt_file, fileptr, MAX_FONT_SIZE); - eofptr = fileptr + size; - close(fnt_file); - fnt_file = -1; + read(fntfile[font].font_fd, fntfile[font].fileptr, MAX_FONT_SIZE); + fntfile[font].eofptr = fntfile[font].fileptr + size; + close(fntfile[font].font_fd); + fntfile[font].font_fd = -1; - if (!font_load_header(pf)) + if (!font_load_header(pf, font)) { DEBUGF("Failed font header load"); return NULL; } - if (!font_load_in_memory(pf)) + if (!font_load_in_memory(pf, font)) { DEBUGF("Failed mem load"); return NULL; @@ -359,13 +428,25 @@ /* * Return a pointer to an incore font structure. * If the requested font isn't loaded/compiled-in, - * decrement the font number and try again. + * (decrement the font number and try again) + * MWE return sysfont instead + * */ -struct font* font_get(int font) +struct font *font_get(int font) { - struct font* pf; + struct font *pf; - if (font >= MAXFONTS) + if (font >= MAXFONTS){ + return &sysfont; + } + + pf = sysfonts[font]; + if (pf && pf->height) + return pf; + + return &sysfont; + +/* if (font >= MAXFONTS) font = 0; while (1) { @@ -374,14 +455,14 @@ return pf; if (--font < 0) panicf("No font!"); - } + }*/ } /* * Returns the stringsize of a given string. */ -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 font) { - struct font* pf = font_get(fontnumber); + struct font* pf = font_get(font); unsigned short ch; int width = 0; @@ -389,7 +470,7 @@ { /* get proportional width and glyph bits*/ - width += font_get_width(pf,ch); + width += font_get_width(pf, ch, font); } if ( w ) *w = width; @@ -402,17 +483,17 @@ * Reads an entry into cache entry */ static void -load_cache_entry(struct font_cache_entry* p, void* callback_data) +load_cache_entry(struct font_cache_entry* p, void* callback_data, int font) { struct font* pf = callback_data; unsigned short char_code = p->_char_code; unsigned char tmp[2]; - if (file_width_offset) + if (fntfile[font].file_width_offset) { - int width_offset = file_width_offset + char_code; - lseek(fnt_file, width_offset, SEEK_SET); - read(fnt_file, &(p->width), 1); + int width_offset = fntfile[font].file_width_offset + char_code; + lseek(fntfile[font].font_fd, width_offset, SEEK_SET); + read(fntfile[font].font_fd, &(p->width), 1); } else { @@ -421,14 +502,14 @@ int32_t bitmap_offset = 0; - if (file_offset_offset) + if (fntfile[font].file_offset_offset) { - int32_t offset = file_offset_offset + char_code * (long_offset ? sizeof(int32_t) : sizeof(short)); - lseek(fnt_file, offset, SEEK_SET); - read (fnt_file, tmp, 2); + int32_t offset = fntfile[font].file_offset_offset + char_code * (fntfile[font].long_offset ? sizeof(int32_t) : sizeof(short)); + lseek(fntfile[font].font_fd, offset, SEEK_SET); + read (fntfile[font].font_fd, tmp, 2); bitmap_offset = tmp[0] | (tmp[1] << 8); - if (long_offset) { - read (fnt_file, tmp, 2); + if (fntfile[font].long_offset) { + read (fntfile[font].font_fd, tmp, 2); bitmap_offset |= (tmp[0] << 16) | (tmp[1] << 24); } } @@ -438,117 +519,205 @@ } int32_t file_offset = FONT_HEADER_SIZE + bitmap_offset; - lseek(fnt_file, file_offset, SEEK_SET); + lseek(fntfile[font].font_fd, file_offset, SEEK_SET); int src_bytes = p->width * ((pf->height + 7) / 8); - read(fnt_file, p->bitmap, src_bytes); + read(fntfile[font].font_fd, p->bitmap, src_bytes); } /* * Converts cbuf into a font cache */ -static void cache_create(int maxwidth, int height) +static void cache_create(int maxwidth, int height, int font) { /* maximum size of rotated bitmap */ int bitmap_size = maxwidth * ((height + 7) / 8); /* Initialise cache */ - font_cache_create(&font_cache_ui, mbuf, MAX_FONT_SIZE, bitmap_size); + font_cache_create(&sys_font_cache[font], &font_membuf[font], MAX_FONT_SIZE, bitmap_size); } /* * Returns width of character */ -int font_get_width(struct font* pf, unsigned short char_code) +int font_get_width(struct font* pf, unsigned short char_code, int font) { /* check input range*/ if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) char_code = pf->defaultchar; char_code -= pf->firstchar; - return (fnt_file >= 0 && pf != &sysfont)? - font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->width: - pf->width? pf->width[char_code]: pf->maxwidth; + if (pf == &sysfont || fntfile[font-1].font_fd < 0) /* sysfont or loaded into mem */ + { + if (pf->width) + return pf->width[char_code]; + else + return pf->maxwidth; + } + else /* cached */ + return font_cache_get(&sys_font_cache[font-1], char_code, load_cache_entry, pf, font-1)->width; } -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, int font) { const unsigned char* bits; /* check input range*/ if (char_code < pf->firstchar || char_code >= pf->firstchar+pf->size) char_code = pf->defaultchar; - char_code -= pf->firstchar; + char_code -= pf->firstchar; - if (fnt_file >= 0 && pf != &sysfont) - { - bits = - (unsigned char*)font_cache_get(&font_cache_ui,char_code,load_cache_entry,pf)->bitmap; + if (font <= 0 || fntfile[font-1].font_fd < 0) /* sysfont */ + bits = pf->bits + (pf->offset?pf->offset[char_code]:(((pf->height + 7) / 8) * pf->maxwidth * char_code)); + else + bits = (unsigned char*)font_cache_get(&sys_font_cache[font-1], char_code, load_cache_entry, pf, font-1)->bitmap; + + return bits; } - else + +static void glyph_file_write(void* data, int font) { - bits = pf->bits + (pf->offset? - pf->offset[char_code]: - (((pf->height + 7) / 8) * pf->maxwidth * char_code)); - } - - return bits; -} + struct font_cache_entry* p = data; + struct font* pf = sysfonts[font]; + unsigned short ch; + unsigned char tmp[2]; -static void glyph_file_write(void* data) -{ - struct font_cache_entry* p = data; - struct font* pf = &font_ui; - unsigned short ch; - unsigned char tmp[2]; + ch = p->_char_code + pf->firstchar; - ch = p->_char_code + pf->firstchar; + if (p->_char_code != 0xffff && fntfile[font].glyph_fd >= 0) { + tmp[0] = p->_char_code >> 8; + tmp[1] = p->_char_code & 0xff; - if (ch != 0xffff && glyph_file >= 0) { - tmp[0] = ch >> 8; - tmp[1] = ch & 0xff; - if (write(glyph_file, tmp, 2) != 2) { - close(glyph_file); - glyph_file = -1; + if (write(fntfile[font].glyph_fd, tmp, 2) != 2) { + close(fntfile[font].glyph_fd); + fntfile[font].glyph_fd = -1; + } } + return; } - return; -} -/* save the char codes of the loaded glyphs to a file */ -void glyph_cache_save(void) -{ + /* save the char codes of the loaded glyphs to a file */ +void glyph_cache_save(int font) + { - if (fnt_file >= 0) { + if (fntfile[font].font_fd >= 0) { - glyph_file = creat(GLYPH_CACHE_FILE); + switch (font) + { + case 0: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_BRWSR); + break; + case 1: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_WPS); + break; + case 2: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_MENU); + break; +#ifdef CONFIG_TUNER + case 3: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_TUNER); + break; +#endif +#ifdef HAVE_RECORDING + case 4: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_RECORD); + break; +#endif + case 5: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER1); + break; + case 6: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER2); + break; + case 7: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER3); + break; + case 8: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER4); + break; + case 9: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER5); + break; + case 10: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER6); + break; + case 11: + fntfile[font].glyph_fd = creat(GLYPH_CACHE_FILE_USER7); + break; + default: + return; + } - if (glyph_file < 0) return; + if (fntfile[font].glyph_fd < 0) return; - lru_traverse(&font_cache_ui._lru, glyph_file_write); + lru_traverse(&sys_font_cache[font]._lru, glyph_file_write, font); - if (glyph_file >= 0) - close(glyph_file); + if (fntfile[font].glyph_fd >= 0) + close(fntfile[font].glyph_fd); + } + return; } - return; -} -static void glyph_cache_load(void) -{ - if (fnt_file >= 0) { +static void glyph_cache_load(int font) + { + if (fntfile[font].font_fd >= 0) { int fd; unsigned char tmp[2]; unsigned short ch; - struct font* pf = &font_ui; + struct font* pf = sysfonts[font]; - fd = open(GLYPH_CACHE_FILE, O_RDONLY|O_BINARY); + switch (font) + { + case 0: + fd = open(GLYPH_CACHE_FILE_BRWSR, O_RDONLY|O_BINARY); + break; + case 1: + fd = open(GLYPH_CACHE_FILE_WPS, O_RDONLY|O_BINARY); + break; + case 2: + fd = open(GLYPH_CACHE_FILE_MENU, O_RDONLY|O_BINARY); + break; +#ifdef CONFIG_TUNER + case 3: + fd = open(GLYPH_CACHE_FILE_TUNER, O_RDONLY|O_BINARY); + break; +#endif +#ifdef HAVE_RECORDING + case 4: + fd = open(GLYPH_CACHE_FILE_RECORD, O_RDONLY|O_BINARY); + break; +#endif + case 5: + fd = open(GLYPH_CACHE_FILE_USER1, O_RDONLY|O_BINARY); + break; + case 6: + fd = open(GLYPH_CACHE_FILE_USER2, O_RDONLY|O_BINARY); + break; + case 7: + fd = open(GLYPH_CACHE_FILE_USER3, O_RDONLY|O_BINARY); + break; + case 8: + fd = open(GLYPH_CACHE_FILE_USER4, O_RDONLY|O_BINARY); + break; + case 9: + fd = open(GLYPH_CACHE_FILE_USER5, O_RDONLY|O_BINARY); + break; + case 10: + fd = open(GLYPH_CACHE_FILE_USER6, O_RDONLY|O_BINARY); + break; + case 11: + fd = open(GLYPH_CACHE_FILE_USER7, O_RDONLY|O_BINARY); + break; + default: + return; + } if (fd >= 0) { while (read(fd, tmp, 2) == 2) { ch = (tmp[0] << 8) | tmp[1]; - font_get_bits(pf, ch); + font_get_bits(pf, ch, font); } close(fd); @@ -556,7 +725,7 @@ /* load latin1 chars into cache */ ch = 256; while (ch-- > 32) - font_get_bits(pf, ch); + font_get_bits(pf, ch, font); } } return; Index: firmware/font_cache.c =================================================================== --- firmware/font_cache.c (revision 16159) +++ firmware/font_cache.c (working copy) @@ -23,8 +23,9 @@ /******************************************************************************* * font_cache_lru_init ******************************************************************************/ -void font_cache_lru_init(void* data) +void font_cache_lru_init(void* data, int font) { + font = 0; /* Kill gcc warning */ struct font_cache_entry* p = data; p->_char_code = 0xffff; /* assume invalid char */ } @@ -60,7 +61,7 @@ lru_create(&fcache->_lru, lru_buf, cache_size, font_cache_entry_size); /* initialise cache */ - lru_traverse(&fcache->_lru, font_cache_lru_init); + lru_traverse(&fcache->_lru, font_cache_lru_init, 0); /* font parameter not needed for callback */ short i; for (i = 0; i < cache_size; i++) fcache->_index[i] = i; /* small cheat here */ @@ -158,8 +159,8 @@ struct font_cache_entry* font_cache_get( struct font_cache* fcache, unsigned short char_code, - void (*callback) (struct font_cache_entry* p, void *callback_data), - void *callback_data) + void (*callback) (struct font_cache_entry* p, void *callback_data, int font), + void *callback_data, int font) { int insertion_point = font_cache_insertion_point(fcache, char_code); if (insertion_point >= 0) @@ -207,7 +208,7 @@ fcache->_size++; p->_char_code = char_code; - callback(p, callback_data); + callback(p, callback_data, font); return p; } Index: firmware/lru.c =================================================================== --- firmware/lru.c (revision 16159) +++ firmware/lru.c (working copy) @@ -57,7 +57,7 @@ /******************************************************************************* * lru_traverse ******************************************************************************/ -void lru_traverse(struct lru* pl, void (*callback)(void* data)) +void lru_traverse(struct lru* pl, void (*callback)(void* data, int font), int font) { short i; struct lru_node* slot; @@ -66,7 +66,7 @@ for (i = 0; i < pl->_size; i++) { slot = lru_node_p(pl, loc); - callback(slot->data); + callback(slot->data, font); loc = slot->_next; } } Index: firmware/include/font_cache.h =================================================================== --- firmware/include/font_cache.h (revision 16159) +++ firmware/include/font_cache.h (working copy) @@ -21,6 +21,10 @@ /******************************************************************************* * ******************************************************************************/ + +/* Maximum loadable/cacheable fonts. Exclude sysfont since it's compiled in */ +#define MAXCACHEFONTS MAXFONTS-1 + struct font_cache { struct lru _lru; @@ -36,6 +40,19 @@ unsigned char bitmap[1]; /* place holder */ }; +/* Per-font internal cache struct */ +struct font_file_info +{ + unsigned long file_width_offset; /* offset to file width data */ + unsigned long file_offset_offset; /* offset to file offset data */ + int long_offset; + int glyph_fd; + unsigned char *freeptr; + unsigned char *fileptr; + unsigned char *eofptr; + int font_fd; /* >=0 if font is cached */ +}; + /* void (*f) (void*, struct font_cache_entry*); */ /* Create an auto sized font cache from buf */ void font_cache_create( @@ -44,5 +61,5 @@ struct font_cache_entry* font_cache_get( struct font_cache* fcache, unsigned short char_code, - void (*callback) (struct font_cache_entry* p, void *callback_data), - void *callback_data); + void (*callback) (struct font_cache_entry* p, void *callback_data, int font), + void *callback_data, int font); Index: firmware/include/lru.h =================================================================== --- firmware/include/lru.h (revision 16159) +++ firmware/include/lru.h (working copy) @@ -40,7 +40,7 @@ /* Data */ void *lru_data(struct lru* pl, short handle); /* Traverse lru-wise */ -void lru_traverse(struct lru* pl, void (*callback)(void* data)); +void lru_traverse(struct lru* pl, void (*callback)(void* data, int font), int font); #endif /* LRU_H */ Index: firmware/powermgmt.c =================================================================== --- firmware/powermgmt.c (revision 16159) +++ firmware/powermgmt.c (working copy) @@ -1187,7 +1187,12 @@ audio_stop(); if (battery_level_safe()) { /* do not save on critical battery */ #ifdef HAVE_LCD_BITMAP - glyph_cache_save(); + int i = FONT_BROWSER; /* Skip sysfont, even though glyph_cache_save() would ignore it */ + while (i < MAXFONTS) + { + glyph_cache_save(i); + i++; + } #endif if(ata_disk_is_active()) ata_spindown(1); Index: firmware/drivers/lcd-remote-2bit-vi.c =================================================================== --- firmware/drivers/lcd-remote-2bit-vi.c (revision 16159) +++ firmware/drivers/lcd-remote-2bit-vi.c (working copy) @@ -1031,7 +1031,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf, ch); + width = font_get_width(pf, ch, current_vp->font); if (ofs > width) { @@ -1039,7 +1039,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_remote_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-2bit-vert.c =================================================================== --- firmware/drivers/lcd-2bit-vert.c (revision 16159) +++ firmware/drivers/lcd-2bit-vert.c (working copy) @@ -1035,7 +1035,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf,ch); + width = font_get_width(pf,ch, current_vp->font); if (ofs > width) { @@ -1043,7 +1043,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-2bit-horz.c =================================================================== --- firmware/drivers/lcd-2bit-horz.c (revision 16159) +++ firmware/drivers/lcd-2bit-horz.c (working copy) @@ -897,7 +897,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf,ch); + width = font_get_width(pf,ch,current_vp->font); if (ofs > width) { @@ -905,7 +905,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-16bit.c =================================================================== --- firmware/drivers/lcd-16bit.c (revision 16159) +++ firmware/drivers/lcd-16bit.c (working copy) @@ -926,7 +926,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf,ch); + width = font_get_width(pf,ch,current_vp->font); if (ofs > width) { @@ -934,7 +934,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_mono_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height); Index: firmware/drivers/lcd-remote-1bit-v.c =================================================================== --- firmware/drivers/lcd-remote-1bit-v.c (revision 16159) +++ firmware/drivers/lcd-remote-1bit-v.c (working copy) @@ -682,7 +682,7 @@ const unsigned char *bits; /* get proportional width and glyph bits */ - width = font_get_width(pf, ch); + width = font_get_width(pf, ch, current_vp->font); if (ofs > width) { @@ -690,7 +690,7 @@ continue; } - bits = font_get_bits(pf, ch); + bits = font_get_bits(pf, ch, current_vp->font); lcd_remote_bitmap_part(bits, ofs, 0, width, x, y, width - ofs, pf->height);