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.
- data/ChangeLog +10 -2
- data/README.html +7 -7
- data/doc/comtasks.html +2 -2
- data/doc/constants.html +5 -5
- data/doc/draw.html +131 -20
- data/doc/ex/InitialCoords.rb +1 -1
- data/doc/ex/NewCoordSys.rb +2 -2
- data/doc/ex/OrigCoordSys.rb +1 -1
- data/doc/ex/RotateScale.rb +2 -2
- data/doc/ex/Skew.rb +2 -2
- data/doc/ex/ViewBox.rb +1 -1
- data/doc/ex/arc.rb +4 -2
- data/doc/ex/arcs02.rb +1 -1
- data/doc/ex/bounding_box.rb +3 -0
- data/doc/ex/cbezier1.rb +2 -0
- data/doc/ex/cbezier2.rb +2 -0
- data/doc/ex/cbezier3.rb +2 -0
- data/doc/ex/cbezier4.rb +2 -0
- data/doc/ex/cbezier5.rb +2 -0
- data/doc/ex/cbezier6.rb +2 -0
- data/doc/ex/channel.rb +1 -0
- data/doc/ex/circle.rb +2 -0
- data/doc/ex/cubic01.rb +1 -1
- data/doc/ex/cubic02.rb +1 -1
- data/doc/ex/ellipse.rb +2 -0
- data/doc/ex/font_styles.rb +12 -10
- data/doc/ex/get_type_metrics.rb +2 -0
- data/doc/ex/grav.rb +2 -0
- data/doc/ex/image.rb +1 -1
- data/doc/ex/line.rb +2 -0
- data/doc/ex/opacity.rb +6 -4
- data/doc/ex/path.rb +2 -0
- data/doc/ex/polaroid.rb +2 -0
- data/doc/ex/qbezierpath.rb +3 -0
- data/doc/ex/rectangle.rb +2 -0
- data/doc/ex/rotate.rb +2 -0
- data/doc/ex/roundrect.rb +2 -0
- data/doc/ex/skewx.rb +2 -0
- data/doc/ex/skewy.rb +2 -0
- data/doc/ex/stroke_dasharray.rb +2 -0
- data/doc/ex/stroke_width.rb +2 -0
- data/doc/ex/text.rb +3 -2
- data/doc/ex/text01.rb +1 -1
- data/doc/ex/text_styles.rb +1 -1
- data/doc/ex/text_undercolor.rb +2 -0
- data/doc/ex/translate.rb +3 -1
- data/doc/ilist.html +2 -2
- data/doc/image1.html +2 -2
- data/doc/image2.html +2 -2
- data/doc/image3.html +37 -6
- data/doc/imageattrs.html +2 -2
- data/doc/imusage.html +3 -3
- data/doc/index.html +3 -3
- data/doc/info.html +2 -2
- data/doc/magick.html +2 -2
- data/doc/optequiv.html +24 -2
- data/doc/rvg.html +2 -2
- data/doc/rvgclip.html +2 -2
- data/doc/rvggroup.html +2 -2
- data/doc/rvgimage.html +2 -2
- data/doc/rvgpattern.html +2 -2
- data/doc/rvgshape.html +2 -2
- data/doc/rvgstyle.html +2 -2
- data/doc/rvgtext.html +2 -2
- data/doc/rvgtspan.html +2 -2
- data/doc/rvgtut.html +2 -2
- data/doc/rvguse.html +2 -2
- data/doc/rvgxform.html +2 -2
- data/doc/struct.html +2 -2
- data/doc/usage.html +6 -4
- data/ext/RMagick/MANIFEST +6 -1
- data/ext/RMagick/extconf.rb +18 -2
- data/ext/RMagick/rmagick.c +312 -0
- data/ext/RMagick/rmagick.h +137 -61
- data/ext/RMagick/rmdraw.c +271 -377
- data/ext/RMagick/rmenum.c +1016 -0
- data/ext/RMagick/rmimage.c +172 -16
- data/ext/RMagick/rminfo.c +5 -5
- data/ext/RMagick/rmmain.c +50 -303
- data/ext/RMagick/rmmontage.c +386 -0
- data/ext/RMagick/rmpixel.c +816 -0
- data/ext/RMagick/rmstruct.c +887 -0
- data/ext/RMagick/rmutil.c +25 -2634
- data/lib/RMagick.rb +46 -2
- data/lib/rvg/misc.rb +5 -4
- data/lib/rvg/stylable.rb +7 -1
- data/rmagick.gemspec +1 -1
- 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
|
+
|