rmagick 2.8.0 → 2.9.0

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

Potentially problematic release.


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

Files changed (88) hide show
  1. data/ChangeLog +10 -2
  2. data/README.html +7 -7
  3. data/doc/comtasks.html +2 -2
  4. data/doc/constants.html +5 -5
  5. data/doc/draw.html +131 -20
  6. data/doc/ex/InitialCoords.rb +1 -1
  7. data/doc/ex/NewCoordSys.rb +2 -2
  8. data/doc/ex/OrigCoordSys.rb +1 -1
  9. data/doc/ex/RotateScale.rb +2 -2
  10. data/doc/ex/Skew.rb +2 -2
  11. data/doc/ex/ViewBox.rb +1 -1
  12. data/doc/ex/arc.rb +4 -2
  13. data/doc/ex/arcs02.rb +1 -1
  14. data/doc/ex/bounding_box.rb +3 -0
  15. data/doc/ex/cbezier1.rb +2 -0
  16. data/doc/ex/cbezier2.rb +2 -0
  17. data/doc/ex/cbezier3.rb +2 -0
  18. data/doc/ex/cbezier4.rb +2 -0
  19. data/doc/ex/cbezier5.rb +2 -0
  20. data/doc/ex/cbezier6.rb +2 -0
  21. data/doc/ex/channel.rb +1 -0
  22. data/doc/ex/circle.rb +2 -0
  23. data/doc/ex/cubic01.rb +1 -1
  24. data/doc/ex/cubic02.rb +1 -1
  25. data/doc/ex/ellipse.rb +2 -0
  26. data/doc/ex/font_styles.rb +12 -10
  27. data/doc/ex/get_type_metrics.rb +2 -0
  28. data/doc/ex/grav.rb +2 -0
  29. data/doc/ex/image.rb +1 -1
  30. data/doc/ex/line.rb +2 -0
  31. data/doc/ex/opacity.rb +6 -4
  32. data/doc/ex/path.rb +2 -0
  33. data/doc/ex/polaroid.rb +2 -0
  34. data/doc/ex/qbezierpath.rb +3 -0
  35. data/doc/ex/rectangle.rb +2 -0
  36. data/doc/ex/rotate.rb +2 -0
  37. data/doc/ex/roundrect.rb +2 -0
  38. data/doc/ex/skewx.rb +2 -0
  39. data/doc/ex/skewy.rb +2 -0
  40. data/doc/ex/stroke_dasharray.rb +2 -0
  41. data/doc/ex/stroke_width.rb +2 -0
  42. data/doc/ex/text.rb +3 -2
  43. data/doc/ex/text01.rb +1 -1
  44. data/doc/ex/text_styles.rb +1 -1
  45. data/doc/ex/text_undercolor.rb +2 -0
  46. data/doc/ex/translate.rb +3 -1
  47. data/doc/ilist.html +2 -2
  48. data/doc/image1.html +2 -2
  49. data/doc/image2.html +2 -2
  50. data/doc/image3.html +37 -6
  51. data/doc/imageattrs.html +2 -2
  52. data/doc/imusage.html +3 -3
  53. data/doc/index.html +3 -3
  54. data/doc/info.html +2 -2
  55. data/doc/magick.html +2 -2
  56. data/doc/optequiv.html +24 -2
  57. data/doc/rvg.html +2 -2
  58. data/doc/rvgclip.html +2 -2
  59. data/doc/rvggroup.html +2 -2
  60. data/doc/rvgimage.html +2 -2
  61. data/doc/rvgpattern.html +2 -2
  62. data/doc/rvgshape.html +2 -2
  63. data/doc/rvgstyle.html +2 -2
  64. data/doc/rvgtext.html +2 -2
  65. data/doc/rvgtspan.html +2 -2
  66. data/doc/rvgtut.html +2 -2
  67. data/doc/rvguse.html +2 -2
  68. data/doc/rvgxform.html +2 -2
  69. data/doc/struct.html +2 -2
  70. data/doc/usage.html +6 -4
  71. data/ext/RMagick/MANIFEST +6 -1
  72. data/ext/RMagick/extconf.rb +18 -2
  73. data/ext/RMagick/rmagick.c +312 -0
  74. data/ext/RMagick/rmagick.h +137 -61
  75. data/ext/RMagick/rmdraw.c +271 -377
  76. data/ext/RMagick/rmenum.c +1016 -0
  77. data/ext/RMagick/rmimage.c +172 -16
  78. data/ext/RMagick/rminfo.c +5 -5
  79. data/ext/RMagick/rmmain.c +50 -303
  80. data/ext/RMagick/rmmontage.c +386 -0
  81. data/ext/RMagick/rmpixel.c +816 -0
  82. data/ext/RMagick/rmstruct.c +887 -0
  83. data/ext/RMagick/rmutil.c +25 -2634
  84. data/lib/RMagick.rb +46 -2
  85. data/lib/rvg/misc.rb +5 -4
  86. data/lib/rvg/stylable.rb +7 -1
  87. data/rmagick.gemspec +1 -1
  88. metadata +7 -2
@@ -0,0 +1,887 @@
1
+ /* $Id: rmstruct.c,v 1.2 2008/12/27 17:16:04 rmagick Exp $ */
2
+ /*============================================================================\
3
+ | Copyright (C) 2008 by Timothy P. Hunter
4
+ | Name: rmstruct.c
5
+ | Author: Tim Hunter
6
+ | Purpose: Contains various Struct class methods.
7
+ \============================================================================*/
8
+
9
+ #include "rmagick.h"
10
+
11
+
12
+
13
+
14
+ static const char *ComplianceType_name(ComplianceType *);
15
+ static VALUE ComplianceType_new(ComplianceType);
16
+ static const char *StretchType_name(StretchType);
17
+ static VALUE StretchType_new(StretchType);
18
+ static const char *StyleType_name(StyleType);
19
+ static VALUE StyleType_new(StyleType);
20
+
21
+
22
+
23
+
24
+ /*
25
+ Extern: Import_AffineMatrix
26
+ Purpose: Given a C AffineMatrix, create the equivalent
27
+ AffineMatrix object.
28
+ Notes: am = Magick::AffineMatrix.new(sx, rx, ry, sy, tx, ty)
29
+ */
30
+ VALUE
31
+ Import_AffineMatrix(AffineMatrix *affine)
32
+ {
33
+ VALUE argv[6];
34
+
35
+ argv[0] = rb_float_new(affine->sx);
36
+ argv[1] = rb_float_new(affine->rx);
37
+ argv[2] = rb_float_new(affine->ry);
38
+ argv[3] = rb_float_new(affine->sy);
39
+ argv[4] = rb_float_new(affine->tx);
40
+ argv[5] = rb_float_new(affine->ty);
41
+ return rb_class_new_instance(6, argv, Class_AffineMatrix);
42
+ }
43
+
44
+
45
+ /*
46
+ Extern: Export_AffineMatrix
47
+ Purpose: Convert a Magick::AffineMatrix object to a AffineMatrix structure.
48
+ Notes: If not initialized, the defaults are [sx,rx,ry,sy,tx,ty] = [1,0,0,1,0,0]
49
+ */
50
+ void
51
+ Export_AffineMatrix(AffineMatrix *am, VALUE st)
52
+ {
53
+ volatile VALUE values, v;
54
+
55
+ if (CLASS_OF(st) != Class_AffineMatrix)
56
+ {
57
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
58
+ rb_class2name(CLASS_OF(st)));
59
+ }
60
+ values = rb_funcall(st, rm_ID_values, 0);
61
+ v = rb_ary_entry(values, 0);
62
+ am->sx = v == Qnil ? 1.0 : NUM2DBL(v);
63
+ v = rb_ary_entry(values, 1);
64
+ am->rx = v == Qnil ? 0.0 : NUM2DBL(v);
65
+ v = rb_ary_entry(values, 2);
66
+ am->ry = v == Qnil ? 0.0 : NUM2DBL(v);
67
+ v = rb_ary_entry(values, 3);
68
+ am->sy = v == Qnil ? 1.0 : NUM2DBL(v);
69
+ v = rb_ary_entry(values, 4);
70
+ am->tx = v == Qnil ? 0.0 : NUM2DBL(v);
71
+ v = rb_ary_entry(values, 5);
72
+ am->ty = v == Qnil ? 0.0 : NUM2DBL(v);
73
+ }
74
+
75
+
76
+ /*
77
+ Extern: ChromaticityInfo_new(pp)
78
+ Purpose: Create a Magick::ChromaticityInfo object from a
79
+ ChromaticityInfo structure.
80
+ */
81
+ VALUE
82
+ ChromaticityInfo_new(ChromaticityInfo *ci)
83
+ {
84
+ volatile VALUE red_primary;
85
+ volatile VALUE green_primary;
86
+ volatile VALUE blue_primary;
87
+ volatile VALUE white_point;
88
+
89
+ red_primary = Import_PrimaryInfo(&ci->red_primary);
90
+ green_primary = Import_PrimaryInfo(&ci->green_primary);
91
+ blue_primary = Import_PrimaryInfo(&ci->blue_primary);
92
+ white_point = Import_PrimaryInfo(&ci->white_point);
93
+
94
+ return rb_funcall(Class_Chromaticity, rm_ID_new, 4
95
+ , red_primary, green_primary, blue_primary, white_point);
96
+ }
97
+
98
+
99
+ /*
100
+ Extern: Export_ChromaticityInfo
101
+ Purpose: Extract the elements from a Magick::ChromaticityInfo
102
+ and store in a ChromaticityInfo structure.
103
+ */
104
+ void
105
+ Export_ChromaticityInfo(ChromaticityInfo *ci, VALUE chrom)
106
+ {
107
+ volatile VALUE chrom_members;
108
+ volatile VALUE red_primary, green_primary, blue_primary, white_point;
109
+ volatile VALUE entry_members, x, y;
110
+ ID values_id;
111
+
112
+ if (CLASS_OF(chrom) != Class_Chromaticity)
113
+ {
114
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
115
+ rb_class2name(CLASS_OF(chrom)));
116
+ }
117
+ values_id = rm_ID_values;
118
+
119
+ // Get the struct members in an array
120
+ chrom_members = rb_funcall(chrom, values_id, 0);
121
+ red_primary = rb_ary_entry(chrom_members, 0);
122
+ green_primary = rb_ary_entry(chrom_members, 1);
123
+ blue_primary = rb_ary_entry(chrom_members, 2);
124
+ white_point = rb_ary_entry(chrom_members, 3);
125
+
126
+ // Get the red_primary PrimaryInfo members in an array
127
+ entry_members = rb_funcall(red_primary, values_id, 0);
128
+ x = rb_ary_entry(entry_members, 0); // red_primary.x
129
+ ci->red_primary.x = x == Qnil ? 0.0 : NUM2DBL(x);
130
+ y = rb_ary_entry(entry_members, 1); // red_primary.y
131
+ ci->red_primary.y = y == Qnil ? 0.0 : NUM2DBL(y);
132
+ ci->red_primary.z = 0.0;
133
+
134
+ // Get the green_primary PrimaryInfo members in an array
135
+ entry_members = rb_funcall(green_primary, values_id, 0);
136
+ x = rb_ary_entry(entry_members, 0); // green_primary.x
137
+ ci->green_primary.x = x == Qnil ? 0.0 : NUM2DBL(x);
138
+ y = rb_ary_entry(entry_members, 1); // green_primary.y
139
+ ci->green_primary.y = y == Qnil ? 0.0 : NUM2DBL(y);
140
+ ci->green_primary.z = 0.0;
141
+
142
+ // Get the blue_primary PrimaryInfo members in an array
143
+ entry_members = rb_funcall(blue_primary, values_id, 0);
144
+ x = rb_ary_entry(entry_members, 0); // blue_primary.x
145
+ ci->blue_primary.x = x == Qnil ? 0.0 : NUM2DBL(x);
146
+ y = rb_ary_entry(entry_members, 1); // blue_primary.y
147
+ ci->blue_primary.y = y == Qnil ? 0.0 : NUM2DBL(y);
148
+ ci->blue_primary.z = 0.0;
149
+
150
+ // Get the white_point PrimaryInfo members in an array
151
+ entry_members = rb_funcall(white_point, values_id, 0);
152
+ x = rb_ary_entry(entry_members, 0); // white_point.x
153
+ ci->white_point.x = x == Qnil ? 0.0 : NUM2DBL(x);
154
+ y = rb_ary_entry(entry_members, 1); // white_point.y
155
+ ci->white_point.y = y == Qnil ? 0.0 : NUM2DBL(y);
156
+ ci->white_point.z = 0.0;
157
+ }
158
+
159
+
160
+ /*
161
+ Method: Magick::Chromaticity#to_s
162
+ Purpose: Create a string representation of a Magick::Chromaticity
163
+ */
164
+ VALUE
165
+ ChromaticityInfo_to_s(VALUE self)
166
+ {
167
+ ChromaticityInfo ci;
168
+ char buff[200];
169
+
170
+ Export_ChromaticityInfo(&ci, self);
171
+ sprintf(buff, "red_primary=(x=%g,y=%g) "
172
+ "green_primary=(x=%g,y=%g) "
173
+ "blue_primary=(x=%g,y=%g) "
174
+ "white_point=(x=%g,y=%g) ",
175
+ ci.red_primary.x, ci.red_primary.y,
176
+ ci.green_primary.x, ci.green_primary.y,
177
+ ci.blue_primary.x, ci.blue_primary.y,
178
+ ci.white_point.x, ci.white_point.y);
179
+ return rb_str_new2(buff);
180
+ }
181
+
182
+
183
+ /*
184
+ External: Import_ColorInfo
185
+ Purpose: Convert a ColorInfo structure to a Magick::Color
186
+ */
187
+ VALUE
188
+ Import_ColorInfo(const ColorInfo *ci)
189
+ {
190
+ ComplianceType compliance_type;
191
+ volatile VALUE name;
192
+ volatile VALUE compliance;
193
+ volatile VALUE color;
194
+
195
+ name = rb_str_new2(ci->name);
196
+
197
+ compliance_type = ci->compliance;
198
+ compliance = ComplianceType_new(compliance_type);
199
+ color = Pixel_from_MagickPixelPacket(&(ci->color));
200
+
201
+ return rb_funcall(Class_Color, rm_ID_new, 3
202
+ , name, compliance, color);
203
+ }
204
+
205
+
206
+ /*
207
+ External: Export_ColorInfo
208
+ Purpose: Convert a Magick::Color to a ColorInfo structure
209
+ */
210
+ void
211
+ Export_ColorInfo(ColorInfo *ci, VALUE st)
212
+ {
213
+ Pixel *pixel;
214
+ volatile VALUE members, m;
215
+
216
+ if (CLASS_OF(st) != Class_Color)
217
+ {
218
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
219
+ rb_class2name(CLASS_OF(st)));
220
+ }
221
+
222
+ memset(ci, '\0', sizeof(ColorInfo));
223
+
224
+ members = rb_funcall(st, rm_ID_values, 0);
225
+
226
+ m = rb_ary_entry(members, 0);
227
+ if (m != Qnil)
228
+ {
229
+ (void) CloneString((char **)&(ci->name), StringValuePtr(m));
230
+ }
231
+ m = rb_ary_entry(members, 1);
232
+ if (m != Qnil)
233
+ {
234
+ VALUE_TO_ENUM(m, ci->compliance, ComplianceType);
235
+ }
236
+ m = rb_ary_entry(members, 2);
237
+ if (m != Qnil)
238
+ {
239
+ Data_Get_Struct(m, Pixel, pixel);
240
+ // For >= 6.3.0, ColorInfo.color is a MagickPixelPacket so we have to
241
+ // convert the PixelPacket.
242
+ GetMagickPixelPacket(NULL, &ci->color);
243
+ ci->color.red = (MagickRealType) pixel->red;
244
+ ci->color.green = (MagickRealType) pixel->green;
245
+ ci->color.blue = (MagickRealType) pixel->blue;
246
+ ci->color.opacity = (MagickRealType) OpaqueOpacity;
247
+ ci->color.index = (MagickRealType) 0;
248
+ }
249
+ }
250
+
251
+
252
+ /*
253
+ Extern: Color_to_MagickPixelPacket
254
+ Purpose: Convert either a String color name or
255
+ a Magick::Pixel to a MagickPixelPacket
256
+ Notes: The channel values in a MagickPixelPacket are doubles.
257
+ */
258
+ void
259
+ Color_to_MagickPixelPacket(Image *image, MagickPixelPacket *mpp, VALUE color)
260
+ {
261
+ PixelPacket pp;
262
+
263
+ // image can be NULL
264
+ GetMagickPixelPacket(image, mpp);
265
+
266
+ memset(&pp, '\0', sizeof(pp));
267
+ Color_to_PixelPacket(&pp, color);
268
+ mpp->red = (MagickRealType) pp.red;
269
+ mpp->green = (MagickRealType) pp.green;
270
+ mpp->blue = (MagickRealType) pp.blue;
271
+ mpp->opacity = (MagickRealType) pp.opacity;
272
+ }
273
+
274
+
275
+ /*
276
+ Static: destroy_ColorInfo
277
+ Purpose: free the storage allocated by Export_ColorInfo, above.
278
+ */
279
+ static void
280
+ destroy_ColorInfo(ColorInfo *ci)
281
+ {
282
+ magick_free((void*)ci->name);
283
+ ci->name = NULL;
284
+ }
285
+
286
+
287
+ /*
288
+ Method: Color#to_s
289
+ Purpose: Return a string representation of a Magick::Color object
290
+ */
291
+ VALUE
292
+ Color_to_s(VALUE self)
293
+ {
294
+ ColorInfo ci;
295
+ char buff[1024];
296
+
297
+ Export_ColorInfo(&ci, self);
298
+
299
+ sprintf(buff, "name=%s, compliance=%s, "
300
+ #if (QuantumDepth == 32 || QuantumDepth == 64) && defined(HAVE_TYPE_LONG_DOUBLE)
301
+ "color.red=%Lg, color.green=%Lg, color.blue=%Lg, color.opacity=%Lg ",
302
+ #else
303
+ "color.red=%g, color.green=%g, color.blue=%g, color.opacity=%g ",
304
+ #endif
305
+ ci.name,
306
+ ComplianceType_name(&ci.compliance),
307
+ ci.color.red, ci.color.green, ci.color.blue, ci.color.opacity);
308
+
309
+ destroy_ColorInfo(&ci);
310
+ return rb_str_new2(buff);
311
+ }
312
+
313
+
314
+ /*
315
+ Static: ComplianceType_name
316
+ Purpose: Return the string representation of a ComplianceType value
317
+ Notes: xMagick will OR multiple compliance types so we have to
318
+ arbitrarily pick one name. Set the compliance argument
319
+ to the selected value.
320
+ */
321
+ static const char *
322
+ ComplianceType_name(ComplianceType *c)
323
+ {
324
+ if ((*c & (SVGCompliance|X11Compliance|XPMCompliance))
325
+ == (SVGCompliance|X11Compliance|XPMCompliance))
326
+ {
327
+ return "AllCompliance";
328
+ }
329
+ else if (*c & SVGCompliance)
330
+ {
331
+ *c = SVGCompliance;
332
+ return "SVGCompliance";
333
+ }
334
+ else if (*c & X11Compliance)
335
+ {
336
+ *c = X11Compliance;
337
+ return "X11Compliance";
338
+ }
339
+ else if (*c & XPMCompliance)
340
+ {
341
+ *c = XPMCompliance;
342
+ return "XPMCompliance";
343
+ }
344
+ else if (*c == NoCompliance)
345
+ {
346
+ *c = NoCompliance;
347
+ return "NoCompliance";
348
+ }
349
+ else
350
+ {
351
+ *c = UndefinedCompliance;
352
+ return "UndefinedCompliance";
353
+ }
354
+ }
355
+
356
+
357
+ /*
358
+ * Static: ComplianceType_new
359
+ Purpose: construct a ComplianceType enum object for the specified value
360
+ */
361
+ static VALUE
362
+ ComplianceType_new(ComplianceType compliance)
363
+ {
364
+ const char *name;
365
+
366
+ // Turn off undefined bits
367
+ compliance &= (SVGCompliance|X11Compliance|XPMCompliance);
368
+ name = ComplianceType_name(&compliance);
369
+ return rm_enum_new(Class_ComplianceType, ID2SYM(rb_intern(name)), INT2FIX(compliance));
370
+ }
371
+
372
+
373
+ /*
374
+ External: Import_TypeInfo
375
+ Purpose: Convert a TypeInfo structure to a Magick::Font
376
+ */
377
+ VALUE
378
+ Import_TypeInfo(const TypeInfo *ti)
379
+ {
380
+ volatile VALUE name, description, family;
381
+ volatile VALUE style, stretch, weight;
382
+ volatile VALUE encoding, foundry, format;
383
+
384
+ name = rb_str_new2(ti->name);
385
+ family = rb_str_new2(ti->family);
386
+ style = StyleType_new(ti->style);
387
+ stretch = StretchType_new(ti->stretch);
388
+ weight = ULONG2NUM(ti->weight);
389
+ description = ti->description ? rb_str_new2(ti->description) : Qnil;
390
+ encoding = ti->encoding ? rb_str_new2(ti->encoding) : Qnil;
391
+ foundry = ti->foundry ? rb_str_new2(ti->foundry) : Qnil;
392
+ format = ti->format ? rb_str_new2(ti->format) : Qnil;
393
+
394
+ return rb_funcall(Class_Font, rm_ID_new, 9
395
+ , name, description, family, style
396
+ , stretch, weight, encoding, foundry, format);
397
+ }
398
+
399
+
400
+ /*
401
+ External: Export_TypeInfo
402
+ Purpose: Convert a Magick::Font to a TypeInfo structure
403
+ */
404
+ void
405
+ Export_TypeInfo(TypeInfo *ti, VALUE st)
406
+ {
407
+ volatile VALUE members, m;
408
+
409
+ if (CLASS_OF(st) != Class_Font)
410
+ {
411
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
412
+ rb_class2name(CLASS_OF(st)));
413
+ }
414
+
415
+ memset(ti, '\0', sizeof(TypeInfo));
416
+
417
+ members = rb_funcall(st, rm_ID_values, 0);
418
+ m = rb_ary_entry(members, 0);
419
+ if (m != Qnil)
420
+ {
421
+ (void) CloneString((char **)&(ti->name), StringValuePtr(m));
422
+ }
423
+ m = rb_ary_entry(members, 1);
424
+ if (m != Qnil)
425
+ {
426
+ (void) CloneString((char **)&(ti->description), StringValuePtr(m));
427
+ }
428
+ m = rb_ary_entry(members, 2);
429
+ if (m != Qnil)
430
+ {
431
+ (void) CloneString((char **)&(ti->family), StringValuePtr(m));
432
+ }
433
+ m = rb_ary_entry(members, 3); ti->style = m == Qnil ? 0 : FIX2INT(m);
434
+ m = rb_ary_entry(members, 4); ti->stretch = m == Qnil ? 0 : FIX2INT(m);
435
+ m = rb_ary_entry(members, 5); ti->weight = m == Qnil ? 0 : FIX2INT(m);
436
+
437
+ m = rb_ary_entry(members, 6);
438
+ if (m != Qnil)
439
+ (void) CloneString((char **)&(ti->encoding), StringValuePtr(m));
440
+ m = rb_ary_entry(members, 7);
441
+ if (m != Qnil)
442
+ (void) CloneString((char **)&(ti->foundry), StringValuePtr(m));
443
+ m = rb_ary_entry(members, 8);
444
+ if (m != Qnil)
445
+ (void) CloneString((char **)&(ti->format), StringValuePtr(m));
446
+ }
447
+
448
+
449
+ /*
450
+ Static: destroy_TypeInfo
451
+ Purpose: free the storage allocated by Export_TypeInfo, above.
452
+ */
453
+ static void
454
+ destroy_TypeInfo(TypeInfo *ti)
455
+ {
456
+ magick_free((void*)ti->name);
457
+ ti->name = NULL;
458
+ magick_free((void*)ti->description);
459
+ ti->description = NULL;
460
+ magick_free((void*)ti->family);
461
+ ti->family = NULL;
462
+ magick_free((void*)ti->encoding);
463
+ ti->encoding = NULL;
464
+ magick_free((void*)ti->foundry);
465
+ ti->foundry = NULL;
466
+ magick_free((void*)ti->format);
467
+ ti->format = NULL;
468
+ }
469
+
470
+
471
+ /*
472
+ External: Font_to_s
473
+ Purpose: implement the Font#to_s method
474
+ */
475
+ VALUE
476
+ Font_to_s(VALUE self)
477
+ {
478
+ TypeInfo ti;
479
+ char weight[20];
480
+ char buff[1024];
481
+
482
+ Export_TypeInfo(&ti, self);
483
+
484
+ switch (ti.weight)
485
+ {
486
+ case 400:
487
+ strcpy(weight, "NormalWeight");
488
+ break;
489
+ case 700:
490
+ strcpy(weight, "BoldWeight");
491
+ break;
492
+ default:
493
+ sprintf(weight, "%lu", ti.weight);
494
+ break;
495
+ }
496
+
497
+ sprintf(buff, "name=%s, description=%s, "
498
+ "family=%s, style=%s, stretch=%s, weight=%s, "
499
+ "encoding=%s, foundry=%s, format=%s",
500
+ ti.name,
501
+ ti.description,
502
+ ti.family,
503
+ StyleType_name(ti.style),
504
+ StretchType_name(ti.stretch),
505
+ weight,
506
+ ti.encoding ? ti.encoding : "",
507
+ ti.foundry ? ti.foundry : "",
508
+ ti.format ? ti.format : "");
509
+
510
+ destroy_TypeInfo(&ti);
511
+ return rb_str_new2(buff);
512
+
513
+ }
514
+
515
+
516
+ /*
517
+ Extern: Import_PointInfo(pp)
518
+ Purpose: Create a Magick::Point object from a PointInfo structure.
519
+ */
520
+ VALUE
521
+ Import_PointInfo(PointInfo *p)
522
+ {
523
+ return rb_funcall(Class_Point, rm_ID_new, 2
524
+ , INT2FIX(p->x), INT2FIX(p->y));
525
+ }
526
+
527
+
528
+ /*
529
+ Extern: Export_PointInfo
530
+ Purpose: Convert a Magick::Point object to a PointInfo structure
531
+ */
532
+ void
533
+ Export_PointInfo(PointInfo *pi, VALUE sp)
534
+ {
535
+ volatile VALUE members, m;
536
+
537
+ if (CLASS_OF(sp) != Class_Point)
538
+ {
539
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
540
+ rb_class2name(CLASS_OF(sp)));
541
+ }
542
+ members = rb_funcall(sp, rm_ID_values, 0);
543
+ m = rb_ary_entry(members, 0);
544
+ pi->x = m == Qnil ? 0.0 : NUM2DBL(m);
545
+ m = rb_ary_entry(members, 1);
546
+ pi->y = m == Qnil ? 0.0 : NUM2DBL(m);
547
+ }
548
+
549
+
550
+ /*
551
+ Extern: Import_PrimaryInfo(pp)
552
+ Purpose: Create a Magick::PrimaryInfo object from a PrimaryInfo structure.
553
+ */
554
+ VALUE
555
+ Import_PrimaryInfo(PrimaryInfo *p)
556
+ {
557
+ return rb_funcall(Class_Primary, rm_ID_new, 3
558
+ , INT2FIX(p->x), INT2FIX(p->y), INT2FIX(p->z));
559
+ }
560
+
561
+
562
+ /*
563
+ Extern: Export_PrimaryInfo
564
+ Purpose: Convert a Magick::PrimaryInfo object to a PrimaryInfo structure
565
+ */
566
+ void
567
+ Export_PrimaryInfo(PrimaryInfo *pi, VALUE sp)
568
+ {
569
+ volatile VALUE members, m;
570
+
571
+ if (CLASS_OF(sp) != Class_Primary)
572
+ {
573
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
574
+ rb_class2name(CLASS_OF(sp)));
575
+ }
576
+ members = rb_funcall(sp, rm_ID_values, 0);
577
+ m = rb_ary_entry(members, 0);
578
+ pi->x = m == Qnil ? 0.0 : NUM2DBL(m);
579
+ m = rb_ary_entry(members, 1);
580
+ pi->y = m == Qnil ? 0.0 : NUM2DBL(m);
581
+ m = rb_ary_entry(members, 2);
582
+ pi->z = m == Qnil ? 0.0 : NUM2DBL(m);
583
+ }
584
+
585
+
586
+ /*
587
+ Method: Magick::PrimaryInfo#to_s
588
+ Purpose: Create a string representation of a Magick::PrimaryInfo
589
+ */
590
+ VALUE
591
+ PrimaryInfo_to_s(VALUE self)
592
+ {
593
+ PrimaryInfo pi;
594
+ char buff[100];
595
+
596
+ Export_PrimaryInfo(&pi, self);
597
+ sprintf(buff, "x=%g, y=%g, z=%g", pi.x, pi.y, pi.z);
598
+ return rb_str_new2(buff);
599
+ }
600
+
601
+
602
+ /*
603
+ External: Import_RectangleInfo
604
+ Purpose: Convert a RectangleInfo structure to a Magick::Rectangle
605
+ */
606
+ VALUE
607
+ Import_RectangleInfo(RectangleInfo *rect)
608
+ {
609
+ volatile VALUE width;
610
+ volatile VALUE height;
611
+ volatile VALUE x, y;
612
+
613
+ width = UINT2NUM(rect->width);
614
+ height = UINT2NUM(rect->height);
615
+ x = INT2NUM(rect->x);
616
+ y = INT2NUM(rect->y);
617
+ return rb_funcall(Class_Rectangle, rm_ID_new, 4
618
+ , width, height, x, y);
619
+ }
620
+
621
+
622
+ /*
623
+ External: Export_RectangleInfo
624
+ Purpose: Convert a Magick::Rectangle to a RectangleInfo structure.
625
+ */
626
+ void
627
+ Export_RectangleInfo(RectangleInfo *rect, VALUE sr)
628
+ {
629
+ volatile VALUE members, m;
630
+
631
+ if (CLASS_OF(sr) != Class_Rectangle)
632
+ {
633
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
634
+ rb_class2name(CLASS_OF(sr)));
635
+ }
636
+ members = rb_funcall(sr, rm_ID_values, 0);
637
+ m = rb_ary_entry(members, 0);
638
+ rect->width = m == Qnil ? 0 : NUM2ULONG(m);
639
+ m = rb_ary_entry(members, 1);
640
+ rect->height = m == Qnil ? 0 : NUM2ULONG(m);
641
+ m = rb_ary_entry(members, 2);
642
+ rect->x = m == Qnil ? 0 : NUM2LONG (m);
643
+ m = rb_ary_entry(members, 3);
644
+ rect->y = m == Qnil ? 0 : NUM2LONG (m);
645
+ }
646
+
647
+
648
+ /*
649
+ Method: Magick::Rectangle#to_s
650
+ Purpose: Create a string representation of a Magick::Rectangle
651
+ */
652
+ VALUE
653
+ RectangleInfo_to_s(VALUE self)
654
+ {
655
+ RectangleInfo rect;
656
+ char buff[100];
657
+
658
+ Export_RectangleInfo(&rect, self);
659
+ sprintf(buff, "width=%lu, height=%lu, x=%ld, y=%ld"
660
+ , rect.width, rect.height, rect.x, rect.y);
661
+ return rb_str_new2(buff);
662
+ }
663
+
664
+
665
+ /*
666
+ External: Import_SegmentInfo
667
+ Purpose: Convert a SegmentInfo structure to a Magick::Segment
668
+ */
669
+ VALUE
670
+ Import_SegmentInfo(SegmentInfo *segment)
671
+ {
672
+ volatile VALUE x1, y1, x2, y2;
673
+
674
+ x1 = rb_float_new(segment->x1);
675
+ y1 = rb_float_new(segment->y1);
676
+ x2 = rb_float_new(segment->x2);
677
+ y2 = rb_float_new(segment->y2);
678
+ return rb_funcall(Class_Segment, rm_ID_new, 4, x1, y1, x2, y2);
679
+ }
680
+
681
+
682
+ /*
683
+ External: Export_SegmentInfo
684
+ Purpose: Convert a Magick::Segment to a SegmentInfo structure.
685
+ */
686
+ void
687
+ Export_SegmentInfo(SegmentInfo *segment, VALUE s)
688
+ {
689
+ volatile VALUE members, m;
690
+
691
+ if (CLASS_OF(s) != Class_Segment)
692
+ {
693
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
694
+ rb_class2name(CLASS_OF(s)));
695
+ }
696
+
697
+ members = rb_funcall(s, rm_ID_values, 0);
698
+ m = rb_ary_entry(members, 0);
699
+ segment->x1 = m == Qnil ? 0.0 : NUM2DBL(m);
700
+ m = rb_ary_entry(members, 1);
701
+ segment->y1 = m == Qnil ? 0.0 : NUM2DBL(m);
702
+ m = rb_ary_entry(members, 2);
703
+ segment->x2 = m == Qnil ? 0.0 : NUM2DBL(m);
704
+ m = rb_ary_entry(members, 3);
705
+ segment->y2 = m == Qnil ? 0.0 : NUM2DBL(m);
706
+ }
707
+
708
+
709
+ /*
710
+ Method: Magick::SegmentInfo#to_s
711
+ Purpose: Create a string representation of a Magick::Segment
712
+ */
713
+ VALUE
714
+ SegmentInfo_to_s(VALUE self)
715
+ {
716
+ SegmentInfo segment;
717
+ char buff[100];
718
+
719
+ Export_SegmentInfo(&segment, self);
720
+ sprintf(buff, "x1=%g, y1=%g, x2=%g, y2=%g"
721
+ , segment.x1, segment.y1, segment.x2, segment.y2);
722
+ return rb_str_new2(buff);
723
+ }
724
+
725
+
726
+ /*
727
+ Static: StretchType_name
728
+ Purpose: Return the string representation of a StretchType value
729
+ */
730
+ static const char *
731
+ StretchType_name(StretchType stretch)
732
+ {
733
+ switch (stretch)
734
+ {
735
+ ENUM_TO_NAME(UndefinedStretch)
736
+ ENUM_TO_NAME(NormalStretch)
737
+ ENUM_TO_NAME(UltraCondensedStretch)
738
+ ENUM_TO_NAME(ExtraCondensedStretch)
739
+ ENUM_TO_NAME(CondensedStretch)
740
+ ENUM_TO_NAME(SemiCondensedStretch)
741
+ ENUM_TO_NAME(SemiExpandedStretch)
742
+ ENUM_TO_NAME(ExpandedStretch)
743
+ ENUM_TO_NAME(ExtraExpandedStretch)
744
+ ENUM_TO_NAME(UltraExpandedStretch)
745
+ ENUM_TO_NAME(AnyStretch)
746
+ }
747
+
748
+ return "UndefinedStretch";
749
+ }
750
+
751
+
752
+ /*
753
+ Static: StretchType_new
754
+ Purpose: Construct a StretchType enum for a specified StretchType value
755
+ */
756
+ static VALUE
757
+ StretchType_new(StretchType stretch)
758
+ {
759
+ const char *name = StretchType_name(stretch);
760
+ return rm_enum_new(Class_StretchType, ID2SYM(rb_intern(name)), INT2FIX(stretch));
761
+ }
762
+
763
+
764
+ /*
765
+ Static: StyleType_name
766
+ Purpose: Return the string representation of a StyleType value
767
+ */
768
+ static const char *
769
+ StyleType_name(StyleType style)
770
+ {
771
+ switch (style)
772
+ {
773
+ ENUM_TO_NAME(UndefinedStyle)
774
+ ENUM_TO_NAME(NormalStyle)
775
+ ENUM_TO_NAME(ItalicStyle)
776
+ ENUM_TO_NAME(ObliqueStyle)
777
+ ENUM_TO_NAME(AnyStyle)
778
+ }
779
+
780
+ return "UndefinedStyle";
781
+ }
782
+
783
+
784
+ /*
785
+ Static: StyleType_new
786
+ Purpose: Construct a StyleType enum for a specified StyleType value
787
+ */
788
+ static VALUE
789
+ StyleType_new(StyleType style)
790
+ {
791
+ const char *name = StyleType_name(style);
792
+ return rm_enum_new(Class_StyleType, ID2SYM(rb_intern(name)), INT2FIX(style));
793
+ }
794
+
795
+
796
+ /*
797
+ External: Import_TypeMetric
798
+ Purpose: Convert a TypeMetric structure to a Magick::TypeMetric
799
+ */
800
+ VALUE
801
+ Import_TypeMetric(TypeMetric *tm)
802
+ {
803
+ volatile VALUE pixels_per_em;
804
+ volatile VALUE ascent, descent;
805
+ volatile VALUE width, height, max_advance;
806
+ volatile VALUE bounds, underline_position, underline_thickness;
807
+
808
+ pixels_per_em = Import_PointInfo(&tm->pixels_per_em);
809
+ ascent = rb_float_new(tm->ascent);
810
+ descent = rb_float_new(tm->descent);
811
+ width = rb_float_new(tm->width);
812
+ height = rb_float_new(tm->height);
813
+ max_advance = rb_float_new(tm->max_advance);
814
+ bounds = Import_SegmentInfo(&tm->bounds);
815
+ underline_position = rb_float_new(tm->underline_position);
816
+ underline_thickness = rb_float_new(tm->underline_position);
817
+
818
+ return rb_funcall(Class_TypeMetric, rm_ID_new, 9
819
+ , pixels_per_em, ascent, descent, width
820
+ , height, max_advance, bounds
821
+ , underline_position, underline_thickness);
822
+ }
823
+
824
+
825
+ /*
826
+ External: Export_TypeMetric
827
+ Purpose: Convert a Magick::TypeMetric to a TypeMetric structure.
828
+ */
829
+ void
830
+ Export_TypeMetric(TypeMetric *tm, VALUE st)
831
+ {
832
+ volatile VALUE members, m;
833
+ volatile VALUE pixels_per_em;
834
+
835
+ if (CLASS_OF(st) != Class_TypeMetric)
836
+ {
837
+ rb_raise(rb_eTypeError, "type mismatch: %s given",
838
+ rb_class2name(CLASS_OF(st)));
839
+ }
840
+ members = rb_funcall(st, rm_ID_values, 0);
841
+
842
+ pixels_per_em = rb_ary_entry(members, 0);
843
+ Export_PointInfo(&tm->pixels_per_em, pixels_per_em);
844
+
845
+ m = rb_ary_entry(members, 1);
846
+ tm->ascent = m == Qnil ? 0.0 : NUM2DBL(m);
847
+ m = rb_ary_entry(members, 2);
848
+ tm->descent = m == Qnil ? 0.0 : NUM2DBL(m);
849
+ m = rb_ary_entry(members, 3);
850
+ tm->width = m == Qnil ? 0.0 : NUM2DBL(m);
851
+ m = rb_ary_entry(members, 4);
852
+ tm->height = m == Qnil ? 0.0 : NUM2DBL(m);
853
+ m = rb_ary_entry(members, 5);
854
+ tm->max_advance = m == Qnil ? 0.0 : NUM2DBL(m);
855
+
856
+ m = rb_ary_entry(members, 6);
857
+ Export_SegmentInfo(&tm->bounds, m);
858
+
859
+ m = rb_ary_entry(members, 7);
860
+ tm->underline_position = m == Qnil ? 0.0 : NUM2DBL(m);
861
+ m = rb_ary_entry(members, 8);
862
+ tm->underline_thickness = m == Qnil ? 0.0 : NUM2DBL(m);
863
+ }
864
+
865
+
866
+ /*
867
+ Method: Magick::TypeMetric#to_s
868
+ Purpose: Create a string representation of a Magick::TypeMetric
869
+ */
870
+ VALUE
871
+ TypeMetric_to_s(VALUE self)
872
+ {
873
+ TypeMetric tm;
874
+ char buff[200];
875
+
876
+ Export_TypeMetric(&tm, self);
877
+ sprintf(buff, "pixels_per_em=(x=%g,y=%g) "
878
+ "ascent=%g descent=%g width=%g height=%g max_advance=%g "
879
+ "bounds.x1=%g bounds.y1=%g bounds.x2=%g bounds.y2=%g "
880
+ "underline_position=%g underline_thickness=%g",
881
+ tm.pixels_per_em.x, tm.pixels_per_em.y,
882
+ tm.ascent, tm.descent, tm.width, tm.height, tm.max_advance,
883
+ tm.bounds.x1, tm.bounds.y1, tm.bounds.x2, tm.bounds.y2,
884
+ tm.underline_position, tm.underline_thickness);
885
+ return rb_str_new2(buff);
886
+ }
887
+