From 70c7b81c2fd459c87697216b69c2bd17e5d3086c Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 1 Jun 2008 00:15:53 +0000 Subject: Improve MNG error handling to show error code. Fix code not expecting bitmap_get_buffer() to return 0. svn path=/trunk/netsurf/; revision=4237 --- image/bmpread.c | 12 +++++++- image/mng.c | 94 ++++++++++++++++++++++++++++++++++++-------------------- image/nssprite.c | 13 ++++++-- 3 files changed, 83 insertions(+), 36 deletions(-) (limited to 'image') diff --git a/image/bmpread.c b/image/bmpread.c index 7e6a9fefa..cf11ab807 100644 --- a/image/bmpread.c +++ b/image/bmpread.c @@ -127,7 +127,7 @@ bmp_result ico_analyse(struct ico_collection *ico) { image->bmp.bmp_data = ico->ico_data + READ_INT(data, 12); image->bmp.ico = true; data += 16; - result = bmp_analyse_header(&image->bmp, + result = bmp_analyse_header(&image->bmp, (char *) image->bmp.bmp_data); if (result != BMP_OK) return result; @@ -425,6 +425,8 @@ bmp_result bmp_decode_rgb24(struct bmp_image *bmp, char **start, int bytes) { data = *start; swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; bottom = top + swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; @@ -485,6 +487,8 @@ bmp_result bmp_decode_rgb16(struct bmp_image *bmp, char **start, int bytes) { data = *start; swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; bottom = top + swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; @@ -552,6 +556,8 @@ bmp_result bmp_decode_rgb(struct bmp_image *bmp, char **start, int bytes) { data = *start; swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; bottom = top + swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; @@ -598,6 +604,8 @@ bmp_result bmp_decode_mask(struct bmp_image *bmp, char *data, int bytes) { swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; bottom = top + swidth * (bmp->height - 1); end = data + bytes; addr = ((intptr_t)data) & 3; @@ -642,6 +650,8 @@ bmp_result bmp_decode_rle(struct bmp_image *bmp, char *data, int bytes, int size swidth = bitmap_get_rowstride(bmp->bitmap); top = bitmap_get_buffer(bmp->bitmap); + if (!top) + return BMP_INSUFFICIENT_MEMORY; bottom = top + swidth * (bmp->height - 1); end = data + bytes; bmp->decoded = true; diff --git a/image/mng.c b/image/mng.c index fb2528514..7e92193cf 100644 --- a/image/mng.c +++ b/image/mng.c @@ -54,7 +54,7 @@ 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 bool nsmng_broadcast_error(struct content *c); +static bool nsmng_broadcast_error(struct 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); @@ -65,6 +65,8 @@ static void nsmng_free(mng_ptr p, mng_size_t n); bool nsmng_create(struct content *c, const char *params[]) { + mng_retcode code; + union content_msg_data msg_data; assert(c != NULL); assert(params != NULL); @@ -78,58 +80,70 @@ bool nsmng_create(struct content *c, const char *params[]) { #endif if (c->data.mng.handle == MNG_NULL) { LOG(("Unable to initialise MNG library.")); - return nsmng_broadcast_error(c); + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; } /* We need to decode in suspension mode */ - if (mng_set_suspensionmode(c->data.mng.handle, MNG_TRUE) != MNG_NOERROR) { + code = mng_set_suspensionmode(c->data.mng.handle, MNG_TRUE); + if (code) { LOG(("Unable to set suspension mode.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } /* We need to register our callbacks */ - if (mng_setcb_openstream(c->data.mng.handle, nsmng_openstream) != MNG_NOERROR) { + code = mng_setcb_openstream(c->data.mng.handle, nsmng_openstream); + if (code) { LOG(("Unable to set openstream callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } - if (mng_setcb_readdata(c->data.mng.handle, nsmng_readdata) != MNG_NOERROR) { + code = mng_setcb_readdata(c->data.mng.handle, nsmng_readdata); + if (code) { LOG(("Unable to set readdata callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } - if (mng_setcb_closestream(c->data.mng.handle, nsmng_closestream) != MNG_NOERROR) { + code = mng_setcb_closestream(c->data.mng.handle, nsmng_closestream); + if (code) { LOG(("Unable to set closestream callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } - if (mng_setcb_processheader(c->data.mng.handle, nsmng_processheader) != MNG_NOERROR) { + code = mng_setcb_processheader(c->data.mng.handle, nsmng_processheader); + if (code) { LOG(("Unable to set processheader callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } /* Register our callbacks for displaying */ - if (mng_setcb_getcanvasline(c->data.mng.handle, nsmng_getcanvasline) != MNG_NOERROR) { + code = mng_setcb_getcanvasline(c->data.mng.handle, nsmng_getcanvasline); + if (code) { LOG(("Unable to set getcanvasline callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } - if (mng_setcb_refresh(c->data.mng.handle, nsmng_refresh) != MNG_NOERROR) { + code = mng_setcb_refresh(c->data.mng.handle, nsmng_refresh); + if (code) { LOG(("Unable to set refresh callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } - if (mng_setcb_gettickcount(c->data.mng.handle, nsmng_gettickcount) != MNG_NOERROR) { + code = mng_setcb_gettickcount(c->data.mng.handle, nsmng_gettickcount); + if (code) { LOG(("Unable to set gettickcount callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } - if (mng_setcb_settimer(c->data.mng.handle, nsmng_settimer) != MNG_NOERROR) { + code = mng_setcb_settimer(c->data.mng.handle, nsmng_settimer); + if (code) { LOG(("Unable to set settimer callback.")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } /* register error handling function */ - if (mng_setcb_errorproc(c->data.mng.handle, nsmng_errorproc) != MNG_NOERROR) { + code = mng_setcb_errorproc(c->data.mng.handle, nsmng_errorproc); + if (code) { LOG(("Unable to set errorproc")); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, code); } /* Initialise the reading @@ -188,6 +202,7 @@ mng_bool nsmng_closestream(mng_handle mng) { mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height) { struct content *c; union content_msg_data msg_data; + char *buffer; assert(mng != NULL); @@ -205,6 +220,16 @@ mng_bool nsmng_processheader(mng_handle mng, mng_uint32 width, mng_uint32 height 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) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + LOG(("Insufficient memory to create canvas.")); + return MNG_FALSE; + } + /* Initialise the content size */ c->width = width; @@ -247,7 +272,7 @@ bool nsmng_process_data(struct content *c, char *data, unsigned int size) { c->data.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); + return nsmng_broadcast_error(c, status); } /* Continue onwards @@ -267,7 +292,7 @@ bool nsmng_convert(struct content *c, int width, int height) { * and the bitmap created, so ensure that's the case */ if (!c->bitmap) - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, -1); /* Set the title */ @@ -311,7 +336,7 @@ bool nsmng_convert(struct content *c, int width, int height) { status = mng_display(c->data.mng.handle); if ((status != MNG_NOERROR) && (status != MNG_NEEDTIMERWAIT)) { LOG(("Unable to start display (%i)", status)); - return nsmng_broadcast_error(c); + return nsmng_broadcast_error(c, status); } bitmap_modified(c->bitmap); @@ -550,23 +575,26 @@ void nsmng_animate(void *p) { * \param c the content to broadcast for * \return false */ -bool nsmng_broadcast_error(struct content *c) { +bool nsmng_broadcast_error(struct content *c, mng_retcode code) +{ union content_msg_data msg_data; + char error[100]; assert(c != NULL); - if (c->type == CONTENT_MNG) { - msg_data.error = messages_get("MNGError"); - } else if (c->type == CONTENT_PNG) { - msg_data.error = messages_get("PNGError"); - } else { - msg_data.error = messages_get("JNGError"); + if (code == MNG_OUTOFMEMORY) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; } + + snprintf(error, sizeof error, messages_get("MNGError"), code); + msg_data.error = error; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; - } + mng_bool nsmng_errorproc(mng_handle mng, mng_int32 code, mng_int8 severity, mng_chunkid chunktype, mng_uint32 chunkseq, diff --git a/image/nssprite.c b/image/nssprite.c index c9aff34e9..e7e40683b 100644 --- a/image/nssprite.c +++ b/image/nssprite.c @@ -58,8 +58,10 @@ bool nssprite_convert(struct content *c, int width, int height) { + union content_msg_data msg_data; + struct rosprite_mem_context* ctx; - ERRCHK(rosprite_create_mem_context((uint8_t *) c->source_data, + ERRCHK(rosprite_create_mem_context((uint8_t *) c->source_data, c->total_size, &ctx)); struct rosprite_area* sprite_area; @@ -73,11 +75,18 @@ bool nssprite_convert(struct content *c, int width, int height) c->bitmap = bitmap_create(sprite->width, sprite->height, BITMAP_NEW); if (!c->bitmap) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } char* imagebuf = bitmap_get_buffer(c->bitmap); + if (!imagebuf) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } unsigned int row_width = bitmap_get_rowstride(c->bitmap); - + memcpy(imagebuf, sprite->image, row_width * sprite->height); // TODO: avoid copying entire image buffer /* reverse byte order of each word */ -- cgit v1.2.3