/* -*- c-file-style: "ruby"; indent-tabs-mode: nil -*- */ /* * Copyright (C) 2011 Ruby-GNOME2 Project Team * Copyright (C) 2005-2006 Ruby-GNOME2 Project Team * Copyright (C) 2004 Kouhei Sutou * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301 USA */ #include "rsvg2.h" #define RG_TARGET_NAMESPACE cHandle #ifdef RSVG_TYPE_HANDLE # define _SELF(self) (RSVG_HANDLE(RVAL2GOBJ(self))) #else # define _SELF(self) ((RsvgHandle *)DATA_PTR(self)) #endif static VALUE RG_TARGET_NAMESPACE; static ID id_call; static ID id_callback; static ID id_closed; static void exec_callback(gint *width, gint *height, gpointer self) { VALUE result; result = rb_funcall(rb_ivar_get((VALUE)self, id_callback), id_call, 2, INT2NUM(*width), INT2NUM(*height)); if (T_ARRAY == TYPE(result)) { VALUE w, h; w = rb_ary_entry(result, 0); h = rb_ary_entry(result, 1); if (!NIL_P(w)) { *width = NUM2INT(w); } if (!NIL_P(h)) { *height = NUM2INT(h); } } } static VALUE rg_set_dpi(VALUE self, VALUE dpi) { #ifdef HAVE_RSVG_HANDLE_SET_DPI rsvg_handle_set_dpi(_SELF(self), NUM2DBL(dpi)); #else rb_warning("rsvg_handle_set_dpi isn't supported in your librsvg"); #endif return self; } static VALUE rg_set_dpi_x_y(VALUE self, VALUE dpi_x, VALUE dpi_y) { #ifdef HAVE_RSVG_HANDLE_SET_DPI_X_Y rsvg_handle_set_dpi_x_y(_SELF(self), NUM2DBL(dpi_x), NUM2DBL(dpi_y)); #else rb_warning("rsvg_handle_set_dpi_x_y isn't supported in your librsvg"); #endif return self; } #ifndef RSVG_TYPE_HANDLE static void rb_rsvg_handle_free(RsvgHandle *handle) { if (handle) { rsvg_handle_free(handle); } } static VALUE rb_rsvg_handle_alloc(VALUE klass) { return Data_Wrap_Struct(klass, 0, rb_rsvg_handle_free, 0); } #endif #if LIBRSVG_CHECK_VERSION(2, 14, 0) static VALUE rg_s_new_from_data(G_GNUC_UNUSED VALUE self, VALUE data) { GError *error = NULL; RsvgHandle *handle; handle = rsvg_handle_new_from_data((const guint8 *)RVAL2CSTR(data), RSTRING_LEN(data), &error); if (error) RAISE_GERROR(error); return GOBJ2RVAL(handle); } static VALUE rg_s_new_from_file(G_GNUC_UNUSED VALUE self, VALUE file) { GError *error = NULL; RsvgHandle *handle; handle = rsvg_handle_new_from_file((const gchar *)RVAL2CSTR(file), &error); if (error) RAISE_GERROR(error); return GOBJ2RVAL(handle); } #endif static VALUE rg_initialize(int argc, VALUE *argv, VALUE self) { RsvgHandle *handle; VALUE gz; rb_scan_args(argc, argv, "01", &gz); #if LIBRSVG_CHECK_VERSION(2, 11, 0) handle = rsvg_handle_new(); #else if (RVAL2CBOOL(gz)) { # ifdef HAVE_LIBRSVG_RSVG_GZ_H handle = rsvg_handle_new_gz(); # else rb_warning("gz handling is not supported in your librsvg"); handle = rsvg_handle_new(); # endif } else { handle = rsvg_handle_new(); } #endif #ifdef RSVG_TYPE_HANDLE G_INITIALIZE(self, handle); #else DATA_PTR(self) = handle; #endif rb_ivar_set(self, id_closed, Qfalse); return Qnil; } static VALUE rg_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; } static VALUE rg_write(VALUE self, VALUE buf) { gboolean result; GError *error = NULL; result = rsvg_handle_write(_SELF(self), (const guchar*)RVAL2CSTR(buf), RSTRING_LEN(buf), &error); if (!result) RAISE_GERROR(error); return CBOOL2RVAL(result); } static VALUE rg_close(VALUE self) { gboolean result; GError *error = NULL; if (RVAL2CBOOL(rb_ivar_get(self, id_closed))) { return Qnil; } result = rsvg_handle_close(_SELF(self), &error); if (result) { rb_ivar_set(self, id_closed, Qtrue); } else { RAISE_GERROR(error); } return CBOOL2RVAL(result); } static VALUE rg_closed_p(VALUE self) { return rb_ivar_get(self, id_closed); } static VALUE rg_pixbuf(int argc, VALUE *argv, VALUE self) { VALUE id; VALUE rb_pixbuf; GdkPixbuf *pixbuf = NULL; rb_scan_args(argc, argv, "01", &id); if (NIL_P(id)) { pixbuf = rsvg_handle_get_pixbuf(_SELF(self)); } else { #ifdef HAVE_RSVG_HANDLE_GET_PIXBUF_SUB pixbuf = rsvg_handle_get_pixbuf_sub(_SELF(self), (const char *)RVAL2CSTR(id)); #else rb_warning("rsvg_handle_get_pixbuf_sub isn't " "supported in your librsvg"); #endif } rb_pixbuf = GOBJ2RVAL(pixbuf); if (pixbuf) g_object_unref(pixbuf); return rb_pixbuf; } #if LIBRSVG_CHECK_VERSION(2, 9, 0) static VALUE rg_base_uri(VALUE self) { return CSTR2RVAL(rsvg_handle_get_base_uri(_SELF(self))); } static VALUE rg_set_base_uri(VALUE self, VALUE base_uri) { rsvg_handle_set_base_uri(_SELF(self), RVAL2CSTR(base_uri)); return self; } #endif #ifdef HAVE_TYPE_RSVGDIMENSIONDATA static VALUE rg_dimensions(VALUE self) { RsvgDimensionData dim; VALUE args[4]; VALUE cDimensionData = rb_const_get(rb_const_get(rb_cObject, rb_intern("RSVG")), rb_intern("DimensionData")); rsvg_handle_get_dimensions(_SELF(self), &dim); args[0] = INT2NUM(dim.width); args[1] = INT2NUM(dim.height); args[2] = rb_float_new(dim.em); args[3] = rb_float_new(dim.ex); return rb_class_new_instance(sizeof(args) / sizeof(VALUE), args, cDimensionData); } #endif /* Accessibility API */ static VALUE rg_title(VALUE self) { return CSTR2RVAL(rsvg_handle_get_title(_SELF(self))); } static VALUE rg_desc(VALUE self) { return CSTR2RVAL(rsvg_handle_get_desc(_SELF(self))); } #ifdef HAVE_RSVG_HANDLE_GET_METADATA static VALUE rg_metadata(VALUE self) { return CSTR2RVAL(rsvg_handle_get_metadata(_SELF(self))); } #endif #if !LIBRSVG_CHECK_VERSION(2, 11, 0) /* Extended Convenience API */ static VALUE rg_pixbuf_from_file_at_size(VALUE self, VALUE file_name, VALUE width, VALUE height) { VALUE rb_pixbuf; GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = rsvg_pixbuf_from_file_at_size_ex(_SELF(self), RVAL2CSTR(file_name), NUM2INT(width), NUM2INT(height), &error); if (error) RAISE_GERROR(error); rb_pixbuf = GOBJ2RVAL(pixbuf); g_object_unref(pixbuf); return rb_pixbuf; } static VALUE rg_pixbuf_from_file(VALUE self, VALUE file_name) { VALUE rb_pixbuf; GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = rsvg_pixbuf_from_file_ex(_SELF(self), RVAL2CSTR(file_name), &error); if (error) RAISE_GERROR(error); rb_pixbuf = GOBJ2RVAL(pixbuf); g_object_unref(pixbuf); return rb_pixbuf; } static VALUE rg_pixbuf_from_file_at_zoom(VALUE self, VALUE file_name, VALUE x_zoom, VALUE y_zoom) { VALUE rb_pixbuf; GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = rsvg_pixbuf_from_file_at_zoom_ex(_SELF(self), RVAL2CSTR(file_name), NUM2DBL(x_zoom), NUM2DBL(y_zoom), &error); if (error) RAISE_GERROR(error); rb_pixbuf = GOBJ2RVAL(pixbuf); g_object_unref(pixbuf); return rb_pixbuf; } static VALUE rg_pixbuf_from_file_at_max_size(VALUE self, VALUE file_name, VALUE max_width, VALUE max_height) { VALUE rb_pixbuf; GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = rsvg_pixbuf_from_file_at_max_size_ex(_SELF(self), RVAL2CSTR(file_name), NUM2INT(max_width), NUM2INT(max_height), &error); if (error) RAISE_GERROR(error); rb_pixbuf = GOBJ2RVAL(pixbuf); g_object_unref(pixbuf); return rb_pixbuf; } static VALUE rg_pixbuf_from_file_at_zoom_with_max(VALUE self, VALUE file_name, VALUE x_zoom, VALUE y_zoom, VALUE max_width, VALUE max_height) { VALUE rb_pixbuf; GdkPixbuf *pixbuf; GError *error = NULL; pixbuf = rsvg_pixbuf_from_file_at_zoom_with_max_ex(_SELF(self), RVAL2CSTR(file_name), NUM2DBL(x_zoom), NUM2DBL(y_zoom), NUM2INT(max_width), NUM2INT(max_height), &error); if (error) RAISE_GERROR(error); rb_pixbuf = GOBJ2RVAL(pixbuf); g_object_unref(pixbuf); return rb_pixbuf; } #endif #ifdef HAVE_LIBRSVG_RSVG_CAIRO_H static VALUE rg_render_cairo(int argc, VALUE *argv, VALUE self) { VALUE cr, id; rb_scan_args(argc, argv, "11", &cr, &id); if (NIL_P(id)) { rsvg_handle_render_cairo( _SELF(self), RVAL2CRCONTEXT(cr)); } else { rsvg_handle_render_cairo_sub( _SELF(self), RVAL2CRCONTEXT(cr), (const char *)RVAL2CSTR(id)); } return Qnil; } #endif void Init_rsvg_handle(VALUE mRSVG) { id_call = rb_intern("call"); id_callback = rb_intern("callback"); id_closed = rb_intern("closed"); #ifdef RSVG_TYPE_HANDLE RG_TARGET_NAMESPACE = G_DEF_CLASS(RSVG_TYPE_HANDLE, "Handle", mRSVG); #else RG_TARGET_NAMESPACE = rb_define_class_under(mRSVG, "Handle", rb_cObject); rb_define_alloc_func(RG_TARGET_NAMESPACE, rb_rsvg_handle_alloc); #endif #if LIBRSVG_CHECK_VERSION(2, 14, 0) RG_DEF_SMETHOD(new_from_data, 1); RG_DEF_SMETHOD(new_from_file, 1); #endif RG_DEF_METHOD(initialize, -1); RG_DEF_METHOD(set_size_callback, 0); RG_DEF_METHOD(set_dpi, 1); RG_DEF_METHOD(set_dpi_x_y, 2); RG_DEF_METHOD(write, 1); RG_DEF_METHOD(close, 0); RG_DEF_METHOD_P(closed, 0); RG_DEF_METHOD(pixbuf, -1); #if LIBRSVG_CHECK_VERSION(2, 9, 0) RG_DEF_METHOD(base_uri, 0); RG_DEF_METHOD(set_base_uri, 1); #endif #ifdef HAVE_TYPE_RSVGDIMENSIONDATA RG_DEF_METHOD(dimensions, 0); #endif /* Accessibility API */ RG_DEF_METHOD(title, 0); RG_DEF_METHOD(desc, 0); #ifdef HAVE_RSVG_HANDLE_GET_METADATA RG_DEF_METHOD(metadata, 0); #endif #if !LIBRSVG_CHECK_VERSION(2, 11, 0) /* Extended Convenience API */ RG_DEF_METHOD(pixbuf_from_file_at_size, 3); RG_DEF_METHOD(pixbuf_from_file, 1); RG_DEF_METHOD(pixbuf_from_file_at_zoom, 3); RG_DEF_METHOD(pixbuf_from_file_at_max_size, 3); RG_DEF_METHOD(pixbuf_from_file_at_zoom_with_max, 5); #endif #ifdef HAVE_LIBRSVG_RSVG_CAIRO_H RG_DEF_METHOD(render_cairo, -1); #endif }