1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
|
/* -*- mode: objc; c-file-style: "gnu"; indent-tabs-mode: nil -*- */
/*
* Ruby Cairo Binding
*
* Copyright 2008-2015 Kouhei Sutou <kou@cozmixng.org>
* Copyright 2014 Patrick Hanevold <patrick.hanevold@gmail.com>
*
* 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 <cairo-quartz.h>
# define T_DATA RUBY_T_DATA
# define RB_CAIRO_HAS_QUARTZ_SURFACE
# ifdef CAIRO_HAS_QUARTZ_IMAGE_SURFACE
# include <cairo-quartz-image.h>
# define RB_CAIRO_HAS_QUARTZ_IMAGE_SURFACE
# endif
#endif
#define _SELF (RVAL2CRSURFACE(self))
#ifdef RB_CAIRO_HAS_QUARTZ_SURFACE
/* Quartz-surface functions */
#include <objc/objc-runtime.h>
# 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
}
|