From 3a7fc30a5f1c0945c021abf185274e88f72e7080 Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Wed, 13 May 2020 19:03:14 +0100 Subject: implement content opacity check through the function table --- content/content.c | 15 +++------------ content/content_protected.h | 11 ++++++++++- content/handlers/image/bmp.c | 11 +++++++++++ content/handlers/image/gif.c | 14 ++++++++++++++ content/handlers/image/ico.c | 32 ++++++++++++++++++++++++++++++-- content/handlers/image/image_cache.c | 11 +++++++++++ content/handlers/image/image_cache.h | 5 ++++- content/handlers/image/jpeg.c | 1 + content/handlers/image/nssprite.c | 12 ++++++++++++ content/handlers/image/png.c | 1 + content/handlers/image/rsvg.c | 14 ++++++++++++++ content/handlers/image/webp.c | 1 + frontends/amiga/icon.c | 13 +++++++++++++ 13 files changed, 125 insertions(+), 16 deletions(-) diff --git a/content/content.c b/content/content.c index bc3f48429..f72f3d434 100644 --- a/content/content.c +++ b/content/content.c @@ -33,7 +33,6 @@ #include "netsurf/bitmap.h" #include "netsurf/content.h" #include "desktop/knockout.h" -#include "desktop/gui_internal.h" #include "content/content_protected.h" #include "content/textsearch.h" @@ -1294,21 +1293,13 @@ bool content_get_opaque(hlcache_handle *h) /* exported interface documented in content/content_protected.h */ bool content__get_opaque(struct content *c) { - bool opaque = false; - if ((c != NULL) && (c->handler != NULL) && - (c->handler->type != NULL) && - (c->handler->type() == CONTENT_IMAGE) && - (c->handler->get_internal != NULL) ) { - struct bitmap *bitmap = NULL; - bitmap = c->handler->get_internal(c, NULL); - if (bitmap != NULL) { - opaque = guit->bitmap->get_opaque(bitmap); - } + (c->handler->is_opaque != NULL)) { + return c->handler->is_opaque(c); } - return opaque; + return false; } diff --git a/content/content_protected.h b/content/content_protected.h index 667f5ba7b..881a43268 100644 --- a/content/content_protected.h +++ b/content/content_protected.h @@ -119,7 +119,16 @@ struct content_handler { /** * handler dependant content sensitive internal data interface. */ - void * (*get_internal)(const struct content *c, void *context); + void *(*get_internal)(const struct content *c, void *context); + + /** + * are the content contents opaque. + * + * Determine if this content would obscure (not mix with) any background + * + * \param c The content to check + */ + bool (*is_opaque)(struct content *c); /** * There must be one content per user for this type. diff --git a/content/handlers/image/bmp.c b/content/handlers/image/bmp.c index a1a6ce686..a723022fe 100644 --- a/content/handlers/image/bmp.c +++ b/content/handlers/image/bmp.c @@ -264,6 +264,16 @@ static content_type nsbmp_content_type(void) return CONTENT_IMAGE; } +static bool nsbmp_content_is_opaque(struct content *c) +{ + nsbmp_content *bmp = (nsbmp_content *)c; + + if (bmp->bitmap != NULL) { + return guit->bitmap->get_opaque(bmp->bitmap); + } + + return false; +} static const content_handler nsbmp_content_handler = { .create = nsbmp_create, @@ -273,6 +283,7 @@ static const content_handler nsbmp_content_handler = { .clone = nsbmp_clone, .get_internal = nsbmp_get_internal, .type = nsbmp_content_type, + .is_opaque = nsbmp_content_is_opaque, .no_share = false, }; diff --git a/content/handlers/image/gif.c b/content/handlers/image/gif.c index 6ef4fa7e7..e2a0ca5db 100644 --- a/content/handlers/image/gif.c +++ b/content/handlers/image/gif.c @@ -416,6 +416,19 @@ static content_type nsgif_content_type(void) return CONTENT_IMAGE; } +static bool nsgif_content_is_opaque(struct content *c) +{ + nsgif_content *gif = (nsgif_content *) c; + + if (gif->current_frame != gif->gif->decoded_frame) { + if (nsgif_get_frame(gif) != GIF_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, @@ -426,6 +439,7 @@ static const content_handler nsgif_content_handler = { .remove_user = nsgif_remove_user, .get_internal = nsgif_get_internal, .type = nsgif_content_type, + .is_opaque = nsgif_content_is_opaque, .no_share = false, }; diff --git a/content/handlers/image/ico.c b/content/handlers/image/ico.c index 312127869..2d839b1d1 100644 --- a/content/handlers/image/ico.c +++ b/content/handlers/image/ico.c @@ -84,7 +84,7 @@ static nserror nsico_create_ico_data(nsico_content *c) } -static nserror nsico_create(const content_handler *handler, +static nserror nsico_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) @@ -251,7 +251,7 @@ static void *nsico_get_internal(const struct content *c, void *context) nsico_content *ico = (nsico_content *) c; /* TODO: Pick best size for purpose. * Currently assumes it's for a URL bar. */ - struct bmp_image *bmp; + struct bmp_image *bmp; bmp = ico_find(ico->ico, 16, 16); if (bmp == NULL) { @@ -276,6 +276,33 @@ static content_type nsico_content_type(void) return CONTENT_IMAGE; } +static bool nsico_is_opaque(struct content *c) +{ + nsico_content *ico = (nsico_content *) c; + struct bmp_image *bmp; + + /** + * \todo Pick best size for purpose. Currently assumes + * it's for a URL bar. + */ + bmp = ico_find(ico->ico, 16, 16); + if (bmp == NULL) { + /* return error */ + NSLOG(netsurf, INFO, "Failed to select icon"); + return false; + } + + if (bmp->decoded == false) { + if (bmp_decode(bmp) != BMP_OK) { + return false; + } + + guit->bitmap->modified(bmp->bitmap); + } + + return guit->bitmap->get_opaque(bmp->bitmap); +} + static const content_handler nsico_content_handler = { .create = nsico_create, .data_complete = nsico_convert, @@ -284,6 +311,7 @@ static const content_handler nsico_content_handler = { .clone = nsico_clone, .get_internal = nsico_get_internal, .type = nsico_content_type, + .is_opaque = nsico_is_opaque, .no_share = false, }; diff --git a/content/handlers/image/image_cache.c b/content/handlers/image/image_cache.c index a1de01da5..bc0b91408 100644 --- a/content/handlers/image/image_cache.c +++ b/content/handlers/image/image_cache.c @@ -858,6 +858,17 @@ void *image_cache_get_internal(const struct content *c, void *context) return image_cache_get_bitmap(c); } +/* exported interface documented in image_cache.h */ +bool image_cache_is_opaque(struct content *c) +{ + struct bitmap *bmp; + bmp = image_cache_get_bitmap(c); + if (bmp != NULL) { + return guit->bitmap->get_opaque(bmp); + } + return false; +} + /* exported interface documented in image_cache.h */ content_type image_cache_content_type(void) { diff --git a/content/handlers/image/image_cache.h b/content/handlers/image/image_cache.h index d57a3a956..955306e1b 100644 --- a/content/handlers/image/image_cache.h +++ b/content/handlers/image/image_cache.h @@ -170,7 +170,8 @@ int image_cache_snsummaryf(char *string, size_t size, const char *fmt); /********* Image content handler generic cache callbacks ************/ -/** Generic content redraw callback +/** + * Generic content redraw callback * * May be used by image content handlers as their redraw * callback. Performs all neccissary cache lookups and conversions and @@ -185,6 +186,8 @@ void image_cache_destroy(struct content *c); void *image_cache_get_internal(const struct content *c, void *context); +bool image_cache_is_opaque(struct content *c); + content_type image_cache_content_type(void); #endif diff --git a/content/handlers/image/jpeg.c b/content/handlers/image/jpeg.c index 09e68fd29..549c2b674 100644 --- a/content/handlers/image/jpeg.c +++ b/content/handlers/image/jpeg.c @@ -414,6 +414,7 @@ static const content_handler nsjpeg_content_handler = { .clone = nsjpeg_clone, .get_internal = image_cache_get_internal, .type = image_cache_content_type, + .is_opaque = image_cache_is_opaque, .no_share = false, }; diff --git a/content/handlers/image/nssprite.c b/content/handlers/image/nssprite.c index f0114ee89..a4ce6b574 100644 --- a/content/handlers/image/nssprite.c +++ b/content/handlers/image/nssprite.c @@ -258,6 +258,17 @@ static content_type nssprite_content_type(void) } +static bool nssprite_content_is_opaque(struct content *c) +{ + nssprite_content *nssprite = (nssprite_content *) c; + + if (nssprite->bitmap != NULL) { + return guit->bitmap->get_opaque(nssprite->bitmap); + } + + return false; +} + static const content_handler nssprite_content_handler = { .create = nssprite_create, .data_complete = nssprite_convert, @@ -266,6 +277,7 @@ static const content_handler nssprite_content_handler = { .clone = nssprite_clone, .get_internal = nssprite_get_internal, .type = nssprite_content_type, + .is_opaque = nssprite_content_is_opaque, .no_share = false, }; diff --git a/content/handlers/image/png.c b/content/handlers/image/png.c index 1fa707d35..4926d9a27 100644 --- a/content/handlers/image/png.c +++ b/content/handlers/image/png.c @@ -602,6 +602,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, }; diff --git a/content/handlers/image/rsvg.c b/content/handlers/image/rsvg.c index 5cf900dac..0051df38f 100644 --- a/content/handlers/image/rsvg.c +++ b/content/handlers/image/rsvg.c @@ -316,6 +316,19 @@ static content_type rsvg_content_type(void) return CONTENT_IMAGE; } + +static bool rsvg_content_is_opaque(struct content *c) +{ + rsvg_content *d = (rsvg_content *) c; + + if (d->bitmap != NULL) { + return guit->bitmap->get_opaque(d->bitmap); + } + + return false; +} + + static const content_handler rsvg_content_handler = { .create = rsvg_create, .process_data = rsvg_process_data, @@ -325,6 +338,7 @@ static const content_handler rsvg_content_handler = { .clone = rsvg_clone, .get_internal = rsvg_get_internal, .type = rsvg_content_type, + .is_opaque = rsvg_content_is_opaque, .no_share = false, }; diff --git a/content/handlers/image/webp.c b/content/handlers/image/webp.c index 8450fb161..721e92438 100644 --- a/content/handlers/image/webp.c +++ b/content/handlers/image/webp.c @@ -225,6 +225,7 @@ static const content_handler webp_content_handler = { .clone = webp_clone, .get_internal = image_cache_get_internal, .type = image_cache_content_type, + .is_opaque = image_cache_is_opaque, .no_share = false, }; diff --git a/frontends/amiga/icon.c b/frontends/amiga/icon.c index 353ba9196..001874c86 100644 --- a/frontends/amiga/icon.c +++ b/frontends/amiga/icon.c @@ -48,6 +48,7 @@ #include "content/content.h" #include "content/content_protected.h" #include "content/content_factory.h" +#include "desktop/gui_internal.h" #include "amiga/os3support.h" #include "amiga/bitmap.h" @@ -87,6 +88,17 @@ static void *amiga_icon_get_internal(const struct content *c, void *context) return icon_c->bitmap; } +static bool amiga_icon_is_opaque(struct content *c) +{ + amiga_icon_content *icon_c = (amiga_icon_content *)c; + + if (icon_c->bitmap != NULL) { + return guit->bitmap->get_opaque(icon_c->bitmap); + } + + return false; +} + static const content_handler amiga_icon_content_handler = { .create = amiga_icon_create, .data_complete = amiga_icon_convert, @@ -95,6 +107,7 @@ static const content_handler amiga_icon_content_handler = { .clone = amiga_icon_clone, .get_internal = amiga_icon_get_internal, .type = amiga_icon_content_type, + .is_opaque = amiga_icon_is_opaque, .no_share = false, }; -- cgit v1.2.3