Index: apps/recorder/bmp.c =================================================================== --- apps/recorder/bmp.c (révision 16132) +++ apps/recorder/bmp.c (copie de travail) @@ -180,6 +180,7 @@ int depth, numcolors, compression, totalsize; int row, col, ret; int rowstart, rowstop, rowstep; + int currpos; unsigned char *bitmap = bm->data; uint32_t bmpbuf[LCD_WIDTH]; /* Buffer for one line */ @@ -223,6 +224,8 @@ return -3; } + currpos = sizeof(struct bmp_header); + width = readlong(&bmph.width); if (width > LCD_WIDTH) { DEBUGF("read_bmp_fd: Bitmap too wide (%d pixels, max is %d)\n", @@ -314,6 +317,7 @@ DEBUGF("read_bmp_fd: Can't read color palette\n"); return -7; } + currpos += numcolors * sizeof(uint32_t); } switch (depth) { @@ -353,7 +357,7 @@ } /* Search to the beginning of the image data */ - lseek(fd, (off_t)readlong(&bmph.off_bits), SEEK_SET); + lseek(fd, (off_t)readlong(&bmph.off_bits) - currpos, SEEK_CUR); memset(bitmap, 0, totalsize); Index: apps/gui/backdrop.c =================================================================== --- apps/gui/backdrop.c (révision 16132) +++ apps/gui/backdrop.c (copie de travail) @@ -20,6 +20,7 @@ #include #include "config.h" #include "lcd.h" +#include "file.h" #ifdef HAVE_REMOTE_LCD #include "lcd-remote.h" #endif @@ -42,15 +43,15 @@ static bool wps_backdrop_valid = false; /* load a backdrop into a buffer */ -static bool load_backdrop(char* filename, fb_data* backdrop_buffer) +static bool load_backdrop_fd(int fd, fb_data* backdrop_buffer) { struct bitmap bm; int ret; /* load the image */ bm.data=(char*)backdrop_buffer; - ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), - FORMAT_NATIVE | FORMAT_DITHER); + ret = read_bmp_fd(fd, &bm, sizeof(main_backdrop), + FORMAT_NATIVE | FORMAT_DITHER); if ((ret > 0) && (bm.width == LCD_WIDTH) && (bm.height == LCD_HEIGHT)) { @@ -62,6 +63,17 @@ } } +static bool load_backdrop(char* filename, fb_data* backdrop_buffer) +{ + bool ret; + int fd = open(filename, O_RDONLY); + if (fd < 0) + return false; + ret = load_backdrop_fd(fd, backdrop_buffer); + close(fd); + return ret; +} + bool load_main_backdrop(char* filename) { main_backdrop_valid = load_backdrop(filename, &main_backdrop[0][0]); @@ -74,6 +86,12 @@ return wps_backdrop_valid; } +bool load_wps_backdrop_fd(int fd) +{ + wps_backdrop_valid = load_backdrop_fd(fd, &wps_backdrop[0][0]); + return wps_backdrop_valid; +} + void unload_main_backdrop(void) { main_backdrop_valid = false; @@ -104,15 +122,15 @@ #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 -static bool load_remote_backdrop(char* filename, fb_remote_data* backdrop_buffer) +static bool load_remote_backdrop_fd(int fd, fb_remote_data* backdrop_buffer) { struct bitmap bm; int ret; /* load the image */ bm.data=(char*)backdrop_buffer; - ret = read_bmp_file(filename, &bm, sizeof(main_backdrop), - FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE); + ret = read_bmp_fd(fd, &bm, sizeof(main_backdrop), + FORMAT_NATIVE | FORMAT_DITHER | FORMAT_REMOTE); if ((ret > 0) && (bm.width == LCD_REMOTE_WIDTH) && (bm.height == LCD_REMOTE_HEIGHT)) { @@ -124,12 +142,29 @@ } } +static bool load_remote_backdrop(char* filename, fb_remote_data* backdrop_buffer) +{ + bool ret; + int fd = open(filename, O_RDONLY); + if (fd < 0) + return false; + ret = load_remote_backdrop_fd(fd, backdrop_buffer); + close(fd); + return ret; +} + bool load_remote_wps_backdrop(char* filename) { remote_wps_backdrop_valid = load_remote_backdrop(filename, &remote_wps_backdrop[0][0]); return remote_wps_backdrop_valid; } +bool load_remote_wps_backdrop_fd(int fd) +{ + remote_wps_backdrop_valid = load_remote_backdrop_fd(fd, &remote_wps_backdrop[0][0]); + return remote_wps_backdrop_valid; +} + void unload_remote_wps_backdrop(void) { remote_wps_backdrop_valid = false; Index: apps/gui/wps_parser.c =================================================================== --- apps/gui/wps_parser.c (révision 16132) +++ apps/gui/wps_parser.c (copie de travail) @@ -361,37 +361,6 @@ return skip_end_of_line(wps_bufptr); } -static bool load_bitmap(struct wps_data *wps_data, - char* filename, - struct bitmap *bm) -{ - int format; -#ifdef HAVE_REMOTE_LCD - if (wps_data->remote_wps) - format = FORMAT_ANY|FORMAT_REMOTE; - else -#endif - format = FORMAT_ANY|FORMAT_TRANSPARENT; - - int ret = read_bmp_file(filename, bm, - wps_data->img_buf_free, - format); - - if (ret > 0) - { -#if LCD_DEPTH == 16 - if (ret % 2) ret++; - /* Always consume an even number of bytes */ -#endif - wps_data->img_buf_ptr += ret; - wps_data->img_buf_free -= ret; - - return true; - } - else - return false; -} - static int get_image_id(int c) { if(c >= 'a' && c <= 'z') @@ -402,9 +371,13 @@ return -1; } +/* Read a bitmap filename in the WPS at start and return the full path to that + bitmap in buf by appending it to bmpdir. + bmpdir can be NULL to only get the filename in buf. */ static char *get_image_filename(const char *start, const char* bmpdir, char *buf, int buf_size) { + int bmpdirlen = 0; const char *end = strchr(start, '|'); if ( !end || (end - start) >= (buf_size - ROCKBOX_DIR_LEN - 2) ) @@ -413,12 +386,15 @@ return NULL; } - int bmpdirlen = strlen(bmpdir); + if (bmpdir) + { + bmpdirlen = strlen(bmpdir); + strcpy(buf, bmpdir); + buf[bmpdirlen++] = '/'; + } - strcpy(buf, bmpdir); - buf[bmpdirlen] = '/'; - memcpy( &buf[bmpdirlen + 1], start, end - start); - buf[bmpdirlen + 1 + end - start] = 0; + memcpy( &buf[bmpdirlen], start, end - start); + buf[bmpdirlen + end - start] = 0; return buf; } @@ -1229,7 +1205,6 @@ #ifdef HAVE_LCD_BITMAP - static void clear_bmp_names(void) { int n; @@ -1239,6 +1214,188 @@ } } +static bool load_bitmap(struct wps_data *wps_data, + char* filename, int fd, + struct bitmap *bm) +{ + int format, ret; +#ifdef HAVE_REMOTE_LCD + if (wps_data->remote_wps) + format = FORMAT_ANY|FORMAT_REMOTE; + else +#endif + format = FORMAT_ANY|FORMAT_TRANSPARENT; + + bm->data = wps_data->img_buf_ptr; + if (filename) + { + ret = read_bmp_file(filename, bm, wps_data->img_buf_free, format); + } + else if (fd >= 0) + { + ret = read_bmp_fd(fd, bm, wps_data->img_buf_free, format); + } + else + return false; + + if (ret > 0) + { +#if LCD_DEPTH == 16 + if (ret % 2) ret++; + /* Always consume an even number of bytes */ +#endif + wps_data->img_buf_ptr += ret; + wps_data->img_buf_free -= ret; + + return true; + } + else + return false; +} + +/* Process a tar file header. Confirm that the filename in header + is the same as the parameter, and return the location in the tar + file of the next file (or 0 if no more files). Returns -1 if the + filenames don't match. + + A tar file consists of one or more files, each preceeded by + a 512-byte tar header block. The files themselves are padded + to a multiple of 512 bytes. +*/ +int process_tar_header(int fd, unsigned char *buf, int bufsize) +{ + int nextpos; + int n, len, i; + unsigned char *tar_header = buf; + + /* We only need the first 136 bytes */ + if (bufsize < 136) + return -1; + n = read(fd, tar_header, 136); + i = strlen(tar_header); + + /* Parse the filesize field */ + len = 0; + for (i = 124 ; i < 124 + 11 ; i++) { + len = (8 * len) + tar_header[i] - '0'; + } + /* Round length up to next multiple of 512 */ + len = (len + 511) & (~511); + + /* Skip rest of header */ + nextpos = lseek(fd, 512 - 136, SEEK_CUR); + + /* Calculate start of next file */ + nextpos += len; + + if (nextpos >= filesize(fd)) { + return 0; + } else { + return nextpos; + } +} + +#if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) +static void load_backdrop_bitmap(struct wps_data *wps_data, char *bmpdir, + int tar_fd) +{ + char img_path[MAX_PATH]; + (void)wps_data; + + if (bmp_names[BACKDROP_BMP]) + { + if (tar_fd < 0) + get_image_filename(bmp_names[BACKDROP_BMP], bmpdir, + img_path, sizeof(img_path)); +#ifdef HAVE_REMOTE_LCD + if (wps_data->remote_wps) + { +#if LCD_REMOTE_DEPTH > 1 + if (tar_fd < 0) + load_remote_wps_backdrop(img_path); + else + load_remote_wps_backdrop_fd(tar_fd); +#endif + } + else +#endif /* HAVE_REMOTE_LCD */ + { + if (tar_fd < 0) + load_wps_backdrop(img_path); + else + load_wps_backdrop_fd(tar_fd); + } + } +} +#endif /* has backdrop support */ + +static void load_wps_bitmaps_tar(struct wps_data *wps_data, int tar_fd) +{ + char img_path[MAX_PATH]; + struct bitmap *bitmap; + bool *loaded; + int n; + int nextpos = 0; + unsigned char tar_header[136]; + + do + { + /* load image name from the .tar */ + nextpos = process_tar_header(tar_fd, tar_header, + sizeof(tar_header)); + + /* look for the image's index in the WPS */ + for (n = 0; n <= BACKDROP_BMP; n++) + { + if (bmp_names[n]) + { + get_image_filename(bmp_names[n], NULL, + img_path, sizeof(img_path)); + + if ( !wps_data->img[n].loaded + && strcmp(tar_header, img_path) == 0 ) + { + + if (n == PROGRESSBAR_BMP) { + /* progressbar bitmap */ + bitmap = &wps_data->progressbar.bm; + loaded = &wps_data->progressbar.have_bitmap_pb; + DEBUGF("tar: %s -> progressbar. ", tar_header); + } +#if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) + else if (n == BACKDROP_BMP) { + /* Load the backdrop */ + DEBUGF("tar: %s -> backdrop. ", tar_header); + load_backdrop_bitmap(wps_data, NULL, tar_fd); + continue; + } +#endif + else { + /* regular bitmap */ + bitmap = &wps_data->img[n].bm; + loaded = &wps_data->img[n].loaded; + DEBUGF("tar: %s -> %d. ", tar_header, n); + } + + /* we found the index for the picture : load it */ + if (load_bitmap(wps_data, NULL, tar_fd, + &wps_data->img[n].bm)) + { + *loaded = true; + } + continue; + } + } + } + + if (nextpos > 0) + { + lseek(tar_fd, nextpos, SEEK_SET); + } + } + while (nextpos > 0); +} + static void load_wps_bitmaps(struct wps_data *wps_data, char *bmpdir) { char img_path[MAX_PATH]; @@ -1265,7 +1422,7 @@ /* load the image */ bitmap->data = wps_data->img_buf_ptr; - if (load_bitmap(wps_data, img_path, bitmap)) + if (load_bitmap(wps_data, img_path, -1, bitmap)) { *loaded = true; } @@ -1273,21 +1430,9 @@ } #if (LCD_DEPTH > 1) || (defined(HAVE_LCD_REMOTE) && (LCD_REMOTE_DEPTH > 1)) - if (bmp_names[BACKDROP_BMP]) - { - get_image_filename(bmp_names[BACKDROP_BMP], bmpdir, - img_path, sizeof(img_path)); -#ifdef HAVE_REMOTE_LCD - if (wps_data->remote_wps) -#if LCD_REMOTE_DEPTH > 1 - load_remote_wps_backdrop(img_path) + /* Load the backdrop */ + load_backdrop_bitmap(wps_data, bmpdir, -1); #endif - ; - else -#endif /* HAVE_REMOTE_LCD */ - load_wps_backdrop(img_path); - } -#endif /* has backdrop support */ } #endif /* HAVE_LCD_BITMAP */ @@ -1395,8 +1540,19 @@ strncpy(bmpdir, buf, dot - buf); bmpdir[bmpdirlen] = 0; + /* Open the bitmap .tar file if it exists */ + char bmptarname[MAX_PATH]; + strcpy(bmptarname, bmpdir); + strcat(bmptarname, ".tar"); + int bmptar = open(bmptarname, O_RDONLY); + /* load the bitmaps that were found by the parsing */ - load_wps_bitmaps(wps_data, bmpdir); + if (bmptar >= 0) { + load_wps_bitmaps_tar(wps_data, bmptar); + close(bmptar); + } else + load_wps_bitmaps(wps_data, bmpdir); + #endif return true; } Index: apps/gui/backdrop.h =================================================================== --- apps/gui/backdrop.h (révision 16132) +++ apps/gui/backdrop.h (copie de travail) @@ -27,6 +27,7 @@ bool load_main_backdrop(char* filename); bool load_wps_backdrop(char* filename); +bool load_wps_backdrop_fd(int fd); void unload_main_backdrop(void); void unload_wps_backdrop(void); @@ -38,6 +39,7 @@ #if defined(HAVE_REMOTE_LCD) && LCD_REMOTE_DEPTH > 1 bool load_remote_wps_backdrop(char* filename); +bool load_remote_wps_backdrop_fd(int fd); void unload_remote_wps_backdrop(void); void show_remote_wps_backdrop(void); void show_remote_main_backdrop(void); /* only clears the wps backdrop */