From f2e8be9fe75817a29eb7aeda08659944c0c69932 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sat, 7 May 2011 23:35:57 +0000 Subject: Cleanup png code only use the bitmap pointer in the png content the one in teh base content seems extraneous for png. svn path=/trunk/netsurf/; revision=12304 --- image/png.c | 556 +++++++++++++++++++++++++++++------------------------------- 1 file changed, 266 insertions(+), 290 deletions(-) diff --git a/image/png.c b/image/png.c index 5469e6923..8a88a09c8 100644 --- a/image/png.c +++ b/image/png.c @@ -45,8 +45,8 @@ #ifndef png_jmpbuf #warning you have an antique libpng -#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) -#endif +#define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf) +#endif #if PNG_LIBPNG_VER < 10209 #define png_set_expand_gray_1_2_4_to_8(png) png_set_gray_1_2_4_to_8(png) @@ -58,278 +58,95 @@ typedef struct nspng_content { png_structp png; png_infop info; int interlace; - struct bitmap *bitmap; /**< Created NetSurf bitmap */ - size_t rowstride, bpp; /**< Bitmap rowstride and bpp */ - size_t rowbytes; /**< Number of bytes per row */ + struct bitmap *bitmap; /**< Created NetSurf bitmap */ + size_t rowstride, bpp; /**< Bitmap rowstride and bpp */ + size_t rowbytes; /**< Number of bytes per row */ } nspng_content; -static nserror nspng_create(const content_handler *handler, - lwc_string *imime_type, const http_parameter *params, - llcache_handle *llcache, const char *fallback_charset, - bool quirks, struct content **c); -static nserror nspng_create_png_data(nspng_content *c); -static bool nspng_process_data(struct content *c, const char *data, - unsigned int size); -static bool nspng_convert(struct content *c); -static void nspng_destroy(struct content *c); -static bool nspng_redraw(struct content *c, int x, int y, - int width, int height, const struct rect *clip, - float scale, colour background_colour); -static bool nspng_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 nspng_clone(const struct content *old, struct content **newc); -static content_type nspng_content_type(lwc_string *mime_type); - -static void info_callback(png_structp png, png_infop info); -static void row_callback(png_structp png, png_bytep new_row, - png_uint_32 row_num, int pass); -static void end_callback(png_structp png, png_infop info); - -static const content_handler nspng_content_handler = { - nspng_create, - nspng_process_data, - nspng_convert, - NULL, - nspng_destroy, - NULL, - NULL, - NULL, - nspng_redraw, - nspng_redraw_tiled, - NULL, - NULL, - nspng_clone, - NULL, - nspng_content_type, - false -}; - static const char *nspng_types[] = { "image/png" }; static lwc_string *nspng_mime_types[NOF_ELEMENTS(nspng_types)]; -nserror nspng_init(void) -{ - uint32_t i; - lwc_error lerror; - nserror error; - - for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) { - lerror = lwc_intern_string(nspng_types[i], - strlen(nspng_types[i]), - &nspng_mime_types[i]); - if (lerror != lwc_error_ok) { - error = NSERROR_NOMEM; - goto error; - } - - error = content_factory_register_handler(nspng_mime_types[i], - &nspng_content_handler); - if (error != NSERROR_OK) - goto error; - } - - return NSERROR_OK; - -error: - nspng_fini(); - - return error; -} - -void nspng_fini(void) -{ - uint32_t i; - - for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) { - if (nspng_mime_types[i] != NULL) - lwc_string_unref(nspng_mime_types[i]); - } -} - -nserror nspng_create(const content_handler *handler, - lwc_string *imime_type, const http_parameter *params, - llcache_handle *llcache, const char *fallback_charset, - bool quirks, struct content **c) -{ - nspng_content *png; - nserror error; - - png = talloc_zero(0, nspng_content); - if (png == NULL) - return NSERROR_NOMEM; - - error = content__init(&png->base, handler, imime_type, params, - llcache, fallback_charset, quirks); - if (error != NSERROR_OK) { - talloc_free(png); - return error; - } - - error = nspng_create_png_data(png); - if (error != NSERROR_OK) { - talloc_free(png); - return error; - } - - *c = (struct content *) png; - - return NSERROR_OK; -} - -nserror nspng_create_png_data(nspng_content *c) -{ - union content_msg_data msg_data; - - c->bitmap = NULL; - - c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); - if (c->png == NULL) { - msg_data.error = messages_get("NoMemory"); - content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); - warn_user("NoMemory", 0); - return NSERROR_NOMEM; - } - - c->info = png_create_info_struct(c->png); - if (c->info == NULL) { - png_destroy_read_struct(&c->png, &c->info, 0); - - msg_data.error = messages_get("NoMemory"); - content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); - warn_user("NoMemory", 0); - return NSERROR_NOMEM; - } - - if (setjmp(png_jmpbuf(c->png))) { - png_destroy_read_struct(&c->png, &c->info, 0); - LOG(("Failed to set callbacks")); - c->png = NULL; - c->info = NULL; - - msg_data.error = messages_get("PNGError"); - content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data); - return NSERROR_NOMEM; - } - - png_set_progressive_read_fn(c->png, c, - info_callback, row_callback, end_callback); - - return NSERROR_OK; -} - - -bool nspng_process_data(struct content *c, const char *data, unsigned int size) -{ - nspng_content *png = (nspng_content *) c; - union content_msg_data msg_data; - - if (setjmp(png_jmpbuf(png->png))) { - png_destroy_read_struct(&png->png, &png->info, 0); - LOG(("Failed to process data")); - png->png = NULL; - png->info = NULL; - if (png->bitmap != NULL) { - bitmap_destroy(png->bitmap); - png->bitmap = NULL; - } - - msg_data.error = messages_get("PNGError"); - content_broadcast(c, CONTENT_MSG_ERROR, msg_data); - return false; - } - - png_process_data(png->png, png->info, (uint8_t *) data, size); - - return true; -} - +static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0}; +static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0}; +static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1}; +static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2}; /** * info_callback -- PNG header has been completely received, prepare to process * image data */ - -void info_callback(png_structp png, png_infop info) +static void info_callback(png_structp png_s, png_infop info) { int bit_depth, color_type, interlace, intent; double gamma; png_uint_32 width, height; - nspng_content *c = png_get_progressive_ptr(png); + nspng_content *png_c = png_get_progressive_ptr(png_s); /* Read the PNG details */ - png_get_IHDR(png, info, &width, &height, &bit_depth, - &color_type, &interlace, 0, 0); + png_get_IHDR(png_s, info, &width, &height, &bit_depth, + &color_type, &interlace, 0, 0); /* Claim the required memory for the converted PNG */ - c->bitmap = bitmap_create(width, height, BITMAP_NEW); - if (c->bitmap == NULL) { + png_c->bitmap = bitmap_create(width, height, BITMAP_NEW); + if (png_c->bitmap == NULL) { /* Failed -- bail out */ - longjmp(png_jmpbuf(png), 1); + longjmp(png_jmpbuf(png_s), 1); } - c->rowstride = bitmap_get_rowstride(c->bitmap); - c->bpp = bitmap_get_bpp(c->bitmap); + png_c->rowstride = bitmap_get_rowstride(png_c->bitmap); + png_c->bpp = bitmap_get_bpp(png_c->bitmap); - /* Set up our transformations */ + /* Set up our transformations */ if (color_type == PNG_COLOR_TYPE_PALETTE) - png_set_palette_to_rgb(png); - if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) - png_set_expand_gray_1_2_4_to_8(png); - if (png_get_valid(png, info, PNG_INFO_tRNS)) - png_set_tRNS_to_alpha(png); + png_set_palette_to_rgb(png_s); + if ((color_type == PNG_COLOR_TYPE_GRAY) && (bit_depth < 8)) + png_set_expand_gray_1_2_4_to_8(png_s); + if (png_get_valid(png_s, info, PNG_INFO_tRNS)) + png_set_tRNS_to_alpha(png_s); if (bit_depth == 16) - png_set_strip_16(png); + png_set_strip_16(png_s); if (color_type == PNG_COLOR_TYPE_GRAY || - color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - png_set_gray_to_rgb(png); + color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_s); if (!(color_type & PNG_COLOR_MASK_ALPHA)) - png_set_filler(png, 0xff, PNG_FILLER_AFTER); + png_set_filler(png_s, 0xff, PNG_FILLER_AFTER); /* gamma correction - we use 2.2 as our screen gamma * this appears to be correct (at least in respect to !Browse) * see http://www.w3.org/Graphics/PNG/all_seven.html for a test case */ - if (png_get_sRGB(png, info, &intent)) - png_set_gamma(png, 2.2, 0.45455); - else { - if (png_get_gAMA(png, info, &gamma)) - png_set_gamma(png, 2.2, gamma); - else - png_set_gamma(png, 2.2, 0.45455); + if (png_get_sRGB(png_s, info, &intent)) { + png_set_gamma(png_s, 2.2, 0.45455); + } else { + if (png_get_gAMA(png_s, info, &gamma)) { + png_set_gamma(png_s, 2.2, gamma); + } else { + png_set_gamma(png_s, 2.2, 0.45455); + } } + png_read_update_info(png_s, info); - png_read_update_info(png, info); - - c->rowbytes = png_get_rowbytes(png, info); - c->interlace = (interlace == PNG_INTERLACE_ADAM7); - c->base.width = width; - c->base.height = height; + png_c->rowbytes = png_get_rowbytes(png_s, info); + png_c->interlace = (interlace == PNG_INTERLACE_ADAM7); + png_c->base.width = width; + png_c->base.height = height; LOG(("size %li * %li, bpp %i, rowbytes %zu", (unsigned long)width, - (unsigned long)height, bit_depth, c->rowbytes)); + (unsigned long)height, bit_depth, png_c->rowbytes)); } - -static unsigned int interlace_start[8] = {0, 16, 0, 8, 0, 4, 0}; -static unsigned int interlace_step[8] = {28, 28, 12, 12, 4, 4, 0}; -static unsigned int interlace_row_start[8] = {0, 0, 4, 0, 2, 0, 1}; -static unsigned int interlace_row_step[8] = {8, 8, 8, 4, 4, 2, 2}; - -void row_callback(png_structp png, png_bytep new_row, - png_uint_32 row_num, int pass) +static void row_callback(png_structp png_s, png_bytep new_row, + png_uint_32 row_num, int pass) { - nspng_content *c = png_get_progressive_ptr(png); - unsigned long i, j, rowbytes = c->rowbytes; - unsigned int start, step; + nspng_content *png_c = png_get_progressive_ptr(png_s); + unsigned long rowbytes = png_c->rowbytes; unsigned char *buffer, *row; /* Give up if there's no bitmap */ - if (c->bitmap == NULL) + if (png_c->bitmap == NULL) return; /* Abort if we've not got any data */ @@ -337,31 +154,35 @@ void row_callback(png_structp png, png_bytep new_row, return; /* Get bitmap buffer */ - buffer = bitmap_get_buffer(c->bitmap); + buffer = bitmap_get_buffer(png_c->bitmap); if (buffer == NULL) { /* No buffer, bail out */ - longjmp(png_jmpbuf(png), 1); + longjmp(png_jmpbuf(png_s), 1); } /* Calculate address of row start */ - row = buffer + (c->rowstride * row_num); + row = buffer + (png_c->rowstride * row_num); /* Handle interlaced sprites using the Adam7 algorithm */ - if (c->interlace) { + if (png_c->interlace) { + unsigned long dst_off; + unsigned long src_off = 0; + unsigned int start, step; + start = interlace_start[pass]; step = interlace_step[pass]; row_num = interlace_row_start[pass] + - interlace_row_step[pass] * row_num; + interlace_row_step[pass] * row_num; /* Copy the data to our current row taking interlacing * into consideration */ - row = buffer + (c->rowstride * row_num); + row = buffer + (png_c->rowstride * row_num); - for (j = 0, i = start; i < rowbytes; i += step) { - row[i++] = new_row[j++]; - row[i++] = new_row[j++]; - row[i++] = new_row[j++]; - row[i++] = new_row[j++]; + for (dst_off = start; dst_off < rowbytes; dst_off += step) { + row[dst_off++] = new_row[src_off++]; + row[dst_off++] = new_row[src_off++]; + row[dst_off++] = new_row[src_off++]; + row[dst_off++] = new_row[src_off++]; } } else { /* Do a fast memcpy of the row data */ @@ -370,23 +191,117 @@ void row_callback(png_structp png, png_bytep new_row, } -void end_callback(png_structp png, png_infop info) +static void end_callback(png_structp png_s, png_infop info) { } +static nserror nspng_create_png_data(nspng_content *png_c) +{ + union content_msg_data msg_data; + + png_c->bitmap = NULL; + + png_c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); + if (png_c->png == NULL) { + msg_data.error = messages_get("NoMemory"); + content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return NSERROR_NOMEM; + } + + png_c->info = png_create_info_struct(png_c->png); + if (png_c->info == NULL) { + png_destroy_read_struct(&png_c->png, &png_c->info, 0); + + msg_data.error = messages_get("NoMemory"); + content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data); + warn_user("NoMemory", 0); + return NSERROR_NOMEM; + } + + if (setjmp(png_jmpbuf(png_c->png))) { + png_destroy_read_struct(&png_c->png, &png_c->info, 0); + LOG(("Failed to set callbacks")); + png_c->png = NULL; + png_c->info = NULL; + + msg_data.error = messages_get("PNGError"); + content_broadcast(&png_c->base, CONTENT_MSG_ERROR, msg_data); + return NSERROR_NOMEM; + } + + png_set_progressive_read_fn(png_c->png, png_c, + info_callback, row_callback, end_callback); + + return NSERROR_OK; +} + +static nserror nspng_create(const content_handler *handler, + lwc_string *imime_type, const http_parameter *params, + llcache_handle *llcache, const char *fallback_charset, + bool quirks, struct content **c) +{ + nspng_content *png_c; + nserror error; + + png_c = talloc_zero(0, nspng_content); + if (png_c == NULL) + return NSERROR_NOMEM; + + error = content__init(&png_c->base, handler, imime_type, params, + llcache, fallback_charset, quirks); + if (error != NSERROR_OK) { + talloc_free(png_c); + return error; + } + + error = nspng_create_png_data(png_c); + if (error != NSERROR_OK) { + talloc_free(png_c); + return error; + } + + *c = (struct content *)png_c; + + return NSERROR_OK; +} -bool nspng_convert(struct content *c) +static bool nspng_process_data(struct content *c, const char *data, + unsigned int size) { - nspng_content *png = (nspng_content *) c; - const char *data; - unsigned long size; + nspng_content *png_c = (nspng_content *)c; + union content_msg_data msg_data; + + if (setjmp(png_jmpbuf(png_c->png))) { + png_destroy_read_struct(&png_c->png, &png_c->info, 0); + LOG(("Failed to process data")); + png_c->png = NULL; + png_c->info = NULL; + if (png_c->bitmap != NULL) { + bitmap_destroy(png_c->bitmap); + png_c->bitmap = NULL; + } + + msg_data.error = messages_get("PNGError"); + content_broadcast(c, CONTENT_MSG_ERROR, msg_data); + return false; + } + + png_process_data(png_c->png, png_c->info, (uint8_t *)data, size); + + return true; +} + +static bool nspng_convert(struct content *c) +{ + nspng_content *png_c = (nspng_content *) c; char title[100]; - assert(png->png != NULL); - assert(png->info != NULL); + assert(png_c->png != NULL); + assert(png_c->info != NULL); - if (png->bitmap == NULL) { + if (png_c->bitmap == NULL) { union content_msg_data msg_data; msg_data.error = messages_get("PNGError"); @@ -395,19 +310,19 @@ bool nspng_convert(struct content *c) return false; } - data = content__get_source_data(c, &size); + /* clean up png structures */ + png_destroy_read_struct(&png_c->png, &png_c->info, 0); - png_destroy_read_struct(&png->png, &png->info, 0); + c->size += (c->width * c->height * 4); + /* set title text */ snprintf(title, sizeof(title), messages_get("PNGTitle"), - c->width, c->height, size); + c->width, c->height, c->size); content__set_title(c, title); - c->size += (c->width * c->height * 4); + bitmap_set_opaque(png_c->bitmap, bitmap_test_opaque(png_c->bitmap)); + bitmap_modified(png_c->bitmap); - c->bitmap = png->bitmap; - bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap)); - bitmap_modified(c->bitmap); content_set_ready(c); content_set_done(c); content_set_status(c, ""); @@ -416,92 +331,153 @@ bool nspng_convert(struct content *c) } -void nspng_destroy(struct content *c) +static void nspng_destroy(struct content *c) { - nspng_content *png = (nspng_content *) c; + nspng_content *png_c = (nspng_content *) c; - if (png->bitmap != NULL) { - bitmap_destroy(png->bitmap); + if (png_c->bitmap != NULL) { + bitmap_destroy(png_c->bitmap); } } -bool nspng_redraw(struct content *c, int x, int y, - int width, int height, const struct rect *clip, - float scale, colour background_colour) +static bool nspng_redraw(struct content *c, int x, int y, + int width, int height, const struct rect *clip, + float scale, colour background_colour) { - assert(c->bitmap != NULL); + nspng_content *png_c = (nspng_content *) c; - return plot.bitmap(x, y, width, height, c->bitmap, - background_colour, BITMAPF_NONE); + assert(png_c->bitmap != NULL); + + return plot.bitmap(x, y, width, height, png_c->bitmap, + background_colour, BITMAPF_NONE); } -bool nspng_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 bool nspng_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) { + nspng_content *png_c = (nspng_content *) c; bitmap_flags_t flags = 0; - assert(c->bitmap != NULL); + assert(png_c->bitmap != NULL); if (repeat_x) flags |= BITMAPF_REPEAT_X; if (repeat_y) flags |= BITMAPF_REPEAT_Y; - return plot.bitmap(x, y, width, height, c->bitmap, - background_colour, flags); + return plot.bitmap(x, y, width, height, + png_c->bitmap, background_colour, flags); } -nserror nspng_clone(const struct content *old, struct content **newc) +static nserror nspng_clone(const struct content *old_c, struct content **new_c) { - nspng_content *png; + nspng_content *clone_png_c; nserror error; const char *data; unsigned long size; - png = talloc_zero(0, nspng_content); - if (png == NULL) + clone_png_c = talloc_zero(0, nspng_content); + if (clone_png_c == NULL) return NSERROR_NOMEM; - error = content__clone(old, &png->base); + error = content__clone(old_c, &clone_png_c->base); if (error != NSERROR_OK) { - content_destroy(&png->base); + content_destroy(&clone_png_c->base); return error; } /* Simply replay create/process/convert */ - error = nspng_create_png_data(png); + error = nspng_create_png_data(clone_png_c); if (error != NSERROR_OK) { - content_destroy(&png->base); + content_destroy(&clone_png_c->base); return error; } - data = content__get_source_data(&png->base, &size); + data = content__get_source_data(&clone_png_c->base, &size); if (size > 0) { - if (nspng_process_data(&png->base, data, size) == false) { - content_destroy(&png->base); + if (nspng_process_data(&clone_png_c->base, data, size) == false) { + content_destroy(&clone_png_c->base); return NSERROR_NOMEM; } } - if (old->status == CONTENT_STATUS_READY || - old->status == CONTENT_STATUS_DONE) { - if (nspng_convert(&png->base) == false) { - content_destroy(&png->base); + if ((old_c->status == CONTENT_STATUS_READY) || + (old_c->status == CONTENT_STATUS_DONE)) { + if (nspng_convert(&clone_png_c->base) == false) { + content_destroy(&clone_png_c->base); return NSERROR_CLONE_FAILED; } } - *newc = (struct content *) png; + *new_c = (struct content *)clone_png_c; return NSERROR_OK; } -content_type nspng_content_type(lwc_string *mime_type) +static content_type nspng_content_type(lwc_string *mime_type) { return CONTENT_IMAGE; } +static const content_handler nspng_content_handler = { + nspng_create, + nspng_process_data, + nspng_convert, + NULL, + nspng_destroy, + NULL, + NULL, + NULL, + nspng_redraw, + nspng_redraw_tiled, + NULL, + NULL, + nspng_clone, + NULL, + nspng_content_type, + false +}; + +nserror nspng_init(void) +{ + uint32_t i; + lwc_error lerror; + nserror error; + + for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) { + lerror = lwc_intern_string(nspng_types[i], + strlen(nspng_types[i]), + &nspng_mime_types[i]); + if (lerror != lwc_error_ok) { + error = NSERROR_NOMEM; + goto error; + } + + error = content_factory_register_handler(nspng_mime_types[i], + &nspng_content_handler); + if (error != NSERROR_OK) + goto error; + } + + return NSERROR_OK; + +error: + nspng_fini(); + + return error; +} + +void nspng_fini(void) +{ + uint32_t i; + + for (i = 0; i < NOF_ELEMENTS(nspng_mime_types); i++) { + if (nspng_mime_types[i] != NULL) + lwc_string_unref(nspng_mime_types[i]); + } +} + #endif -- cgit v1.2.3