summaryrefslogtreecommitdiff
path: root/gtk
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers@netsurf-browser.org>2006-08-09 15:06:14 +0000
committerDaniel Silverstone <dsilvers@netsurf-browser.org>2006-08-09 15:06:14 +0000
commit6d7357e2cb1b106d5da8082958b23bdbe628d052 (patch)
treec03d6baa0abbf1f6c0298248c0232d164e863127 /gtk
parent5e1f0332add2458c4eb142bff4becdebe197325a (diff)
downloadnetsurf-6d7357e2cb1b106d5da8082958b23bdbe628d052.tar.gz
netsurf-6d7357e2cb1b106d5da8082958b23bdbe628d052.tar.bz2
Merge 2818:HEAD of branches/dsilvers/gtk-bitmap-pretile
svn path=/trunk/netsurf/; revision=2824
Diffstat (limited to 'gtk')
-rw-r--r--gtk/gtk_bitmap.c139
-rw-r--r--gtk/gtk_bitmap.h22
-rw-r--r--gtk/gtk_plotters.c35
-rw-r--r--gtk/gtk_thumbnail.c3
4 files changed, 184 insertions, 15 deletions
diff --git a/gtk/gtk_bitmap.c b/gtk/gtk_bitmap.c
index d70b27ac9..e33b436d0 100644
--- a/gtk/gtk_bitmap.c
+++ b/gtk/gtk_bitmap.c
@@ -19,9 +19,18 @@
#include "netsurf/content/content.h"
#include "netsurf/gtk/gtk_window.h"
#include "netsurf/image/bitmap.h"
+#include "netsurf/utils/log.h"
-struct bitmap;
+struct bitmap {
+ GdkPixbuf *primary;
+ GdkPixbuf *pretile_x;
+ GdkPixbuf *pretile_y;
+ GdkPixbuf *pretile_xy;
+};
+
+#define MIN_PRETILE_WIDTH 256
+#define MIN_PRETILE_HEIGHT 256
/**
@@ -35,9 +44,11 @@ struct bitmap;
struct bitmap *bitmap_create(int width, int height, unsigned int state)
{
- GdkPixbuf *pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
- width, height);
- return (struct bitmap *) pixbuf;
+ struct bitmap *bmp = malloc(sizeof(struct bitmap));
+ bmp->primary = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
+ width, height);
+ bmp->pretile_x = bmp->pretile_y = bmp->pretile_xy = NULL;
+ return bmp;
}
@@ -94,7 +105,7 @@ bool bitmap_get_opaque(struct bitmap *bitmap)
char *bitmap_get_buffer(struct bitmap *bitmap)
{
assert(bitmap);
- return (char *)gdk_pixbuf_get_pixels((GdkPixbuf *) bitmap);
+ return (char *)gdk_pixbuf_get_pixels(bitmap->primary);
}
@@ -108,10 +119,20 @@ char *bitmap_get_buffer(struct bitmap *bitmap)
size_t bitmap_get_rowstride(struct bitmap *bitmap)
{
assert(bitmap);
- return gdk_pixbuf_get_rowstride((GdkPixbuf *) bitmap);
+ return gdk_pixbuf_get_rowstride(bitmap->primary);
}
+static void
+gtk_bitmap_free_pretiles(struct bitmap *bitmap)
+{
+#define FREE_TILE(XY) if (bitmap->pretile_##XY) g_object_unref(bitmap->pretile_##XY); bitmap->pretile_##XY = NULL
+ FREE_TILE(x);
+ FREE_TILE(y);
+ FREE_TILE(xy);
+#undef FREE_TILE
+}
+
/**
* Free a bitmap.
*
@@ -121,7 +142,9 @@ size_t bitmap_get_rowstride(struct bitmap *bitmap)
void bitmap_destroy(struct bitmap *bitmap)
{
assert(bitmap);
- g_object_unref((GdkPixbuf *) bitmap);
+ gtk_bitmap_free_pretiles(bitmap);
+ g_object_unref(bitmap->primary);
+ free(bitmap);
}
@@ -145,6 +168,7 @@ bool bitmap_save(struct bitmap *bitmap, const char *path)
* \param bitmap a bitmap, as returned by bitmap_create()
*/
void bitmap_modified(struct bitmap *bitmap) {
+ gtk_bitmap_free_pretiles(bitmap);
}
@@ -159,3 +183,104 @@ void bitmap_modified(struct bitmap *bitmap) {
void bitmap_set_suspendable(struct bitmap *bitmap, void *private_word,
void (*invalidate)(struct bitmap *bitmap, void *private_word)) {
}
+
+static GdkPixbuf *
+gtk_bitmap_generate_pretile(GdkPixbuf *primary, int repeat_x, int repeat_y)
+{
+ int width = gdk_pixbuf_get_width(primary);
+ int height = gdk_pixbuf_get_height(primary);
+ size_t primary_stride = gdk_pixbuf_get_rowstride(primary);
+ GdkPixbuf *result = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8,
+ width * repeat_x, height * repeat_y);
+ char *target_buffer = (char *)gdk_pixbuf_get_pixels(result);
+ size_t target_stride = gdk_pixbuf_get_rowstride(result);
+ int x,y,row;
+ /* This algorithm won't work if the strides are not multiples */
+ assert(target_stride == (primary_stride * repeat_x));
+
+ if (repeat_x == 1 && repeat_y == 1) {
+ g_object_ref(primary);
+ g_object_unref(result);
+ return primary;
+ }
+
+ for (y = 0; y < repeat_y; ++y) {
+ char *primary_buffer = (char *)gdk_pixbuf_get_pixels(primary);
+ for (row = 0; row < height; ++row) {
+ for (x = 0; x < repeat_x; ++x) {
+ memcpy(target_buffer,
+ primary_buffer, primary_stride);
+ target_buffer += primary_stride;
+ }
+ primary_buffer += primary_stride;
+ }
+ }
+ return result;
+}
+
+/**
+ * The primary image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+GdkPixbuf *
+gtk_bitmap_get_primary(struct bitmap* bitmap)
+{
+ return bitmap->primary;
+}
+
+/**
+ * The X-pretiled image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+GdkPixbuf *
+gtk_bitmap_get_pretile_x(struct bitmap* bitmap)
+{
+ if (!bitmap->pretile_x) {
+ int width = gdk_pixbuf_get_width(bitmap->primary);
+ int height = gdk_pixbuf_get_height(bitmap->primary);
+ int xmult = (MIN_PRETILE_WIDTH + width - 1)/width;
+ LOG(("Pretiling %p for X*%d", bitmap, xmult));
+ bitmap->pretile_x = gtk_bitmap_generate_pretile(bitmap->primary, xmult, 1);
+ }
+ return bitmap->pretile_x;
+
+}
+
+/**
+ * The Y-pretiled image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+GdkPixbuf *
+gtk_bitmap_get_pretile_y(struct bitmap* bitmap)
+{
+ if (!bitmap->pretile_y) {
+ int width = gdk_pixbuf_get_width(bitmap->primary);
+ int height = gdk_pixbuf_get_height(bitmap->primary);
+ int ymult = (MIN_PRETILE_HEIGHT + height - 1)/height;
+ LOG(("Pretiling %p for Y*%d", bitmap, ymult));
+ bitmap->pretile_y = gtk_bitmap_generate_pretile(bitmap->primary, 1, ymult);
+ }
+ return bitmap->pretile_y;
+}
+
+/**
+ * The XY-pretiled image associated with this bitmap object.
+ *
+ * \param bitmap a bitmap, as returned by bitmap_create()
+ */
+GdkPixbuf *
+gtk_bitmap_get_pretile_xy(struct bitmap* bitmap)
+{
+ if (!bitmap->pretile_xy) {
+ int width = gdk_pixbuf_get_width(bitmap->primary);
+ int height = gdk_pixbuf_get_height(bitmap->primary);
+ int xmult = (MIN_PRETILE_WIDTH + width - 1)/width;
+ int ymult = (MIN_PRETILE_HEIGHT + height - 1)/height;
+ LOG(("Pretiling %p for X*%d Y*%d", bitmap, xmult, ymult));
+ bitmap->pretile_xy = gtk_bitmap_generate_pretile(bitmap->primary, xmult, ymult);
+ }
+ return bitmap->pretile_xy;
+}
diff --git a/gtk/gtk_bitmap.h b/gtk/gtk_bitmap.h
new file mode 100644
index 000000000..719bb0ab5
--- /dev/null
+++ b/gtk/gtk_bitmap.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of NetSurf, http://netsurf.sourceforge.net/
+ * Licensed under the GNU General Public License,
+ * http://www.opensource.org/licenses/gpl-license
+ * Copyright 2006 Daniel Silverstone <dsilvers@digital-scurf.org>
+ */
+
+#ifndef NS_GTK_BITMAP_H
+#define NS_GTK_BITMAP_H
+
+#include <gdk/gdk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "netsurf/image/bitmap.h"
+
+GdkPixbuf *gtk_bitmap_get_primary(struct bitmap*);
+GdkPixbuf *gtk_bitmap_get_pretile_x(struct bitmap*);
+GdkPixbuf *gtk_bitmap_get_pretile_y(struct bitmap*);
+GdkPixbuf *gtk_bitmap_get_pretile_xy(struct bitmap*);
+
+
+
+#endif /* NS_GTK_BITMAP_H */
diff --git a/gtk/gtk_plotters.c b/gtk/gtk_plotters.c
index 773137381..27e5a78a3 100644
--- a/gtk/gtk_plotters.c
+++ b/gtk/gtk_plotters.c
@@ -26,6 +26,7 @@
#include "netsurf/utils/log.h"
#include "netsurf/desktop/options.h"
#include "netsurf/gtk/options.h"
+#include "netsurf/gtk/gtk_bitmap.h"
static bool nsgtk_plot_clg(colour c);
static bool nsgtk_plot_rectangle(int x0, int y0, int width, int height,
@@ -256,13 +257,12 @@ bool nsgtk_plot_arc(int x, int y, int radius, int angle1, int angle2, colour c)
return true;
}
-bool nsgtk_plot_bitmap(int x, int y, int width, int height,
- struct bitmap *bitmap, colour bg)
+static bool nsgtk_plot_pixbuf(int x, int y, int width, int height,
+ GdkPixbuf *pixbuf, colour bg)
{
/* XXX: This currently ignores the background colour supplied.
* Does this matter?
*/
- GdkPixbuf *pixbuf = (GdkPixbuf *) bitmap;
if (width == 0 || height == 0)
return true;
@@ -298,18 +298,39 @@ bool nsgtk_plot_bitmap(int x, int y, int width, int height,
return true;
}
+bool nsgtk_plot_bitmap(int x, int y, int width, int height,
+ struct bitmap *bitmap, colour bg)
+{
+ GdkPixbuf *pixbuf = gtk_bitmap_get_primary(bitmap);
+ nsgtk_plot_pixbuf(x, y, width, height, pixbuf, bg);
+}
bool nsgtk_plot_bitmap_tile(int x, int y, int width, int height,
struct bitmap *bitmap, colour bg,
bool repeat_x, bool repeat_y)
{
int doneheight = 0, donewidth = 0;
-
+ GdkPixbuf *primary;
+ GdkPixbuf *pretiled;
+
if (!(repeat_x || repeat_y)) {
/* Not repeating at all, so just pass it on */
return nsgtk_plot_bitmap(x,y,width,height,bitmap,bg);
}
-
+
+ if (repeat_x && !repeat_y)
+ pretiled = gtk_bitmap_get_pretile_x(bitmap);
+ if (repeat_x && repeat_y)
+ pretiled = gtk_bitmap_get_pretile_xy(bitmap);
+ if (!repeat_x && repeat_y)
+ pretiled = gtk_bitmap_get_pretile_y(bitmap);
+ primary = gtk_bitmap_get_primary(bitmap);
+ /* use the primary and pretiled widths to scale the w/h provided */
+ width *= gdk_pixbuf_get_width(pretiled);
+ width /= gdk_pixbuf_get_width(primary);
+ height *= gdk_pixbuf_get_height(pretiled);
+ height /= gdk_pixbuf_get_height(primary);
+
if (y > cliprect.y)
doneheight = (cliprect.y - height) + ((y - cliprect.y) % height);
else
@@ -321,8 +342,8 @@ bool nsgtk_plot_bitmap_tile(int x, int y, int width, int height,
else
donewidth = x;
while (donewidth < (cliprect.x + cliprect.width)) {
- nsgtk_plot_bitmap(donewidth, doneheight,
- width, height, bitmap, bg);
+ nsgtk_plot_pixbuf(donewidth, doneheight,
+ width, height, pretiled, bg);
donewidth += width;
if (!repeat_x) break;
}
diff --git a/gtk/gtk_thumbnail.c b/gtk/gtk_thumbnail.c
index 4d4fea11c..c5e03c479 100644
--- a/gtk/gtk_thumbnail.c
+++ b/gtk/gtk_thumbnail.c
@@ -24,6 +24,7 @@
#include "netsurf/utils/log.h"
#include "netsurf/gtk/gtk_window.h"
#include "netsurf/gtk/gtk_plotters.h"
+#include "netsurf/gtk/gtk_bitmap.h"
/**
* Create a thumbnail of a page.
@@ -35,7 +36,7 @@
bool thumbnail_create(struct content *content, struct bitmap *bitmap,
const char *url)
{
- GdkPixbuf *pixbuf = (GdkPixbuf *) bitmap;
+ GdkPixbuf *pixbuf = gtk_bitmap_get_primary(bitmap);
gint width = gdk_pixbuf_get_width(pixbuf);
gint height = gdk_pixbuf_get_height(pixbuf);
gint depth = (gdk_screen_get_system_visual(gdk_screen_get_default()))->depth;