From 81c52ad4947c2b658473f8f87e244660a72c002a Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 27 Aug 2011 08:43:51 +0000 Subject: Initial image content handler refactor svn path=/trunk/netsurf/; revision=12671 --- image/mng.c | 876 ++++++++++++++++++++++++++++-------------------------------- 1 file changed, 410 insertions(+), 466 deletions(-) (limited to 'image/mng.c') diff --git a/image/mng.c b/image/mng.c index 69c13fe97..44b62f203 100644 --- a/image/mng.c +++ b/image/mng.c @@ -41,9 +41,9 @@ #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. -*/ +/* This implementation does not currently support dynamic MNGs or any + * form of colour/gamma correction, + */ typedef struct nsmng_content { @@ -58,263 +58,64 @@ typedef struct nsmng_content 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, struct content_redraw_data *data, - const struct rect *clip, const struct redraw_context *ctx); -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, - mng_uint32 size, mng_uint32 *bytesread); -static mng_bool nsmng_closestream(mng_handle mng); -static mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, - mng_uint32 height); -static mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line); -static mng_uint32 nsmng_gettickcount(mng_handle mng); -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 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); -#ifndef MNG_INTERNAL_MEMMNGMT -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 = { - .create = nsmng_create, - .process_data = nsmng_process_data, - .data_complete = nsmng_convert, - .destroy = nsmng_destroy, - .redraw = nsmng_redraw, - .clone = nsmng_clone, - .type = nsmng_content_type, - .no_share = 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" -}; +#ifndef MNG_INTERNAL_MEMMNGMT -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)]; +/** + * Memory allocation callback for libmng. + */ -nserror nsmng_init(void) +static mng_ptr nsmng_alloc(mng_size_t n) { - 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; + return calloc(1, n); } -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]); - } -} +/** + * Memory free callback for libmng. + */ -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 void nsmng_free(mng_ptr p, mng_size_t n) { - 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; - - return NSERROR_OK; + free(p); } -nserror nsmng_create_mng_data(nsmng_content *c) +#endif + +/** + * Broadcasts an error message and returns false + * + * \param c the content to broadcast for + * \return Appropriate error + */ +static nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code) { - mng_retcode code; union content_msg_data msg_data; + char error[100]; assert(c != NULL); - /* Initialise the library - */ -#ifdef MNG_INTERNAL_MEMMNGMT - c->handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL); -#else - c->handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL); -#endif - if (c->handle == MNG_NULL) { - LOG(("Unable to initialise MNG library.")); + if (code == MNG_OUTOFMEMORY) { msg_data.error = messages_get("NoMemory"); content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); return NSERROR_NOMEM; } - /* We need to decode in suspension mode - */ - code = mng_set_suspensionmode(c->handle, MNG_TRUE); - if (code) { - LOG(("Unable to set suspension mode.")); - return nsmng_broadcast_error(c, code); - } - - /* We need to register our callbacks - */ - 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->handle, nsmng_readdata); - if (code) { - LOG(("Unable to set readdata callback.")); - return nsmng_broadcast_error(c, code); - } - 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->handle, nsmng_processheader); - if (code) { - LOG(("Unable to set processheader callback.")); - return nsmng_broadcast_error(c, code); - } - - /* Register our callbacks for displaying - */ - 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->handle, nsmng_refresh); - if (code) { - LOG(("Unable to set refresh callback.")); - return nsmng_broadcast_error(c, code); - } - 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->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->handle, nsmng_errorproc); - if (code) { - LOG(("Unable to set errorproc")); - return nsmng_broadcast_error(c, code); - } - - /* Initialise the reading - */ - c->read_start = true; - c->read_resume = false; - c->read_size = 0; - c->waiting = false; - - c->displayed = false; - - return NSERROR_OK; + snprintf(error, sizeof error, messages_get("MNGError"), code); + msg_data.error = error; + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + return NSERROR_MNG_ERROR; } +/* CALLBACKS REQUIRED FOR libmng READING */ -/* START OF CALLBACKS REQUIRED FOR READING -*/ - - -mng_bool nsmng_openstream(mng_handle mng) +static mng_bool nsmng_openstream(mng_handle mng) { assert(mng != NULL); return MNG_TRUE; } -mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, +static mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, mng_uint32 *bytesread) { nsmng_content *c; @@ -347,13 +148,13 @@ mng_bool nsmng_readdata(mng_handle mng, mng_ptr buffer, mng_uint32 size, return MNG_TRUE; } -mng_bool nsmng_closestream(mng_handle mng) +static mng_bool nsmng_closestream(mng_handle mng) { assert(mng != NULL); return MNG_TRUE; } -mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, +static mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height) { nsmng_content *c; @@ -407,7 +208,7 @@ mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, */ -bool nsmng_process_data(struct content *c, const char *data, unsigned int size) +static bool nsmng_process_data(struct content *c, const char *data, unsigned int size) { nsmng_content *mng = (nsmng_content *) c; mng_retcode status; @@ -439,107 +240,11 @@ bool nsmng_process_data(struct content *c, const char *data, unsigned int size) return true; } - -bool nsmng_convert(struct content *c) -{ - nsmng_content *mng = (nsmng_content *) c; - mng_retcode status; - unsigned long size; - lwc_string *content_type; - bool match; - bool is_mng = false; - uint32_t i; - char title[100]; - - assert(c != NULL); - - content__get_source_data(c, &size); - - /* by this point, the png should have been parsed - * and the bitmap created, so ensure that's the case - */ - if (content__get_bitmap(c) == NULL) - return nsmng_broadcast_error(mng, -1) == NSERROR_OK; - - /* Set the title - */ - 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 (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 { - snprintf(title, sizeof(title), messages_get("JNGTitle"), - c->width, c->height, size); - } - 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); - /* Done: update status bar */ - content_set_status(c, ""); - - /* jmb: I'm really not sure that this should be here. - * The *_convert functions are for converting a content into a - * displayable format. They should not, however, do anything which - * could cause the content to be displayed; the content may have - * hidden visibility or be a fallback for an object; this - * information is not available here (nor is there any need for it - * to be). - * The specific issue here is that mng_display calls the display - * callbacks, which include nsmng_refresh. nsmng_refresh forces - * a content to be redrawn regardless of whether it should be - * displayed or not. - */ - /* Start displaying - */ - status = mng_display(mng->handle); - if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) { - LOG(("Unable to start display (%i)", status)); - return nsmng_broadcast_error(mng, status) == NSERROR_OK; - } - bitmap_modified(c->bitmap); - - /* Optimise the plotting of JNG/PNGs - */ - 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 (is_mng == false) { - mng_handle handle = mng->handle; - - mng_cleanup(&handle); - - mng->handle = NULL; - } - - return true; -} - - /* START OF CALLBACKS REQUIRED FOR DISPLAYING */ -mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line) +static mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line) { nsmng_content *c; @@ -556,39 +261,8 @@ mng_ptr nsmng_getcanvasline(mng_handle mng, mng_uint32 line) bitmap_get_rowstride(c->base.bitmap) * line; } - -/** - * Get the wall-clock time in milliseconds since some fixed time. - */ - -mng_uint32 nsmng_gettickcount(mng_handle mng) -{ - static bool start = true; - static time_t t0; - struct timeval tv; -#if defined(__SVR4) && defined(__sun) || defined(__NetBSD__) || \ - defined(__APPLE__) - /* Solaris, NetBSD, and OS X don't have this structure, and ignore the - * second parameter to gettimeofday() - */ - int tz; -#else - struct timezone tz; -#endif - assert(mng != NULL); - - gettimeofday(&tv, &tz); - if (start) { - t0 = tv.tv_sec; - start = false; - } - - return (tv.tv_sec - t0) * 1000 + tv.tv_usec / 1000; -} - - -mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, - mng_uint32 w, mng_uint32 h) +static mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, + mng_uint32 w, mng_uint32 h) { union content_msg_data data; nsmng_content *c; @@ -639,7 +313,31 @@ mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, return MNG_TRUE; } -mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs) +/** + * Animates to the next frame + */ +static void nsmng_animate(void *p) +{ + nsmng_content *c; + + assert(p != NULL); + + c = (nsmng_content *) p; + + /* If we used the last animation we advance, if not we try again later + */ + if (c->base.user_list->next == NULL) { + c->waiting = true; + } else { + c->waiting = false; + mng_display_resume(c->handle); + c->opaque_test_pending = true; + if (c->base.bitmap) + bitmap_modified(c->base.bitmap); + } +} + +static mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs) { nsmng_content *c; @@ -656,12 +354,316 @@ mng_bool nsmng_settimer(mng_handle mng, mng_uint32 msecs) return MNG_TRUE; } +/** + * Get the wall-clock time in milliseconds since some fixed time. + */ + +static mng_uint32 nsmng_gettickcount(mng_handle mng) +{ + static bool start = true; + static time_t t0; + struct timeval tv; +#if defined(__SVR4) && defined(__sun) || defined(__NetBSD__) || \ + defined(__APPLE__) + /* Solaris, NetBSD, and OS X don't have this structure, and ignore the + * second parameter to gettimeofday() + */ + int tz; +#else + struct timezone tz; +#endif + assert(mng != NULL); + + gettimeofday(&tv, &tz); + if (start) { + t0 = tv.tv_sec; + start = false; + } + + return (tv.tv_sec - t0) * 1000 + tv.tv_usec / 1000; +} /* END OF CALLBACKS REQUIRED FOR DISPLAYING */ +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) +{ + nsmng_content *c; + char chunk[5]; + + assert(mng != NULL); + + c = (nsmng_content *) mng_get_userdata(mng); + assert(c != NULL); + + chunk[0] = (char)((chunktype >> 24) & 0xFF); + chunk[1] = (char)((chunktype >> 16) & 0xFF); + chunk[2] = (char)((chunktype >> 8) & 0xFF); + chunk[3] = (char)((chunktype ) & 0xFF); + chunk[4] = '\0'; + + LOG(("error playing '%s' chunk %s (%d):", + 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); +} -void nsmng_destroy(struct content *c) +static nserror nsmng_create_mng_data(nsmng_content *c) +{ + mng_retcode code; + union content_msg_data msg_data; + + assert(c != NULL); + + /* Initialise the library + */ +#ifdef MNG_INTERNAL_MEMMNGMT + c->handle = mng_initialize(c, MNG_NULL, MNG_NULL, MNG_NULL); +#else + c->handle = mng_initialize(c, nsmng_alloc, nsmng_free, MNG_NULL); +#endif + if (c->handle == MNG_NULL) { + LOG(("Unable to initialise MNG library.")); + msg_data.error = messages_get("NoMemory"); + content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); + return NSERROR_NOMEM; + } + + /* We need to decode in suspension mode + */ + code = mng_set_suspensionmode(c->handle, MNG_TRUE); + if (code) { + LOG(("Unable to set suspension mode.")); + return nsmng_broadcast_error(c, code); + } + + /* We need to register our callbacks + */ + 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->handle, nsmng_readdata); + if (code) { + LOG(("Unable to set readdata callback.")); + return nsmng_broadcast_error(c, code); + } + 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->handle, nsmng_processheader); + if (code) { + LOG(("Unable to set processheader callback.")); + return nsmng_broadcast_error(c, code); + } + + /* Register our callbacks for displaying + */ + 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->handle, nsmng_refresh); + if (code) { + LOG(("Unable to set refresh callback.")); + return nsmng_broadcast_error(c, code); + } + 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->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->handle, nsmng_errorproc); + if (code) { + LOG(("Unable to set errorproc")); + return nsmng_broadcast_error(c, code); + } + + /* Initialise the reading + */ + c->read_start = true; + c->read_resume = false; + c->read_size = 0; + c->waiting = false; + + c->displayed = false; + + return NSERROR_OK; +} + +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) +{ + 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; + + return NSERROR_OK; +} + + + +static bool nsmng_convert(struct content *c) +{ + nsmng_content *mng = (nsmng_content *) c; + mng_retcode status; + unsigned long size; + char title[100]; + + assert(c != NULL); + + content__get_source_data(c, &size); + + /* by this point, the png should have been parsed + * and the bitmap created, so ensure that's the case + */ + if (content__get_bitmap(c) == NULL) { + return nsmng_broadcast_error(mng, -1) == NSERROR_OK; + } + + /* Set the title + */ + snprintf(title, sizeof(title), + messages_get("MNGTitle"), + c->width, c->height, size); + content__set_title(c, title); + + c->size += c->width * c->height * 4; + content_set_ready(c); + content_set_done(c); + /* Done: update status bar */ + content_set_status(c, ""); + + /* jmb: I'm really not sure that this should be here. + * The *_convert functions are for converting a content into a + * displayable format. They should not, however, do anything which + * could cause the content to be displayed; the content may have + * hidden visibility or be a fallback for an object; this + * information is not available here (nor is there any need for it + * to be). + * The specific issue here is that mng_display calls the display + * callbacks, which include nsmng_refresh. nsmng_refresh forces + * a content to be redrawn regardless of whether it should be + * displayed or not. + */ + /* Start displaying + */ + status = mng_display(mng->handle); + if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) { + LOG(("Unable to start display (%i)", status)); + return nsmng_broadcast_error(mng, status) == NSERROR_OK; + } + bitmap_modified(c->bitmap); + + /* Optimise the plotting of MNG */ + mng->opaque_test_pending = false; + + return true; +} + +static bool nsjpng_convert(struct content *c) +{ + nsmng_content *mng = (nsmng_content *) c; + mng_retcode status; + unsigned long size; + char title[100]; + + assert(c != NULL); + + content__get_source_data(c, &size); + + /* by this point, the png should have been parsed + * and the bitmap created, so ensure that's the case + */ + if (content__get_bitmap(c) == NULL) { + return nsmng_broadcast_error(mng, -1) == NSERROR_OK; + } + + /* Set the title */ + snprintf(title, sizeof(title), + messages_get("PNGTitle"), + c->width, c->height, size); + content__set_title(c, title); + + c->size += c->width * c->height * 4; + content_set_ready(c); + content_set_done(c); + /* Done: update status bar */ + content_set_status(c, ""); + + /* jmb: I'm really not sure that this should be here. + * The *_convert functions are for converting a content into a + * displayable format. They should not, however, do anything which + * could cause the content to be displayed; the content may have + * hidden visibility or be a fallback for an object; this + * information is not available here (nor is there any need for it + * to be). + * The specific issue here is that mng_display calls the display + * callbacks, which include nsmng_refresh. nsmng_refresh forces + * a content to be redrawn regardless of whether it should be + * displayed or not. + */ + /* Start displaying + */ + status = mng_display(mng->handle); + if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) { + LOG(("Unable to start display (%i)", status)); + return nsmng_broadcast_error(mng, status) == NSERROR_OK; + } + bitmap_modified(c->bitmap); + + /* Optimise the plotting of JNG/PNGs + */ + mng->opaque_test_pending = true; + bitmap_set_opaque(c->bitmap, false); + + /* free associated memory */ + + mng_handle handle = mng->handle; + + mng_cleanup(&handle); + + mng->handle = NULL; + + return true; +} + +static void nsmng_destroy(struct content *c) { nsmng_content *mng = (nsmng_content *) c; @@ -684,7 +686,7 @@ void nsmng_destroy(struct content *c) } -bool nsmng_redraw(struct content *c, struct content_redraw_data *data, +static bool nsmng_redraw(struct content *c, struct content_redraw_data *data, const struct rect *clip, const struct redraw_context *ctx) { nsmng_content *mng = (nsmng_content *) c; @@ -707,8 +709,7 @@ bool nsmng_redraw(struct content *c, struct content_redraw_data *data, ret = ctx->plot->bitmap(data->x, data->y, data->width, data->height, c->bitmap, data->background_colour, flags); - /* Check if we need to restart the animation - */ + /* Check if we need to restart the animation */ if ((mng->waiting) && (option_animate_images)) nsmng_animate(c); @@ -716,7 +717,7 @@ bool nsmng_redraw(struct content *c, struct content_redraw_data *data, } -nserror nsmng_clone(const struct content *old, struct content **newc) +static nserror nsmng_clone(const struct content *old, struct content **newc) { nsmng_content *mng; nserror error; @@ -761,111 +762,54 @@ nserror nsmng_clone(const struct content *old, struct content **newc) return NSERROR_OK; } -content_type nsmng_content_type(lwc_string *mime_type) +static content_type nsmng_content_type(lwc_string *mime_type) { return CONTENT_IMAGE; } -/** - * Animates to the next frame - */ -void nsmng_animate(void *p) -{ - nsmng_content *c; - - assert(p != NULL); - - c = (nsmng_content *) p; - - /* If we used the last animation we advance, if not we try again later - */ - if (c->base.user_list->next == NULL) { - c->waiting = true; - } else { - c->waiting = false; - mng_display_resume(c->handle); - c->opaque_test_pending = true; - if (c->base.bitmap) - bitmap_modified(c->base.bitmap); - } -} - - - -/** - * Broadcasts an error message and returns false - * - * \param c the content to broadcast for - * \return Appropriate error - */ -nserror nsmng_broadcast_error(nsmng_content *c, mng_retcode code) -{ - union content_msg_data msg_data; - char error[100]; - - assert(c != NULL); - - if (code == MNG_OUTOFMEMORY) { - msg_data.error = messages_get("NoMemory"); - 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->base, CONTENT_MSG_ERROR, msg_data); - return NSERROR_MNG_ERROR; -} - - -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) -{ - nsmng_content *c; - char chunk[5]; - - assert(mng != NULL); - - c = (nsmng_content *) mng_get_userdata(mng); - assert(c != NULL); - - chunk[0] = (char)((chunktype >> 24) & 0xFF); - chunk[1] = (char)((chunktype >> 16) & 0xFF); - chunk[2] = (char)((chunktype >> 8) & 0xFF); - chunk[3] = (char)((chunktype ) & 0xFF); - chunk[4] = '\0'; - - LOG(("error playing '%s' chunk %s (%d):", - 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); -} - - -#ifndef MNG_INTERNAL_MEMMNGMT +/* register handler for mng types */ +static const content_handler nsmng_content_handler = { + .create = nsmng_create, + .process_data = nsmng_process_data, + .data_complete = nsmng_convert, + .destroy = nsmng_destroy, + .redraw = nsmng_redraw, + .clone = nsmng_clone, + .type = nsmng_content_type, + .no_share = false, +}; -/** - * Memory allocation callback for libmng. - */ +static const char *nsmng_types[] = { + /* MNG types*/ + "image/mng", + "image/x-mng", + "video/mng", + "video/x-mng", +}; -mng_ptr nsmng_alloc(mng_size_t n) -{ - return calloc(1, n); -} +CONTENT_FACTORY_REGISTER_TYPES(nsmng, nsmng_types, nsmng_content_handler); +/* register handler for jng and png types */ +static const content_handler nsjpng_content_handler = { + .create = nsmng_create, + .process_data = nsmng_process_data, + .data_complete = nsjpng_convert, + .destroy = nsmng_destroy, + .redraw = nsmng_redraw, + .clone = nsmng_clone, + .type = nsmng_content_type, + .no_share = false, +}; -/** - * Memory free callback for libmng. - */ -void nsmng_free(mng_ptr p, mng_size_t n) -{ - free(p); -} +static const char *nsjpng_types[] = { + /* JNG types*/ + "image/jng", + "image/x-jng", + /* PNG types*/ + "image/png" +}; -#endif +CONTENT_FACTORY_REGISTER_TYPES(nsjpng, nsjpng_types, nsjpng_content_handler); #endif -- cgit v1.2.3