magickwand 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  require 'mkmf'
2
2
 
3
- MAGICKWAND_VERSION = "0.1.0"
3
+ MAGICKWAND_VERSION = "0.2.0"
4
4
  MIN_IM_VERS = "6.5.0"
5
5
  MIN_IM_VERS_NO = MIN_IM_VERS.tr(".","").to_i
6
6
 
@@ -50,7 +50,8 @@ unless have_library("MagickWand", "MagickWandGenesis", headers)
50
50
  end
51
51
 
52
52
  # ImageMagick features Release added
53
- ["MagickSetColorspace", # 6.5.1
53
+ ["DrawSetBorderColor", # 6.5.4
54
+ "MagickSetColorspace", # 6.5.1
54
55
  "MagickSetImageFuzz" # 6.5.1
55
56
  ].each do |func|
56
57
  have_func(func, headers)
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * magickwand.c
3
- * $Id: magickwand.c 146 2009-05-31 22:00:57Z rmagick $
3
+ * $Id: magickwand.c 164 2009-06-21 16:52:27Z rmagick $
4
4
  * Copyright (C) 2009 Timothy Paul Hunter
5
5
  */
6
6
 
@@ -145,7 +145,7 @@ void Init_magickwand(void)
145
145
  ImageMagick_config();
146
146
 
147
147
  mwr_init_Wand();
148
- mwr_init_GC();
148
+ mwr_init_Drawing();
149
149
  mwr_init_ImageMagickError();
150
150
  mwr_init_FatalImageMagickError();
151
151
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * magickwand.h
3
- * $Id: magickwand.h 25 2009-04-28 23:11:33Z rmagick $
3
+ * $Id: magickwand.h 285 2009-08-14 23:09:24Z rmagick $
4
4
  * Copyright (C) 2009 Timothy Paul Hunter
5
5
  */
6
6
 
@@ -32,8 +32,8 @@ typedef struct
32
32
 
33
33
  typedef struct
34
34
  {
35
- DrawingWand *drawingwand;
36
- } GC;
35
+ DrawingWand *wand;
36
+ } Drawing;
37
37
 
38
38
 
39
39
  // What to do when an option value is not in the list of defined option values
@@ -48,7 +48,7 @@ typedef enum {
48
48
  */
49
49
  VALUE mwr_mMagickWand;
50
50
  VALUE mwr_cWand;
51
- VALUE mwr_cGC;
51
+ VALUE mwr_cDrawing;
52
52
  VALUE mwr_eImageMagickError;
53
53
  VALUE mwr_eFatalImageMagickError;
54
54
 
@@ -56,7 +56,7 @@ VALUE mwr_eFatalImageMagickError;
56
56
  /*
57
57
  * Extern functions
58
58
  */
59
- extern void mwr_init_GC(void);
59
+ extern void mwr_init_Drawing(void);
60
60
  extern void mwr_init_Wand(void);
61
61
  extern void mwr_init_ImageMagickError(void);
62
62
  extern void mwr_init_FatalImageMagickError(void);
@@ -67,18 +67,24 @@ extern void mwr_check_error(ExceptionInfo *);
67
67
  extern MagickBooleanType mwr_get_option(VALUE, const char *, VALUE *);
68
68
  extern char *mwr_imagetype_to_s(ImageType);
69
69
  extern VALUE mwr_pixelpacket_to_hex(Image *, PixelPacket *);
70
+ extern VALUE mwr_pixelwand_to_hex(Image *, PixelWand *);
70
71
  extern void mwr_option_value_error(const char *, const char *);
71
72
  extern VALUE mwr_option_values_to_hash(char *);
72
73
  extern AlignType mwr_string_to_aligntype(VALUE, AlignType, OnUndefinedOption);
73
74
  extern ChannelType mwr_string_to_channeltype(VALUE, ChannelType, OnUndefinedOption);
75
+ extern ClipPathUnits mwr_string_to_clip_units(VALUE, ClipPathUnits, OnUndefinedOption);
74
76
  extern ColorspaceType mwr_string_to_colorspacetype(VALUE, ColorspaceType, OnUndefinedOption);
75
77
  extern CompositeOperator mwr_string_to_composetype(VALUE, CompositeOperator, OnUndefinedOption);
76
78
  extern CompressionType mwr_string_to_compressiontype(VALUE, CompressionType, OnUndefinedOption);
77
79
  extern DecorationType mwr_string_to_decorationtype(VALUE, DecorationType, OnUndefinedOption);
80
+ extern FillRule mwr_string_to_fillrule(VALUE, FillRule, OnUndefinedOption);
78
81
  extern FilterTypes mwr_string_to_filtertypes(VALUE, FilterTypes, OnUndefinedOption);
79
82
  extern GravityType mwr_string_to_gravitytype(VALUE, GravityType, OnUndefinedOption);
80
83
  extern ImageType mwr_string_to_imagetype(VALUE, ImageType, OnUndefinedOption);
84
+ extern LineCap mwr_string_to_line_cap(VALUE, LineCap, OnUndefinedOption);
85
+ extern LineJoin mwr_string_to_line_join(VALUE, LineJoin, OnUndefinedOption);
81
86
  extern MetricType mwr_string_to_metrictype(VALUE, MetricType, OnUndefinedOption);
87
+ extern PaintMethod mwr_string_to_paintmethod(VALUE, PaintMethod, OnUndefinedOption);
82
88
  extern StorageType mwr_string_to_storagetype(VALUE, StorageType, OnUndefinedOption);
83
89
  extern StretchType mwr_string_to_stretchtype(VALUE, StretchType, OnUndefinedOption);
84
90
  extern StyleType mwr_string_to_styletype(VALUE, StyleType, OnUndefinedOption);
@@ -87,5 +93,5 @@ extern char *mwr_format_size(const MagickSizeType, char *);
87
93
  extern void mwr_get_pixelpacket_from_pixelwand(PixelPacket *, PixelWand *);
88
94
  extern void mwr_get_pixelwand_from_pixelpacket(PixelWand *, PixelPacket *);
89
95
  extern void mwr_process_options(VALUE, VALUE);
90
- extern VALUE mwr_gc_new(void);
96
+ extern VALUE mwr_drawing_new(void);
91
97
  #endif
@@ -1,7 +1,7 @@
1
1
 
2
2
  /*
3
3
  * utility.c
4
- * $Id: utility.c 144 2009-05-31 20:51:53Z rmagick $
4
+ * $Id: utility.c 285 2009-08-14 23:09:24Z rmagick $
5
5
  * Copyright (C) 2009 Timothy Paul Hunter
6
6
  */
7
7
 
@@ -38,6 +38,7 @@ static ValueList align_types[] = {
38
38
  { "right", (long) RightAlign },
39
39
  { "start", (long) LeftAlign },
40
40
  { NULL, (long) UndefinedAlign } };
41
+
41
42
  static ValueList channel_types[] = {
42
43
  { "all", (long) AllChannels },
43
44
  { "alpha", (long) OpacityChannel },
@@ -59,6 +60,13 @@ static ValueList channel_types[] = {
59
60
  { "saturation", (long) GreenChannel },
60
61
  { "yellow", (long) YellowChannel },
61
62
  { NULL, (long) UndefinedChannel} };
63
+
64
+ static ValueList clip_units[] = {
65
+ { "objectboundingbox", (long) ObjectBoundingBox },
66
+ { "userspace", (long) UserSpace },
67
+ { "userspaceonuse", (long) UserSpaceOnUse } };
68
+
69
+
62
70
  static ValueList colorspace_types[] = {
63
71
  { "cmy", (long) CMYColorspace },
64
72
  { "cmyk", (long) CMYKColorspace },
@@ -83,6 +91,7 @@ static ValueList colorspace_types[] = {
83
91
  { "ypbpr", (long) YPbPrColorspace },
84
92
  { "yuv", (long) YUVColorspace },
85
93
  { NULL, (long) UndefinedColorspace } };
94
+
86
95
  static ValueList compose_types[] = {
87
96
  { "add", (long) AddCompositeOp },
88
97
  { "atop", (long) AtopCompositeOp },
@@ -142,6 +151,7 @@ static ValueList compose_types[] = {
142
151
  { "threshold", (long) ThresholdCompositeOp },
143
152
  { "xor", (long) XorCompositeOp },
144
153
  { NULL, (long) UndefinedCompositeOp } };
154
+
145
155
  static ValueList compression_types[] = {
146
156
  { "bzip", (long) BZipCompression },
147
157
  { "dxt1", (long) DXT1Compression },
@@ -159,12 +169,19 @@ static ValueList compression_types[] = {
159
169
  { "zip", (long) ZipCompression },
160
170
  { "runlengthencoded", (long) RLECompression },
161
171
  { NULL, (long) UndefinedCompression } };
172
+
162
173
  static ValueList decoration_types[] = {
163
174
  { "linethrough", (long) LineThroughDecoration },
164
175
  { "none", (long) NoDecoration },
165
176
  { "overline", (long) OverlineDecoration },
166
177
  { "underline", (long) UnderlineDecoration },
167
178
  { NULL, (long) UndefinedDecoration } };
179
+
180
+ static ValueList fill_rules[] = {
181
+ { "evenodd", (long) EvenOddRule },
182
+ { "nonzero", (long) NonZeroRule },
183
+ { NULL, (long) UndefinedRule } };
184
+
168
185
  static ValueList filter_types[] = {
169
186
  {"bartlett", (long) BartlettFilter},
170
187
  {"bessel", (long) BesselFilter},
@@ -217,6 +234,19 @@ static ValueList gravity_types[] = {
217
234
  { "west", (long) WestGravity },
218
235
  { "static", (long) StaticGravity },
219
236
  { NULL, (long) UndefinedGravity } };
237
+
238
+ static ValueList line_caps[] = {
239
+ { "butt", (long) ButtCap },
240
+ { "round", (long) RoundCap },
241
+ { "square", (long) SquareCap },
242
+ { NULL, (long) UndefinedCap } };
243
+
244
+ static ValueList line_joins[] = {
245
+ { "bevel", (long) BevelJoin },
246
+ { "miter", (long) MiterJoin },
247
+ { "round", (long) RoundJoin },
248
+ { NULL, (long) UndefinedJoin } };
249
+
220
250
  static ValueList metric_types[] = {
221
251
  { "ae", (long) AbsoluteErrorMetric },
222
252
  { "mae", (long) MeanAbsoluteErrorMetric },
@@ -226,6 +256,15 @@ static ValueList metric_types[] = {
226
256
  { "psnr", (long) PeakSignalToNoiseRatioMetric },
227
257
  { "rmse", (long) RootMeanSquaredErrorMetric },
228
258
  { NULL, (long) UndefinedMetric } };
259
+
260
+ static ValueList paint_methods[] = {
261
+ { "filltoborder", (long) FillToBorderMethod },
262
+ { "floodfill", (long) FloodfillMethod },
263
+ { "point", (long) PointMethod },
264
+ { "replace", (long) ReplaceMethod },
265
+ { "reset", (long) ResetMethod },
266
+ { NULL, (long) UndefinedMethod } };
267
+
229
268
  static ValueList storage_types[] = {
230
269
  { "char", (long) CharPixel },
231
270
  { "double", (long) DoublePixel },
@@ -235,6 +274,7 @@ static ValueList storage_types[] = {
235
274
  { "quantum", (long) QuantumPixel },
236
275
  { "short", (long) ShortPixel },
237
276
  { NULL, (long) UndefinedPixel } };
277
+
238
278
  static ValueList stretch_types[] = {
239
279
  { "any", (long) AnyStretch },
240
280
  { "condensed", (long) CondensedStretch },
@@ -247,12 +287,14 @@ static ValueList stretch_types[] = {
247
287
  { "ultracondensed", (long) UltraCondensedStretch },
248
288
  { "ultraexpanded", (long) UltraExpandedStretch },
249
289
  { NULL, (long) UndefinedStretch } };
290
+
250
291
  static ValueList style_types[] = {
251
- { "any", (long) AnyStyle },
292
+ { "any", (long) AnyStyle },
252
293
  { "italic", (long) ItalicStyle },
253
294
  { "normal", (long) NormalStyle },
254
295
  { "oblique", (long) ObliqueStyle },
255
296
  { NULL, (long) UndefinedStyle } };
297
+
256
298
  static ValueList weight_types[] = {
257
299
  { "any", 0L },
258
300
  { "light", 100L },
@@ -261,21 +303,26 @@ static ValueList weight_types[] = {
261
303
  { NULL, 0L } };
262
304
 
263
305
  static OptionList option_list[] = {
264
- {"align", align_types},
265
- {"channel", channel_types},
266
- {"colorspace", colorspace_types},
267
- {"compose", compose_types},
268
- {"compress", compression_types},
269
- {"decoration", decoration_types},
270
- {"filter", filter_types},
271
- {"gravity", gravity_types},
272
- {"metric", metric_types},
273
- {"type", image_types},
274
- {"storage_type", storage_types},
275
- {"stretch", stretch_types},
276
- {"style", style_types},
277
- {"weight", weight_types},
278
- {NULL, NULL} };
306
+ {"align", align_types},
307
+ {"channel", channel_types},
308
+ {"clip_units", clip_units},
309
+ {"colorspace", colorspace_types},
310
+ {"compose", compose_types},
311
+ {"compress", compression_types},
312
+ {"decoration", decoration_types},
313
+ {"fillrule", fill_rules},
314
+ {"filter", filter_types},
315
+ {"gravity", gravity_types},
316
+ {"metric", metric_types},
317
+ {"method", paint_methods},
318
+ {"type", image_types},
319
+ {"storage_type", storage_types},
320
+ {"line_cap", line_caps},
321
+ {"line_join", line_joins},
322
+ {"stretch", stretch_types},
323
+ {"style", style_types},
324
+ {"weight", weight_types},
325
+ {NULL, NULL} };
279
326
 
280
327
 
281
328
 
@@ -390,6 +437,11 @@ ChannelType mwr_string_to_channeltype(VALUE s, ChannelType defval, OnUndefinedOp
390
437
  return (ChannelType) string_to_enum("channel", channel_types, s, (long)defval, undef);
391
438
  }
392
439
 
440
+ ClipPathUnits mwr_string_to_clip_units(VALUE s, ClipPathUnits defval, OnUndefinedOption undef)
441
+ {
442
+ return (ClipPathUnits) string_to_enum("clip_units", clip_units, s, (long)defval, undef);
443
+ }
444
+
393
445
  ColorspaceType mwr_string_to_colorspacetype(VALUE s, ColorspaceType defval, OnUndefinedOption undef)
394
446
  {
395
447
  return (ColorspaceType) string_to_enum("colorspace", colorspace_types, s, (long)defval, undef);
@@ -410,6 +462,11 @@ DecorationType mwr_string_to_decorationtype(VALUE s, DecorationType defval, OnUn
410
462
  return (DecorationType) string_to_enum("decoration", decoration_types, s, (long)defval, undef);
411
463
  }
412
464
 
465
+ FillRule mwr_string_to_fillrule(VALUE s, FillRule defval, OnUndefinedOption undef)
466
+ {
467
+ return (FillRule) string_to_enum("fillrule", fill_rules, s, (long)defval, undef);
468
+ }
469
+
413
470
  FilterTypes mwr_string_to_filtertypes(VALUE s, FilterTypes defval, OnUndefinedOption undef)
414
471
  {
415
472
  return (FilterTypes) string_to_enum("filter", filter_types, s, (long)defval, undef);
@@ -425,11 +482,26 @@ ImageType mwr_string_to_imagetype(VALUE s, ImageType defval, OnUndefinedOption u
425
482
  return (ImageType) string_to_enum("type", image_types, s, (long)defval, undef);
426
483
  }
427
484
 
485
+ LineCap mwr_string_to_line_cap(VALUE s, LineCap defval, OnUndefinedOption undef)
486
+ {
487
+ return (LineCap) string_to_enum("line_cap", line_caps, s, (long)defval, undef);
488
+ }
489
+
490
+ LineJoin mwr_string_to_line_join(VALUE s, LineJoin defval, OnUndefinedOption undef)
491
+ {
492
+ return (LineCap) string_to_enum("line_join", line_joins, s, (long)defval, undef);
493
+ }
494
+
428
495
  MetricType mwr_string_to_metrictype(VALUE s, MetricType defval, OnUndefinedOption undef)
429
496
  {
430
497
  return (MetricType) string_to_enum("type", metric_types, s, (long)defval, undef);
431
498
  }
432
499
 
500
+ PaintMethod mwr_string_to_paintmethod(VALUE s, PaintMethod defval, OnUndefinedOption undef)
501
+ {
502
+ return (PaintMethod) string_to_enum("method", paint_methods, s, (long)defval, undef);
503
+ }
504
+
433
505
  StorageType mwr_string_to_storagetype(VALUE s, StorageType defval, OnUndefinedOption undef)
434
506
  {
435
507
  return (StretchType) string_to_enum("storage_type", storage_types, s, (long)defval, undef);
@@ -533,6 +605,21 @@ extern void mwr_get_pixelwand_from_pixelpacket(PixelWand *pixelwand, PixelPacket
533
605
 
534
606
 
535
607
 
608
+ /*
609
+ * Return the hex representation of the pixel as a Ruby string.
610
+ * (The PixelWand method always returns the rgb() representation.)
611
+ */
612
+ extern VALUE mwr_pixelwand_to_hex(Image *image, PixelWand *pixelwand)
613
+ {
614
+ PixelPacket pixelpacket;
615
+
616
+ mwr_get_pixelpacket_from_pixelwand(&pixelpacket, pixelwand);
617
+ return mwr_pixelpacket_to_hex(image, &pixelpacket);
618
+ }
619
+
620
+
621
+
622
+
536
623
  /*
537
624
  * Return the hex representation of the pixel as a Ruby string.
538
625
  * (The PixelWand method always returns the rgb() representation.)
@@ -659,16 +746,55 @@ static VALUE rescue_option(VALUE args, VALUE errinfo)
659
746
  * rescue NoMethodError
660
747
  * raise(ArgumentError, "undefined option :#{option}")
661
748
  * end
749
+ *
750
+ * Because the options hash is unordered in 1.8.*, we make two passes over the
751
+ * options. The :stroke_opacity and :fill_opacity options must succeed the
752
+ * :stroke and :fill options, otherwise the opacity specified by the colors
753
+ * overrides the opacity specified by the :xxx_opacity options. So the first
754
+ * pass specifically skips these two options, and the second pass skips over
755
+ * all but these two options.
662
756
  */
663
- static int begin_option(VALUE option, VALUE value, VALUE obj)
757
+
758
+ static int options_pass_1(VALUE option, VALUE value, VALUE obj)
664
759
  {
665
760
  VALUE args;
761
+ volatile VALUE fill_opacity, stroke_opacity;
762
+
763
+ fill_opacity = ID2SYM(rb_intern("fill_opacity"));
764
+ stroke_opacity = ID2SYM(rb_intern("stroke_opacity"));
765
+
766
+ if (!(option == fill_opacity || option == stroke_opacity))
767
+ {
768
+ args = rb_ary_new2(3);
769
+ rb_ary_push(args, option);
770
+ rb_ary_push(args, value);
771
+ rb_ary_push(args, obj);
772
+ (void) rb_rescue(call_option_setter, args, rescue_option, args);
773
+ }
774
+
775
+ return 0;
776
+ }
777
+
778
+
779
+
780
+
781
+ static int options_pass_2(VALUE option, VALUE value, VALUE obj)
782
+ {
783
+ VALUE args;
784
+ volatile VALUE fill_opacity, stroke_opacity;
785
+
786
+ fill_opacity = ID2SYM(rb_intern("fill_opacity"));
787
+ stroke_opacity = ID2SYM(rb_intern("stroke_opacity"));
788
+
789
+ if (option == fill_opacity || option == stroke_opacity)
790
+ {
791
+ args = rb_ary_new2(3);
792
+ rb_ary_push(args, option);
793
+ rb_ary_push(args, value);
794
+ rb_ary_push(args, obj);
795
+ (void) rb_rescue(call_option_setter, args, rescue_option, args);
796
+ }
666
797
 
667
- args = rb_ary_new2(3);
668
- rb_ary_push(args, option);
669
- rb_ary_push(args, value);
670
- rb_ary_push(args, obj);
671
- (void) rb_rescue(call_option_setter, args, rescue_option, args);
672
798
  return 0;
673
799
  }
674
800
 
@@ -682,7 +808,8 @@ void mwr_process_options(VALUE obj, VALUE options)
682
808
  {
683
809
  if (options != Qnil)
684
810
  {
685
- rb_hash_foreach(options, begin_option, obj);
811
+ rb_hash_foreach(options, options_pass_1, obj);
812
+ rb_hash_foreach(options, options_pass_2, obj);
686
813
  }
687
814
  }
688
815
 
@@ -1,6 +1,6 @@
1
1
  /*
2
2
  * wand.c
3
- * $Id: wand.c 147 2009-05-31 22:01:22Z rmagick $
3
+ * $Id: wand.c 275 2009-08-13 22:30:55Z rmagick $
4
4
  * Copyright (C) 2009 Timothy Paul Hunter
5
5
  */
6
6
 
@@ -253,7 +253,7 @@ leave:
253
253
  static VALUE wand_annotate(int argc, VALUE *argv, VALUE obj)
254
254
  {
255
255
  Wand *wand;
256
- GC *gc;
256
+ Drawing *drawing;
257
257
  double x, y, angle;
258
258
  volatile VALUE graphics_context;
259
259
  VALUE v, text, options;
@@ -271,11 +271,11 @@ static VALUE wand_annotate(int argc, VALUE *argv, VALUE obj)
271
271
  y = mwr_get_option(options, "y", &v) ? NUM2DBL(v) : 0.0;
272
272
  angle = mwr_get_option(options, "angle", &v) ? NUM2DBL(v) : 0.0;
273
273
 
274
- graphics_context = mwr_gc_new();
275
- Data_Get_Struct(graphics_context, GC, gc);
274
+ graphics_context = mwr_drawing_new();
275
+ Data_Get_Struct(graphics_context, Drawing, drawing);
276
276
 
277
277
  // Override default NorthWest gravity. It's useless.
278
- DrawSetGravity(gc->drawingwand, CenterGravity);
278
+ DrawSetGravity(drawing->wand, CenterGravity);
279
279
  mwr_process_options(graphics_context, options);
280
280
 
281
281
  Data_Get_Struct(obj, Wand, wand);
@@ -283,7 +283,7 @@ static VALUE wand_annotate(int argc, VALUE *argv, VALUE obj)
283
283
  MagickResetIterator(wand->magickwand);
284
284
  while (MagickNextImage(wand->magickwand) != MagickFalse)
285
285
  {
286
- MagickAnnotateImage(wand->magickwand, gc->drawingwand, x, y, angle, text_string);
286
+ MagickAnnotateImage(wand->magickwand, drawing->wand, x, y, angle, text_string);
287
287
  }
288
288
 
289
289
  return obj;
@@ -471,6 +471,72 @@ static VALUE wand_background(VALUE obj)
471
471
 
472
472
 
473
473
 
474
+ /*
475
+ * returns the border color property for the 0th image
476
+ */
477
+ static VALUE wand_bordercolor(VALUE obj)
478
+ {
479
+ Wand *wand;
480
+ PixelWand *bordercolor;
481
+ Image *image;
482
+ volatile VALUE color;
483
+
484
+ if (FIX2LONG(wand_length(obj)) == 0)
485
+ {
486
+ return Qnil;
487
+ }
488
+
489
+ Data_Get_Struct(obj, Wand, wand);
490
+
491
+ MagickResetIterator(wand->magickwand);
492
+ bordercolor = NewPixelWand();
493
+ MagickGetImageBorderColor(wand->magickwand, bordercolor);
494
+ mwr_check_magickwand_error(wand->magickwand);
495
+
496
+ image = GetImageFromMagickWand(wand->magickwand);
497
+ mwr_check_magickwand_error(wand->magickwand);
498
+
499
+ color = mwr_pixelwand_to_hex(image, bordercolor);
500
+ DestroyPixelWand(bordercolor);
501
+
502
+ return color;
503
+ }
504
+
505
+
506
+
507
+
508
+ /*
509
+ * sets the border color property for the 0th image
510
+ */
511
+ static VALUE wand_bordercolor_set(VALUE obj, VALUE color)
512
+ {
513
+ Wand *wand;
514
+ PixelWand *pixelwand;
515
+ char *bordercolor;
516
+
517
+ rb_check_frozen(obj);
518
+
519
+ Data_Get_Struct(obj, Wand, wand);
520
+
521
+ bordercolor = StringValuePtr(color);
522
+ pixelwand = NewPixelWand();
523
+ PixelSetColor(pixelwand, bordercolor);
524
+ mwr_check_pixelwand_error(pixelwand);
525
+
526
+ MagickResetIterator(wand->magickwand);
527
+ while (MagickNextImage(wand->magickwand) != MagickFalse)
528
+ {
529
+ (void) MagickSetImageBorderColor(wand->magickwand, pixelwand);
530
+ mwr_check_magickwand_error(wand->magickwand);
531
+ }
532
+ DestroyPixelWand(pixelwand);
533
+
534
+ return color;
535
+ }
536
+
537
+
538
+
539
+
474
540
  static VALUE convolve(int argc, VALUE *argv, VALUE obj,
475
541
  MagickBooleanType (*convolve)(MagickWand *, const ChannelType, const double, const double))
476
542
  {
@@ -520,17 +586,17 @@ static VALUE wand_border(int argc, VALUE *argv, VALUE obj)
520
586
  Wand *wand;
521
587
  PixelWand *pixelwand;
522
588
  VALUE color, wt, ht;
523
- char *border_color;
589
+ char *bordercolor;
524
590
  unsigned long width, height;
525
591
 
526
592
  rb_check_frozen(obj);
527
593
  (void) rb_scan_args(argc, argv, "12", &color, &wt, &ht);
528
- border_color = StringValuePtr(color);
594
+ bordercolor = StringValuePtr(color);
529
595
  width = wt != Qnil ? NUM2ULONG(wt) : 1UL;
530
596
  height = ht != Qnil ? NUM2ULONG(ht) : width;
531
597
 
532
598
  pixelwand = NewPixelWand();
533
- PixelSetColor(pixelwand, border_color);
599
+ PixelSetColor(pixelwand, bordercolor);
534
600
  mwr_check_pixelwand_error(pixelwand);
535
601
 
536
602
  Data_Get_Struct(obj, Wand, wand);
@@ -971,6 +1037,10 @@ static VALUE wand_display(VALUE obj)
971
1037
  Wand *wand;
972
1038
 
973
1039
  Data_Get_Struct(obj, Wand, wand);
1040
+ if (MagickGetNumberImages(wand->magickwand) == 0UL)
1041
+ {
1042
+ return Qnil;
1043
+ }
974
1044
  MagickDisplayImages(wand->magickwand, NULL);
975
1045
  mwr_check_magickwand_error(wand->magickwand);
976
1046
  return obj;
@@ -979,6 +1049,28 @@ static VALUE wand_display(VALUE obj)
979
1049
 
980
1050
 
981
1051
 
1052
+ static VALUE wand_draw(VALUE obj, VALUE drawing_obj)
1053
+ {
1054
+ Wand *wand;
1055
+ Drawing *drawing;
1056
+
1057
+ rb_check_frozen(obj);
1058
+ Data_Get_Struct(obj, Wand, wand);
1059
+ Data_Get_Struct(drawing_obj, Drawing, drawing);
1060
+
1061
+ MagickResetIterator(wand->magickwand);
1062
+ while (MagickNextImage(wand->magickwand) != MagickFalse)
1063
+ {
1064
+ MagickDrawImage(wand->magickwand, drawing->wand);
1065
+ mwr_check_magickwand_error(wand->magickwand);
1066
+ }
1067
+
1068
+ return obj;
1069
+ }
1070
+
1071
+
1072
+
1073
+
982
1074
  /*
983
1075
  * (>= 1.8.7) if no block return enumerator
984
1076
  */
@@ -2262,6 +2354,8 @@ void mwr_init_Wand(void)
2262
2354
  rb_define_method(mwr_cWand, "animate", wand_animate, -1);
2263
2355
  rb_define_method(mwr_cWand, "annotate", wand_annotate, -1);
2264
2356
  rb_define_method(mwr_cWand, "background", wand_background, 0);
2357
+ rb_define_method(mwr_cWand, "bordercolor", wand_bordercolor, 0);
2358
+ rb_define_method(mwr_cWand, "bordercolor=", wand_bordercolor_set, 1);
2265
2359
  rb_define_method(mwr_cWand, "blur", wand_blur, -1);
2266
2360
  rb_define_method(mwr_cWand, "border", wand_border, -1);
2267
2361
  rb_define_method(mwr_cWand, "colors", wand_colors, 0);
@@ -2273,6 +2367,7 @@ void mwr_init_Wand(void)
2273
2367
  rb_define_method(mwr_cWand, "depth", wand_depth, 0);
2274
2368
  rb_define_method(mwr_cWand, "dimensions", wand_dimensions, 0);
2275
2369
  rb_define_method(mwr_cWand, "display", wand_display, 0);
2370
+ rb_define_method(mwr_cWand, "draw", wand_draw, 1);
2276
2371
  rb_define_method(mwr_cWand, "export_pixels", wand_export_pixels, -1);
2277
2372
  rb_define_method(mwr_cWand, "filename", wand_filename, 0);
2278
2373
  rb_define_method(mwr_cWand, "format", wand_format, 0);