summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2015-04-22 23:13:24 +0100
committerVincent Sanders <vince@kyllikki.org>2015-04-22 23:14:51 +0100
commitde98108e7f5dde136164a6e74596d70fd1289397 (patch)
treebee10caaf3f76eaed32b91adebf7b0a45af84859
parentdf3a8894357444704ec6c72df2dd3b2161e3f4c7 (diff)
downloadnetsurf-de98108e7f5dde136164a6e74596d70fd1289397.tar.gz
netsurf-de98108e7f5dde136164a6e74596d70fd1289397.tar.bz2
Add render to bitmap operations and update gtk to provide it.
-rw-r--r--desktop/gui_factory.c4
-rw-r--r--gtk/bitmap.c116
-rw-r--r--image/bitmap.h33
3 files changed, 126 insertions, 27 deletions
diff --git a/desktop/gui_factory.c b/desktop/gui_factory.c
index cab11eb0a..50244e334 100644
--- a/desktop/gui_factory.c
+++ b/desktop/gui_factory.c
@@ -620,6 +620,10 @@ static nserror verify_bitmap_register(struct gui_bitmap_table *gbt)
return NSERROR_BAD_PARAMETER;
}
+ if (gbt->render == NULL) {
+ return NSERROR_BAD_PARAMETER;
+ }
+
return NSERROR_OK;
}
diff --git a/gtk/bitmap.c b/gtk/bitmap.c
index 978838d2e..6e53154c4 100644
--- a/gtk/bitmap.c
+++ b/gtk/bitmap.c
@@ -32,8 +32,11 @@
#include "utils/log.h"
#include "content/content.h"
#include "image/bitmap.h"
+#include "desktop/plotters.h"
+#include "desktop/thumbnail.h"
#include "gtk/scaffolding.h"
+#include "gtk/plotters.h"
#include "gtk/bitmap.h"
@@ -86,17 +89,17 @@ static void bitmap_set_opaque(void *vbitmap, bool opaque)
if (fmt == CAIRO_FORMAT_RGB24) {
if (opaque == false) {
/* opaque to transparent */
- nsurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- cairo_image_surface_get_width(gbitmap->surface),
+ nsurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ cairo_image_surface_get_width(gbitmap->surface),
cairo_image_surface_get_height(gbitmap->surface));
}
-
+
} else {
if (opaque == true) {
/* transparent to opaque */
- nsurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
- cairo_image_surface_get_width(gbitmap->surface),
+ nsurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,
+ cairo_image_surface_get_width(gbitmap->surface),
cairo_image_surface_get_height(gbitmap->surface));
}
@@ -106,8 +109,8 @@ static void bitmap_set_opaque(void *vbitmap, bool opaque)
if (cairo_surface_status(nsurface) != CAIRO_STATUS_SUCCESS) {
cairo_surface_destroy(nsurface);
} else {
- memcpy(cairo_image_surface_get_data(nsurface),
- cairo_image_surface_get_data(gbitmap->surface),
+ memcpy(cairo_image_surface_get_data(nsurface),
+ cairo_image_surface_get_data(gbitmap->surface),
cairo_image_surface_get_stride(gbitmap->surface) * cairo_image_surface_get_height(gbitmap->surface));
cairo_surface_destroy(gbitmap->surface);
gbitmap->surface = nsurface;
@@ -116,7 +119,7 @@ static void bitmap_set_opaque(void *vbitmap, bool opaque)
}
- }
+ }
}
@@ -137,13 +140,13 @@ static bool bitmap_test_opaque(void *vbitmap)
pixels = cairo_image_surface_get_data(gbitmap->surface);
- pcount = cairo_image_surface_get_stride(gbitmap->surface) *
+ pcount = cairo_image_surface_get_stride(gbitmap->surface) *
cairo_image_surface_get_height(gbitmap->surface);
for (ploop = 3; ploop < pcount; ploop += 4) {
if (pixels[ploop] != 0xff) {
return false;
- }
+ }
}
return true;
@@ -190,7 +193,7 @@ static unsigned char *bitmap_get_buffer(void *vbitmap)
cairo_format_t fmt;
assert(gbitmap);
-
+
cairo_surface_flush(gbitmap->surface);
pixels = cairo_image_surface_get_data(gbitmap->surface);
@@ -259,7 +262,7 @@ static unsigned char *bitmap_get_buffer(void *vbitmap)
}
gbitmap->converted = false;
-
+
return (unsigned char *) pixels;
}
@@ -341,7 +344,7 @@ static void bitmap_modified(void *vbitmap)
{
struct bitmap *gbitmap = (struct bitmap *)vbitmap;
int pixel_loop;
- int pixel_count;
+ int pixel_count;
uint8_t *pixels;
uint32_t t, r, g, b;
cairo_format_t fmt;
@@ -350,7 +353,7 @@ static void bitmap_modified(void *vbitmap)
fmt = cairo_image_surface_get_format(gbitmap->surface);
- pixel_count = cairo_image_surface_get_width(gbitmap->surface) *
+ pixel_count = cairo_image_surface_get_width(gbitmap->surface) *
cairo_image_surface_get_height(gbitmap->surface);
pixels = cairo_image_surface_get_data(gbitmap->surface);
@@ -411,7 +414,7 @@ static void bitmap_modified(void *vbitmap)
#endif
}
}
-
+
cairo_surface_mark_dirty(gbitmap->surface);
gbitmap->converted = true;
@@ -435,6 +438,88 @@ int nsgtk_bitmap_get_height(void *vbitmap)
return cairo_image_surface_get_height(gbitmap->surface);
}
+/**
+ * Render content into a bitmap.
+ *
+ * \param content content structure to thumbnail
+ * \param bitmap the bitmap to draw to
+ * \return true on success and bitmap updated else false
+ */
+static nserror
+bitmap_render(struct bitmap *bitmap, struct hlcache_handle *content)
+{
+ cairo_surface_t *dsurface = bitmap->surface;
+ cairo_surface_t *surface;
+ cairo_t *old_cr;
+ gint dwidth, dheight;
+ int cwidth, cheight;
+ struct redraw_context ctx = {
+ .interactive = false,
+ .background_images = true,
+ .plot = &nsgtk_plotters
+ };
+
+ assert(content);
+ assert(bitmap);
+
+ dwidth = cairo_image_surface_get_width(dsurface);
+ dheight = cairo_image_surface_get_height(dsurface);
+
+ /* Calculate size of buffer to render the content into */
+ /* Get the width from the content width, unless it exceeds 1024,
+ * in which case we use 1024. This means we never create excessively
+ * large render buffers for huge contents, which would eat memory and
+ * cripple performance.
+ */
+ cwidth = min(max(content_get_width(content), dwidth), 1024);
+
+ /* The height is set in proportion with the width, according to the
+ * aspect ratio of the required thumbnail. */
+ cheight = ((cwidth * dheight) + (dwidth / 2)) / dwidth;
+
+ /* Create surface to render into */
+ surface = cairo_surface_create_similar(dsurface, CAIRO_CONTENT_COLOR_ALPHA, cwidth, cheight);
+
+ if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
+ cairo_surface_destroy(surface);
+ return false;
+ }
+
+ old_cr = current_cr;
+ current_cr = cairo_create(surface);
+
+ /* render the content */
+ thumbnail_redraw(content, cwidth, cheight, &ctx);
+
+ cairo_destroy(current_cr);
+ current_cr = old_cr;
+
+ cairo_t *cr = cairo_create(dsurface);
+
+ /* Scale *before* setting the source surface (1) */
+ cairo_scale (cr, (double)dwidth / cwidth, (double)dheight / cheight);
+ cairo_set_source_surface (cr, surface, 0, 0);
+
+ /* To avoid getting the edge pixels blended with 0 alpha,
+ * which would occur with the default EXTEND_NONE. Use
+ * EXTEND_PAD for 1.2 or newer (2)
+ */
+ cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_REFLECT);
+
+ /* Replace the destination with the source instead of overlaying */
+ cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+
+ /* Do the actual drawing */
+ cairo_paint(cr);
+
+ cairo_destroy(cr);
+
+ cairo_surface_destroy(surface);
+
+ return NSERROR_OK;
+}
+
+
static struct gui_bitmap_table bitmap_table = {
.create = bitmap_create,
.destroy = bitmap_destroy,
@@ -448,6 +533,7 @@ static struct gui_bitmap_table bitmap_table = {
.get_bpp = bitmap_get_bpp,
.save = bitmap_save,
.modified = bitmap_modified,
+ .render = bitmap_render,
};
struct gui_bitmap_table *nsgtk_bitmap_table = &bitmap_table;
diff --git a/image/bitmap.h b/image/bitmap.h
index b121f8abd..ef6c1b49b 100644
--- a/image/bitmap.h
+++ b/image/bitmap.h
@@ -28,27 +28,27 @@
* For example, an opaque 1x1 pixel image would yield the following bitmap
* data:
*
- * Red : 0xff 0x00 0x00 0x00
- * Green: 0x00 0xff 0x00 0x00
- * Blue : 0x00 0x00 0xff 0x00
+ * > Red : 0xff 0x00 0x00 0x00
+ * > Green: 0x00 0xff 0x00 0x00
+ * > Blue : 0x00 0x00 0xff 0x00
*
* Any attempt to read pixels by casting bitmap data to uint32_t or similar
* will need to cater for the order of bytes in a word being different on
* big and little endian systems. To avoid confusion, it is recommended
* that pixel data is loaded as follows:
*
- * uint32_t read_pixel(const uint8_t *bmp)
- * {
- * // red green blue alpha
- * return bmp[0] | (bmp[1] << 8) | (bmp[2] << 16) | (bmp[3] << 24);
- * }
+ * uint32_t read_pixel(const uint8_t *bmp)
+ * {
+ * // red green blue alpha
+ * return bmp[0] | (bmp[1] << 8) | (bmp[2] << 16) | (bmp[3] << 24);
+ * }
*
* and *not* as follows:
*
- * uint32_t read_pixel(const uint8_t *bmp)
- * {
- * return *((uint32_t *) bmp);
- * }
+ * uint32_t read_pixel(const uint8_t *bmp)
+ * {
+ * return *((uint32_t *) bmp);
+ * }
*/
#ifndef _NETSURF_IMAGE_BITMAP_H_
@@ -61,6 +61,7 @@
struct content;
struct bitmap;
+struct hlcache_handle;
/**
* Bitmap operations.
@@ -163,6 +164,14 @@ struct gui_bitmap_table {
* \param bitmap The bitmap set as modified.
*/
void (*modified)(void *bitmap);
+
+ /**
+ * Render content into a bitmap.
+ *
+ * \param bitmap The bitmap to render into.
+ * \param content The content to render.
+ */
+ nserror (*render)(struct bitmap *bitmap, struct hlcache_handle *content);
};
#endif