summaryrefslogtreecommitdiff
path: root/image
diff options
context:
space:
mode:
Diffstat (limited to 'image')
-rw-r--r--image/bmp.c225
-rw-r--r--image/bmp.h26
-rw-r--r--image/gif.c322
-rw-r--r--image/gif.h28
-rw-r--r--image/ico.c222
-rw-r--r--image/ico.h31
-rw-r--r--image/image.c100
-rw-r--r--image/image.h31
-rw-r--r--image/jpeg.c142
-rw-r--r--image/jpeg.h27
-rw-r--r--image/mng.c430
-rw-r--r--image/mng.h33
-rw-r--r--image/nssprite.c149
-rw-r--r--image/nssprite.h20
-rw-r--r--image/png.c287
-rw-r--r--image/png.h40
-rw-r--r--image/rsvg.c189
-rw-r--r--image/rsvg.h34
-rw-r--r--image/svg.c188
-rw-r--r--image/svg.h33
-rw-r--r--image/webp.c136
-rw-r--r--image/webp.h22
22 files changed, 2099 insertions, 616 deletions
diff --git a/image/bmp.c b/image/bmp.c
index 1e8ec5be9..dbb4d9796 100644
--- a/image/bmp.c
+++ b/image/bmp.c
@@ -31,13 +31,40 @@
#include <libnsbmp.h>
#include "utils/config.h"
#include "content/content_protected.h"
+#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "image/bmp.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct nsbmp_content {
+ struct content base;
+
+ bmp_image *bmp; /** BMP image data */
+} nsbmp_content;
+
+static nserror nsbmp_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsbmp_create_bmp_data(nsbmp_content *bmp);
+static bool nsbmp_convert(struct content *c);
+static void nsbmp_destroy(struct content *c);
+static bool nsbmp_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsbmp_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsbmp_clone(const struct content *old, struct content **newc);
+static content_type nsbmp_content_type(lwc_string *mime_type);
+
+static void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state);
+
/* The Bitmap callbacks function table;
* necessary for interaction with nsbmplib.
*/
@@ -49,25 +76,131 @@ bmp_bitmap_callback_vt bmp_bitmap_callbacks = {
.bitmap_get_bpp = bitmap_get_bpp
};
-bool nsbmp_create(struct content *c, const struct http_parameter *params)
+static const content_handler nsbmp_content_handler = {
+ nsbmp_create,
+ NULL,
+ nsbmp_convert,
+ NULL,
+ nsbmp_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsbmp_redraw,
+ nsbmp_redraw_tiled,
+ NULL,
+ NULL,
+ nsbmp_clone,
+ NULL,
+ nsbmp_content_type,
+ false
+};
+
+static const char *nsbmp_types[] = {
+ "application/bmp",
+ "application/preview",
+ "application/x-bmp",
+ "application/x-win-bitmap",
+ "image/bmp",
+ "image/ms-bmp",
+ "image/x-bitmap",
+ "image/x-bmp",
+ "image/x-ms-bmp",
+ "image/x-win-bitmap",
+ "image/x-windows-bmp",
+ "image/x-xbitmap"
+};
+
+static lwc_string *nsbmp_mime_types[NOF_ELEMENTS(nsbmp_types)];
+
+nserror nsbmp_init(void)
{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsbmp_mime_types); i++) {
+ lerror = lwc_intern_string(nsbmp_types[i],
+ strlen(nsbmp_types[i]),
+ &nsbmp_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsbmp_mime_types[i],
+ &nsbmp_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsbmp_fini();
+
+ return error;
+}
+
+void nsbmp_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsbmp_mime_types); i++) {
+ if (nsbmp_mime_types[i] != NULL)
+ lwc_string_unref(nsbmp_mime_types[i]);
+ }
+}
+
+nserror nsbmp_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsbmp_content *bmp;
+ nserror error;
+
+ bmp = talloc_zero(0, nsbmp_content);
+ if (bmp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&bmp->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(bmp);
+ return error;
+ }
+
+ error = nsbmp_create_bmp_data(bmp);
+ if (error != NSERROR_OK) {
+ talloc_free(bmp);
+ return error;
+ }
+
+ *c = (struct content *) bmp;
+
+ return NSERROR_OK;
+}
+
+nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
+{
union content_msg_data msg_data;
- c->data.bmp.bmp = calloc(sizeof(struct bmp_image), 1);
- if (!c->data.bmp.bmp) {
+ bmp->bmp = calloc(sizeof(struct bmp_image), 1);
+ if (bmp->bmp == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&bmp->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- bmp_create(c->data.bmp.bmp, &bmp_bitmap_callbacks);
- return true;
-}
+ bmp_create(bmp->bmp, &bmp_bitmap_callbacks);
+
+ return NSERROR_OK;
+}
bool nsbmp_convert(struct content *c)
{
+ nsbmp_content *bmp = (nsbmp_content *) c;
bmp_result res;
- bmp_image *bmp;
union content_msg_data msg_data;
uint32_t swidth;
const char *data;
@@ -75,12 +208,10 @@ bool nsbmp_convert(struct content *c)
char title[100];
/* set the bmp data */
- bmp = c->data.bmp.bmp;
-
data = content__get_source_data(c, &size);
/* analyse the BMP */
- res = bmp_analyse(bmp, size, (unsigned char *) data);
+ res = bmp_analyse(bmp->bmp, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
break;
@@ -96,17 +227,18 @@ bool nsbmp_convert(struct content *c)
}
/* Store our content width and description */
- c->width = bmp->width;
- c->height = bmp->height;
+ c->width = bmp->bmp->width;
+ c->height = bmp->bmp->height;
LOG(("BMP width %u height %u", c->width, c->height));
snprintf(title, sizeof(title), messages_get("BMPTitle"),
c->width, c->height, size);
content__set_title(c, title);
- swidth = bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bitmap) * bmp->width;
- c->size += (swidth * bmp->height) + 16 + 44;
+ swidth = bmp->bmp->bitmap_callbacks.bitmap_get_bpp(bmp->bmp->bitmap) *
+ bmp->bmp->width;
+ c->size += (swidth * bmp->bmp->height) + 16 + 44;
/* exit as a success */
- c->bitmap = bmp->bitmap;
+ c->bitmap = bmp->bmp->bitmap;
bitmap_modified(c->bitmap);
content_set_ready(c);
@@ -122,11 +254,14 @@ bool nsbmp_redraw(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ nsbmp_content *bmp = (nsbmp_content *) c;
- if (!c->data.bmp.bmp->decoded)
- if (bmp_decode(c->data.bmp.bmp) != BMP_OK)
+ if (bmp->bmp->decoded == false)
+ if (bmp_decode(bmp->bmp) != BMP_OK)
return false;
- c->bitmap = c->data.bmp.bmp->bitmap;
+
+ c->bitmap = bmp->bmp->bitmap;
+
return plot.bitmap(x, y, width, height, c->bitmap,
background_colour, BITMAPF_NONE);
}
@@ -137,13 +272,14 @@ bool nsbmp_redraw_tiled(struct content *c, int x, int y,
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
+ nsbmp_content *bmp = (nsbmp_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
- if (!c->data.bmp.bmp->decoded)
- if (bmp_decode(c->data.bmp.bmp) != BMP_OK)
+ if (bmp->bmp->decoded == false)
+ if (bmp_decode(bmp->bmp) != BMP_OK)
return false;
- c->bitmap = c->data.bmp.bmp->bitmap;
+ c->bitmap = bmp->bmp->bitmap;
if (repeat_x)
flags |= BITMAPF_REPEAT_X;
@@ -157,27 +293,52 @@ bool nsbmp_redraw_tiled(struct content *c, int x, int y,
void nsbmp_destroy(struct content *c)
{
- bmp_finalise(c->data.bmp.bmp);
- free(c->data.bmp.bmp);
-}
+ nsbmp_content *bmp = (nsbmp_content *) c;
+ bmp_finalise(bmp->bmp);
+ free(bmp->bmp);
+}
-bool nsbmp_clone(const struct content *old, struct content *new_content)
+nserror nsbmp_clone(const struct content *old, struct content **newc)
{
+ nsbmp_content *new_bmp;
+ nserror error;
+
+ new_bmp = talloc_zero(0, nsbmp_content);
+ if (new_bmp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &new_bmp->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&new_bmp->base);
+ return error;
+ }
+
/* We "clone" the old content by replaying creation and conversion */
- if (nsbmp_create(new_content, NULL) == false)
- return false;
+ error = nsbmp_create_bmp_data(new_bmp);
+ if (error != NSERROR_OK) {
+ content_destroy(&new_bmp->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsbmp_convert(new_content) == false)
- return false;
+ if (nsbmp_convert(&new_bmp->base) == false) {
+ content_destroy(&new_bmp->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) new_bmp;
+
+ return NSERROR_OK;
}
+content_type nsbmp_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
/**
* Callback for libnsbmp; forwards the call to bitmap_create()
diff --git a/image/bmp.h b/image/bmp.h
index cb386f6d1..885b94344 100644
--- a/image/bmp.h
+++ b/image/bmp.h
@@ -31,29 +31,15 @@
#include <libnsbmp.h>
#include "image/bitmap.h"
-struct content;
-struct bitmap;
-struct http_parameter;
-struct rect;
+extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
-struct content_bmp_data {
- bmp_image *bmp; /** BMP image data */
-};
+nserror nsbmp_init(void);
+void nsbmp_fini(void);
-extern bmp_bitmap_callback_vt bmp_bitmap_callbacks; /** Only to be used by ICO code. */
+#else
-bool nsbmp_create(struct content *c, const struct http_parameter *params);
-bool nsbmp_convert(struct content *c);
-void nsbmp_destroy(struct content *c);
-bool nsbmp_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsbmp_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsbmp_clone(const struct content *old, struct content *new_content);
-void *nsbmp_bitmap_create(int width, int height, unsigned int bmp_state);
+#define nsbmp_init() NSERROR_OK
+#define nsbmp_fini() ((void) 0)
#endif /* WITH_BMP */
diff --git a/image/gif.c b/image/gif.c
index e449db345..20a67424e 100644
--- a/image/gif.c
+++ b/image/gif.c
@@ -38,6 +38,7 @@
#include <libnsgif.h>
#include "utils/config.h"
#include "content/content_protected.h"
+#include "content/hlcache.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
@@ -45,8 +46,34 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct nsgif_content {
+ struct content base;
+
+ struct gif_animation *gif; /**< GIF animation data */
+ int current_frame; /**< current frame to display [0...(max-1)] */
+} nsgif_content;
+
+static nserror nsgif_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsgif_create_gif_data(nsgif_content *c);
+static bool nsgif_convert(struct content *c);
+static void nsgif_destroy(struct content *c);
+static bool nsgif_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsgif_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsgif_clone(const struct content *old, struct content **newc);
+static content_type nsgif_content_type(lwc_string *mime_type);
+
+static void *nsgif_bitmap_create(int width, int height);
static void nsgif_invalidate(void *bitmap, void *private_word);
static void nsgif_animate(void *p);
static gif_result nsgif_get_frame(struct content *c);
@@ -63,39 +90,131 @@ gif_bitmap_callback_vt gif_bitmap_callbacks = {
.bitmap_modified = bitmap_modified
};
+static const content_handler nsgif_content_handler = {
+ nsgif_create,
+ NULL,
+ nsgif_convert,
+ NULL,
+ nsgif_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsgif_redraw,
+ nsgif_redraw_tiled,
+ NULL,
+ NULL,
+ nsgif_clone,
+ NULL,
+ nsgif_content_type,
+ false
+};
+
+static const char *nsgif_types[] = {
+ "image/gif"
+};
-bool nsgif_create(struct content *c, const struct http_parameter *params)
+static lwc_string *nsgif_mime_types[NOF_ELEMENTS(nsgif_types)];
+
+nserror nsgif_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsgif_mime_types); i++) {
+ lerror = lwc_intern_string(nsgif_types[i],
+ strlen(nsgif_types[i]),
+ &nsgif_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsgif_mime_types[i],
+ &nsgif_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsgif_fini();
+
+ return error;
+}
+
+void nsgif_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsgif_mime_types); i++) {
+ if (nsgif_mime_types[i] != NULL)
+ lwc_string_unref(nsgif_mime_types[i]);
+ }
+}
+
+nserror nsgif_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsgif_content *result;
+ nserror error;
+
+ result = talloc_zero(0, nsgif_content);
+ if (result == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&result->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ error = nsgif_create_gif_data(result);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ *c = (struct content *) result;
+
+ return NSERROR_OK;
+}
+
+nserror nsgif_create_gif_data(nsgif_content *c)
{
union content_msg_data msg_data;
+
/* Initialise our data structure */
- c->data.gif.gif = calloc(sizeof(gif_animation), 1);
- if (!c->data.gif.gif) {
+ c->gif = calloc(sizeof(gif_animation), 1);
+ if (c->gif == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- gif_create(c->data.gif.gif, &gif_bitmap_callbacks);
- return true;
+ gif_create(c->gif, &gif_bitmap_callbacks);
+ return NSERROR_OK;
}
bool nsgif_convert(struct content *c)
{
+ nsgif_content *gif = (nsgif_content *) c;
int res;
- struct gif_animation *gif;
union content_msg_data msg_data;
const char *data;
unsigned long size;
char title[100];
/* Get the animation */
- gif = c->data.gif.gif;
-
data = content__get_source_data(c, &size);
/* Initialise the GIF */
do {
- res = gif_initialise(gif, size, (unsigned char *) data);
+ res = gif_initialise(gif->gif, size, (unsigned char *) data);
if (res != GIF_OK && res != GIF_WORKING &&
res != GIF_INSUFFICIENT_FRAME_DATA) {
switch (res) {
@@ -114,30 +233,31 @@ bool nsgif_convert(struct content *c)
} while (res != GIF_OK && res != GIF_INSUFFICIENT_FRAME_DATA);
/* Abort on bad GIFs */
- if ((gif->frame_count_partial == 0) || (gif->width == 0) ||
- (gif->height == 0)) {
+ if ((gif->gif->frame_count_partial == 0) || (gif->gif->width == 0) ||
+ (gif->gif->height == 0)) {
msg_data.error = messages_get("BadGIF");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* Store our content width and description */
- c->width = gif->width;
- c->height = gif->height;
+ c->width = gif->gif->width;
+ c->height = gif->gif->height;
snprintf(title, sizeof(title), messages_get("GIFTitle"),
c->width, c->height, size);
content__set_title(c, title);
- c->size += (gif->width * gif->height * 4) + 16 + 44;
+ c->size += (gif->gif->width * gif->gif->height * 4) + 16 + 44;
/* Schedule the animation if we have one */
- c->data.gif.current_frame = 0;
- if (gif->frame_count_partial > 1)
- schedule(gif->frames[0].frame_delay, nsgif_animate, c);
+ gif->current_frame = 0;
+ if (gif->gif->frame_count_partial > 1)
+ schedule(gif->gif->frames[0].frame_delay, nsgif_animate, c);
else
- bitmap_set_suspendable(gif->frame_image, gif, nsgif_invalidate);
+ bitmap_set_suspendable(gif->gif->frame_image, gif->gif,
+ nsgif_invalidate);
/* Exit as a success */
- c->bitmap = gif->frame_image;
+ c->bitmap = gif->gif->frame_image;
content_set_ready(c);
content_set_done(c);
/* Done: update status bar */
@@ -156,10 +276,12 @@ bool nsgif_redraw(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
- if (c->data.gif.current_frame != c->data.gif.gif->decoded_frame)
+ nsgif_content *gif = (nsgif_content *) c;
+
+ if (gif->current_frame != gif->gif->decoded_frame)
if (nsgif_get_frame(c) != GIF_OK)
return false;
- c->bitmap = c->data.gif.gif->frame_image;
+ c->bitmap = gif->gif->frame_image;
if ((width == -1) && (height == -1))
return true;
return plot.bitmap(x, y, width, height, c->bitmap,
@@ -172,13 +294,14 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
+ nsgif_content *gif = (nsgif_content *) c;
bitmap_flags_t flags = BITMAPF_NONE;
- if (c->data.gif.current_frame != c->data.gif.gif->decoded_frame)
+ if (gif->current_frame != gif->gif->decoded_frame)
if (nsgif_get_frame(c) != GIF_OK)
return false;
- c->bitmap = c->data.gif.gif->frame_image;
+ c->bitmap = gif->gif->frame_image;
if (repeat_x)
flags |= BITMAPF_REPEAT_X;
@@ -191,28 +314,54 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
void nsgif_destroy(struct content *c)
{
+ nsgif_content *gif = (nsgif_content *) c;
+
/* Free all the associated memory buffers */
schedule_remove(nsgif_animate, c);
- gif_finalise(c->data.gif.gif);
- free(c->data.gif.gif);
+ gif_finalise(gif->gif);
+ free(gif->gif);
}
-bool nsgif_clone(const struct content *old, struct content *new_content)
+nserror nsgif_clone(const struct content *old, struct content **newc)
{
+ nsgif_content *gif;
+ nserror error;
+
+ gif = talloc_zero(0, nsgif_content);
+ if (gif == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &gif->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&gif->base);
+ return error;
+ }
+
/* Simply replay creation and conversion of content */
- if (nsgif_create(new_content, NULL) == false)
- return false;
+ error = nsgif_create_gif_data(gif);
+ if (error != NSERROR_OK) {
+ content_destroy(&gif->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsgif_convert(new_content) == false)
- return false;
+ if (nsgif_convert(&gif->base) == false) {
+ content_destroy(&gif->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) gif;
+
+ return NSERROR_OK;
}
+content_type nsgif_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
/**
* Updates the GIF bitmap to display the current frame
@@ -221,18 +370,19 @@ bool nsgif_clone(const struct content *old, struct content *new_content)
*/
gif_result nsgif_get_frame(struct content *c)
{
+ nsgif_content *gif = (nsgif_content *) c;
int previous_frame, current_frame, frame;
gif_result res = GIF_OK;
- current_frame = c->data.gif.current_frame;
+ current_frame = gif->current_frame;
if (!option_animate_images)
current_frame = 0;
- if (current_frame < c->data.gif.gif->decoded_frame)
+ if (current_frame < gif->gif->decoded_frame)
previous_frame = 0;
else
- previous_frame = c->data.gif.gif->decoded_frame + 1;
+ previous_frame = gif->gif->decoded_frame + 1;
for (frame = previous_frame; frame <= current_frame; frame++)
- res = gif_decode_frame(c->data.gif.gif, frame);
+ res = gif_decode_frame(gif->gif, frame);
return res;
}
@@ -245,105 +395,105 @@ gif_result nsgif_get_frame(struct content *c)
*/
void nsgif_animate(void *p)
{
- struct content *c = p;
+ nsgif_content *gif = p;
union content_msg_data data;
- struct gif_animation *gif;
int delay;
int f;
/* Advance by a frame, updating the loop count accordingly */
- gif = c->data.gif.gif;
- c->data.gif.current_frame++;
- if (c->data.gif.current_frame == (int)gif->frame_count_partial) {
- c->data.gif.current_frame = 0;
+ gif->current_frame++;
+ if (gif->current_frame == (int)gif->gif->frame_count_partial) {
+ gif->current_frame = 0;
/* A loop count of 0 has a special meaning of infinite */
- if (gif->loop_count != 0) {
- gif->loop_count--;
- if (gif->loop_count == 0) {
- c->data.gif.current_frame =
- gif->frame_count_partial - 1;
- gif->loop_count = -1;
+ if (gif->gif->loop_count != 0) {
+ gif->gif->loop_count--;
+ if (gif->gif->loop_count == 0) {
+ gif->current_frame =
+ gif->gif->frame_count_partial - 1;
+ gif->gif->loop_count = -1;
}
}
}
/* Continue animating if we should */
- if (gif->loop_count >= 0) {
- delay = gif->frames[c->data.gif.current_frame].frame_delay;
+ if (gif->gif->loop_count >= 0) {
+ delay = gif->gif->frames[gif->current_frame].frame_delay;
if (delay < option_minimum_gif_delay)
delay = option_minimum_gif_delay;
- schedule(delay, nsgif_animate, c);
+ schedule(delay, nsgif_animate, gif);
}
if ((!option_animate_images) ||
- (!gif->frames[c->data.gif.current_frame].display))
+ (!gif->gif->frames[gif->current_frame].display))
return;
/* area within gif to redraw */
- f = c->data.gif.current_frame;
- data.redraw.x = gif->frames[f].redraw_x;
- data.redraw.y = gif->frames[f].redraw_y;
- data.redraw.width = gif->frames[f].redraw_width;
- data.redraw.height = gif->frames[f].redraw_height;
+ f = gif->current_frame;
+ data.redraw.x = gif->gif->frames[f].redraw_x;
+ data.redraw.y = gif->gif->frames[f].redraw_y;
+ data.redraw.width = gif->gif->frames[f].redraw_width;
+ data.redraw.height = gif->gif->frames[f].redraw_height;
/* redraw background (true) or plot on top (false) */
- if (c->data.gif.current_frame > 0) {
- data.redraw.full_redraw = gif->frames[f - 1].redraw_required;
+ if (gif->current_frame > 0) {
+ data.redraw.full_redraw =
+ gif->gif->frames[f - 1].redraw_required;
/* previous frame needed clearing: expand the redraw area to
* cover it */
if (data.redraw.full_redraw) {
if (data.redraw.x >
- (int)(gif->frames[f - 1].redraw_x)) {
+ (int)(gif->gif->frames[f - 1].redraw_x)) {
data.redraw.width += data.redraw.x -
- gif->frames[f - 1].redraw_x;
- data.redraw.x = gif->frames[f - 1].redraw_x;
+ gif->gif->frames[f - 1].redraw_x;
+ data.redraw.x =
+ gif->gif->frames[f - 1].redraw_x;
}
if (data.redraw.y >
- (int)(gif->frames[f - 1].redraw_y)) {
+ (int)(gif->gif->frames[f - 1].redraw_y)) {
data.redraw.height += (data.redraw.y -
- gif->frames[f - 1].redraw_y);
- data.redraw.y = gif->frames[f - 1].redraw_y;
+ gif->gif->frames[f - 1].redraw_y);
+ data.redraw.y =
+ gif->gif->frames[f - 1].redraw_y;
}
- if ((int)(gif->frames[f - 1].redraw_x +
- gif->frames[f - 1].redraw_width) >
+ if ((int)(gif->gif->frames[f - 1].redraw_x +
+ gif->gif->frames[f - 1].redraw_width) >
(data.redraw.x + data.redraw.width))
data.redraw.width =
- gif->frames[f - 1].redraw_x -
- data.redraw.x +
- gif->frames[f - 1].redraw_width;
- if ((int)(gif->frames[f - 1].redraw_y +
- gif->frames[f - 1].redraw_height) >
+ gif->gif->frames[f - 1].redraw_x -
+ data.redraw.x +
+ gif->gif->frames[f - 1].redraw_width;
+ if ((int)(gif->gif->frames[f - 1].redraw_y +
+ gif->gif->frames[f - 1].redraw_height) >
(data.redraw.y + data.redraw.height))
data.redraw.height =
- gif->frames[f - 1].redraw_y -
- data.redraw.y +
- gif->frames[f - 1].
- redraw_height;
+ gif->gif->frames[f - 1].redraw_y -
+ data.redraw.y +
+ gif->gif->frames[f - 1].redraw_height;
}
} else {
/* do advanced check */
if ((data.redraw.x == 0) && (data.redraw.y == 0) &&
- (data.redraw.width == (int)(gif->width)) &&
- (data.redraw.height == (int)(gif->height))) {
- data.redraw.full_redraw = !gif->frames[f].opaque;
+ (data.redraw.width == (int)(gif->gif->width)) &&
+ (data.redraw.height == (int)(gif->gif->height))) {
+ data.redraw.full_redraw = !gif->gif->frames[f].opaque;
} else {
data.redraw.full_redraw = true;
data.redraw.x = 0;
data.redraw.y = 0;
- data.redraw.width = gif->width;
- data.redraw.height = gif->height;
+ data.redraw.width = gif->gif->width;
+ data.redraw.height = gif->gif->height;
}
}
/* other data */
- data.redraw.object = c;
+ data.redraw.object = (struct content *) gif;
data.redraw.object_x = 0;
data.redraw.object_y = 0;
- data.redraw.object_width = c->width;
- data.redraw.object_height = c->height;
+ data.redraw.object_width = gif->base.width;
+ data.redraw.object_height = gif->base.height;
- content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ content_broadcast(&gif->base, CONTENT_MSG_REDRAW, data);
}
diff --git a/image/gif.h b/image/gif.h
index a9f16d489..4ed06d09e 100644
--- a/image/gif.h
+++ b/image/gif.h
@@ -30,27 +30,13 @@
#include <stdbool.h>
#include <libnsgif.h>
-struct content;
-struct http_parameter;
-struct rect;
-
-struct content_gif_data {
- struct gif_animation *gif; /**< GIF animation data */
- int current_frame; /**< current frame to display [0...(max-1)] */
-};
-
-bool nsgif_create(struct content *c, const struct http_parameter *params);
-bool nsgif_convert(struct content *c);
-void nsgif_destroy(struct content *c);
-bool nsgif_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsgif_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsgif_clone(const struct content *old, struct content *new_content);
-void *nsgif_bitmap_create(int width, int height);
+nserror nsgif_init(void);
+void nsgif_fini(void);
+
+#else
+
+#define nsgif_init() NSERROR_OK
+#define nsgif_fini() ((void) 0)
#endif /* WITH_GIF */
diff --git a/image/ico.c b/image/ico.c
index a753f470b..0397c5c7f 100644
--- a/image/ico.c
+++ b/image/ico.c
@@ -33,42 +33,164 @@
#include "content/hlcache.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
+#include "image/bmp.h"
#include "image/ico.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
-bool nsico_create(struct content *c, const struct http_parameter *params)
+typedef struct nsico_content {
+ struct content base;
+
+ struct ico_collection *ico; /** ICO collection data */
+} nsico_content;
+
+static nserror nsico_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsico_create_ico_data(nsico_content *c);
+static bool nsico_convert(struct content *c);
+static void nsico_destroy(struct content *c);
+static bool nsico_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsico_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsico_clone(const struct content *old, struct content **newc);
+static content_type nsico_content_type(lwc_string *mime_type);
+
+static const content_handler nsico_content_handler = {
+ nsico_create,
+ NULL,
+ nsico_convert,
+ NULL,
+ nsico_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsico_redraw,
+ nsico_redraw_tiled,
+ NULL,
+ NULL,
+ nsico_clone,
+ NULL,
+ nsico_content_type,
+ false
+};
+
+static const char *nsico_types[] = {
+ "application/ico",
+ "application/x-ico",
+ "image/ico",
+ "image/vnd.microsoft.icon",
+ "image/x-icon"
+};
+
+static lwc_string *nsico_mime_types[NOF_ELEMENTS(nsico_types)];
+
+nserror nsico_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsico_mime_types); i++) {
+ lerror = lwc_intern_string(nsico_types[i],
+ strlen(nsico_types[i]),
+ &nsico_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsico_mime_types[i],
+ &nsico_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsico_fini();
+
+ return error;
+}
+
+void nsico_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsico_mime_types); i++) {
+ if (nsico_mime_types[i] != NULL)
+ lwc_string_unref(nsico_mime_types[i]);
+ }
+}
+
+nserror nsico_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsico_content *result;
+ nserror error;
+
+ result = talloc_zero(0, nsico_content);
+ if (result == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&result->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ error = nsico_create_ico_data(result);
+ if (error != NSERROR_OK) {
+ talloc_free(result);
+ return error;
+ }
+
+ *c = (struct content *) result;
+
+ return NSERROR_OK;
+}
+
+nserror nsico_create_ico_data(nsico_content *c)
{
union content_msg_data msg_data;
- c->data.ico.ico = calloc(sizeof(ico_collection), 1);
- if (!c->data.ico.ico) {
+
+ c->ico = calloc(sizeof(ico_collection), 1);
+ if (c->ico == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- ico_collection_create(c->data.ico.ico, &bmp_bitmap_callbacks);
- return true;
+ ico_collection_create(c->ico, &bmp_bitmap_callbacks);
+ return NSERROR_OK;
}
bool nsico_convert(struct content *c)
{
+ nsico_content *ico = (nsico_content *) c;
struct bmp_image *bmp;
bmp_result res;
- ico_collection *ico;
union content_msg_data msg_data;
const char *data;
unsigned long size;
char title[100];
/* set the ico data */
- ico = c->data.ico.ico;
-
data = content__get_source_data(c, &size);
/* analyse the ico */
- res = ico_analyse(ico, size, (unsigned char *) data);
+ res = ico_analyse(ico->ico, size, (unsigned char *) data);
switch (res) {
case BMP_OK:
@@ -85,15 +207,15 @@ bool nsico_convert(struct content *c)
}
/* Store our content width and description */
- c->width = ico->width;
- c->height = ico->height;
+ c->width = ico->ico->width;
+ c->height = ico->ico->height;
snprintf(title, sizeof(title), messages_get("ICOTitle"),
c->width, c->height, size);
content__set_title(c, title);
- c->size += (ico->width * ico->height * 4) + 16 + 44;
+ c->size += (ico->ico->width * ico->ico->height * 4) + 16 + 44;
/* exit as a success */
- bmp = ico_find(c->data.ico.ico, 255, 255);
+ bmp = ico_find(ico->ico, 255, 255);
assert(bmp);
c->bitmap = bmp->bitmap;
bitmap_modified(c->bitmap);
@@ -110,7 +232,8 @@ bool nsico_redraw(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
- struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp = ico_find(ico->ico, width, height);
if (!bmp->decoded)
if (bmp_decode(bmp) != BMP_OK)
return false;
@@ -119,33 +242,13 @@ bool nsico_redraw(struct content *c, int x, int y,
background_colour, BITMAPF_NONE);
}
-/** sets the bitmap for an ico according to the dimensions */
-
-bool nsico_set_bitmap_from_size(hlcache_handle *h, int width, int height)
-{
- struct content *c = hlcache_handle_get_content(h);
- struct bmp_image *bmp;
-
- assert(c != NULL);
-
- bmp = ico_find(c->data.ico.ico, width, height);
- if (bmp == NULL)
- return false;
-
- if ((bmp->decoded == false) && (bmp_decode(bmp) != BMP_OK))
- return false;
-
- c->bitmap = bmp->bitmap;
-
- return true;
-}
-
bool nsico_redraw_tiled(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
- struct bmp_image *bmp = ico_find(c->data.ico.ico, width, height);
+ nsico_content *ico = (nsico_content *) c;
+ struct bmp_image *bmp = ico_find(ico->ico, width, height);
bitmap_flags_t flags = BITMAPF_NONE;
if (!bmp->decoded)
@@ -165,23 +268,50 @@ bool nsico_redraw_tiled(struct content *c, int x, int y,
void nsico_destroy(struct content *c)
{
- ico_finalise(c->data.ico.ico);
- free(c->data.ico.ico);
+ nsico_content *ico = (nsico_content *) c;
+
+ ico_finalise(ico->ico);
+ free(ico->ico);
}
-bool nsico_clone(const struct content *old, struct content *new_content)
+nserror nsico_clone(const struct content *old, struct content **newc)
{
+ nsico_content *ico;
+ nserror error;
+
+ ico = talloc_zero(0, nsico_content);
+ if (ico == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &ico->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&ico->base);
+ return error;
+ }
+
/* Simply replay creation and conversion */
- if (nsico_create(new_content, NULL) == false)
- return false;
+ error = nsico_create_ico_data(ico);
+ if (error != NSERROR_OK) {
+ content_destroy(&ico->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsico_convert(new_content) == false)
- return false;
+ if (nsico_convert(&ico->base) == false) {
+ content_destroy(&ico->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) ico;
+
+ return NSERROR_OK;
+}
+
+content_type nsico_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif
diff --git a/image/ico.h b/image/ico.h
index 666c22371..5df3bca95 100644
--- a/image/ico.h
+++ b/image/ico.h
@@ -29,28 +29,15 @@
#include <stdbool.h>
#include <libnsbmp.h>
-struct content;
-struct hlcache_handle;
-struct http_parameter;
-struct rect;
-
-struct content_ico_data {
- struct ico_collection *ico; /** ICO collection data */
-};
-
-bool nsico_create(struct content *c, const struct http_parameter *params);
-bool nsico_convert(struct content *c);
-void nsico_destroy(struct content *c);
-bool nsico_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsico_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsico_clone(const struct content *old, struct content *new_content);
-bool nsico_set_bitmap_from_size(struct hlcache_handle *h,
- int width, int height);
+#include "utils/errors.h"
+
+nserror nsico_init(void);
+void nsico_fini(void);
+
+#else
+
+#define nsico_init() NSERROR_OK
+#define nsico_fini() ((void) 0)
#endif /* WITH_BMP */
diff --git a/image/image.c b/image/image.c
new file mode 100644
index 000000000..23853f133
--- /dev/null
+++ b/image/image.c
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "image/image.h"
+
+#include "image/bmp.h"
+#include "image/gif.h"
+#include "image/ico.h"
+#include "image/jpeg.h"
+#include "image/mng.h"
+#include "image/nssprite.h"
+#include "image/png.h"
+#include "image/rsvg.h"
+#include "image/svg.h"
+#include "image/webp.h"
+
+/**
+ * Initialise image content handlers
+ *
+ * \return NSERROR_OK on success, appropriate error otherwise.
+ */
+nserror image_init(void)
+{
+ nserror error;
+
+ error = nsbmp_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsgif_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsico_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nsjpeg_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ /* Prefer libpng over libmng for pngs */
+ error = nsmng_init();
+ if (error != NSERROR_OK)
+ return error;
+ error = nspng_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = nssprite_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ /* Prefer rsvg over libsvgtiny for svgs */
+ error = svg_init();
+ if (error != NSERROR_OK)
+ return error;
+ error = nsrsvg_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ error = webp_init();
+ if (error != NSERROR_OK)
+ return error;
+
+ return NSERROR_OK;
+}
+
+/**
+ * Finalise image content handlers
+ */
+void image_fini(void)
+{
+ nsbmp_fini();
+ nsgif_fini();
+ nsico_fini();
+ nsjpeg_fini();
+ nsmng_fini();
+ nssprite_fini();
+ nspng_fini();
+ nsrsvg_fini();
+ svg_fini();
+ webp_fini();
+}
+
diff --git a/image/image.h b/image/image.h
new file mode 100644
index 000000000..44ea148a8
--- /dev/null
+++ b/image/image.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2011 John-Mark Bell <jmb@netsurf-browser.org>
+ *
+ * This file is part of NetSurf, http://www.netsurf-browser.org/
+ *
+ * NetSurf is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * NetSurf is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/** \file
+ * Initialisation/finalisation of image handlers.
+ */
+
+#ifndef NETSURF_IMAGE_IMAGE_H_
+#define NETSURF_IMAGE_IMAGE_H_
+
+#include "utils/errors.h"
+
+nserror image_init(void);
+void image_fini(void);
+
+#endif
diff --git a/image/jpeg.c b/image/jpeg.c
index 7ef621121..05519d63f 100644
--- a/image/jpeg.c
+++ b/image/jpeg.c
@@ -26,20 +26,19 @@
#include "utils/config.h"
#ifdef WITH_JPEG
-/* This must come first due to libpng issues */
-#include "content/content_protected.h"
-
#include <assert.h>
#include <setjmp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
+#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
#define JPEG_INTERNAL_OPTIONS
@@ -57,12 +56,30 @@
static char nsjpeg_error_buffer[JMSG_LENGTH_MAX];
+typedef struct nsjpeg_content {
+ struct content base;
+} nsjpeg_content;
struct nsjpeg_error_mgr {
struct jpeg_error_mgr pub;
jmp_buf setjmp_buffer;
};
+static nserror nsjpeg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool nsjpeg_convert(struct content *c);
+static void nsjpeg_destroy(struct content *c);
+static bool nsjpeg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsjpeg_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsjpeg_clone(const struct content *old, struct content **newc);
+static content_type nsjpeg_content_type(lwc_string *mime_type);
static void nsjpeg_error_exit(j_common_ptr cinfo);
static void nsjpeg_init_source(j_decompress_ptr cinfo);
@@ -70,6 +87,95 @@ static boolean nsjpeg_fill_input_buffer(j_decompress_ptr cinfo);
static void nsjpeg_skip_input_data(j_decompress_ptr cinfo, long num_bytes);
static void nsjpeg_term_source(j_decompress_ptr cinfo);
+static const content_handler nsjpeg_content_handler = {
+ nsjpeg_create,
+ NULL,
+ nsjpeg_convert,
+ NULL,
+ nsjpeg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsjpeg_redraw,
+ nsjpeg_redraw_tiled,
+ NULL,
+ NULL,
+ nsjpeg_clone,
+ NULL,
+ nsjpeg_content_type,
+ false
+};
+
+static const char *nsjpeg_types[] = {
+ "image/jpeg",
+ "image/jpg",
+ "image/pjpeg"
+};
+
+static lwc_string *nsjpeg_mime_types[NOF_ELEMENTS(nsjpeg_types)];
+
+nserror nsjpeg_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nsjpeg_mime_types); i++) {
+ lerror = lwc_intern_string(nsjpeg_types[i],
+ strlen(nsjpeg_types[i]),
+ &nsjpeg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nsjpeg_mime_types[i],
+ &nsjpeg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsjpeg_fini();
+
+ return error;
+}
+
+void nsjpeg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nsjpeg_mime_types); i++) {
+ if (nsjpeg_mime_types[i] != NULL)
+ lwc_string_unref(nsjpeg_mime_types[i]);
+ }
+}
+
+nserror nsjpeg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsjpeg_content *jpeg;
+ nserror error;
+
+ jpeg = talloc_zero(0, nsjpeg_content);
+ if (jpeg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&jpeg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(jpeg);
+ return error;
+ }
+
+ *c = (struct content *) jpeg;
+
+ return NSERROR_OK;
+}
/**
* Convert a CONTENT_JPEG for display.
@@ -286,16 +392,38 @@ void nsjpeg_destroy(struct content *c)
}
-bool nsjpeg_clone(const struct content *old, struct content *new_content)
+nserror nsjpeg_clone(const struct content *old, struct content **newc)
{
+ nsjpeg_content *jpeg;
+ nserror error;
+
+ jpeg = talloc_zero(0, nsjpeg_content);
+ if (jpeg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &jpeg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&jpeg->base);
+ return error;
+ }
+
/* Simply replay conversion */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsjpeg_convert(new_content) == false)
- return false;
+ if (nsjpeg_convert(&jpeg->base) == false) {
+ content_destroy(&jpeg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) jpeg;
+
+ return NSERROR_OK;
+}
+
+content_type nsjpeg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif /* WITH_JPEG */
diff --git a/image/jpeg.h b/image/jpeg.h
index 70bae4a6b..57b82bdc1 100644
--- a/image/jpeg.h
+++ b/image/jpeg.h
@@ -28,24 +28,15 @@
#include <stdbool.h>
-struct bitmap;
-struct content;
-struct rect;
-
-struct content_jpeg_data {
- int dummy; /* NOT USED but to satisfy Norcroft */
-};
-
-bool nsjpeg_convert(struct content *c);
-void nsjpeg_destroy(struct content *c);
-bool nsjpeg_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsjpeg_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsjpeg_clone(const struct content *old, struct content *new_content);
+#include "utils/errors.h"
+
+nserror nsjpeg_init(void);
+void nsjpeg_fini(void);
+
+#else
+
+#define nsjpeg_init() NSERROR_OK
+#define nsjpeg_fini() ((void) 0)
#endif /* WITH_JPEG */
diff --git a/image/mng.c b/image/mng.c
index 6067aa8e8..a6b0377c4 100644
--- a/image/mng.c
+++ b/image/mng.c
@@ -23,9 +23,6 @@
#include "utils/config.h"
#ifdef WITH_MNG
-/* This must come first due to libpng issues */
-#include "content/content_protected.h"
-
#include <assert.h>
#include <stdbool.h>
#include <string.h>
@@ -33,6 +30,7 @@
#include <sys/time.h>
#include <time.h>
#include <libmng.h>
+#include "content/content_protected.h"
#include "desktop/options.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
@@ -40,12 +38,44 @@
#include "utils/log.h"
#include "utils/messages.h"
#include "utils/schedule.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
/* We do not currently support any form of colour/gamma correction, nor do
we support dynamic MNGs.
*/
+typedef struct nsmng_content
+{
+ struct content base;
+
+ bool opaque_test_pending;
+ bool read_start;
+ bool read_resume;
+ int read_size;
+ bool waiting;
+ bool displayed;
+ void *handle;
+} nsmng_content;
+
+static nserror nsmng_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nsmng_create_mng_data(nsmng_content *c);
+static bool nsmng_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool nsmng_convert(struct content *c);
+static void nsmng_destroy(struct content *c);
+static bool nsmng_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nsmng_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nsmng_clone(const struct content *old, struct content **newc);
+static content_type nsmng_content_type(lwc_string *mime_type);
static mng_bool nsmng_openstream(mng_handle mng);
static mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer,
@@ -59,7 +89,7 @@ static mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
mng_uint32 w, mng_uint32 h);
static mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs);
static void nsmng_animate(void *p);
-static bool nsmng_broadcast_error(struct content *c, mng_retcode code);
+static nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code);
static mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq,
mng_int32 extra1, mng_int32 extra2, mng_pchar text);
@@ -68,8 +98,131 @@ static mng_ptr nsmng_alloc(mng_size_t n);
static void nsmng_free(mng_ptr p, mng_size_t n);
#endif
+static const content_handler nsmng_content_handler = {
+ nsmng_create,
+ nsmng_process_data,
+ nsmng_convert,
+ NULL,
+ nsmng_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsmng_redraw,
+ nsmng_redraw_tiled,
+ NULL,
+ NULL,
+ nsmng_clone,
+ NULL,
+ nsmng_content_type,
+ false
+};
+
+static const char *jng_types[] = {
+ "image/jng",
+ "image/x-jng"
+};
+
+static const char *mng_types[] = {
+ "image/mng",
+ "image/x-mng",
+ "video/mng",
+ "video/x-mng"
+};
+
+static const char *png_types[] = {
+ "image/png"
+};
+
+static lwc_string *jng_mime_types[NOF_ELEMENTS(jng_types)];
+static lwc_string *mng_mime_types[NOF_ELEMENTS(mng_types)];
+static lwc_string *png_mime_types[NOF_ELEMENTS(png_types)];
+
+nserror nsmng_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+#define register_types(type) \
+ for (i = 0; i < NOF_ELEMENTS(type##_mime_types); i++) { \
+ lerror = lwc_intern_string(type##_types[i], \
+ strlen(type##_types[i]), \
+ &type##_mime_types[i]); \
+ if (lerror != lwc_error_ok) { \
+ error = NSERROR_NOMEM; \
+ goto error; \
+ } \
+ \
+ error = content_factory_register_handler( \
+ type##_mime_types[i], \
+ &nsmng_content_handler); \
+ if (error != NSERROR_OK) \
+ goto error; \
+ }
+
+ register_types(jng)
+ register_types(mng)
+ register_types(png)
+
+ return NSERROR_OK;
+
+error:
+ nsmng_fini();
+
+ return error;
+}
+
+void nsmng_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(jng_mime_types); i++) {
+ if (jng_mime_types[i] != NULL)
+ lwc_string_unref(jng_mime_types[i]);
+ }
+
+ for (i = 0; i < NOF_ELEMENTS(mng_mime_types); i++) {
+ if (mng_mime_types[i] != NULL)
+ lwc_string_unref(mng_mime_types[i]);
+ }
+
+ for (i = 0; i < NOF_ELEMENTS(png_mime_types); i++) {
+ if (png_mime_types[i] != NULL)
+ lwc_string_unref(png_mime_types[i]);
+ }
+}
+
+nserror nsmng_create(const content_handler *handler,
+ lwc_string *imime_type, const struct http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nsmng_content *mng;
+ nserror error;
+
+ mng = talloc_zero(0, nsmng_content);
+ if (mng == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&mng->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(mng);
+ return error;
+ }
+
+ error = nsmng_create_mng_data(mng);
+ if (error != NSERROR_OK) {
+ talloc_free(mng);
+ return error;
+ }
+
+ *c = (struct content *) mng;
-bool nsmng_create(struct content *c, const struct http_parameter *params)
+ return NSERROR_OK;
+}
+
+nserror nsmng_create_mng_data(nsmng_content *c)
{
mng_retcode code;
union content_msg_data msg_data;
@@ -79,20 +232,20 @@ bool nsmng_create(struct content *c, const struct http_parameter *params)
/* Initialise the library
*/
#ifdef MNG_INTERNAL_MEMMNGMT
- c->data.mng.handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL);
+ c->handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL);
#else
- c->data.mng.handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL);
+ c->handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL);
#endif
- if (c->data.mng.handle == MNG_NULL) {
+ if (c->handle == MNG_NULL) {
LOG(("Unable to initialise MNG library."));
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
/* We need to decode in suspension mode
*/
- code = mng_set_suspensionmode(c->data.mng.handle, MNG_TRUE);
+ code = mng_set_suspensionmode(c->handle, MNG_TRUE);
if (code) {
LOG(("Unable to set suspension mode."));
return nsmng_broadcast_error(c, code);
@@ -100,22 +253,22 @@ bool nsmng_create(struct content *c, const struct http_parameter *params)
/* We need to register our callbacks
*/
- code = mng_setcb_openstream(c->data.mng.handle, nsmng_openstream);
+ code = mng_setcb_openstream(c->handle, nsmng_openstream);
if (code) {
LOG(("Unable to set openstream callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_readdata(c->data.mng.handle, nsmng_readdata);
+ code = mng_setcb_readdata(c->handle, nsmng_readdata);
if (code) {
LOG(("Unable to set readdata callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_closestream(c->data.mng.handle, nsmng_closestream);
+ code = mng_setcb_closestream(c->handle, nsmng_closestream);
if (code) {
LOG(("Unable to set closestream callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_processheader(c->data.mng.handle, nsmng_processheader);
+ code = mng_setcb_processheader(c->handle, nsmng_processheader);
if (code) {
LOG(("Unable to set processheader callback."));
return nsmng_broadcast_error(c, code);
@@ -123,29 +276,29 @@ bool nsmng_create(struct content *c, const struct http_parameter *params)
/* Register our callbacks for displaying
*/
- code = mng_setcb_getcanvasline(c->data.mng.handle, nsmng_getcanvasline);
+ code = mng_setcb_getcanvasline(c->handle, nsmng_getcanvasline);
if (code) {
LOG(("Unable to set getcanvasline callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_refresh(c->data.mng.handle, nsmng_refresh);
+ code = mng_setcb_refresh(c->handle, nsmng_refresh);
if (code) {
LOG(("Unable to set refresh callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_gettickcount(c->data.mng.handle, nsmng_gettickcount);
+ code = mng_setcb_gettickcount(c->handle, nsmng_gettickcount);
if (code) {
LOG(("Unable to set gettickcount callback."));
return nsmng_broadcast_error(c, code);
}
- code = mng_setcb_settimer(c->data.mng.handle, nsmng_settimer);
+ code = mng_setcb_settimer(c->handle, nsmng_settimer);
if (code) {
LOG(("Unable to set settimer callback."));
return nsmng_broadcast_error(c, code);
}
/* register error handling function */
- code = mng_setcb_errorproc(c->data.mng.handle, nsmng_errorproc);
+ code = mng_setcb_errorproc(c->handle, nsmng_errorproc);
if (code) {
LOG(("Unable to set errorproc"));
return nsmng_broadcast_error(c, code);
@@ -153,13 +306,14 @@ bool nsmng_create(struct content *c, const struct http_parameter *params)
/* Initialise the reading
*/
- c->data.mng.read_start = true;
- c->data.mng.read_resume = false;
- c->data.mng.read_size = 0;
- c->data.mng.waiting = false;
+ c->read_start = true;
+ c->read_resume = false;
+ c->read_size = 0;
+ c->waiting = false;
- c->data.mng.displayed = false;
- return true;
+ c->displayed = false;
+
+ return NSERROR_OK;
}
@@ -176,7 +330,7 @@ mng_bool nsmng_openstream(mng_handle mng)
mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size,
mng_uint32 *bytesread)
{
- struct content *c;
+ nsmng_content *c;
const char *data;
unsigned long data_size;
@@ -186,19 +340,19 @@ mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size,
/* Get our content back
*/
- c = (struct content *) mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Copy any data we have (maximum of 'size')
*/
- data = content__get_source_data(c, &data_size);
+ data = content__get_source_data(&c->base, &data_size);
- *bytesread = ((data_size - c->data.mng.read_size) < size) ?
- (data_size - c->data.mng.read_size) : size;
+ *bytesread = ((data_size - c->read_size) < size) ?
+ (data_size - c->read_size) : size;
if ((*bytesread) > 0) {
- memcpy(buffer, data + c->data.mng.read_size, *bytesread);
- c->data.mng.read_size += *bytesread;
+ memcpy(buffer, data + c->read_size, *bytesread);
+ c->read_size += *bytesread;
}
/* Return success
@@ -215,7 +369,7 @@ mng_bool nsmng_closestream(mng_handle mng)
mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width,
mng_uint32 height)
{
- struct content *c;
+ nsmng_content *c;
union content_msg_data msg_data;
uint8_t *buffer;
@@ -224,31 +378,31 @@ mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width,
/* This function is called when the header has been read and we
know the dimensions of the canvas.
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
- c->bitmap = bitmap_create(width, height, BITMAP_NEW);
- if (!c->bitmap) {
+ c->base.bitmap = bitmap_create(width, height, BITMAP_NEW);
+ if (c->base.bitmap == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
LOG(("Insufficient memory to create canvas."));
return MNG_FALSE;
}
/* Get the buffer to ensure that it is allocated and the calls in
* nsmng_getcanvasline() succeed. */
- buffer = bitmap_get_buffer(c->bitmap);
- if (!buffer) {
+ buffer = bitmap_get_buffer(c->base.bitmap);
+ if (buffer == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
LOG(("Insufficient memory to create canvas."));
return MNG_FALSE;
}
/* Initialise the content size
*/
- c->width = width;
- c->height = height;
+ c->base.width = width;
+ c->base.height = height;
/* Set the canvas style
*/
@@ -268,6 +422,7 @@ mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width,
bool nsmng_process_data(struct content *c, const char *data, unsigned int size)
{
+ nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
assert(c != NULL);
@@ -275,21 +430,21 @@ bool nsmng_process_data(struct content *c, const char *data, unsigned int size)
/* We only need to do any processing if we're starting/resuming reading.
*/
- if ((!c->data.mng.read_resume) && (!c->data.mng.read_start))
+ if ((!mng->read_resume) && (!mng->read_start))
return true;
/* Try to start processing, or process some more data
*/
- if (c->data.mng.read_start) {
- status = mng_read(c->data.mng.handle);
- c->data.mng.read_start = false;
+ if (mng->read_start) {
+ status = mng_read(mng->handle);
+ mng->read_start = false;
} else {
- status = mng_read_resume(c->data.mng.handle);
+ status = mng_read_resume(mng->handle);
}
- c->data.mng.read_resume = (status == MNG_NEEDMOREDATA);
+ mng->read_resume = (status == MNG_NEEDMOREDATA);
if ((status != MNG_NOERROR) && (status != MNG_NEEDMOREDATA)) {
LOG(("Failed to start/continue reading (%i).", status));
- return nsmng_broadcast_error(c, status);
+ return nsmng_broadcast_error(mng, status) == NSERROR_OK;
}
/* Continue onwards
@@ -300,9 +455,14 @@ bool nsmng_process_data(struct content *c, const char *data, unsigned int size)
bool nsmng_convert(struct content *c)
{
+ nsmng_content *mng = (nsmng_content *) c;
mng_retcode status;
const char *data;
unsigned long size;
+ lwc_string *content_type;
+ bool match;
+ bool is_mng = false;
+ uint32_t i;
char title[100];
assert(c != NULL);
@@ -312,15 +472,26 @@ bool nsmng_convert(struct content *c)
/* by this point, the png should have been parsed
* and the bitmap created, so ensure that's the case
*/
- if (!c->bitmap)
- return nsmng_broadcast_error(c, -1);
+ if (content__get_bitmap(c) == NULL)
+ return nsmng_broadcast_error(mng, -1) == NSERROR_OK;
/* Set the title
*/
- if (c->type == CONTENT_MNG) {
+ content_type = content__get_mime_type(c);
+
+ for (i = 0; i < NOF_ELEMENTS(mng_mime_types); i++) {
+ if (lwc_string_caseless_isequal(content_type, mng_mime_types[i],
+ &match) == lwc_error_ok && match) {
+ is_mng = true;
+ break;
+ }
+ }
+
+ if (is_mng) {
snprintf(title, sizeof(title), messages_get("MNGTitle"),
c->width, c->height, size);
- } else if (c->type == CONTENT_PNG) {
+ } else if (lwc_string_caseless_isequal(content_type, png_mime_types[0],
+ &match) == lwc_error_ok && match) {
snprintf(title, sizeof(title), messages_get("PNGTitle"),
c->width, c->height, size);
} else {
@@ -329,6 +500,8 @@ bool nsmng_convert(struct content *c)
}
content__set_title(c, title);
+ lwc_string_unref(content_type);
+
c->size += c->width * c->height * 4;
content_set_ready(c);
content_set_done(c);
@@ -349,28 +522,27 @@ bool nsmng_convert(struct content *c)
*/
/* Start displaying
*/
- status = mng_display(c->data.mng.handle);
+ status = mng_display(mng->handle);
if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) {
LOG(("Unable to start display (%i)", status));
- return nsmng_broadcast_error(c, status);
+ return nsmng_broadcast_error(mng, status) == NSERROR_OK;
}
bitmap_modified(c->bitmap);
/* Optimise the plotting of JNG/PNGs
*/
- c->data.mng.opaque_test_pending = (c->type == CONTENT_PNG) ||
- (c->type == CONTENT_JNG);
- if (c->data.mng.opaque_test_pending)
+ mng->opaque_test_pending = (is_mng == false);
+ if (mng->opaque_test_pending)
bitmap_set_opaque(c->bitmap, false);
/* free associated memory except for mngs where it may be subsequently needed for
* animation decoding. */
- if (c->type != CONTENT_MNG) {
- mng_handle handle = c->data.mng.handle;
+ if (is_mng == false) {
+ mng_handle handle = mng->handle;
mng_cleanup(&handle);
- c->data.mng.handle = NULL;
+ mng->handle = NULL;
}
return true;
@@ -383,19 +555,19 @@ bool nsmng_convert(struct content *c)
mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line)
{
- struct content *c;
+ nsmng_content *c;
assert(mng != NULL);
/* Get our content back
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Calculate the address
*/
- return bitmap_get_buffer(c->bitmap) +
- bitmap_get_rowstride(c->bitmap) * line;
+ return bitmap_get_buffer(c->base.bitmap) +
+ bitmap_get_rowstride(c->base.bitmap) * line;
}
@@ -433,13 +605,13 @@ mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
mng_uint32 w, mng_uint32 h)
{
union content_msg_data data;
- struct content *c;
+ nsmng_content *c;
assert(mng != NULL);
/* Get our content back
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Set the minimum redraw area
@@ -463,11 +635,11 @@ mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
/* Set the object characteristics
*/
- data.redraw.object = c;
+ data.redraw.object = &c->base;
data.redraw.object_x = 0;
data.redraw.object_y = 0;
- data.redraw.object_width = c->width;
- data.redraw.object_height = c->height;
+ data.redraw.object_width = c->base.width;
+ data.redraw.object_height = c->base.height;
/* Only attempt to force the redraw if we've been requested to
* display the image in the first place (i.e. nsmng_redraw has
@@ -475,21 +647,21 @@ mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y,
* an image that shouldn't be shown (e.g. if the image is a fallback
* for an object that can't be rendered)
*/
- if (c->data.mng.displayed)
- content_broadcast(c, CONTENT_MSG_REDRAW, data);
+ if (c->displayed)
+ content_broadcast(&c->base, CONTENT_MSG_REDRAW, data);
return MNG_TRUE;
}
mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs)
{
- struct content *c;
+ nsmng_content *c;
assert(mng != NULL);
/* Get our content back
*/
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
/* Perform the scheduling
@@ -505,18 +677,20 @@ mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs)
void nsmng_destroy(struct content *c)
{
+ nsmng_content *mng = (nsmng_content *) c;
assert (c != NULL);
/* Cleanup the MNG structure and release the canvas memory
*/
schedule_remove(nsmng_animate, c);
- if (c->type == CONTENT_MNG) {
- mng_handle handle = c->data.mng.handle;
+
+ if (mng->handle != NULL) {
+ mng_handle handle = mng->handle;
mng_cleanup(&handle);
- c->data.mng.handle = NULL;
+ mng->handle = NULL;
}
if (c->bitmap)
@@ -528,14 +702,15 @@ bool nsmng_redraw(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ nsmng_content *mng = (nsmng_content *) c;
bool ret;
/* mark image as having been requested to display */
- c->data.mng.displayed = true;
+ mng->displayed = true;
- if ((c->bitmap) && (c->data.mng.opaque_test_pending)) {
+ if ((c->bitmap) && (mng->opaque_test_pending)) {
bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
- c->data.mng.opaque_test_pending = false;
+ mng->opaque_test_pending = false;
}
ret = plot.bitmap(x, y, width, height,
@@ -543,7 +718,7 @@ bool nsmng_redraw(struct content *c, int x, int y,
/* Check if we need to restart the animation
*/
- if ((c->data.mng.waiting) && (option_animate_images))
+ if ((mng->waiting) && (option_animate_images))
nsmng_animate(c);
return ret;
@@ -555,15 +730,16 @@ bool nsmng_redraw_tiled(struct content *c, int x, int y,
float scale, colour background_colour,
bool repeat_x, bool repeat_y)
{
+ nsmng_content *mng = (nsmng_content *) c;
bool ret;
bitmap_flags_t flags = BITMAPF_NONE;
/* mark image as having been requested to display */
- c->data.mng.displayed = true;
+ mng->displayed = true;
- if ((c->bitmap) && (c->data.mng.opaque_test_pending)) {
+ if ((c->bitmap) && (mng->opaque_test_pending)) {
bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
- c->data.mng.opaque_test_pending = false;
+ mng->opaque_test_pending = false;
}
if (repeat_x)
@@ -577,35 +753,61 @@ bool nsmng_redraw_tiled(struct content *c, int x, int y,
/* Check if we need to restart the animation
*/
- if ((c->data.mng.waiting) && (option_animate_images))
+ if ((mng->waiting) && (option_animate_images))
nsmng_animate(c);
return ret;
}
-bool nsmng_clone(const struct content *old, struct content *new_content)
+nserror nsmng_clone(const struct content *old, struct content **newc)
{
+ nsmng_content *mng;
+ nserror error;
const char *data;
unsigned long size;
+ mng = talloc_zero(0, nsmng_content);
+ if (mng == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &mng->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&mng->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (nsmng_create(new_content, NULL) == false)
- return false;
+ error = nsmng_create_mng_data(mng);
+ if (error != NSERROR_OK) {
+ content_destroy(&mng->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&mng->base, &size);
if (size > 0) {
- if (nsmng_process_data(new_content, data, size) == false)
- return false;
+ if (nsmng_process_data(&mng->base, data, size) == false) {
+ content_destroy(&mng->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nsmng_convert(new_content) == false)
- return false;
+ if (nsmng_convert(&mng->base) == false) {
+ content_destroy(&mng->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) mng;
+
+ return NSERROR_OK;
+}
+
+content_type nsmng_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
/**
@@ -613,22 +815,22 @@ bool nsmng_clone(const struct content *old, struct content *new_content)
*/
void nsmng_animate(void *p)
{
- struct content *c;
+ nsmng_content *c;
assert(p != NULL);
- c = (struct content *)p;
+ c = (nsmng_content *) p;
/* If we used the last animation we advance, if not we try again later
*/
- if (c->user_list->next == NULL) {
- c->data.mng.waiting = true;
+ if (c->base.user_list->next == NULL) {
+ c->waiting = true;
} else {
- c->data.mng.waiting = false;
- mng_display_resume(c->data.mng.handle);
- c->data.mng.opaque_test_pending = true;
- if (c->bitmap)
- bitmap_modified(c->bitmap);
+ c->waiting = false;
+ mng_display_resume(c->handle);
+ c->opaque_test_pending = true;
+ if (c->base.bitmap)
+ bitmap_modified(c->base.bitmap);
}
}
@@ -638,9 +840,9 @@ void nsmng_animate(void *p)
* Broadcasts an error message and returns false
*
* \param c the content to broadcast for
- * \return false
+ * \return Appropriate error
*/
-bool nsmng_broadcast_error(struct content *c, mng_retcode code)
+nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code)
{
union content_msg_data msg_data;
char error[100];
@@ -649,14 +851,14 @@ bool nsmng_broadcast_error(struct content *c, mng_retcode code)
if (code == MNG_OUTOFMEMORY) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
snprintf(error, sizeof error, messages_get("MNGError"), code);
msg_data.error = error;
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_MNG_ERROR;
}
@@ -664,12 +866,12 @@ mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq,
mng_int32 extra1, mng_int32 extra2, mng_pchar text)
{
- struct content *c;
+ nsmng_content *c;
char chunk[5];
assert(mng != NULL);
- c = (struct content *)mng_get_userdata(mng);
+ c = (nsmng_content *) mng_get_userdata(mng);
assert(c != NULL);
chunk[0] = (char)((chunktype >> 24) & 0xFF);
@@ -679,11 +881,11 @@ mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code,
chunk[4] = '\0';
LOG(("error playing '%s' chunk %s (%d):",
- content__get_url(c), chunk, chunkseq));
+ content__get_url(&c->base), chunk, chunkseq));
LOG(("code %d severity %d extra1 %d extra2 %d text:'%s'", code,
severity, extra1, extra2, text));
- return (0);
+ return (0);
}
diff --git a/image/mng.h b/image/mng.h
index 5835fef96..a3318615b 100644
--- a/image/mng.h
+++ b/image/mng.h
@@ -28,32 +28,13 @@
#include <stdbool.h>
-struct content;
-struct http_parameter;
-struct rect;
-
-struct content_mng_data {
- bool opaque_test_pending;
- bool read_start;
- bool read_resume;
- int read_size;
- bool waiting;
- bool displayed;
- void *handle;
-};
-
-bool nsmng_create(struct content *c, const struct http_parameter *params);
-bool nsmng_process_data(struct content *c, const char *data, unsigned int size);
-bool nsmng_convert(struct content *c);
-void nsmng_destroy(struct content *c);
-bool nsmng_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nsmng_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nsmng_clone(const struct content *old, struct content *new_content);
+nserror nsmng_init(void);
+void nsmng_fini(void);
+
+#else
+
+#define nsmng_init() NSERROR_OK
+#define nsmng_fini() ((void) 0)
#endif /* WITH_MNG */
diff --git a/image/nssprite.c b/image/nssprite.c
index a0ad8678c..961188c84 100644
--- a/image/nssprite.c
+++ b/image/nssprite.c
@@ -29,13 +29,33 @@
#include <stdlib.h>
#include <librosprite.h>
#include "utils/config.h"
+#include "content/content_protected.h"
#include "desktop/plotters.h"
#include "image/bitmap.h"
-#include "content/content_protected.h"
+#include "image/nssprite.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct nssprite_content {
+ struct content base;
+
+ struct rosprite_area* sprite_area;
+} nssprite_content;
+
+static nserror nssprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool nssprite_convert(struct content *c);
+static void nssprite_destroy(struct content *c);
+static bool nssprite_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror nssprite_clone(const struct content *old, struct content **newc);
+static content_type nssprite_content_type(lwc_string *mime_type);
+
#define ERRCHK(x) do { \
rosprite_error err = x; \
if (err == ROSPRITE_EOF) { \
@@ -50,6 +70,94 @@
} \
} while(0)
+static const content_handler nssprite_content_handler = {
+ nssprite_create,
+ NULL,
+ nssprite_convert,
+ NULL,
+ nssprite_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nssprite_redraw,
+ NULL,
+ NULL,
+ NULL,
+ nssprite_clone,
+ NULL,
+ nssprite_content_type,
+ false
+};
+
+static const char *nssprite_types[] = {
+ "image/x-riscos-sprite"
+};
+
+static lwc_string *nssprite_mime_types[NOF_ELEMENTS(nssprite_types)];
+
+nserror nssprite_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nssprite_mime_types); i++) {
+ lerror = lwc_intern_string(nssprite_types[i],
+ strlen(nssprite_types[i]),
+ &nssprite_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nssprite_mime_types[i],
+ &nssprite_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nssprite_fini();
+
+ return error;
+}
+
+void nssprite_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nssprite_mime_types); i++) {
+ if (nssprite_mime_types[i] != NULL)
+ lwc_string_unref(nssprite_mime_types[i]);
+ }
+}
+
+nserror nssprite_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nssprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, nssprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&sprite->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(sprite);
+ return error;
+ }
+
+ *c = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_SPRITE for display.
*
@@ -58,6 +166,7 @@
bool nssprite_convert(struct content *c)
{
+ nssprite_content *nssprite = (nssprite_content *) c;
union content_msg_data msg_data;
struct rosprite_mem_context* ctx;
@@ -72,7 +181,7 @@ bool nssprite_convert(struct content *c)
struct rosprite_area* sprite_area;
ERRCHK(rosprite_load(rosprite_mem_reader, ctx, &sprite_area));
rosprite_destroy_mem_context(ctx);
- c->data.nssprite.sprite_area = sprite_area;
+ nssprite->sprite_area = sprite_area;
assert(sprite_area->sprite_count > 0);
@@ -126,8 +235,10 @@ bool nssprite_convert(struct content *c)
void nssprite_destroy(struct content *c)
{
- if (c->data.nssprite.sprite_area != NULL)
- rosprite_destroy_sprite_area(c->data.nssprite.sprite_area);
+ nssprite_content *sprite = (nssprite_content *) c;
+
+ if (sprite->sprite_area != NULL)
+ rosprite_destroy_sprite_area(sprite->sprite_area);
if (c->bitmap != NULL)
bitmap_destroy(c->bitmap);
}
@@ -146,16 +257,38 @@ bool nssprite_redraw(struct content *c, int x, int y,
}
-bool nssprite_clone(const struct content *old, struct content *new_content)
+nserror nssprite_clone(const struct content *old, struct content **newc)
{
+ nssprite_content *sprite;
+ nserror error;
+
+ sprite = talloc_zero(0, nssprite_content);
+ if (sprite == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &sprite->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&sprite->base);
+ return error;
+ }
+
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nssprite_convert(new_content) == false)
- return false;
+ if (nssprite_convert(&sprite->base) == false) {
+ content_destroy(&sprite->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) sprite;
+
+ return NSERROR_OK;
+}
+
+content_type nssprite_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif
diff --git a/image/nssprite.h b/image/nssprite.h
index 3b69108cd..1f25896b3 100644
--- a/image/nssprite.h
+++ b/image/nssprite.h
@@ -28,19 +28,13 @@
#include <stdbool.h>
-struct content;
-struct rect;
-
-struct content_nssprite_data {
- struct rosprite_area* sprite_area;
-};
-
-bool nssprite_convert(struct content *c);
-void nssprite_destroy(struct content *c);
-bool nssprite_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nssprite_clone(const struct content *old, struct content *new_content);
+nserror nssprite_init(void);
+void nssprite_fini(void);
+
+#else
+
+#define nssprite_init() NSERROR_OK
+#define nssprite_fini() ((void) 0)
#endif /* WITH_NSSPRITE */
diff --git a/image/png.c b/image/png.c
index 159019996..5469e6923 100644
--- a/image/png.c
+++ b/image/png.c
@@ -23,8 +23,7 @@
#include <string.h>
#include <stdlib.h>
-/* Ugh -- setjmp.h weirdness ensues if this isn't first... */
-#include "image/png.h"
+#include <png.h>
#include "utils/config.h"
@@ -33,14 +32,16 @@
#include "content/content_protected.h"
#include "image/bitmap.h"
+#include "image/png.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
#ifdef WITH_PNG
-/* accomodate for old versions of libpng (beware security holes!) */
+/* accommodate for old versions of libpng (beware security holes!) */
#ifndef png_jmpbuf
#warning you have an antique libpng
@@ -51,72 +52,190 @@
#define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png)
#endif
-/* libpng uses names starting png_, so use nspng_ here to avoid clashes */
+typedef struct nspng_content {
+ struct content base;
+
+ png_structp png;
+ png_infop info;
+ int interlace;
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+ size_t rowstride, bpp; /**< Bitmap rowstride and bpp */
+ size_t rowbytes; /**< Number of bytes per row */
+} nspng_content;
+
+static nserror nspng_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror nspng_create_png_data(nspng_content *c);
+static bool nspng_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool nspng_convert(struct content *c);
+static void nspng_destroy(struct content *c);
+static bool nspng_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static bool nspng_redraw_tiled(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour,
+ bool repeat_x, bool repeat_y);
+static nserror nspng_clone(const struct content *old, struct content **newc);
+static content_type nspng_content_type(lwc_string *mime_type);
static void info_callback(png_structp png, png_infop info);
static void row_callback(png_structp png, png_bytep new_row,
png_uint_32 row_num, int pass);
static void end_callback(png_structp png, png_infop info);
+static const content_handler nspng_content_handler = {
+ nspng_create,
+ nspng_process_data,
+ nspng_convert,
+ NULL,
+ nspng_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nspng_redraw,
+ nspng_redraw_tiled,
+ NULL,
+ NULL,
+ nspng_clone,
+ NULL,
+ nspng_content_type,
+ false
+};
+
+static const char *nspng_types[] = {
+ "image/png"
+};
+
+static lwc_string *nspng_mime_types[NOF_ELEMENTS(nspng_types)];
+
+nserror nspng_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
+ lerror = lwc_intern_string(nspng_types[i],
+ strlen(nspng_types[i]),
+ &nspng_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(nspng_mime_types[i],
+ &nspng_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nspng_fini();
+
+ return error;
+}
+
+void nspng_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) {
+ if (nspng_mime_types[i] != NULL)
+ lwc_string_unref(nspng_mime_types[i]);
+ }
+}
-bool nspng_create(struct content *c, const struct http_parameter *params)
+nserror nspng_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ nspng_content *png;
+ nserror error;
+
+ png = talloc_zero(0, nspng_content);
+ if (png == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&png->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(png);
+ return error;
+ }
+
+ error = nspng_create_png_data(png);
+ if (error != NSERROR_OK) {
+ talloc_free(png);
+ return error;
+ }
+
+ *c = (struct content *) png;
+
+ return NSERROR_OK;
+}
+
+nserror nspng_create_png_data(nspng_content *c)
{
union content_msg_data msg_data;
- c->data.png.bitmap = NULL;
+ c->bitmap = NULL;
- c->data.png.png = png_create_read_struct(PNG_LIBPNG_VER_STRING,
- 0, 0, 0);
- if (c->data.png.png == NULL) {
+ c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
+ if (c->png == NULL) {
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
warn_user("NoMemory", 0);
- return false;
+ return NSERROR_NOMEM;
}
- c->data.png.info = png_create_info_struct(c->data.png.png);
- if (c->data.png.info == NULL) {
- png_destroy_read_struct(&c->data.png.png,
- &c->data.png.info, 0);
+ c->info = png_create_info_struct(c->png);
+ if (c->info == NULL) {
+ png_destroy_read_struct(&c->png, &c->info, 0);
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
warn_user("NoMemory", 0);
- return false;
+ return NSERROR_NOMEM;
}
- if (setjmp(png_jmpbuf(c->data.png.png))) {
- png_destroy_read_struct(&c->data.png.png,
- &c->data.png.info, 0);
+ if (setjmp(png_jmpbuf(c->png))) {
+ png_destroy_read_struct(&c->png, &c->info, 0);
LOG(("Failed to set callbacks"));
- c->data.png.png = NULL;
- c->data.png.info = NULL;
+ c->png = NULL;
+ c->info = NULL;
msg_data.error = messages_get("PNGError");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- png_set_progressive_read_fn(c->data.png.png, c,
+ png_set_progressive_read_fn(c->png, c,
info_callback, row_callback, end_callback);
- return true;
+ return NSERROR_OK;
}
bool nspng_process_data(struct content *c, const char *data, unsigned int size)
{
+ nspng_content *png = (nspng_content *) c;
union content_msg_data msg_data;
- if (setjmp(png_jmpbuf(c->data.png.png))) {
- png_destroy_read_struct(&c->data.png.png,
- &c->data.png.info, 0);
+ if (setjmp(png_jmpbuf(png->png))) {
+ png_destroy_read_struct(&png->png, &png->info, 0);
LOG(("Failed to process data"));
- c->data.png.png = NULL;
- c->data.png.info = NULL;
- if (c->data.png.bitmap != NULL) {
- bitmap_destroy(c->data.png.bitmap);
- c->data.png.bitmap = NULL;
+ png->png = NULL;
+ png->info = NULL;
+ if (png->bitmap != NULL) {
+ bitmap_destroy(png->bitmap);
+ png->bitmap = NULL;
}
msg_data.error = messages_get("PNGError");
@@ -124,8 +243,7 @@ bool nspng_process_data(struct content *c, const char *data, unsigned int size)
return false;
}
- png_process_data(c->data.png.png, c->data.png.info,
- (uint8_t *) data, size);
+ png_process_data(png->png, png->info, (uint8_t *) data, size);
return true;
}
@@ -141,21 +259,21 @@ void info_callback(png_structp png, png_infop info)
int bit_depth, color_type, interlace, intent;
double gamma;
png_uint_32 width, height;
- struct content *c = png_get_progressive_ptr(png);
+ nspng_content *c = png_get_progressive_ptr(png);
/* Read the PNG details */
png_get_IHDR(png, info, &width, &height, &bit_depth,
&color_type, &interlace, 0, 0);
/* Claim the required memory for the converted PNG */
- c->data.png.bitmap = bitmap_create(width, height, BITMAP_NEW);
- if (c->data.png.bitmap == NULL) {
+ c->bitmap = bitmap_create(width, height, BITMAP_NEW);
+ if (c->bitmap == NULL) {
/* Failed -- bail out */
longjmp(png_jmpbuf(png), 1);
}
- c->data.png.rowstride = bitmap_get_rowstride(c->data.png.bitmap);
- c->data.png.bpp = bitmap_get_bpp(c->data.png.bitmap);
+ c->rowstride = bitmap_get_rowstride(c->bitmap);
+ c->bpp = bitmap_get_bpp(c->bitmap);
/* Set up our transformations */
if (color_type == PNG_COLOR_TYPE_PALETTE)
@@ -187,13 +305,13 @@ void info_callback(png_structp png, png_infop info)
png_read_update_info(png, info);
- c->data.png.rowbytes = png_get_rowbytes(png, info);
- c->data.png.interlace = (interlace == PNG_INTERLACE_ADAM7);
- c->width = width;
- c->height = height;
+ c->rowbytes = png_get_rowbytes(png, info);
+ c->interlace = (interlace == PNG_INTERLACE_ADAM7);
+ c->base.width = width;
+ c->base.height = height;
LOG(("size %li * %li, bpp %i, rowbytes %zu", (unsigned long)width,
- (unsigned long)height, bit_depth, c->data.png.rowbytes));
+ (unsigned long)height, bit_depth, c->rowbytes));
}
@@ -205,13 +323,13 @@ static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2};
void row_callback(png_structp png, png_bytep new_row,
png_uint_32 row_num, int pass)
{
- struct content *c = png_get_progressive_ptr(png);
- unsigned long i, j, rowbytes = c->data.png.rowbytes;
+ nspng_content *c = png_get_progressive_ptr(png);
+ unsigned long i, j, rowbytes = c->rowbytes;
unsigned int start, step;
unsigned char *buffer, *row;
/* Give up if there's no bitmap */
- if (c->data.png.bitmap == NULL)
+ if (c->bitmap == NULL)
return;
/* Abort if we've not got any data */
@@ -219,17 +337,17 @@ void row_callback(png_structp png, png_bytep new_row,
return;
/* Get bitmap buffer */
- buffer = bitmap_get_buffer(c->data.png.bitmap);
+ buffer = bitmap_get_buffer(c->bitmap);
if (buffer == NULL) {
/* No buffer, bail out */
longjmp(png_jmpbuf(png), 1);
}
/* Calculate address of row start */
- row = buffer + (c->data.png.rowstride * row_num);
+ row = buffer + (c->rowstride * row_num);
/* Handle interlaced sprites using the Adam7 algorithm */
- if (c->data.png.interlace) {
+ if (c->interlace) {
start = interlace_start[pass];
step = interlace_step[pass];
row_num = interlace_row_start[pass] +
@@ -237,7 +355,7 @@ void row_callback(png_structp png, png_bytep new_row,
/* Copy the data to our current row taking interlacing
* into consideration */
- row = buffer + (c->data.png.rowstride * row_num);
+ row = buffer + (c->rowstride * row_num);
for (j = 0, i = start; i < rowbytes; i += step) {
row[i++] = new_row[j++];
@@ -260,14 +378,15 @@ void end_callback(png_structp png, png_infop info)
bool nspng_convert(struct content *c)
{
+ nspng_content *png = (nspng_content *) c;
const char *data;
unsigned long size;
char title[100];
- assert(c->data.png.png != NULL);
- assert(c->data.png.info != NULL);
+ assert(png->png != NULL);
+ assert(png->info != NULL);
- if (c->data.png.bitmap == NULL) {
+ if (png->bitmap == NULL) {
union content_msg_data msg_data;
msg_data.error = messages_get("PNGError");
@@ -278,7 +397,7 @@ bool nspng_convert(struct content *c)
data = content__get_source_data(c, &size);
- png_destroy_read_struct(&c->data.png.png, &c->data.png.info, 0);
+ png_destroy_read_struct(&png->png, &png->info, 0);
snprintf(title, sizeof(title), messages_get("PNGTitle"),
c->width, c->height, size);
@@ -286,7 +405,7 @@ bool nspng_convert(struct content *c)
c->size += (c->width * c->height * 4);
- c->bitmap = c->data.png.bitmap;
+ c->bitmap = png->bitmap;
bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
bitmap_modified(c->bitmap);
content_set_ready(c);
@@ -299,9 +418,11 @@ bool nspng_convert(struct content *c)
void nspng_destroy(struct content *c)
{
- if (c->data.png.bitmap != NULL) {
- bitmap_destroy(c->data.png.bitmap);
- }
+ nspng_content *png = (nspng_content *) c;
+
+ if (png->bitmap != NULL) {
+ bitmap_destroy(png->bitmap);
+ }
}
@@ -333,28 +454,54 @@ bool nspng_redraw_tiled(struct content *c, int x, int y,
background_colour, flags);
}
-bool nspng_clone(const struct content *old, struct content *new_content)
+nserror nspng_clone(const struct content *old, struct content **newc)
{
+ nspng_content *png;
+ nserror error;
const char *data;
unsigned long size;
+ png = talloc_zero(0, nspng_content);
+ if (png == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &png->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&png->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (nspng_create(new_content, NULL) == false)
- return false;
+ error = nspng_create_png_data(png);
+ if (error != NSERROR_OK) {
+ content_destroy(&png->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&png->base, &size);
if (size > 0) {
- if (nspng_process_data(new_content, data, size) == false)
- return false;
+ if (nspng_process_data(&png->base, data, size) == false) {
+ content_destroy(&png->base);
+ return NSERROR_NOMEM;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (nspng_convert(new_content) == false)
- return false;
+ if (nspng_convert(&png->base) == false) {
+ content_destroy(&png->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) png;
+
+ return NSERROR_OK;
+}
+
+content_type nspng_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif
diff --git a/image/png.h b/image/png.h
index fb9efcfd4..1119b6a43 100644
--- a/image/png.h
+++ b/image/png.h
@@ -24,37 +24,17 @@
#ifdef WITH_PNG
-#include "desktop/plot_style.h"
-
#include <stdbool.h>
-#include <png.h>
-
-struct content;
-struct bitmap;
-struct http_parameter;
-struct rect;
-
-struct content_png_data {
- png_structp png;
- png_infop info;
- int interlace;
- struct bitmap *bitmap; /**< Created NetSurf bitmap */
- size_t rowstride, bpp; /**< Bitmap rowstride and bpp */
- size_t rowbytes; /**< Number of bytes per row */
-};
-
-bool nspng_create(struct content *c, const struct http_parameter *params);
-bool nspng_process_data(struct content *c, const char *data, unsigned int size);
-bool nspng_convert(struct content *c);
-void nspng_destroy(struct content *c);
-bool nspng_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool nspng_redraw_tiled(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour,
- bool repeat_x, bool repeat_y);
-bool nspng_clone(const struct content *old, struct content *new_content);
+
+#include "utils/errors.h"
+
+nserror nspng_init(void);
+void nspng_fini(void);
+
+#else
+
+#define nspng_init() NSERROR_OK
+#define nspng_fini() ((void) 0)
#endif
diff --git a/image/rsvg.c b/image/rsvg.c
index cf3d5cea6..26370de57 100644
--- a/image/rsvg.c
+++ b/image/rsvg.c
@@ -32,6 +32,7 @@
#include <stdbool.h>
#include <assert.h>
+#include <string.h>
#include <sys/types.h>
#include <librsvg/rsvg.h>
@@ -46,33 +47,151 @@
#include "utils/messages.h"
#include "utils/talloc.h"
+typedef struct rsvg_content {
+ struct content base;
+
+ RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
+ cairo_surface_t *cs; /**< The surface built inside a nsbitmap */
+ cairo_t *ct; /**< Cairo drawing context */
+ struct bitmap *bitmap; /**< Created NetSurf bitmap */
+} rsvg_content;
+
+static nserror rsvg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror rsvg_create_svg_data(rsvg_content *c);
+static bool rsvg_process_data(struct content *c, const char *data,
+ unsigned int size);
+static bool rsvg_convert(struct content *c);
+static void rsvg_destroy(struct content *c);
+static bool rsvg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror rsvg_clone(const struct content *old, struct content **newc);
+static content_type rsvg_content_type(lwc_string *mime_type);
+
static inline void rsvg_argb_to_abgr(uint8_t *pixels,
int width, int height, size_t rowstride);
-bool rsvg_create(struct content *c, const struct http_parameter *params)
+static const content_handler rsvg_content_handler = {
+ rsvg_create,
+ rsvg_process_data,
+ rsvg_convert,
+ NULL,
+ rsvg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ rsvg_redraw,
+ NULL,
+ NULL,
+ NULL,
+ rsvg_clone,
+ NULL,
+ rsvg_content_type,
+ false
+};
+
+static const char *rsvg_types[] = {
+ "image/svg",
+ "image/svg+xml"
+};
+
+static lwc_string *rsvg_mime_types[NOF_ELEMENTS(rsvg_types)];
+
+nserror nsrsvg_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(rsvg_mime_types); i++) {
+ lerror = lwc_intern_string(rsvg_types[i],
+ strlen(rsvg_types[i]),
+ &rsvg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(rsvg_mime_types[i],
+ &rsvg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ nsrsvg_fini();
+
+ return error;
+}
+
+void nsrsvg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(rsvg_mime_types); i++) {
+ if (rsvg_mime_types[i] != NULL)
+ lwc_string_unref(rsvg_mime_types[i]);
+ }
+}
+
+nserror rsvg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ rsvg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, rsvg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&svg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ error = rsvg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ *c = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+nserror rsvg_create_svg_data(rsvg_content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
union content_msg_data msg_data;
- d->rsvgh = NULL;
- d->cs = NULL;
- d->ct = NULL;
- d->bitmap = NULL;
+ c->rsvgh = NULL;
+ c->cs = NULL;
+ c->ct = NULL;
+ c->bitmap = NULL;
- if ((d->rsvgh = rsvg_handle_new()) == NULL) {
+ if ((c->rsvgh = rsvg_handle_new()) == NULL) {
LOG(("rsvg_handle_new() returned NULL."));
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
- return true;
+ return NSERROR_OK;
}
bool rsvg_process_data(struct content *c, const char *data,
unsigned int size)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
GError *err = NULL;
@@ -118,7 +237,7 @@ static inline void rsvg_argb_to_abgr(uint8_t *pixels,
bool rsvg_convert(struct content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
union content_msg_data msg_data;
RsvgDimensionData rsvgsize;
GError *err = NULL;
@@ -191,7 +310,7 @@ bool rsvg_redraw(struct content *c, int x, int y,
void rsvg_destroy(struct content *c)
{
- struct content_rsvg_data *d = &c->data.rsvg;
+ rsvg_content *d = (rsvg_content *) c;
if (d->bitmap != NULL) bitmap_destroy(d->bitmap);
if (d->rsvgh != NULL) rsvg_handle_free(d->rsvgh);
@@ -201,28 +320,54 @@ void rsvg_destroy(struct content *c)
return;
}
-bool rsvg_clone(const struct content *old, struct content *new_content)
+nserror rsvg_clone(const struct content *old, struct content **newc)
{
+ rsvg_content *svg;
+ nserror error;
const char *data;
unsigned long size;
+ svg = talloc_zero(0, rsvg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &svg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
+
/* Simply replay create/process/convert */
- if (rsvg_create(new_content, NULL) == false)
- return false;
+ error = rsvg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
- data = content__get_source_data(new_content, &size);
+ data = content__get_source_data(&svg->base, &size);
if (size > 0) {
- if (rsvg_process_data(new_content, data, size) == false)
- return false;
+ if (rsvg_process_data(&svg->base, data, size) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_NOMEM;
+ }
}
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (rsvg_convert(new_content) == false)
- return false;
+ if (rsvg_convert(&svg->base) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+content_type rsvg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif /* WITH_RSVG */
diff --git a/image/rsvg.h b/image/rsvg.h
index 90b4ba8f3..4d4e65fea 100644
--- a/image/rsvg.h
+++ b/image/rsvg.h
@@ -27,30 +27,16 @@
#ifdef WITH_RSVG
#include <stdbool.h>
-#include <librsvg/rsvg.h>
-#include <cairo.h>
-#include "desktop/plot_style.h"
-#include "image/bitmap.h"
-
-struct content;
-struct http_parameter;
-struct rect;
-
-struct content_rsvg_data {
- RsvgHandle *rsvgh; /**< Context handle for RSVG renderer */
- cairo_surface_t *cs; /**< The surface built inside a nsbitmap */
- cairo_t *ct; /**< Cairo drawing context */
- struct bitmap *bitmap; /**< Created NetSurf bitmap */
-};
-
-bool rsvg_create(struct content *c, const struct http_parameter *params);
-bool rsvg_process_data(struct content *c, const char *data, unsigned int size);
-bool rsvg_convert(struct content *c);
-void rsvg_destroy(struct content *c);
-bool rsvg_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool rsvg_clone(const struct content *old, struct content *new_content);
+
+#include "utils/errors.h"
+
+nserror nsrsvg_init(void);
+void nsrsvg_fini(void);
+
+#else
+
+#define nsrsvg_init() NSERROR_OK
+#define nsrsvg_fini() ((void) 0)
#endif /* WITH_RSVG */
diff --git a/image/svg.c b/image/svg.c
index d77c8e03a..781a9af48 100644
--- a/image/svg.c
+++ b/image/svg.c
@@ -33,29 +33,145 @@
#include "desktop/plotters.h"
#include "image/svg.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct svg_content {
+ struct content base;
+
+ struct svgtiny_diagram *diagram;
+ bool done_parse;
+} svg_content;
+
+static nserror svg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static nserror svg_create_svg_data(svg_content *c);
+static bool svg_convert(struct content *c);
+static void svg_destroy(struct content *c);
+static void svg_reformat(struct content *c, int width, int height);
+static bool svg_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror svg_clone(const struct content *old, struct content **newc);
+static content_type svg_content_type(lwc_string *mime_type);
+
+static const content_handler svg_content_handler = {
+ svg_create,
+ NULL,
+ svg_convert,
+ svg_reformat,
+ svg_destroy,
+ NULL,
+ NULL,
+ NULL,
+ svg_redraw,
+ NULL,
+ NULL,
+ NULL,
+ svg_clone,
+ NULL,
+ svg_content_type,
+ false
+};
+
+static const char *svg_types[] = {
+ "image/svg",
+ "image/svg+xml"
+};
+
+static lwc_string *svg_mime_types[NOF_ELEMENTS(svg_types)];
+
+nserror svg_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(svg_mime_types); i++) {
+ lerror = lwc_intern_string(svg_types[i],
+ strlen(svg_types[i]),
+ &svg_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(svg_mime_types[i],
+ &svg_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ svg_fini();
+
+ return error;
+}
+
+void svg_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(svg_mime_types); i++) {
+ if (svg_mime_types[i] != NULL)
+ lwc_string_unref(svg_mime_types[i]);
+ }
+}
/**
* Create a CONTENT_SVG.
*/
-bool svg_create(struct content *c, const struct http_parameter *params)
+nserror svg_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ svg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, svg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&svg->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ error = svg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ talloc_free(svg);
+ return error;
+ }
+
+ *c = (struct content *) svg;
+
+ return NSERROR_OK;
+}
+
+nserror svg_create_svg_data(svg_content *c)
{
union content_msg_data msg_data;
- c->data.svg.diagram = svgtiny_create();
- if (!c->data.svg.diagram)
+ c->diagram = svgtiny_create();
+ if (c->diagram == NULL)
goto no_memory;
- c->data.svg.done_parse = false;
+ c->done_parse = false;
- return true;
+ return NSERROR_OK;
no_memory:
msg_data.error = messages_get("NoMemory");
- content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
- return false;
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
@@ -84,22 +200,23 @@ bool svg_convert(struct content *c)
void svg_reformat(struct content *c, int width, int height)
{
+ svg_content *svg = (svg_content *) c;
const char *source_data;
unsigned long source_size;
- assert(c->data.svg.diagram);
+ assert(svg->diagram);
- if (c->data.svg.done_parse == false) {
+ if (svg->done_parse == false) {
source_data = content__get_source_data(c, &source_size);
- svgtiny_parse(c->data.svg.diagram, source_data, source_size,
+ svgtiny_parse(svg->diagram, source_data, source_size,
content__get_url(c), width, height);
- c->data.svg.done_parse = true;
+ svg->done_parse = true;
}
- c->width = c->data.svg.diagram->width;
- c->height = c->data.svg.diagram->height;
+ c->width = svg->diagram->width;
+ c->height = svg->diagram->height;
}
@@ -111,8 +228,9 @@ bool svg_redraw(struct content *c, int x, int y,
int width, int height, const struct rect *clip,
float scale, colour background_colour)
{
+ svg_content *svg = (svg_content *) c;
float transform[6];
- struct svgtiny_diagram *diagram = c->data.svg.diagram;
+ struct svgtiny_diagram *diagram = svg->diagram;
bool ok;
int px, py;
unsigned int i;
@@ -173,25 +291,51 @@ bool svg_redraw(struct content *c, int x, int y,
void svg_destroy(struct content *c)
{
- if (c->data.svg.diagram)
- svgtiny_free(c->data.svg.diagram);
+ svg_content *svg = (svg_content *) c;
+
+ if (svg->diagram != NULL)
+ svgtiny_free(svg->diagram);
}
-bool svg_clone(const struct content *old, struct content *new_content)
+nserror svg_clone(const struct content *old, struct content **newc)
{
+ svg_content *svg;
+ nserror error;
+
+ svg = talloc_zero(0, svg_content);
+ if (svg == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &svg->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
+
/* Simply replay create/convert */
- if (svg_create(new_content, NULL) == false)
- return false;
+ error = svg_create_svg_data(svg);
+ if (error != NSERROR_OK) {
+ content_destroy(&svg->base);
+ return error;
+ }
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (svg_convert(new_content) == false)
- return false;
+ if (svg_convert(&svg->base) == false) {
+ content_destroy(&svg->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) svg;
+
+ return NSERROR_OK;
}
+content_type svg_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
+}
#endif /* WITH_NS_SVG */
diff --git a/image/svg.h b/image/svg.h
index d836cb310..0e8ad8559 100644
--- a/image/svg.h
+++ b/image/svg.h
@@ -23,25 +23,22 @@
#ifndef _NETSURF_IMAGE_SVG_H_
#define _NETSURF_IMAGE_SVG_H_
+#include "utils/config.h"
+
+#ifdef WITH_NS_SVG
+
#include <stdbool.h>
-struct content;
-struct http_parameter;
-struct svgtiny_diagram;
-struct rect;
-
-struct content_svg_data {
- struct svgtiny_diagram *diagram;
- bool done_parse;
-};
-
-bool svg_create(struct content *c, const struct http_parameter *params);
-bool svg_convert(struct content *c);
-void svg_destroy(struct content *c);
-void svg_reformat(struct content *c, int width, int height);
-bool svg_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool svg_clone(const struct content *old, struct content *new_content);
+#include "utils/errors.h"
+
+nserror svg_init(void);
+void svg_fini(void);
+
+#else
+
+#define svg_init() NSERROR_OK
+#define svg_fini() ((void) 0)
+
+#endif
#endif
diff --git a/image/webp.c b/image/webp.c
index 439bdfc9b..a76c0918c 100644
--- a/image/webp.c
+++ b/image/webp.c
@@ -33,8 +33,114 @@
#include "content/content_protected.h"
#include "utils/log.h"
#include "utils/messages.h"
+#include "utils/talloc.h"
#include "utils/utils.h"
+typedef struct webp_content
+{
+ struct content base;
+} webp_content;
+
+static nserror webp_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c);
+static bool webp_convert(struct content *c);
+static void webp_destroy(struct content *c);
+static bool webp_redraw(struct content *c, int x, int y,
+ int width, int height, const struct rect *clip,
+ float scale, colour background_colour);
+static nserror webp_clone(const struct content *old, struct content **newc);
+static content_type webp_content_type(lwc_string *mime_type);
+
+static const content_handler webp_content_handler = {
+ webp_create,
+ NULL,
+ webp_convert,
+ NULL,
+ webp_destroy,
+ NULL,
+ NULL,
+ NULL,
+ webp_redraw,
+ NULL,
+ NULL,
+ NULL,
+ webp_clone,
+ NULL,
+ webp_content_type,
+ false
+};
+
+static const char *webp_types[] = {
+ "image/webp"
+};
+
+static lwc_string *webp_mime_types[NOF_ELEMENTS(webp_types)];
+
+nserror webp_init(void)
+{
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
+
+ for (i = 0; i < NOF_ELEMENTS(webp_mime_types); i++) {
+ lerror = lwc_intern_string(webp_types[i],
+ strlen(webp_types[i]),
+ &webp_mime_types[i]);
+ if (lerror != lwc_error_ok) {
+ error = NSERROR_NOMEM;
+ goto error;
+ }
+
+ error = content_factory_register_handler(webp_mime_types[i],
+ &webp_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
+ }
+
+ return NSERROR_OK;
+
+error:
+ webp_fini();
+
+ return error;
+}
+
+void webp_fini(void)
+{
+ uint32_t i;
+
+ for (i = 0; i < NOF_ELEMENTS(webp_mime_types); i++) {
+ if (webp_mime_types[i] != NULL)
+ lwc_string_unref(webp_mime_types[i]);
+ }
+}
+
+nserror webp_create(const content_handler *handler,
+ lwc_string *imime_type, const http_parameter *params,
+ llcache_handle *llcache, const char *fallback_charset,
+ bool quirks, struct content **c)
+{
+ webp_content *webp;
+ nserror error;
+
+ webp = talloc_zero(0, webp_content);
+ if (webp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__init(&webp->base, handler, imime_type, params,
+ llcache, fallback_charset, quirks);
+ if (error != NSERROR_OK) {
+ talloc_free(webp);
+ return error;
+ }
+
+ *c = (struct content *) webp;
+
+ return NSERROR_OK;
+}
+
/**
* Convert a CONTENT_WEBP for display.
*
@@ -124,16 +230,38 @@ bool webp_redraw(struct content *c, int x, int y,
}
-bool webp_clone(const struct content *old, struct content *new_content)
+nserror webp_clone(const struct content *old, struct content **newc)
{
+ webp_content *webp;
+ nserror error;
+
+ webp = talloc_zero(0, webp_content);
+ if (webp == NULL)
+ return NSERROR_NOMEM;
+
+ error = content__clone(old, &webp->base);
+ if (error != NSERROR_OK) {
+ content_destroy(&webp->base);
+ return error;
+ }
+
/* Simply replay convert */
if (old->status == CONTENT_STATUS_READY ||
old->status == CONTENT_STATUS_DONE) {
- if (webp_convert(new_content) == false)
- return false;
+ if (webp_convert(&webp->base) == false) {
+ content_destroy(&webp->base);
+ return NSERROR_CLONE_FAILED;
+ }
}
- return true;
+ *newc = (struct content *) webp;
+
+ return NSERROR_OK;
+}
+
+content_type webp_content_type(lwc_string *mime_type)
+{
+ return CONTENT_IMAGE;
}
#endif
diff --git a/image/webp.h b/image/webp.h
index a89713ac3..3d976d13e 100644
--- a/image/webp.h
+++ b/image/webp.h
@@ -28,19 +28,15 @@
#include <stdbool.h>
-struct content;
-struct rect;
-
-struct content_webp_data {
-/* empty */
-};
-
-bool webp_convert(struct content *c);
-void webp_destroy(struct content *c);
-bool webp_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour);
-bool webp_clone(const struct content *old, struct content *new_content);
+#include "utils/errors.h"
+
+nserror webp_init(void);
+void webp_fini(void);
+
+#else
+
+#define webp_init() NSERROR_OK
+#define webp_fini() ((void) 0)
#endif /* WITH_WEBP */