From 8aa4b9e7b3828d04785f9d444b75d0f9f0374167 Mon Sep 17 00:00:00 2001 From: Rob Kendrick Date: Wed, 18 Jul 2007 23:57:39 +0000 Subject: Fixes to rsvg renderer. Now mostly works for direct (non-embedded in a document) viewing. svn path=/trunk/netsurf/; revision=3438 --- image/rsvg.c | 79 ++++++++++++++++++++++++------------------------------------ 1 file changed, 32 insertions(+), 47 deletions(-) (limited to 'image/rsvg.c') diff --git a/image/rsvg.c b/image/rsvg.c index 534f57be6..c37859bf3 100644 --- a/image/rsvg.c +++ b/image/rsvg.c @@ -20,6 +20,7 @@ #ifdef WITH_RSVG #include +#include #include #include @@ -35,34 +36,17 @@ #include "utils/talloc.h" static inline void rsvg_argb_to_abgr(u_int32_t pixels[], int width, int height, - int rowstride); -static void rsvg_size_func(gint *width, gint *height, gpointer user_data); - -/** Callback called by librsvg when it has determined the graphic's natural - * size. - * - * \param width Pointer to graphic's natual width. Change this to - * change what size we'd like librsvg to render it - * \param height Pointer to the graphic's natual height. Change this to - * change what size we'd like librsvg to redner it - * \param user_data User-specific context, in this case it contains the - * pointer to the content object - */ -static void rsvg_size_func(gint *width, gint *height, gpointer user_data) -{ - struct content *c = (struct content *)user_data; - LOG(("svg image's natural size is %d x %d", *width, *height)); - - c->width = *width; - c->height = *height; -} + size_t rowstride); bool rsvg_create(struct content *c, const char *params[]) { struct content_rsvg_data *d = &c->data.rsvg; union content_msg_data msg_data; - LOG(("!!!!!!!!!!!!!!!!!!!!!!!!!!!!")); + d->rsvgh = NULL; + d->cs = NULL; + d->ct = NULL; + d->bitmap = NULL; if ((d->rsvgh = rsvg_handle_new()) == NULL) { LOG(("rsvg_handle_new() returned NULL.")); @@ -71,13 +55,11 @@ bool rsvg_create(struct content *c, const char *params[]) return false; } - rsvg_handle_set_size_callback(d->rsvgh, rsvg_size_func, c, NULL); - return true; } /** Convert Cairo's ARGB output to NetSurf's favoured ABGR format. It converts - * the data in-place. + * the data in-place. Operation is endian-swap and rotate right 8 bits. * * \param pixels Array of 32-bit values, in the form of ARGB. This will * be overwritten with new data in the form of ABGR. @@ -87,7 +69,7 @@ bool rsvg_create(struct content *c, const char *params[]) * implementation requires this to be a multiple of 4.) */ static inline void rsvg_argb_to_abgr(u_int32_t pixels[], int width, int height, - int rowstride) + size_t rowstride) { u_int32_t *p = &pixels[0]; @@ -100,7 +82,7 @@ static inline void rsvg_argb_to_abgr(u_int32_t pixels[], int width, int height, ((e & 0xff000000) >> 24)); p[x] = (s >> 8) | (s << 24); } - p += rowstride; + p += (rowstride >> 2); } } @@ -108,30 +90,39 @@ bool rsvg_convert(struct content *c, int iwidth, int iheight) { struct content_rsvg_data *d = &c->data.rsvg; union content_msg_data msg_data; + RsvgDimensionData rsvgsize; GError *err = NULL; if (rsvg_handle_write(d->rsvgh, (guchar *)c->source_data, - (gsize)c->source_size, &err) - == FALSE) { + (gsize)c->source_size, &err) == FALSE) { LOG(("rsvg_handle_write returned an error: %s", err->message)); - rsvg_handle_free(d->rsvgh); msg_data.error = err->message; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } + assert(err == NULL); + if (rsvg_handle_close(d->rsvgh, &err) == FALSE) { LOG(("rsvg_handle_close returned an error: %s", err->message)); - rsvg_handle_free(d->rsvgh); msg_data.error = err->message; content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } + assert(err == NULL); + + /* we should now be able to query librsvg for the natural size of the + * graphic, so we can create our bitmap. + */ + + rsvg_handle_get_dimensions(d->rsvgh, &rsvgsize); + c->width = rsvgsize.width; + c->height = rsvgsize.height; + if ((d->bitmap = bitmap_create(c->width, c->height, BITMAP_NEW)) == NULL) { LOG(("Failed to create bitmap for rsvg render.")); - rsvg_handle_free(d->rsvgh); msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; @@ -143,28 +134,22 @@ bool rsvg_convert(struct content *c, int iwidth, int iheight) c->width, c->height, bitmap_get_rowstride(d->bitmap))) == NULL) { LOG(("Failed to create Cairo image surface for rsvg render.")); - bitmap_destroy(d->bitmap); - rsvg_handle_free(d->rsvgh); msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; - } + } if ((d->ct = cairo_create(d->cs)) == NULL) { LOG(("Failed to create Cairo drawing context for rsvg render.")); - bitmap_destroy(d->bitmap); - rsvg_handle_free(d->rsvgh); - cairo_surface_destroy(d->cs); msg_data.error = messages_get("NoMemory"); content_broadcast(c, CONTENT_MSG_ERROR, msg_data); return false; } - + rsvg_handle_render_cairo(d->rsvgh, d->ct); - /* TODO: This currently segfaults */ -// rsvg_argb_to_abgr((u_int32_t *)bitmap_get_buffer(d->bitmap), -// c->width, c->height, -// bitmap_get_rowstride(d->bitmap)); + rsvg_argb_to_abgr((u_int32_t *)bitmap_get_buffer(d->bitmap), + c->width, c->height, + bitmap_get_rowstride(d->bitmap)); c->bitmap = d->bitmap; c->status = CONTENT_STATUS_DONE; @@ -192,10 +177,10 @@ void rsvg_destroy(struct content *c) { struct content_rsvg_data *d = &c->data.rsvg; - bitmap_destroy(d->bitmap); - rsvg_handle_free(d->rsvgh); - cairo_destroy(d->ct); - cairo_surface_destroy(d->cs); + if (d->bitmap != NULL) bitmap_destroy(d->bitmap); + if (d->rsvgh != NULL) rsvg_handle_free(d->rsvgh); + if (d->ct != NULL) cairo_destroy(d->ct); + if (d->cs != NULL) cairo_surface_destroy(d->cs); return; } -- cgit v1.2.3