Gitweb links:

...log 
http://git.netsurf-browser.org/netsurf.git/shortlog/0f547ed94026145f48602e72d5c9bbafbbb72b10
...commit 
http://git.netsurf-browser.org/netsurf.git/commit/0f547ed94026145f48602e72d5c9bbafbbb72b10
...tree 
http://git.netsurf-browser.org/netsurf.git/tree/0f547ed94026145f48602e72d5c9bbafbbb72b10

The branch, tlsa/gif-api has been created
        at  0f547ed94026145f48602e72d5c9bbafbbb72b10 (commit)

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/netsurf.git/commit/?id=0f547ed94026145f48602e72d5c9bbafbbb72b10
commit 0f547ed94026145f48602e72d5c9bbafbbb72b10
Author: Michael Drake <t...@netsurf-browser.org>
Commit: Michael Drake <t...@netsurf-browser.org>

    WIP: GIF: Update to new libnsgif API.

diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c
index e2a0ca5..d7dedef 100644
--- a/content/handlers/image/gif.c
+++ b/content/handlers/image/gif.c
@@ -34,7 +34,8 @@
 #include <string.h>
 #include <stdbool.h>
 #include <stdlib.h>
-#include <libnsgif.h>
+
+#include <nsgif.h>
 
 #include "utils/utils.h"
 #include "utils/messages.h"
@@ -51,13 +52,12 @@
 #include "image/image.h"
 #include "image/gif.h"
 
-typedef struct nsgif_content {
+typedef struct gif_content {
        struct content base;
 
-       struct gif_animation *gif; /**< GIF animation data */
-       int current_frame;   /**< current frame to display [0...(max-1)] */
-} nsgif_content;
-
+       nsgif *gif; /**< GIF animation data */
+       uint32_t current_frame;   /**< current frame to display [0...(max-1)] */
+} gif_content;
 
 /**
  * Callback for libnsgif; forwards the call to bitmap_create()
@@ -66,44 +66,41 @@ typedef struct nsgif_content {
  * \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)
+static void *gif_bitmap_create(int width, int height)
 {
        return guit->bitmap->create(width, height, BITMAP_NEW);
 }
 
-
-static nserror nsgif_create_gif_data(nsgif_content *c)
+static nserror gif_create_gif_data(gif_content *c)
 {
-       gif_bitmap_callback_vt gif_bitmap_callbacks = {
-               .bitmap_create = nsgif_bitmap_create,
-               .bitmap_destroy = guit->bitmap->destroy,
-               .bitmap_get_buffer = guit->bitmap->get_buffer,
-               .bitmap_set_opaque = guit->bitmap->set_opaque,
-               .bitmap_test_opaque = guit->bitmap->test_opaque,
-               .bitmap_modified = guit->bitmap->modified
+       nsgif_bitmap_cb_vt gif_bitmap_callbacks = {
+               .create = gif_bitmap_create,
+               .destroy = guit->bitmap->destroy,
+               .get_buffer = guit->bitmap->get_buffer,
+               .set_opaque = guit->bitmap->set_opaque,
+               .test_opaque = guit->bitmap->test_opaque,
+               .modified = guit->bitmap->modified
        };
 
        /* Initialise our data structure */
-       c->gif = calloc(sizeof(gif_animation), 1);
+       c->gif = calloc(sizeof(nsgif), 1);
        if (c->gif == NULL) {
                content_broadcast_error(&c->base, NSERROR_NOMEM, NULL);
                return NSERROR_NOMEM;
        }
-       gif_create(c->gif, &gif_bitmap_callbacks);
+       nsgif_create(c->gif, &gif_bitmap_callbacks);
        return NSERROR_OK;
 }
 
-
-
-static nserror nsgif_create(const content_handler *handler, 
-               lwc_string *imime_type, const struct http_parameter *params, 
+static nserror gif_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;
+       gif_content *result;
        nserror error;
 
-       result = calloc(1, sizeof(nsgif_content));
+       result = calloc(1, sizeof(gif_content));
        if (result == NULL)
                return NSERROR_NOMEM;
 
@@ -114,7 +111,7 @@ static nserror nsgif_create(const content_handler *handler,
                return error;
        }
 
-       error = nsgif_create_gif_data(result);
+       error = gif_create_gif_data(result);
        if (error != NSERROR_OK) {
                free(result);
                return error;
@@ -126,99 +123,83 @@ static nserror nsgif_create(const content_handler 
*handler,
 }
 
 /**
+ * Scheduler callback. Performs any necessary animation.
+ *
+ * \param p  The content to animate
+*/
+static void gif_animate_cb(void *p);
+
+static inline nserror gif__nsgif_error_to_ns(nsgif_result gif_res)
+{
+       nserror err;
+
+       switch (gif_res) {
+       case NSGIF_OK:
+               err = NSERROR_OK;
+               break;
+       case NSGIF_INSUFFICIENT_MEMORY:
+               err = NSERROR_NOMEM;
+               break;
+       default:
+               err = NSERROR_GIF_ERROR;
+               break;
+       }
+
+       return err;
+}
+
+/**
  * Performs any necessary animation.
  *
  * \param p  The content to animate
 */
-static void nsgif_animate(void *p)
+static nserror gif__animate(gif_content *gif, bool redraw)
 {
-       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;
-
-               /* 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;
-                       }
-               }
+       nsgif_result gif_res;
+       nsgif_rect rect;
+       uint32_t delay;
+       uint32_t f;
+
+       gif_res = nsgif_frame_prepare(gif->gif, &rect, &delay, &f);
+       if (gif_res != NSGIF_OK) {
+               return gif__nsgif_error_to_ns(gif_res);
        }
 
+       gif->current_frame = f;
+
        /* Continue animating if we should */
-       if (gif->gif->loop_count >= 0) {
-               delay = gif->gif->frames[gif->current_frame].frame_delay;
-               if (delay <= 1) {
-                       /* Assuming too fast to be intended, set default. */
-                       delay = 10;
-               }
-               guit->misc->schedule(delay * 10, nsgif_animate, gif);
+       if (nsoption_bool(animate_images) && delay != NSGIF_INFINITE) {
+               guit->misc->schedule(delay * 10, gif_animate_cb, gif);
        }
 
-       if ((!nsoption_bool(animate_images)) ||
-           (!gif->gif->frames[gif->current_frame].display)) {
-               return;
-       }
+       if (redraw) {
+               union content_msg_data data;
 
-       /* 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) {
-               /* previous frame needed clearing: expand the redraw area to
-                * cover it */
-               if (gif->gif->frames[f - 1].redraw_required) {
-                       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;
-               }
+               /* area within gif to redraw */
+               data.redraw.x = rect.x0;
+               data.redraw.y = rect.y0;
+               data.redraw.width  = rect.x1 - rect.x0;
+               data.redraw.height = rect.y1 - rect.y0;
+
+               content_broadcast(&gif->base, CONTENT_MSG_REDRAW, &data);
        }
 
-       content_broadcast(&gif->base, CONTENT_MSG_REDRAW, &data);
+       return NSERROR_OK;
 }
 
-static bool nsgif_convert(struct content *c)
+static void gif_animate_cb(void *p)
 {
-       nsgif_content *gif = (nsgif_content *) c;
-       int res;
+       gif_content *gif = p;
+
+       gif__animate(gif, true);
+}
+
+static bool gif_convert(struct content *c)
+{
+       gif_content *gif = (gif_content *) c;
        const uint8_t *data;
+       nsgif_result res;
+       nserror err;
        size_t size;
        char *title;
 
@@ -227,24 +208,14 @@ static bool nsgif_convert(struct content *c)
 
        /* Initialise the GIF */
        do {
-               res = gif_initialise(gif->gif, size, (unsigned char *) data);
-               if (res != GIF_OK && res != GIF_WORKING && 
-                               res != GIF_INSUFFICIENT_FRAME_DATA) {
-                       nserror error = NSERROR_UNKNOWN;
-                       switch (res) {
-                       case GIF_FRAME_DATA_ERROR:
-                       case GIF_INSUFFICIENT_DATA:
-                       case GIF_DATA_ERROR:
-                               error = NSERROR_GIF_ERROR;
-                               break;
-                       case GIF_INSUFFICIENT_MEMORY:
-                               error = NSERROR_NOMEM;
-                               break;
-                       }
-                       content_broadcast_error(c, error, NULL);
+               res = nsgif_data_scan(gif->gif, size, data);
+               if (res != NSGIF_OK && res != NSGIF_WORKING &&
+                               res != NSGIF_INSUFFICIENT_FRAME_DATA) {
+                       err = gif__nsgif_error_to_ns(res);
+                       content_broadcast_error(c, err, NULL);
                        return false;
                }
-       } while (res != GIF_OK && res != GIF_INSUFFICIENT_FRAME_DATA);
+       } while (res != NSGIF_OK && res != NSGIF_INSUFFICIENT_FRAME_DATA);
 
        /* Abort on bad GIFs */
        if ((gif->gif->frame_count_partial == 0) || (gif->gif->width == 0) ||
@@ -267,12 +238,11 @@ static bool nsgif_convert(struct content *c)
                free(title);
        }
 
-       /* Schedule the animation if we have one */
-       gif->current_frame = 0;
-       if (gif->gif->frame_count_partial > 1)
-               guit->misc->schedule(gif->gif->frames[0].frame_delay * 10,
-                                       nsgif_animate,
-                                       c);
+       err = gif__animate(gif, false);
+       if (err != NSERROR_OK) {
+               content_broadcast_error(c, NSERROR_GIF_ERROR, NULL);
+               return false;
+       }
 
        /* Exit as a success */
        content_set_ready(c);
@@ -283,68 +253,50 @@ static bool nsgif_convert(struct content *c)
        return true;
 }
 
-
 /**
  * Updates the GIF bitmap to display the current frame
  *
  * \param gif The gif context to update.
- * \return GIF_OK on success else apropriate error code.
+ * \return NSGIF_OK on success else apropriate error code.
  */
-static gif_result nsgif_get_frame(nsgif_content *gif)
+static nsgif_result gif_get_frame(gif_content *gif)
 {
-       int previous_frame, current_frame, frame;
-       gif_result res = GIF_OK;
-
-       current_frame = gif->current_frame;
+       uint32_t current_frame = gif->current_frame;
        if (!nsoption_bool(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;
+       return nsgif_frame_decode(gif->gif, current_frame);
 }
 
-static bool nsgif_redraw(struct content *c, struct content_redraw_data *data,
+static bool gif_redraw(struct content *c, struct content_redraw_data *data,
                const struct rect *clip, const struct redraw_context *ctx)
 {
-       nsgif_content *gif = (nsgif_content *) c;
+       gif_content *gif = (gif_content *) c;
 
-       if (gif->current_frame != gif->gif->decoded_frame) {
-               if (nsgif_get_frame(gif) != GIF_OK) {
-                       return false;
-               }
+       if (gif_get_frame(gif) != NSGIF_OK) {
+               return false;
        }
 
        return image_bitmap_plot(gif->gif->frame_image, data, clip, ctx);
 }
 
-
-static void nsgif_destroy(struct content *c)
+static void gif_destroy(struct content *c)
 {
-       nsgif_content *gif = (nsgif_content *) c;
+       gif_content *gif = (gif_content *) c;
 
        /* Free all the associated memory buffers */
-       guit->misc->schedule(-1, nsgif_animate, c);
-       gif_finalise(gif->gif);
+       guit->misc->schedule(-1, gif_animate_cb, c);
+       nsgif_finalise(gif->gif);
        free(gif->gif);
 }
 
-
-static nserror nsgif_clone(const struct content *old, struct content **newc)
+static nserror gif_clone(const struct content *old, struct content **newc)
 {
-       nsgif_content *gif;
+       gif_content *gif;
        nserror error;
 
-       gif = calloc(1, sizeof(nsgif_content));
+       gif = calloc(1, sizeof(gif_content));
        if (gif == NULL)
                return NSERROR_NOMEM;
 
@@ -355,7 +307,7 @@ static nserror nsgif_clone(const struct content *old, 
struct content **newc)
        }
 
        /* Simply replay creation and conversion of content */
-       error = nsgif_create_gif_data(gif);
+       error = gif_create_gif_data(gif);
        if (error != NSERROR_OK) {
                content_destroy(&gif->base);
                return error;
@@ -363,7 +315,7 @@ static nserror nsgif_clone(const struct content *old, 
struct content **newc)
 
        if (old->status == CONTENT_STATUS_READY ||
                        old->status == CONTENT_STATUS_DONE) {
-               if (nsgif_convert(&gif->base) == false) {
+               if (gif_convert(&gif->base) == false) {
                        content_destroy(&gif->base);
                        return NSERROR_CLONE_FAILED;
                }
@@ -374,9 +326,9 @@ static nserror nsgif_clone(const struct content *old, 
struct content **newc)
        return NSERROR_OK;
 }
 
-static void nsgif_add_user(struct content *c)
+static void gif_add_user(struct content *c)
 {
-       nsgif_content *gif = (nsgif_content *) c;
+       gif_content *gif = (gif_content *) c;
 
        /* Ensure this content has already been converted.
         * If it hasn't, the animation will start at the conversion phase 
instead. */
@@ -384,67 +336,63 @@ static void nsgif_add_user(struct content *c)
 
        if (content_count_users(c) == 1) {
                /* First user, and content already converted, so start the 
animation. */
-               if (gif->gif->frame_count_partial > 1) {
-                       guit->misc->schedule(gif->gif->frames[0].frame_delay * 
10,
-                               nsgif_animate, c);
+               if (nsgif_reset(gif->gif) == NSGIF_OK) {
+                       gif__animate(gif, true);
                }
        }
 }
 
-static void nsgif_remove_user(struct content *c)
+static void gif_remove_user(struct content *c)
 {
        if (content_count_users(c) == 1) {
                /* Last user is about to be removed from this content, so stop 
the animation. */
-               guit->misc->schedule(-1, nsgif_animate, c);
+               guit->misc->schedule(-1, gif_animate_cb, c);
        }
 }
 
-static void *nsgif_get_internal(const struct content *c, void *context)
+static void *gif_get_internal(const struct content *c, void *context)
 {
-       nsgif_content *gif = (nsgif_content *) c;
+       gif_content *gif = (gif_content *) c;
 
-       if (gif->current_frame != gif->gif->decoded_frame) {
-               if (nsgif_get_frame(gif) != GIF_OK)
-                       return NULL;
+       if (gif_get_frame(gif) != NSGIF_OK) {
+               return NULL;
        }
 
        return gif->gif->frame_image;
 }
 
-static content_type nsgif_content_type(void)
+static content_type gif_content_type(void)
 {
        return CONTENT_IMAGE;
 }
 
-static bool nsgif_content_is_opaque(struct content *c)
+static bool gif_content_is_opaque(struct content *c)
 {
-       nsgif_content *gif = (nsgif_content *) c;
+       gif_content *gif = (gif_content *) c;
 
-       if (gif->current_frame != gif->gif->decoded_frame) {
-               if (nsgif_get_frame(gif) != GIF_OK) {
-                       return false;
-               }
+       if (gif_get_frame(gif) != NSGIF_OK) {
+               return false;
        }
 
        return guit->bitmap->get_opaque(gif->gif->frame_image);
 }
 
-static const content_handler nsgif_content_handler = {
-       .create = nsgif_create,
-       .data_complete = nsgif_convert,
-       .destroy = nsgif_destroy,
-       .redraw = nsgif_redraw,
-       .clone = nsgif_clone,
-       .add_user = nsgif_add_user,
-       .remove_user = nsgif_remove_user,
-       .get_internal = nsgif_get_internal,
-       .type = nsgif_content_type,
-       .is_opaque = nsgif_content_is_opaque,
+static const content_handler gif_content_handler = {
+       .create = gif_create,
+       .data_complete = gif_convert,
+       .destroy = gif_destroy,
+       .redraw = gif_redraw,
+       .clone = gif_clone,
+       .add_user = gif_add_user,
+       .remove_user = gif_remove_user,
+       .get_internal = gif_get_internal,
+       .type = gif_content_type,
+       .is_opaque = gif_content_is_opaque,
        .no_share = false,
 };
 
-static const char *nsgif_types[] = {
+static const char *gif_types[] = {
        "image/gif"
 };
 
-CONTENT_FACTORY_REGISTER_TYPES(nsgif, nsgif_types, nsgif_content_handler);
+CONTENT_FACTORY_REGISTER_TYPES(nsgif, gif_types, gif_content_handler);


-----------------------------------------------------------------------


-- 
NetSurf Browser
_______________________________________________
netsurf-commits mailing list -- netsurf-commits@netsurf-browser.org
To unsubscribe send an email to netsurf-commits-le...@netsurf-browser.org

Reply via email to