summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--!NetSurf/Resources/de/Messages2
-rw-r--r--!NetSurf/Resources/en/Messages2
-rw-r--r--!NetSurf/Resources/fr/Messages2
-rw-r--r--!NetSurf/Resources/nl/Messages2
-rw-r--r--content/content.c14
-rw-r--r--content/content.h2
-rw-r--r--content/content_type.h1
-rw-r--r--image/bmp.c12
-rw-r--r--image/bmpread.c268
-rw-r--r--image/bmpread.h18
-rw-r--r--image/ico.c118
-rw-r--r--image/ico.h33
-rw-r--r--riscos/filetype.c3
-rw-r--r--riscos/gui.c5
-rw-r--r--riscos/save.c1
-rw-r--r--riscos/window.c1
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: