cairo 1.4.1 → 1.5.0

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.

@@ -3,7 +3,7 @@
3
3
  * Ruby Cairo Binding
4
4
  *
5
5
  * $Author: kou $
6
- * $Date: 2007/03/06 12:35:40 $
6
+ * $Date: 2007/05/20 08:46:07 $
7
7
  *
8
8
  * Copyright 2005 Øyvind Kolås <pippin@freedesktop.org>
9
9
  * Copyright 2004-2005 MenTaLguY <mental@rydia.com>
@@ -17,7 +17,8 @@
17
17
 
18
18
  VALUE rb_cCairo_Context;
19
19
 
20
- static ID cr_id_surface, cr_id_source, cr_id_source_class;
20
+ static ID cr_id_surface, cr_id_source;
21
+ static ID cr_id_plus, cr_id_minus, cr_id_multi, cr_id_div;
21
22
 
22
23
  #define _SELF (RVAL2CRCONTEXT(self))
23
24
 
@@ -25,6 +26,8 @@ static ID cr_id_surface, cr_id_source, cr_id_source_class;
25
26
  static VALUE rb_cCairo_Rectangle;
26
27
  static ID at_x, at_y, at_width, at_height;
27
28
 
29
+ static VALUE cr_get_current_point (VALUE self);
30
+
28
31
  static VALUE
29
32
  cr_rectangle_initialize (VALUE self, VALUE x, VALUE y,
30
33
  VALUE width, VALUE height)
@@ -49,7 +52,7 @@ cairo_t *
49
52
  rb_cairo_context_from_ruby_object (VALUE obj)
50
53
  {
51
54
  cairo_t *context;
52
- if (!RTEST (rb_obj_is_kind_of (obj, rb_cCairo_Context)))
55
+ if (!rb_cairo__is_kind_of (obj, rb_cCairo_Context))
53
56
  {
54
57
  rb_raise (rb_eTypeError, "not a cairo graphics context");
55
58
  }
@@ -122,9 +125,11 @@ cr_save (VALUE self)
122
125
  static VALUE
123
126
  cr_pop_group (VALUE self)
124
127
  {
125
- cairo_pop_group (_SELF);
128
+ cairo_pattern_t *pattern;
129
+
130
+ pattern = cairo_pop_group (_SELF);
126
131
  cr_check_status (_SELF);
127
- return Qnil;
132
+ return CRPATTERN2RVAL (pattern);
128
133
  }
129
134
 
130
135
  static VALUE
@@ -140,7 +145,7 @@ cr_pop_group_generic (int argc, VALUE *argv, VALUE self)
140
145
  {
141
146
  VALUE to_source;
142
147
  rb_scan_args (argc, argv, "01", &to_source);
143
- if (RTEST(to_source))
148
+ if (RVAL2CBOOL (to_source))
144
149
  return cr_pop_group_to_source (self);
145
150
  else
146
151
  return cr_pop_group (self);
@@ -161,13 +166,22 @@ cr_push_group (int argc, VALUE *argv, VALUE self)
161
166
 
162
167
  if (rb_block_given_p ())
163
168
  {
169
+ int state = 0;
170
+
164
171
  if (NIL_P (pop_to_source))
165
172
  pop_to_source = Qtrue;
166
173
 
167
- if (RTEST (pop_to_source))
168
- result = rb_ensure (rb_yield, self, cr_pop_group_to_source, self);
169
- else
170
- result = rb_ensure (rb_yield, self, cr_pop_group, self);
174
+ result = rb_protect (rb_yield, self, &state);
175
+ if (cairo_status(_SELF) == CAIRO_STATUS_SUCCESS)
176
+ {
177
+ if (RVAL2CBOOL (pop_to_source))
178
+ cr_pop_group_to_source (self);
179
+ else
180
+ result = cr_pop_group (self);
181
+ }
182
+
183
+ if (state)
184
+ rb_jump_tag (state);
171
185
  }
172
186
 
173
187
  return result;
@@ -191,7 +205,7 @@ cr_set_source_rgb (int argc, VALUE *argv, VALUE self)
191
205
 
192
206
  n = rb_scan_args (argc, argv, "12", &red, &green, &blue);
193
207
 
194
- if (n == 1 && RTEST (rb_obj_is_kind_of (red, rb_cArray)))
208
+ if (n == 1 && rb_cairo__is_kind_of (red, rb_cArray))
195
209
  {
196
210
  VALUE ary = red;
197
211
  n = RARRAY (ary)->len;
@@ -217,7 +231,6 @@ cr_set_source_rgb (int argc, VALUE *argv, VALUE self)
217
231
  }
218
232
  cr_check_status (_SELF);
219
233
  rb_ivar_set (self, cr_id_source, Qnil);
220
- rb_ivar_set (self, cr_id_source_class, rb_cCairo_SolidPattern);
221
234
  return self;
222
235
  }
223
236
 
@@ -229,7 +242,7 @@ cr_set_source_rgba (int argc, VALUE *argv, VALUE self)
229
242
 
230
243
  n = rb_scan_args (argc, argv, "13", &red, &green, &blue, &alpha);
231
244
 
232
- if (n == 1 && RTEST (rb_obj_is_kind_of (red, rb_cArray)))
245
+ if (n == 1 && rb_cairo__is_kind_of (red, rb_cArray))
233
246
  {
234
247
  VALUE ary = red;
235
248
  n = RARRAY (ary)->len;
@@ -266,7 +279,6 @@ cr_set_source_rgba (int argc, VALUE *argv, VALUE self)
266
279
  }
267
280
  cr_check_status (_SELF);
268
281
  rb_ivar_set (self, cr_id_source, Qnil);
269
- rb_ivar_set (self, cr_id_source_class, rb_cCairo_SolidPattern);
270
282
  return self;
271
283
  }
272
284
 
@@ -279,7 +291,6 @@ cr_set_source_surface (VALUE self, VALUE surface, VALUE width, VALUE height)
279
291
  NUM2INT (height));
280
292
  cr_check_status (_SELF);
281
293
  rb_ivar_set (self, cr_id_source, Qnil);
282
- rb_ivar_set (self, cr_id_source_class, rb_cCairo_SurfacePattern);
283
294
  return self;
284
295
  }
285
296
 
@@ -289,7 +300,6 @@ cr_set_source (VALUE self, VALUE pattern)
289
300
  cairo_set_source (_SELF, RVAL2CRPATTERN (pattern));
290
301
  cr_check_status (_SELF);
291
302
  rb_ivar_set (self, cr_id_source, pattern);
292
- rb_ivar_set (self, cr_id_source_class, rb_obj_class (pattern));
293
303
  return self;
294
304
  }
295
305
 
@@ -301,7 +311,7 @@ cr_set_source_generic (int argc, VALUE *argv, VALUE self)
301
311
 
302
312
  n = rb_scan_args (argc, argv, "13", &arg1, &arg2, &arg3, &arg4);
303
313
 
304
- if (n == 1 && RTEST (rb_obj_is_kind_of (arg1, rb_cArray)))
314
+ if (n == 1 && rb_cairo__is_kind_of (arg1, rb_cArray))
305
315
  {
306
316
  return cr_set_source_rgba (argc, argv, self);
307
317
  }
@@ -309,7 +319,7 @@ cr_set_source_generic (int argc, VALUE *argv, VALUE self)
309
319
  {
310
320
  return cr_set_source (self, arg1);
311
321
  }
312
- else if (n == 3 && rb_obj_is_kind_of (arg1, rb_cCairo_Surface))
322
+ else if (n == 3 && rb_cairo__is_kind_of (arg1, rb_cCairo_Surface))
313
323
  {
314
324
  return cr_set_source_surface (self, arg1, arg2, arg3);
315
325
  }
@@ -375,16 +385,34 @@ cr_set_line_join (VALUE self, VALUE join)
375
385
  }
376
386
 
377
387
  static VALUE
378
- cr_set_dash (VALUE self, VALUE dash_array, VALUE offset)
388
+ cr_set_dash (int argc, VALUE *argv, VALUE self)
379
389
  {
380
- if (!NIL_P (dash_array))
390
+ VALUE dash_array, rb_offset;
391
+ double offset;
392
+ cairo_bool_t is_num;
393
+
394
+ rb_scan_args(argc, argv, "11", &dash_array, &rb_offset);
395
+
396
+ is_num = rb_cairo__is_kind_of (dash_array, rb_cNumeric);
397
+ if (!(NIL_P (dash_array) || is_num))
381
398
  {
382
399
  Check_Type (dash_array, T_ARRAY);
383
400
  }
384
401
 
385
- if (NIL_P (dash_array) || RARRAY (dash_array)->len == 0)
402
+ if (NIL_P (rb_offset))
403
+ offset = 0.0;
404
+ else
405
+ offset = NUM2DBL (rb_offset);
406
+
407
+ if (is_num)
386
408
  {
387
- cairo_set_dash (_SELF, NULL, 0, NUM2DBL (offset));
409
+ double values[1];
410
+ values[0] = NUM2DBL (dash_array);
411
+ cairo_set_dash (_SELF, values, 1, offset);
412
+ }
413
+ else if (NIL_P (dash_array) || RARRAY (dash_array)->len == 0)
414
+ {
415
+ cairo_set_dash (_SELF, NULL, 0, offset);
388
416
  }
389
417
  else
390
418
  {
@@ -400,9 +428,9 @@ cr_set_dash (VALUE self, VALUE dash_array, VALUE offset)
400
428
  {
401
429
  values[i] = NUM2DBL (RARRAY (dash_array)->ptr[i]);
402
430
  }
403
- cairo_set_dash (_SELF, values, length, NUM2DBL (offset));
431
+ cairo_set_dash (_SELF, values, length, offset);
404
432
  }
405
-
433
+
406
434
  cr_check_status (_SELF);
407
435
  return self;
408
436
  }
@@ -551,6 +579,59 @@ cr_curve_to (VALUE self, VALUE x1, VALUE y1,
551
579
  return self;
552
580
  }
553
581
 
582
+ static VALUE
583
+ cr_quadratic_curve_to (VALUE self, VALUE x1, VALUE y1, VALUE x2, VALUE y2)
584
+ {
585
+ VALUE current_point, x0, y0, cx1, cy1, cx2, cy2;
586
+
587
+ current_point = cr_get_current_point (self);
588
+ x0 = RARRAY (current_point)->ptr[0];
589
+ y0 = RARRAY (current_point)->ptr[1];
590
+
591
+ /* cx1 = x0 + 2 * ((x1 - x0) / 3.0) */
592
+ cx1 = rb_funcall (x0, cr_id_plus, 1,
593
+ rb_funcall (INT2NUM(2), cr_id_multi, 1,
594
+ rb_funcall (rb_funcall (x1, cr_id_minus, 1, x0),
595
+ cr_id_div, 1, rb_float_new (3.0))));
596
+ /* cy1 = y0 + 2 * ((y1 - y0) / 3.0) */
597
+ cy1 = rb_funcall (y0, cr_id_plus, 1,
598
+ rb_funcall (INT2NUM(2), cr_id_multi, 1,
599
+ rb_funcall (rb_funcall (y1, cr_id_minus, 1, y0),
600
+ cr_id_div, 1, rb_float_new (3.0))));
601
+ /* cx2 = cx1 + (x2 - x0) / 3.0 */
602
+ cx2 = rb_funcall (cx1, cr_id_plus, 1,
603
+ rb_funcall (rb_funcall (x2, cr_id_minus, 1, x0),
604
+ cr_id_div, 1, rb_float_new (3.0)));
605
+ /* cy2 = cy1 + (y2 - y0) / 3.0 */
606
+ cy2 = rb_funcall (cy1, cr_id_plus, 1,
607
+ rb_funcall (rb_funcall (y2, cr_id_minus, 1, y0),
608
+ cr_id_div, 1, rb_float_new (3.0)));
609
+ return cr_curve_to (self, cx1, cy1, cx2, cy2, x2, y2);
610
+ }
611
+
612
+ static VALUE
613
+ cr_curve_to_generic (int argc, VALUE *argv, VALUE self)
614
+ {
615
+ VALUE x1, y1, x2, y2, x3, y3;
616
+
617
+ rb_scan_args (argc, argv, "42", &x1, &y1, &x2, &y2, &x3, &y3);
618
+
619
+ if (!(argc == 4 || argc == 6))
620
+ {
621
+ VALUE inspected_arg = rb_inspect (rb_ary_new4 (argc, argv));
622
+ rb_raise (rb_eArgError,
623
+ "invalid argument: %s (expect "
624
+ "(x1, y1, x2, y2) (quadratic) or "
625
+ "(x1, y1, x2, y2, x3, y3) (cubic))",
626
+ StringValuePtr (inspected_arg));
627
+ }
628
+
629
+ if (argc == 4)
630
+ return cr_quadratic_curve_to (self, x1, y1, x2, y2);
631
+ else
632
+ return cr_curve_to (self, x1, y1, x2, y2, x3, y3);
633
+ }
634
+
554
635
  static VALUE
555
636
  cr_arc (VALUE self, VALUE xc, VALUE yc, VALUE radius,
556
637
  VALUE angle1, VALUE angle2)
@@ -588,15 +669,55 @@ cr_rel_line_to (VALUE self, VALUE x, VALUE y)
588
669
  }
589
670
 
590
671
  static VALUE
591
- cr_rel_curve_to (VALUE self, VALUE x1, VALUE y1,
592
- VALUE x2, VALUE y2, VALUE x3, VALUE y3)
672
+ cr_rel_curve_to (VALUE self, VALUE dx1, VALUE dy1,
673
+ VALUE dx2, VALUE dy2, VALUE dx3, VALUE dy3)
593
674
  {
594
- cairo_rel_curve_to (_SELF, NUM2DBL (x1), NUM2DBL (y1),
595
- NUM2DBL (x2), NUM2DBL (y2), NUM2DBL (x3), NUM2DBL (y3));
675
+ cairo_rel_curve_to (_SELF, NUM2DBL (dx1), NUM2DBL (dy1),
676
+ NUM2DBL (dx2), NUM2DBL (dy2),
677
+ NUM2DBL (dx3), NUM2DBL (dy3));
596
678
  cr_check_status (_SELF);
597
679
  return self;
598
680
  }
599
681
 
682
+ static VALUE
683
+ cr_rel_quadratic_curve_to (VALUE self, VALUE dx1, VALUE dy1,
684
+ VALUE dx2, VALUE dy2)
685
+ {
686
+ VALUE current_point, x0, y0;
687
+
688
+ current_point = cr_get_current_point (self);
689
+ x0 = RARRAY (current_point)->ptr[0];
690
+ y0 = RARRAY (current_point)->ptr[1];
691
+ return cr_quadratic_curve_to (self,
692
+ rb_funcall (dx1, cr_id_plus, 1, x0),
693
+ rb_funcall (dy1, cr_id_plus, 1, y0),
694
+ rb_funcall (dx2, cr_id_plus, 1, x0),
695
+ rb_funcall (dy2, cr_id_plus, 1, y0));
696
+ }
697
+
698
+ static VALUE
699
+ cr_rel_curve_to_generic (int argc, VALUE *argv, VALUE self)
700
+ {
701
+ VALUE dx1, dy1, dx2, dy2, dx3, dy3;
702
+
703
+ rb_scan_args (argc, argv, "42", &dx1, &dy1, &dx2, &dy2, &dx3, &dy3);
704
+
705
+ if (!(argc == 4 || argc == 6))
706
+ {
707
+ VALUE inspected_arg = rb_inspect (rb_ary_new4 (argc, argv));
708
+ rb_raise (rb_eArgError,
709
+ "invalid argument: %s (expect "
710
+ "(dx1, dy1, dx2, dy2) (quadratic) or "
711
+ "(dx1, dy1, dx2, dy2, dx3, dy3) (cubic))",
712
+ StringValuePtr (inspected_arg));
713
+ }
714
+
715
+ if (argc == 4)
716
+ return cr_rel_quadratic_curve_to (self, dx1, dy1, dx2, dy2);
717
+ else
718
+ return cr_rel_curve_to (self, dx1, dy1, dx2, dy2, dx3, dy3);
719
+ }
720
+
600
721
  static VALUE
601
722
  cr_rectangle (VALUE self, VALUE x, VALUE y, VALUE width, VALUE height)
602
723
  {
@@ -639,7 +760,7 @@ cr_paint_generic(int argc, VALUE *argv, VALUE self)
639
760
 
640
761
  n = rb_scan_args (argc, argv, "01", &alpha);
641
762
 
642
- if (n == 0 || (n == 1 && NIL_P(alpha)))
763
+ if (n == 0 || (n == 1 && NIL_P (alpha)))
643
764
  {
644
765
  return cr_paint (self);
645
766
  }
@@ -695,58 +816,50 @@ cr_mask_generic (int argc, VALUE *argv, VALUE self)
695
816
  }
696
817
 
697
818
  static VALUE
698
- cr_stroke (VALUE self)
819
+ cr_stroke (int argc, VALUE *argv, VALUE self)
699
820
  {
700
- if (rb_block_given_p ())
701
- {
702
- cr_new_path (self);
703
- rb_yield (self);
704
- }
705
- cairo_stroke (_SELF);
706
- cr_check_status (_SELF);
707
- return self;
708
- }
821
+ VALUE preserve;
822
+
823
+ rb_scan_args (argc, argv, "01", &preserve);
709
824
 
710
- static VALUE
711
- cr_stroke_preserve (VALUE self)
712
- {
713
825
  if (rb_block_given_p ())
714
826
  {
715
827
  cr_new_path (self);
716
828
  rb_yield (self);
717
829
  }
718
- cairo_stroke_preserve (_SELF);
830
+
831
+ if (RVAL2CBOOL (preserve))
832
+ cairo_stroke_preserve (_SELF);
833
+ else
834
+ cairo_stroke (_SELF);
835
+
719
836
  cr_check_status (_SELF);
720
837
  return self;
721
838
  }
722
839
 
723
840
  static VALUE
724
- cr_fill (VALUE self)
841
+ cr_fill (int argc, VALUE *argv, VALUE self)
725
842
  {
726
- if (rb_block_given_p ())
727
- {
728
- cr_new_path (self);
729
- rb_yield (self);
730
- }
731
- cairo_fill (_SELF);
732
- cr_check_status (_SELF);
733
- return self;
734
- }
843
+ VALUE preserve;
735
844
 
845
+ rb_scan_args (argc, argv, "01", &preserve);
736
846
 
737
- static VALUE
738
- cr_fill_preserve (VALUE self)
739
- {
740
847
  if (rb_block_given_p ())
741
848
  {
742
849
  cr_new_path (self);
743
850
  rb_yield (self);
744
851
  }
745
- cairo_fill_preserve (_SELF);
852
+
853
+ if (RVAL2CBOOL (preserve))
854
+ cairo_fill_preserve (_SELF);
855
+ else
856
+ cairo_fill (_SELF);
857
+
746
858
  cr_check_status (_SELF);
747
859
  return self;
748
860
  }
749
861
 
862
+
750
863
  static VALUE
751
864
  cr_copy_page (VALUE self)
752
865
  {
@@ -772,7 +885,7 @@ cr_in_stroke (VALUE self, VALUE x, VALUE y)
772
885
  cr_new_path (self);
773
886
  rb_yield (self);
774
887
  }
775
- return cairo_in_stroke (_SELF, NUM2DBL (x), NUM2DBL (y)) ? Qtrue : Qfalse;
888
+ return CBOOL2RVAL (cairo_in_stroke (_SELF, NUM2DBL (x), NUM2DBL (y)));
776
889
  }
777
890
 
778
891
  static VALUE
@@ -783,7 +896,7 @@ cr_in_fill (VALUE self, VALUE x, VALUE y)
783
896
  cr_new_path (self);
784
897
  rb_yield (self);
785
898
  }
786
- return cairo_in_fill (_SELF, NUM2DBL (x), NUM2DBL (y)) ? Qtrue : Qfalse;
899
+ return CBOOL2RVAL (cairo_in_fill (_SELF, NUM2DBL (x), NUM2DBL (y)));
787
900
  }
788
901
 
789
902
  /* Rectangular extents */
@@ -823,27 +936,23 @@ cr_reset_clip (VALUE self)
823
936
  }
824
937
 
825
938
  static VALUE
826
- cr_clip (VALUE self)
939
+ cr_clip (int argc, VALUE *argv, VALUE self)
827
940
  {
828
- if (rb_block_given_p ())
829
- {
830
- cr_new_path (self);
831
- rb_yield (self);
832
- }
833
- cairo_clip (_SELF);
834
- cr_check_status (_SELF);
835
- return self;
836
- }
941
+ VALUE preserve;
942
+
943
+ rb_scan_args(argc, argv, "01", &preserve);
837
944
 
838
- static VALUE
839
- cr_clip_preserve (VALUE self)
840
- {
841
945
  if (rb_block_given_p ())
842
946
  {
843
947
  cr_new_path (self);
844
948
  rb_yield (self);
845
949
  }
846
- cairo_clip_preserve (_SELF);
950
+
951
+ if (RVAL2CBOOL (preserve))
952
+ cairo_clip_preserve(_SELF);
953
+ else
954
+ cairo_clip (_SELF);
955
+
847
956
  cr_check_status (_SELF);
848
957
  return self;
849
958
  }
@@ -908,12 +1017,12 @@ cr_select_font_face (int argc, VALUE *argv, VALUE self)
908
1017
  else
909
1018
  weight = RVAL2CRFONTWEIGHT (rb_weight);
910
1019
 
911
- cairo_select_font_face (_SELF, StringValueCStr (family), slant, weight);
1020
+ cairo_select_font_face (_SELF, RVAL2CSTR (family), slant, weight);
912
1021
  cr_check_status (_SELF);
913
1022
  return self;
914
1023
  }
915
1024
 
916
- static VALUE
1025
+ static VALUE
917
1026
  cr_set_font_size (VALUE self, VALUE scale)
918
1027
  {
919
1028
  cairo_set_font_size (_SELF, NUM2DBL (scale));
@@ -952,7 +1061,7 @@ cr_get_font_options (VALUE self)
952
1061
  cairo_font_options_t *options = cairo_font_options_create ();
953
1062
  rb_cairo_check_status (cairo_font_options_status (options));
954
1063
  cairo_get_font_options (_SELF, options);
955
- cr_check_status (_SELF);
1064
+ rb_cairo_check_status (cairo_font_options_status (options));
956
1065
  return CRFONTOPTIONS2RVAL (options);
957
1066
  }
958
1067
 
@@ -975,7 +1084,7 @@ cr_get_scaled_font (VALUE self)
975
1084
  static VALUE
976
1085
  cr_show_text (VALUE self, VALUE utf8)
977
1086
  {
978
- cairo_show_text (_SELF, StringValuePtr (utf8));
1087
+ cairo_show_text (_SELF, RVAL2CSTR (utf8));
979
1088
  cr_check_status (_SELF);
980
1089
  return self;
981
1090
  }
@@ -986,10 +1095,7 @@ cr_show_glyphs (VALUE self, VALUE rb_glyphs)
986
1095
  int count;
987
1096
  cairo_glyph_t *glyphs;
988
1097
 
989
- if (!rb_obj_is_kind_of (rb_glyphs, rb_cArray))
990
- rb_raise (rb_eTypeError, "expected array");
991
-
992
- rb_cairo__glyphs_to_array (rb_glyphs, &glyphs, &count);
1098
+ RB_CAIRO__GLYPHS_TO_ARRAY (rb_glyphs, glyphs, count);
993
1099
  cairo_show_glyphs (_SELF, glyphs, count);
994
1100
  cr_check_status (_SELF);
995
1101
  return self;
@@ -999,9 +1105,9 @@ static VALUE
999
1105
  cr_get_font_face (VALUE self)
1000
1106
  {
1001
1107
  cairo_font_face_t *face;
1002
-
1108
+
1003
1109
  face = cairo_get_font_face (_SELF);
1004
- cr_check_status (_SELF);
1110
+ rb_cairo_check_status (cairo_font_face_status (face));
1005
1111
  return CRFONTFACE2RVAL (face);
1006
1112
  }
1007
1113
 
@@ -1017,7 +1123,7 @@ cr_font_extents (VALUE self)
1017
1123
  static VALUE
1018
1124
  cr_set_font_face (VALUE self, VALUE face)
1019
1125
  {
1020
- cairo_set_font_face (_SELF, RVAL2CRFONTFACE (face));
1126
+ cairo_set_font_face (_SELF, NIL_P (face) ? NULL : RVAL2CRFONTFACE (face));
1021
1127
  cr_check_status (_SELF);
1022
1128
  return self;
1023
1129
  }
@@ -1038,7 +1144,7 @@ cr_glyph_extents (VALUE self, VALUE rb_glyphs)
1038
1144
  cairo_glyph_t *glyphs;
1039
1145
  int length;
1040
1146
 
1041
- rb_cairo__glyphs_to_array (rb_glyphs, &glyphs, &length);
1147
+ RB_CAIRO__GLYPHS_TO_ARRAY (rb_glyphs, glyphs, length);
1042
1148
  cairo_glyph_extents (_SELF, glyphs, length, &extents);
1043
1149
  cr_check_status (_SELF);
1044
1150
  return CRTEXTEXTENTS2RVAL (&extents);
@@ -1058,10 +1164,10 @@ cr_glyph_path (VALUE self, VALUE rb_glyphs)
1058
1164
  int count;
1059
1165
  cairo_glyph_t *glyphs;
1060
1166
 
1061
- rb_cairo__glyphs_to_array (rb_glyphs, &glyphs, &count);
1167
+ RB_CAIRO__GLYPHS_TO_ARRAY (rb_glyphs, glyphs, count);
1062
1168
  cairo_glyph_path (_SELF, glyphs, count);
1063
1169
  cr_check_status (_SELF);
1064
-
1170
+
1065
1171
  return self;
1066
1172
  }
1067
1173
 
@@ -1079,14 +1185,13 @@ cr_get_source (VALUE self)
1079
1185
  cairo_pattern_t *source;
1080
1186
  source = cairo_get_source (_SELF);
1081
1187
 
1082
- rb_source = rb_ivar_get (self, cr_id_source);
1083
1188
  if (source)
1084
1189
  {
1085
1190
  rb_cairo_check_status (cairo_pattern_status (source));
1191
+ rb_source = rb_ivar_get (self, cr_id_source);
1086
1192
  if (NIL_P (rb_source) || RVAL2CRPATTERN (rb_source) != source)
1087
1193
  {
1088
- rb_source =
1089
- CRPATTERN2RVAL (source, rb_ivar_get (self, cr_id_source_class));
1194
+ rb_source = CRPATTERN2RVAL (source);
1090
1195
  rb_ivar_set (self, cr_id_source, rb_source);
1091
1196
  }
1092
1197
  }
@@ -1206,6 +1311,8 @@ cr_get_group_target (VALUE self)
1206
1311
  cairo_surface_t *surface;
1207
1312
 
1208
1313
  surface = cairo_get_group_target (_SELF);
1314
+ if (!surface)
1315
+ return Qnil;
1209
1316
  rb_cairo_check_status (cairo_surface_status (surface));
1210
1317
  return CRSURFACE2RVAL (surface);
1211
1318
  }
@@ -1214,17 +1321,21 @@ cr_get_group_target (VALUE self)
1214
1321
  static VALUE
1215
1322
  cr_copy_path (VALUE self)
1216
1323
  {
1217
- VALUE path = CRPATH2RVAL (cairo_copy_path (_SELF));
1218
- cr_check_status (_SELF);
1219
- return path;
1324
+ cairo_path_t *path;
1325
+
1326
+ path = cairo_copy_path (_SELF);
1327
+ rb_cairo_check_status (path->status);
1328
+ return CRPATH2RVAL (path);
1220
1329
  }
1221
1330
 
1222
1331
  static VALUE
1223
1332
  cr_copy_path_flat (VALUE self)
1224
1333
  {
1225
- VALUE path = CRPATH2RVAL (cairo_copy_path_flat (_SELF));
1226
- cr_check_status (_SELF);
1227
- return path;
1334
+ cairo_path_t *path;
1335
+
1336
+ path = cairo_copy_path_flat (_SELF);
1337
+ rb_cairo_check_status (path->status);
1338
+ return CRPATH2RVAL (path);
1228
1339
  }
1229
1340
 
1230
1341
  static VALUE
@@ -1240,7 +1351,11 @@ Init_cairo_context (void)
1240
1351
  {
1241
1352
  cr_id_surface = rb_intern ("surface");
1242
1353
  cr_id_source = rb_intern ("source");
1243
- cr_id_source_class = rb_intern ("source_class");
1354
+
1355
+ cr_id_plus = rb_intern ("+");
1356
+ cr_id_minus = rb_intern ("-");
1357
+ cr_id_multi = rb_intern ("*");
1358
+ cr_id_div = rb_intern ("/");
1244
1359
 
1245
1360
  #if CAIRO_CHECK_VERSION(1, 3, 0)
1246
1361
  rb_cCairo_Rectangle =
@@ -1263,7 +1378,7 @@ Init_cairo_context (void)
1263
1378
  rb_define_class_under (rb_mCairo, "Context", rb_cObject);
1264
1379
 
1265
1380
  rb_define_alloc_func (rb_cCairo_Context, cr_allocate);
1266
-
1381
+
1267
1382
  /* Functions for manipulating state objects */
1268
1383
  rb_define_method (rb_cCairo_Context, "initialize", cr_initialize, 1);
1269
1384
 
@@ -1287,15 +1402,15 @@ Init_cairo_context (void)
1287
1402
  rb_define_method (rb_cCairo_Context, "set_line_width", cr_set_line_width, 1);
1288
1403
  rb_define_method (rb_cCairo_Context, "set_line_cap", cr_set_line_cap, 1);
1289
1404
  rb_define_method (rb_cCairo_Context, "set_line_join", cr_set_line_join, 1);
1290
- rb_define_method (rb_cCairo_Context, "set_dash", cr_set_dash, 2);
1405
+ rb_define_method (rb_cCairo_Context, "set_dash", cr_set_dash, -1);
1291
1406
  rb_define_method (rb_cCairo_Context, "set_miter_limit",
1292
1407
  cr_set_miter_limit, 1);
1293
-
1408
+
1294
1409
  rb_define_method (rb_cCairo_Context, "translate", cr_translate, 2);
1295
1410
  rb_define_method (rb_cCairo_Context, "scale", cr_scale, 2);
1296
1411
  rb_define_method (rb_cCairo_Context, "rotate", cr_rotate, 1);
1297
1412
  rb_define_method (rb_cCairo_Context, "transform", cr_transform, 1);
1298
-
1413
+
1299
1414
  rb_define_method (rb_cCairo_Context, "set_matrix", cr_set_matrix, 1);
1300
1415
  rb_define_method (rb_cCairo_Context, "identity_matrix",
1301
1416
  cr_identity_matrix, 0);
@@ -1311,38 +1426,35 @@ Init_cairo_context (void)
1311
1426
  rb_define_method (rb_cCairo_Context, "move_to", cr_move_to, 2);
1312
1427
  rb_define_method (rb_cCairo_Context, "new_sub_path", cr_new_sub_path, 0);
1313
1428
  rb_define_method (rb_cCairo_Context, "line_to", cr_line_to, 2);
1314
- rb_define_method (rb_cCairo_Context, "curve_to", cr_curve_to, 6);
1429
+ rb_define_method (rb_cCairo_Context, "curve_to", cr_curve_to_generic, -1);
1315
1430
  rb_define_method (rb_cCairo_Context, "arc", cr_arc, 5);
1316
1431
  rb_define_method (rb_cCairo_Context, "arc_negative", cr_arc_negative, 5);
1317
1432
  rb_define_method (rb_cCairo_Context, "rel_move_to", cr_rel_move_to, 2);
1318
1433
  rb_define_method (rb_cCairo_Context, "rel_line_to", cr_rel_line_to, 2);
1319
- rb_define_method (rb_cCairo_Context, "rel_curve_to", cr_rel_curve_to, 6);
1434
+ rb_define_method (rb_cCairo_Context, "rel_curve_to",
1435
+ cr_rel_curve_to_generic, -1);
1320
1436
  rb_define_method (rb_cCairo_Context, "rectangle", cr_rectangle, 4);
1321
1437
  rb_define_method (rb_cCairo_Context, "close_path", cr_close_path, 0);
1322
1438
 
1323
1439
  /* Painting functions */
1324
1440
  rb_define_method (rb_cCairo_Context, "paint", cr_paint_generic, -1);
1325
1441
  rb_define_method (rb_cCairo_Context, "mask", cr_mask_generic, -1);
1326
- rb_define_method (rb_cCairo_Context, "stroke", cr_stroke, 0);
1327
- rb_define_method (rb_cCairo_Context, "stroke_preserve",
1328
- cr_stroke_preserve, 0);
1329
- rb_define_method (rb_cCairo_Context, "fill", cr_fill, 0);
1330
- rb_define_method (rb_cCairo_Context, "fill_preserve", cr_fill_preserve, 0);
1442
+ rb_define_method (rb_cCairo_Context, "stroke", cr_stroke, -1);
1443
+ rb_define_method (rb_cCairo_Context, "fill", cr_fill, -1);
1331
1444
  rb_define_method (rb_cCairo_Context, "copy_page", cr_copy_page, 0);
1332
1445
  rb_define_method (rb_cCairo_Context, "show_page", cr_show_page, 0);
1333
1446
 
1334
1447
  /* Insideness testing */
1335
1448
  rb_define_method (rb_cCairo_Context, "in_stroke?", cr_in_stroke, 2);
1336
1449
  rb_define_method (rb_cCairo_Context, "in_fill?", cr_in_fill, 2);
1337
-
1450
+
1338
1451
  /* Rectangular extents */
1339
1452
  rb_define_method (rb_cCairo_Context, "stroke_extents", cr_stroke_extents, 0);
1340
1453
  rb_define_method (rb_cCairo_Context, "fill_extents", cr_fill_extents, 0);
1341
-
1454
+
1342
1455
  /* Clipping */
1343
1456
  rb_define_method (rb_cCairo_Context, "reset_clip", cr_reset_clip, 0);
1344
- rb_define_method (rb_cCairo_Context, "clip", cr_clip, 0);
1345
- rb_define_method (rb_cCairo_Context, "clip_preserve", cr_clip_preserve, 0);
1457
+ rb_define_method (rb_cCairo_Context, "clip", cr_clip, -1);
1346
1458
  #if CAIRO_CHECK_VERSION(1, 3, 0)
1347
1459
  rb_define_method (rb_cCairo_Context, "clip_extents", cr_clip_extents, 0);
1348
1460
  rb_define_method (rb_cCairo_Context, "clip_rectangle_list",