static void draw_page (GtkPrintOperation *operation, GtkPrintContext *context, gint page_nr, gpointer user_data) { ViewerCbInfo *info = (ViewerCbInfo *) user_data; cairo_t *cr; gdouble page_width, page_height; cr = gtk_print_context_get_cairo_context (context); page_width = gtk_print_context_get_width (context); page_height = gtk_print_context_get_height (context); { RsvgHandle *handle; RsvgDimensionData svg_dimensions; struct RsvgSizeCallbackData size_data; /* should not fail */ handle = rsvg_handle_new_from_data(info->svg_bytes->data, info->svg_bytes->len, NULL); rsvg_handle_set_base_uri (handle, info->base_uri); rsvg_handle_set_dpi_x_y (handle, gtk_print_context_get_dpi_x(context), gtk_print_context_get_dpi_y(context)); rsvg_handle_get_dimensions(handle, &svg_dimensions); if (svg_dimensions.width > page_width || svg_dimensions.height > page_height) { /* scale down the image to the page's size, while preserving the aspect ratio */ if ((double) svg_dimensions.height * (double) page_width > (double) svg_dimensions.width * (double) page_height) { svg_dimensions.width = 0.5 + (double) svg_dimensions.width *(double) page_height / (double) svg_dimensions.height; svg_dimensions.height = page_height; } else { svg_dimensions.height = 0.5 + (double) svg_dimensions.height *(double) page_width / (double) svg_dimensions.width; svg_dimensions.width = page_width; } } size_data.type = RSVG_SIZE_WH; size_data.width = svg_dimensions.width; size_data.height = svg_dimensions.height; size_data.keep_aspect_ratio = FALSE; rsvg_handle_set_size_callback (handle, _rsvg_size_callback, &size_data, NULL); rsvg_handle_render_cairo(handle, cr); g_object_unref (handle); } }
static GdkPixbuf * pixbuf_from_data_with_size_data (const guchar * buff, size_t len, struct RsvgSizeCallbackData *data, const char *base_uri, const char *id, GError ** error) { RsvgHandle *handle; GdkPixbuf *retval; handle = rsvg_handle_new (); if (!handle) { g_set_error (error, rsvg_error_quark (), 0, _("Error creating SVG reader")); return NULL; } rsvg_handle_set_size_callback (handle, _rsvg_size_callback, data, NULL); rsvg_handle_set_base_uri (handle, base_uri); if (!rsvg_handle_write (handle, buff, len, error)) { g_object_unref (G_OBJECT (handle)); return NULL; } if (!rsvg_handle_close (handle, error)) { g_object_unref (G_OBJECT (handle)); return NULL; } retval = rsvg_handle_get_pixbuf_sub (handle, id); g_object_unref (G_OBJECT (handle)); return retval; }
/* This function renders a pixbuf from an SVG file according to vals. */ static GdkPixbuf * load_rsvg_pixbuf (const gchar *filename, SvgLoadVals *vals, GError **error) { GdkPixbuf *pixbuf = NULL; RsvgHandle *handle; GIOChannel *io; gchar *uri; GIOStatus status = G_IO_STATUS_NORMAL; gboolean success = TRUE; io = g_io_channel_new_file (filename, "r", error); if (!io) return NULL; g_io_channel_set_encoding (io, NULL, NULL); handle = rsvg_handle_new (); rsvg_handle_set_dpi (handle, vals->resolution); /* set the base URI so that librsvg can resolve relative paths */ uri = g_filename_to_uri (filename, NULL, NULL); if (uri) { gchar *p = strrchr (uri, '/'); if (p) *p = '\0'; rsvg_handle_set_base_uri (handle, uri); g_free (uri); } rsvg_handle_set_size_callback (handle, load_set_size_callback, vals, NULL); while (success && status != G_IO_STATUS_EOF) { gchar buf[8192]; gsize len; status = g_io_channel_read_chars (io, buf, sizeof (buf), &len, error); switch (status) { case G_IO_STATUS_ERROR: success = FALSE; break; case G_IO_STATUS_EOF: success = rsvg_handle_close (handle, error); break; case G_IO_STATUS_NORMAL: success = rsvg_handle_write (handle, (const guchar *) buf, len, error); break; case G_IO_STATUS_AGAIN: break; } } g_io_channel_unref (io); if (success) pixbuf = rsvg_handle_get_pixbuf (handle); g_object_unref (handle); return pixbuf; }
static gboolean gdk_pixbuf__svg_image_load_increment (gpointer data, const guchar *buf, guint size, GError **error) { SvgContext *context = (SvgContext *)data; if (error) *error = NULL; if (context->first_write == TRUE) { context->first_write = FALSE; context->handle = rsvg_handle_new (); if (!context->handle) { rsvg_propegate_error (error, _("Error displaying image"), ERROR_DISPLAYING_IMAGE); return FALSE; } rsvg_handle_set_size_callback (context->handle, context->size_func, context->user_data, NULL); } if (!context->handle) { rsvg_propegate_error (error, _("Error displaying image"), ERROR_DISPLAYING_IMAGE); return FALSE; } if (!rsvg_handle_write (context->handle, buf, size, error)) { rsvg_propegate_error (error, _("Error writing"), ERROR_WRITING); return FALSE; } return TRUE; }
CAMLprim value ml_rsvg_handle_set_size_callback(value vh, value cb) { RsvgHandle *h = RsvgHandle_val(vh); value *u_data = ml_global_root_new(cb); rsvg_handle_set_size_callback(h, ml_rsvg_size_callback, u_data, ml_global_root_destroy); return Val_unit; }
static VALUE rb_rsvg_handle_set_size_callback(VALUE self) { rb_ivar_set(self, id_callback, rb_block_proc()); rsvg_handle_set_size_callback(_SELF(self), exec_callback, (gpointer)self, NULL); return self; }
PyObject * render_svg_to_buffer(PyObject *module, PyObject *args, PyObject *kwargs) { int len, w, h, i; guchar *svgdata; GError *error; RsvgHandle *svg; GdkPixbuf *pixbuf; gboolean res; size_cb_data cbdata; PyObject *buffer; guchar *buffer_ptr; if (!PyArg_ParseTuple(args, "iis#", &w, &h, &svgdata, &len)) return NULL; cbdata.w = w; cbdata.h = h; svg = rsvg_handle_new(); rsvg_handle_set_size_callback(svg, size_cb, &cbdata, NULL); res = rsvg_handle_write(svg, svgdata, len, &error); res = rsvg_handle_close(svg, &error); pixbuf = rsvg_handle_get_pixbuf(svg); rsvg_handle_free(svg); w = gdk_pixbuf_get_width(pixbuf); h = gdk_pixbuf_get_height(pixbuf); buffer = PyBuffer_New(w*h*4); PyObject_AsWriteBuffer(buffer, (void **)&buffer_ptr, &len); memcpy(buffer_ptr, gdk_pixbuf_get_pixels(pixbuf), w*h*4); g_object_unref(pixbuf); // RGBA to BGRA conversion. // FIXME: MMXify. for (i = 0; i < w*h*4; i+=4) { guchar save = buffer_ptr[i+2]; buffer_ptr[i+2] = buffer_ptr[i]; buffer_ptr[i] = save; } return Py_BuildValue("(iiO)", w, h, buffer); }