From 8be1e85e919d5b6c12979dca0d57f7cd67d2cb79 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 8 May 2011 19:54:35 +0000 Subject: consolidate content redraw more cleanups ready for image content refactor svn path=/trunk/netsurf/; revision=12317 --- image/gif.c | 448 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 206 insertions(+), 242 deletions(-) (limited to 'image/gif.c') 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 -- cgit v1.2.3