cairo 1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of cairo might be problematic. Click here for more details.

@@ -0,0 +1,51 @@
1
+ /* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Ruby Cairo Binding
4
+ *
5
+ * $Author: kou $
6
+ * $Date: 2007/03/06 12:17:34 $
7
+ *
8
+ * Copyright 2005 Kouhei Sutou <kou@cozmixng.org>
9
+ *
10
+ * This file is made available under the same terms as Ruby
11
+ *
12
+ */
13
+
14
+ #include "rb_cairo.h"
15
+
16
+ VALUE
17
+ rb_cairo__float_array (double *values, unsigned count)
18
+ {
19
+ VALUE result;
20
+ int i;
21
+
22
+ result = rb_ary_new2 (count);
23
+ for (i = 0; i < count; i++)
24
+ {
25
+ rb_ary_push (result, rb_float_new (values[i]));
26
+ }
27
+ return result;
28
+ }
29
+
30
+ void
31
+ rb_cairo__glyphs_to_array (VALUE rb_array, cairo_glyph_t **glyphs, int *length)
32
+ {
33
+ int i;
34
+
35
+ if (!rb_obj_is_kind_of (rb_array, rb_cArray))
36
+ rb_raise (rb_eTypeError, "expected array");
37
+
38
+ *length = RARRAY(rb_array)->len;
39
+ *glyphs = ALLOCA_N (cairo_glyph_t, *length);
40
+
41
+ if (!*glyphs)
42
+ rb_cairo_check_status (CAIRO_STATUS_NO_MEMORY);
43
+
44
+ for (i = 0; i < *length; i++)
45
+ {
46
+ memcpy ((char *) &(*glyphs)[i],
47
+ (char *) RVAL2CRGLYPH (rb_ary_entry (rb_array, i)),
48
+ sizeof (cairo_glyph_t));
49
+ }
50
+ }
51
+
@@ -0,0 +1,23 @@
1
+ /* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Ruby Cairo Binding
4
+ *
5
+ * $Author: kou $
6
+ * $Date: 2007/03/06 12:17:34 $
7
+ *
8
+ * Copyright 2005 Kouhei Sutou <kou@cozmixng.org>
9
+ *
10
+ * This file is made available under the same terms as Ruby
11
+ *
12
+ */
13
+
14
+ #ifndef RB_CAIRO_PRIVATE_H
15
+ #define RB_CAIRO_PRIVATE_H
16
+
17
+ #define CR_TRUE 1
18
+ #define CR_FALSE 0
19
+
20
+ VALUE rb_cairo__float_array (double *values, unsigned count);
21
+ void rb_cairo__glyphs_to_array (VALUE rb_array, cairo_glyph_t **glyphs, int *length);
22
+
23
+ #endif
@@ -0,0 +1,184 @@
1
+ /* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Ruby Cairo Binding
4
+ *
5
+ * $Author: kou $
6
+ * $Date: 2007/03/06 12:17:34 $
7
+ *
8
+ * Copyright 2005 Kouhei Sutou <kou@cozmixng.org>
9
+ *
10
+ * This file is made available under the same terms as Ruby
11
+ *
12
+ */
13
+
14
+
15
+ #include "rb_cairo.h"
16
+ #include "rb_cairo_private.h"
17
+
18
+ VALUE rb_cCairo_ScaledFont;
19
+
20
+ #define _SELF(self) (RVAL2CRSCALEDFONT(self))
21
+
22
+ static inline void
23
+ cr_scaled_font_check_status (cairo_scaled_font_t *font)
24
+ {
25
+ rb_cairo_check_status (cairo_scaled_font_status (font));
26
+ }
27
+
28
+ cairo_scaled_font_t *
29
+ rb_cairo_scaled_font_from_ruby_object (VALUE obj)
30
+ {
31
+ cairo_scaled_font_t *font;
32
+ if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_ScaledFont)))
33
+ {
34
+ rb_raise (rb_eTypeError, "not a cairo scaled font");
35
+ }
36
+ Data_Get_Struct (obj, cairo_scaled_font_t, font);
37
+ return font;
38
+ }
39
+
40
+ static void
41
+ cr_scaled_font_free (void *ptr)
42
+ {
43
+ if (ptr)
44
+ {
45
+ cairo_scaled_font_destroy ((cairo_scaled_font_t *) ptr);
46
+ }
47
+ }
48
+
49
+ VALUE
50
+ rb_cairo_scaled_font_to_ruby_object (cairo_scaled_font_t *font)
51
+ {
52
+ if (font)
53
+ {
54
+ cairo_scaled_font_reference (font);
55
+ return Data_Wrap_Struct (rb_cCairo_ScaledFont, NULL,
56
+ cr_scaled_font_free, font);
57
+ }
58
+ else
59
+ {
60
+ return Qnil;
61
+ }
62
+ }
63
+
64
+ static VALUE
65
+ cr_scaled_font_allocate (VALUE klass)
66
+ {
67
+ return Data_Wrap_Struct (klass, NULL, cr_scaled_font_free, NULL);
68
+ }
69
+
70
+ static VALUE
71
+ cr_scaled_font_initialize (VALUE self, VALUE face, VALUE matrix,
72
+ VALUE ctm, VALUE options)
73
+ {
74
+ cairo_scaled_font_t *font;
75
+
76
+ font = cairo_scaled_font_create (RVAL2CRFONTFACE (face),
77
+ RVAL2CRMATRIX (matrix),
78
+ RVAL2CRMATRIX (ctm),
79
+ RVAL2CRFONTOPTIONS (options));
80
+ cr_scaled_font_check_status (font);
81
+ DATA_PTR (self) = font;
82
+ return Qnil;
83
+ }
84
+
85
+ static VALUE
86
+ cr_scaled_font_get_type (VALUE self)
87
+ {
88
+ return INT2NUM (cairo_scaled_font_get_type ( _SELF (self)));
89
+ }
90
+
91
+ static VALUE
92
+ cr_scaled_font_extents (VALUE self)
93
+ {
94
+ cairo_font_extents_t extents;
95
+ cairo_scaled_font_extents (_SELF (self), &extents);
96
+ cr_scaled_font_check_status (_SELF (self));
97
+ return CRFONTEXTENTS2RVAL (&extents);
98
+ }
99
+
100
+ static VALUE
101
+ cr_scaled_font_text_extents (VALUE self, VALUE utf8)
102
+ {
103
+ cairo_text_extents_t extents;
104
+ cairo_scaled_font_text_extents (_SELF (self), StringValueCStr (utf8),
105
+ &extents);
106
+ cr_scaled_font_check_status (_SELF (self));
107
+ return CRTEXTEXTENTS2RVAL (&extents);
108
+ }
109
+
110
+ static VALUE
111
+ cr_scaled_font_glyph_extents (VALUE self, VALUE rb_glyphs)
112
+ {
113
+ cairo_text_extents_t extents;
114
+ cairo_glyph_t *glyphs;
115
+ int count;
116
+
117
+ rb_cairo__glyphs_to_array (rb_glyphs, &glyphs, &count);
118
+ cairo_scaled_font_glyph_extents (_SELF (self), glyphs, count, &extents);
119
+ cr_scaled_font_check_status (_SELF (self));
120
+ return CRTEXTEXTENTS2RVAL (&extents);
121
+ }
122
+
123
+ static VALUE
124
+ cr_scaled_font_get_font_face (VALUE self)
125
+ {
126
+ cairo_font_face_t *face;
127
+ face = cairo_scaled_font_get_font_face (_SELF (self));
128
+ cr_scaled_font_check_status (_SELF (self));
129
+ return CRFONTFACE2RVAL (face);
130
+ }
131
+
132
+ static VALUE
133
+ cr_scaled_font_get_font_matrix (VALUE self)
134
+ {
135
+ cairo_matrix_t font_matrix;
136
+ cairo_scaled_font_get_font_matrix (_SELF (self), &font_matrix);
137
+ cr_scaled_font_check_status (_SELF (self));
138
+ return CRMATRIX2RVAL (&font_matrix);
139
+ }
140
+
141
+ static VALUE
142
+ cr_scaled_font_get_ctm (VALUE self)
143
+ {
144
+ cairo_matrix_t ctm;
145
+ cairo_scaled_font_get_font_matrix (_SELF (self), &ctm);
146
+ cr_scaled_font_check_status (_SELF (self));
147
+ return CRMATRIX2RVAL (&ctm);
148
+ }
149
+
150
+ static VALUE
151
+ cr_scaled_font_get_font_options (VALUE self)
152
+ {
153
+ cairo_font_options_t *options = cairo_font_options_create();
154
+ cairo_scaled_font_get_font_options (_SELF (self), options);
155
+ cr_scaled_font_check_status (_SELF (self));
156
+ rb_cairo_check_status (cairo_font_options_status (options));
157
+ return CRFONTOPTIONS2RVAL (options);
158
+ }
159
+
160
+ void
161
+ Init_cairo_scaled_font (void)
162
+ {
163
+ rb_cCairo_ScaledFont =
164
+ rb_define_class_under (rb_mCairo, "ScaledFont", rb_cObject);
165
+
166
+ rb_define_alloc_func (rb_cCairo_ScaledFont, cr_scaled_font_allocate);
167
+
168
+ rb_define_method (rb_cCairo_ScaledFont, "initialize",
169
+ cr_scaled_font_initialize, 4);
170
+
171
+ rb_define_method (rb_cCairo_ScaledFont, "type", cr_scaled_font_get_type, 0);
172
+ rb_define_method (rb_cCairo_ScaledFont, "extents", cr_scaled_font_extents, 0);
173
+ rb_define_method (rb_cCairo_ScaledFont, "text_extents",
174
+ cr_scaled_font_text_extents, 1);
175
+ rb_define_method (rb_cCairo_ScaledFont, "glyph_extents",
176
+ cr_scaled_font_glyph_extents, 1);
177
+ rb_define_method (rb_cCairo_ScaledFont, "font_face",
178
+ cr_scaled_font_get_font_face, 0);
179
+ rb_define_method (rb_cCairo_ScaledFont, "font_matrix",
180
+ cr_scaled_font_get_font_matrix, 0);
181
+ rb_define_method (rb_cCairo_ScaledFont, "ctm", cr_scaled_font_get_ctm, 0);
182
+ rb_define_method (rb_cCairo_ScaledFont, "font_options",
183
+ cr_scaled_font_get_font_options, 0);
184
+ }
@@ -0,0 +1,837 @@
1
+ /* -*- c-file-style: "gnu"; indent-tabs-mode: nil -*- */
2
+ /*
3
+ * Ruby Cairo Binding
4
+ *
5
+ * $Author: kou $
6
+ * $Date: 2007/03/06 12:17:34 $
7
+ *
8
+ * Copyright 2005 Øyvind Kolås <pippin@freedesktop.org>
9
+ * Copyright 2004-2005 MenTaLguY <mental@rydia.com>
10
+ *
11
+ * This file is made available under the same terms as Ruby
12
+ *
13
+ */
14
+
15
+ #include "rb_cairo.h"
16
+ #include "rb_cairo_private.h"
17
+
18
+ #include "rubyio.h"
19
+
20
+ #if CAIRO_HAS_PS_SURFACE || CAIRO_HAS_PDF_SURFACE || CAIRO_HAS_SVG_SURFACE
21
+ # define HAS_CREATE_CR_CLOSURE_SURFACE 1
22
+ #else
23
+ # define HAS_CREATE_CR_CLOSURE_SURFACE 0
24
+ #endif
25
+
26
+
27
+ VALUE rb_cCairo_Surface;
28
+ VALUE rb_cCairo_ImageSurface;
29
+ VALUE rb_cCairo_PDFSurface;
30
+ VALUE rb_cCairo_PSSurface;
31
+ VALUE rb_cCairo_SVGSurface;
32
+
33
+ static ID cr_id_target;
34
+ static ID cr_id_read;
35
+ static ID cr_id_write;
36
+ static cairo_user_data_key_t cr_klass_key;
37
+ static cairo_user_data_key_t cr_closure_key;
38
+
39
+ #define _SELF (RVAL2CRSURFACE(self))
40
+
41
+ static inline void
42
+ cr_surface_check_status (cairo_surface_t *surface)
43
+ {
44
+ rb_cairo_check_status (cairo_surface_status (surface));
45
+ }
46
+
47
+ static void
48
+ cr_surface_set_klass (cairo_surface_t *surface, VALUE klass)
49
+ {
50
+ cairo_status_t status;
51
+ status = cairo_surface_set_user_data (surface, &cr_klass_key,
52
+ (void *)klass, NULL);
53
+ rb_cairo_check_status (status);
54
+ }
55
+
56
+ static VALUE
57
+ cr_surface_get_klass (cairo_surface_t *surface)
58
+ {
59
+ VALUE klass;
60
+ void *data = cairo_surface_get_user_data (surface, &cr_klass_key);
61
+
62
+ if (data)
63
+ klass = (VALUE) data;
64
+ else
65
+ {
66
+ switch (cairo_surface_get_type (surface))
67
+ {
68
+ case CAIRO_SURFACE_TYPE_IMAGE:
69
+ klass = rb_cCairo_ImageSurface;
70
+ break;
71
+ case CAIRO_SURFACE_TYPE_PDF:
72
+ klass = rb_cCairo_PDFSurface;
73
+ break;
74
+ case CAIRO_SURFACE_TYPE_PS:
75
+ klass = rb_cCairo_PSSurface;
76
+ break;
77
+ case CAIRO_SURFACE_TYPE_SVG:
78
+ klass = rb_cCairo_SVGSurface;
79
+ break;
80
+ default:
81
+ klass = rb_cCairo_Surface;
82
+ break;
83
+ }
84
+ }
85
+
86
+ return klass;
87
+ }
88
+
89
+ /* read/write callback */
90
+ typedef struct cr_io_callback_closure {
91
+ VALUE target;
92
+ VALUE error;
93
+ unsigned char *data;
94
+ unsigned int length;
95
+ } cr_io_callback_closure_t;
96
+
97
+ #if HAS_CREATE_CR_CLOSURE_SURFACE
98
+ static cr_io_callback_closure_t *
99
+ cr_closure_new (VALUE target)
100
+ {
101
+ cr_io_callback_closure_t *closure;
102
+ closure = ALLOC (cr_io_callback_closure_t);
103
+
104
+ closure->target = target;
105
+ closure->error = Qnil;
106
+
107
+ return closure;
108
+ }
109
+
110
+ static void
111
+ cr_closure_destroy (cr_io_callback_closure_t *closure)
112
+ {
113
+ free (closure);
114
+ }
115
+
116
+ static void
117
+ cr_closure_free (void *closure)
118
+ {
119
+ cr_closure_destroy ((cr_io_callback_closure_t *) closure);
120
+ }
121
+ #endif
122
+
123
+ static VALUE
124
+ cr_surface_io_func_rescue (VALUE io_closure)
125
+ {
126
+ cr_io_callback_closure_t *closure;
127
+ closure = (cr_io_callback_closure_t *)io_closure;
128
+ closure->error = ruby_errinfo;
129
+ return Qnil;
130
+ }
131
+
132
+ /* write callback */
133
+ static VALUE
134
+ cr_surface_write_func_invoke (VALUE write_closure)
135
+ {
136
+ VALUE output, data;
137
+ long written_bytes;
138
+ cr_io_callback_closure_t *closure;
139
+ unsigned int length;
140
+
141
+ closure = (cr_io_callback_closure_t *)write_closure;
142
+
143
+ output = closure->target;
144
+ data = rb_str_new ((const char *)closure->data, closure->length);
145
+
146
+ length = RSTRING (data)->len;
147
+ while (length != 0)
148
+ {
149
+ VALUE rb_written_bytes = rb_funcall (output, cr_id_write, 1, data);
150
+ written_bytes = NUM2LONG (rb_written_bytes);
151
+ data = rb_str_substr (data, written_bytes,
152
+ RSTRING (data)->len - written_bytes);
153
+ length -= written_bytes;
154
+ }
155
+
156
+ return Qnil;
157
+ }
158
+
159
+ static cairo_status_t
160
+ cr_surface_write_func (void *write_closure,
161
+ const unsigned char *data, unsigned int length)
162
+ {
163
+ cr_io_callback_closure_t *closure;
164
+
165
+ closure = (cr_io_callback_closure_t *)write_closure;
166
+ closure->data = (unsigned char *)data;
167
+ closure->length = length;
168
+
169
+ rb_rescue2 (cr_surface_write_func_invoke, (VALUE) closure,
170
+ cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
171
+ (VALUE)0);
172
+
173
+ if (NIL_P (closure->error))
174
+ return CAIRO_STATUS_SUCCESS;
175
+ else
176
+ return CAIRO_STATUS_WRITE_ERROR;
177
+ }
178
+
179
+ /* read callback */
180
+ static VALUE
181
+ cr_surface_read_func_invoke (VALUE read_closure)
182
+ {
183
+ VALUE input, result;
184
+ cr_io_callback_closure_t *closure;
185
+ unsigned int length, rest;
186
+
187
+ closure = (cr_io_callback_closure_t *)read_closure;
188
+ input = closure->target;
189
+ length = closure->length;
190
+
191
+ result = rb_str_new2 ("");
192
+
193
+ for (rest = length; rest != 0; rest = length - RSTRING (result)->len)
194
+ {
195
+ rb_str_concat (result, rb_funcall (input, cr_id_read, 1, INT2NUM (rest)));
196
+ }
197
+
198
+ memcpy ((void *)closure->data, (const void *)StringValuePtr (result), length);
199
+
200
+ return Qnil;
201
+ }
202
+
203
+ static cairo_status_t
204
+ cr_surface_read_func (void *read_closure,
205
+ unsigned char *data, unsigned int length)
206
+ {
207
+ cr_io_callback_closure_t *closure;
208
+
209
+ closure = (cr_io_callback_closure_t *)read_closure;
210
+ closure->data = data;
211
+ closure->length = length;
212
+ rb_rescue2 (cr_surface_read_func_invoke, (VALUE) closure,
213
+ cr_surface_io_func_rescue, (VALUE) closure, rb_eException,
214
+ (VALUE)0);
215
+
216
+ if (NIL_P (closure->error))
217
+ return CAIRO_STATUS_SUCCESS;
218
+ else
219
+ return CAIRO_STATUS_READ_ERROR;
220
+ }
221
+
222
+ /* constructor/de-constructor */
223
+ cairo_surface_t *
224
+ rb_cairo_surface_from_ruby_object (VALUE obj)
225
+ {
226
+ cairo_surface_t *surface;
227
+ if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Surface)))
228
+ {
229
+ rb_raise (rb_eTypeError, "not a cairo surface");
230
+ }
231
+ Data_Get_Struct (obj, cairo_surface_t, surface);
232
+ cr_surface_set_klass (surface, rb_obj_class (obj));
233
+ return surface;
234
+ }
235
+
236
+ static void
237
+ cr_surface_free (void *ptr)
238
+ {
239
+ if (ptr)
240
+ {
241
+ cairo_surface_destroy ((cairo_surface_t *) ptr);
242
+ }
243
+ }
244
+
245
+ VALUE
246
+ rb_cairo_surface_to_ruby_object (cairo_surface_t *surface)
247
+ {
248
+ if (surface)
249
+ {
250
+ VALUE klass = cr_surface_get_klass (surface);
251
+ cairo_surface_reference (surface);
252
+ return Data_Wrap_Struct (klass, NULL, cr_surface_free, surface);
253
+ }
254
+ else
255
+ {
256
+ return Qnil;
257
+ }
258
+ }
259
+
260
+ static VALUE
261
+ cr_surface_allocate (VALUE klass)
262
+ {
263
+ return Data_Wrap_Struct (klass, NULL, cr_surface_free, NULL);
264
+ }
265
+
266
+ /* Surface manipulation */
267
+ static VALUE
268
+ cr_surface_create_similar (VALUE self, VALUE content,
269
+ VALUE width, VALUE height)
270
+ {
271
+ cairo_surface_t *surface;
272
+
273
+ surface = cairo_surface_create_similar (RVAL2CRSURFACE (self),
274
+ RVAL2CRCONTENT (content),
275
+ NUM2INT (width), NUM2INT (height));
276
+ cr_surface_check_status (surface);
277
+ cr_surface_set_klass (surface, rb_obj_class (self));
278
+ return CRSURFACE2RVAL (surface);
279
+ }
280
+
281
+ static VALUE
282
+ cr_surface_finish (VALUE self)
283
+ {
284
+ cr_io_callback_closure_t *closure;
285
+ closure = cairo_surface_get_user_data (_SELF, &cr_closure_key);
286
+
287
+ cairo_surface_finish (_SELF);
288
+
289
+ if (closure && !NIL_P (closure->error))
290
+ rb_exc_raise (closure->error);
291
+
292
+ cr_surface_check_status (_SELF);
293
+ return self;
294
+ }
295
+
296
+ static VALUE
297
+ cr_surface_get_type (VALUE self)
298
+ {
299
+ return INT2NUM (cairo_surface_get_type (_SELF));
300
+ }
301
+
302
+ static VALUE
303
+ cr_surface_get_content (VALUE self)
304
+ {
305
+ return INT2NUM (cairo_surface_get_content (_SELF));
306
+ }
307
+
308
+
309
+ #if CAIRO_HAS_PNG_FUNCTIONS
310
+ static VALUE
311
+ cr_surface_write_to_png_stream (VALUE self, VALUE target)
312
+ {
313
+ cairo_status_t status;
314
+ cr_io_callback_closure_t closure;
315
+
316
+ closure.target = target;
317
+ closure.error = Qnil;
318
+
319
+ status = cairo_surface_write_to_png_stream (_SELF, cr_surface_write_func,
320
+ (void *)&closure);
321
+ if (!NIL_P (closure.error))
322
+ rb_exc_raise (closure.error);
323
+
324
+ rb_cairo_check_status (status);
325
+ return self;
326
+ }
327
+
328
+ static VALUE
329
+ cr_surface_write_to_png (VALUE self, VALUE filename)
330
+ {
331
+ cairo_status_t status;
332
+ status = cairo_surface_write_to_png (_SELF, StringValueCStr (filename));
333
+ rb_cairo_check_status (status);
334
+ return self;
335
+ }
336
+
337
+ static VALUE
338
+ cr_surface_write_to_png_generic (VALUE self, VALUE target)
339
+ {
340
+ if (rb_respond_to (target, cr_id_write))
341
+ return cr_surface_write_to_png_stream (self, target);
342
+ else
343
+ return cr_surface_write_to_png (self, target);
344
+ }
345
+ #endif
346
+
347
+ static VALUE
348
+ cr_surface_get_font_options (VALUE self)
349
+ {
350
+ cairo_font_options_t *options = cairo_font_options_create();
351
+ cairo_surface_get_font_options (_SELF, options);
352
+ cr_surface_check_status (_SELF);
353
+ rb_cairo_check_status (cairo_font_options_status (options));
354
+ return CRFONTOPTIONS2RVAL (options);
355
+ }
356
+
357
+ static VALUE
358
+ cr_surface_flush (VALUE self)
359
+ {
360
+ cairo_surface_flush (_SELF);
361
+ cr_surface_check_status (_SELF);
362
+ return self;
363
+ }
364
+
365
+ static VALUE
366
+ cr_surface_mark_dirty (int argc, VALUE *argv, VALUE self)
367
+ {
368
+ VALUE x, y, width, height;
369
+ int n;
370
+
371
+ n = rb_scan_args (argc, argv, "04", &x, &y, &width, &height);
372
+
373
+ if (n == 0)
374
+ {
375
+ cairo_surface_mark_dirty (_SELF);
376
+ }
377
+ else if (n == 4)
378
+ {
379
+ cairo_surface_mark_dirty_rectangle (_SELF,
380
+ NUM2INT (x), NUM2INT (y),
381
+ NUM2INT (width), NUM2INT (height));
382
+ }
383
+ else
384
+ {
385
+ rb_raise (rb_eArgError,
386
+ "invalid argument (expect () or (x, y, width, height))");
387
+ }
388
+
389
+ cr_surface_check_status (_SELF);
390
+ return self;
391
+ }
392
+
393
+ static VALUE
394
+ cr_surface_set_device_offset (VALUE self, VALUE x_offset, VALUE y_offset)
395
+ {
396
+ cairo_surface_set_device_offset (_SELF,
397
+ NUM2DBL (x_offset),
398
+ NUM2DBL (y_offset));
399
+ cr_surface_check_status (_SELF);
400
+ return self;
401
+ }
402
+
403
+ static VALUE
404
+ cr_surface_get_device_offset (VALUE self)
405
+ {
406
+ double x_offset, y_offset;
407
+
408
+ cairo_surface_get_device_offset (_SELF, &x_offset, &y_offset);
409
+ cr_surface_check_status (_SELF);
410
+ return rb_ary_new3 (2, rb_float_new (x_offset), rb_float_new (y_offset));
411
+ }
412
+
413
+ static VALUE
414
+ cr_surface_set_fallback_resolution (VALUE self,
415
+ VALUE x_pixels_per_inch,
416
+ VALUE y_pixels_per_inch)
417
+ {
418
+ cairo_surface_set_fallback_resolution (_SELF,
419
+ NUM2DBL (x_pixels_per_inch),
420
+ NUM2DBL (y_pixels_per_inch));
421
+ cr_surface_check_status (_SELF);
422
+ return self;
423
+ }
424
+
425
+
426
+ /* Image-surface functions */
427
+ #if CAIRO_HAS_PNG_FUNCTIONS
428
+ static cairo_surface_t *
429
+ cr_image_surface_create_from_png_stream (VALUE target)
430
+ {
431
+ cr_io_callback_closure_t closure;
432
+ cairo_surface_t *surface;
433
+
434
+ closure.target = target;
435
+ closure.error = Qnil;
436
+
437
+ surface = cairo_image_surface_create_from_png_stream (cr_surface_read_func,
438
+ (void *)&closure);
439
+ if (!NIL_P (closure.error))
440
+ rb_exc_raise (closure.error);
441
+
442
+ return surface;
443
+ }
444
+
445
+ static cairo_surface_t *
446
+ cr_image_surface_create_from_png (VALUE filename)
447
+ {
448
+ return cairo_image_surface_create_from_png (StringValueCStr (filename));
449
+ }
450
+
451
+ static VALUE
452
+ cr_image_surface_create_from_png_generic (VALUE klass, VALUE target)
453
+ {
454
+ VALUE rb_surface;
455
+ cairo_surface_t *surface;
456
+
457
+ if (rb_respond_to (target, cr_id_read))
458
+ surface = cr_image_surface_create_from_png_stream (target);
459
+ else
460
+ surface = cr_image_surface_create_from_png (target);
461
+
462
+ cr_surface_check_status (surface);
463
+ cr_surface_set_klass (surface, klass);
464
+ rb_surface = cr_surface_allocate (klass);
465
+ DATA_PTR (rb_surface) = surface;
466
+ return rb_surface;
467
+ }
468
+ #endif
469
+
470
+
471
+ static cairo_surface_t *
472
+ cr_image_surface_create (VALUE self, VALUE format, VALUE width, VALUE height)
473
+ {
474
+ cairo_format_t cr_format;
475
+ cr_format = NIL_P (format) ? CAIRO_FORMAT_ARGB32 : RVAL2CRFORMAT (format);
476
+ return cairo_image_surface_create (cr_format,
477
+ NUM2INT (width),
478
+ NUM2INT (height));
479
+ }
480
+
481
+ static cairo_surface_t *
482
+ cr_image_surface_create_for_data (VALUE self, VALUE rb_data, VALUE format,
483
+ VALUE width, VALUE height, VALUE stride)
484
+ {
485
+ unsigned char *data;
486
+
487
+ data = (unsigned char *)StringValuePtr (rb_data);
488
+
489
+ return cairo_image_surface_create_for_data (data,
490
+ RVAL2CRFORMAT (format),
491
+ NUM2INT (width),
492
+ NUM2INT (height),
493
+ NUM2INT (stride));
494
+ }
495
+
496
+ static VALUE
497
+ cr_image_surface_initialize (int argc, VALUE *argv, VALUE self)
498
+ {
499
+ cairo_surface_t *surface;
500
+ VALUE arg1, arg2, arg3, arg4, arg5;
501
+ int n;
502
+
503
+ n = rb_scan_args (argc, argv, "23", &arg1, &arg2, &arg3, &arg4, &arg5);
504
+
505
+ if (n == 2)
506
+ surface = cr_image_surface_create (self, Qnil, arg1, arg2);
507
+ else if (n == 3)
508
+ surface = cr_image_surface_create (self, arg1, arg2, arg3);
509
+ else if (n == 5)
510
+ surface =
511
+ cr_image_surface_create_for_data (self, arg1, arg2, arg3, arg4, arg5);
512
+ else
513
+ rb_raise (rb_eArgError,
514
+ "invalid argument (expect "
515
+ "(width, height) or "
516
+ "(format, width, height) or "
517
+ "(data, format, width, height, stride))");
518
+
519
+ cr_surface_check_status (surface);
520
+ DATA_PTR (self) = surface;
521
+ return Qnil;
522
+ }
523
+
524
+ static VALUE
525
+ cr_image_surface_get_data (VALUE self)
526
+ {
527
+ unsigned char *data;
528
+ cairo_surface_t *surface;
529
+
530
+ surface = _SELF;
531
+ data = cairo_image_surface_get_data (surface);
532
+
533
+ if (data)
534
+ return rb_str_new ((const char *)data,
535
+ cairo_image_surface_get_stride (surface) *
536
+ cairo_image_surface_get_height (surface));
537
+ else
538
+ return Qnil;
539
+ }
540
+
541
+ static VALUE
542
+ cr_image_surface_get_format (VALUE self)
543
+ {
544
+ return INT2NUM (cairo_image_surface_get_format (_SELF));
545
+ }
546
+
547
+ static VALUE
548
+ cr_image_surface_get_width (VALUE self)
549
+ {
550
+ return INT2NUM (cairo_image_surface_get_width (_SELF));
551
+ }
552
+
553
+ static VALUE
554
+ cr_image_surface_get_height (VALUE self)
555
+ {
556
+ return INT2NUM (cairo_image_surface_get_height (_SELF));
557
+ }
558
+
559
+ static VALUE
560
+ cr_image_surface_get_stride (VALUE self)
561
+ {
562
+ return INT2NUM (cairo_image_surface_get_stride (_SELF));
563
+ }
564
+
565
+
566
+ /* Printing surfaces */
567
+ #define DEFINE_SURFACE(type) \
568
+ static VALUE \
569
+ cr_ ## type ## _surface_initialize (VALUE self, VALUE target, \
570
+ VALUE rb_width_in_points, \
571
+ VALUE rb_height_in_points) \
572
+ { \
573
+ cairo_surface_t *surface; \
574
+ double width_in_points, height_in_points; \
575
+ \
576
+ width_in_points = NUM2DBL (rb_width_in_points); \
577
+ height_in_points = NUM2DBL (rb_height_in_points); \
578
+ \
579
+ if (rb_respond_to (target, cr_id_write)) \
580
+ { \
581
+ cr_io_callback_closure_t *closure; \
582
+ \
583
+ closure = cr_closure_new (target); \
584
+ surface = \
585
+ cairo_ ## type ## _surface_create_for_stream ( \
586
+ cr_surface_write_func, \
587
+ (void *) closure, \
588
+ width_in_points, \
589
+ height_in_points); \
590
+ \
591
+ if (cairo_surface_status (surface)) \
592
+ { \
593
+ cr_closure_destroy (closure); \
594
+ } \
595
+ else \
596
+ { \
597
+ rb_ivar_set (self, cr_id_target, target); \
598
+ cairo_surface_set_user_data (surface, &cr_closure_key, \
599
+ closure, cr_closure_free); \
600
+ } \
601
+ } \
602
+ else \
603
+ { \
604
+ surface = \
605
+ cairo_ ## type ## _surface_create (StringValueCStr (target), \
606
+ width_in_points, \
607
+ height_in_points); \
608
+ } \
609
+ \
610
+ cr_surface_check_status (surface); \
611
+ DATA_PTR (self) = surface; \
612
+ return Qnil; \
613
+ }
614
+
615
+
616
+ #if CAIRO_HAS_PS_SURFACE
617
+ /* PS-surface functions */
618
+ DEFINE_SURFACE(ps)
619
+
620
+ static VALUE
621
+ cr_ps_surface_set_size (VALUE self,
622
+ VALUE width_in_points,
623
+ VALUE height_in_points)
624
+ {
625
+ cairo_ps_surface_set_size (_SELF,
626
+ NUM2DBL (width_in_points),
627
+ NUM2DBL (height_in_points));
628
+ cr_surface_check_status (_SELF);
629
+ return Qnil;
630
+ }
631
+
632
+ static VALUE
633
+ cr_ps_surface_dsc_comment (VALUE self, VALUE comment)
634
+ {
635
+ cairo_ps_surface_dsc_comment (_SELF, StringValueCStr (comment));
636
+ cr_surface_check_status (_SELF);
637
+ return Qnil;
638
+ }
639
+
640
+ static VALUE
641
+ cr_ps_surface_dsc_begin_setup (VALUE self)
642
+ {
643
+ cairo_ps_surface_dsc_begin_setup (_SELF);
644
+ cr_surface_check_status (_SELF);
645
+ if (rb_block_given_p ())
646
+ return rb_yield (self);
647
+ else
648
+ return Qnil;
649
+ }
650
+
651
+ static VALUE
652
+ cr_ps_surface_dsc_begin_page_setup (VALUE self)
653
+ {
654
+ cairo_ps_surface_dsc_begin_page_setup (_SELF);
655
+ cr_surface_check_status (_SELF);
656
+ if (rb_block_given_p ())
657
+ return rb_yield (self);
658
+ else
659
+ return Qnil;
660
+ }
661
+ #endif
662
+
663
+ #if CAIRO_HAS_PDF_SURFACE
664
+ /* PDF-surface functions */
665
+ DEFINE_SURFACE(pdf)
666
+
667
+ static VALUE
668
+ cr_pdf_surface_set_size (VALUE self,
669
+ VALUE width_in_points,
670
+ VALUE height_in_points)
671
+ {
672
+ cairo_pdf_surface_set_size (_SELF,
673
+ NUM2DBL (width_in_points),
674
+ NUM2DBL (height_in_points));
675
+ cr_surface_check_status (_SELF);
676
+ return Qnil;
677
+ }
678
+ #endif
679
+
680
+ #if CAIRO_HAS_SVG_SURFACE
681
+ /* SVG-surface functions */
682
+ DEFINE_SURFACE(svg)
683
+
684
+ static VALUE
685
+ cr_svg_surface_restrict_to_version (VALUE self, VALUE version)
686
+ {
687
+ cairo_svg_surface_restrict_to_version (_SELF, RVAL2CRSVGVERSION (version));
688
+ cr_surface_check_status (_SELF);
689
+ return Qnil;
690
+ }
691
+
692
+ static VALUE
693
+ cr_svg_get_versions (VALUE self)
694
+ {
695
+ VALUE rb_versions;
696
+ int i, num_versions;
697
+ cairo_svg_version_t const *versions;
698
+
699
+ cairo_svg_get_versions (&versions, &num_versions);
700
+
701
+ rb_versions = rb_ary_new2 (num_versions);
702
+
703
+ for (i = 0; i < num_versions; i++)
704
+ {
705
+ rb_ary_push (rb_versions, INT2NUM (versions[i]));
706
+ }
707
+
708
+ return rb_versions;
709
+ }
710
+
711
+ static VALUE
712
+ cr_svg_version_to_string (VALUE self, VALUE version)
713
+ {
714
+ const char *ver_str;
715
+ ver_str = cairo_svg_version_to_string (RVAL2CRSVGVERSION(version));
716
+ return rb_str_new2 (ver_str);
717
+ }
718
+ #endif
719
+
720
+
721
+ void
722
+ Init_cairo_surface (void)
723
+ {
724
+ cr_id_target = rb_intern ("target");
725
+ cr_id_read = rb_intern ("read");
726
+ cr_id_write = rb_intern ("write");
727
+
728
+ rb_cCairo_Surface =
729
+ rb_define_class_under (rb_mCairo, "Surface", rb_cObject);
730
+ rb_define_alloc_func (rb_cCairo_Surface, cr_surface_allocate);
731
+
732
+ rb_define_method (rb_cCairo_Surface, "create_similar",
733
+ cr_surface_create_similar, 3);
734
+ rb_define_method (rb_cCairo_Surface, "finish", cr_surface_finish, 0);
735
+ rb_define_method (rb_cCairo_Surface, "type", cr_surface_get_type, 0);
736
+ rb_define_method (rb_cCairo_Surface, "content", cr_surface_get_content, 0);
737
+
738
+ rb_define_method (rb_cCairo_Surface, "font_options",
739
+ cr_surface_get_font_options, 0);
740
+ rb_define_method (rb_cCairo_Surface, "flush", cr_surface_flush, 0);
741
+ rb_define_method (rb_cCairo_Surface, "mark_dirty", cr_surface_mark_dirty, 0);
742
+ rb_define_method (rb_cCairo_Surface, "set_device_offset",
743
+ cr_surface_set_device_offset, 2);
744
+ rb_define_method (rb_cCairo_Surface, "device_offset",
745
+ cr_surface_get_device_offset, 0);
746
+ rb_define_method (rb_cCairo_Surface, "set_fallback_resolution",
747
+ cr_surface_set_fallback_resolution, 2);
748
+
749
+ #if CAIRO_HAS_PNG_FUNCTIONS
750
+ rb_define_method (rb_cCairo_Surface, "write_to_png",
751
+ cr_surface_write_to_png_generic, 1);
752
+ #endif
753
+
754
+ RB_CAIRO_DEF_SETTERS (rb_cCairo_Surface);
755
+
756
+ /* Image-surface */
757
+ rb_cCairo_ImageSurface =
758
+ rb_define_class_under (rb_mCairo, "ImageSurface", rb_cCairo_Surface);
759
+
760
+ #if CAIRO_HAS_PNG_FUNCTIONS
761
+ rb_define_singleton_method (rb_cCairo_ImageSurface, "from_png",
762
+ cr_image_surface_create_from_png_generic, 1);
763
+ #endif
764
+
765
+ rb_define_method (rb_cCairo_ImageSurface, "initialize",
766
+ cr_image_surface_initialize, -1);
767
+
768
+ rb_define_method (rb_cCairo_ImageSurface, "data",
769
+ cr_image_surface_get_data, 0);
770
+ rb_define_method (rb_cCairo_ImageSurface, "format",
771
+ cr_image_surface_get_format, 0);
772
+ rb_define_method (rb_cCairo_ImageSurface, "width",
773
+ cr_image_surface_get_width, 0);
774
+ rb_define_method (rb_cCairo_ImageSurface, "height",
775
+ cr_image_surface_get_height, 0);
776
+ rb_define_method (rb_cCairo_ImageSurface, "stride",
777
+ cr_image_surface_get_stride, 0);
778
+
779
+ #define INIT_SURFACE(type, name) \
780
+ rb_cCairo_ ## name ## Surface = \
781
+ rb_define_class_under (rb_mCairo, # name "Surface", \
782
+ rb_cCairo_Surface); \
783
+ \
784
+ rb_define_method (rb_cCairo_ ## name ## Surface, "initialize", \
785
+ cr_ ## type ## _surface_initialize, 3);
786
+
787
+ #if CAIRO_HAS_PS_SURFACE
788
+ /* PS-surface */
789
+ INIT_SURFACE(ps, PS)
790
+
791
+ rb_define_method (rb_cCairo_PSSurface, "set_size", cr_ps_surface_set_size, 2);
792
+ rb_define_method (rb_cCairo_PSSurface, "dsc_comment",
793
+ cr_ps_surface_dsc_comment, 1);
794
+ rb_define_method (rb_cCairo_PSSurface, "dsc_begin_setup",
795
+ cr_ps_surface_dsc_begin_setup, 0);
796
+ rb_define_method (rb_cCairo_PSSurface, "dsc_begin_page_setup",
797
+ cr_ps_surface_dsc_begin_page_setup, 0);
798
+
799
+ RB_CAIRO_DEF_SETTERS (rb_cCairo_PSSurface);
800
+ #else
801
+ rb_cCairo_PSSurface = Qnil;
802
+ #endif
803
+
804
+ #if CAIRO_HAS_PDF_SURFACE
805
+ /* PDF-surface */
806
+ INIT_SURFACE(pdf, PDF)
807
+
808
+ rb_define_method (rb_cCairo_PDFSurface, "set_size",
809
+ cr_pdf_surface_set_size, 2);
810
+
811
+ RB_CAIRO_DEF_SETTERS (rb_cCairo_PDFSurface);
812
+ #else
813
+ rb_cCairo_PDFSurface = Qnil;
814
+ #endif
815
+
816
+ #if CAIRO_HAS_SVG_SURFACE
817
+ /* SVG-surface */
818
+ INIT_SURFACE(svg, SVG)
819
+
820
+ rb_define_const (rb_cCairo_SVGSurface, "VERSION_1_1",
821
+ rb_const_get (rb_mCairo, rb_intern ("SVG_VERSION_1_1")));
822
+ rb_define_const (rb_cCairo_SVGSurface, "VERSION_1_2",
823
+ rb_const_get (rb_mCairo, rb_intern ("SVG_VERSION_1_2")));
824
+
825
+ rb_define_singleton_method (rb_cCairo_SVGSurface, "versions",
826
+ cr_svg_get_versions, 0);
827
+ rb_define_singleton_method (rb_cCairo_SVGSurface, "version_to_string",
828
+ cr_svg_version_to_string, 1);
829
+
830
+ rb_define_method (rb_cCairo_SVGSurface, "restrict_to_version",
831
+ cr_svg_surface_restrict_to_version, 1);
832
+
833
+ RB_CAIRO_DEF_SETTERS (rb_cCairo_SVGSurface);
834
+ #else
835
+ rb_cCairo_SVGSurface = Qnil;
836
+ #endif
837
+ }