summaryrefslogtreecommitdiff
path: root/gtk
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 /gtk
parentdf3a8894357444704ec6c72df2dd3b2161e3f4c7 (diff)
downloadnetsurf-de98108e7f5dde136164a6e74596d70fd1289397.tar.gz
netsurf-de98108e7f5dde136164a6e74596d70fd1289397.tar.bz2
Add render to bitmap operations and update gtk to provide it.
Diffstat (limited to 'gtk')
-rw-r--r--gtk/bitmap.c116
1 files changed, 101 insertions, 15 deletions
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;