diff options
-rw-r--r-- | !NetSurf/Resources/de/Messages | 2 | ||||
-rw-r--r-- | !NetSurf/Resources/en/Messages | 2 | ||||
-rw-r--r-- | !NetSurf/Resources/fr/Messages | 2 | ||||
-rw-r--r-- | !NetSurf/Resources/nl/Messages | 2 | ||||
-rw-r--r-- | content/content.c | 14 | ||||
-rw-r--r-- | content/content.h | 2 | ||||
-rw-r--r-- | content/content_type.h | 1 | ||||
-rw-r--r-- | image/bmp.c | 12 | ||||
-rw-r--r-- | image/bmpread.c | 268 | ||||
-rw-r--r-- | image/bmpread.h | 18 | ||||
-rw-r--r-- | image/ico.c | 118 | ||||
-rw-r--r-- | image/ico.h | 33 | ||||
-rw-r--r-- | riscos/filetype.c | 3 | ||||
-rw-r--r-- | riscos/gui.c | 5 | ||||
-rw-r--r-- | riscos/save.c | 1 | ||||
-rw-r--r-- | riscos/window.c | 1 |
16 files changed, 438 insertions, 46 deletions
diff --git a/!NetSurf/Resources/de/Messages b/!NetSurf/Resources/de/Messages index a493d92a8..3a96920d1 100644 --- a/!NetSurf/Resources/de/Messages +++ b/!NetSurf/Resources/de/Messages @@ -326,6 +326,7 @@ SelectMenu:Select DrawTitle:Draw Bild (%lux%lu, %lu bytes) GIFTitle:GIF Bild (%lux%lu, %lu bytes) BMPTitle:BMP Bild (%lux%lu, %lu bytes) +ICOTitle:ICO Bild (%lux%lu, %lu bytes) JPEGTitle:JPEG Bild (%ux%u, %lu bytes) PNGTitle:PNG Bild (%lux%lu, %lu bytes) JNGTitle:JNG Bild (%lux%lu, %lu bytes) @@ -438,6 +439,7 @@ ObjError:Error loading object: %s ParsingFail:Parsing the document failed. BadGIF:Reading GIF failed. BadBMP:Reading BMP failed. +BadICO:Reading ICO failed. PNGError:PNG library error. MNGError:MNG library error. BadSprite:Invalid or corrupt Sprite data. diff --git a/!NetSurf/Resources/en/Messages b/!NetSurf/Resources/en/Messages index fac4bbcf0..ee17b8321 100644 --- a/!NetSurf/Resources/en/Messages +++ b/!NetSurf/Resources/en/Messages @@ -326,6 +326,7 @@ SelectMenu:Select DrawTitle:Draw image (%lux%lu, %lu bytes) GIFTitle:GIF image (%lux%lu, %lu bytes) BMPTitle:BMP image (%lux%lu, %lu bytes) +ICOTitle:ICO image (%lux%lu, %lu bytes) JPEGTitle:JPEG image (%ux%u, %lu bytes) PNGTitle:PNG image (%lux%lu, %lu bytes) JNGTitle:JNG image (%lux%lu, %lu bytes) @@ -437,6 +438,7 @@ ObjError:Error loading object: %s ParsingFail:Parsing the document failed. BadGIF:Reading GIF failed. BadBMP:Reading BMP failed. +BadICO:Reading ICO failed. PNGError:PNG library error. MNGError:MNG library error. BadSprite:Invalid or corrupt Sprite data. diff --git a/!NetSurf/Resources/fr/Messages b/!NetSurf/Resources/fr/Messages index 97b6b11a3..9960d3b96 100644 --- a/!NetSurf/Resources/fr/Messages +++ b/!NetSurf/Resources/fr/Messages @@ -326,6 +326,7 @@ SelectMenu:Sélection DrawTitle:Image Draw (%lux%lu, %lu octets) GIFTitle:Image GIF (%lux%lu, %lu octets) BMPTitle:Image BMP (%lux%lu, %lu octets) +ICOTitle:Image BMP (%lux%lu, %lu octets) JPEGTitle:Image JPEG (%ux%u, %lu octets) PNGTitle:Image PNG (%lux%lu, %lu octets) JNGTitle:Image JNG (%lux%lu, %lu octets) @@ -438,6 +439,7 @@ ObjError:Erreur lors du chargement de: %s ParsingFail:L'analyse syntaxique du document a échoué. BadGIF:Erreur de lecture de GIF. BadBMP:Erreur de lecture de BMP. +BadICO:Erreur de lecture de ICO. PNGError:Erreur dans la bibliothèque PNG. MNGError:Erreur dans la bibliothèque MNG. BadSprite:Les données du sprite sont invalides ou corrompues. diff --git a/!NetSurf/Resources/nl/Messages b/!NetSurf/Resources/nl/Messages index 6aaeda156..23b4db27a 100644 --- a/!NetSurf/Resources/nl/Messages +++ b/!NetSurf/Resources/nl/Messages @@ -327,6 +327,7 @@ SelectMenu:Select DrawTitle:Draw image (%lux%lu, %lu bytes) GIFTitle:GIF image (%lux%lu, %lu bytes) BMPTitle:BMP image (%lux%lu, %lu bytes) +ICOTitle:ICO image (%lux%lu, %lu bytes) JPEGTitle:JPEG image (%ux%u, %lu bytes) PNGTitle:PNG image (%lux%lu, %lu bytes) JNGTitle:JNG image (%lux%lu, %lu bytes) @@ -440,6 +441,7 @@ ObjError:fout bij laden object: %s ParsingFail:fout bij ontleden van dit document. BadGIF:fout bij lezen GIF. BadBMP:fout bij lezen BMP. +BadICO:fout bij lezen ICO. PNGError:PNG library fout. MNGError:MNG library fout. BadSprite:foutief sprite bestand. diff --git a/content/content.c b/content/content.c index f18f401cf..e29990461 100644 --- a/content/content.c +++ b/content/content.c @@ -38,6 +38,7 @@ #endif #ifdef WITH_BMP #include "netsurf/image/bmp.h" +#include "netsurf/image/ico.h" #endif #ifdef WITH_SPRITE #include "netsurf/riscos/sprite.h" @@ -78,12 +79,16 @@ static const struct mime_entry mime_map[] = { {"application/drawfile", CONTENT_DRAW}, #endif #ifdef WITH_BMP + {"application/ico", CONTENT_ICO}, {"application/preview", CONTENT_BMP}, {"application/x-bmp", CONTENT_BMP}, #endif #ifdef WITH_DRAW {"application/x-drawfile", CONTENT_DRAW}, #endif +#ifdef WITH_BMP + {"application/x-ico", CONTENT_ICO}, +#endif #ifdef WITH_THEME_INSTALL {"application/x-netsurf-theme", CONTENT_THEME}, #endif @@ -103,6 +108,9 @@ static const struct mime_entry mime_map[] = { #ifdef WITH_GIF {"image/gif", CONTENT_GIF}, #endif +#ifdef WITH_BMP + {"image/ico", CONTENT_ICO}, +#endif #ifdef WITH_MNG {"image/jng", CONTENT_JNG}, #endif @@ -128,6 +136,9 @@ static const struct mime_entry mime_map[] = { #ifdef WITH_DRAW {"image/x-drawfile", CONTENT_DRAW}, #endif +#ifdef WITH_BMP + {"image/x-icon", CONTENT_ICO}, +#endif #ifdef WITH_MNG {"image/x-jng", CONTENT_JNG}, {"image/x-mng", CONTENT_MNG}, @@ -165,6 +176,7 @@ const char *content_type_name[] = { #endif #ifdef WITH_BMP "BMP", + "ICO", #endif #ifdef WITH_MNG "PNG", @@ -245,6 +257,8 @@ static const struct handler_entry handler_map[] = { #ifdef WITH_BMP {nsbmp_create, 0, nsbmp_convert, 0, nsbmp_destroy, 0, nsbmp_redraw, nsbmp_redraw_tiled, 0, 0, false}, + {nsico_create, 0, nsico_convert, 0, nsico_destroy, 0, + nsico_redraw, nsico_redraw_tiled, 0, 0, false}, #endif #ifdef WITH_MNG {nsmng_create, nsmng_process_data, nsmng_convert, diff --git a/content/content.h b/content/content.h index 52a22e5ef..ec050a7be 100644 --- a/content/content.h +++ b/content/content.h @@ -117,6 +117,7 @@ #endif #ifdef WITH_BMP #include "netsurf/image/bmp.h" +#include "netsurf/image/ico.h" #endif #ifdef WITH_PLUGIN #include "netsurf/riscos/plugin.h" @@ -235,6 +236,7 @@ struct content { #endif #ifdef WITH_BMP struct content_bmp_data bmp; + struct content_ico_data ico; #endif #ifdef WITH_MNG struct content_mng_data mng; diff --git a/content/content_type.h b/content/content_type.h index ef184ce7c..b8b891514 100644 --- a/content/content_type.h +++ b/content/content_type.h @@ -30,6 +30,7 @@ typedef enum { #endif #ifdef WITH_BMP CONTENT_BMP, + CONTENT_ICO, #endif #ifdef WITH_MNG CONTENT_PNG, diff --git a/image/bmp.c b/image/bmp.c index b2fc59f86..1eaef0592 100644 --- a/image/bmp.c +++ b/image/bmp.c @@ -11,8 +11,6 @@ #include <stdlib.h> #include "netsurf/utils/config.h" #include "netsurf/content/content.h" -#include "netsurf/desktop/browser.h" -#include "netsurf/desktop/options.h" #include "netsurf/desktop/plotters.h" #include "netsurf/image/bitmap.h" #include "netsurf/image/bmp.h" @@ -23,8 +21,6 @@ #ifdef WITH_BMP -static void nsbmp_invalidate(struct bitmap *bitmap, void *private_word); - bool nsbmp_create(struct content *c, const char *params[]) { union content_msg_data msg_data; @@ -76,20 +72,12 @@ bool nsbmp_convert(struct content *c, int iwidth, int iheight) { c->height, c->source_size); c->size += (bmp->width * bmp->height * 4) + 16 + 44 + 100; - /* make so that the bitmap code can free our image quickly */ - bitmap_set_suspendable(bmp->bitmap, bmp, nsbmp_invalidate); - /* exit as a success */ c->bitmap = bmp->bitmap; c->status = CONTENT_STATUS_DONE; return true; } -void nsbmp_invalidate(struct bitmap *bitmap, void *private_word) { - struct bmp_image *bmp = (struct bmp_image *)private_word; - - bmp->decoded = false; -} bool nsbmp_redraw(struct content *c, int x, int y, int width, int height, diff --git a/image/bmpread.c b/image/bmpread.c index 15c103ae0..89f30789e 100644 --- a/image/bmpread.c +++ b/image/bmpread.c @@ -18,9 +18,12 @@ #define READ_SHORT(a, o) (a[o]|(a[o+1]<<8)) #define READ_INT(a, o) (a[o]|(a[o+1]<<8)|(a[o+2]<<16)|(a[o+3]<<24)) -bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char *data, int bytes); -bmp_result bmp_decode_rgb(struct bmp_image *bmp, char *data, int bytes); +bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data); +bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes); +bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes); +bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes); bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size); +void bmp_invalidate(struct bitmap *bitmap, void *private_word); /** @@ -37,10 +40,6 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size */ bmp_result bmp_analyse(struct bmp_image *bmp) { char *data = bmp->bmp_data; - unsigned int header_size; - unsigned int i; - int width, height; - int palette_size; /* ensure we aren't already initialised */ if (bmp->bitmap) @@ -59,9 +58,85 @@ bmp_result bmp_analyse(struct bmp_image *bmp) { if ((data[0] != 'B') || (data[1] != 'M')) return BMP_DATA_ERROR; bmp->bitmap_offset = READ_INT(data, 10); - data += 14; + + /* decode the BMP header */ + return bmp_analyse_header(bmp, data + 14); +} + + +/** + * Analyse an ICO prior to decoding. + * + * This function will scan the data provided and perform simple checks to + * ensure the data is a valid ICO. + * + * This function must be called before ico_find(). + * + * \param ico the ICO image to analyse + * \return BMP_OK on success + */ +bmp_result ico_analyse(struct ico_collection *ico) { + char *data = ico->ico_data; + unsigned int count, i; + bmp_result result; + struct ico_image *image; + int area, max_area = 0; + + /* ensure we aren't already initialised */ + if (ico->first) + return BMP_OK; + + /* standard 6-byte ICO file header is: + * + * +0 INT 0x00010000 + * +4 SHORT number of BMPs to follow + */ + if (ico->buffer_size < 6) + return BMP_INSUFFICIENT_DATA; + if (READ_INT(data, 0) != 0x00010000) + return BMP_DATA_ERROR; + count = READ_SHORT(data, 4); + if (count == 0) + return BMP_DATA_ERROR; + data += 6; + + /* decode the BMP files */ + if (ico->buffer_size < 6 + (16 * count)) + return BMP_INSUFFICIENT_DATA; + for (i = 0; i < count; i++) { + image = calloc(1, sizeof(struct ico_image)); + if (!image) + return BMP_INSUFFICIENT_MEMORY; + image->next = ico->first; + ico->first = image; + image->bmp.width = data[0]; + image->bmp.height = data[1]; + image->bmp.buffer_size = READ_INT(data, 8) + 40; + image->bmp.bmp_data = ico->ico_data + READ_INT(data, 12); + image->bmp.ico = true; + data += 16; + result = bmp_analyse_header(&image->bmp, image->bmp.bmp_data); + if (result != BMP_OK) + return result; + area = image->bmp.width * image->bmp.height; + if (area > max_area) { + ico->width = image->bmp.width; + ico->height = image->bmp.height; + max_area = area; + } + } + return BMP_OK; +} + + +bmp_result bmp_analyse_header(struct bmp_image *bmp, char *data) { + unsigned int header_size; + unsigned int i; + int width, height; + int palette_size; + unsigned int flags; - /* a variety of different bitmap headers can now follow, depending + /* a variety of different bitmap headers can follow, depending * on the BMP variant. A full description of the various headers * can be found at http://www.fileformat.info/format/bmp/ */ @@ -127,19 +202,23 @@ bmp_result bmp_analyse(struct bmp_image *bmp) { * +100 INT gamma green coordinate scale value * +104 INT gamma blue coordinate scale value */ - width = READ_INT(data, 4); - height = READ_INT(data, 8); - if (width < 0) - return BMP_DATA_ERROR; - if (height < 0) { - bmp->reversed = true; - height = -height; + if (!bmp->ico) { + width = READ_INT(data, 4); + height = READ_INT(data, 8); + if (width < 0) + return BMP_DATA_ERROR; + if (height < 0) { + bmp->reversed = true; + height = -height; + } + bmp->width = width; + bmp->height = height; } - bmp->width = width; - bmp->height = height; if (READ_SHORT(data, 12) != 1) return BMP_DATA_ERROR; bmp->bpp = READ_SHORT(data, 14); + if (bmp->bpp == 0) + bmp->bpp = 8; bmp->encoding = READ_INT(data, 16); if (bmp->encoding >= BMP_ENCODING_BITFIELDS) /* unsupported so far */ return BMP_DATA_ERROR; @@ -169,25 +248,74 @@ bmp_result bmp_analyse(struct bmp_image *bmp) { if (!bmp->colour_table) return BMP_INSUFFICIENT_MEMORY; for (i = 0; i < bmp->colours; i++) { - bmp->colour_table[i] = (data[2] | (data[1] << 8) | - (data[0] << 16) | (0xff << 24)); + bmp->colour_table[i] = data[2] | (data[1] << 8) | + (data[0] << 16); data += palette_size; } } /* create our bitmap */ - bmp->bitmap = bitmap_create(bmp->width, bmp->height, - BITMAP_NEW | BITMAP_OPAQUE | BITMAP_CLEAR_MEMORY); + flags = BITMAP_NEW | BITMAP_CLEAR_MEMORY; + if (!bmp->ico) + flags |= BITMAP_OPAQUE; + bmp->bitmap = bitmap_create(bmp->width, bmp->height, flags); if (!bmp->bitmap) { if (bmp->colour_table) free(bmp->colour_table); bmp->colour_table = NULL; return BMP_INSUFFICIENT_MEMORY; } + bmp->bitmap_offset = (int)data - (int)bmp->bmp_data; + bitmap_set_suspendable(bmp->bitmap, bmp, bmp_invalidate); return BMP_OK; } +/* + * Finds the closest BMP within an ICO collection + * + * This function finds the BMP with dimensions as close to a specified set + * as possible from the images in the collection. + * + * \param ico the ICO collection to examine + * \param width the preferred width + * \param height the preferred height + */ +struct bmp_image *ico_find(struct ico_collection *ico, int width, int height) { + struct bmp_image *bmp = NULL; + struct ico_image *image; + int x, y, cur, distance = (1 << 24); + + for (image = ico->first; image; image = image->next) { + if (((int)image->bmp.width == width) && ((int)image->bmp.height == height)) + return &image->bmp; + x = image->bmp.width - width; + y = image->bmp.height - height; + cur = (x * x) + (y * y); + if (cur < distance) { + distance = cur; + bmp = &image->bmp; + } + } + return bmp; +} + + +/** + * Invalidates a BMP + * + * This function sets the BMP into a state such that the bitmap image data + * can be released from memory. + * + * \param bmp the BMP image to invalidate + */ +void bmp_invalidate(struct bitmap *bitmap, void *private_word) { + struct bmp_image *bmp = (struct bmp_image *)private_word; + + bmp->decoded = false; +} + + /** * Decode a BMP * @@ -201,6 +329,7 @@ bmp_result bmp_analyse(struct bmp_image *bmp) { bmp_result bmp_decode(struct bmp_image *bmp) { char *data; int bytes; + bmp_result result = BMP_OK; assert(bmp->bitmap); @@ -210,20 +339,27 @@ bmp_result bmp_decode(struct bmp_image *bmp) { switch (bmp->encoding) { case BMP_ENCODING_RGB: if (bmp->bpp >= 24) - return bmp_decode_rgb24(bmp, data, bytes); + result = bmp_decode_rgb24(bmp, &data, bytes); else if (bmp->bpp > 8) return BMP_DATA_ERROR; else - return bmp_decode_rgb(bmp, data, bytes); + result = bmp_decode_rgb(bmp, &data, bytes); + break; case BMP_ENCODING_RLE8: - return bmp_decode_rle(bmp, data, bytes, 8); + result = bmp_decode_rle(bmp, data, bytes, 8); + break; case BMP_ENCODING_RLE4: - return bmp_decode_rle(bmp, data, bytes, 4); - case BMP_ENCODING_BITFIELDS: - /* todo: implement me */ + result = bmp_decode_rle(bmp, data, bytes, 4); break; + case BMP_ENCODING_BITFIELDS: + return BMP_DATA_ERROR; } - return BMP_DATA_ERROR; + + if ((!bmp->ico) || (result != BMP_OK)) + return result; + + bytes = (int)bmp->bmp_data + bmp->buffer_size - (int)data; + return bmp_decode_mask(bmp, data, bytes); } @@ -231,16 +367,17 @@ bmp_result bmp_decode(struct bmp_image *bmp) { * Decode BMP data stored in 24bpp colour. * * \param bmp the BMP image to decode - * \param data the data to decode + * \param start the data to decode, updated to last byte read on success * \param bytes the number of bytes of data available * \return BMP_OK on success */ -bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char *data, int bytes) { - char *top, *bottom, *end; +bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes) { + char *top, *bottom, *end, *data; unsigned int *scanline; unsigned int x, y, swidth, skip; unsigned int addr; + data = *start; swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); bottom = top + swidth * (bmp->height - 1); @@ -263,6 +400,7 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char *data, int bytes) { data += skip; } } + *start = data; return BMP_OK; } @@ -271,12 +409,12 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char *data, int bytes) { * Decode BMP data stored with a palette and in 8bpp colour or less. * * \param bmp the BMP image to decode - * \param data the data to decode + * \param start the data to decode, updated to last byte read on success * \param bytes the number of bytes of data available * \return BMP_OK on success */ -bmp_result bmp_decode_rgb(struct bmp_image *bmp, char *data, int bytes) { - char *top, *bottom, *end; +bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes) { + char *top, *bottom, *end, *data; unsigned int *scanline; unsigned int addr; unsigned int x, y, swidth; @@ -289,6 +427,7 @@ bmp_result bmp_decode_rgb(struct bmp_image *bmp, char *data, int bytes) { for (i = 0; i < ppb; i++) bit_shifts[i] = 8 - ((i + 1) * bmp->bpp); + data = *start; swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); bottom = top + swidth * (bmp->height - 1); @@ -315,6 +454,46 @@ bmp_result bmp_decode_rgb(struct bmp_image *bmp, char *data, int bytes) { bit_shifts[bit++]) & bit_mask]; } } + *start = data; + return BMP_OK; +} + + +/** + * Decode a 1bpp mask for an ICO + * + * \param bmp the BMP image to decode + * \param data the data to decode + * \param bytes the number of bytes of data available + * \return BMP_OK on success + */ +bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes) { + char *top, *bottom, *end; + unsigned int *scanline; + unsigned int addr; + unsigned int x, y, swidth; + int cur_byte = 0; + + swidth = bitmap_get_rowstride(bmp->bitmap); + top = bitmap_get_buffer(bmp->bitmap); + bottom = top + swidth * (bmp->height - 1); + end = data + bytes; + addr = ((unsigned int)data) & 3; + + for (y = 0; y < bmp->height; y++) { + while (addr != (((unsigned int)data) & 3)) + data++; + if ((data + (bmp->width >> 3)) > end) + return BMP_INSUFFICIENT_DATA; + scanline = (unsigned int *)(bottom - (y * swidth)); + for (x = 0; x < bmp->width; x++) { + if ((x & 7) == 0) + cur_byte = *data++; + if ((cur_byte & 128) == 0) + scanline[x] |= (0xff << 24); + cur_byte = cur_byte << 1; + } + } return BMP_OK; } @@ -336,6 +515,9 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size unsigned int x = 0, y = 0, last_y = 0; unsigned int pixel = 0, pixel2; + if (bmp->ico) + return BMP_DATA_ERROR; + swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); bottom = top + swidth * (bmp->height - 1); @@ -481,3 +663,21 @@ void bmp_finalise(struct bmp_image *bmp) { free(bmp->colour_table); bmp->colour_table = NULL; } + + +/** + * Finalise an ICO prior to destruction. + * + * \param ico the ICO image to finalise + */ +void ico_finalise(struct ico_collection *ico) { + struct ico_image *image; + + for (image = ico->first; image; image = image->next) + bmp_finalise(&image->bmp); + while (ico->first) { + image = ico->first; + ico->first = image->next; + free(image); + } +} diff --git a/image/bmpread.h b/image/bmpread.h index 45468a9ed..275374e5a 100644 --- a/image/bmpread.h +++ b/image/bmpread.h @@ -44,11 +44,29 @@ struct bmp_image { unsigned int *colour_table; /** colour table */ bool reversed; /** scanlines are top to bottom */ bool decoded; /** whether the image has been decoded */ + bool ico; /** image is part of an ICO, mask follows */ struct bitmap *bitmap; /** decoded image */ }; +struct ico_image { + struct bmp_image bmp; + struct ico_image *next; +}; + +struct ico_collection { + unsigned char *ico_data; /** pointer to ICO data */ + unsigned int buffer_size; /** total number of bytes of ICO data available */ + unsigned int width; /** width of largest BMP */ + unsigned int height; /** heigth of largest BMP */ + struct ico_image *first; +}; + bmp_result bmp_analyse(struct bmp_image *bmp); bmp_result bmp_decode(struct bmp_image *bmp); void bmp_finalise(struct bmp_image *bmp); +bmp_result ico_analyse(struct ico_collection *ico); +struct bmp_image *ico_find(struct ico_collection *ico, int width, int height); +void ico_finalise(struct ico_collection *ico); + #endif diff --git a/image/ico.c b/image/ico.c new file mode 100644 index 000000000..cdb21eb57 --- /dev/null +++ b/image/ico.c @@ -0,0 +1,118 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2006 Richard Wilson <info@tinct.net> + */ + +#include <assert.h> +#include <string.h> +#include <stdbool.h> +#include <stdlib.h> +#include "netsurf/utils/config.h" +#include "netsurf/content/content.h" +#include "netsurf/desktop/plotters.h" +#include "netsurf/image/bitmap.h" +#include "netsurf/image/bmpread.h" +#include "netsurf/image/ico.h" +#include "netsurf/utils/log.h" +#include "netsurf/utils/messages.h" +#include "netsurf/utils/utils.h" + +#ifdef WITH_BMP + +bool nsico_create(struct content *c, const char *params[]) { + union content_msg_data msg_data; + + c->data.ico.ico = calloc(sizeof(struct ico_collection), 1); + if (!c->data.ico.ico) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + } + return true; +} + + +bool nsico_convert(struct content *c, int iwidth, int iheight) { + struct bmp_image *bmp; + bmp_result res; + struct ico_collection *ico; + union content_msg_data msg_data; + + /* set our source data */ + ico = c->data.ico.ico; + ico->ico_data = c->source_data; + ico->buffer_size = c->source_size; + + /* analyse the BMP */ + res = ico_analyse(ico); + switch (res) { + case BMP_OK: + break; + case BMP_INSUFFICIENT_MEMORY: + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return false; + case BMP_INSUFFICIENT_DATA: + case BMP_DATA_ERROR: + msg_data.error = messages_get("BadICO"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + /* Store our content width and description + */ + c->width = ico->width; + c->height = ico->height; + c->title = malloc(100); + if (c->title) + snprintf(c->title, 100, messages_get("ICOTitle"), c->width, + c->height, c->source_size); + c->size += (ico->width * ico->height * 4) + 16 + 44 + 100; + + /* exit as a success */ + bmp = ico_find(c->data.ico.ico, 255, 255); + assert(bmp); + c->bitmap = bmp->bitmap; + c->status = CONTENT_STATUS_DONE; + return true; +} + +bool nsico_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, unsigned long background_colour) { + struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height); + if (!bmp->decoded) + bmp_decode(bmp); + c->bitmap = bmp->bitmap; + return plot.bitmap(x, y, width, height, c->bitmap, + background_colour); +} + + +bool nsico_redraw_tiled(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, unsigned long background_colour, + bool repeat_x, bool repeat_y) { + struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height); + if (!bmp->decoded) + bmp_decode(bmp); + c->bitmap = bmp->bitmap; + return plot.bitmap_tile(x, y, width, height, c->bitmap, + background_colour, repeat_x, repeat_y); +} + + +void nsico_destroy(struct content *c) +{ + ico_finalise(c->data.ico.ico); + free(c->data.ico.ico); + free(c->title); +} + +#endif diff --git a/image/ico.h b/image/ico.h new file mode 100644 index 000000000..401962e96 --- /dev/null +++ b/image/ico.h @@ -0,0 +1,33 @@ +/* + * This file is part of NetSurf, http://netsurf.sourceforge.net/ + * Licensed under the GNU General Public License, + * http://www.opensource.org/licenses/gpl-license + * Copyright 2006 Richard Wilson <info@tinct.net> + */ + +#ifndef _NETSURF_IMAGE_ICO_H_ +#define _NETSURF_IMAGE_ICO_H_ + +#include <stdbool.h> +#include "netsurf/image/bmpread.h" + +struct content; + +struct content_ico_data { + struct ico_collection *ico; /** ICO collection data */ +}; + +bool nsico_create(struct content *c, const char *params[]); +bool nsico_convert(struct content *c, int width, int height); +void nsico_destroy(struct content *c); +bool nsico_redraw(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, unsigned long background_colour); +bool nsico_redraw_tiled(struct content *c, int x, int y, + int width, int height, + int clip_x0, int clip_y0, int clip_x1, int clip_y1, + float scale, unsigned long background_colour, + bool repeat_x, bool repeat_y); + +#endif diff --git a/riscos/filetype.c b/riscos/filetype.c index 89be38e99..a763e46f8 100644 --- a/riscos/filetype.c +++ b/riscos/filetype.c @@ -23,8 +23,10 @@ struct type_entry { char mime_type[40]; }; static const struct type_entry type_map[] = { + {0x132, "image/ico"}, {0x188, "application/x-shockwave-flash"}, {0x695, "image/gif"}, + {0x69c, "image/x-ms-bmp"}, {0xaff, "image/x-drawfile"}, {0xb60, "image/png"}, {0xc85, "image/jpeg"}, @@ -247,6 +249,7 @@ int ro_content_filetype_from_type(content_type type) { #endif #ifdef WITH_BMP case CONTENT_BMP: return 0x69c; + case CONTENT_ICO: return 0x132; #endif #ifdef WITH_SPRITE case CONTENT_SPRITE: return 0xff9; diff --git a/riscos/gui.c b/riscos/gui.c index 23897a629..c09b00375 100644 --- a/riscos/gui.c +++ b/riscos/gui.c @@ -112,6 +112,9 @@ #ifndef FILETYPE_BMP #define FILETYPE_BMP 0x69c #endif +#ifndef FILETYPE_ICO +#define FILETYPE_ICO 0x132 +#endif #ifndef FILETYPE_PNG #define FILETYPE_PNG 0xb60 #endif @@ -1496,6 +1499,7 @@ void ro_msg_dataload(wimp_message *message) case FILETYPE_MNG: case FILETYPE_GIF: case FILETYPE_BMP: + case FILETYPE_ICO: case osfile_TYPE_DRAW: case FILETYPE_PNG: case FILETYPE_JPEG: @@ -1784,6 +1788,7 @@ void ro_msg_datasave(wimp_message *message) case FILETYPE_MNG: case FILETYPE_GIF: case FILETYPE_BMP: + case FILETYPE_ICO: case osfile_TYPE_DRAW: case FILETYPE_PNG: case FILETYPE_JPEG: diff --git a/riscos/save.c b/riscos/save.c index ac2e2267a..d184d5641 100644 --- a/riscos/save.c +++ b/riscos/save.c @@ -815,6 +815,7 @@ void ro_gui_save_object_native(struct content *c, char *path) #endif #ifdef WITH_BMP case CONTENT_BMP: + case CONTENT_ICO: bitmap_save(c->bitmap, path); break; #endif diff --git a/riscos/window.c b/riscos/window.c index 386e4d984..9ba7d02a4 100644 --- a/riscos/window.c +++ b/riscos/window.c @@ -498,6 +498,7 @@ void ro_gui_window_redraw(struct gui_window *g, wimp_draw *redraw) #endif #ifdef WITH_BMP case CONTENT_BMP: + case CONTENT_ICO: #endif #ifdef WITH_MNG case CONTENT_JNG: |