summaryrefslogtreecommitdiff
path: root/image/gif.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@netsurf-browser.org>2011-05-08 19:54:35 +0000
committerVincent Sanders <vince@netsurf-browser.org>2011-05-08 19:54:35 +0000
commit8be1e85e919d5b6c12979dca0d57f7cd67d2cb79 (patch)
treec0887e7c26229de5f543b03eb9bdb8d5561e9787 /image/gif.c
parent8f6c343309dd32c3193622961df5e2f785915665 (diff)
downloadnetsurf-8be1e85e919d5b6c12979dca0d57f7cd67d2cb79.tar.gz
netsurf-8be1e85e919d5b6c12979dca0d57f7cd67d2cb79.tar.bz2
consolidate content redraw
more cleanups ready for image content refactor svn path=/trunk/netsurf/; revision=12317
Diffstat (limited to 'image/gif.c')
-rw-r--r--image/gif.c448
1 files changed, 206 insertions, 242 deletions
diff --git a/image/gif.c b/image/gif.c
index 20a67424e..798097bf5 100644
--- a/image/gif.c
+++ b/image/gif.c
@@ -56,32 +56,28 @@ typedef struct nsgif_content {
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 const char *nsgif_types[] = {
+ "image/gif"
+};
-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);
+static lwc_string *nsgif_mime_types[NOF_ELEMENTS(nsgif_types)];
+
+/**
+ * Callback for libnsgif; forwards the call to bitmap_create()
+ *
+ * \param width width of image in pixels
+ * \param height width of image in pixels
+ * \return an opaque struct bitmap, or NULL on memory exhaustion
+ */
+static void *nsgif_bitmap_create(int width, int height)
+{
+ return bitmap_create(width, height, BITMAP_NEW);
+}
/* The Bitmap callbacks function table;
* necessary for interaction with nsgiflib.
*/
-gif_bitmap_callback_vt gif_bitmap_callbacks = {
+static gif_bitmap_callback_vt gif_bitmap_callbacks = {
.bitmap_create = nsgif_bitmap_create,
.bitmap_destroy = bitmap_destroy,
.bitmap_get_buffer = bitmap_get_buffer,
@@ -90,71 +86,24 @@ 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"
-};
-
-static lwc_string *nsgif_mime_types[NOF_ELEMENTS(nsgif_types)];
-
-nserror nsgif_init(void)
+static nserror nsgif_create_gif_data(nsgif_content *c)
{
- 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;
- }
+ union content_msg_data msg_data;
- error = content_factory_register_handler(nsgif_mime_types[i],
- &nsgif_content_handler);
- if (error != NSERROR_OK)
- goto error;
+ /* Initialise our data structure */
+ c->gif = calloc(sizeof(gif_animation), 1);
+ if (c->gif == NULL) {
+ msg_data.error = messages_get("NoMemory");
+ content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
+ return NSERROR_NOMEM;
}
-
+ gif_create(c->gif, &gif_bitmap_callbacks);
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,
+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)
@@ -184,23 +133,122 @@ nserror nsgif_create(const content_handler *handler,
return NSERROR_OK;
}
-nserror nsgif_create_gif_data(nsgif_content *c)
+/**
+ * Performs any necessary animation.
+ *
+ * \param p The content to animate
+*/
+static void nsgif_animate(void *p)
{
- union content_msg_data msg_data;
+ nsgif_content *gif = p;
+ union content_msg_data data;
+ int delay;
+ int f;
- /* Initialise our data structure */
- c->gif = calloc(sizeof(gif_animation), 1);
- if (c->gif == NULL) {
- msg_data.error = messages_get("NoMemory");
- content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
- return NSERROR_NOMEM;
+ /* Advance by a frame, updating the loop count accordingly */
+ 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->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;
+ }
+ }
}
- gif_create(c->gif, &gif_bitmap_callbacks);
- return NSERROR_OK;
+
+ /* Continue animating if we should */
+ 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, gif);
+ }
+
+ if ((!option_animate_images) ||
+ (!gif->gif->frames[gif->current_frame].display))
+ return;
+
+ /* area within gif to redraw */
+ 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 (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->gif->frames[f - 1].redraw_x)) {
+ data.redraw.width += data.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->gif->frames[f - 1].redraw_y)) {
+ data.redraw.height += (data.redraw.y -
+ gif->gif->frames[f - 1].redraw_y);
+ data.redraw.y =
+ gif->gif->frames[f - 1].redraw_y;
+ }
+ 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->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->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->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->gif->width;
+ data.redraw.height = gif->gif->height;
+ }
+ }
+
+ /* other data */
+ data.redraw.object = (struct content *) gif;
+ data.redraw.object_x = 0;
+ data.redraw.object_y = 0;
+ data.redraw.object_width = gif->base.width;
+ data.redraw.object_height = gif->base.height;
+
+ content_broadcast(&gif->base, CONTENT_MSG_REDRAW, data);
}
+static void nsgif_invalidate(void *bitmap, void *private_word)
+{
+ struct gif_animation *gif = (struct gif_animation *)private_word;
+
+ gif->decoded_frame = -1;
+}
-bool nsgif_convert(struct content *c)
+static bool nsgif_convert(struct content *c)
{
nsgif_content *gif = (nsgif_content *) c;
int res;
@@ -265,31 +313,32 @@ bool nsgif_convert(struct content *c)
return true;
}
-void nsgif_invalidate(void *bitmap, void *private_word)
-{
- struct gif_animation *gif = (struct gif_animation *)private_word;
-
- gif->decoded_frame = -1;
-}
-bool nsgif_redraw(struct content *c, int x, int y,
- int width, int height, const struct rect *clip,
- float scale, colour background_colour)
+/**
+ * Updates the GIF bitmap to display the current frame
+ *
+ * \param c the content to update
+ */
+static 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;
- if (gif->current_frame != gif->gif->decoded_frame)
- if (nsgif_get_frame(c) != GIF_OK)
- return false;
- c->bitmap = gif->gif->frame_image;
- if ((width == -1) && (height == -1))
- return true;
- return plot.bitmap(x, y, width, height, c->bitmap,
- background_colour, BITMAPF_NONE);
-}
+ current_frame = gif->current_frame;
+ if (!option_animate_images)
+ current_frame = 0;
+ if (current_frame < gif->gif->decoded_frame)
+ previous_frame = 0;
+ else
+ previous_frame = gif->gif->decoded_frame + 1;
+ for (frame = previous_frame; frame <= current_frame; frame++)
+ res = gif_decode_frame(gif->gif, frame);
+ return res;
+}
-bool nsgif_redraw_tiled(struct content *c, int x, int y,
+static bool nsgif_redraw(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)
@@ -302,6 +351,9 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
return false;
c->bitmap = gif->gif->frame_image;
+
+ if ((width == -1) && (height == -1))
+ return true;
if (repeat_x)
flags |= BITMAPF_REPEAT_X;
@@ -312,7 +364,7 @@ bool nsgif_redraw_tiled(struct content *c, int x, int y,
}
-void nsgif_destroy(struct content *c)
+static void nsgif_destroy(struct content *c)
{
nsgif_content *gif = (nsgif_content *) c;
@@ -323,7 +375,7 @@ void nsgif_destroy(struct content *c)
}
-nserror nsgif_clone(const struct content *old, struct content **newc)
+static nserror nsgif_clone(const struct content *old, struct content **newc)
{
nsgif_content *gif;
nserror error;
@@ -358,155 +410,67 @@ nserror nsgif_clone(const struct content *old, struct content **newc)
return NSERROR_OK;
}
-content_type nsgif_content_type(lwc_string *mime_type)
+static content_type nsgif_content_type(lwc_string *mime_type)
{
return CONTENT_IMAGE;
}
-/**
- * Updates the GIF bitmap to display the current frame
- *
- * \param c the content to update
- */
-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 = gif->current_frame;
- if (!option_animate_images)
- current_frame = 0;
- if (current_frame < gif->gif->decoded_frame)
- previous_frame = 0;
- else
- previous_frame = gif->gif->decoded_frame + 1;
- for (frame = previous_frame; frame <= current_frame; frame++)
- res = gif_decode_frame(gif->gif, frame);
-
- return res;
-}
+static const content_handler nsgif_content_handler = {
+ nsgif_create,
+ NULL,
+ nsgif_convert,
+ NULL,
+ nsgif_destroy,
+ NULL,
+ NULL,
+ NULL,
+ nsgif_redraw,
+ NULL,
+ NULL,
+ nsgif_clone,
+ NULL,
+ nsgif_content_type,
+ false
+};
-/**
- * Performs any necessary animation.
- *
- * \param p The content to animate
-*/
-void nsgif_animate(void *p)
+nserror nsgif_init(void)
{
- nsgif_content *gif = p;
- union content_msg_data data;
- int delay;
- int f;
-
- /* Advance by a frame, updating the loop count accordingly */
- gif->current_frame++;
- if (gif->current_frame == (int)gif->gif->frame_count_partial) {
- gif->current_frame = 0;
+ uint32_t i;
+ lwc_error lerror;
+ nserror error;
- /* A loop count of 0 has a special meaning of infinite */
- 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;
- }
+ 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;
}
- }
- /* Continue animating if we should */
- 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, gif);
+ error = content_factory_register_handler(nsgif_mime_types[i],
+ &nsgif_content_handler);
+ if (error != NSERROR_OK)
+ goto error;
}
- if ((!option_animate_images) ||
- (!gif->gif->frames[gif->current_frame].display))
- return;
-
- /* area within gif to redraw */
- 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 (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->gif->frames[f - 1].redraw_x)) {
- data.redraw.width += data.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->gif->frames[f - 1].redraw_y)) {
- data.redraw.height += (data.redraw.y -
- gif->gif->frames[f - 1].redraw_y);
- data.redraw.y =
- gif->gif->frames[f - 1].redraw_y;
- }
- 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->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->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->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->gif->width;
- data.redraw.height = gif->gif->height;
- }
- }
+ return NSERROR_OK;
- /* other data */
- data.redraw.object = (struct content *) gif;
- data.redraw.object_x = 0;
- data.redraw.object_y = 0;
- data.redraw.object_width = gif->base.width;
- data.redraw.object_height = gif->base.height;
+error:
+ nsgif_fini();
- content_broadcast(&gif->base, CONTENT_MSG_REDRAW, data);
+ return error;
}
-
-/**
- * Callback for libnsgif; forwards the call to bitmap_create()
- *
- * \param width width of image in pixels
- * \param height width of image in pixels
- * \return an opaque struct bitmap, or NULL on memory exhaustion
- */
-void *nsgif_bitmap_create(int width, int height)
+void nsgif_fini(void)
{
- return bitmap_create(width, height, BITMAP_NEW);
+ 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]);
+ }
}
#endif