rmagick 7.1.7 → 7.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +40 -0
- data/README.md +11 -0
- data/Rakefile +1 -0
- data/ext/RMagick/extconf.rb +3 -2
- data/ext/RMagick/rmagick.h +12 -7
- data/ext/RMagick/rmagick_gvl.cpp +1216 -0
- data/ext/RMagick/rmagick_gvl.h +4 -2
- data/ext/RMagick/rmagick_gvl.hpp +100 -0
- data/ext/RMagick/rmdraw.cpp +101 -70
- data/ext/RMagick/rmfill.cpp +17 -17
- data/ext/RMagick/rmilist.cpp +139 -85
- data/ext/RMagick/rmimage.cpp +1354 -979
- data/ext/RMagick/rminfo.cpp +58 -39
- data/ext/RMagick/rmkinfo.cpp +28 -9
- data/ext/RMagick/rmmain.cpp +2 -0
- data/ext/RMagick/rmmontage.cpp +38 -18
- data/ext/RMagick/rmpixel.cpp +7 -4
- data/ext/RMagick/rmutil.cpp +60 -12
- data/lib/rmagick/version.rb +1 -1
- data/lib/rmagick_internal.rb +15 -4
- data/lib/rvg/rvg.rb +1 -1
- metadata +3 -1
data/ext/RMagick/rmagick_gvl.h
CHANGED
|
@@ -2,13 +2,15 @@
|
|
|
2
2
|
#define _RMAGICK_GVL_H_
|
|
3
3
|
|
|
4
4
|
#include "ruby/thread.h"
|
|
5
|
+
#include "ruby/fiber/scheduler.h"
|
|
5
6
|
|
|
6
7
|
typedef void *(gvl_function_t)(void *);
|
|
7
8
|
|
|
8
9
|
#define GVL_FUNC(name) name##_gvl
|
|
9
10
|
#define GVL_STRUCT_TYPE(name) name##_args_t
|
|
10
|
-
#
|
|
11
|
-
|
|
11
|
+
#if defined(RB_NOGVL_OFFLOAD_SAFE) && defined(HAVE_RB_FIBER_SCHEDULER_BLOCKING_OPERATION_EXTRACT)
|
|
12
|
+
#define RMAGICK_OFFLOAD_SAFE 1
|
|
13
|
+
#endif
|
|
12
14
|
|
|
13
15
|
|
|
14
16
|
#define DEFINE_GVL_STRUCT1(name, type1) \
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#ifndef _RMAGICK_GVL_HPP_
|
|
2
|
+
#define _RMAGICK_GVL_HPP_
|
|
3
|
+
|
|
4
|
+
extern void rm_gvl_init(void);
|
|
5
|
+
extern void rm_gvl_check_readable(const void *);
|
|
6
|
+
extern void rm_gvl_check_writable(const void *);
|
|
7
|
+
extern bool rm_gvl_in_use(const void *);
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A call to an ImageMagick function without the GVL, which a Fiber scheduler
|
|
11
|
+
* with a worker pool may run on a worker thread. Register the Ruby objects the
|
|
12
|
+
* call uses and what the caller releases after it, then call run().
|
|
13
|
+
*/
|
|
14
|
+
class rm_gvl_call
|
|
15
|
+
{
|
|
16
|
+
public:
|
|
17
|
+
rm_gvl_call(gvl_function_t *fp, void *args);
|
|
18
|
+
|
|
19
|
+
rm_gvl_call &read(VALUE obj);
|
|
20
|
+
rm_gvl_call &read(const void *ptr);
|
|
21
|
+
rm_gvl_call &update(VALUE obj);
|
|
22
|
+
rm_gvl_call &update(const void *ptr);
|
|
23
|
+
rm_gvl_call &read_each(VALUE ary);
|
|
24
|
+
rm_gvl_call &update_each(VALUE ary);
|
|
25
|
+
rm_gvl_call &release(ExceptionInfo *exception);
|
|
26
|
+
rm_gvl_call &release(ImageInfo *info);
|
|
27
|
+
rm_gvl_call &release(DrawInfo *draw_info);
|
|
28
|
+
rm_gvl_call &release(KernelInfo *kernel);
|
|
29
|
+
rm_gvl_call &destroy(Image *image);
|
|
30
|
+
rm_gvl_call &split(Image *images);
|
|
31
|
+
#if defined(IMAGEMAGICK_7)
|
|
32
|
+
rm_gvl_call &restore_mask(Image *image, ChannelType channel_mask);
|
|
33
|
+
#endif
|
|
34
|
+
rm_gvl_call &free_buffer(void *buffer);
|
|
35
|
+
rm_gvl_call &relinquish(void *memory);
|
|
36
|
+
rm_gvl_call &free_result();
|
|
37
|
+
rm_gvl_call &keep_thread(bool keep = true);
|
|
38
|
+
rm_gvl_call &cleanup(void (*release)(void *, intptr_t), void *ptr, intptr_t arg = 0);
|
|
39
|
+
rm_gvl_call &restore(void (*release)(void *, intptr_t), void *ptr, intptr_t arg = 0, size_t size = 0);
|
|
40
|
+
|
|
41
|
+
template <typename T> T run();
|
|
42
|
+
|
|
43
|
+
private:
|
|
44
|
+
enum ResultType { ResultIgnored, ResultImage, ResultMemory };
|
|
45
|
+
enum { MaxObjects = 4, MaxCleanups = 4 };
|
|
46
|
+
|
|
47
|
+
typedef struct
|
|
48
|
+
{
|
|
49
|
+
VALUE obj;
|
|
50
|
+
const void *ptr;
|
|
51
|
+
bool update;
|
|
52
|
+
bool each;
|
|
53
|
+
} object_t;
|
|
54
|
+
|
|
55
|
+
typedef struct
|
|
56
|
+
{
|
|
57
|
+
void (*release)(void *, intptr_t);
|
|
58
|
+
void *ptr;
|
|
59
|
+
intptr_t arg;
|
|
60
|
+
size_t size;
|
|
61
|
+
bool restore;
|
|
62
|
+
} cleanup_t;
|
|
63
|
+
|
|
64
|
+
gvl_function_t *fp;
|
|
65
|
+
void *args;
|
|
66
|
+
object_t objects[MaxObjects];
|
|
67
|
+
int nobjects;
|
|
68
|
+
cleanup_t cleanups[MaxCleanups];
|
|
69
|
+
int ncleanups;
|
|
70
|
+
ResultType result_type;
|
|
71
|
+
bool keep;
|
|
72
|
+
|
|
73
|
+
rm_gvl_call &add_object(VALUE obj, const void *ptr, bool update, bool each);
|
|
74
|
+
rm_gvl_call &add_cleanup(void (*release)(void *, intptr_t), void *ptr, intptr_t arg, size_t size, bool restore);
|
|
75
|
+
void *call(ResultType type);
|
|
76
|
+
void *call_here(ResultType type);
|
|
77
|
+
void unwind(ResultType type, void *result, bool abandoned = false);
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
template <typename T>
|
|
81
|
+
T
|
|
82
|
+
rm_gvl_call::run()
|
|
83
|
+
{
|
|
84
|
+
return (T)(uintptr_t)call(result_type);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
template <> Image *rm_gvl_call::run<Image *>();
|
|
88
|
+
template <> void rm_gvl_call::run<void>();
|
|
89
|
+
|
|
90
|
+
//! declare the arguments of the GVL stub of name and an rm_gvl_call named var that calls it
|
|
91
|
+
#define DECLARE_GVL_CALL(var, name, ...) \
|
|
92
|
+
GVL_STRUCT_TYPE(name) var##_args = { __VA_ARGS__ }; \
|
|
93
|
+
rm_gvl_call var(GVL_FUNC(name), &var##_args)
|
|
94
|
+
|
|
95
|
+
//! declare the arguments of type and an rm_gvl_call named var that calls fp with them
|
|
96
|
+
#define DECLARE_GVL_CALL_FP(var, type, fp, ...) \
|
|
97
|
+
GVL_STRUCT_TYPE(type) var##_args = { __VA_ARGS__ }; \
|
|
98
|
+
rm_gvl_call var(fp, &var##_args)
|
|
99
|
+
|
|
100
|
+
#endif
|
data/ext/RMagick/rmdraw.cpp
CHANGED
|
@@ -74,6 +74,28 @@ get_draw(VALUE self)
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Get the Draw struct of a Draw object for a method that changes it.
|
|
79
|
+
*
|
|
80
|
+
* No Ruby usage (internal function)
|
|
81
|
+
*
|
|
82
|
+
* @param self the Draw object
|
|
83
|
+
* @return the initialized Draw struct
|
|
84
|
+
* @throw FrozenError if the Draw object is frozen
|
|
85
|
+
* @throw RuntimeError if an offloaded call is using the Draw object
|
|
86
|
+
*/
|
|
87
|
+
static Draw *
|
|
88
|
+
get_writable_draw(VALUE self)
|
|
89
|
+
{
|
|
90
|
+
Draw *draw;
|
|
91
|
+
|
|
92
|
+
rb_check_frozen(self);
|
|
93
|
+
draw = get_draw(self);
|
|
94
|
+
rm_gvl_check_writable(draw);
|
|
95
|
+
return draw;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
77
99
|
/**
|
|
78
100
|
* Set the affine matrix from an {Magick::AffineMatrix}.
|
|
79
101
|
*
|
|
@@ -85,8 +107,7 @@ Draw_affine_eq(VALUE self, VALUE matrix)
|
|
|
85
107
|
{
|
|
86
108
|
Draw *draw;
|
|
87
109
|
|
|
88
|
-
|
|
89
|
-
draw = get_draw(self);
|
|
110
|
+
draw = get_writable_draw(self);
|
|
90
111
|
Export_AffineMatrix(&draw->info->affine, matrix);
|
|
91
112
|
return matrix;
|
|
92
113
|
}
|
|
@@ -103,8 +124,7 @@ Draw_align_eq(VALUE self, VALUE align)
|
|
|
103
124
|
{
|
|
104
125
|
Draw *draw;
|
|
105
126
|
|
|
106
|
-
|
|
107
|
-
draw = get_draw(self);
|
|
127
|
+
draw = get_writable_draw(self);
|
|
108
128
|
VALUE_TO_ENUM(align, draw->info->align, AlignType);
|
|
109
129
|
return align;
|
|
110
130
|
}
|
|
@@ -121,8 +141,7 @@ Draw_decorate_eq(VALUE self, VALUE decorate)
|
|
|
121
141
|
{
|
|
122
142
|
Draw *draw;
|
|
123
143
|
|
|
124
|
-
|
|
125
|
-
draw = get_draw(self);
|
|
144
|
+
draw = get_writable_draw(self);
|
|
126
145
|
VALUE_TO_ENUM(decorate, draw->info->decorate, DecorationType);
|
|
127
146
|
return decorate;
|
|
128
147
|
}
|
|
@@ -139,8 +158,7 @@ Draw_density_eq(VALUE self, VALUE density)
|
|
|
139
158
|
{
|
|
140
159
|
Draw *draw;
|
|
141
160
|
|
|
142
|
-
|
|
143
|
-
draw = get_draw(self);
|
|
161
|
+
draw = get_writable_draw(self);
|
|
144
162
|
magick_clone_string(&draw->info->density, StringValueCStr(density));
|
|
145
163
|
|
|
146
164
|
return density;
|
|
@@ -158,8 +176,7 @@ Draw_encoding_eq(VALUE self, VALUE encoding)
|
|
|
158
176
|
{
|
|
159
177
|
Draw *draw;
|
|
160
178
|
|
|
161
|
-
|
|
162
|
-
draw = get_draw(self);
|
|
179
|
+
draw = get_writable_draw(self);
|
|
163
180
|
magick_clone_string(&draw->info->encoding, StringValueCStr(encoding));
|
|
164
181
|
|
|
165
182
|
return encoding;
|
|
@@ -177,8 +194,7 @@ Draw_fill_eq(VALUE self, VALUE fill)
|
|
|
177
194
|
{
|
|
178
195
|
Draw *draw;
|
|
179
196
|
|
|
180
|
-
|
|
181
|
-
draw = get_draw(self);
|
|
197
|
+
draw = get_writable_draw(self);
|
|
182
198
|
Color_to_PixelColor(&draw->info->fill, fill);
|
|
183
199
|
return fill;
|
|
184
200
|
}
|
|
@@ -198,8 +214,7 @@ Draw_fill_pattern_eq(VALUE self, VALUE pattern)
|
|
|
198
214
|
{
|
|
199
215
|
Draw *draw;
|
|
200
216
|
|
|
201
|
-
|
|
202
|
-
draw = get_draw(self);
|
|
217
|
+
draw = get_writable_draw(self);
|
|
203
218
|
|
|
204
219
|
if (draw->info->fill_pattern != NULL)
|
|
205
220
|
{
|
|
@@ -213,7 +228,7 @@ Draw_fill_pattern_eq(VALUE self, VALUE pattern)
|
|
|
213
228
|
Image *image;
|
|
214
229
|
|
|
215
230
|
pattern = rm_cur_image(pattern);
|
|
216
|
-
image =
|
|
231
|
+
image = rm_check_readable(pattern);
|
|
217
232
|
// Do not trace creation
|
|
218
233
|
draw->info->fill_pattern = rm_clone_image(image);
|
|
219
234
|
}
|
|
@@ -233,8 +248,7 @@ Draw_font_eq(VALUE self, VALUE font)
|
|
|
233
248
|
{
|
|
234
249
|
Draw *draw;
|
|
235
250
|
|
|
236
|
-
|
|
237
|
-
draw = get_draw(self);
|
|
251
|
+
draw = get_writable_draw(self);
|
|
238
252
|
magick_clone_string(&draw->info->font, StringValueCStr(font));
|
|
239
253
|
|
|
240
254
|
return font;
|
|
@@ -252,8 +266,7 @@ Draw_font_family_eq(VALUE self, VALUE family)
|
|
|
252
266
|
{
|
|
253
267
|
Draw *draw;
|
|
254
268
|
|
|
255
|
-
|
|
256
|
-
draw = get_draw(self);
|
|
269
|
+
draw = get_writable_draw(self);
|
|
257
270
|
magick_clone_string(&draw->info->family, StringValueCStr(family));
|
|
258
271
|
|
|
259
272
|
return family;
|
|
@@ -271,8 +284,7 @@ Draw_font_stretch_eq(VALUE self, VALUE stretch)
|
|
|
271
284
|
{
|
|
272
285
|
Draw *draw;
|
|
273
286
|
|
|
274
|
-
|
|
275
|
-
draw = get_draw(self);
|
|
287
|
+
draw = get_writable_draw(self);
|
|
276
288
|
VALUE_TO_ENUM(stretch, draw->info->stretch, StretchType);
|
|
277
289
|
return stretch;
|
|
278
290
|
}
|
|
@@ -289,8 +301,7 @@ Draw_font_style_eq(VALUE self, VALUE style)
|
|
|
289
301
|
{
|
|
290
302
|
Draw *draw;
|
|
291
303
|
|
|
292
|
-
|
|
293
|
-
draw = get_draw(self);
|
|
304
|
+
draw = get_writable_draw(self);
|
|
294
305
|
VALUE_TO_ENUM(style, draw->info->style, StyleType);
|
|
295
306
|
return style;
|
|
296
307
|
}
|
|
@@ -309,8 +320,7 @@ Draw_font_weight_eq(VALUE self, VALUE weight)
|
|
|
309
320
|
Draw *draw;
|
|
310
321
|
size_t w;
|
|
311
322
|
|
|
312
|
-
|
|
313
|
-
draw = get_draw(self);
|
|
323
|
+
draw = get_writable_draw(self);
|
|
314
324
|
|
|
315
325
|
if (FIXNUM_P(weight))
|
|
316
326
|
{
|
|
@@ -375,8 +385,7 @@ Draw_gravity_eq(VALUE self, VALUE grav)
|
|
|
375
385
|
{
|
|
376
386
|
Draw *draw;
|
|
377
387
|
|
|
378
|
-
|
|
379
|
-
draw = get_draw(self);
|
|
388
|
+
draw = get_writable_draw(self);
|
|
380
389
|
VALUE_TO_ENUM(grav, draw->info->gravity, GravityType);
|
|
381
390
|
|
|
382
391
|
return grav;
|
|
@@ -394,8 +403,7 @@ Draw_kerning_eq(VALUE self, VALUE kerning)
|
|
|
394
403
|
{
|
|
395
404
|
Draw *draw;
|
|
396
405
|
|
|
397
|
-
|
|
398
|
-
draw = get_draw(self);
|
|
406
|
+
draw = get_writable_draw(self);
|
|
399
407
|
draw->info->kerning = NUM2DBL(kerning);
|
|
400
408
|
return kerning;
|
|
401
409
|
}
|
|
@@ -412,8 +420,7 @@ Draw_interline_spacing_eq(VALUE self, VALUE spacing)
|
|
|
412
420
|
{
|
|
413
421
|
Draw *draw;
|
|
414
422
|
|
|
415
|
-
|
|
416
|
-
draw = get_draw(self);
|
|
423
|
+
draw = get_writable_draw(self);
|
|
417
424
|
draw->info->interline_spacing = NUM2DBL(spacing);
|
|
418
425
|
return spacing;
|
|
419
426
|
}
|
|
@@ -430,8 +437,7 @@ Draw_interword_spacing_eq(VALUE self, VALUE spacing)
|
|
|
430
437
|
{
|
|
431
438
|
Draw *draw;
|
|
432
439
|
|
|
433
|
-
|
|
434
|
-
draw = get_draw(self);
|
|
440
|
+
draw = get_writable_draw(self);
|
|
435
441
|
draw->info->interword_spacing = NUM2DBL(spacing);
|
|
436
442
|
return spacing;
|
|
437
443
|
}
|
|
@@ -463,8 +469,8 @@ image_to_str(Image *image)
|
|
|
463
469
|
|
|
464
470
|
info = CloneImageInfo(NULL);
|
|
465
471
|
exception = AcquireExceptionInfo();
|
|
466
|
-
|
|
467
|
-
blob = (unsigned char
|
|
472
|
+
DECLARE_GVL_CALL(call, ImageToBlob, info, image, &length, exception);
|
|
473
|
+
blob = call.keep_thread().run<unsigned char *>();
|
|
468
474
|
DestroyImageInfo(info);
|
|
469
475
|
CHECK_EXCEPTION();
|
|
470
476
|
DestroyExceptionInfo(exception);
|
|
@@ -504,8 +510,8 @@ Image *str_to_image(VALUE str)
|
|
|
504
510
|
|
|
505
511
|
info = CloneImageInfo(NULL);
|
|
506
512
|
exception = AcquireExceptionInfo();
|
|
507
|
-
|
|
508
|
-
image = (Image
|
|
513
|
+
DECLARE_GVL_CALL(call, BlobToImage, info, RSTRING_PTR(str), (size_t)RSTRING_LEN(str), exception);
|
|
514
|
+
image = call.keep_thread().run<Image *>();
|
|
509
515
|
DestroyImageInfo(info);
|
|
510
516
|
CHECK_EXCEPTION();
|
|
511
517
|
DestroyExceptionInfo(exception);
|
|
@@ -668,8 +674,7 @@ Draw_pointsize_eq(VALUE self, VALUE pointsize)
|
|
|
668
674
|
{
|
|
669
675
|
Draw *draw;
|
|
670
676
|
|
|
671
|
-
|
|
672
|
-
draw = get_draw(self);
|
|
677
|
+
draw = get_writable_draw(self);
|
|
673
678
|
draw->info->pointsize = NUM2DBL(pointsize);
|
|
674
679
|
return pointsize;
|
|
675
680
|
}
|
|
@@ -688,8 +693,7 @@ Draw_rotation_eq(VALUE self, VALUE deg)
|
|
|
688
693
|
double degrees;
|
|
689
694
|
AffineMatrix affine, current;
|
|
690
695
|
|
|
691
|
-
|
|
692
|
-
draw = get_draw(self);
|
|
696
|
+
draw = get_writable_draw(self);
|
|
693
697
|
|
|
694
698
|
degrees = NUM2DBL(deg);
|
|
695
699
|
if (fabs(degrees) > DBL_EPSILON)
|
|
@@ -724,8 +728,7 @@ Draw_stroke_eq(VALUE self, VALUE stroke)
|
|
|
724
728
|
{
|
|
725
729
|
Draw *draw;
|
|
726
730
|
|
|
727
|
-
|
|
728
|
-
draw = get_draw(self);
|
|
731
|
+
draw = get_writable_draw(self);
|
|
729
732
|
Color_to_PixelColor(&draw->info->stroke, stroke);
|
|
730
733
|
return stroke;
|
|
731
734
|
}
|
|
@@ -744,8 +747,7 @@ Draw_stroke_pattern_eq(VALUE self, VALUE pattern)
|
|
|
744
747
|
{
|
|
745
748
|
Draw *draw;
|
|
746
749
|
|
|
747
|
-
|
|
748
|
-
draw = get_draw(self);
|
|
750
|
+
draw = get_writable_draw(self);
|
|
749
751
|
|
|
750
752
|
if (draw->info->stroke_pattern != NULL)
|
|
751
753
|
{
|
|
@@ -760,7 +762,7 @@ Draw_stroke_pattern_eq(VALUE self, VALUE pattern)
|
|
|
760
762
|
|
|
761
763
|
// DestroyDrawInfo destroys the clone
|
|
762
764
|
pattern = rm_cur_image(pattern);
|
|
763
|
-
image =
|
|
765
|
+
image = rm_check_readable(pattern);
|
|
764
766
|
// Do not trace creation
|
|
765
767
|
draw->info->stroke_pattern = rm_clone_image(image);
|
|
766
768
|
}
|
|
@@ -780,8 +782,7 @@ Draw_stroke_width_eq(VALUE self, VALUE stroke_width)
|
|
|
780
782
|
{
|
|
781
783
|
Draw *draw;
|
|
782
784
|
|
|
783
|
-
|
|
784
|
-
draw = get_draw(self);
|
|
785
|
+
draw = get_writable_draw(self);
|
|
785
786
|
draw->info->stroke_width = NUM2DBL(stroke_width);
|
|
786
787
|
return stroke_width;
|
|
787
788
|
}
|
|
@@ -798,8 +799,7 @@ Draw_text_antialias_eq(VALUE self, VALUE text_antialias)
|
|
|
798
799
|
{
|
|
799
800
|
Draw *draw;
|
|
800
801
|
|
|
801
|
-
|
|
802
|
-
draw = get_draw(self);
|
|
802
|
+
draw = get_writable_draw(self);
|
|
803
803
|
draw->info->text_antialias = (MagickBooleanType) RTEST(text_antialias);
|
|
804
804
|
return text_antialias;
|
|
805
805
|
}
|
|
@@ -829,8 +829,7 @@ Draw_undercolor_eq(VALUE self, VALUE undercolor)
|
|
|
829
829
|
{
|
|
830
830
|
Draw *draw;
|
|
831
831
|
|
|
832
|
-
|
|
833
|
-
draw = get_draw(self);
|
|
832
|
+
draw = get_writable_draw(self);
|
|
834
833
|
Color_to_PixelColor(&draw->info->undercolor, undercolor);
|
|
835
834
|
return undercolor;
|
|
836
835
|
}
|
|
@@ -868,9 +867,12 @@ annotate_ensure(VALUE arg)
|
|
|
868
867
|
struct Draw_annotate_args *annotate = (struct Draw_annotate_args *)arg;
|
|
869
868
|
Draw *draw = annotate->draw;
|
|
870
869
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
870
|
+
if (!rm_gvl_in_use(draw))
|
|
871
|
+
{
|
|
872
|
+
magick_free(draw->info->text);
|
|
873
|
+
draw->info->text = NULL;
|
|
874
|
+
draw->info->affine = annotate->keep;
|
|
875
|
+
}
|
|
874
876
|
|
|
875
877
|
#if defined(IMAGEMAGICK_7)
|
|
876
878
|
if (annotate->exception)
|
|
@@ -930,23 +932,24 @@ annotate_body(VALUE arg)
|
|
|
930
932
|
snprintf(geometry_str, sizeof(geometry_str), "%lux%lu%+ld%+ld", width, height, x, y);
|
|
931
933
|
}
|
|
932
934
|
|
|
933
|
-
magick_clone_string(&draw->info->geometry, geometry_str);
|
|
934
|
-
|
|
935
935
|
// Store in Draw structure. The text is drawn as given: it is not run
|
|
936
936
|
// through InterpretImageProperties(), so a `%[...]` or `%x` escape in it is
|
|
937
937
|
// not expanded. Everything those escapes provide is available directly from
|
|
938
938
|
// Ruby -- Image#columns, Image#filename, Image#artifact and so on.
|
|
939
939
|
embed_text = StringValueCStr(annotate->text);
|
|
940
940
|
image = rm_check_frozen(annotate->image_arg);
|
|
941
|
+
rm_gvl_check_writable(draw);
|
|
942
|
+
|
|
943
|
+
magick_clone_string(&draw->info->geometry, geometry_str);
|
|
941
944
|
draw->info->text = ConstantString(embed_text);
|
|
942
945
|
|
|
943
946
|
#if defined(IMAGEMAGICK_7)
|
|
944
947
|
annotate->exception = AcquireExceptionInfo();
|
|
945
|
-
|
|
948
|
+
DECLARE_GVL_CALL(call, AnnotateImage, image, draw->info, annotate->exception);
|
|
946
949
|
#else
|
|
947
|
-
|
|
950
|
+
DECLARE_GVL_CALL(call, AnnotateImage, image, draw->info);
|
|
948
951
|
#endif
|
|
949
|
-
|
|
952
|
+
call.update(annotate->image_arg).update(annotate->self).run<void>();
|
|
950
953
|
|
|
951
954
|
#if defined(IMAGEMAGICK_7)
|
|
952
955
|
exception = annotate->exception;
|
|
@@ -991,6 +994,7 @@ VALUE Draw_annotate(
|
|
|
991
994
|
// Save the affine matrix in case it is modified by
|
|
992
995
|
// Draw#rotation=
|
|
993
996
|
annotate.draw = get_draw(self);
|
|
997
|
+
rm_gvl_check_writable(annotate.draw);
|
|
994
998
|
annotate.keep = annotate.draw->info->affine;
|
|
995
999
|
|
|
996
1000
|
annotate.self = self;
|
|
@@ -1057,7 +1061,7 @@ Draw_composite(int argc, VALUE *argv, VALUE self)
|
|
|
1057
1061
|
|
|
1058
1062
|
// Retrieve the image to composite
|
|
1059
1063
|
image = rm_cur_image(argv[4]);
|
|
1060
|
-
comp_img =
|
|
1064
|
+
comp_img = rm_check_readable(image);
|
|
1061
1065
|
|
|
1062
1066
|
x = NUM2DBL(argv[0]);
|
|
1063
1067
|
y = NUM2DBL(argv[1]);
|
|
@@ -1102,6 +1106,26 @@ Draw_composite(int argc, VALUE *argv, VALUE self)
|
|
|
1102
1106
|
}
|
|
1103
1107
|
|
|
1104
1108
|
|
|
1109
|
+
// Release what Draw#draw and get_type_metrics() set on the DrawInfo for one call
|
|
1110
|
+
static void
|
|
1111
|
+
free_primitive(void *ptr, intptr_t arg ATTRIBUTE_UNUSED)
|
|
1112
|
+
{
|
|
1113
|
+
Draw *draw = (Draw *)ptr;
|
|
1114
|
+
|
|
1115
|
+
magick_free(draw->info->primitive);
|
|
1116
|
+
draw->info->primitive = NULL;
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
static void
|
|
1120
|
+
free_text(void *ptr, intptr_t arg ATTRIBUTE_UNUSED)
|
|
1121
|
+
{
|
|
1122
|
+
Draw *draw = (Draw *)ptr;
|
|
1123
|
+
|
|
1124
|
+
magick_free(draw->info->text);
|
|
1125
|
+
draw->info->text = NULL;
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
|
|
1105
1129
|
/**
|
|
1106
1130
|
* Execute the stored drawing primitives on the current image.
|
|
1107
1131
|
*
|
|
@@ -1122,6 +1146,7 @@ Draw_draw(VALUE self, VALUE image_arg)
|
|
|
1122
1146
|
image = rm_check_frozen(image_arg);
|
|
1123
1147
|
|
|
1124
1148
|
draw = get_draw(self);
|
|
1149
|
+
rm_gvl_check_writable(draw);
|
|
1125
1150
|
if (draw->primitives == 0)
|
|
1126
1151
|
{
|
|
1127
1152
|
rb_raise(rb_eArgError, "nothing to draw");
|
|
@@ -1132,11 +1157,12 @@ Draw_draw(VALUE self, VALUE image_arg)
|
|
|
1132
1157
|
|
|
1133
1158
|
#if defined(IMAGEMAGICK_7)
|
|
1134
1159
|
exception = AcquireExceptionInfo();
|
|
1135
|
-
|
|
1160
|
+
DECLARE_GVL_CALL(call, DrawImage, image, draw->info, exception);
|
|
1161
|
+
call.release(exception);
|
|
1136
1162
|
#else
|
|
1137
|
-
|
|
1163
|
+
DECLARE_GVL_CALL(call, DrawImage, image, draw->info);
|
|
1138
1164
|
#endif
|
|
1139
|
-
|
|
1165
|
+
call.update(image_arg).update(self).restore(free_primitive, draw).run<void>();
|
|
1140
1166
|
|
|
1141
1167
|
magick_free(draw->info->primitive);
|
|
1142
1168
|
draw->info->primitive = NULL;
|
|
@@ -1576,8 +1602,7 @@ PolaroidOptions_border_color_eq(VALUE self, VALUE border)
|
|
|
1576
1602
|
{
|
|
1577
1603
|
Draw *draw;
|
|
1578
1604
|
|
|
1579
|
-
|
|
1580
|
-
draw = get_draw(self);
|
|
1605
|
+
draw = get_writable_draw(self);
|
|
1581
1606
|
Color_to_PixelColor(&draw->info->border_color, border);
|
|
1582
1607
|
return border;
|
|
1583
1608
|
}
|
|
@@ -1669,7 +1694,7 @@ get_type_metrics(int argc, VALUE *argv, VALUE self, gvl_function_t fp)
|
|
|
1669
1694
|
break;
|
|
1670
1695
|
case 2:
|
|
1671
1696
|
t = rm_cur_image(argv[0]);
|
|
1672
|
-
image =
|
|
1697
|
+
image = rm_check_readable(t);
|
|
1673
1698
|
text_arg = argv[1];
|
|
1674
1699
|
text = rm_str2cstr(&text_arg, &text_l);
|
|
1675
1700
|
break; // okay
|
|
@@ -1684,16 +1709,22 @@ get_type_metrics(int argc, VALUE *argv, VALUE self, gvl_function_t fp)
|
|
|
1684
1709
|
}
|
|
1685
1710
|
|
|
1686
1711
|
draw = get_draw(self);
|
|
1712
|
+
rm_gvl_check_writable(draw);
|
|
1687
1713
|
// Measured as given: see the comment in Draw_annotate().
|
|
1688
1714
|
draw->info->text = ConstantString(text);
|
|
1689
1715
|
|
|
1690
1716
|
#if defined(IMAGEMAGICK_7)
|
|
1691
1717
|
exception = AcquireExceptionInfo();
|
|
1692
|
-
|
|
1718
|
+
DECLARE_GVL_CALL_FP(call, get_type_metrics, fp, image, draw->info, &metrics, exception);
|
|
1719
|
+
call.release(exception);
|
|
1693
1720
|
#else
|
|
1694
|
-
|
|
1721
|
+
DECLARE_GVL_CALL_FP(call, get_type_metrics, fp, image, draw->info, &metrics);
|
|
1695
1722
|
#endif
|
|
1696
|
-
|
|
1723
|
+
if (argc == 2)
|
|
1724
|
+
{
|
|
1725
|
+
call.read(t);
|
|
1726
|
+
}
|
|
1727
|
+
void *ret = call.update(self).restore(free_text, draw).run<void *>();
|
|
1697
1728
|
okay = static_cast<MagickBooleanType>(reinterpret_cast<intptr_t &>(ret));
|
|
1698
1729
|
|
|
1699
1730
|
magick_free(draw->info->text);
|
data/ext/RMagick/rmfill.cpp
CHANGED
|
@@ -191,8 +191,8 @@ point_fill(
|
|
|
191
191
|
#endif
|
|
192
192
|
}
|
|
193
193
|
|
|
194
|
-
|
|
195
|
-
|
|
194
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
195
|
+
call.keep_thread().run<void>();
|
|
196
196
|
CHECK_EXCEPTION();
|
|
197
197
|
}
|
|
198
198
|
|
|
@@ -261,8 +261,8 @@ vertical_fill(
|
|
|
261
261
|
row_pixels += GetPixelChannels(image);
|
|
262
262
|
}
|
|
263
263
|
|
|
264
|
-
|
|
265
|
-
|
|
264
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
265
|
+
call.keep_thread().run<void>();
|
|
266
266
|
CHECK_EXCEPTION();
|
|
267
267
|
}
|
|
268
268
|
|
|
@@ -295,8 +295,8 @@ vertical_fill(
|
|
|
295
295
|
|
|
296
296
|
memcpy(row_pixels, master, image->columns * sizeof(PixelPacket));
|
|
297
297
|
|
|
298
|
-
|
|
299
|
-
|
|
298
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
299
|
+
call.keep_thread().run<void>();
|
|
300
300
|
if (rm_should_raise_exception(exception, RetainExceptionRetention))
|
|
301
301
|
{
|
|
302
302
|
xfree((void *)master);
|
|
@@ -369,8 +369,8 @@ horizontal_fill(
|
|
|
369
369
|
row_pixels += GetPixelChannels(image);
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
|
|
373
|
-
|
|
372
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
373
|
+
call.keep_thread().run<void>();
|
|
374
374
|
CHECK_EXCEPTION();
|
|
375
375
|
}
|
|
376
376
|
|
|
@@ -402,8 +402,8 @@ horizontal_fill(
|
|
|
402
402
|
|
|
403
403
|
memcpy(col_pixels, master, image->rows * sizeof(PixelPacket));
|
|
404
404
|
|
|
405
|
-
|
|
406
|
-
|
|
405
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
406
|
+
call.keep_thread().run<void>();
|
|
407
407
|
if (rm_should_raise_exception(exception, RetainExceptionRetention))
|
|
408
408
|
{
|
|
409
409
|
xfree((void *)master);
|
|
@@ -514,8 +514,8 @@ v_diagonal_fill(
|
|
|
514
514
|
#endif
|
|
515
515
|
}
|
|
516
516
|
|
|
517
|
-
|
|
518
|
-
|
|
517
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
518
|
+
call.keep_thread().run<void>();
|
|
519
519
|
CHECK_EXCEPTION();
|
|
520
520
|
}
|
|
521
521
|
|
|
@@ -621,8 +621,8 @@ h_diagonal_fill(
|
|
|
621
621
|
#endif
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
|
|
625
|
-
|
|
624
|
+
DECLARE_GVL_CALL(call, SyncAuthenticPixels, image, exception);
|
|
625
|
+
call.keep_thread().run<void>();
|
|
626
626
|
CHECK_EXCEPTION();
|
|
627
627
|
}
|
|
628
628
|
|
|
@@ -645,7 +645,7 @@ GradientFill_fill(VALUE self, VALUE image_obj)
|
|
|
645
645
|
double x1, y1, x2, y2; // points on the line
|
|
646
646
|
|
|
647
647
|
TypedData_Get_Struct(self, rm_GradientFill, &rm_gradient_fill_data_type, fill);
|
|
648
|
-
image =
|
|
648
|
+
image = rm_check_writable(rm_cur_image(image_obj));
|
|
649
649
|
|
|
650
650
|
x1 = fill->x1;
|
|
651
651
|
y1 = fill->y1;
|
|
@@ -765,7 +765,7 @@ TextureFill_initialize(VALUE self, VALUE texture_arg)
|
|
|
765
765
|
texture_image = rm_cur_image(texture_arg);
|
|
766
766
|
|
|
767
767
|
// Bump the reference count on the texture image.
|
|
768
|
-
texture =
|
|
768
|
+
texture = rm_check_readable(texture_image);
|
|
769
769
|
ReferenceImage(texture);
|
|
770
770
|
|
|
771
771
|
fill->texture = texture;
|
|
@@ -791,7 +791,7 @@ TextureFill_fill(VALUE self, VALUE image_obj)
|
|
|
791
791
|
ExceptionInfo *exception;
|
|
792
792
|
#endif
|
|
793
793
|
|
|
794
|
-
image =
|
|
794
|
+
image = rm_check_writable(rm_cur_image(image_obj));
|
|
795
795
|
TypedData_Get_Struct(self, rm_TextureFill, &rm_texture_fill_data_type, fill);
|
|
796
796
|
|
|
797
797
|
#if defined(IMAGEMAGICK_7)
|