File: rb_cairo_quartz_surface.c

package info (click to toggle)
ruby-cairo 1.17.13-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,532 kB
  • sloc: ruby: 11,997; ansic: 10,183; sh: 48; makefile: 4
file content (212 lines) | stat: -rw-r--r-- 5,701 bytes parent folder | download
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
}