This removes the bitmap entry from the generic content structure and
moves it into individual image handlers.

I think I found all the references but I may have missed some in a
frontend, please check

This is the last refactor step before altering the image handlers to
using a global bitmap cache.

I am unsure if adding the get_internal content method was the right
thing to do but as several places still use content_get_bitmap to
extract the underlying bitmap I thought a generic interface with
context allows for future use.

Comments or suggestions welcome.

 amiga/dt_anim.c             |   27 ++++++++++++++--------
 amiga/dt_picture.c          |   38 +++++++++++++++++++++---------
 amiga/icon.c                |   38 +++++++++++++++++++++---------
 cocoa/apple_image.m         |   23 +++++++++++++++---
 content/content.c           |   54 ++++++++++++++++++++++++++++++++++++++++----
 content/content.h           |    1 
 content/content_protected.h |   10 ++++----
 image/bmp.c                 |   18 +++++++++++---
 image/gif.c                 |   18 +++++++++++---
 image/ico.c                 |   18 +++++++++++---
 image/jpeg.c                |   22 ++++++++++++++---
 image/mng.c                 |   47 ++++++++++++++++++++++++--------------
 image/nssprite.c            |   33 +++++++++++++++++---------
 image/png.c                 |   10 ++++++--
 image/rsvg.c                |   16 +++++++++----
 image/webp.c                |   30 +++++++++++++++++-------
 render/html_redraw.c        |   41 +++++++++++++++------------------
 17 files changed, 319 insertions(+), 125 deletions(-)

-- 
Regards Vincent
http://www.kyllikki.org/
Index: render/html_redraw.c
===================================================================
--- render/html_redraw.c	(revision 12682)
+++ render/html_redraw.c	(working copy)
@@ -2060,24 +2060,23 @@
 		/* handle background-repeat */
 		switch (css_computed_background_repeat(background->style)) {
 		case CSS_BACKGROUND_REPEAT_REPEAT:
-		{
-			struct bitmap *bmp = content_get_bitmap(
-					background->background);
 			repeat_x = repeat_y = true;
 			/* optimisation: only plot the colour if
 			 * bitmap is not opaque */
-			if (bmp != NULL)
-				plot_colour = !bitmap_get_opaque(bmp);
-		}
+			plot_colour = !content_get_opaque(box->background);
 			break;
+
 		case CSS_BACKGROUND_REPEAT_REPEAT_X:
 			repeat_x = true;
 			break;
+
 		case CSS_BACKGROUND_REPEAT_REPEAT_Y:
 			repeat_y = true;
 			break;
+
 		case CSS_BACKGROUND_REPEAT_NO_REPEAT:
 			break;
+
 		default:
 			break;
 		}
@@ -2126,8 +2125,6 @@
 	for (; clip_box; clip_box = clip_box->next) {
 		/* clip to child boxes if needed */
 		if (clip_to_children) {
-			struct bitmap *bmp = NULL;
-
 			assert(clip_box->type == BOX_TABLE_CELL);
 
 			/* update clip.* to the child cell */
@@ -2145,16 +2142,16 @@
 			if (r.x1 > clip->x1) r.x1 = clip->x1;
 			if (r.y1 > clip->y1) r.y1 = clip->y1;
 
-			if (clip_box->background != NULL)
-				bmp = content_get_bitmap(clip_box->background);
-
 			css_computed_background_color(clip_box->style, &bgcol);
 
 			/* <td> attributes override <tr> */
-			if ((r.x0 >= r.x1) || (r.y0 >= r.y1) ||
-					(nscss_color_is_transparent(bgcol) ==
-						false) ||
-					(bmp != NULL && bitmap_get_opaque(bmp)))
+			/* if the background content is opaque there
+			 * is no need to plot underneath it.
+			 */
+			if ((r.x0 >= r.x1) || 
+			    (r.y0 >= r.y1) ||
+			    (nscss_color_is_transparent(bgcol) == false) ||
+			    content_get_opaque(clip_box->background))
 				continue;
 		}
 
@@ -2259,24 +2256,24 @@
 		/* handle background-repeat */
 		switch (css_computed_background_repeat(box->style)) {
 		case CSS_BACKGROUND_REPEAT_REPEAT:
-		{
-			struct bitmap *bmp = 
-					content_get_bitmap(box->background);
 			repeat_x = repeat_y = true;
 			/* optimisation: only plot the colour if
-			 * bitmap is not opaque */
-			if (bmp != NULL)
-				plot_colour = !bitmap_get_opaque(bmp);
-		}
+			 * bitmap is not opaque 
+			 */
+			plot_colour = !content_get_opaque(box->background);
 			break;
+
 		case CSS_BACKGROUND_REPEAT_REPEAT_X:
 			repeat_x = true;
 			break;
+
 		case CSS_BACKGROUND_REPEAT_REPEAT_Y:
 			repeat_y = true;
 			break;
+
 		case CSS_BACKGROUND_REPEAT_NO_REPEAT:
 			break;
+
 		default:
 			break;
 		}
Index: image/gif.c
===================================================================
--- image/gif.c	(revision 12682)
+++ image/gif.c	(working copy)
@@ -51,6 +51,7 @@
 
 	struct gif_animation *gif; /**< GIF animation data */
 	int current_frame;	   /**< current frame to display [0...(max-1)] */
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } nsgif_content;
 
 
@@ -297,9 +298,11 @@
 				nsgif_invalidate);
 
 	/* Exit as a success */
-	c->bitmap = gif->gif->frame_image;
+	gif->bitmap = gif->gif->frame_image;
+
 	content_set_ready(c);
 	content_set_done(c);
+
 	/* Done: update status bar */
 	content_set_status(c, "");
 	return true;
@@ -340,7 +343,7 @@
 		if (nsgif_get_frame(c) != GIF_OK)
 			return false;
 
-	c->bitmap = gif->gif->frame_image;
+	gif->bitmap = gif->gif->frame_image;
 
 	if ((data->width == -1) && (data->height == -1))
 		return true;
@@ -351,7 +354,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			gif->bitmap, data->background_colour, flags);
 }
 
 
@@ -401,18 +404,25 @@
 	return NSERROR_OK;
 }
 
+static void *nsgif_get_internal(const struct content *c, void *context)
+{
+	nsgif_content *gif = (nsgif_content *) c;
+
+	return gif->bitmap;
+}
+
 static content_type nsgif_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
 }
 
-
 static const content_handler nsgif_content_handler = {
 	.create = nsgif_create,
 	.data_complete = nsgif_convert,
 	.destroy = nsgif_destroy,
 	.redraw = nsgif_redraw,
 	.clone = nsgif_clone,
+	.get_internal = nsgif_get_internal,
 	.type = nsgif_content_type,
 	.no_share = false,
 };
Index: image/nssprite.c
===================================================================
--- image/nssprite.c	(revision 12682)
+++ image/nssprite.c	(working copy)
@@ -37,6 +37,7 @@
 
 typedef struct nssprite_content {
 	struct content base;
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 
 	struct rosprite_area* sprite_area;
 } nssprite_content;
@@ -112,19 +113,19 @@
 
 	struct rosprite* sprite = sprite_area->sprites[0];
 
-	c->bitmap = bitmap_create(sprite->width, sprite->height, BITMAP_NEW);
-	if (!c->bitmap) {
+	nssprite->bitmap = bitmap_create(sprite->width, sprite->height, BITMAP_NEW);
+	if (!nssprite->bitmap) {
 		msg_data.error = messages_get("NoMemory");
 		content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
 		return false;
 	}
-	unsigned char* imagebuf = bitmap_get_buffer(c->bitmap);
+	unsigned char* imagebuf = bitmap_get_buffer(nssprite->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);
+	unsigned int row_width = bitmap_get_rowstride(nssprite->bitmap);
 
 	memcpy(imagebuf, sprite->image, row_width * sprite->height); // TODO: avoid copying entire image buffer
 
@@ -145,7 +146,7 @@
 
 	c->width = sprite->width;
 	c->height = sprite->height;
-	bitmap_modified(c->bitmap);
+	bitmap_modified(nssprite->bitmap);
 
 	content_set_ready(c);
 	content_set_done(c);
@@ -160,12 +161,12 @@
 
 static void nssprite_destroy(struct content *c)
 {
-	nssprite_content *sprite = (nssprite_content *) c;
+	nssprite_content *nssprite = (nssprite_content *) c;
 
-	if (sprite->sprite_area != NULL)
-		rosprite_destroy_sprite_area(sprite->sprite_area);
-	if (c->bitmap != NULL)
-		bitmap_destroy(c->bitmap);
+	if (nssprite->sprite_area != NULL)
+		rosprite_destroy_sprite_area(nssprite->sprite_area);
+	if (nssprite->bitmap != NULL)
+		bitmap_destroy(nssprite->bitmap);
 }
 
 
@@ -176,6 +177,7 @@
 static bool nssprite_redraw(struct content *c, struct content_redraw_data *data,
 		const struct rect *clip, const struct redraw_context *ctx)
 {
+	nssprite_content *nssprite = (nssprite_content *) c;
 	bitmap_flags_t flags = BITMAPF_NONE;
 
 	if (data->repeat_x)
@@ -184,7 +186,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			nssprite->bitmap, data->background_colour, flags);
 }
 
 
@@ -217,17 +219,26 @@
 	return NSERROR_OK;
 }
 
+static void *nssprite_get_internal(const struct content *c, void *context)
+{
+	nssprite_content *nssprite = (nssprite_content *) c;
+
+	return nssprite->bitmap;
+}
+
 static content_type nssprite_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
 }
 
+
 static const content_handler nssprite_content_handler = {
 	.create = nssprite_create,
 	.data_complete = nssprite_convert,
 	.destroy = nssprite_destroy,
 	.redraw = nssprite_redraw,
 	.clone = nssprite_clone,
+	.get_internal = nssprite_get_internal,
 	.type = nssprite_content_type,
 	.no_share = false,
 };
Index: image/ico.c
===================================================================
--- image/ico.c	(revision 12682)
+++ image/ico.c	(working copy)
@@ -41,6 +41,8 @@
 	struct content base;
 
 	struct ico_collection *ico;	/** ICO collection data */
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } nsico_content;
 
 
@@ -132,8 +134,8 @@
 	/* exit as a success */
 	bmp = ico_find(ico->ico, 255, 255);
 	assert(bmp);
-	c->bitmap = bmp->bitmap;
-	bitmap_modified(c->bitmap);
+	ico->bitmap = bmp->bitmap;
+	bitmap_modified(ico->bitmap);
 
 	content_set_ready(c);
 	content_set_done(c);
@@ -155,7 +157,7 @@
 		if (bmp_decode(bmp) != BMP_OK)
 			return false;
 
-	c->bitmap = bmp->bitmap;
+	ico->bitmap = bmp->bitmap;
 
 	if (data->repeat_x)
 		flags |= BITMAPF_REPEAT_X;
@@ -163,7 +165,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			ico->bitmap, data->background_colour, flags);
 }
 
 
@@ -210,6 +212,13 @@
 	return NSERROR_OK;
 }
 
+static void *nsico_get_internal(const struct content *c, void *context)
+{
+	nsico_content *ico = (nsico_content *) c;
+
+	return ico->bitmap;
+}
+
 static content_type nsico_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -221,6 +230,7 @@
 	.destroy = nsico_destroy,
 	.redraw = nsico_redraw,
 	.clone = nsico_clone,
+	.get_internal = nsico_get_internal,
 	.type = nsico_content_type,
 	.no_share = false,
 };
Index: image/bmp.c
===================================================================
--- image/bmp.c	(revision 12682)
+++ image/bmp.c	(working copy)
@@ -43,6 +43,8 @@
 	struct content base;
 
 	bmp_image *bmp;	/** BMP image data */
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } nsbmp_content;
 
 static nserror nsbmp_create_bmp_data(nsbmp_content *bmp)
@@ -165,8 +167,8 @@
 	c->size += (swidth * bmp->bmp->height) + 16 + 44;
 
 	/* exit as a success */
-	c->bitmap = bmp->bmp->bitmap;
-	bitmap_modified(c->bitmap);
+	bmp->bitmap = bmp->bmp->bitmap;
+	bitmap_modified(bmp->bitmap);
 
 	content_set_ready(c);
 	content_set_done(c);
@@ -186,7 +188,7 @@
 		if (bmp_decode(bmp->bmp) != BMP_OK)
 			return false;
 
-	c->bitmap = bmp->bmp->bitmap;
+	bmp->bitmap = bmp->bmp->bitmap;
 
 	if (data->repeat_x)
 		flags |= BITMAPF_REPEAT_X;
@@ -194,7 +196,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			bmp->bitmap, data->background_colour, flags);
 }
 
 
@@ -242,6 +244,13 @@
 	return NSERROR_OK;
 }
 
+static void *nsbmp_get_internal(const struct content *c, void *context)
+{
+	nsbmp_content *bmp = (nsbmp_content *)c;
+
+	return bmp->bitmap;
+}
+
 static content_type nsbmp_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -254,6 +263,7 @@
 	.destroy = nsbmp_destroy,
 	.redraw = nsbmp_redraw,
 	.clone = nsbmp_clone,
+	.get_internal = nsbmp_get_internal,
 	.type = nsbmp_content_type,
 	.no_share = false,
 };
Index: image/rsvg.c
===================================================================
--- image/rsvg.c	(revision 12682)
+++ image/rsvg.c	(working copy)
@@ -207,8 +207,7 @@
 				c->width, c->height,
 				bitmap_get_rowstride(d->bitmap));
 
-	c->bitmap = d->bitmap;
-	bitmap_modified(c->bitmap);
+	bitmap_modified(d->bitmap);
 	content_set_ready(c);
 	content_set_done(c);
 	/* Done: update status bar */
@@ -220,9 +219,10 @@
 static bool rsvg_redraw(struct content *c, struct content_redraw_data *data,
 		const struct rect *clip, const struct redraw_context *ctx)
 {
+	rsvg_content *rsvgcontent = (rsvg_content *) c;
 	bitmap_flags_t flags = BITMAPF_NONE;
 
-	assert(c->bitmap != NULL);
+	assert(rsvgcontent->bitmap != NULL);
 
 	if (data->repeat_x)
 		flags |= BITMAPF_REPEAT_X;
@@ -230,7 +230,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height, 
-			c->bitmap, data->background_colour, flags);
+			rsvgcontent->bitmap, data->background_colour, flags);
 }
 
 static void rsvg_destroy(struct content *c)
@@ -290,6 +290,13 @@
 	return NSERROR_OK;
 }
 
+static void *rsvg_get_internal(const struct content *c, void *context)
+{
+	rsvg_content *d = (rsvg_content *) c;
+
+	return d->bitmap;
+}
+
 static content_type rsvg_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -302,6 +309,7 @@
 	.destroy = rsvg_destroy,
 	.redraw = rsvg_redraw,
 	.clone = rsvg_clone,
+	.get_internal = rsvg_get_internal,
 	.type = rsvg_content_type,
 	.no_share = false,
 };
Index: image/mng.c
===================================================================
--- image/mng.c	(revision 12682)
+++ image/mng.c	(working copy)
@@ -53,6 +53,8 @@
 	bool waiting;
 	bool displayed;
 	void *handle;
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } nsmng_content;
 
 
@@ -166,8 +168,8 @@
 	c = (nsmng_content *) mng_get_userdata(mng);
 	assert(c != NULL);
 
-	c->base.bitmap = bitmap_create(width, height, BITMAP_NEW);
-	if (c->base.bitmap == NULL) {
+	c->bitmap = bitmap_create(width, height, BITMAP_NEW);
+	if (c->bitmap == NULL) {
 		msg_data.error = messages_get("NoMemory");
 		content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
 		LOG(("Insufficient memory to create canvas."));
@@ -176,7 +178,7 @@
 
 	/* Get the buffer to ensure that it is allocated and the calls in
 	 * nsmng_getcanvasline() succeed. */
-	buffer = bitmap_get_buffer(c->base.bitmap);
+	buffer = bitmap_get_buffer(c->bitmap);
 	if (buffer == NULL) {
 		msg_data.error = messages_get("NoMemory");
 		content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
@@ -254,8 +256,8 @@
 
 	/*	Calculate the address
 	*/
-	return bitmap_get_buffer(c->base.bitmap) +
-			bitmap_get_rowstride(c->base.bitmap) * line;
+	return bitmap_get_buffer(c->bitmap) +
+			bitmap_get_rowstride(c->bitmap) * line;
 }
 
 static mng_bool nsmng_refresh(mng_handle mng, mng_uint32 x, mng_uint32 y, 
@@ -329,8 +331,8 @@
  		c->waiting = false;
  		mng_display_resume(c->handle);
 		c->opaque_test_pending = true;
-		if (c->base.bitmap)
-			bitmap_modified(c->base.bitmap);
+		if (c->bitmap)
+			bitmap_modified(c->bitmap);
  	}
 }
 
@@ -549,7 +551,7 @@
 	/* 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) {
+	if (mng->bitmap == NULL) {
 		return nsmng_broadcast_error(mng, -1) == NSERROR_OK;
 	}
 
@@ -585,7 +587,7 @@
 		LOG(("Unable to start display (%i)", status));
 		return nsmng_broadcast_error(mng, status) == NSERROR_OK;
 	}
-	bitmap_modified(c->bitmap);
+	bitmap_modified(mng->bitmap);
 
 	/* Optimise the plotting of MNG */
 	mng->opaque_test_pending = false;
@@ -607,7 +609,7 @@
 	/* 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) {
+	if (mng->bitmap == NULL) {
 		return nsmng_broadcast_error(mng, -1) == NSERROR_OK;
 	}
 
@@ -642,12 +644,12 @@
 		LOG(("Unable to start display (%i)", status));
 		return nsmng_broadcast_error(mng, status) == NSERROR_OK;
 	}
-	bitmap_modified(c->bitmap);
+	bitmap_modified(mng->bitmap);
 
 	/*	Optimise the plotting of JNG/PNGs
 	*/
 	mng->opaque_test_pending = true;
-	bitmap_set_opaque(c->bitmap, false);
+	bitmap_set_opaque(mng->bitmap, false);
 
 	/* free associated memory */
 
@@ -678,8 +680,9 @@
 		mng->handle = NULL;
 	}
 
-	if (c->bitmap)
-		bitmap_destroy(c->bitmap);
+	if (mng->bitmap) {
+		bitmap_destroy(mng->bitmap);
+	}
 }
 
 
@@ -693,8 +696,9 @@
 	/* mark image as having been requested to display */
 	mng->displayed = true;
 
-	if ((c->bitmap) && (mng->opaque_test_pending)) {
-		bitmap_set_opaque(c->bitmap, bitmap_test_opaque(c->bitmap));
+	if ((mng->bitmap) && 
+	    (mng->opaque_test_pending)) {
+		bitmap_set_opaque(mng->bitmap, bitmap_test_opaque(mng->bitmap));
 		mng->opaque_test_pending = false;
 	}
 
@@ -704,7 +708,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	ret = ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			mng->bitmap, data->background_colour, flags);
 
 	/* Check if we need to restart the animation */
 	if ((mng->waiting) && (option_animate_images))
@@ -759,6 +763,13 @@
 	return NSERROR_OK;
 }
 
+static void *nsmng_get_internal(const struct content *c, void *context)
+{
+	nsmng_content *mng = (nsmng_content *)c;
+
+	return mng->bitmap;
+}
+
 static content_type nsmng_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -772,6 +783,7 @@
 	.destroy = nsmng_destroy,
 	.redraw = nsmng_redraw,
 	.clone = nsmng_clone,
+	.get_internal = nsmng_get_internal,
 	.type = nsmng_content_type,
 	.no_share = false,
 };
@@ -794,6 +806,7 @@
 	.destroy = nsmng_destroy,
 	.redraw = nsmng_redraw,
 	.clone = nsmng_clone,
+	.get_internal = nsmng_get_internal,
 	.type = nsmng_content_type,
 	.no_share = false,
 };
Index: image/png.c
===================================================================
--- image/png.c	(revision 12682)
+++ image/png.c	(working copy)
@@ -331,8 +331,6 @@
 	bitmap_set_opaque(png_c->bitmap, bitmap_test_opaque(png_c->bitmap));
 	bitmap_modified(png_c->bitmap);
 
-	c->bitmap = png_c->bitmap; /* this needs to go */
-
 	content_set_ready(c);
 	content_set_done(c);
 	content_set_status(c, "");
@@ -413,6 +411,13 @@
 	return NSERROR_OK;
 }
 
+static void *nspng_get_internal(const struct content *c, void *context)
+{
+	nspng_content *png_c = (nspng_content *) c;
+
+	return png_c->bitmap;
+}
+
 static content_type nspng_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -425,6 +430,7 @@
 	.destroy = nspng_destroy,
 	.redraw = nspng_redraw,
 	.clone = nspng_clone,
+	.get_internal = nspng_get_internal,
 	.type = nspng_content_type,
 	.no_share = false,
 };
Index: image/jpeg.c
===================================================================
--- image/jpeg.c	(revision 12682)
+++ image/jpeg.c	(working copy)
@@ -56,6 +56,8 @@
 
 typedef struct nsjpeg_content {
 	struct content base; /**< base content */
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } nsjpeg_content;
 
 struct nsjpeg_error_mgr {
@@ -171,6 +173,7 @@
  */
 static bool nsjpeg_convert(struct content *c)
 {
+	struct nsjpeg_content *jpeg_content = (nsjpeg_content *)c;
 	struct jpeg_decompress_struct cinfo;
 	struct nsjpeg_error_mgr jerr;
 	struct jpeg_source_mgr source_mgr = { 0, 0,
@@ -257,7 +260,7 @@
 
 	c->width = width;
 	c->height = height;
-	c->bitmap = bitmap;
+	jpeg_content->bitmap = bitmap;
 	snprintf(title, sizeof(title), messages_get("JPEGTitle"),
 		 width, height, size);
 	content__set_title(c, title);
@@ -275,8 +278,11 @@
  */
 static void nsjpeg_destroy(struct content *c)
 {
-	if (c->bitmap)
-		bitmap_destroy(c->bitmap);
+	struct nsjpeg_content *jpeg_content = (nsjpeg_content *)c;
+
+	if (jpeg_content->bitmap) {
+		bitmap_destroy(jpeg_content->bitmap);
+	}
 }
 
 
@@ -286,6 +292,7 @@
 static bool nsjpeg_redraw(struct content *c, struct content_redraw_data *data,
 		const struct rect *clip, const struct redraw_context *ctx)
 {
+	struct nsjpeg_content *jpeg_content = (nsjpeg_content *)c;
 	bitmap_flags_t flags = BITMAPF_NONE;
 
 	if (data->repeat_x)
@@ -294,7 +301,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			jpeg_content->bitmap, data->background_colour, flags);
 }
 
 
@@ -331,7 +338,13 @@
 	return NSERROR_OK;
 }
 
+static void *nsjpeg_get_internal(const struct content *c, void *context)
+{
+	nsjpeg_content *jpeg_c = (nsjpeg_content *)c;
 
+	return jpeg_c->bitmap;
+}
+
 static content_type nsjpeg_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -343,6 +356,7 @@
 	.destroy = nsjpeg_destroy,
 	.redraw = nsjpeg_redraw,
 	.clone = nsjpeg_clone,
+	.get_internal = nsjpeg_get_internal,
 	.type = nsjpeg_content_type,
 	.no_share = false,
 };
Index: image/webp.c
===================================================================
--- image/webp.c	(revision 12682)
+++ image/webp.c	(working copy)
@@ -36,6 +36,8 @@
 typedef struct webp_content
 {
 	struct content base;
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } webp_content;
 
 
@@ -71,6 +73,7 @@
 
 static bool webp_convert(struct content *c)
 {
+	webp_content *webp = (webp_content *)c;
 	union content_msg_data msg_data;
 	const uint8_t *data;
 	unsigned char *imagebuf = NULL;
@@ -89,20 +92,20 @@
 		return false;
 	}
 
-	c->bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE);
-	if (!c->bitmap) {
+	webp->bitmap = bitmap_create(width, height, BITMAP_NEW | BITMAP_OPAQUE);
+	if (!webp->bitmap) {
 		msg_data.error = messages_get("NoMemory");
 		content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
 		return false;
 	}
 
-	imagebuf = bitmap_get_buffer(c->bitmap);
+	imagebuf = bitmap_get_buffer(webp->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);
+	unsigned int row_width = bitmap_get_rowstride(webp->bitmap);
 
 	res_p = WebPDecodeRGBAInto(data, size, imagebuf,
 				row_width * height, row_width);
@@ -118,7 +121,7 @@
 		width, height, size);
 	content__set_title(c, title);
 
-	bitmap_modified(c->bitmap);
+	bitmap_modified(webp->bitmap);
 
 	content_set_ready(c);
 	content_set_done(c);
@@ -134,8 +137,10 @@
 
 static void webp_destroy(struct content *c)
 {
-	if (c->bitmap != NULL)
-		bitmap_destroy(c->bitmap);
+	webp_content *webp = (webp_content *)c;
+
+	if (webp->bitmap != NULL)
+		bitmap_destroy(webp->bitmap);
 }
 
 
@@ -146,6 +151,7 @@
 static bool webp_redraw(struct content *c, struct content_redraw_data *data,
 		const struct rect *clip, const struct redraw_context *ctx)
 {
+	webp_content *webp = (webp_content *)c;
 	bitmap_flags_t flags = BITMAPF_NONE;
 
 	if (data->repeat_x)
@@ -154,7 +160,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			webp->bitmap, data->background_colour, flags);
 }
 
 
@@ -187,6 +193,13 @@
 	return NSERROR_OK;
 }
 
+static void *webp_get_internal(const struct content *c, void *context)
+{
+	webp_content *webp = (webp_content *)c;
+
+	return webp->bitmap;
+}
+
 static content_type webp_content_type(lwc_string *mime_type)
 {
 	return CONTENT_IMAGE;
@@ -198,6 +211,7 @@
 	.destroy = webp_destroy,
 	.redraw = webp_redraw,
 	.clone = webp_clone,
+	.get_internal = webp_get_internal,
 	.type = webp_content_type,
 	.no_share = false,
 };
Index: cocoa/apple_image.m
===================================================================
--- cocoa/apple_image.m	(revision 12682)
+++ cocoa/apple_image.m	(working copy)
@@ -30,6 +30,9 @@
 
 typedef struct apple_image_content {
 	struct content base;
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
+
     NSUInteger frames;
     NSUInteger currentFrame;
     int *frameTimes;
@@ -47,12 +50,20 @@
 		struct content **newc);
 static content_type apple_image_content_type(lwc_string *mime_type);
 
+static void *apple_image_get_internal(const struct content *c, void *context)
+{
+	apple_image_content *ai_c = (apple_image_content *)c;
+
+	return ai_c->bitmap;
+}
+
 static const content_handler apple_image_content_handler = {
 	.create = apple_image_create,
 	.data_complete = apple_image_convert,
 	.destroy = apple_image_destroy,
 	.redraw = apple_image_redraw,
 	.clone = apple_image_clone,
+	.get_internal = apple_image_get_internal,
 	.type = apple_image_content_type,
 	.no_share = false
 };
@@ -156,6 +167,7 @@
 
 bool apple_image_convert(struct content *c)
 {
+	apple_image_content *ai_c = (apple_image_content *)c;
 	unsigned long size;
 	const char *bytes = content__get_source_data(c, &size);
 
@@ -171,7 +183,7 @@
 	
 	c->width = [image pixelsWide];
 	c->height = [image pixelsHigh];
-	c->bitmap = (void *)image;
+	ai_c->bitmap = (void *)image;
 
 	NSString *url = [NSString stringWithUTF8String: llcache_handle_get_url( content_get_llcache_handle( c ) )];
 	NSString *title = [NSString stringWithFormat: @"%@ (%dx%d)", [url lastPathComponent], c->width, c->height];
@@ -201,8 +213,10 @@
 
 void apple_image_destroy(struct content *c)
 {
-	[(id)c->bitmap release];
-	c->bitmap = NULL;
+	apple_image_content *ai_c = (apple_image_content *)c;
+
+	[(id)ai_c->bitmap release];
+	ai_c->bitmap = NULL;
     schedule_remove( animate_image_cb, c );
 }
 
@@ -246,6 +260,7 @@
 bool apple_image_redraw(struct content *c, struct content_redraw_data *data,
 		const struct rect *clip, const struct redraw_context *ctx)
 {
+	apple_image_content *ai_c = (apple_image_content *)c;
 	bitmap_flags_t flags = BITMAPF_NONE;
 
 	if (data->repeat_x)
@@ -254,7 +269,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			ai_c->bitmap, data->background_colour, flags);
 }
 
 #endif /* WITH_APPLE_IMAGE */
Index: content/content.c
===================================================================
--- content/content.c	(revision 12682)
+++ content/content.c	(working copy)
@@ -103,7 +103,6 @@
 	c->available_width = 0;
 	c->quirks = quirks;
 	c->refresh = 0;
-	c->bitmap = NULL;
 	c->time = wallclock();
 	c->size = 0;
 	c->title = NULL;
@@ -959,6 +958,7 @@
 	return c->refresh;
 }
 
+
 /**
  * Retrieve the bitmap contained in an image content
  *
@@ -972,14 +972,60 @@
 
 struct bitmap *content__get_bitmap(struct content *c)
 {
-	if (c == NULL)
-		return NULL;
+	struct bitmap *bitmap = NULL;
 
-	return c->bitmap;
+	if ((c != NULL) && 
+	    (c->handler != NULL) && 
+	    (c->handler->type != NULL) && 
+	    (c->handler->type(NULL) == CONTENT_IMAGE) &&
+	    (c->handler->get_internal != NULL) ) {
+		bitmap = c->handler->get_internal(c, NULL);
+	}
+
+	return bitmap;
 }
 
 
 /**
+ * Determine if a content is opaque from handle
+ *
+ * \param h high level cache handle to retrieve opacity from.
+ * \return false if the content is not opaque or information is not
+ *         known else true.
+ */
+bool content_get_opaque(hlcache_handle *h)
+{
+	return content__get_opaque(hlcache_handle_get_content(h));
+}
+
+/**
+ * Determine if a content is opaque
+ *
+ * \param c Content to retrieve opacity from
+ * \return false if the content is not opaque or information is not
+ *         known else true.
+ */
+bool content__get_opaque(struct content *c)
+{
+	bool opaque = false;
+
+	if ((c != NULL) && 
+	    (c->handler != NULL) && 
+	    (c->handler->type != NULL) && 
+	    (c->handler->type(NULL) == CONTENT_IMAGE) &&
+	    (c->handler->get_internal != NULL) ) {
+		struct bitmap *bitmap = NULL;
+		bitmap = c->handler->get_internal(c, NULL);
+		if (bitmap != NULL) { 
+			opaque = bitmap_get_opaque(bitmap);
+		}
+	}
+
+	return opaque;
+}
+
+
+/**
  * Retrieve quirkiness of a content
  *
  * \param h  Content to examine
Index: content/content.h
===================================================================
--- content/content.h	(revision 12682)
+++ content/content.h	(working copy)
@@ -174,6 +174,7 @@
 void content_invalidate_reuse_data(struct hlcache_handle *c);
 const char *content_get_refresh_url(struct hlcache_handle *c);
 struct bitmap *content_get_bitmap(struct hlcache_handle *c);
+bool content_get_opaque(struct hlcache_handle *h);
 bool content_get_quirks(struct hlcache_handle *c);
 
 bool content_is_locked(struct hlcache_handle *h);
Index: content/content_protected.h
===================================================================
--- content/content_protected.h	(revision 12682)
+++ content/content_protected.h	(working copy)
@@ -68,6 +68,10 @@
 	nserror (*clone)(const struct content *old, struct content **newc);
 	bool (*matches_quirks)(const struct content *c, bool quirks);
 	content_type (*type)(lwc_string *mime_type);
+
+        /** handler dependant content sensitive internal data interface. */
+	void * (*get_internal)(const struct content *c, void *context);
+
 	/** There must be one content per user for this type. */
 	bool no_share;
 };
@@ -98,12 +102,9 @@
 	bool quirks;		/**< Content is in quirks mode */
 	char *fallback_charset;	/**< Fallback charset, or NULL */
 
-	/**< URL for refresh request, in standard form as from url_join. */
+	/** URL for refresh request, in standard form as from url_join. */
 	char *refresh;
 
-	/** Bitmap, for various image contents. */
-	struct bitmap *bitmap;
-
 	unsigned int time;		/**< Creation time,
 					  if LOADING or READY,
 					  otherwise total time. */
@@ -174,6 +175,7 @@
 void content__invalidate_reuse_data(struct content *c);
 const char *content__get_refresh_url(struct content *c);
 struct bitmap *content__get_bitmap(struct content *c);
+bool content__get_opaque(struct content *c);
 
 bool content__is_locked(struct content *c);
 
Index: amiga/dt_picture.c
===================================================================
--- amiga/dt_picture.c	(revision 12682)
+++ amiga/dt_picture.c	(working copy)
@@ -40,6 +40,8 @@
 typedef struct amiga_dt_picture_content {
 	struct content base;
 
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
+
 	Object *dto;
 	int x;
 	int y;
@@ -59,12 +61,20 @@
 static nserror amiga_dt_picture_clone(const struct content *old, struct content **newc);
 static content_type amiga_dt_picture_content_type(lwc_string *mime_type);
 
+static void *amiga_dt_picture_get_internal(const struct content *c, void *context)
+{
+	amiga_dt_picture_content *pic_c = (amiga_dt_picture_content *) c;
+
+	return pic_c->bitmap;
+}
+
 static const content_handler amiga_dt_picture_content_handler = {
 	.create = amiga_dt_picture_create,
 	.data_complete = amiga_dt_picture_convert,
 	.destroy = amiga_dt_picture_destroy,
 	.redraw = amiga_dt_picture_redraw,
 	.clone = amiga_dt_picture_clone,
+	.get_internal = amiga_dt_picture_get_internal,
 	.type = amiga_dt_picture_content_type,
 	.no_share = false,
 };
@@ -171,17 +181,17 @@
 			width = (int)bmh->bmh_Width;
 			height = (int)bmh->bmh_Height;
 
-			c->bitmap = bitmap_create(width, height, bm_flags);
-			if (!c->bitmap) {
+			plugin->bitmap = bitmap_create(width, height, bm_flags);
+			if (!plugin->bitmap) {
 				msg_data.error = messages_get("NoMemory");
 				content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
 				return false;
 			}
 
-			bm_buffer = bitmap_get_buffer(c->bitmap);
+			bm_buffer = bitmap_get_buffer(plugin->bitmap);
 
 			IDoMethod(plugin->dto, PDTM_READPIXELARRAY,
-				bm_buffer, bm_format, bitmap_get_rowstride(c->bitmap),
+				bm_buffer, bm_format, bitmap_get_rowstride(plugin->bitmap),
 				0, 0, width, height);
 		}
 		else return false;
@@ -197,7 +207,7 @@
 	content__set_title(c, title);
 */
 
-	bitmap_modified(c->bitmap);
+	bitmap_modified(plugin->bitmap);
 
 	content_set_ready(c);
 	content_set_done(c);
@@ -212,8 +222,9 @@
 
 	LOG(("amiga_dt_picture_destroy"));
 
-	if (c->bitmap != NULL)
-		bitmap_destroy(c->bitmap);
+	if (plugin->bitmap != NULL) {
+		bitmap_destroy(plugin->bitmap);
+	}
 
 	DisposeDTObject(plugin->dto);
 
@@ -221,19 +232,22 @@
 }
 
 bool amiga_dt_picture_redraw(struct content *c,
-		struct content_redraw_data *data, const struct rect *clip,
+		struct content_redraw_data *data, 
+		const struct rect *clip,
 		const struct redraw_context *ctx)
 {
-	LOG(("amiga_dt_picture_redraw"));
+	amiga_dt_picture_content *plugin = (amiga_dt_picture_content *) c;
 	bitmap_flags_t flags = BITMAPF_NONE;
 
+	LOG(("amiga_dt_picture_redraw"));
+
 	if (data->repeat_x)
 		flags |= BITMAPF_REPEAT_X;
 	if (data->repeat_y)
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			plugin->bitmap, data->background_colour, flags);
 }
 
 nserror amiga_dt_picture_clone(const struct content *old, struct content **newc)
@@ -254,8 +268,8 @@
 	}
 
 	/* We "clone" the old content by replaying conversion */
-	if (old->status == CONTENT_STATUS_READY || 
-			old->status == CONTENT_STATUS_DONE) {
+	if ((old->status == CONTENT_STATUS_READY) || 
+	    (old->status == CONTENT_STATUS_DONE)) {
 		if (amiga_dt_picture_convert(&plugin->base) == false) {
 			content_destroy(&plugin->base);
 			return NSERROR_CLONE_FAILED;
Index: amiga/dt_anim.c
===================================================================
--- amiga/dt_anim.c	(revision 12682)
+++ amiga/dt_anim.c	(working copy)
@@ -44,6 +44,8 @@
 typedef struct amiga_dt_anim_content {
 	struct content base;
 
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
+
 	Object *dto;
 	int x;
 	int y;
@@ -70,6 +72,13 @@
 static nserror amiga_dt_anim_clone(const struct content *old, struct content **newc);
 static content_type amiga_dt_anim_content_type(lwc_string *mime_type);
 
+static void *amiga_dt_anim_get_internal(const struct content *c, void *context)
+{
+	amiga_dt_anim_content *adta_c = (amiga_dt_anim_content *)c;
+
+	return adta_c->bitmap;
+}
+
 static const content_handler amiga_dt_anim_content_handler = {
 	.create = amiga_dt_anim_create,
 	.data_complete = amiga_dt_anim_convert,
@@ -79,6 +88,7 @@
 	.open = amiga_dt_anim_open,
 	.close = amiga_dt_anim_close,
 	.clone = amiga_dt_anim_clone,
+	.get_internal = amiga_dt_anim_get_internal,
 	.type = amiga_dt_anim_content_type,
 	.no_share = false,
 };
@@ -183,14 +193,14 @@
 			width = (int)bmh->bmh_Width;
 			height = (int)bmh->bmh_Height;
 
-			c->bitmap = bitmap_create(width, height, bm_flags);
-			if (!c->bitmap) {
+			plugin->bitmap = bitmap_create(width, height, bm_flags);
+			if (!plugin->bitmap) {
 				msg_data.error = messages_get("NoMemory");
 				content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
 				return false;
 			}
 
-			bm_buffer = bitmap_get_buffer(c->bitmap);
+			bm_buffer = bitmap_get_buffer(plugin->bitmap);
 
 			adt_frame.MethodID = ADTM_LOADFRAME;
 			adt_frame.alf_TimeStamp = 0;
@@ -227,7 +237,7 @@
 	content__set_title(c, title);
 */
 
-	bitmap_modified(c->bitmap);
+	bitmap_modified(plugin->bitmap);
 
 	content_set_ready(c);
 	content_set_done(c);
@@ -242,8 +252,8 @@
 
 	LOG(("amiga_dt_anim_destroy"));
 
-	if (c->bitmap != NULL)
-		bitmap_destroy(c->bitmap);
+	if (plugin->bitmap != NULL)
+		bitmap_destroy(plugin->bitmap);
 
 	DisposeDTObject(plugin->dto);
 
@@ -255,18 +265,17 @@
 		const struct redraw_context *ctx)
 {
 	amiga_dt_anim_content *plugin = (amiga_dt_anim_content *) c;
+	bitmap_flags_t flags = BITMAPF_NONE;
 
 	LOG(("amiga_dt_anim_redraw"));
 
-	bitmap_flags_t flags = BITMAPF_NONE;
-
 	if (data->repeat_x)
 		flags |= BITMAPF_REPEAT_X;
 	if (data->repeat_y)
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			plugin->bitmap, data->background_colour, flags);
 }
 
 /**
Index: amiga/icon.c
===================================================================
--- amiga/icon.c	(revision 12682)
+++ amiga/icon.c	(working copy)
@@ -58,6 +58,8 @@
 
 typedef struct amiga_icon_content {
 	struct content base;
+
+	struct bitmap *bitmap;	/**< Created NetSurf bitmap */
 } amiga_icon_content;
 
 static nserror amiga_icon_create(const content_handler *handler,
@@ -73,12 +75,20 @@
 		struct content **newc);
 static content_type amiga_icon_content_type(lwc_string *mime_type);
 
+static void *amiga_icon_get_internal(const struct content *c, void *context)
+{
+	amiga_icon_content *icon_c = (amiga_icon_content *)c;
+
+	return icon_c->bitmap;
+}
+
 static const content_handler amiga_icon_content_handler = {
 	.create = amiga_icon_create,
 	.data_complete = amiga_icon_convert,
 	.destroy = amiga_icon_destroy,
 	.redraw = amiga_icon_redraw,
 	.clone = amiga_icon_clone,
+	.get_internal = amiga_icon_get_internal,
 	.type = amiga_icon_content_type,
 	.no_share = false,
 };
@@ -134,21 +144,21 @@
 		llcache_handle *llcache, const char *fallback_charset,
 		bool quirks, struct content **c)
 {
-	amiga_icon_content *ai;
+	amiga_icon_content *ai_content;
 	nserror error;
 
-	ai = talloc_zero(0, amiga_icon_content);
-	if (ai == NULL)
+	ai_content = talloc_zero(0, amiga_icon_content);
+	if (ai_content == NULL)
 		return NSERROR_NOMEM;
 
-	error = content__init(&ai->base, handler, imime_type, params,
+	error = content__init(&ai_content->base, handler, imime_type, params,
 			llcache, fallback_charset, quirks);
 	if (error != NSERROR_OK) {
-		talloc_free(ai);
+		talloc_free(ai_content);
 		return error;
 	}
 
-	*c = (struct content *) ai;
+	*c = (struct content *)ai_content;
 
 	return NSERROR_OK;
 }
@@ -161,6 +171,7 @@
 
 bool amiga_icon_convert(struct content *c)
 {
+	amiga_icon_content *icon_c = (amiga_icon_content *)c;	
 	union content_msg_data msg_data;
 	struct DiskObject *dobj;
 	ULONG *imagebuf;
@@ -213,8 +224,8 @@
 		return false;
 	}
 
-	c->bitmap = bitmap_create(width, height, BITMAP_NEW);
-	if (!c->bitmap) {
+	icon_c->bitmap = bitmap_create(width, height, BITMAP_NEW);
+	if (!icon_c->bitmap) {
 		msg_data.error = messages_get("NoMemory");
 		content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
 		if(dobj) FreeDiskObject(dobj);
@@ -260,7 +271,7 @@
 	c->width = width;
 	c->height = height;
 
-	bitmap_modified(c->bitmap);
+	bitmap_modified(icon_c->bitmap);
 	content_set_ready(c);
 	content_set_done(c);
 	content_set_status(c, "");
@@ -280,8 +291,10 @@
 
 void amiga_icon_destroy(struct content *c)
 {
-	if (c->bitmap != NULL)
-		bitmap_destroy(c->bitmap);
+	amiga_icon_content *icon_c = (amiga_icon_content *)c;	
+
+	if (icon_c->bitmap != NULL)
+		bitmap_destroy(icon_c->bitmap);
 }
 
 
@@ -293,6 +306,7 @@
 		struct content_redraw_data *data, const struct rect *clip,
 		const struct redraw_context *ctx)
 {
+	amiga_icon_content *icon_c = (amiga_icon_content *)c;	
 	bitmap_flags_t flags = BITMAPF_NONE;
 
 	if (data->repeat_x)
@@ -301,7 +315,7 @@
 		flags |= BITMAPF_REPEAT_Y;
 
 	return ctx->plot->bitmap(data->x, data->y, data->width, data->height,
-			c->bitmap, data->background_colour, flags);
+			icon_c->bitmap, data->background_colour, flags);
 }
 
 

Attachment: signature.asc
Description: Digital signature

Reply via email to