/* -*- mode: objc; c-file-style: "gnu"; indent-tabs-mode: nil -*- */ /* * Ruby Cairo Binding * * Copyright 2008-2015 Kouhei Sutou * Copyright 2014 Patrick Hanevold * * This file is made available under the same terms as Ruby * */ #include "rb_cairo.h" #include "rb_cairo_private.h" #if CAIRO_CHECK_VERSION(1, 5, 12) # define RB_CAIRO_HAS_QUARTZ_IMAGE_SURFACE_TYPE #endif #ifdef CAIRO_HAS_QUARTZ_SURFACE static ID cr_id_image_surface; # ifndef HAVE_TYPE_ENUM_RUBY_VALUE_TYPE enum ruby_value_type { RUBY_T_DATA = T_DATA }; # endif # undef T_DATA # include # define T_DATA RUBY_T_DATA # define RB_CAIRO_HAS_QUARTZ_SURFACE # ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE # include # define RB_CAIRO_HAS_QUARTZ_IMAGE_SURFACE # endif #endif #define _SELF (RVAL2CRSURFACE(self)) #ifdef RB_CAIRO_HAS_QUARTZ_SURFACE /* Quartz-surface functions */ #include # ifdef HAVE_RUBY_COCOA BOOL rbobj_to_nsobj (VALUE obj, id* nsobj); VALUE ocid_to_rbobj (VALUE context_obj, id ocid); # endif static VALUE cr_quartz_surface_initialize (int argc, VALUE *argv, VALUE self) { id objc_object = nil; CGContextRef context; unsigned int width, height; cairo_surface_t *surface = NULL; cairo_format_t format = CAIRO_FORMAT_ARGB32; VALUE arg1, arg2, arg3, rb_width, rb_height; # ifdef HAVE_RUBY_COCOA static VALUE rb_cOSXCGContextRef = Qnil; # endif rb_scan_args (argc, argv, "21", &arg1, &arg2, &arg3); if (argc == 2) { rb_width = arg1; rb_height = arg2; } else { switch (TYPE (arg1)) { case T_NIL: break; case T_STRING: case T_SYMBOL: case T_FIXNUM: format = RVAL2CRFORMAT (arg1); break; default: # ifdef HAVE_RUBY_COCOA if (NIL_P (rb_cOSXCGContextRef)) rb_cOSXCGContextRef = rb_const_get (rb_const_get (rb_cObject, rb_intern ("OSX")), rb_intern ("CGContextRef")); # endif # ifdef HAVE_RUBY_COCOA if (RTEST (rb_obj_is_kind_of (arg1, rb_cOSXCGContextRef))) { rbobj_to_nsobj (arg1, &objc_object); } else # endif { if (!NIL_P (rb_cairo__cFFIPointer) && RTEST (rb_obj_is_kind_of (arg1, rb_cairo__cFFIPointer))) { VALUE rb_objc_pointer; rb_objc_pointer = rb_funcall (arg1, rb_intern ("address"), 0); objc_object = (id) NUM2ULONG (rb_objc_pointer); } else { rb_raise (rb_eArgError, "invalid argument (expect " "(width, height), " "(format, width, height), " "(cg_context, width, height) or " "(ffi_pointer, width, height)): %s", rb_cairo__inspect (rb_ary_new3 (3, arg1, arg2, arg3))); } } break; } rb_width = arg2; rb_height = arg3; } width = NUM2UINT (rb_width); height = NUM2UINT (rb_height); if (objc_object == nil) { surface = cairo_quartz_surface_create (format, width, height); } else { context = (CGContextRef)objc_object; surface = cairo_quartz_surface_create_for_cg_context (context, width, height); } rb_cairo_surface_check_status (surface); RTYPEDDATA_DATA (self) = surface; if (rb_block_given_p ()) rb_cairo__surface_yield_and_finish (self); return Qnil; } static VALUE cr_quartz_surface_get_cg_context (VALUE self) { # ifdef HAVE_RUBY_COCOA CGContextRef context; id objc_object; context = cairo_quartz_surface_get_cg_context (_SELF); objc_object = (id)context; return ocid_to_rbobj (Qnil, objc_object); # else rb_raise (rb_eNotImpError, "%s#cg_context requires RubyCocoa", rb_obj_classname(self)); return Qnil; # endif } #endif #ifdef RB_CAIRO_HAS_QUARTZ_IMAGE_SURFACE /* Quartz image surface functions */ static VALUE cr_quartz_image_surface_initialize (VALUE self, VALUE image_surface) { cairo_surface_t *surface; surface = cairo_quartz_image_surface_create (RVAL2CRSURFACE (image_surface)); rb_cairo_surface_check_status (surface); RTYPEDDATA_DATA (self) = surface; rb_ivar_set (self, cr_id_image_surface, image_surface); if (rb_block_given_p ()) rb_cairo__surface_yield_and_finish (self); return Qnil; } static VALUE cr_quartz_image_surface_get_image (VALUE self) { cairo_surface_t *surface; surface = cairo_quartz_image_surface_get_image (_SELF); if (!surface) return Qnil; rb_cairo_surface_check_status (surface); return CRSURFACE2RVAL (surface); } #endif void Init_cairo_quartz_surface (void) { /* Quartz surface */ #ifdef RB_CAIRO_HAS_QUARTZ_SURFACE rb_define_method (rb_cCairo_QuartzSurface, "initialize", cr_quartz_surface_initialize, -1); rb_define_method (rb_cCairo_QuartzSurface, "cg_context", cr_quartz_surface_get_cg_context, 0); #endif /* Quartz image surface */ #ifdef RB_CAIRO_HAS_QUARTZ_IMAGE_SURFACE cr_id_image_surface = rb_intern ("image_surface"); rb_define_method (rb_cCairo_QuartzImageSurface, "initialize", cr_quartz_image_surface_initialize, 1); rb_define_method (rb_cCairo_QuartzImageSurface, "image", cr_quartz_image_surface_get_image, 0); #endif }