diff options
Diffstat (limited to 'content/handlers/image/png.c')
-rw-r--r-- | content/handlers/image/png.c | 74 |
1 files changed, 59 insertions, 15 deletions
diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c index 7a4ce3010..97a5795b3 100644 --- a/content/handlers/image/png.c +++ b/content/handlers/image/png.c @@ -19,6 +19,7 @@ */ #include <stdbool.h> +#include <string.h> #include <stdlib.h> #include <png.h> @@ -29,7 +30,9 @@ #include "netsurf/bitmap.h" #include "content/llcache.h" #include "content/content_protected.h" +#include "content/content_factory.h" #include "desktop/gui_internal.h" +#include "desktop/bitmap.h" #include "image/image_cache.h" #include "image/png.h" @@ -116,8 +119,37 @@ static void nspng_setup_transforms(png_structp png_ptr, png_infop info_ptr) png_set_gray_to_rgb(png_ptr); } + switch (bitmap_fmt.layout) { + case BITMAP_LAYOUT_B8G8R8A8: /* Fall through. */ + case BITMAP_LAYOUT_A8B8G8R8: + png_set_bgr(png_ptr); + break; + default: + /* RGB is the default. */ + break; + } + if (!(color_type & PNG_COLOR_MASK_ALPHA)) { - png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + switch (bitmap_fmt.layout) { + case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */ + case BITMAP_LAYOUT_A8B8G8R8: + png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE); + break; + + default: + png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER); + break; + } + } else { + switch (bitmap_fmt.layout) { + case BITMAP_LAYOUT_A8R8G8B8: /* Fall through. */ + case BITMAP_LAYOUT_A8B8G8R8: + png_set_swap_alpha(png_ptr); + break; + default: + /* Alpha as final component is the default. */ + break; + } } /* gamma correction - we use 2.2 as our screen gamma @@ -161,14 +193,14 @@ static void info_callback(png_structp png_s, png_infop info) } /* Claim the required memory for the converted PNG */ - png_c->bitmap = guit->bitmap->create(width, height, BITMAP_NEW); + png_c->bitmap = guit->bitmap->create(width, height, BITMAP_NONE); if (png_c->bitmap == NULL) { /* Failed to create bitmap skip pre-conversion */ longjmp(png_jmpbuf(png_s), CBERR_NOPRE); } png_c->rowstride = guit->bitmap->get_rowstride(png_c->bitmap); - png_c->bpp = guit->bitmap->get_bpp(png_c->bitmap); + png_c->bpp = sizeof(uint32_t); nspng_setup_transforms(png_s, info); @@ -242,7 +274,7 @@ static nserror nspng_create_png_data(nspng_content *png_c) png_c->png = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0); if (png_c->png == NULL) { - content_broadcast_errorcode(&png_c->base, NSERROR_NOMEM); + content_broadcast_error(&png_c->base, NSERROR_NOMEM, NULL); return NSERROR_NOMEM; } @@ -252,7 +284,7 @@ static nserror nspng_create_png_data(nspng_content *png_c) if (png_c->info == NULL) { png_destroy_read_struct(&png_c->png, &png_c->info, 0); - content_broadcast_errorcode(&png_c->base, NSERROR_NOMEM); + content_broadcast_error(&png_c->base, NSERROR_NOMEM, NULL); return NSERROR_NOMEM; } @@ -262,7 +294,7 @@ static nserror nspng_create_png_data(nspng_content *png_c) png_c->png = NULL; png_c->info = NULL; - content_broadcast_errorcode(&png_c->base, NSERROR_PNG_ERROR); + content_broadcast_error(&png_c->base, NSERROR_PNG_ERROR, NULL); return NSERROR_NOMEM; } @@ -355,7 +387,7 @@ static bool nspng_process_data(struct content *c, const char *data, png_c->png = NULL; png_c->info = NULL; - content_broadcast_errorcode(c, NSERROR_PNG_ERROR); + content_broadcast_error(c, NSERROR_PNG_ERROR, NULL); ret = false; @@ -367,8 +399,8 @@ static bool nspng_process_data(struct content *c, const char *data, } struct png_cache_read_data_s { - const char *data; - unsigned long size; + const uint8_t *data; + size_t size; }; /** PNG library read fucntion to read data from a memory array @@ -481,7 +513,7 @@ png_cache_convert(struct content *c) height = png_get_image_height(png_ptr, info_ptr); /* Claim the required memory for the converted PNG */ - bitmap = guit->bitmap->create(width, height, BITMAP_NEW); + bitmap = guit->bitmap->create(width, height, BITMAP_NONE); if (bitmap == NULL) { /* cleanup and bail */ goto png_cache_convert_error; @@ -506,7 +538,13 @@ png_cache_convert_error: } if (bitmap != NULL) { - guit->bitmap->modified((struct bitmap *)bitmap); + bool opaque = bitmap_test_opaque((void *)bitmap); + guit->bitmap->set_opaque((void *)bitmap, opaque); + bitmap_format_to_client((void *)bitmap, &(bitmap_fmt_t) { + .layout = bitmap_fmt.layout, + .pma = opaque ? bitmap_fmt.pma : false, + }); + guit->bitmap->modified((void *)bitmap); } return (struct bitmap *)bitmap; @@ -533,7 +571,12 @@ static bool nspng_convert(struct content *c) } if (png_c->bitmap != NULL) { - guit->bitmap->set_opaque(png_c->bitmap, guit->bitmap->test_opaque(png_c->bitmap)); + bool opaque = bitmap_test_opaque(png_c->bitmap); + guit->bitmap->set_opaque(png_c->bitmap, opaque); + bitmap_format_to_client(png_c->bitmap, &(bitmap_fmt_t) { + .layout = bitmap_fmt.layout, + .pma = opaque ? bitmap_fmt.pma : false, + }); guit->bitmap->modified(png_c->bitmap); } @@ -551,8 +594,8 @@ static nserror nspng_clone(const struct content *old_c, struct content **new_c) { nspng_content *clone_png_c; nserror error; - const char *data; - unsigned long size; + const uint8_t *data; + size_t size; clone_png_c = calloc(1, sizeof(nspng_content)); if (clone_png_c == NULL) @@ -573,7 +616,7 @@ static nserror nspng_clone(const struct content *old_c, struct content **new_c) data = content__get_source_data(&clone_png_c->base, &size); if (size > 0) { - if (nspng_process_data(&clone_png_c->base, data, size) == false) { + if (nspng_process_data(&clone_png_c->base, (const char *)data, size) == false) { content_destroy(&clone_png_c->base); return NSERROR_NOMEM; } @@ -601,6 +644,7 @@ static const content_handler nspng_content_handler = { .redraw = image_cache_redraw, .get_internal = image_cache_get_internal, .type = image_cache_content_type, + .is_opaque = image_cache_is_opaque, .no_share = false, }; |