rgd 0.4.1a-x86-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. data/BSDL +22 -0
  2. data/COPYING +4 -0
  3. data/README +3 -0
  4. data/Rakefile +48 -0
  5. data/ext/rgd/extconf.rb +15 -0
  6. data/ext/rgd/gd_playground/bmp.h +114 -0
  7. data/ext/rgd/gd_playground/gd_bmp.c +1130 -0
  8. data/ext/rgd/gd_playground/gdhelpers.h +61 -0
  9. data/ext/rgd/rgd.c +2976 -0
  10. data/lib/rgd/1.8/rgd.so +0 -0
  11. data/lib/rgd/1.9/rgd.so +0 -0
  12. data/lib/rgd.rb +2 -0
  13. data/test/main.rb +22 -0
  14. data/test/mtest_stringft_cn.png +0 -0
  15. data/test/mtest_stringft_cn.rb +20 -0
  16. data/test/test_arc.png +0 -0
  17. data/test/test_arc.rb +10 -0
  18. data/test/test_color_closest.rb +32 -0
  19. data/test/test_color_exact.rb +37 -0
  20. data/test/test_color_resolve.rb +42 -0
  21. data/test/test_color_transparent.rb +16 -0
  22. data/test/test_copy.png +0 -0
  23. data/test/test_copy.rb +13 -0
  24. data/test/test_copy_rotated.png +0 -0
  25. data/test/test_copy_rotated.rb +14 -0
  26. data/test/test_fill_1.png +0 -0
  27. data/test/test_fill_1.rb +9 -0
  28. data/test/test_fill_2.png +0 -0
  29. data/test/test_fill_2.rb +30 -0
  30. data/test/test_fill_3.png +0 -0
  31. data/test/test_fill_3.rb +35 -0
  32. data/test/test_fill_4.png +0 -0
  33. data/test/test_fill_4.rb +25 -0
  34. data/test/test_fill_to_border.rb +14 -0
  35. data/test/test_filled_ellipse.png +0 -0
  36. data/test/test_filled_ellipse.rb +8 -0
  37. data/test/test_filled_rectangle.rb +46 -0
  38. data/test/test_line_1.png +0 -0
  39. data/test/test_line_1.rb +18 -0
  40. data/test/test_line_2.rb +18 -0
  41. data/test/test_line_3.rb +40 -0
  42. data/test/test_line_3_1.png +0 -0
  43. data/test/test_line_3_2.png +0 -0
  44. data/test/test_line_3_3.png +0 -0
  45. data/test/test_line_3_4.png +0 -0
  46. data/test/test_line_3_5.png +0 -0
  47. data/test/test_line_3_6.png +0 -0
  48. data/test/test_line_3_7.png +0 -0
  49. data/test/test_line_3_8.png +0 -0
  50. data/test/test_tiled.png +0 -0
  51. data/test/test_tiled.rb +15 -0
  52. metadata +117 -0
data/ext/rgd/rgd.c ADDED
@@ -0,0 +1,2976 @@
1
+ #include "ruby.h"
2
+
3
+ #include "gd.h"
4
+ #include "gdfontg.h"
5
+ #include "gdfontl.h"
6
+ #include "gdfontmb.h"
7
+ #include "gdfonts.h"
8
+ #include "gdfontt.h"
9
+ #ifndef HAVE_GDIMAGECREATEFROMBMP
10
+ // get from https://svn.php.net/viewvc/gd/trunk/playground/gdbmp/
11
+ #include "gd_playground/gd_bmp.c"
12
+ #endif
13
+
14
+ #ifdef WIN32
15
+ #define GDFUNC __stdcall
16
+ #else
17
+ #define GDFUNC
18
+ #endif
19
+
20
+ #ifdef _MSC_VER
21
+ #define strcasecmp stricmp
22
+ #endif
23
+
24
+ #define SetIntIfQnil(v, i) if (v == Qnil) v = INT2NUM(i)
25
+ #define STR2SYM(v) ID2SYM(rb_intern(v))
26
+
27
+ typedef enum ImageFormat { FMT_UNKNOW, FMT_JPEG, FMT_PNG, FMT_GIF, FMT_GD, FMT_GD2, FMT_WBMP, FMT_XBM, FMT_XPM, FMT_BMP } ImageFormat;
28
+
29
+ static VALUE rb_mRGD, rb_eRGDError, rb_cFont, rb_cImage;
30
+
31
+ static ImageFormat m_image_detect_format_by_ext(const char* ext) {
32
+ if (strcasecmp(ext, "jpg") == 0 || strcasecmp(ext, "jpeg") == 0) {
33
+ return FMT_JPEG;
34
+ } else if (strcasecmp(ext, "png") == 0) {
35
+ return FMT_PNG;
36
+ } else if (strcasecmp(ext, "gif") == 0) {
37
+ return FMT_GIF;
38
+ } else if (strcasecmp(ext, "bmp") == 0) {
39
+ return FMT_BMP;
40
+ } else if (strcasecmp(ext, "gd2") == 0) {
41
+ return FMT_GD2;
42
+ } else if (strcasecmp(ext, "gd") == 0) {
43
+ return FMT_GD;
44
+ } else if (strcasecmp(ext, "wbmp") == 0) {
45
+ return FMT_WBMP;
46
+ } else if (strcasecmp(ext, "xbm") == 0) {
47
+ return FMT_XBM;
48
+ } else if (strcasecmp(ext, "xpm") == 0) {
49
+ return FMT_XPM;
50
+ } else {
51
+ return FMT_UNKNOW;
52
+ }
53
+ }
54
+
55
+ static ImageFormat m_image_detect_format_by_magic(const char* buf) {
56
+ if (strncmp(buf, "\377\330\377\340", 4) == 0 || strncmp(buf, "\377\330\377\341", 4) == 0 || strncmp(buf, "\377\330\377\356", 4) == 0) {
57
+ return FMT_JPEG;
58
+ } else if (strncmp(buf, "\x89PNG", 4) == 0) {
59
+ return FMT_PNG;
60
+ } else if (strncmp(buf, "GIF89a", 6) == 0) {
61
+ return FMT_GIF;
62
+ } else if (strncmp(buf, "BM", 2) == 0 || strncmp(buf, "BA", 2) == 0 || strncmp(buf, "CI", 2) == 0 || strncmp(buf, "CP", 2) == 0 || strncmp(buf, "IC", 2) == 0 || strncmp(buf, "PT", 2) == 0) {
63
+ return FMT_BMP;
64
+ } else if (strncmp(buf, "gd2\0", 4) == 0) {
65
+ return FMT_GD2;
66
+ } else if (strncmp(buf, "\xFF\xFF", 2) == 0 || strncmp(buf, "\xFF\xFE", 2) == 0) {
67
+ return FMT_GD;
68
+ } else if (strncmp(buf, "/* XPM */", 9) == 0) {
69
+ return FMT_XPM;
70
+ } else if (strncmp(buf, "\0\0", 2) == 0) {
71
+ return FMT_WBMP;
72
+ } else {
73
+ return FMT_UNKNOW;
74
+ }
75
+ }
76
+
77
+ static VALUE m_named_colors() {
78
+ VALUE h = rb_hash_new();
79
+ rb_hash_aset(h, rb_str_new2("aliceblue"), rb_ary_new3(4, INT2NUM(0xF0), INT2NUM(0xF8), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
80
+ rb_hash_aset(h, rb_str_new2("antiquewhite"), rb_ary_new3(4, INT2NUM(0xFA), INT2NUM(0xEB), INT2NUM(0xD7), INT2NUM(gdAlphaOpaque)));
81
+ rb_hash_aset(h, rb_str_new2("aqua"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
82
+ rb_hash_aset(h, rb_str_new2("aquamarine"), rb_ary_new3(4, INT2NUM(0x7F), INT2NUM(0xFF), INT2NUM(0xD4), INT2NUM(gdAlphaOpaque)));
83
+ rb_hash_aset(h, rb_str_new2("azure"), rb_ary_new3(4, INT2NUM(0xF0), INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
84
+ rb_hash_aset(h, rb_str_new2("beige"), rb_ary_new3(4, INT2NUM(0xF5), INT2NUM(0xF5), INT2NUM(0xDC), INT2NUM(gdAlphaOpaque)));
85
+ rb_hash_aset(h, rb_str_new2("bisque"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xE4), INT2NUM(0xC4), INT2NUM(gdAlphaOpaque)));
86
+ rb_hash_aset(h, rb_str_new2("black"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x00), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
87
+ rb_hash_aset(h, rb_str_new2("blanchedalmond"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xEB), INT2NUM(0xCD), INT2NUM(gdAlphaOpaque)));
88
+ rb_hash_aset(h, rb_str_new2("blue"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
89
+ rb_hash_aset(h, rb_str_new2("blueviolet"), rb_ary_new3(4, INT2NUM(0x8A), INT2NUM(0x2B), INT2NUM(0xE2), INT2NUM(gdAlphaOpaque)));
90
+ rb_hash_aset(h, rb_str_new2("brown"), rb_ary_new3(4, INT2NUM(0xA5), INT2NUM(0x2A), INT2NUM(0x2A), INT2NUM(gdAlphaOpaque)));
91
+ rb_hash_aset(h, rb_str_new2("burlywood"), rb_ary_new3(4, INT2NUM(0xDE), INT2NUM(0xB8), INT2NUM(0x87), INT2NUM(gdAlphaOpaque)));
92
+ rb_hash_aset(h, rb_str_new2("cadetblue"), rb_ary_new3(4, INT2NUM(0x5F), INT2NUM(0x9E), INT2NUM(0xA0), INT2NUM(gdAlphaOpaque)));
93
+ rb_hash_aset(h, rb_str_new2("chartreuse"), rb_ary_new3(4, INT2NUM(0x7F), INT2NUM(0xFF), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
94
+ rb_hash_aset(h, rb_str_new2("chocolate"), rb_ary_new3(4, INT2NUM(0xD2), INT2NUM(0x69), INT2NUM(0x1E), INT2NUM(gdAlphaOpaque)));
95
+ rb_hash_aset(h, rb_str_new2("coral"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x7F), INT2NUM(0x50), INT2NUM(gdAlphaOpaque)));
96
+ rb_hash_aset(h, rb_str_new2("cornflowerblue"), rb_ary_new3(4, INT2NUM(0x64), INT2NUM(0x95), INT2NUM(0xED), INT2NUM(gdAlphaOpaque)));
97
+ rb_hash_aset(h, rb_str_new2("cornsilk"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xF8), INT2NUM(0xDC), INT2NUM(gdAlphaOpaque)));
98
+ rb_hash_aset(h, rb_str_new2("crimson"), rb_ary_new3(4, INT2NUM(0xDC), INT2NUM(0x14), INT2NUM(0x3C), INT2NUM(gdAlphaOpaque)));
99
+ rb_hash_aset(h, rb_str_new2("cyan"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
100
+ rb_hash_aset(h, rb_str_new2("darkblue"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x00), INT2NUM(0x8B), INT2NUM(gdAlphaOpaque)));
101
+ rb_hash_aset(h, rb_str_new2("darkcyan"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x8B), INT2NUM(0x8B), INT2NUM(gdAlphaOpaque)));
102
+ rb_hash_aset(h, rb_str_new2("darkgoldenrod"), rb_ary_new3(4, INT2NUM(0xB8), INT2NUM(0x86), INT2NUM(0x0B), INT2NUM(gdAlphaOpaque)));
103
+ rb_hash_aset(h, rb_str_new2("darkgray"), rb_ary_new3(4, INT2NUM(0xA9), INT2NUM(0xA9), INT2NUM(0xA9), INT2NUM(gdAlphaOpaque)));
104
+ rb_hash_aset(h, rb_str_new2("darkgrey"), rb_ary_new3(4, INT2NUM(0xA9), INT2NUM(0xA9), INT2NUM(0xA9), INT2NUM(gdAlphaOpaque)));
105
+ rb_hash_aset(h, rb_str_new2("darkgreen"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x64), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
106
+ rb_hash_aset(h, rb_str_new2("darkkhaki"), rb_ary_new3(4, INT2NUM(0xBD), INT2NUM(0xB7), INT2NUM(0x6B), INT2NUM(gdAlphaOpaque)));
107
+ rb_hash_aset(h, rb_str_new2("darkmagenta"), rb_ary_new3(4, INT2NUM(0x8B), INT2NUM(0x00), INT2NUM(0x8B), INT2NUM(gdAlphaOpaque)));
108
+ rb_hash_aset(h, rb_str_new2("darkolivegreen"), rb_ary_new3(4, INT2NUM(0x55), INT2NUM(0x6B), INT2NUM(0x2F), INT2NUM(gdAlphaOpaque)));
109
+ rb_hash_aset(h, rb_str_new2("darkorange"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x8C), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
110
+ rb_hash_aset(h, rb_str_new2("darkorchid"), rb_ary_new3(4, INT2NUM(0x99), INT2NUM(0x32), INT2NUM(0xCC), INT2NUM(gdAlphaOpaque)));
111
+ rb_hash_aset(h, rb_str_new2("darkred"), rb_ary_new3(4, INT2NUM(0x8B), INT2NUM(0x00), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
112
+ rb_hash_aset(h, rb_str_new2("darksalmon"), rb_ary_new3(4, INT2NUM(0xE9), INT2NUM(0x96), INT2NUM(0x7A), INT2NUM(gdAlphaOpaque)));
113
+ rb_hash_aset(h, rb_str_new2("darkseagreen"), rb_ary_new3(4, INT2NUM(0x8F), INT2NUM(0xBC), INT2NUM(0x8F), INT2NUM(gdAlphaOpaque)));
114
+ rb_hash_aset(h, rb_str_new2("darkslateblue"), rb_ary_new3(4, INT2NUM(0x48), INT2NUM(0x3D), INT2NUM(0x8B), INT2NUM(gdAlphaOpaque)));
115
+ rb_hash_aset(h, rb_str_new2("darkslategray"), rb_ary_new3(4, INT2NUM(0x2F), INT2NUM(0x4F), INT2NUM(0x4F), INT2NUM(gdAlphaOpaque)));
116
+ rb_hash_aset(h, rb_str_new2("darkslategrey"), rb_ary_new3(4, INT2NUM(0x2F), INT2NUM(0x4F), INT2NUM(0x4F), INT2NUM(gdAlphaOpaque)));
117
+ rb_hash_aset(h, rb_str_new2("darkturquoise"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xCE), INT2NUM(0xD1), INT2NUM(gdAlphaOpaque)));
118
+ rb_hash_aset(h, rb_str_new2("darkviolet"), rb_ary_new3(4, INT2NUM(0x94), INT2NUM(0x00), INT2NUM(0xD3), INT2NUM(gdAlphaOpaque)));
119
+ rb_hash_aset(h, rb_str_new2("deeppink"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x14), INT2NUM(0x93), INT2NUM(gdAlphaOpaque)));
120
+ rb_hash_aset(h, rb_str_new2("deepskyblue"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xBF), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
121
+ rb_hash_aset(h, rb_str_new2("dimgray"), rb_ary_new3(4, INT2NUM(0x69), INT2NUM(0x69), INT2NUM(0x69), INT2NUM(gdAlphaOpaque)));
122
+ rb_hash_aset(h, rb_str_new2("dimgrey"), rb_ary_new3(4, INT2NUM(0x69), INT2NUM(0x69), INT2NUM(0x69), INT2NUM(gdAlphaOpaque)));
123
+ rb_hash_aset(h, rb_str_new2("dodgerblue"), rb_ary_new3(4, INT2NUM(0x1E), INT2NUM(0x90), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
124
+ rb_hash_aset(h, rb_str_new2("firebrick"), rb_ary_new3(4, INT2NUM(0xB2), INT2NUM(0x22), INT2NUM(0x22), INT2NUM(gdAlphaOpaque)));
125
+ rb_hash_aset(h, rb_str_new2("floralwhite"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFA), INT2NUM(0xF0), INT2NUM(gdAlphaOpaque)));
126
+ rb_hash_aset(h, rb_str_new2("forestgreen"), rb_ary_new3(4, INT2NUM(0x22), INT2NUM(0x8B), INT2NUM(0x22), INT2NUM(gdAlphaOpaque)));
127
+ rb_hash_aset(h, rb_str_new2("fuchsia"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
128
+ rb_hash_aset(h, rb_str_new2("gainsboro"), rb_ary_new3(4, INT2NUM(0xDC), INT2NUM(0xDC), INT2NUM(0xDC), INT2NUM(gdAlphaOpaque)));
129
+ rb_hash_aset(h, rb_str_new2("ghostwhite"), rb_ary_new3(4, INT2NUM(0xF8), INT2NUM(0xF8), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
130
+ rb_hash_aset(h, rb_str_new2("gold"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xD7), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
131
+ rb_hash_aset(h, rb_str_new2("goldenrod"), rb_ary_new3(4, INT2NUM(0xDA), INT2NUM(0xA5), INT2NUM(0x20), INT2NUM(gdAlphaOpaque)));
132
+ rb_hash_aset(h, rb_str_new2("gray"), rb_ary_new3(4, INT2NUM(0x80), INT2NUM(0x80), INT2NUM(0x80), INT2NUM(gdAlphaOpaque)));
133
+ rb_hash_aset(h, rb_str_new2("grey"), rb_ary_new3(4, INT2NUM(0x80), INT2NUM(0x80), INT2NUM(0x80), INT2NUM(gdAlphaOpaque)));
134
+ rb_hash_aset(h, rb_str_new2("green"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x80), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
135
+ rb_hash_aset(h, rb_str_new2("greenyellow"), rb_ary_new3(4, INT2NUM(0xAD), INT2NUM(0xFF), INT2NUM(0x2F), INT2NUM(gdAlphaOpaque)));
136
+ rb_hash_aset(h, rb_str_new2("honeydew"), rb_ary_new3(4, INT2NUM(0xF0), INT2NUM(0xFF), INT2NUM(0xF0), INT2NUM(gdAlphaOpaque)));
137
+ rb_hash_aset(h, rb_str_new2("hotpink"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x69), INT2NUM(0xB4), INT2NUM(gdAlphaOpaque)));
138
+ rb_hash_aset(h, rb_str_new2("indianred"), rb_ary_new3(4, INT2NUM(0xCD), INT2NUM(0x5C), INT2NUM(0x5C), INT2NUM(gdAlphaOpaque)));
139
+ rb_hash_aset(h, rb_str_new2("indigo"), rb_ary_new3(4, INT2NUM(0x4B), INT2NUM(0x00), INT2NUM(0x82), INT2NUM(gdAlphaOpaque)));
140
+ rb_hash_aset(h, rb_str_new2("ivory"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(0xF0), INT2NUM(gdAlphaOpaque)));
141
+ rb_hash_aset(h, rb_str_new2("khaki"), rb_ary_new3(4, INT2NUM(0xF0), INT2NUM(0xE6), INT2NUM(0x8C), INT2NUM(gdAlphaOpaque)));
142
+ rb_hash_aset(h, rb_str_new2("lavender"), rb_ary_new3(4, INT2NUM(0xE6), INT2NUM(0xE6), INT2NUM(0xFA), INT2NUM(gdAlphaOpaque)));
143
+ rb_hash_aset(h, rb_str_new2("lavenderblush"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xF0), INT2NUM(0xF5), INT2NUM(gdAlphaOpaque)));
144
+ rb_hash_aset(h, rb_str_new2("lawngreen"), rb_ary_new3(4, INT2NUM(0x7C), INT2NUM(0xFC), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
145
+ rb_hash_aset(h, rb_str_new2("lemonchiffon"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFA), INT2NUM(0xCD), INT2NUM(gdAlphaOpaque)));
146
+ rb_hash_aset(h, rb_str_new2("lightblue"), rb_ary_new3(4, INT2NUM(0xAD), INT2NUM(0xD8), INT2NUM(0xE6), INT2NUM(gdAlphaOpaque)));
147
+ rb_hash_aset(h, rb_str_new2("lightcoral"), rb_ary_new3(4, INT2NUM(0xF0), INT2NUM(0x80), INT2NUM(0x80), INT2NUM(gdAlphaOpaque)));
148
+ rb_hash_aset(h, rb_str_new2("lightcyan"), rb_ary_new3(4, INT2NUM(0xE0), INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
149
+ rb_hash_aset(h, rb_str_new2("lightgoldenrodyellow"), rb_ary_new3(4, INT2NUM(0xFA), INT2NUM(0xFA), INT2NUM(0xD2), INT2NUM(gdAlphaOpaque)));
150
+ rb_hash_aset(h, rb_str_new2("lightgray"), rb_ary_new3(4, INT2NUM(0xD3), INT2NUM(0xD3), INT2NUM(0xD3), INT2NUM(gdAlphaOpaque)));
151
+ rb_hash_aset(h, rb_str_new2("lightgrey"), rb_ary_new3(4, INT2NUM(0xD3), INT2NUM(0xD3), INT2NUM(0xD3), INT2NUM(gdAlphaOpaque)));
152
+ rb_hash_aset(h, rb_str_new2("lightgreen"), rb_ary_new3(4, INT2NUM(0x90), INT2NUM(0xEE), INT2NUM(0x90), INT2NUM(gdAlphaOpaque)));
153
+ rb_hash_aset(h, rb_str_new2("lightpink"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xB6), INT2NUM(0xC1), INT2NUM(gdAlphaOpaque)));
154
+ rb_hash_aset(h, rb_str_new2("lightsalmon"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xA0), INT2NUM(0x7A), INT2NUM(gdAlphaOpaque)));
155
+ rb_hash_aset(h, rb_str_new2("lightseagreen"), rb_ary_new3(4, INT2NUM(0x20), INT2NUM(0xB2), INT2NUM(0xAA), INT2NUM(gdAlphaOpaque)));
156
+ rb_hash_aset(h, rb_str_new2("lightskyblue"), rb_ary_new3(4, INT2NUM(0x87), INT2NUM(0xCE), INT2NUM(0xFA), INT2NUM(gdAlphaOpaque)));
157
+ rb_hash_aset(h, rb_str_new2("lightslategray"), rb_ary_new3(4, INT2NUM(0x77), INT2NUM(0x88), INT2NUM(0x99), INT2NUM(gdAlphaOpaque)));
158
+ rb_hash_aset(h, rb_str_new2("lightslategrey"), rb_ary_new3(4, INT2NUM(0x77), INT2NUM(0x88), INT2NUM(0x99), INT2NUM(gdAlphaOpaque)));
159
+ rb_hash_aset(h, rb_str_new2("lightsteelblue"), rb_ary_new3(4, INT2NUM(0xB0), INT2NUM(0xC4), INT2NUM(0xDE), INT2NUM(gdAlphaOpaque)));
160
+ rb_hash_aset(h, rb_str_new2("lightyellow"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(0xE0), INT2NUM(gdAlphaOpaque)));
161
+ rb_hash_aset(h, rb_str_new2("lime"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
162
+ rb_hash_aset(h, rb_str_new2("limegreen"), rb_ary_new3(4, INT2NUM(0x32), INT2NUM(0xCD), INT2NUM(0x32), INT2NUM(gdAlphaOpaque)));
163
+ rb_hash_aset(h, rb_str_new2("linen"), rb_ary_new3(4, INT2NUM(0xFA), INT2NUM(0xF0), INT2NUM(0xE6), INT2NUM(gdAlphaOpaque)));
164
+ rb_hash_aset(h, rb_str_new2("magenta"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
165
+ rb_hash_aset(h, rb_str_new2("maroon"), rb_ary_new3(4, INT2NUM(0x80), INT2NUM(0x00), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
166
+ rb_hash_aset(h, rb_str_new2("mediumaquamarine"), rb_ary_new3(4, INT2NUM(0x66), INT2NUM(0xCD), INT2NUM(0xAA), INT2NUM(gdAlphaOpaque)));
167
+ rb_hash_aset(h, rb_str_new2("mediumblue"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x00), INT2NUM(0xCD), INT2NUM(gdAlphaOpaque)));
168
+ rb_hash_aset(h, rb_str_new2("mediumorchid"), rb_ary_new3(4, INT2NUM(0xBA), INT2NUM(0x55), INT2NUM(0xD3), INT2NUM(gdAlphaOpaque)));
169
+ rb_hash_aset(h, rb_str_new2("mediumpurple"), rb_ary_new3(4, INT2NUM(0x93), INT2NUM(0x70), INT2NUM(0xD8), INT2NUM(gdAlphaOpaque)));
170
+ rb_hash_aset(h, rb_str_new2("mediumseagreen"), rb_ary_new3(4, INT2NUM(0x3C), INT2NUM(0xB3), INT2NUM(0x71), INT2NUM(gdAlphaOpaque)));
171
+ rb_hash_aset(h, rb_str_new2("mediumslateblue"), rb_ary_new3(4, INT2NUM(0x7B), INT2NUM(0x68), INT2NUM(0xEE), INT2NUM(gdAlphaOpaque)));
172
+ rb_hash_aset(h, rb_str_new2("mediumspringgreen"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xFA), INT2NUM(0x9A), INT2NUM(gdAlphaOpaque)));
173
+ rb_hash_aset(h, rb_str_new2("mediumturquoise"), rb_ary_new3(4, INT2NUM(0x48), INT2NUM(0xD1), INT2NUM(0xCC), INT2NUM(gdAlphaOpaque)));
174
+ rb_hash_aset(h, rb_str_new2("mediumvioletred"), rb_ary_new3(4, INT2NUM(0xC7), INT2NUM(0x15), INT2NUM(0x85), INT2NUM(gdAlphaOpaque)));
175
+ rb_hash_aset(h, rb_str_new2("midnightblue"), rb_ary_new3(4, INT2NUM(0x19), INT2NUM(0x19), INT2NUM(0x70), INT2NUM(gdAlphaOpaque)));
176
+ rb_hash_aset(h, rb_str_new2("mintcream"), rb_ary_new3(4, INT2NUM(0xF5), INT2NUM(0xFF), INT2NUM(0xFA), INT2NUM(gdAlphaOpaque)));
177
+ rb_hash_aset(h, rb_str_new2("mistyrose"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xE4), INT2NUM(0xE1), INT2NUM(gdAlphaOpaque)));
178
+ rb_hash_aset(h, rb_str_new2("moccasin"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xE4), INT2NUM(0xB5), INT2NUM(gdAlphaOpaque)));
179
+ rb_hash_aset(h, rb_str_new2("navajowhite"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xDE), INT2NUM(0xAD), INT2NUM(gdAlphaOpaque)));
180
+ rb_hash_aset(h, rb_str_new2("navy"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x00), INT2NUM(0x80), INT2NUM(gdAlphaOpaque)));
181
+ rb_hash_aset(h, rb_str_new2("oldlace"), rb_ary_new3(4, INT2NUM(0xFD), INT2NUM(0xF5), INT2NUM(0xE6), INT2NUM(gdAlphaOpaque)));
182
+ rb_hash_aset(h, rb_str_new2("olive"), rb_ary_new3(4, INT2NUM(0x80), INT2NUM(0x80), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
183
+ rb_hash_aset(h, rb_str_new2("olivedrab"), rb_ary_new3(4, INT2NUM(0x6B), INT2NUM(0x8E), INT2NUM(0x23), INT2NUM(gdAlphaOpaque)));
184
+ rb_hash_aset(h, rb_str_new2("orange"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xA5), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
185
+ rb_hash_aset(h, rb_str_new2("orangered"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x45), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
186
+ rb_hash_aset(h, rb_str_new2("orchid"), rb_ary_new3(4, INT2NUM(0xDA), INT2NUM(0x70), INT2NUM(0xD6), INT2NUM(gdAlphaOpaque)));
187
+ rb_hash_aset(h, rb_str_new2("palegoldenrod"), rb_ary_new3(4, INT2NUM(0xEE), INT2NUM(0xE8), INT2NUM(0xAA), INT2NUM(gdAlphaOpaque)));
188
+ rb_hash_aset(h, rb_str_new2("palegreen"), rb_ary_new3(4, INT2NUM(0x98), INT2NUM(0xFB), INT2NUM(0x98), INT2NUM(gdAlphaOpaque)));
189
+ rb_hash_aset(h, rb_str_new2("paleturquoise"), rb_ary_new3(4, INT2NUM(0xAF), INT2NUM(0xEE), INT2NUM(0xEE), INT2NUM(gdAlphaOpaque)));
190
+ rb_hash_aset(h, rb_str_new2("palevioletred"), rb_ary_new3(4, INT2NUM(0xD8), INT2NUM(0x70), INT2NUM(0x93), INT2NUM(gdAlphaOpaque)));
191
+ rb_hash_aset(h, rb_str_new2("papayawhip"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xEF), INT2NUM(0xD5), INT2NUM(gdAlphaOpaque)));
192
+ rb_hash_aset(h, rb_str_new2("peachpuff"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xDA), INT2NUM(0xB9), INT2NUM(gdAlphaOpaque)));
193
+ rb_hash_aset(h, rb_str_new2("peru"), rb_ary_new3(4, INT2NUM(0xCD), INT2NUM(0x85), INT2NUM(0x3F), INT2NUM(gdAlphaOpaque)));
194
+ rb_hash_aset(h, rb_str_new2("pink"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xC0), INT2NUM(0xCB), INT2NUM(gdAlphaOpaque)));
195
+ rb_hash_aset(h, rb_str_new2("plum"), rb_ary_new3(4, INT2NUM(0xDD), INT2NUM(0xA0), INT2NUM(0xDD), INT2NUM(gdAlphaOpaque)));
196
+ rb_hash_aset(h, rb_str_new2("powderblue"), rb_ary_new3(4, INT2NUM(0xB0), INT2NUM(0xE0), INT2NUM(0xE6), INT2NUM(gdAlphaOpaque)));
197
+ rb_hash_aset(h, rb_str_new2("purple"), rb_ary_new3(4, INT2NUM(0x80), INT2NUM(0x00), INT2NUM(0x80), INT2NUM(gdAlphaOpaque)));
198
+ rb_hash_aset(h, rb_str_new2("red"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x00), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
199
+ rb_hash_aset(h, rb_str_new2("rosybrown"), rb_ary_new3(4, INT2NUM(0xBC), INT2NUM(0x8F), INT2NUM(0x8F), INT2NUM(gdAlphaOpaque)));
200
+ rb_hash_aset(h, rb_str_new2("royalblue"), rb_ary_new3(4, INT2NUM(0x41), INT2NUM(0x69), INT2NUM(0xE1), INT2NUM(gdAlphaOpaque)));
201
+ rb_hash_aset(h, rb_str_new2("saddlebrown"), rb_ary_new3(4, INT2NUM(0x8B), INT2NUM(0x45), INT2NUM(0x13), INT2NUM(gdAlphaOpaque)));
202
+ rb_hash_aset(h, rb_str_new2("salmon"), rb_ary_new3(4, INT2NUM(0xFA), INT2NUM(0x80), INT2NUM(0x72), INT2NUM(gdAlphaOpaque)));
203
+ rb_hash_aset(h, rb_str_new2("sandybrown"), rb_ary_new3(4, INT2NUM(0xF4), INT2NUM(0xA4), INT2NUM(0x60), INT2NUM(gdAlphaOpaque)));
204
+ rb_hash_aset(h, rb_str_new2("seagreen"), rb_ary_new3(4, INT2NUM(0x2E), INT2NUM(0x8B), INT2NUM(0x57), INT2NUM(gdAlphaOpaque)));
205
+ rb_hash_aset(h, rb_str_new2("seashell"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xF5), INT2NUM(0xEE), INT2NUM(gdAlphaOpaque)));
206
+ rb_hash_aset(h, rb_str_new2("sienna"), rb_ary_new3(4, INT2NUM(0xA0), INT2NUM(0x52), INT2NUM(0x2D), INT2NUM(gdAlphaOpaque)));
207
+ rb_hash_aset(h, rb_str_new2("silver"), rb_ary_new3(4, INT2NUM(0xC0), INT2NUM(0xC0), INT2NUM(0xC0), INT2NUM(gdAlphaOpaque)));
208
+ rb_hash_aset(h, rb_str_new2("skyblue"), rb_ary_new3(4, INT2NUM(0x87), INT2NUM(0xCE), INT2NUM(0xEB), INT2NUM(gdAlphaOpaque)));
209
+ rb_hash_aset(h, rb_str_new2("slateblue"), rb_ary_new3(4, INT2NUM(0x6A), INT2NUM(0x5A), INT2NUM(0xCD), INT2NUM(gdAlphaOpaque)));
210
+ rb_hash_aset(h, rb_str_new2("slategray"), rb_ary_new3(4, INT2NUM(0x70), INT2NUM(0x80), INT2NUM(0x90), INT2NUM(gdAlphaOpaque)));
211
+ rb_hash_aset(h, rb_str_new2("slategrey"), rb_ary_new3(4, INT2NUM(0x70), INT2NUM(0x80), INT2NUM(0x90), INT2NUM(gdAlphaOpaque)));
212
+ rb_hash_aset(h, rb_str_new2("snow"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFA), INT2NUM(0xFA), INT2NUM(gdAlphaOpaque)));
213
+ rb_hash_aset(h, rb_str_new2("springgreen"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0xFF), INT2NUM(0x7F), INT2NUM(gdAlphaOpaque)));
214
+ rb_hash_aset(h, rb_str_new2("steelblue"), rb_ary_new3(4, INT2NUM(0x46), INT2NUM(0x82), INT2NUM(0xB4), INT2NUM(gdAlphaOpaque)));
215
+ rb_hash_aset(h, rb_str_new2("tan"), rb_ary_new3(4, INT2NUM(0xD2), INT2NUM(0xB4), INT2NUM(0x8C), INT2NUM(gdAlphaOpaque)));
216
+ rb_hash_aset(h, rb_str_new2("teal"), rb_ary_new3(4, INT2NUM(0x00), INT2NUM(0x80), INT2NUM(0x80), INT2NUM(gdAlphaOpaque)));
217
+ rb_hash_aset(h, rb_str_new2("thistle"), rb_ary_new3(4, INT2NUM(0xD8), INT2NUM(0xBF), INT2NUM(0xD8), INT2NUM(gdAlphaOpaque)));
218
+ rb_hash_aset(h, rb_str_new2("tomato"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0x63), INT2NUM(0x47), INT2NUM(gdAlphaOpaque)));
219
+ rb_hash_aset(h, rb_str_new2("turquoise"), rb_ary_new3(4, INT2NUM(0x40), INT2NUM(0xE0), INT2NUM(0xD0), INT2NUM(gdAlphaOpaque)));
220
+ rb_hash_aset(h, rb_str_new2("violet"), rb_ary_new3(4, INT2NUM(0xEE), INT2NUM(0x82), INT2NUM(0xEE), INT2NUM(gdAlphaOpaque)));
221
+ rb_hash_aset(h, rb_str_new2("wheat"), rb_ary_new3(4, INT2NUM(0xF5), INT2NUM(0xDE), INT2NUM(0xB3), INT2NUM(gdAlphaOpaque)));
222
+ rb_hash_aset(h, rb_str_new2("white"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(gdAlphaOpaque)));
223
+ rb_hash_aset(h, rb_str_new2("whitesmoke"), rb_ary_new3(4, INT2NUM(0xF5), INT2NUM(0xF5), INT2NUM(0xF5), INT2NUM(gdAlphaOpaque)));
224
+ rb_hash_aset(h, rb_str_new2("yellow"), rb_ary_new3(4, INT2NUM(0xFF), INT2NUM(0xFF), INT2NUM(0x00), INT2NUM(gdAlphaOpaque)));
225
+ rb_hash_aset(h, rb_str_new2("yellowgreen"), rb_ary_new3(4, INT2NUM(0x9A), INT2NUM(0xCD), INT2NUM(0x32), INT2NUM(gdAlphaOpaque)));
226
+ return h;
227
+ }
228
+
229
+ static VALUE m_scan_color_args(int argc, VALUE *argv) {
230
+ VALUE r, g, b, a;
231
+ int i;
232
+ if (argc == 1) {
233
+ i = TYPE(argv[0]);
234
+ if (i == T_STRING) {
235
+ a = rb_hash_aref(rb_cv_get(rb_cImage, "@@named_colors"), rb_funcall(argv[0], rb_intern("downcase"), 0));
236
+ if (TYPE(a) == T_ARRAY) {
237
+ return a;
238
+ } else {
239
+ rb_raise(rb_eArgError, "Unknow color name: %s", RSTRING_PTR(argv[0]));
240
+ }
241
+ } else if (i == T_FIXNUM) {
242
+ i = NUM2INT(argv[0]);
243
+ return rb_ary_new3(4, INT2NUM(gdTrueColorGetRed(i)), INT2NUM(gdTrueColorGetGreen(i)), INT2NUM(gdTrueColorGetBlue(i)), INT2NUM(gdTrueColorGetAlpha(i)));
244
+ } else {
245
+ rb_raise(rb_eArgError, "String or Fixnum expected");
246
+ }
247
+ } else if (argc == 3 || argc == 4) {
248
+ rb_scan_args(argc, argv, "31", &r, &g, &b, &a);
249
+ SetIntIfQnil(a, gdAlphaOpaque);
250
+ return rb_ary_new3(4, r, g, b, a);
251
+ } else {
252
+ rb_raise(rb_eArgError, "Wrong # of arguments (1 or 3 or 4 for %d)", argc);
253
+ }
254
+ }
255
+
256
+ // gd_gfp__X
257
+ static VALUE gd_font_get(VALUE klass, gdFontPtr (GDFUNC *pfunc)(void)) {
258
+ gdFontPtr ft = (*pfunc)();
259
+ return Data_Wrap_Struct(klass, 0, 0, ft);
260
+ }
261
+
262
+ /*
263
+ * call-seq:
264
+ * Font.small()
265
+ *
266
+ * Returns the "small" gd font.
267
+ *
268
+ * See Image.string for more information, or Image.stringft for a
269
+ * freetype-based alternative that supports truetype fonts.
270
+ */
271
+ static VALUE font_s_small(VALUE klass) {
272
+ return gd_font_get(klass, gdFontGetSmall);
273
+ }
274
+
275
+ /*
276
+ * call-seq:
277
+ * Font.large()
278
+ *
279
+ * Returns the "large" gd font.
280
+ *
281
+ * See Image.string for more information, or Image.stringft for a
282
+ * freetype-based alternative that supports truetype fonts.
283
+ */
284
+ static VALUE font_s_large(VALUE klass) {
285
+ return gd_font_get(klass, gdFontGetLarge);
286
+ }
287
+
288
+ /*
289
+ * call-seq:
290
+ * Font.medium_bold()
291
+ *
292
+ * Returns the "medium bold" gd font.
293
+ *
294
+ * See Image.string for more information, or Image.stringft for a
295
+ * freetype-based alternative that supports truetype fonts.
296
+ */
297
+ static VALUE font_s_medium_bold(VALUE klass) {
298
+ return gd_font_get(klass, gdFontGetMediumBold);
299
+ }
300
+
301
+ /*
302
+ * call-seq:
303
+ * Font.giant()
304
+ *
305
+ * Returns the "giant" gd font.
306
+ *
307
+ * See Image.string for more information, or Image.stringft for a
308
+ * freetype-based alternative that supports truetype fonts.
309
+ */
310
+ static VALUE font_s_giant(VALUE klass) {
311
+ return gd_font_get(klass, gdFontGetGiant);
312
+ }
313
+
314
+ /*
315
+ * call-seq:
316
+ * Font.tiny()
317
+ *
318
+ * Returns the "tiny" gd font.
319
+ *
320
+ * See Image.string for more information, or Image.stringft for a
321
+ * freetype-based alternative that supports truetype fonts.
322
+ */
323
+ static VALUE font_s_tiny(VALUE klass) {
324
+ return gd_font_get(klass, gdFontGetTiny);
325
+ }
326
+
327
+ // gd_H__H
328
+ /*
329
+ * call-seq:
330
+ * use_fontconfig = boolean
331
+ *
332
+ * GD 2.0.29 introduced the ability to use fontconfig patterns rather than font
333
+ * file names as parameters to Image.stringft, Image.stringft_circle. For
334
+ * backwards compatibility reasons, the fontlist parameter to those functions is
335
+ * still expected to be a full or partial font file path name or list thereof by
336
+ * default. However, as a convenience, when use_fontconfig=true configures
337
+ * gd to expect the fontlist parameter to be a fontconfig pattern.
338
+ *
339
+ * NOTE, if the fontconfig library is not available, use_fontconfig=true
340
+ * will raise an error.
341
+ */
342
+ static VALUE image_s_use_fontconfig(VALUE klass, VALUE flag) {
343
+ if (!gdFTUseFontConfig(RTEST(flag) ? 1 : 0)) {
344
+ rb_raise(rb_eRGDError, "The FontConfig library is not available.");
345
+ }
346
+ }
347
+
348
+ // gd_H__H2
349
+ /*
350
+ * call-seq:
351
+ * alpha_blend(dst, src)
352
+ *
353
+ * Accepts truecolor pixel values only. The source color is composited with the
354
+ * destination color based on the alpha channel value of the source color.
355
+ *
356
+ * The resulting color is opaque.
357
+ */
358
+ static VALUE image_s_alpha_blend(VALUE klass, VALUE dst, VALUE src) {
359
+ return INT2NUM(gdAlphaBlend(NUM2INT(dst), NUM2INT(src)));
360
+ }
361
+
362
+ // gd_H__H4
363
+ /*
364
+ * call-seq:
365
+ * truecolor(args)
366
+ *
367
+ * Returns an RGBA color value for use when drawing on a truecolor image.
368
+ *
369
+ * Usage:
370
+ *
371
+ * * truecolor(color_name)
372
+ * * truecolor(r, g, b, a = ALPHA_OPAQUE)
373
+ *
374
+ * _color_name_ can be any one of 147 color names are defined in the HTML and
375
+ * CSS color specification.
376
+ *
377
+ * Red, green, and blue are all in the range between 0 (off) and 255 (maximum).
378
+ * Alpha is in the range between ALPHA_OPAQUE (opaque) and ALPHA_TRANSPARENT
379
+ * (fully transparent). This method should not be used with palette-based
380
+ * images. If you need to write code which is compatible with both palette-based
381
+ * and truecolor images, use Image.color_resolve.
382
+ */
383
+ static VALUE image_s_truecolor(int argc, VALUE *argv, VALUE klass) {
384
+ VALUE r = m_scan_color_args(argc, argv);
385
+ return INT2NUM(gdTrueColorAlpha(NUM2INT(rb_ary_entry(r, 0)), NUM2INT(rb_ary_entry(r, 1)), NUM2INT(rb_ary_entry(r, 2)), NUM2INT(rb_ary_entry(r, 3))));
386
+ }
387
+
388
+ static void gd_image_free(gdImagePtr im) {
389
+ if (im) gdImageDestroy(im);
390
+ }
391
+
392
+ // gd_gip__H2
393
+ static VALUE gd_image_create(VALUE klass, VALUE w, VALUE h, gdImagePtr (GDFUNC *pfunc)(int, int)) {
394
+ gdImagePtr im = (*pfunc)(NUM2INT(w), NUM2INT(h));
395
+ if (!im) rb_raise(rb_eRGDError, "unable to allocate the image");
396
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
397
+ }
398
+
399
+ /*
400
+ * call-seq:
401
+ * Image.create(width, height)
402
+ *
403
+ * Creates a palette-based image, with no more than 256 colors.
404
+ */
405
+ static VALUE image_s_create(VALUE klass, VALUE width, VALUE height) {
406
+ return gd_image_create(klass, width, height, gdImageCreate);
407
+ }
408
+
409
+ /*
410
+ * call-seq:
411
+ * create_truecolor(width, height)
412
+ *
413
+ * Creates a truecolor image, with an essentially unlimited number of colors.
414
+ */
415
+ static VALUE image_s_create_truecolor(VALUE klass, VALUE width, VALUE height) {
416
+ return gd_image_create(klass, width, height, gdImageCreateTrueColor);
417
+ }
418
+
419
+ // gd_gip__H_PAX
420
+ static VALUE gd_image_create_from_data(VALUE klass, VALUE data, gdImagePtr (GDFUNC *pfunc)(int, void*)) {
421
+ gdImagePtr im;
422
+
423
+ Check_Type(data, T_STRING);
424
+ im = (*pfunc)(RSTRING_LEN(data), RSTRING_PTR(data));
425
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image data");
426
+
427
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
428
+ }
429
+
430
+ /*
431
+ * call-seq:
432
+ * from_jpeg_data(data)
433
+ *
434
+ * Creates a truecolor image from a JPEG format byte-string.
435
+ */
436
+ static VALUE image_s_from_jpeg_data(VALUE klass, VALUE data) {
437
+ return gd_image_create_from_data(klass, data, gdImageCreateFromJpegPtr);
438
+ }
439
+
440
+ /*
441
+ * call-seq:
442
+ * from_png_data(data)
443
+ *
444
+ * Creates a image from a PNG format byte-string.
445
+ *
446
+ * If the PNG image being loaded is a truecolor image, the result will be a
447
+ * truecolor image. If the PNG image being loaded is a palette or grayscale
448
+ * image, the result will be a palette image. gd retains only 8 bits of
449
+ * resolution for each of the red, green and blue channels, and only 7 bits of
450
+ * resolution for the alpha channel. The former restriction affects only a
451
+ * handful of very rare 48-bit color and 16-bit grayscale PNG images. The second
452
+ * restriction affects all semitransparent PNG images, but the difference is
453
+ * essentially invisible to the eye. 7 bits of alpha channel resolution is, in
454
+ * practice, quite a lot.
455
+ */
456
+ static VALUE image_s_from_png_data(VALUE klass, VALUE data) {
457
+ return gd_image_create_from_data(klass, data, gdImageCreateFromPngPtr);
458
+ }
459
+
460
+ /*
461
+ * call-seq:
462
+ * from_gif_data(data)
463
+ *
464
+ * Creates a image from a GIF format byte-string.
465
+ */
466
+ static VALUE image_s_from_gif_data(VALUE klass, VALUE data) {
467
+ return gd_image_create_from_data(klass, data, gdImageCreateFromGifPtr);
468
+ }
469
+
470
+ /*
471
+ * call-seq:
472
+ * from_gd_data(data)
473
+ *
474
+ * Creates a image from a GD format byte-string.
475
+ */
476
+ static VALUE image_s_from_gd_data(VALUE klass, VALUE data) {
477
+ return gd_image_create_from_data(klass, data, gdImageCreateFromGdPtr);
478
+ }
479
+
480
+ /*
481
+ * call-seq:
482
+ * from_gd2_data(data)
483
+ *
484
+ * Creates a image from a GD2 format byte-string.
485
+ */
486
+ static VALUE image_s_from_gd2_data(VALUE klass, VALUE data) {
487
+ return gd_image_create_from_data(klass, data, gdImageCreateFromGd2Ptr);
488
+ }
489
+
490
+ /*
491
+ * call-seq:
492
+ * from_wbmp_data(data)
493
+ *
494
+ * Creates a image from a WBMP format byte-string.
495
+ */
496
+ static VALUE image_s_from_wbmp_data(VALUE klass, VALUE data) {
497
+ return gd_image_create_from_data(klass, data, gdImageCreateFromWBMPPtr);
498
+ }
499
+
500
+ /*
501
+ * call-seq:
502
+ * from_bmp_data(data)
503
+ *
504
+ * Creates a image from a BMP format byte-string.
505
+ */
506
+ static VALUE image_s_from_bmp_data(VALUE klass, VALUE data) {
507
+ return gd_image_create_from_data(klass, data, gdImageCreateFromBmpPtr);
508
+ }
509
+
510
+ // gd_gip__H_PAX_H4
511
+ /*
512
+ * call-seq:
513
+ * from_gd2_part_data(data, x, y, width, height)
514
+ *
515
+ * Create a image from a GD2 format byte-string, with extra parameters
516
+ * indicating the source (x, y) and width/height of the desired image.
517
+ */
518
+ static VALUE image_s_from_gd2_part_data(VALUE klass, VALUE data, VALUE x, VALUE y, VALUE w, VALUE h) {
519
+ gdImagePtr im;
520
+
521
+ Check_Type(data, T_STRING);
522
+ Check_Type(x, T_FIXNUM);Check_Type(y, T_FIXNUM);
523
+ Check_Type(w, T_FIXNUM);Check_Type(h, T_FIXNUM);
524
+ im = gdImageCreateFromGd2PartPtr(RSTRING_LEN(data), RSTRING_PTR(data), NUM2INT(x), NUM2INT(y), NUM2INT(w), NUM2INT(h));
525
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image data");
526
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
527
+ }
528
+
529
+ // gd_gip__PAD
530
+ /*
531
+ * call-seq:
532
+ * from_xpm(filename)
533
+ *
534
+ * Creates a image from a XPM file.
535
+ */
536
+ static VALUE image_s_from_xpm(VALUE klass, VALUE filename) {
537
+ gdImagePtr im;
538
+
539
+ if (rb_funcall(rb_cFile, rb_intern("readable?"), 1, filename) != Qtrue)
540
+ rb_raise(rb_eIOError, "Cannot open %s for read", RSTRING_PTR(filename));
541
+ im = gdImageCreateFromXpm(RSTRING_PTR(filename));
542
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image: %s", RSTRING_PTR(filename));
543
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
544
+ }
545
+
546
+ // gd_gip__fp
547
+ static VALUE gd_image_create_from_file(VALUE klass, VALUE filename, gdImagePtr (GDFUNC *pfunc)(FILE*)) {
548
+ gdImagePtr im;
549
+ FILE* fp;
550
+
551
+ fp = fopen(RSTRING_PTR(filename), "rb");
552
+ if (!fp) rb_raise(rb_eIOError, "Cannot open %s for read", RSTRING_PTR(filename));
553
+
554
+ im = (*pfunc)(fp);
555
+ fclose(fp);
556
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image: %s", RSTRING_PTR(filename));
557
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
558
+ }
559
+
560
+ /*
561
+ * call-seq:
562
+ * from_jpeg(filename)
563
+ *
564
+ * Creates a truecolor image from a JPEG format file.
565
+ */
566
+ static VALUE image_s_from_jpeg(VALUE klass, VALUE filename) {
567
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromJpeg);
568
+ }
569
+
570
+ /*
571
+ * call-seq:
572
+ * from_png(filename)
573
+ *
574
+ * Creates a image from a PNG format file.
575
+ *
576
+ * If the PNG image being loaded is a truecolor image, the result will be a
577
+ * truecolor image. If the PNG image being loaded is a palette or grayscale
578
+ * image, the result will be a palette image. gd retains only 8 bits of
579
+ * resolution for each of the red, green and blue channels, and only 7 bits of
580
+ * resolution for the alpha channel. The former restriction affects only a
581
+ * handful of very rare 48-bit color and 16-bit grayscale PNG images. The second
582
+ * restriction affects all semitransparent PNG images, but the difference is
583
+ * essentially invisible to the eye. 7 bits of alpha channel resolution is, in
584
+ * practice, quite a lot.
585
+ */
586
+ static VALUE image_s_from_png(VALUE klass, VALUE filename) {
587
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromPng);
588
+ }
589
+
590
+ /*
591
+ * call-seq:
592
+ * from_gif(filename)
593
+ *
594
+ * Creates a image from a GIF format file.
595
+ */
596
+ static VALUE image_s_from_gif(VALUE klass, VALUE filename) {
597
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromGif);
598
+ }
599
+
600
+ /*
601
+ * call-seq:
602
+ * from_gd(filename)
603
+ *
604
+ * Creates a image from a GD format file.
605
+ */
606
+ static VALUE image_s_from_gd(VALUE klass, VALUE filename) {
607
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromGd);
608
+ }
609
+
610
+ /*
611
+ * call-seq:
612
+ * from_gd2(filename)
613
+ *
614
+ * Creates a image from a GD2 format file, with extra parameters indicating the
615
+ * source (x, y) and width/height of the desired image.
616
+ */
617
+ static VALUE image_s_from_gd2(VALUE klass, VALUE filename) {
618
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromGd2);
619
+ }
620
+
621
+ /*
622
+ * call-seq:
623
+ * from_wbmp(filename)
624
+ *
625
+ * Creates a image from a WBMP format file.
626
+ */
627
+ static VALUE image_s_from_wbmp(VALUE klass, VALUE filename) {
628
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromWBMP);
629
+ }
630
+
631
+ /*
632
+ * call-seq:
633
+ * from_xbm(filename)
634
+ *
635
+ * Creates a image from a XBM format file.
636
+ */
637
+ static VALUE image_s_from_xbm(VALUE klass, VALUE filename) {
638
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromXbm);
639
+ }
640
+
641
+ /*
642
+ * call-seq:
643
+ * from_bmp(filename)
644
+ *
645
+ * Creates a image from a BMP format file.
646
+ */
647
+ static VALUE image_s_from_bmp(VALUE klass, VALUE filename) {
648
+ return gd_image_create_from_file(klass, filename, gdImageCreateFromBmp);
649
+ }
650
+
651
+ // gd_gip__fp_H4
652
+ /*
653
+ * call-seq:
654
+ * from_gd2_part(filename, x, y, width, height)
655
+ *
656
+ * Create a image from a GD2 format file, with extra parameters indicating the
657
+ * source (x, y) and width/height of the desired image.
658
+ */
659
+ static VALUE image_s_from_gd2_part(VALUE klass, VALUE filename, VALUE x, VALUE y, VALUE w, VALUE h) {
660
+ gdImagePtr im;
661
+ FILE* fp;
662
+
663
+ Check_Type(x, T_FIXNUM);Check_Type(y, T_FIXNUM);
664
+ Check_Type(w, T_FIXNUM);Check_Type(h, T_FIXNUM);
665
+ fp = fopen(RSTRING_PTR(filename), "rb");
666
+ if (!fp) rb_raise(rb_eIOError, "Cannot open %s for read", RSTRING_PTR(filename));
667
+
668
+ im = gdImageCreateFromGd2Part(fp, NUM2INT(x), NUM2INT(y), NUM2INT(w), NUM2INT(h));
669
+ fclose(fp);
670
+
671
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image: %s", RSTRING_PTR(filename));
672
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
673
+ }
674
+
675
+ // gd_gip__gip_H2
676
+ /*
677
+ * call-seq:
678
+ * create_palette_from_truecolor(img, dither = true, colors = MAX_COLORS)
679
+ *
680
+ * Create a new palette-based image from a truecolor image, by using a
681
+ * high-quality two-pass quantization routine. If _dither_ is true, the image
682
+ * will be dithered to approximate colors better, at the expense of some
683
+ * obvious "speckling." _colors_ can be anything up to 256. If the original
684
+ * source image includes photographic information or anything that came out of
685
+ * a JPEG, 256 is strongly recommended. 100% transparency of a single
686
+ * transparent color in the original truecolor image will be preserved. There is
687
+ * no other support for preservation of alpha channel or transparency in the
688
+ * destination image.
689
+ */
690
+ static VALUE image_s_create_palette_from_truecolor(int argc, VALUE *argv, VALUE klass) {
691
+ gdImagePtr im, im2;
692
+ VALUE img2, dither, colors;
693
+ rb_scan_args(argc, argv, "12", &img2, &dither, &colors);
694
+ SetIntIfQnil(dither, Qtrue);
695
+ Data_Get_Struct(img2, gdImage, im2);
696
+ im = gdImageCreatePaletteFromTrueColor(im2, RTEST(dither) ? 1 : 0, RTEST(colors) ? NUM2INT(colors) : gdMaxColors);
697
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image data");
698
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
699
+ }
700
+
701
+ // gd_gip__gip_H
702
+ /*
703
+ * call-seq:
704
+ * square_to_circle(img, radius)
705
+ *
706
+ * The argument _img_ MUST be square, but can have any size. Returns a new image
707
+ * of width and height radius * 2, in which the X axis of the original has been
708
+ * remapped to theta (angle) and the Y axis of the original has been remapped to
709
+ * rho (distance from center). This is known as a "polar coordinate transform."
710
+ *
711
+ * See also Image.stringft_circle, which uses this function internally.
712
+ */
713
+ static VALUE image_s_square_to_circle(VALUE klass, VALUE img2, VALUE radius) {
714
+ gdImagePtr im, im2;
715
+ Data_Get_Struct(img2, gdImage, im2);
716
+ im = gdImageSquareToCircle(im2, NUM2INT(radius));
717
+ if (!im) rb_raise(rb_eRGDError, "Not valid Image data");
718
+ return Data_Wrap_Struct(klass, 0, gd_image_free, im);
719
+ }
720
+
721
+ // gd_X__gip_fp
722
+ static VALUE gd_image_to_file(VALUE klass, VALUE filename, void (GDFUNC *pfunc)(gdImagePtr, FILE*)) {
723
+ gdImagePtr im;
724
+ FILE* fp;
725
+
726
+ fp = fopen(RSTRING_PTR(filename), "wb");
727
+ if (!fp) rb_raise(rb_eIOError, "Cannot open %s for write", RSTRING_PTR(filename));
728
+
729
+ Data_Get_Struct(klass, gdImage, im);
730
+ (*pfunc)(im, fp);
731
+ fclose(fp);
732
+ return klass;
733
+ }
734
+
735
+ /*
736
+ * call-seq:
737
+ * gif(filename)
738
+ *
739
+ * Write the image to the specified file in GIF format.
740
+ */
741
+ static VALUE image_gif(VALUE klass, VALUE filename) {
742
+ return gd_image_to_file(klass, filename, gdImageGif);
743
+ }
744
+
745
+ /*
746
+ * call-seq:
747
+ * gd(filename)
748
+ *
749
+ * Write the image to the specified file in GD format.
750
+ */
751
+ static VALUE image_gd(VALUE klass, VALUE filename) {
752
+ return gd_image_to_file(klass, filename, gdImageGd);
753
+ }
754
+
755
+ // gd_X__gip_fp_H
756
+ // gd_X__gip_H_fp
757
+ static VALUE gd_image_to_file_H(VALUE klass, VALUE filename, VALUE a, void (GDFUNC *pfunc)(gdImagePtr, FILE*, int)) {
758
+ gdImagePtr im;
759
+ FILE* fp;
760
+
761
+ Check_Type(a, T_FIXNUM);
762
+
763
+ fp = fopen(RSTRING_PTR(filename), "wb");
764
+ if (!fp) rb_raise(rb_eIOError, "Cannot open %s for write", RSTRING_PTR(filename));
765
+
766
+ Data_Get_Struct(klass, gdImage, im);
767
+ (*pfunc)(im, fp, NUM2INT(a));
768
+ fclose(fp);
769
+ return klass;
770
+ }
771
+
772
+ /*
773
+ * call-seq:
774
+ * jpeg(filename, quality = -1)
775
+ *
776
+ * Write the image to the specified file in JPEG format.
777
+ *
778
+ * If quality is negative, the default IJG JPEG quality value (which should
779
+ * yield a good general quality / size tradeoff for most situations) is used.
780
+ * Otherwise, for practical purposes, quality should be a value in the range
781
+ * 0-95, higher quality values usually implying both higher quality and larger
782
+ * image sizes.
783
+ */
784
+ static VALUE image_jpeg(int argc, VALUE *argv, VALUE klass) {
785
+ VALUE filename, quality;
786
+ rb_scan_args(argc, argv, "11", &filename, &quality);
787
+ SetIntIfQnil(quality, -1);
788
+ return gd_image_to_file_H(klass, filename, quality, gdImageJpeg);
789
+ }
790
+
791
+ /*
792
+ * call-seq:
793
+ * png(filename, level = -1)
794
+ *
795
+ * Write the image to the specified file in PNG format.
796
+ *
797
+ * _level_ specified the level of compression to be specified. A compression
798
+ * level of 0 means "no compression." A compression level of 1 means
799
+ * "compressed, but as quickly as possible." A compression level of 9 means
800
+ * "compressed as much as possible to produce the smallest possible file." A
801
+ * compression level of -1 will use the default compression level at the time
802
+ * zlib was compiled on your system.
803
+ */
804
+ static VALUE image_png(int argc, VALUE *argv, VALUE klass) {
805
+ VALUE filename, level;
806
+ rb_scan_args(argc, argv, "11", &filename, &level);
807
+ SetIntIfQnil(level, -1);
808
+ return gd_image_to_file_H(klass, filename, level, gdImagePngEx);
809
+ }
810
+
811
+ /*
812
+ * call-seq:
813
+ * bmp(filename)
814
+ *
815
+ * Write the image to the specified file in BMP format.
816
+ */
817
+ static VALUE image_bmp(VALUE klass, VALUE filename) {
818
+ return gd_image_to_file_H(klass, filename, 1, gdImageBmp);
819
+ }
820
+
821
+ void GDFUNC gd_gdImageWBMP(gdImagePtr im, FILE* out, int fg) {
822
+ gdImageWBMP(im, fg, out);
823
+ }
824
+
825
+ /*
826
+ * call-seq:
827
+ * wbmp(filename, fg = 1)
828
+ *
829
+ * Write the image to the specified file in WBMP format.
830
+ *
831
+ * WBMP file support is black and white only. The color index specified by
832
+ * the _fg_ argument is the "foreground," and only pixels of this color will be
833
+ * set in the WBMP file. All other pixels will be considered "background."
834
+ */
835
+ static VALUE image_wbmp(int argc, VALUE *argv, VALUE klass) {
836
+ VALUE filename, fg;
837
+ rb_scan_args(argc, argv, "11", &filename, &fg);
838
+ SetIntIfQnil(fg, 1);
839
+ return gd_image_to_file_H(klass, filename, fg, gd_gdImageWBMP);
840
+ }
841
+
842
+ // gd_X__gip_fp_H2
843
+ /*
844
+ * call-seq:
845
+ * gd2(filename, chunk_size = 0, fmt = GD2_FMT_COMPRESSED)
846
+ *
847
+ * Write the image to the specified file in GD2 format.
848
+ *
849
+ * The gd2 image format is intended for fast reads and writes of parts of
850
+ * images. It is a compressed format (when _fmt_ is GD2_FMT_COMPRESSED), and
851
+ * well suited to retrieving smll sections of much larger images.
852
+ *
853
+ * The file is stored as a series of compressed subimages, and the _chunk_size_
854
+ * determines the sub-image size - a value of zero causes the GD library to use
855
+ * the default.
856
+ *
857
+ * It is also possible to store GD2 files in an uncompressed format, in which
858
+ * case _fmt_ should be GD2_FMT_RAW.
859
+ */
860
+ static VALUE image_gd2(int argc, VALUE *argv, VALUE klass) {
861
+ VALUE filename, chunk_size, fmt;
862
+ gdImagePtr im;
863
+ FILE* fp;
864
+
865
+ rb_scan_args(argc, argv, "12", &filename, &chunk_size, &fmt);
866
+ SetIntIfQnil(chunk_size, 0);
867
+ SetIntIfQnil(fmt, GD2_FMT_COMPRESSED);
868
+ Check_Type(chunk_size, T_FIXNUM);
869
+ Check_Type(fmt, T_FIXNUM);
870
+
871
+ fp = fopen(RSTRING_PTR(filename), "wb");
872
+ if (!fp) rb_raise(rb_eIOError, "Cannot open %s for write", RSTRING_PTR(filename));
873
+
874
+ Data_Get_Struct(klass, gdImage, im);
875
+ gdImageGd2(im, fp, NUM2INT(chunk_size), NUM2INT(fmt));
876
+ fclose(fp);
877
+ return klass;
878
+ }
879
+
880
+ // gd_PAX__gip_PAH
881
+ static VALUE gd_image_to_data(VALUE klass, void* (GDFUNC *pfunc)(gdImagePtr, int*)) {
882
+ VALUE data;
883
+ gdImagePtr im;
884
+ char* buf;
885
+ int len;
886
+
887
+ Data_Get_Struct(klass, gdImage, im);
888
+ buf = (*pfunc)(im, &len);
889
+ data = rb_str_new(buf, len);
890
+ gdFree(buf);
891
+ return data;
892
+ }
893
+
894
+ /*
895
+ * call-seq:
896
+ * gif_data()
897
+ *
898
+ * Convert the image to a GIF format byte-string.
899
+ */
900
+ static VALUE image_gif_data(VALUE klass) {
901
+ return gd_image_to_data(klass, gdImageGifPtr);
902
+ }
903
+
904
+ /*
905
+ * call-seq:
906
+ * gd_data()
907
+ *
908
+ * Convert the image to a GD format byte-string.
909
+ */
910
+ static VALUE image_gd_data(VALUE klass) {
911
+ return gd_image_to_data(klass, gdImageGdPtr);
912
+ }
913
+
914
+ // gd_PAX__gip_PAH_H
915
+ static VALUE gd_image_to_data_H(VALUE klass, VALUE a, void* (GDFUNC *pfunc)(gdImagePtr, int*, int)) {
916
+ VALUE data;
917
+ gdImagePtr im;
918
+ char* buf;
919
+ int len;
920
+
921
+ Data_Get_Struct(klass, gdImage, im);
922
+ buf = (*pfunc)(im, &len, NUM2INT(a));
923
+ data = rb_str_new(buf, len);
924
+ gdFree(buf);
925
+ return data;
926
+ }
927
+
928
+ /*
929
+ * call-seq:
930
+ * jpeg_data(quality = -1)
931
+ *
932
+ * Convert the image to a JPEG format byte-string.
933
+ *
934
+ * Read Image.jpeg for more.
935
+ */
936
+ static VALUE image_jpeg_data(int argc, VALUE *argv, VALUE klass) {
937
+ VALUE a;
938
+ rb_scan_args(argc, argv, "01", &a);
939
+ SetIntIfQnil(a, -1);
940
+ return gd_image_to_data_H(klass, a, gdImageJpegPtr);
941
+ }
942
+
943
+ /*
944
+ * call-seq:
945
+ * png_data(level = -1)
946
+ *
947
+ * Convert the image to a PNG format byte-string.
948
+ *
949
+ * Read Image.png for more.
950
+ */
951
+ static VALUE image_png_data(int argc, VALUE *argv, VALUE klass) {
952
+ VALUE a;
953
+ rb_scan_args(argc, argv, "01", &a);
954
+ SetIntIfQnil(a, -1);
955
+ return gd_image_to_data_H(klass, a, gdImagePngPtrEx);
956
+ }
957
+
958
+ /*
959
+ * call-seq:
960
+ * wbmp_data(fg = 1)
961
+ *
962
+ * Convert the image to a WBMP format byte-string.
963
+ *
964
+ * Read Image.wbmp for more.
965
+ */
966
+ static VALUE image_wbmp_data(int argc, VALUE *argv, VALUE klass) {
967
+ VALUE a;
968
+ rb_scan_args(argc, argv, "01", &a);
969
+ SetIntIfQnil(a, 1);
970
+ return gd_image_to_data_H(klass, a, gdImageWBMPPtr);
971
+ }
972
+
973
+ /*
974
+ * call-seq:
975
+ * bmp_data()
976
+ *
977
+ * Convert the image to a BMP format byte-string.
978
+ */
979
+ static VALUE image_bmp_data(VALUE klass) {
980
+ return gd_image_to_data_H(klass, INT2NUM(1), gdImageBmpPtr);
981
+ }
982
+
983
+ // gd_PAX__gip_PAH_H2
984
+ // gd_PAX__gip_H2_PAH
985
+ static VALUE gd_image_to_data_H2(VALUE klass, VALUE a, VALUE b, void* (GDFUNC *pfunc)(gdImagePtr, int*, int, int)) {
986
+ VALUE data;
987
+ gdImagePtr im;
988
+ char* buf;
989
+ int len;
990
+
991
+ Data_Get_Struct(klass, gdImage, im);
992
+ buf = (*pfunc)(im, &len, NUM2INT(a), NUM2INT(b));
993
+ data = rb_str_new(buf, len);
994
+ gdFree(buf);
995
+ return data;
996
+ }
997
+
998
+ void* GDFUNC gd_gdImageGd2Ptr(gdImagePtr im, int *size, int cs, int fmt) {
999
+ gdImageGd2Ptr(im, cs, fmt, size);
1000
+ }
1001
+
1002
+ /*
1003
+ * call-seq:
1004
+ * gd2_data(chunk_size = 0, fmt = GD2_FMT_COMPRESSED)
1005
+ *
1006
+ * Convert the image to a GD2 format byte-string.
1007
+ *
1008
+ * Read Image.gd2 for more.
1009
+ */
1010
+ static VALUE image_gd2_data(int argc, VALUE *argv, VALUE klass) {
1011
+ VALUE a, b;
1012
+ rb_scan_args(argc, argv, "02", &a, &b);
1013
+ SetIntIfQnil(a, 0);
1014
+ SetIntIfQnil(b, GD2_FMT_COMPRESSED);
1015
+ return gd_image_to_data_H2(klass, a, b, gd_gdImageGd2Ptr);
1016
+ }
1017
+
1018
+ /*
1019
+ * call-seq:
1020
+ * gif_anim_begin_data(global_cm = -1, loops = 0)
1021
+ *
1022
+ * This function must be called as the first function when creating a GIF
1023
+ * animation. It returns a byte-string for the correct GIF file headers,
1024
+ * and prepares for frames to be added for the animation. It's *NOT* used to
1025
+ * produce an image frame of GIF file, it is only used to establish the GIF
1026
+ * animation frame size, interlacing options and the color palette.
1027
+ * Image.gif_anim_add_data is used to make the first and subsequent frames
1028
+ * to the animation, and the animation must be terminated by writing a semicolon
1029
+ * character (;) to it or by using Image.gif_anim_end_data to get that.
1030
+ *
1031
+ * The global_cm flag indicates if a global color map (or palette) is used in
1032
+ * the GIF89A header. A nonzero value specifies that a global color map should
1033
+ * be used to reduce the size of the animation. Of course, if the color maps of
1034
+ * individual frames differ greatly, a global color map may not be a good idea.
1035
+ * global_cm=1 means write global color map, global_cm=0 means do not, and
1036
+ * global_cm=-1 means to do the default, which currently is to use a global
1037
+ * color map.
1038
+ *
1039
+ * If loops is 0 or greater, the Netscape 2.0 extension for animation loop count
1040
+ * is written. 0 means infinite loop count. -1 means that the extension is not
1041
+ * added which results in no looping.
1042
+ */
1043
+ static VALUE image_gif_anim_begin_data(int argc, VALUE *argv, VALUE klass) {
1044
+ VALUE a, b;
1045
+ rb_scan_args(argc, argv, "02", &a, &b);
1046
+ SetIntIfQnil(a, -1);
1047
+ SetIntIfQnil(b, 0);
1048
+ return gd_image_to_data_H2(klass, a, b, gdImageGifAnimBeginPtr);
1049
+ }
1050
+
1051
+ // gd_PAX__gip_PAzH_H5_gip
1052
+ /*
1053
+ * call-seq:
1054
+ * gif_anim_add_data(local_cm = 1, left = 0, top = 0, delay = 5, disposal = DISPOSAL_NONE, prev_image = nil)
1055
+ *
1056
+ * This function returns GIF animation frames to GIF animation, which was
1057
+ * initialized with Image.gif_anim_begin_data.
1058
+ *
1059
+ * With _left_ and _top_ you can place this frame in different offset than (0,0)
1060
+ * inside the image screen as defined in Image.gif_anim_begin_data.
1061
+ *
1062
+ * The argument _delay_ between the previous frame and this frame is in 1/100s
1063
+ * units.
1064
+ *
1065
+ * The argument _disposal_ is usually DISPOSAL_NONE, meaning that the pixels
1066
+ * changed by this frame should remain on the display when the next frame begins
1067
+ * to render, but can also be DISPOSAL_RESTORE_BACKGROUND (restores the first
1068
+ * allocated color of the global palette), or DISPOSAL_RESTORE_PREVIOUS
1069
+ * (restores the appearance of the affected area before the frame was rendered).
1070
+ * Only DISPOSAL_NONE is a sensible choice for the first frame.
1071
+ *
1072
+ * If _prev_im_ is not nil, the built-in GIF optimizer will always use
1073
+ * DISPOSAL_NONE regardless of the Disposal parameter.
1074
+ */
1075
+ static VALUE image_gif_anim_add_data(int argc, VALUE *argv, VALUE klass) {
1076
+ VALUE data, local_cm, left, top, delay, disposal, prev_image;
1077
+ gdImagePtr im, im2 = NULL;
1078
+ char* buf;
1079
+ int len;
1080
+
1081
+ rb_scan_args(argc, argv, "06", &local_cm, &left, &top, &delay, &disposal, &prev_image);
1082
+ SetIntIfQnil(local_cm, 1);
1083
+ SetIntIfQnil(left, 0);
1084
+ SetIntIfQnil(top, 0);
1085
+ SetIntIfQnil(delay, 5);
1086
+ SetIntIfQnil(disposal, gdDisposalNone);
1087
+ if RTEST(prev_image) Data_Get_Struct(prev_image, gdImage, im2);
1088
+
1089
+ Data_Get_Struct(klass, gdImage, im);
1090
+ buf = gdImageGifAnimAddPtr(im, &len, NUM2INT(local_cm), NUM2INT(left), NUM2INT(top), NUM2INT(delay), NUM2INT(disposal), im2);
1091
+ data = rb_str_new(buf, len);
1092
+ gdFree(buf);
1093
+ return data;
1094
+ }
1095
+
1096
+ // gd_PAX__PAH
1097
+ /*
1098
+ * call-seq:
1099
+ * gif_anim_end_data()
1100
+ *
1101
+ * Returns a one byte string containing the semicolon character (;). The string
1102
+ * ";" can be used in place of this function.
1103
+ */
1104
+ static VALUE image_gif_anim_end_data(VALUE klass) {
1105
+ VALUE data;
1106
+ char* buf;
1107
+ int len;
1108
+
1109
+ buf = gdImageGifAnimEndPtr(&len);
1110
+ data = rb_str_new(buf, len);
1111
+ gdFree(buf);
1112
+ return data;
1113
+ }
1114
+
1115
+ // gd_H__gip2
1116
+ /*
1117
+ * call-seq:
1118
+ * compare(image)
1119
+ *
1120
+ * Returns a bitmap indicating if the two images are different. The members of
1121
+ * the bitmap are defined as GD_CMP_*, but the most important is GD_CMP_IMAGE,
1122
+ * which indicated that the images will actually appear different when displayed.
1123
+ * Other, less important, differences relate to pallette entries. Any difference
1124
+ * in the transparent color is assumed to make images display differently, even
1125
+ * if the transparent color is not used.
1126
+ */
1127
+ static VALUE image_compare(VALUE klass, VALUE image) {
1128
+ gdImagePtr im, im2;
1129
+ Data_Get_Struct(klass, gdImage, im);
1130
+ Data_Get_Struct(image, gdImage, im2);
1131
+ return INT2NUM(gdImageCompare(im, im2));
1132
+ }
1133
+
1134
+ /*
1135
+ * call-seq:
1136
+ * width()
1137
+ *
1138
+ * Get the width of the image in pixels.
1139
+ */
1140
+ static VALUE image_sx(VALUE klass) {
1141
+ gdImagePtr im;
1142
+ Data_Get_Struct(klass, gdImage, im);
1143
+ return INT2NUM(gdImageSX(im));
1144
+ }
1145
+
1146
+ /*
1147
+ * call-seq:
1148
+ * height()
1149
+ *
1150
+ * Get the height of the image in pixels.
1151
+ */
1152
+ static VALUE image_sy(VALUE klass) {
1153
+ gdImagePtr im;
1154
+ Data_Get_Struct(klass, gdImage, im);
1155
+ return INT2NUM(gdImageSY(im));
1156
+ }
1157
+
1158
+ /*
1159
+ * call-seq:
1160
+ * truecolor?()
1161
+ *
1162
+ * Return true if the image is a truecolor image, false for palette-based image.
1163
+ */
1164
+ static VALUE image_is_truecolor(VALUE klass) {
1165
+ gdImagePtr im;
1166
+ Data_Get_Struct(klass, gdImage, im);
1167
+ return gdImageTrueColor(im) != 0 ? Qtrue : Qfalse;
1168
+ }
1169
+
1170
+ /*
1171
+ * call-seq:
1172
+ * colors_total()
1173
+ *
1174
+ * Returns the number of colors currently allocated in a palette image.
1175
+ */
1176
+ static VALUE image_colors_total(VALUE klass) {
1177
+ gdImagePtr im;
1178
+ Data_Get_Struct(klass, gdImage, im);
1179
+ return INT2NUM(gdImageColorsTotal(im));
1180
+ }
1181
+
1182
+ /*
1183
+ * call-seq:
1184
+ * interlace()
1185
+ *
1186
+ * Read Image.interlace= for details.
1187
+ */
1188
+ static VALUE image_get_interlace(VALUE klass) {
1189
+ gdImagePtr im;
1190
+ Data_Get_Struct(klass, gdImage, im);
1191
+ return gdImageGetInterlaced(im) ? Qtrue : Qfalse;
1192
+ }
1193
+
1194
+ /*
1195
+ * call-seq:
1196
+ * transparent()
1197
+ *
1198
+ * Returns the current transparent color index in the image. If there is no
1199
+ * transparent color returns -1.
1200
+ *
1201
+ */
1202
+ static VALUE image_transparent_get(VALUE klass) {
1203
+ gdImagePtr im;
1204
+ Data_Get_Struct(klass, gdImage, im);
1205
+ return INT2NUM(gdImageGetTransparent(im));
1206
+ }
1207
+
1208
+ // gd_H__gip_H
1209
+ /*
1210
+ * call-seq:
1211
+ * r, g, b, a = rgba(color)
1212
+ *
1213
+ * Returns a array containing the red, green, blue, alpha components of the
1214
+ * specified color (for truecolor image) or color index (for palette-based
1215
+ * image).
1216
+ */
1217
+ static VALUE image_rgba(VALUE klass, VALUE color) {
1218
+ gdImagePtr im;
1219
+ int c = NUM2INT(color);
1220
+ Data_Get_Struct(klass, gdImage, im);
1221
+ return rb_ary_new3(4, INT2NUM(gdImageRed(im, c)), INT2NUM(gdImageGreen(im, c)), INT2NUM(gdImageBlue(im, c)), INT2NUM(gdImageAlpha(im, c)));
1222
+ }
1223
+
1224
+ static VALUE gd_H__gip_H2(VALUE klass, VALUE a, VALUE b, int (GDFUNC *pfunc)(gdImagePtr, int, int)) {
1225
+ gdImagePtr im;
1226
+ Data_Get_Struct(klass, gdImage, im);
1227
+ return INT2NUM((*pfunc)(im, NUM2INT(a), NUM2INT(b)));
1228
+ }
1229
+
1230
+ /*
1231
+ * call-seq:
1232
+ * slef[x, y]
1233
+ *
1234
+ * Get the color index or the color values of a particular pixel.
1235
+ *
1236
+ * A color index is returned when the image is palette based (created by
1237
+ * Image.create), the color value is returned when the image is a true
1238
+ * color image (created by Image.create_truecolor). To fetch the value of
1239
+ * each channel, you can use Image.rgba.
1240
+ */
1241
+ static VALUE image_get_pixel(VALUE klass, VALUE x, VALUE y) {
1242
+ return gd_H__gip_H2(klass, x, y, gdImageGetPixel);
1243
+ }
1244
+
1245
+ /*
1246
+ * call-seq:
1247
+ * bounds_safe(x, y)
1248
+ *
1249
+ * Returns true if the specified point is within the current clipping rectangle,
1250
+ * false if not. The clipping rectangle is set by Image.clip= and defaults to
1251
+ * the entire image. This function is intended primarily for use by those who
1252
+ * wish to add functions to gd.
1253
+ */
1254
+ static VALUE image_bounds_safe(VALUE klass, VALUE x, VALUE y) {
1255
+ return gd_H__gip_H2(klass, x, y, gdImageBoundsSafe) == INT2NUM(0) ? Qfalse : Qtrue;
1256
+ }
1257
+
1258
+ // gd_H__gip_H3
1259
+ /*
1260
+ * call-seq:
1261
+ * color_closest_hwb(args)
1262
+ *
1263
+ * Usage:
1264
+ *
1265
+ * * color_closest_hwb(r, g, b)
1266
+ * * color_closest_hwb(integer)
1267
+ * * color_closest_hwb(color_name)
1268
+ *
1269
+ * Read Image.color_allocate for more about usage.
1270
+ *
1271
+ * Searches the colors which have been defined thus far in the image specified
1272
+ * and returns the index of the color with hue, whiteness and blackness closest
1273
+ * to the requested color. This scheme is typically superior to the Euclidian
1274
+ * distance scheme used by Image.color_closest.
1275
+ *
1276
+ * If no colors have yet been allocated in the image, this method returns -1.
1277
+ * When applied to a truecolor image, this function always succeeds in
1278
+ * returning the desired color.
1279
+ *
1280
+ * This function is most useful as a backup method for choosing a drawing color
1281
+ * when an image already contains MAX_COLORS (256) colors and no more can be
1282
+ * allocated. (This is not uncommon when working with existing PNG files that
1283
+ * already use many colors.) See Image.color_exact for a method of
1284
+ * locating exact matches only.
1285
+ */
1286
+ static VALUE image_color_closest_hwb(int argc, VALUE *argv, VALUE klass) {
1287
+ gdImagePtr im;
1288
+ VALUE r = m_scan_color_args(argc, argv);
1289
+ Data_Get_Struct(klass, gdImage, im);
1290
+ return INT2NUM(gdImageColorClosestHWB(im, NUM2INT(rb_ary_entry(r, 0)), NUM2INT(rb_ary_entry(r, 1)), NUM2INT(rb_ary_entry(r, 2))));
1291
+ }
1292
+
1293
+ // gd_H__gip_H4
1294
+ static VALUE gd_image_color_func_alpha(int argc, VALUE *argv, VALUE klass, int (GDFUNC *pfunc)(gdImagePtr, int, int, int, int)) {
1295
+ gdImagePtr im;
1296
+ VALUE r = m_scan_color_args(argc, argv);
1297
+ Data_Get_Struct(klass, gdImage, im);
1298
+ return INT2NUM((*pfunc)(im, NUM2INT(rb_ary_entry(r, 0)), NUM2INT(rb_ary_entry(r, 1)), NUM2INT(rb_ary_entry(r, 2)), NUM2INT(rb_ary_entry(r, 3))));
1299
+ }
1300
+
1301
+ /*
1302
+ * call-seq:
1303
+ * color_allocate(args)
1304
+ *
1305
+ * Usage:
1306
+ *
1307
+ * * color_allocate(r, g, b, a = ALPHA_OPAQUE)
1308
+ * * color_allocate(integer)
1309
+ * * color_allocate(color_name)
1310
+ *
1311
+ * Red, green and blue can be anything upto 255, and 127 represents full
1312
+ * transparency for alpha.
1313
+ *
1314
+ * _color_name_ can be any one of 147 color names are defined in the HTML and
1315
+ * CSS color specification.
1316
+ *
1317
+ * This method finds the first available color index in the image specified,
1318
+ * sets its RGBA values to those requested, and returns the index of the
1319
+ * new color table entry, or an RGBA value in the case of a truecolor image;
1320
+ * in either case you can then use the returned value as a parameter to drawing
1321
+ * functions. When creating a new palette-based image, the first time you
1322
+ * invoke this function, you are setting the background color for that image.
1323
+ *
1324
+ * In the event that all MAX_COLORS colors (256) have already been allocated,
1325
+ * this method will return -1 to indicate failure. (This is not uncommon when
1326
+ * working with existing palette-based PNG files that already use 256 colors.)
1327
+ * Note that this method does not check for existing colors that match your
1328
+ * request; see Image.color_exact and Image.color_closest
1329
+ * for ways to locate existing colors that approximate the color desired in
1330
+ * situations where a new color is not available.Also see
1331
+ * Image.color_resolve.
1332
+ */
1333
+ static VALUE image_color_allocate(int argc, VALUE *argv, VALUE klass) {
1334
+ return gd_image_color_func_alpha(argc, argv, klass, gdImageColorAllocateAlpha);
1335
+ }
1336
+
1337
+ /*
1338
+ * call-seq:
1339
+ * color_closest(args)
1340
+ *
1341
+ * Read Image.color_allocate for more about args.
1342
+ *
1343
+ * Searches the colors which have been defined thus far in the image specified
1344
+ * and returns the index of the color with RGB values closest to those of the
1345
+ * request. (Closeness is determined by Euclidian distance, which is used to
1346
+ * determine the distance in three-dimensional color space between colors.)
1347
+ *
1348
+ * If no colors have yet been allocated in the image, this method returns -1.
1349
+ * When applied to a truecolor image, this function always succeeds in
1350
+ * returning the desired color.
1351
+ *
1352
+ * This function is most useful as a backup method for choosing a drawing color
1353
+ * when an image already contains MAX_COLORS (256) colors and no more can be
1354
+ * allocated. (This is not uncommon when working with existing PNG files that
1355
+ * already use many colors.) See Image.color_exact for a method of
1356
+ * locating exact matches only.
1357
+ *
1358
+ */
1359
+ static VALUE image_color_closest(int argc, VALUE *argv, VALUE klass) {
1360
+ return gd_image_color_func_alpha(argc, argv, klass, gdImageColorClosestAlpha);
1361
+ }
1362
+
1363
+ /*
1364
+ * call-seq:
1365
+ * color_exact(args)
1366
+ *
1367
+ * Read Image.color_allocate for more about args.
1368
+ *
1369
+ * Searches the colors which have been defined thus far in the image specified
1370
+ * and returns the index of the color with RGBA values closest to those of the
1371
+ * request. (Closeness is determined by Euclidian distance, which is used to
1372
+ * determine the distance in four-dimensional color/alpha space between colors.)
1373
+ *
1374
+ * If no colors have yet been allocated in the image, this method returns -1.
1375
+ * When applied to a truecolor image, this function always succeeds in returning
1376
+ * the desired color.
1377
+ *
1378
+ * This function is most useful as a backup method for choosing a drawing color
1379
+ * when a palette-based image already contains MAX_COLORS (256) colors and no
1380
+ * more can be allocated. (This is not uncommon when working with existing
1381
+ * palette-based PNG files that already use many colors.)
1382
+ */
1383
+ static VALUE image_color_exact(int argc, VALUE *argv, VALUE klass) {
1384
+ return gd_image_color_func_alpha(argc, argv, klass, gdImageColorExactAlpha);
1385
+ }
1386
+
1387
+ /*
1388
+ * call-seq:
1389
+ * color_resolve(args)
1390
+ *
1391
+ * Read Image.color_allocate for more about args.
1392
+ *
1393
+ * Searches the colors which have been defined thus far in the image specified
1394
+ * and returns the index of the first color with RGBA values which exactly match
1395
+ * those of the request. If no allocated color matches the request precisely,
1396
+ * then thid medhos tries to allocate the exact color. If there is no space left
1397
+ * in the color table then this method returns the closest color (as in
1398
+ * Image.color_closest). This function always returns an index of a
1399
+ * color.
1400
+ *
1401
+ * When applied to a truecolor image, this function always succeeds in returning
1402
+ * the desired color.
1403
+ */
1404
+ static VALUE image_color_resolve(int argc, VALUE *argv, VALUE klass) {
1405
+ return gd_image_color_func_alpha(argc, argv, klass, gdImageColorResolveAlpha);
1406
+ }
1407
+
1408
+ static VALUE gd_X__gip2(VALUE klass, VALUE img2, void (GDFUNC *pfunc)(gdImagePtr, gdImagePtr)) {
1409
+ gdImagePtr im, im2;
1410
+ Data_Get_Struct(klass, gdImage, im);
1411
+ Data_Get_Struct(img2, gdImage, im2);
1412
+ (*pfunc)(im, im2);
1413
+ return klass;
1414
+ }
1415
+
1416
+ /*
1417
+ * call-seq:
1418
+ * brush = img
1419
+ *
1420
+ * A "brush" is an image used to draw wide, shaped strokes in another image.
1421
+ * Just as a paintbrush is not a single point, a brush image need not be a
1422
+ * single pixel. Any gd image can be used as a brush, and by setting the
1423
+ * transparent color index of the brush image with Image.transparent=, a brush
1424
+ * of any shape can be created. All line-drawing functions, such as Image.line,
1425
+ * Image.open_polygon and Image.polygon, will use the current brush if the
1426
+ * special "color" COLOR_BRUSHED or COLOR_STYLED_BRUSHED is used when calling
1427
+ * them.
1428
+ *
1429
+ * This method is used to specify the brush to be used in a particular image.
1430
+ * You can set any image to be the brush. If the brush image does not have the
1431
+ * same color map as the first image, any colors missing from the first image
1432
+ * will be allocated. If not enough colors can be allocated, the closest colors
1433
+ * already available will be used. This allows arbitrary PNGs to be used as
1434
+ * brush images. It also means, however, that you should not set a brush unless
1435
+ * you will actually use it; if you set a rapid succession of different brush
1436
+ * images, you can quickly fill your color map, and the results will not be
1437
+ * optimal.
1438
+ */
1439
+ static VALUE image_set_brush(VALUE klass, VALUE img2) {
1440
+ return gd_X__gip2(klass, img2, gdImageSetBrush);
1441
+ }
1442
+
1443
+ /*
1444
+ * call-seq:
1445
+ * tile = img
1446
+ *
1447
+ * A "tile" is an image used to fill an area with a repeated pattern. Any gd
1448
+ * image can be used as a tile, and by setting the transparent color index of
1449
+ * the tile image with Image.transparent=, a tile that allows certain parts of
1450
+ * the underlying area to shine through can be created. All region-filling
1451
+ * functions, such as Image.fill and Image.filled_polygon, will use the current
1452
+ * tile if the special "color" COLOR_TILED is used when calling them.
1453
+ *
1454
+ * This is method is used to specify the tile to be used in a particular image.
1455
+ * You can set any image to be the tile. If the tile image does not have the
1456
+ * same color map as the first image, any colors missing from the first image
1457
+ * will be allocated. If not enough colors can be allocated, the closest colors
1458
+ * already available will be used. This allows arbitrary PNGs to be used as tile
1459
+ * images. It also means, however, that you should not set a tile unless you
1460
+ * will actually use it; if you set a rapid succession of different tile images,
1461
+ * you can quickly fill your color map, and the results will not be optimal.
1462
+ */
1463
+ static VALUE image_set_tile(VALUE klass, VALUE img2) {
1464
+ return gd_X__gip2(klass, img2, gdImageSetTile);
1465
+ }
1466
+
1467
+ /*
1468
+ * call-seq:
1469
+ * copy_palette(src)
1470
+ *
1471
+ * Copies a palette from an image, attempting to match the colors in the target
1472
+ * image to the colors in the source palette.
1473
+ */
1474
+ static VALUE image_copy_palette(VALUE klass, VALUE img2) {
1475
+ return gd_X__gip2(klass, img2, gdImagePaletteCopy);
1476
+ }
1477
+
1478
+ // gd_X__gip2_H6
1479
+ /*
1480
+ * call-seq:
1481
+ * copy(src, dstX, dstY, srcX, srcY, w, h)
1482
+ *
1483
+ * Used to copy a rectangular portion of one image to another image. (For a way
1484
+ * of stretching or shrinking the image in the process, see
1485
+ * Image.copy_resized.)
1486
+ *
1487
+ * The dst argument is the destination image to which the region will be copied.
1488
+ * The src argument is the source image from which the region is copied. The
1489
+ * dstX and dstY arguments specify the point in the destination image to which
1490
+ * the region will be copied. The srcX and srcY arguments specify the upper left
1491
+ * corner of the region in the source image. The w and h arguments specify the
1492
+ * width and height of the region.
1493
+ *
1494
+ * When you copy a region from one location in an image to another location in
1495
+ * the same image, this method will perform as expected unless the regions
1496
+ * overlap, in which case the result is unpredictable.
1497
+ *
1498
+ * Important note on copying between images: since different images do not
1499
+ * necessarily have the same color tables, pixels are not simply set to the
1500
+ * same color index values to copy them. This method will attempt to find an
1501
+ * identical RGB value in the destination image for each pixel in the copied
1502
+ * portion of the source image by invoking Image.color_exact. If such a
1503
+ * value is not found, this method will attempt to allocate colors as needed
1504
+ * using Image.color_allocate. If both of these methods fail, this method
1505
+ * will invoke Image.color_closest to find the color in the destination
1506
+ * image which most closely approximates the color of the pixel being copied.
1507
+ */
1508
+ static VALUE image_copy(VALUE klass, VALUE srcImg, VALUE dstX, VALUE dstY, VALUE srcX, VALUE srcY, VALUE w, VALUE h) {
1509
+ gdImagePtr dst, src;
1510
+ Data_Get_Struct(klass, gdImage, dst);
1511
+ Data_Get_Struct(srcImg, gdImage, src);
1512
+ gdImageCopy(dst, src, NUM2INT(dstX), NUM2INT(dstY), NUM2INT(srcX), NUM2INT(srcY), NUM2INT(w), NUM2INT(h));
1513
+ return klass;
1514
+ }
1515
+
1516
+ static VALUE gd_X__gip2_H7(VALUE klass, VALUE img2, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e, VALUE f, VALUE g, void (GDFUNC *pfunc)(gdImagePtr, gdImagePtr, int, int, int, int, int, int, int)) {
1517
+ gdImagePtr im, im2;
1518
+ Data_Get_Struct(klass, gdImage, im);
1519
+ Data_Get_Struct(img2, gdImage, im2);
1520
+ (*pfunc)(im, im2, NUM2INT(a), NUM2INT(b), NUM2INT(c), NUM2INT(d), NUM2INT(e), NUM2INT(f), NUM2INT(g));
1521
+ return klass;
1522
+ }
1523
+
1524
+ /*
1525
+ * call-seq:
1526
+ * copy_merge(src, dstX, dstY, srcX, srcY, w, h, pct)
1527
+ *
1528
+ * This method is almost identical to GD::Image.copy, except that it 'merges'
1529
+ * the two images by an amount specified in the last parameter. If the last
1530
+ * parameter is 100, then it will function identically to GD::Image.copy - the
1531
+ * source image replaces the pixels in the destination.
1532
+ *
1533
+ * If, however, the pct parameter is less than 100, then the two images are
1534
+ * merged. With pct = 0, no action is taken.
1535
+ *
1536
+ * This feature is most useful to 'highlight' sections of an image by merging a
1537
+ * solid color with pct = 50:
1538
+ *
1539
+ * dst.copy_merge(src, 100, 200, 0, 0, 30, 50, 50)
1540
+ */
1541
+ static VALUE image_copy_merge(VALUE klass, VALUE srcImg, VALUE dstX, VALUE dstY, VALUE srcX, VALUE srcY, VALUE w, VALUE h, VALUE pct) {
1542
+ return gd_X__gip2_H7(klass, srcImg, dstX, dstY, srcX, srcY, w, h, pct, gdImageCopyMerge);
1543
+ }
1544
+
1545
+ /*
1546
+ * call-seq:
1547
+ * copy_merge_gray(src, dstX, dstY, srcX, srcY, w, h, pct)
1548
+ *
1549
+ * This method is almost identical to GD::Image.copy_merge, except that when
1550
+ * merging images it preserves the hue of the source by converting the
1551
+ * destination pixels to grey scale before the copy operation.
1552
+ */
1553
+ static VALUE image_copy_merge_gray(VALUE klass, VALUE srcImg, VALUE dstX, VALUE dstY, VALUE srcX, VALUE srcY, VALUE w, VALUE h, VALUE pct) {
1554
+ return gd_X__gip2_H7(klass, srcImg, dstX, dstY, srcX, srcY, w, h, pct, gdImageCopyMergeGray);
1555
+ }
1556
+
1557
+ static VALUE gd_X__gip2_H8(VALUE klass, VALUE img2, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e, VALUE f, VALUE g, VALUE h, void (GDFUNC *pfunc)(gdImagePtr, gdImagePtr, int, int, int, int, int, int, int, int)) {
1558
+ gdImagePtr im, im2;
1559
+ Data_Get_Struct(klass, gdImage, im);
1560
+ Data_Get_Struct(img2, gdImage, im2);
1561
+ (*pfunc)(im, im2, NUM2INT(a), NUM2INT(b), NUM2INT(c), NUM2INT(d), NUM2INT(e), NUM2INT(f), NUM2INT(g), NUM2INT(h));
1562
+ return klass;
1563
+ }
1564
+
1565
+ /*
1566
+ * call-seq:
1567
+ * copy_resized(src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH)
1568
+ *
1569
+ * Used to copy a rectangular portion of one image to another image. The X and Y
1570
+ * dimensions of the original region and the destination region can vary,
1571
+ * resulting in stretching or shrinking of the region as appropriate. (For a
1572
+ * simpler version of this function which does not deal with resizing,
1573
+ * see Image.copy.)
1574
+ *
1575
+ * The dst argument is the destination image to which the region will be copied.
1576
+ * The src argument is the source image from which the region is copied. The
1577
+ * dstX and dstY arguments specify the point in the destination image to which
1578
+ * the region will be copied. The srcX and srcY arguments specify the upper left
1579
+ * corner of the region in the source image. The dstW and dstH arguments specify
1580
+ * the width and height of the destination region. The srcW and srcH arguments
1581
+ * specify the width and height of the source region and can differ from the
1582
+ * destination size, allowing a region to be scaled during the copying process.
1583
+ *
1584
+ * When you copy a region from one location in an image to another location in
1585
+ * the same image, Image.copy will perform as expected unless the regions
1586
+ * overlap, in which case the result is unpredictable. If this presents a
1587
+ * problem, create a scratch image in which to keep intermediate results.
1588
+ *
1589
+ * Important note on copying between images: since images do not necessarily
1590
+ * have the same color tables, pixels are not simply set to the same color index
1591
+ * values to copy them. Image.copy will attempt to find an identical RGB
1592
+ * value in the destination image for each pixel in the copied portion of the
1593
+ * source image by invoking Image.color_exact. If such a value is not
1594
+ * found, Image.copy will attempt to allocate colors as needed
1595
+ * using Image.color_allocate. If both of these methods fail,
1596
+ * Image.copy will invoke Image.color_closest to find the color in the
1597
+ * destination image which most closely approximates the color of the pixel
1598
+ * being copied.
1599
+
1600
+ */
1601
+ static VALUE image_copy_resized(VALUE klass, VALUE srcImg, VALUE dstX, VALUE dstY, VALUE srcX, VALUE srcY, VALUE dstW, VALUE dstH, VALUE srcW, VALUE srcH) {
1602
+ return gd_X__gip2_H8(klass, srcImg, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH, gdImageCopyResized);
1603
+ }
1604
+
1605
+ /*
1606
+ * call-seq:
1607
+ * copy_resampled(src, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH)
1608
+ *
1609
+ * Used to copy a rectangular portion of one image to another image, smoothly
1610
+ * interpolating pixel values so that, in particular, reducing the size of an
1611
+ * image still retains a great deal of clarity. The X and Y dimensions of the
1612
+ * original region and the destination region can vary, resulting in stretching
1613
+ * or shrinking of the region as appropriate. (For a simpler version of this
1614
+ * function which does not deal with resizing, see GD::Image.copy. For a version
1615
+ * which does not interpolate pixel values, see GD::Image.copy_resized.
1616
+ *
1617
+ * Pixel values are only interpolated if the destination image is a truecolor
1618
+ * image. Otherwise, GD::Image.copy_resized is automatically invoked.
1619
+ *
1620
+ * The dst argument is the destination image to which the region will be copied.
1621
+ * The src argument is the source image from which the region is copied. The
1622
+ * dstX and dstY arguments specify the point in the destination image to which
1623
+ * the region will be copied. The srcX and srcY arguments specify the upper left
1624
+ * corner of the region in the source image. The dstW and dstH arguments specify
1625
+ * the width and height of the destination region. The srcW and srcH arguments
1626
+ * specify the width and height of the source region and can differ from the
1627
+ * destination size, allowing a region to be scaled during the copying process.
1628
+ *
1629
+ * When you copy a region from one location in an image to another location in
1630
+ * the same image, GD::Image.copy will perform as expected unless the regions
1631
+ * overlap, in which case the result is unpredictable. If this presents a
1632
+ * problem, create a scratch image in which to keep intermediate results.
1633
+ *
1634
+ * Important note on copying between images: since images do not necessarily
1635
+ * have the same color tables, pixels are not simply set to the same color
1636
+ * index values to copy them. If the destination image is a palette image,
1637
+ * gd will use the Image.color_resolve function to determine the best color
1638
+ * available.
1639
+ */
1640
+ static VALUE image_copy_resampled(VALUE klass, VALUE srcImg, VALUE dstX, VALUE dstY, VALUE srcX, VALUE srcY, VALUE dstW, VALUE dstH, VALUE srcW, VALUE srcH) {
1641
+ return gd_X__gip2_H8(klass, srcImg, dstX, dstY, srcX, srcY, dstW, dstH, srcW, srcH, gdImageCopyResampled);
1642
+ }
1643
+
1644
+ // gd_X__gip2_N2_H5
1645
+ /*
1646
+ * call-seq:
1647
+ * copy_rotated(src, dstX, dstY, srcX, srcY, srcW, srcH, angle)
1648
+ *
1649
+ * Used to copy a rectangular portion of one image to another image, or to
1650
+ * another region of the same image. The srcX and srcY coordinates specify the
1651
+ * upper left corner of the source area; however, the dstX and dstY coordinates
1652
+ * specify the CENTER of the destination area. This important distinction is
1653
+ * made because the rotated rectangle may may or may not be parallel to the X
1654
+ * and Y axes. The destination coordinates may be floating point, as the center
1655
+ * of the desired destination area may lie at the center of a pixel (0.5 pixels)
1656
+ * rather than its upper left corner. The angle specified is an integer number
1657
+ * of degrees, between 0 and 360, with 0 degrees causing no change, and
1658
+ * counterclockwise rotation as the angle increases.
1659
+ *
1660
+ * When you copy a region from one location in an image to another location in
1661
+ * the same image, this method will perform as expected unless the regions
1662
+ * overlap, in which case the result is unpredictable. If this presents a
1663
+ * problem, create a scratch image in which to keep intermediate results.
1664
+ *
1665
+ * Important note on copying between images: since palette-based images do not
1666
+ * necessarily have the same color tables, pixels are not simply set to the same
1667
+ * color index values to copy them. If the destination image is not a truecolor
1668
+ * image, Image.color_resolve is used to choose the destination pixel.
1669
+ */
1670
+ static VALUE image_copy_rotated(VALUE klass, VALUE srcImg, VALUE dstX, VALUE dstY, VALUE srcX, VALUE srcY, VALUE srcW, VALUE srcH, VALUE angle) {
1671
+ gdImagePtr dst, src;
1672
+ Data_Get_Struct(klass, gdImage, dst);
1673
+ Data_Get_Struct(srcImg, gdImage, src);
1674
+ gdImageCopyRotated(dst, src, NUM2DBL(dstX), NUM2DBL(dstY), NUM2INT(srcX), NUM2INT(srcY), NUM2INT(srcW), NUM2INT(srcH), NUM2INT(angle));
1675
+ return klass;
1676
+ }
1677
+
1678
+ static VALUE gd_X__gip_H(VALUE klass, VALUE a, void (GDFUNC *pfunc)(gdImagePtr, int)) {
1679
+ gdImagePtr im;
1680
+ Data_Get_Struct(klass, gdImage, im);
1681
+ (*pfunc)(im, NUM2INT(a));
1682
+ return a;
1683
+ }
1684
+
1685
+ /*
1686
+ * call-seq:
1687
+ * interlace = boolean
1688
+ *
1689
+ * Used to determine whether an image should be stored in a linear fashion, in
1690
+ * which lines will appear on the display from first to last, or in an
1691
+ * interlaced fashion, in which the image will "fade in" over several passes.
1692
+ * By default, images are not interlaced. (When writing JPEG images, interlacing
1693
+ * implies generating progressive JPEG files, which are represented as a series
1694
+ * of scans of increasing quality. Noninterlaced gd images result in regular
1695
+ * (sequential) JPEG data streams.)
1696
+ *
1697
+ * Note that interlace has no effect on other functions, and has no meaning
1698
+ * unless you save the image in PNG or JPEG format.
1699
+ */
1700
+ static VALUE image_interlace_set(VALUE klass, VALUE interlace) {
1701
+ return gd_X__gip_H(klass, RTEST(interlace) ? INT2NUM(1) : INT2NUM(0), gdImageInterlace);
1702
+ }
1703
+
1704
+ /*
1705
+ * call-seq:
1706
+ * antialiased = color
1707
+ *
1708
+ * "Antialiasing" is a process by which jagged edges associated with line
1709
+ * drawing can be reduced by blending the foreground color with an appropriate
1710
+ * percentage of the background, depending on how much of the pixel in question
1711
+ * is actually within the boundaries of the line being drawn. All line-drawing
1712
+ * functions, such as Image.line, Image.open_polygon and Image.polygon, will
1713
+ * draw antialiased lines if the special "color" COLOR_ANTIALIASED is used when
1714
+ * calling them.
1715
+ *
1716
+ * this method is used to specify the actual foreground color to be used when
1717
+ * drawing antialiased lines. You may set any color to be the foreground,
1718
+ * however as of version 2.0.12 an alpha channel component is not supported.
1719
+ *
1720
+ * Antialiased lines can be drawn on both truecolor and palette-based images.
1721
+ * However, attempts to draw antialiased lines on highly complex palette-based
1722
+ * backgrounds may not give satisfactory results, due to the limited number of
1723
+ * colors available in the palette. Antialiased line-drawing on simple
1724
+ * backgrounds should work well with palette-based images; otherwise create or
1725
+ * fetch a truecolor image instead.
1726
+ */
1727
+ static VALUE image_set_antialiased(VALUE klass, VALUE color){
1728
+ return gd_X__gip_H(klass, color, gdImageSetAntiAliased);
1729
+ }
1730
+
1731
+ /*
1732
+ * call-seq:
1733
+ * thickness = width
1734
+ *
1735
+ * This method determines the width of lines drawn by the Image.line,
1736
+ * Image.polygon, Image.open_polygon and related methods, in pixels.
1737
+ */
1738
+ static VALUE image_set_thickness(VALUE klass, VALUE thickness) {
1739
+ return gd_X__gip_H(klass, thickness, gdImageSetThickness);
1740
+ }
1741
+
1742
+ /*
1743
+ * call-seq:
1744
+ * alpha_blending = boolean
1745
+ *
1746
+ * This method allows for two different modes of drawing on truecolor images. In
1747
+ * blending mode, which is on by default (gd 2.0.2 and above), the alpha channel
1748
+ * component of the color supplied to all drawing functions, such as
1749
+ * Image.pixels[]=, determines how much of the underlying color should be
1750
+ * allowed to shine through. As a result, gd automatically blends the existing
1751
+ * color at that point with the drawing color, and stores the result in the
1752
+ * image. The resulting pixel is opaque. In non-blending mode, the drawing color
1753
+ * is copied literally with its alpha channel information, replacing the
1754
+ * destination pixel. Blending mode is not available when drawing on palette
1755
+ * images.
1756
+ */
1757
+ static VALUE image_set_alpha_blending(VALUE klass, VALUE blending) {
1758
+ return gd_X__gip_H(klass, RTEST(blending) ? INT2NUM(1) : INT2NUM(0) , gdImageAlphaBlending);
1759
+ }
1760
+
1761
+ /*
1762
+ * call-seq:
1763
+ * save_alpha = boolean
1764
+ *
1765
+ * By default, gd 2.0.2 and above do not attempt to save full alpha channel
1766
+ * information (as opposed to single-color transparency) when saving PNG images.
1767
+ * (PNG is currently the only output format supported by gd which can
1768
+ * accommodate alpa channel information.) This saves space in the output file.
1769
+ * If you wish to create an image with alpha channel information for use with
1770
+ * tools that support it, set save_alpha=true to turn on saving of such
1771
+ * information, and set alpha_blending=false to turn off alpha blending within
1772
+ * the library so that alpha channel information is actually stored in the image
1773
+ * rather than being composited immediately at the time that drawing functions
1774
+ * are invoked.
1775
+ */
1776
+ static VALUE image_save_alpha(VALUE klass, VALUE save) {
1777
+ return gd_X__gip_H(klass, RTEST(save) ? INT2NUM(1) : INT2NUM(0), gdImageSaveAlpha);
1778
+ }
1779
+
1780
+ /*
1781
+ * call-seq:
1782
+ * transparent = color
1783
+ *
1784
+ * Set the transparent color index for the specified image to the specified
1785
+ * index. To indicate that there should be no transparent color, invoke this
1786
+ * method with a color index of -1. Note that JPEG images do not support
1787
+ * transparency, so this setting has no effect when writing JPEG images.
1788
+ *
1789
+ * The color index used should be an index allocated by Image.color_allocate,
1790
+ * whether explicitly invoked by your code or implicitly invoked by loading an
1791
+ * image. In order to ensure that your image has a reasonable appearance when
1792
+ * viewed by users who do not have transparent background capabilities (or when
1793
+ * you are writing a JPEG-format file, which does not support transparency), be
1794
+ * sure to give reasonable RGB values to the color you allocate for use as a
1795
+ * transparent color, even though it will be transparent on systems that support
1796
+ * PNG transparency.
1797
+ */
1798
+ static VALUE image_color_transparent(VALUE klass, VALUE color) {
1799
+ return gd_X__gip_H(klass, color, gdImageColorTransparent);
1800
+ }
1801
+
1802
+ /*
1803
+ * call-seq:
1804
+ * color_deallocate(color)
1805
+ *
1806
+ * Marks the specified color as being available for reuse. It does not attempt
1807
+ * to determine whether the color index is still in use in the image. After a
1808
+ * call to this function, the next call to Image.color_allocate for the same
1809
+ * image will set new RGB values for that color index, changing the color of any
1810
+ * pixels which have that index as a result. If multiple calls to this method
1811
+ * are made consecutively, the lowest-numbered index among them will be reused
1812
+ * by the next Image.color_allocate call.
1813
+ */
1814
+ static VALUE image_color_deallocate(VALUE klass, VALUE color) {
1815
+ return gd_X__gip_H(klass, color, gdImageColorDeallocate);
1816
+ }
1817
+
1818
+ /*
1819
+ * call-seq:
1820
+ * sharepen(pct)
1821
+ *
1822
+ * Sharpens the specified image. pct is a sharpening percentage, and can be
1823
+ * greater than 100. Silently does nothing to non-truecolor images. Silently
1824
+ * does nothing for pct<0. Transparency/alpha channel are not altered.
1825
+ */
1826
+ static VALUE image_sharepen(VALUE klass, VALUE pct) {
1827
+ return gd_X__gip_H(klass, pct, gdImageSharpen);
1828
+ }
1829
+
1830
+ static VALUE gd_X__gip_H2(VALUE klass, VALUE a, VALUE b, void (GDFUNC *pfunc)(gdImagePtr, int, int)) {
1831
+ gdImagePtr im;
1832
+ Data_Get_Struct(klass, gdImage, im);
1833
+ (*pfunc)(im, NUM2INT(a), NUM2INT(b));
1834
+ return klass;
1835
+ }
1836
+
1837
+ /*
1838
+ * call-seq:
1839
+ * to_palette!(dither = true, colors = MAX_COLORS)
1840
+ *
1841
+ * Convert a truecolor image to a palette-based image, using a high-quality
1842
+ * two-pass quantization routine.
1843
+ *
1844
+ * If _dither_ is true, the image will be dithered to approximate colors better,
1845
+ * at the expense of some obvious "speckling." _colors_ can be anything up to 256.
1846
+ * If the original source image includes photographic information or
1847
+ * anything that came out of a JPEG, 256 is strongly recommended. 100%
1848
+ * transparency of a single transparent color in the original truecolor image
1849
+ * will be preserved. There is no other support for preservation of alpha
1850
+ * channel or transparency in the destination image.
1851
+ */
1852
+ static VALUE image_truecolor_to_palette(int argc, VALUE* argv, VALUE klass) {
1853
+ VALUE dither, colors;
1854
+
1855
+ if (image_is_truecolor(klass) == Qfalse) return klass;
1856
+
1857
+ rb_scan_args(argc, argv, "02", &dither, &colors);
1858
+ return gd_X__gip_H2(klass,
1859
+ (dither == Qnil || dither == Qtrue ? INT2NUM(1) : INT2NUM(0)),
1860
+ (colors == Qnil ? INT2NUM(gdMaxColors) : colors),
1861
+ gdImageTrueColorToPalette);
1862
+ }
1863
+
1864
+ /*
1865
+ * call-seq:
1866
+ * antialiased_dont_blend(color, boolean)
1867
+ *
1868
+ * Normally, when drawing lines with the special COLOR_ANTIALIASED "color,"
1869
+ * blending with the background to reduce jagged edges is the desired behavior.
1870
+ * However, when it is desired that lines not be blended with one particular
1871
+ * color when it is encountered in the background, this method can be used to
1872
+ * indicate the special color that the foreground should stand out more clearly
1873
+ * against.
1874
+ */
1875
+ static VALUE image_set_antialiased_dont_blend(VALUE klass, VALUE color, VALUE dont_blend) {
1876
+ return gd_X__gip_H2(klass, color, RTEST(dont_blend) ? INT2NUM(1) : INT2NUM(0), gdImageSetAntiAliasedDontBlend);
1877
+ }
1878
+
1879
+ static VALUE gd_X__gip_H3(VALUE klass, VALUE a, VALUE b, VALUE c, void (GDFUNC *pfunc)(gdImagePtr, int, int, int)) {
1880
+ gdImagePtr im;
1881
+ Data_Get_Struct(klass, gdImage, im);
1882
+ (*pfunc)(im, NUM2INT(a), NUM2INT(b), NUM2INT(c));
1883
+ return klass;
1884
+ }
1885
+
1886
+ /*
1887
+ * call-seq:
1888
+ * slef[x, y] = color
1889
+ *
1890
+ * Sets a pixel to a particular color index.
1891
+ */
1892
+ static VALUE image_set_pixel(VALUE klass, VALUE x, VALUE y, VALUE color) {
1893
+ return gd_X__gip_H3(klass, x, y, color, gdImageSetPixel);
1894
+ }
1895
+
1896
+ /*
1897
+ * call-seq:
1898
+ * fill(x, y, color)
1899
+ *
1900
+ * Floods a portion of the image with the specified color, beginning at the
1901
+ * specified point and flooding the surrounding region of the same color as the
1902
+ * starting point. For a way of flooding a region defined by a specific border
1903
+ * color rather than by its interior color, see Image.fill_to_border.
1904
+ *
1905
+ * The fill color can be COLOR_TILED, resulting in a tile fill using another
1906
+ * image as the tile. However, the tile image cannot be transparent. If the
1907
+ * image you wish to fill with has a transparent color index, call
1908
+ * Image.transparent= and set the transparent color index to -1 to turn off its
1909
+ * transparency.
1910
+ *
1911
+ * Note, this method is recursive. It is not the most naive implementation
1912
+ * possible, and the implementation is expected to improve, but there will
1913
+ * always be degenerate cases in which the stack can become very deep. This can
1914
+ * be a problem in MSDOS and MS Windows environments. (Of course, in a Unix or
1915
+ * Windows 95/98/NT environment with a proper stack, this is not a problem at
1916
+ * all.)
1917
+ */
1918
+ static VALUE image_fill(VALUE klass, VALUE x, VALUE y, VALUE color) {
1919
+ return gd_X__gip_H3(klass, x, y, color, gdImageFill);
1920
+ }
1921
+
1922
+ static VALUE gd_X__gip_H4(VALUE klass, VALUE a, VALUE b, VALUE c, VALUE d, void (GDFUNC *pfunc)(gdImagePtr, int, int, int, int)) {
1923
+ gdImagePtr im;
1924
+ Data_Get_Struct(klass, gdImage, im);
1925
+ (*pfunc)(im, NUM2INT(a), NUM2INT(b), NUM2INT(c), NUM2INT(d));
1926
+ return klass;
1927
+ }
1928
+
1929
+ /*
1930
+ * call-seq:
1931
+ * fill_to_border(x, y, border, color)
1932
+ *
1933
+ * Floods a portion of the image with the specified color, beginning at the
1934
+ * specified point and stopping at the specified border color. For a way of
1935
+ * flooding an area defined by the color of the starting point, see Image.fill.
1936
+ *
1937
+ * The border color cannot be a special color such as COLOR_TILED; it must be a
1938
+ * proper solid color. The fill color can be, however.
1939
+ *
1940
+ * Note, this method is recursive. It is not the most naive implementation
1941
+ * possible, and the implementation is expected to improve, but there will
1942
+ * always be degenerate cases in which the stack can become very deep. This can
1943
+ * be a problem in MSDOS and MS Windows 3.1 environments. (Of course, in a Unix
1944
+ * or Windows 95/98/NT environment with a proper stack, this is not a problem at
1945
+ * all.)
1946
+ */
1947
+ static VALUE image_fill_to_border(VALUE klass, VALUE x, VALUE y, VALUE border, VALUE color) {
1948
+ return gd_X__gip_H4(klass, x, y, border, color, gdImageFillToBorder);
1949
+ }
1950
+
1951
+ /*
1952
+ * call-seq:
1953
+ * clip = x1, y1, x2, y2
1954
+ *
1955
+ * Establishes a clipping rectangle. Once this method has been called, all
1956
+ * future drawing operations will remain within the specified clipping area,
1957
+ * until a new call takes place. For instance, if a clipping rectangle
1958
+ * of 25, 25, 75, 75 has been set within a 100x100 image, a diagonal line
1959
+ * from 0,0 to 99,99 will appear only between 25,25 and 75,75.
1960
+ *
1961
+ * If this method is never called, the clipping area will be the entire image.
1962
+ *
1963
+ * The parameters passed in are checked against the dimensions of the image and
1964
+ * limited to "safe" values.
1965
+ */
1966
+ static VALUE image_set_clip(VALUE klass, VALUE x1, VALUE y1, VALUE x2, VALUE y2) {
1967
+ return gd_X__gip_H4(klass, x1, y1, x2, y2, gdImageSetClip);
1968
+ }
1969
+
1970
+ static VALUE gd_X__gip_H5(VALUE klass, VALUE a, VALUE b, VALUE c, VALUE d, VALUE e, void (GDFUNC *pfunc)(gdImagePtr, int, int, int, int, int)) {
1971
+ gdImagePtr im;
1972
+ Data_Get_Struct(klass, gdImage, im);
1973
+ (*pfunc)(im, NUM2INT(a), NUM2INT(b), NUM2INT(c), NUM2INT(d), NUM2INT(e));
1974
+ return klass;
1975
+ }
1976
+
1977
+ /*
1978
+ * call-seq:
1979
+ * line(x1, y1, x2, y2, color)
1980
+ *
1981
+ * Used to draw a line between two endpoints (x1,y1 and x2, y2). The line is
1982
+ * drawn using the color index specified. Note that the color index can be an
1983
+ * actual color returned by Image.color_allocate or one of COLOR_STYLED,
1984
+ * COLOR_BRUSHED or COLOR_STYLED_BRUSHED.
1985
+ */
1986
+ static VALUE image_line(VALUE klass, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE color) {
1987
+ return gd_X__gip_H5(klass, x1, y1, x2, y2, color, gdImageLine);
1988
+ }
1989
+
1990
+ /*
1991
+ * call-seq:
1992
+ * dashed_line(x1, y1, x2, y2, color)
1993
+ *
1994
+ * Provided solely for backwards compatibility with gd 1.0. New programs should
1995
+ * draw dashed lines using the normal Image.line and the new Image.set_style.
1996
+ *
1997
+ * This method is used to draw a dashed line between two endpoints (x1,y1 and
1998
+ * x2, y2). The line is drawn using the color index specified. The portions of
1999
+ * the line that are not drawn are left transparent so the background is
2000
+ * visible.
2001
+ */
2002
+ static VALUE image_dashed_line(VALUE klass, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE color) {
2003
+ return gd_X__gip_H5(klass, x1, y1, x2, y2, color, gdImageDashedLine);
2004
+ }
2005
+
2006
+ /*
2007
+ * call-seq:
2008
+ * rectangle(x1, y1, x2, y2, color)
2009
+ *
2010
+ * Used to draw a rectangle with the two corners (upper left first, then lower
2011
+ * right) specified, using the color index specified.
2012
+ */
2013
+ static VALUE image_rectangle(VALUE klass, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE color) {
2014
+ return gd_X__gip_H5(klass, x1, y1, x2, y2, color, gdImageRectangle);
2015
+ }
2016
+
2017
+ /*
2018
+ * call-seq:
2019
+ * filled_rectangle(x1, y1, x2, y2, color)
2020
+ *
2021
+ * Used to fill a polygon with the verticies (at least 3) specified, using the
2022
+ * color index specified. See also Image.polygon.
2023
+ */
2024
+ static VALUE image_filled_rectangle(VALUE klass, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE color) {
2025
+ return gd_X__gip_H5(klass, x1, y1, x2, y2, color, gdImageFilledRectangle);
2026
+ }
2027
+
2028
+ /*
2029
+ * call-seq:
2030
+ * filled_ellipse(x1, y1, x2, y2, color)
2031
+ *
2032
+ * Used to draw an ellipse centered at the given point, with the specified width
2033
+ * and height in pixels. The ellipse is filled in the color specified by the
2034
+ * last argument.
2035
+ */
2036
+ static VALUE image_filled_ellipse(VALUE klass, VALUE x1, VALUE y1, VALUE x2, VALUE y2, VALUE color) {
2037
+ return gd_X__gip_H5(klass, x1, y1, x2, y2, color, gdImageFilledEllipse);
2038
+ }
2039
+
2040
+ // gd_X__gip_H7
2041
+ /*
2042
+ * call-seq:
2043
+ * arc(cx, cy, w, h, s, e, color)
2044
+ *
2045
+ * Used to draw a partial ellipse centered at the given point, with the
2046
+ * specified width and height in pixels. The arc begins at the position in
2047
+ * degrees specified by _s_ and ends at the position specified by _e_. The arc
2048
+ * is drawn in the color specified by the last argument. A circle can be drawn
2049
+ * by beginning from 0 degrees and ending at 360 degrees, with width and height
2050
+ * being equal. _e_ must be greater than _s_. Values greater than 360 are
2051
+ * interpreted modulo 360.
2052
+ */
2053
+ static VALUE image_arc(VALUE klass, VALUE cx, VALUE cy, VALUE w, VALUE h, VALUE s, VALUE e, VALUE color) {
2054
+ gdImagePtr im;
2055
+ Data_Get_Struct(klass, gdImage, im);
2056
+ gdImageArc(im, NUM2INT(cx), NUM2INT(cy), NUM2INT(w), NUM2INT(h), NUM2INT(s), NUM2INT(e), NUM2INT(color));
2057
+ }
2058
+
2059
+ // gd_X__gip_H8
2060
+ /*
2061
+ * call-seq:
2062
+ * filled_arc(cx, cy, w, h, s, e, color, style)
2063
+ *
2064
+ * Used to draw a partial ellipse centered at the given point, with the
2065
+ * specified width and height in pixels. The arc begins at the position in
2066
+ * degrees specified by _s_ and ends at the position specified by _e_. The arc
2067
+ * is filled in the color specified by the second to last argument. A circle can
2068
+ * be drawn by beginning from 0 degrees and ending at 360 degrees, with width
2069
+ * and height being equal. _e_ must be greater than _s_. Values greater than 360
2070
+ * are interpreted modulo 360. The last argument is a bitwise OR of the
2071
+ * following possibilities:
2072
+ *
2073
+ * * STYLE_ARC
2074
+ * * STYLE_CHORD
2075
+ * * STYLE_PIE (synonym for STYLE_CHORD)
2076
+ * * STYLE_NO_FILL
2077
+ * * STYLE_EDGED
2078
+ *
2079
+ * STYLE_ARC and STYLE_CHORD are mutually exclusive; STYLE_CHORD just connects
2080
+ * the starting and ending angles with a straight line, while STYLE_ARC produces
2081
+ * a rounded edge. STYLE_PIE is a synonym for STYLE_ARC. STYLE_NO_FILL indicates
2082
+ * that the arc or chord should be outlined, not filled. STYLE_EDGED, used
2083
+ * together with STYLE_NO_FILL, indicates that the beginning and ending angles
2084
+ * should be connected to the center; this is a good way to outline (rather than
2085
+ * fill) a 'pie slice'.
2086
+ *
2087
+ */
2088
+ static VALUE image_filled_arc(VALUE klass, VALUE cx, VALUE cy, VALUE w, VALUE h, VALUE s, VALUE e, VALUE color, VALUE style) {
2089
+ gdImagePtr im;
2090
+ Data_Get_Struct(klass, gdImage, im);
2091
+ gdImageFilledArc(im, NUM2INT(cx), NUM2INT(cy), NUM2INT(w), NUM2INT(h), NUM2INT(s), NUM2INT(e), NUM2INT(color), NUM2INT(style));
2092
+ }
2093
+
2094
+ // gd_X__gip_PAH4
2095
+ /*
2096
+ * call-seq:
2097
+ * x1, y1, x2, y2 = clip
2098
+ *
2099
+ * Fetches the boundaries of the current clipping rectangle.
2100
+ */
2101
+ static VALUE image_get_clip(VALUE klass) {
2102
+ int x1, y1, x2, y2;
2103
+ gdImagePtr im;
2104
+ Data_Get_Struct(klass, gdImage, im);
2105
+ gdImageGetClip(im, &x1, &y1, &x2, &y2);
2106
+ return rb_ary_new3(4, INT2NUM(x1), INT2NUM(y1), INT2NUM(x2), INT2NUM(y2));
2107
+ }
2108
+
2109
+ // gd_X__gip_PAH_H
2110
+ /*
2111
+ * call-seq:
2112
+ * styles = array
2113
+ *
2114
+ * It is often desirable to draw dashed lines, dotted lines, and other
2115
+ * variations on a broken line. This method can be used to set any desired
2116
+ * series of colors, including a special color that leaves the background
2117
+ * intact, to be repeated during the drawing of a line.
2118
+ *
2119
+ * To use this method, create an array of integers and assign them the desired
2120
+ * series of color values to be repeated. You can assign the special color value
2121
+ * COLOR_TRANSPARENT to indicate that the existing color should be left
2122
+ * unchanged for that particular pixel (allowing a dashed line to be
2123
+ * attractively drawn over an existing image).
2124
+ *
2125
+ * Then, to draw a line using the style, use the normal Image.line with the
2126
+ * special color value COLOR_STYLED.
2127
+ *
2128
+ * You can also combine styles and brushes to draw the brush image at intervals
2129
+ * instead of in a continuous stroke. When creating a style for use with a
2130
+ * brush, the style values are interpreted differently: zero (0) indicates
2131
+ * pixels at which the brush should not be drawn, while one (1) indicates pixels
2132
+ * at which the brush should be drawn. To draw a styled, brushed line, you must
2133
+ * use the special color value COLOR_STYLED_BRUSHED.
2134
+ */
2135
+ static VALUE image_set_style(VALUE klass, VALUE styles) {
2136
+ gdImagePtr im;
2137
+ int *ary;
2138
+ int i, len;
2139
+
2140
+ Check_Type(styles, T_ARRAY);
2141
+ len = RARRAY_LEN(styles);
2142
+ ary = malloc(sizeof(int) * len);
2143
+ for (i=0;i<len;i++) ary[i] = NUM2INT(rb_ary_entry(styles, i));
2144
+
2145
+ Data_Get_Struct(klass, gdImage, im);
2146
+ gdImageSetStyle(im, ary, len);
2147
+ free(ary);
2148
+ return klass;
2149
+ }
2150
+
2151
+ static VALUE gd_X__gip_gptp_H2(VALUE klass, VALUE points, VALUE color, void (GDFUNC *pfunc)(gdImagePtr, gdPointPtr, int, int)) {
2152
+ gdImagePtr im;
2153
+ gdPointPtr ary;
2154
+ int i, len;
2155
+ VALUE t;
2156
+
2157
+ Check_Type(points, T_ARRAY);
2158
+ Check_Type(color, T_FIXNUM);
2159
+ Data_Get_Struct(klass, gdImage, im);
2160
+ len = RARRAY_LEN(points);
2161
+ ary = malloc(sizeof(gdPoint) * len);
2162
+ for (i=0;i<len;i++) {
2163
+ t = rb_ary_entry(points, i);
2164
+ if (TYPE(t) == T_ARRAY && RARRAY_LEN(t) >= 2 && TYPE(rb_ary_entry(t, 0)) == T_FIXNUM && TYPE(rb_ary_entry(t, 1)) == T_FIXNUM) {
2165
+ ary[i].x = NUM2INT(rb_ary_entry(t, 0));
2166
+ ary[i].y = NUM2INT(rb_ary_entry(t, 1));
2167
+ } else {
2168
+ free(ary);
2169
+ rb_raise(rb_eArgError, "array of points please.");
2170
+ }
2171
+ }
2172
+ (*pfunc)(im, ary, len, NUM2INT(color));
2173
+ free(ary);
2174
+ return klass;
2175
+ }
2176
+
2177
+ /*
2178
+ * call-seq:
2179
+ * polygon(points, color)
2180
+ *
2181
+ * Used to draw a polygon with the verticies (at least 3) specified, using the
2182
+ * color index specified. _points_ is an array looks like [[1, 1], [2, 2], [3, 3]].
2183
+ *
2184
+ * See also Image.filled_polygon.
2185
+ */
2186
+ static VALUE image_polygon(VALUE klass, VALUE points, VALUE color) {
2187
+ return gd_X__gip_gptp_H2(klass, points, color, gdImagePolygon);
2188
+ }
2189
+
2190
+ /*
2191
+ * call-seq:
2192
+ * open_polygon(points, color)
2193
+ *
2194
+ * Used to draw a sequence of lines with the verticies (at least 3) specified,
2195
+ * using the color index specified. _points_ is an array looks
2196
+ * like [[1, 1], [2, 2], [3, 3]]. Unlike Image.polygon, the enpoints of the line
2197
+ * sequence are not connected to a closed polygon.
2198
+ */
2199
+ static VALUE image_open_polygon(VALUE klass, VALUE points, VALUE color) {
2200
+ return gd_X__gip_gptp_H2(klass, points, color, gdImageOpenPolygon);
2201
+ }
2202
+
2203
+ /*
2204
+ * call-seq:
2205
+ * filled_polygon(points, color)
2206
+ *
2207
+ * Used to fill a polygon with the verticies (at least 3) specified, using the
2208
+ * color index specified. _points_ is an array looks like [[1, 1], [2, 2], [3, 3]].
2209
+ *
2210
+ * See also Image.polygon.
2211
+ */
2212
+ static VALUE image_filled_polygon(VALUE klass, VALUE points, VALUE color) {
2213
+ return gd_X__gip_gptp_H2(klass, points, color, gdImageFilledPolygon);
2214
+ }
2215
+
2216
+ // gd_X__gip
2217
+ /*
2218
+ * call-seq:
2219
+ * aa_blend()
2220
+ *
2221
+ * TODO: document for aa_blend.
2222
+ */
2223
+ static VALUE image_aa_blend(VALUE klass) {
2224
+ gdImagePtr im;
2225
+ Data_Get_Struct(klass, gdImage, im);
2226
+ gdImageAABlend(im);
2227
+ return klass;
2228
+ }
2229
+
2230
+ // gd_X__gip_gfp_H2_PAE_H
2231
+ // TODO: gdImageString16 and gdImageStringUp16
2232
+ static VALUE gd_image_string(VALUE klass, VALUE font, VALUE x, VALUE y, VALUE str, VALUE color, void (GDFUNC *pfunc)(gdImagePtr, gdFontPtr, int, int, unsigned char*, int)) {
2233
+ gdImagePtr im;
2234
+ gdFontPtr ft;
2235
+ Data_Get_Struct(klass, gdImage, im);
2236
+ Data_Get_Struct(font, gdFont, ft);
2237
+ (*pfunc)(im, ft, NUM2INT(x), NUM2INT(y), RSTRING_PTR(str), NUM2INT(color));
2238
+ return klass;
2239
+ }
2240
+
2241
+ /*
2242
+ * call-seq:
2243
+ * string(font, x, y, str, color)
2244
+ *
2245
+ * Used to draw multiple characters on the image. (To draw single characters,
2246
+ * use #char.)
2247
+ *
2248
+ * The string specified by the fifth argument _str_ is drawn from left to right
2249
+ * in the specified _color_. (See #string_up for a way of drawing vertical text.
2250
+ * See also #stringft for a high quality solution.) Pixels not set by a
2251
+ * particular character retain their previous color.
2252
+ */
2253
+ static VALUE image_string(VALUE klass, VALUE font, VALUE x, VALUE y, VALUE str, VALUE color) {
2254
+ return gd_image_string(klass, font, x, y, str, color, gdImageString);
2255
+ }
2256
+
2257
+ /*
2258
+ * call-seq:
2259
+ * string_up(font, x, y, str, color)
2260
+ *
2261
+ * Used to draw multiple characters on the image, rotated 90 degrees. (To draw
2262
+ * single characters, use Image.char_up.)
2263
+ *
2264
+ * The argument _str_ is drawn from bottom to top (rotated 90 degrees) in the
2265
+ * specified color. (See Image.string for a way of drawing horizontal text.)
2266
+ * Pixels not set by a particular character retain their previous color.
2267
+ */
2268
+ static VALUE image_string_up(VALUE klass, VALUE font, VALUE x, VALUE y, VALUE str, VALUE color) {
2269
+ return gd_image_string(klass, font, x, y, str, color, gdImageStringUp);
2270
+ }
2271
+
2272
+ // gd_X__gip_gfp_H4
2273
+ static VALUE gd_image_char(VALUE klass, VALUE font, VALUE x, VALUE y, VALUE c, VALUE color, void (GDFUNC *pfunc)(gdImagePtr, gdFontPtr, int, int, int, int)) {
2274
+ gdImagePtr im;
2275
+ gdFontPtr ft;
2276
+ Data_Get_Struct(klass, gdImage, im);
2277
+ Data_Get_Struct(font, gdFont, ft);
2278
+ (*pfunc)(im, ft, NUM2INT(x), NUM2INT(y), NUM2INT(rb_funcall(c, rb_intern("rnd"), 0)), NUM2INT(color));
2279
+ return klass;
2280
+ }
2281
+
2282
+ /*
2283
+ * call-seq:
2284
+ * char(font, x, y, c, color)
2285
+ *
2286
+ * Used to draw single characters on the image. (To draw multiple characters,
2287
+ * use Image.string. See also Image.stringft for a high quality solution.)
2288
+ *
2289
+ * The character specified by the fifth argument _c_ is drawn from left to right
2290
+ * in the specified color. (See Image.char_up for a way of drawing vertical
2291
+ * text.) Pixels not set by a particular character retain their previous color.
2292
+ */
2293
+ static VALUE image_char(VALUE klass, VALUE font, VALUE x, VALUE y, VALUE c, VALUE color) {
2294
+ return gd_image_char(klass, font, x, y, c, color, gdImageChar);
2295
+ }
2296
+
2297
+ /*
2298
+ * call-seq:
2299
+ * char_up(font, x, y, c, color)
2300
+ *
2301
+ * Used to draw single characters on the image, rotated 90 degrees. (To draw
2302
+ * multiple characters, use Image.string_up.)
2303
+ *
2304
+ * The character specified by the fifth argument _c_ is drawn from bottom to
2305
+ * top, rotated at a 90-degree angle, in the specified color. (See Image.char
2306
+ * for a way of drawing horizontal text.) Pixels not set by a particular
2307
+ * character retain their previous color.
2308
+ */
2309
+ static VALUE image_char_up(VALUE klass, VALUE font, VALUE x, VALUE y, VALUE c, VALUE color) {
2310
+ return gd_image_char(klass, font, x, y, c, color, gdImageCharUp);
2311
+ }
2312
+
2313
+ // gd_PAD__gip_PAH_H_PAD_N2_H2_PAD
2314
+ // gd_PAD__gip_PAH_H_PAD_N2_H2_PAD_gftexp
2315
+ /*
2316
+ * call-seq:
2317
+ * stringft(fg, fontname, ptsize, angle, x, y, str, opts = {})
2318
+ *
2319
+ * Draws a string of anti-aliased characters on the image using the FreeType
2320
+ * library to render user-supplied TrueType fonts. The string is anti-aliased,
2321
+ * meaning that there should be fewer "jaggies" visible. The fontname is the
2322
+ * full pathname to a TrueType font file, or a font face name if the GDFONTPATH
2323
+ * environment variable or the compiled-in DEFAULT_FONTPATH macro of gdft.c have
2324
+ * been set intelligently. In the absence of a full path, the font face name may
2325
+ * be presented with or without extension (2.0.26).
2326
+ *
2327
+ * The null-terminated string argument is considered to be encoded via
2328
+ * the UTF_8 standard; also, HTML entities are supported, including decimal,
2329
+ * hexadecimal, and named entities (2.0.26). Those who are passing ordinary
2330
+ * ASCII strings may have difficulty with the & character unless encoded
2331
+ * correctly as & but should have no other difficulties.
2332
+ *
2333
+ * The string may be arbitrarily scaled (_ptsize_) and rotated (_angle_ in
2334
+ * radians). The direction of rotation is counter-clockwise, with 0 radians (0
2335
+ * degrees) at 3 o'clock and PI/2 radians (90 degrees) at 12 o'clock.
2336
+ *
2337
+ * The string is rendered in the color indicated by the _fg_ color index. Use
2338
+ * the negative of the desired color index to disable anti-aliasing.
2339
+ *
2340
+ * The string may contain UTF-8 sequences like: "À"
2341
+ *
2342
+ * This method returns a hash object, and the element with key "brect" is an
2343
+ * array filled with 4 elements representing the 4 corner coordinates of the
2344
+ * bounding rectangle (the smallest rectangle that completely surrounds the
2345
+ * rendered string and does not intersect any pixel of the rendered string).
2346
+ *
2347
+ * [ [lower_left_X, lower_left_Y], [lower_right_X, lower_right_Y],
2348
+ * \[upper_right_X, upper_right_Y], [upper_left_X, upper_left_Y] ]
2349
+ *
2350
+ * Use Image::stringft to get the bounding rectangle without rendering. This is
2351
+ * a relatively cheap operation if followed by a rendering of the same string,
2352
+ * because of the caching of the partial rendering during bounding rectangle
2353
+ * calculation.
2354
+ *
2355
+ * Options:
2356
+ *
2357
+ * * :linespcing => double
2358
+ * * :charmap => CHARMAP_*
2359
+ * * :hdpi => integer
2360
+ * * :vdpi => integer
2361
+ * * :kerning => boolean
2362
+ * * :xshow => boolean
2363
+ * * :fontpath => boolean
2364
+ * * :fontconfig => boolean
2365
+ *
2366
+ * To output multiline text with a specific line spacing, set the option
2367
+ * _:linespacing_ to the desired spacing, expressed as a multiple of the font
2368
+ * height. Thus a line spacing of 1.0 is the minimum to guarantee that lines of
2369
+ * text do not collide. If _:linespacing_ is not present, linespacing defaults
2370
+ * to 1.05.
2371
+ *
2372
+ * To specify a preference for Unicode, Shift_JIS Big5 character encoding, set
2373
+ * the option _:charmap_ to CHARMAP_*. If you do not specify a preference,
2374
+ * Unicode will be tried first. If the preferred character mapping is not found
2375
+ * in the font, other character mappings are attempted.
2376
+ *
2377
+ * GD operates on the assumption that the output image will be rendered to a
2378
+ * computer screen. By default, gd passes a resolution of 96 dpi to the freetype
2379
+ * text rendering engine. This influences the "hinting" decisions made by the
2380
+ * renderer. To specify a different resolution, set _:hdpi_ and _:vdpi_
2381
+ * accordingly (in dots per inch).
2382
+ *
2383
+ * GD 2.0.29 and later will normally attempt to apply kerning tables, if
2384
+ * fontconfig is available, to adjust the relative positions of consecutive
2385
+ * characters more ideally for that pair of characters. This can be turn off by
2386
+ * set the option _:kerning_ to false;
2387
+ *
2388
+ * GD 2.0.29 and later can return a vector of individual character position
2389
+ * advances by set the option _:xshow_ to true, occasionally useful in
2390
+ * applications that must know exactly where each character begins. This is
2391
+ * returned in the element with key "xshow".
2392
+ *
2393
+ * GD 2.0.29 and later can also return the path to the actual font file used if
2394
+ * the option _:returnfontpath_ is true. This is useful because GD 2.0.29 and
2395
+ * above are capable of selecting a font automatically based on a fontconfig
2396
+ * font pattern when fontconfig is available. This information is returned in
2397
+ * the element with key "fontpath".
2398
+ *
2399
+ * GD 2.0.29 and later can use fontconfig to resolve font names, including
2400
+ * fontconfig patterns, if the option _:fontconfig_ is true. As a convenience,
2401
+ * this behavior can be made the default by calling Image.use_fontconfig=true.
2402
+ * In that situation it is not necessary to set the option _:fontconfig_ on
2403
+ * every call; however explicit font path names can still be used if the option
2404
+ * _:fontpathname_ is true.
2405
+ *
2406
+ * Unless Image.use_fontconfig=true has been called, GD 2.0.29 and later will
2407
+ * still expect the fontlist argument to the freetype text output functions to
2408
+ * be a font file name or list thereof as in previous versions. If you do not
2409
+ * wish to make fontconfig the default, it is still possible to force the use
2410
+ * of fontconfig for a single call to the freetype text output functions by
2411
+ * setting the option _:fontconfig_ to ture.
2412
+ */
2413
+ static VALUE image_stringft(int argc, VALUE *argv, VALUE klass) {
2414
+ VALUE fg, fontname, ptsize, angle, x, y, str, opts;
2415
+ VALUE ret, m, n;
2416
+ gdImagePtr im = NULL;
2417
+ gdFTStringExtra ftex;
2418
+ int brect[8];
2419
+ char *err;
2420
+
2421
+ if (TYPE(klass) == T_DATA) Data_Get_Struct(klass, gdImage, im);
2422
+ memset(&ftex, 0, sizeof(gdFTStringExtra));
2423
+ if (rb_scan_args(argc, argv, "71", &fg, &fontname, &ptsize, &angle, &x, &y, &str, &opts) == 7) {
2424
+ err = gdImageStringFT(im, &brect[0], NUM2INT(fg), RSTRING_PTR(fontname), NUM2DBL(ptsize), NUM2DBL(angle), NUM2INT(x), NUM2INT(y), RSTRING_PTR(str));
2425
+ } else {
2426
+ Check_Type(opts, T_HASH);
2427
+
2428
+ m = rb_hash_aref(opts, STR2SYM("linespacing"));
2429
+ if (RTEST(m)) {
2430
+ ftex.flags |= gdFTEX_LINESPACE;
2431
+ ftex.linespacing = NUM2DBL(m);
2432
+ }
2433
+
2434
+ m = rb_hash_aref(opts, STR2SYM("charmp"));
2435
+ if (RTEST(m)) {
2436
+ ftex.flags |= gdFTEX_CHARMAP;
2437
+ ftex.charmap = NUM2INT(m);
2438
+ }
2439
+
2440
+ m = rb_hash_aref(opts, STR2SYM("hdpi"));
2441
+ n = rb_hash_aref(opts, STR2SYM("vdpi"));
2442
+ if (RTEST(m) && RTEST(n)) {
2443
+ ftex.flags |= gdFTEX_RESOLUTION;
2444
+ ftex.hdpi = NUM2INT(m);
2445
+ ftex.vdpi = NUM2INT(n);
2446
+ }
2447
+
2448
+ m = rb_hash_aref(opts, STR2SYM("kerning"));
2449
+ if (m == Qfalse) ftex.flags |= gdFTEX_DISABLE_KERNING;
2450
+
2451
+ m = rb_hash_aref(opts, STR2SYM("xshow"));
2452
+ if (RTEST(m)) ftex.flags |= gdFTEX_XSHOW;
2453
+
2454
+ m = rb_hash_aref(opts, STR2SYM("returnfontpath"));
2455
+ if (RTEST(m)) ftex.flags |= gdFTEX_RETURNFONTPATHNAME;
2456
+
2457
+ m = rb_hash_aref(opts, STR2SYM("fontpathname"));
2458
+ if (RTEST(m)) ftex.flags |= gdFTEX_FONTPATHNAME;
2459
+
2460
+ m = rb_hash_aref(opts, STR2SYM("fontconfig"));
2461
+ if (RTEST(m)) ftex.flags |= gdFTEX_FONTCONFIG;
2462
+
2463
+ err = gdImageStringFTEx(im, &brect[0], NUM2INT(fg), RSTRING_PTR(fontname), NUM2DBL(ptsize), NUM2DBL(angle), NUM2INT(x), NUM2INT(y), RSTRING_PTR(str), &ftex);
2464
+ }
2465
+
2466
+ if (err) rb_raise(rb_eRGDError, "%s", err);
2467
+
2468
+ ret = rb_hash_new();
2469
+ rb_hash_aset(ret, rb_str_new2("brect"),
2470
+ rb_ary_new3(4,
2471
+ rb_ary_new3(2, INT2NUM(brect[0]), INT2NUM(brect[1])),
2472
+ rb_ary_new3(2, INT2NUM(brect[2]), INT2NUM(brect[3])),
2473
+ rb_ary_new3(2, INT2NUM(brect[4]), INT2NUM(brect[5])),
2474
+ rb_ary_new3(2, INT2NUM(brect[6]), INT2NUM(brect[7]))
2475
+ ));
2476
+
2477
+ if (ftex.flags != 0) {
2478
+ if (ftex.xshow) {
2479
+ rb_hash_aset(ret, rb_str_new2("xshow"), rb_str_new2(ftex.xshow));
2480
+ gdFree(ftex.xshow);
2481
+ }
2482
+
2483
+ if (ftex.fontpath) {
2484
+ rb_hash_aset(ret, rb_str_new2("fontpath"), rb_str_new2(ftex.fontpath));
2485
+ gdFree(ftex.fontpath);
2486
+ }
2487
+ }
2488
+
2489
+ return ret;
2490
+ }
2491
+
2492
+ // gd_PAD__gip_H2_N3_PAD_N_PAD2_H
2493
+ /*
2494
+ * call-seq:
2495
+ * stringft_circle(cx, cy, radius, textRadius, fillPortion, fontname, points, top, bottom, fg)
2496
+ *
2497
+ * Draws the text strings specified by _top_ and _bottom_ on the image, curved
2498
+ * along the edge of a circle of radius _radius_, with its center at _cx_
2499
+ * and _cy_. _top_ is written clockwise along the top; _bottom_ is written
2500
+ * counterclockwise along the bottom. _textRadius_ determines the "height" of
2501
+ * each character; if _textRadius_ is 1/2 of _radius_, characters extend halfway
2502
+ * from the edge to the center. _fillPortion_ varies from 0 to 1.0, with useful
2503
+ * values from about 0.4 to 0.9, and determines how much of the 180 degrees of
2504
+ * arc assigned to each section of text is actually occupied by text; 0.9 looks
2505
+ * better than 1.0 which is rather crowded. _fontname_ is a freetype font; see
2506
+ * Image.stringft. _points_ is passed to the freetype engine and has an effect
2507
+ * on hinting; although the size of the text is determined by _radius_,
2508
+ * _textRadius_, and _fillPortion_, you should pass a point size that "hints"
2509
+ * appropriately -- if you know the text will be large, pass a large point size
2510
+ * such as 24.0 to get the best results. _fg_ can be any color, and may have an
2511
+ * alpha component, do blending, etc.
2512
+ */
2513
+ static VALUE image_stringft_circle(VALUE klass, VALUE cx, VALUE cy, VALUE radius, VALUE textRadius, VALUE fillPortion, VALUE fontname, VALUE points, VALUE top, VALUE bottom, VALUE fg) {
2514
+ gdImagePtr im;
2515
+ char *err;
2516
+ Data_Get_Struct(klass, gdImage, im);
2517
+ err = gdImageStringFTCircle(im, NUM2INT(cx), NUM2INT(cy), NUM2DBL(radius), NUM2DBL(textRadius), NUM2DBL(fillPortion), RSTRING_PTR(fontname), NUM2DBL(points), RSTRING_PTR(top), RSTRING_PTR(bottom), NUM2INT(fg));
2518
+ if (err) rb_raise(rb_eRGDError, "%s", err);
2519
+ return klass;
2520
+ }
2521
+
2522
+ /*
2523
+ * call-seq:
2524
+ * new(filename, format = nil)
2525
+ *
2526
+ * Create a new image from a file.
2527
+ *
2528
+ * The argument _format_ should be a image format name, like "jpeg", "png", etc.
2529
+ * If it's nil, the image type will be detected automatically by the extension
2530
+ * of _filename_.
2531
+ */
2532
+ static VALUE image_s_new(int argc, VALUE* argv, VALUE klass) {
2533
+ VALUE filename, format;
2534
+ char *ext;
2535
+ ImageFormat i_fmt = FMT_UNKNOW;
2536
+
2537
+ if (rb_scan_args(argc, argv, "11", &filename, &format) == 2) Check_Type(format, T_STRING);
2538
+ Check_Type(filename, T_STRING);
2539
+ if (rb_funcall(rb_cFile, rb_intern("readable?"), 1, filename) != Qtrue) rb_raise(rb_eArgError, "%s is not readable", RSTRING_PTR(filename));
2540
+
2541
+ if (RTEST(format)) {
2542
+ i_fmt = m_image_detect_format_by_ext(RSTRING_PTR(format));
2543
+ } else {
2544
+ ext = strrchr(RSTRING_PTR(filename), '.');
2545
+ if (ext && ++ext) i_fmt = m_image_detect_format_by_ext(ext);
2546
+ }
2547
+
2548
+ switch (i_fmt) {
2549
+ case FMT_JPEG:
2550
+ return image_s_from_jpeg(klass, filename);
2551
+ case FMT_PNG:
2552
+ return image_s_from_png(klass, filename);
2553
+ case FMT_GIF:
2554
+ return image_s_from_gif(klass, filename);
2555
+ case FMT_BMP:
2556
+ return image_s_from_bmp(klass, filename);
2557
+ case FMT_GD2:
2558
+ return image_s_from_gd2(klass, filename);
2559
+ case FMT_GD:
2560
+ return image_s_from_gd(klass, filename);
2561
+ case FMT_WBMP:
2562
+ return image_s_from_wbmp(klass, filename);
2563
+ case FMT_XBM:
2564
+ return image_s_from_xbm(klass, filename);
2565
+ case FMT_XPM:
2566
+ return image_s_from_xpm(klass, filename);
2567
+ default:
2568
+ if (RTEST(format)) {
2569
+ rb_raise(rb_eRGDError, "Unknown image format: %s", RSTRING_PTR(format));
2570
+ } else {
2571
+ rb_raise(rb_eRGDError, "Cannot detect image format: %s", RSTRING_PTR(filename));
2572
+ }
2573
+ }
2574
+ }
2575
+
2576
+ /*
2577
+ * call-seq:
2578
+ * from_data(data, format = nil)
2579
+ *
2580
+ * Create a new image from a byte-string.
2581
+ *
2582
+ * The argument _format_ should be a image format name, like "jpeg", "png", etc.
2583
+ * If it's nil, the image type will be detected automatically by the MAGIC of
2584
+ * _data_ (work for JPEG, PNG, GIF, BMP, GD2 and GD).
2585
+ */
2586
+ static VALUE image_s_from_data(int argc, VALUE* argv, VALUE klass) {
2587
+ VALUE data, format;
2588
+ char *ext;
2589
+ ImageFormat i_fmt = FMT_UNKNOW;
2590
+
2591
+ if (rb_scan_args(argc, argv, "11", &data, &format) == 2) Check_Type(format, T_STRING);
2592
+ Check_Type(data, T_STRING);
2593
+
2594
+ if (RTEST(format)) {
2595
+ i_fmt = m_image_detect_format_by_ext(RSTRING_PTR(format));
2596
+ } else {
2597
+ i_fmt = m_image_detect_format_by_magic(RSTRING_PTR(data));
2598
+ }
2599
+
2600
+ switch (i_fmt) {
2601
+ case FMT_JPEG:
2602
+ return image_s_from_jpeg_data(klass, data);
2603
+ case FMT_PNG:
2604
+ return image_s_from_png_data(klass, data);
2605
+ case FMT_GIF:
2606
+ return image_s_from_gif_data(klass, data);
2607
+ case FMT_BMP:
2608
+ return image_s_from_bmp_data(klass, data);
2609
+ case FMT_GD2:
2610
+ return image_s_from_gd2_data(klass, data);
2611
+ case FMT_GD:
2612
+ return image_s_from_gd_data(klass, data);
2613
+ case FMT_WBMP:
2614
+ return image_s_from_wbmp_data(klass, data);
2615
+ case FMT_XBM:
2616
+ rb_raise(rb_eRGDError, "Cannot load a XBM image from a byte-string.");
2617
+ case FMT_XPM:
2618
+ rb_raise(rb_eRGDError, "Cannot load a XPM image from a byte-string.");
2619
+ default:
2620
+ if (RTEST(format)) {
2621
+ rb_raise(rb_eRGDError, "Unknown image format: %s", RSTRING_PTR(format));
2622
+ } else {
2623
+ rb_raise(rb_eRGDError, "Cannot detect image format");
2624
+ }
2625
+ }
2626
+ }
2627
+
2628
+
2629
+
2630
+ /*
2631
+ * call-seq:
2632
+ * file(filename, format = nil, [more params])
2633
+ *
2634
+ * Write the image to _filename_ in specified _format_. If _format_ is nil, the
2635
+ * file format will be detected automatically by the extension of _filename_.
2636
+ *
2637
+ * Usage:
2638
+ *
2639
+ * * file(filename, "jpeg", quality = -1)
2640
+ * * file(filename, "png", level = -1)
2641
+ * * file(filename, "gif")
2642
+ * * file(filename, "bmp")
2643
+ * * file(filename, "gd2", chunk_size = 0, fmt = GD2_FMT_COMPRESSED)
2644
+ * * file(filename, "gd")
2645
+ * * file(filename, "wbmp", fg = 1)
2646
+ */
2647
+ static VALUE image_file(int argc, VALUE* argv, VALUE klass) {
2648
+ VALUE filename, format, a1, a2;
2649
+ char *ext;
2650
+ ImageFormat i_fmt = FMT_UNKNOW;
2651
+
2652
+ rb_scan_args(argc, argv, "13", &filename, &format, &a1, &a2);
2653
+ Check_Type(filename, T_STRING);
2654
+ if (RTEST(a1)) Check_Type(a1, T_FIXNUM);
2655
+ if (RTEST(a2)) Check_Type(a2, T_FIXNUM);
2656
+
2657
+ if (RTEST(format)) {
2658
+ Check_Type(format, T_STRING);
2659
+ i_fmt = m_image_detect_format_by_ext(RSTRING_PTR(format));
2660
+ } else {
2661
+ ext = strrchr(RSTRING_PTR(filename), '.');
2662
+ if (ext && strlen(ext) > 1) {
2663
+ ext += 1;
2664
+ i_fmt = m_image_detect_format_by_ext(ext);
2665
+ }
2666
+ }
2667
+
2668
+ switch (i_fmt) {
2669
+ case FMT_JPEG:
2670
+ SetIntIfQnil(a1, -1);
2671
+ return rb_funcall(klass, rb_intern("jpeg"), 2, filename, a1);
2672
+ case FMT_GIF:
2673
+ return image_gif(klass, filename);
2674
+ case FMT_PNG:
2675
+ SetIntIfQnil(a1, -1);
2676
+ return rb_funcall(klass, rb_intern("png"), 2, filename, a1);
2677
+ case FMT_BMP:
2678
+ return image_bmp(klass, filename);
2679
+ case FMT_GD2:
2680
+ SetIntIfQnil(a1, 0);
2681
+ SetIntIfQnil(a2, GD2_FMT_COMPRESSED);
2682
+ return rb_funcall(klass, rb_intern("gd2"), 3, filename, a1, a2);
2683
+ case FMT_GD:
2684
+ return image_gd(klass, filename);
2685
+ case FMT_WBMP:
2686
+ SetIntIfQnil(a1, 1);
2687
+ return rb_funcall(klass, rb_intern("wbmp"), 2, filename, a1);
2688
+ case FMT_XBM:
2689
+ rb_raise(rb_eRGDError, "This method doesn't support XBM format");
2690
+ case FMT_XPM:
2691
+ rb_raise(rb_eRGDError, "This method doesn't support XPM format");
2692
+ default:
2693
+ rb_raise(rb_eRGDError, "Unknown image format.");
2694
+ }
2695
+ }
2696
+
2697
+ /*
2698
+ * call-seq:
2699
+ * data(format, [more params])
2700
+ *
2701
+ * Convert the image to a byte-string in specified _format_.
2702
+ *
2703
+ * Usage:
2704
+ *
2705
+ * * data("jpeg", quality = -1)
2706
+ * * data("png", level = -1)
2707
+ * * data("gif")
2708
+ * * data("bmp")
2709
+ * * data("gd2", chunk_size = 0, fmt = GD2_FMT_COMPRESSED)
2710
+ * * data("gd")
2711
+ * * data("wbmp", fg = 1)
2712
+ */
2713
+ static VALUE image_data(int argc, VALUE* argv, VALUE klass) {
2714
+ VALUE format, a1, a2;
2715
+ ImageFormat i_fmt;
2716
+
2717
+ rb_scan_args(argc, argv, "12", &format, &a1, &a2);
2718
+ Check_Type(format, T_STRING);
2719
+ if (RTEST(a1)) Check_Type(a1, T_FIXNUM);
2720
+ if (RTEST(a2)) Check_Type(a2, T_FIXNUM);
2721
+
2722
+ i_fmt = m_image_detect_format_by_ext(RSTRING_PTR(format));
2723
+ switch (i_fmt) {
2724
+ case FMT_JPEG:
2725
+ SetIntIfQnil(a1, -1);
2726
+ return rb_funcall(klass, rb_intern("jpeg_data"), 1, a1);
2727
+ case FMT_GIF:
2728
+ return image_gif_data(klass);
2729
+ case FMT_PNG:
2730
+ SetIntIfQnil(a1, -1);
2731
+ return rb_funcall(klass, rb_intern("png_data"), 1, a1);
2732
+ case FMT_BMP:
2733
+ return image_bmp_data(klass);
2734
+ case FMT_GD2:
2735
+ SetIntIfQnil(a1, 0);
2736
+ SetIntIfQnil(a2, GD2_FMT_COMPRESSED);
2737
+ return rb_funcall(klass, rb_intern("gd2_data"), 2, a1, a2);
2738
+ case FMT_GD:
2739
+ return image_gd_data(klass);
2740
+ case FMT_WBMP:
2741
+ SetIntIfQnil(a1, 1);
2742
+ return rb_funcall(klass, rb_intern("wbmp_data"), 1, a1);
2743
+ case FMT_XBM:
2744
+ rb_raise(rb_eRGDError, "This method doesn't support XBM format");
2745
+ case FMT_XPM:
2746
+ rb_raise(rb_eRGDError, "This method doesn't support XPM format");
2747
+ default:
2748
+ rb_raise(rb_eRGDError, "Unknown image format.");
2749
+ }
2750
+ }
2751
+
2752
+ /*
2753
+ * call-seq:
2754
+ * clone()
2755
+ *
2756
+ * Return a new image clone from current.
2757
+ */
2758
+ static VALUE image_clone(VALUE klass) {
2759
+ VALUE nimage, data;
2760
+
2761
+ data = image_gd2_data(klass, 0, GD2_FMT_RAW);
2762
+ nimage = rb_funcall(rb_cImage, rb_intern("from_gd2_data"), 1, data);
2763
+
2764
+ return nimage;
2765
+ }
2766
+
2767
+ /*
2768
+ * call-seq:
2769
+ * to_palette(dither = true, colors = MAX_COLORS)
2770
+ *
2771
+ * Create a new palette-based image from current. If the image is a
2772
+ * palette-based image already, this method equals to RGD::Image.clone.
2773
+ */
2774
+ static VALUE image_to_palette(int argc, VALUE* argv, VALUE klass) {
2775
+ VALUE nimage = image_clone(klass);
2776
+ if (image_is_truecolor(nimage) == Qfalse) {
2777
+ return nimage;
2778
+ } else {
2779
+ return image_truecolor_to_palette(argc, argv, nimage);
2780
+ }
2781
+ }
2782
+
2783
+ void Init_rgd() {
2784
+ rb_mRGD = rb_define_module("RGD");
2785
+
2786
+ rb_eRGDError = rb_define_class_under(rb_mRGD, "RGDError", rb_eException);
2787
+
2788
+ rb_cFont = rb_define_class_under(rb_mRGD, "Font", rb_cObject);
2789
+ rb_define_singleton_method(rb_cFont, "small", font_s_small, 0);
2790
+ rb_define_singleton_method(rb_cFont, "large", font_s_large, 0);
2791
+ rb_define_singleton_method(rb_cFont, "medium_bold", font_s_medium_bold, 0);
2792
+ rb_define_singleton_method(rb_cFont, "giant", font_s_giant, 0);
2793
+ rb_define_singleton_method(rb_cFont, "tiny", font_s_tiny, 0);
2794
+
2795
+ rb_cImage = rb_define_class_under(rb_mRGD, "Image", rb_cObject);
2796
+ /* gdAlphaMax: Same as ALPHA_TRANSPARENT. */
2797
+ rb_define_const(rb_cImage, "ALPHA_MAX", INT2NUM(gdAlphaMax));
2798
+ /* gdAlphaOpaque: Does not blend at all with the background. */
2799
+ rb_define_const(rb_cImage, "ALPHA_OPAQUE", INT2NUM(gdAlphaOpaque));
2800
+ /* gdAlphaTransparent: Allows the background to shine through 100%. */
2801
+ rb_define_const(rb_cImage, "ALPHA_TRANSPARENT", INT2NUM(gdAlphaTransparent));
2802
+ /* gdMaxColors: Max colors can be used in palette-based image. */
2803
+ rb_define_const(rb_cImage, "MAX_COLORS", INT2NUM(gdMaxColors));
2804
+ /* GD2_FMT_RAW: Uncompressed \GD2 format. */
2805
+ rb_define_const(rb_cImage, "GD2_FMT_RAW", INT2NUM(GD2_FMT_RAW));
2806
+ /* GD2_FMT_COMPRESSED: Compressed \GD2 format. */
2807
+ rb_define_const(rb_cImage, "GD2_FMT_COMPRESSED", INT2NUM(GD2_FMT_COMPRESSED));
2808
+ //rb_define_const(rb_cImage, "DISPOSAL_UNKNOWN", INT2NUM(gdDisposalUnknown));
2809
+ /* gdDisposalNone: Restores the first allocated color of the global palette. */
2810
+ rb_define_const(rb_cImage, "DISPOSAL_NONE", INT2NUM(gdDisposalNone));
2811
+ /* gdDisposalRestoreBackground: Restores the appearance of the affected area before the frame was rendered. */
2812
+ rb_define_const(rb_cImage, "DISPOSAL_RESTORE_BACKGROUND", INT2NUM(gdDisposalRestoreBackground));
2813
+ /* gdDisposalRestorePrevious: The pixels changed by this frame should remain on the display when the next frame begins to render. */
2814
+ rb_define_const(rb_cImage, "DISPOSAL_RESTORE_PREVIOUS", INT2NUM(gdDisposalRestorePrevious));
2815
+ /* GD_CMP_IMAGE: Actual image IS different */
2816
+ rb_define_const(rb_cImage, "GD_CMP_IMAGE", INT2NUM(GD_CMP_IMAGE));
2817
+ /* GD_CMP_NUM_COLORS: Number of Colors in pallette differ */
2818
+ rb_define_const(rb_cImage, "GD_CMP_NUM_COLORS", INT2NUM(GD_CMP_NUM_COLORS));
2819
+ /* GD_CMP_COLOR: \Image Colors differ */
2820
+ rb_define_const(rb_cImage, "GD_CMP_COLOR", INT2NUM(GD_CMP_COLOR));
2821
+ /* GD_CMP_SIZE_X: \Image width differs */
2822
+ rb_define_const(rb_cImage, "GD_CMP_SIZE_X", INT2NUM(GD_CMP_SIZE_X));
2823
+ /* GD_CMP_SIZE_Y: \Image heights differ */
2824
+ rb_define_const(rb_cImage, "GD_CMP_SIZE_Y", INT2NUM(GD_CMP_SIZE_Y));
2825
+ /* GD_CMP_TRANSPARENT: Transparent color */
2826
+ rb_define_const(rb_cImage, "GD_CMP_TRANSPARENT", INT2NUM(GD_CMP_TRANSPARENT));
2827
+ /* GD_CMP_BACKGROUND: Background color */
2828
+ rb_define_const(rb_cImage, "GD_CMP_BACKGROUND", INT2NUM(GD_CMP_BACKGROUND));
2829
+ /* GD_CMP_INTERLACE: Interlaced setting */
2830
+ rb_define_const(rb_cImage, "GD_CMP_INTERLACE", INT2NUM(GD_CMP_INTERLACE));
2831
+ /* GD_CMP_TRUECOLOR: Truecolor vs palette differs */
2832
+ rb_define_const(rb_cImage, "GD_CMP_TRUECOLOR", INT2NUM(GD_CMP_TRUECOLOR));
2833
+ /* gdStyled: Special color. */
2834
+ rb_define_const(rb_cImage, "COLOR_STYLED", INT2NUM(gdStyled));
2835
+ /* gdBrushed: Special color. */
2836
+ rb_define_const(rb_cImage, "COLOR_BRUSHED", INT2NUM(gdBrushed));
2837
+ /* gdStyledBrushed: Special color. */
2838
+ rb_define_const(rb_cImage, "COLOR_STYLED_BRUSHED", INT2NUM(gdStyledBrushed));
2839
+ /* gdTiled: Special color. */
2840
+ rb_define_const(rb_cImage, "COLOR_TILED", INT2NUM(gdTiled));
2841
+ /* gdTransparent: Special color. NOT the same as the transparent color index. This is used in line styles only. */
2842
+ rb_define_const(rb_cImage, "COLOR_TRANSPARENT", INT2NUM(gdTransparent));
2843
+ /* gdAntiAliased: Special color. */
2844
+ rb_define_const(rb_cImage, "COLOR_ANTIALIASED", INT2NUM(gdAntiAliased));
2845
+ /* gdArc: See Image.filled_arc. */
2846
+ rb_define_const(rb_cImage, "STYLE_ARC", INT2NUM(gdArc));
2847
+ /* gdChord: See Image.filled_arc. */
2848
+ rb_define_const(rb_cImage, "STYLE_CHORD", INT2NUM(gdChord));
2849
+ /* gdPie: See Image.filled_arc. */
2850
+ rb_define_const(rb_cImage, "STYLE_PIE", INT2NUM(gdPie));
2851
+ /* gdNoFill: See Image.filled_arc. */
2852
+ rb_define_const(rb_cImage, "STYLE_NO_FILL", INT2NUM(gdNoFill));
2853
+ /* gdEdged: See Image.filled_arc. */
2854
+ rb_define_const(rb_cImage, "STYLE_EDGED", INT2NUM(gdEdged));
2855
+ /* gdFTEX_Unicode: See Image.stringft. */
2856
+ rb_define_const(rb_cImage, "CHARMAP_UNICODE", INT2NUM(gdFTEX_Unicode));
2857
+ /* gdFTEX_Shift_JIS: See Image.stringft. */
2858
+ rb_define_const(rb_cImage, "CHARMAP_SHIFT_JIS", INT2NUM(gdFTEX_Shift_JIS));
2859
+ /* gdFTEX_Big5: See Image.stringft. */
2860
+ rb_define_const(rb_cImage, "CHARMAP_BIG5", INT2NUM(gdFTEX_Big5));
2861
+ /* gdFTEX_Adobe_Custom: See Image.stringft. */
2862
+ rb_define_const(rb_cImage, "CHARMAP_ADOBE_CUSTOM", INT2NUM(gdFTEX_Adobe_Custom));
2863
+ rb_define_singleton_method(rb_cImage, "use_fontconfig=", image_s_use_fontconfig, 1);
2864
+ rb_define_singleton_method(rb_cImage, "alpha_blend", image_s_alpha_blend, 2);
2865
+ rb_define_singleton_method(rb_cImage, "truecolor", image_s_truecolor, -1);
2866
+ rb_define_singleton_method(rb_cImage, "create", image_s_create, 2);
2867
+ rb_define_singleton_method(rb_cImage, "create_truecolor", image_s_create_truecolor, 2);
2868
+ rb_define_singleton_method(rb_cImage, "from_jpeg_data", image_s_from_jpeg_data, 1);
2869
+ rb_define_singleton_method(rb_cImage, "from_png_data", image_s_from_png_data, 1);
2870
+ rb_define_singleton_method(rb_cImage, "from_gif_data", image_s_from_gif_data, 1);
2871
+ rb_define_singleton_method(rb_cImage, "from_gd_data", image_s_from_gd_data, 1);
2872
+ rb_define_singleton_method(rb_cImage, "from_gd2_data", image_s_from_gd2_data, 1);
2873
+ rb_define_singleton_method(rb_cImage, "from_wbmp_data", image_s_from_wbmp_data, 1);
2874
+ rb_define_singleton_method(rb_cImage, "from_bmp_data", image_s_from_bmp_data, 1);
2875
+ rb_define_singleton_method(rb_cImage, "from_gd2_part_data", image_s_from_gd2_part_data, 5);
2876
+ rb_define_singleton_method(rb_cImage, "from_xpm", image_s_from_xpm, 1);
2877
+ rb_define_singleton_method(rb_cImage, "from_jpeg", image_s_from_jpeg, 1);
2878
+ rb_define_singleton_method(rb_cImage, "from_png", image_s_from_png, 1);
2879
+ rb_define_singleton_method(rb_cImage, "from_gif", image_s_from_gif, 1);
2880
+ rb_define_singleton_method(rb_cImage, "from_gd", image_s_from_gd, 1);
2881
+ rb_define_singleton_method(rb_cImage, "from_gd2", image_s_from_gd2, 1);
2882
+ rb_define_singleton_method(rb_cImage, "from_wbmp", image_s_from_wbmp, 1);
2883
+ rb_define_singleton_method(rb_cImage, "from_xbm", image_s_from_xbm, 1);
2884
+ rb_define_singleton_method(rb_cImage, "from_bmp", image_s_from_bmp, 1);
2885
+ rb_define_singleton_method(rb_cImage, "from_gd2_part", image_s_from_gd2_part, 5);
2886
+ rb_define_singleton_method(rb_cImage, "create_palette_from_truecolor", image_s_create_palette_from_truecolor, -1);
2887
+ rb_define_singleton_method(rb_cImage, "square_to_circle", image_s_square_to_circle, 2);
2888
+ // TODO: document for Image.stringft, RDOC doesn't work.
2889
+ rb_define_singleton_method(rb_cImage, "stringft", image_stringft, -1);
2890
+
2891
+ rb_define_method(rb_cImage, "gif", image_gif, 1);
2892
+ rb_define_method(rb_cImage, "gd", image_gd, 1);
2893
+ rb_define_method(rb_cImage, "jpeg", image_jpeg, -1);
2894
+ rb_define_method(rb_cImage, "png", image_png, -1);
2895
+ rb_define_method(rb_cImage, "bmp", image_bmp, 1);
2896
+ rb_define_method(rb_cImage, "wbmp", image_wbmp, -1);
2897
+ rb_define_method(rb_cImage, "gif_data", image_gif_data, 0);
2898
+ rb_define_method(rb_cImage, "gd_data", image_gd_data, 1);
2899
+ rb_define_method(rb_cImage, "jpeg_data", image_jpeg_data, -1);
2900
+ rb_define_method(rb_cImage, "png_data", image_png_data, -1);
2901
+ rb_define_method(rb_cImage, "wbmp_data", image_wbmp_data, -1);
2902
+ rb_define_method(rb_cImage, "bmp_data", image_bmp_data, 0);
2903
+ rb_define_method(rb_cImage, "gd2_data", image_gd2_data, -1);
2904
+ rb_define_method(rb_cImage, "gif_anim_begin_data", image_gif_anim_begin_data, -1);
2905
+ rb_define_method(rb_cImage, "gif_anim_add_data", image_gif_anim_add_data, -1);
2906
+ rb_define_method(rb_cImage, "gif_anim_end_data", image_gif_anim_end_data, 0);
2907
+ rb_define_method(rb_cImage, "gd2", image_gd2, -1);
2908
+ rb_define_method(rb_cImage, "compare", image_compare, 1);
2909
+ rb_define_method(rb_cImage, "width", image_sx, 0);
2910
+ rb_define_method(rb_cImage, "height", image_sy, 0);
2911
+ rb_define_method(rb_cImage, "truecolor?", image_is_truecolor, 0);
2912
+ rb_define_method(rb_cImage, "colors_total", image_colors_total, 0);
2913
+ rb_define_method(rb_cImage, "interlace", image_get_interlace, 0);
2914
+ rb_define_method(rb_cImage, "transparent", image_transparent_get, 0);
2915
+ rb_define_method(rb_cImage, "rgba", image_rgba, 1);
2916
+ rb_define_method(rb_cImage, "[]", image_get_pixel, 2);
2917
+ rb_define_method(rb_cImage, "bounds_safe?", image_bounds_safe, 2);
2918
+ rb_define_method(rb_cImage, "color_closest_hwb", image_color_closest_hwb, -1);
2919
+ rb_define_method(rb_cImage, "color_allocate", image_color_allocate, -1);
2920
+ rb_define_method(rb_cImage, "color_closest", image_color_closest, -1);
2921
+ rb_define_method(rb_cImage, "color_exact", image_color_exact, -1);
2922
+ rb_define_method(rb_cImage, "color_resolve", image_color_resolve, -1);
2923
+ rb_define_method(rb_cImage, "brush=", image_set_brush, 1);
2924
+ rb_define_method(rb_cImage, "tile=", image_set_tile, 1);
2925
+ rb_define_method(rb_cImage, "copy_palette", image_copy_palette, 1);
2926
+ rb_define_method(rb_cImage, "copy", image_copy, 7);
2927
+ rb_define_method(rb_cImage, "copy_merge", image_copy_merge, 8);
2928
+ rb_define_method(rb_cImage, "copy_merge_gray", image_copy_merge_gray, 8);
2929
+ rb_define_method(rb_cImage, "copy_resized", image_copy_resized, 9);
2930
+ rb_define_method(rb_cImage, "copy_resampled", image_copy_resampled, 9);
2931
+ rb_define_method(rb_cImage, "copy_rotated", image_copy_rotated, 8);
2932
+ rb_define_method(rb_cImage, "interlace=", image_interlace_set, 1);
2933
+ rb_define_method(rb_cImage, "antialiased=", image_set_antialiased, 1);
2934
+ rb_define_method(rb_cImage, "thickness=", image_set_thickness, 1);
2935
+ rb_define_method(rb_cImage, "alpha_blending=", image_set_alpha_blending, 1);
2936
+ rb_define_method(rb_cImage, "save_alpha=", image_save_alpha, 1);
2937
+ rb_define_method(rb_cImage, "color_deallocate", image_color_deallocate, 1);
2938
+ rb_define_method(rb_cImage, "transparent=", image_color_transparent, 1);
2939
+ rb_define_method(rb_cImage, "sharepen", image_sharepen, 1);
2940
+ rb_define_method(rb_cImage, "to_palette!", image_truecolor_to_palette, -1);
2941
+ rb_define_method(rb_cImage, "antialiased_dont_blend", image_set_antialiased_dont_blend, 2);
2942
+ rb_define_method(rb_cImage, "[]=", image_set_pixel, 3);
2943
+ rb_define_method(rb_cImage, "fill", image_fill, 3);
2944
+ rb_define_method(rb_cImage, "fill_to_border", image_fill_to_border, 4);
2945
+ rb_define_method(rb_cImage, "clip=", image_set_clip, 4);
2946
+ rb_define_method(rb_cImage, "line", image_line, 5);
2947
+ rb_define_method(rb_cImage, "dashed_line", image_dashed_line, 5);
2948
+ rb_define_method(rb_cImage, "rectangle", image_rectangle, 5);
2949
+ rb_define_method(rb_cImage, "filled_rectangle", image_filled_rectangle, 5);
2950
+ rb_define_method(rb_cImage, "filled_ellipse", image_filled_ellipse, 5);
2951
+ rb_define_method(rb_cImage, "arc", image_arc, 7);
2952
+ rb_define_method(rb_cImage, "filled_arc", image_filled_arc, 8);
2953
+ rb_define_method(rb_cImage, "clip", image_get_clip, 0);
2954
+ rb_define_method(rb_cImage, "styles=", image_set_style, 1);
2955
+ rb_define_method(rb_cImage, "polygon", image_polygon, 2);
2956
+ rb_define_method(rb_cImage, "open_polygon", image_open_polygon, 2);
2957
+ rb_define_method(rb_cImage, "filled_polygon", image_filled_polygon, 2);
2958
+ rb_define_method(rb_cImage, "aa_blend", image_aa_blend, 0);
2959
+ rb_define_method(rb_cImage, "string", image_string, 5);
2960
+ rb_define_method(rb_cImage, "string_up", image_string_up, 5);
2961
+ rb_define_method(rb_cImage, "char", image_char, 5);
2962
+ rb_define_method(rb_cImage, "char_up", image_char_up, 5);
2963
+ rb_define_method(rb_cImage, "stringft", image_stringft, -1);
2964
+ rb_define_method(rb_cImage, "stringft_circle", image_stringft_circle, 10);
2965
+
2966
+ rb_define_class_variable(rb_cImage, "@@named_colors", m_named_colors());
2967
+ rb_define_singleton_method(rb_cImage, "new", image_s_new, -1);
2968
+ rb_define_singleton_method(rb_cImage, "from_data", image_s_from_data, -1);
2969
+ rb_define_method(rb_cImage, "file", image_file, -1);
2970
+ rb_define_method(rb_cImage, "data", image_data, -1);
2971
+ rb_define_method(rb_cImage, "clone", image_clone, 0);
2972
+ rb_define_method(rb_cImage, "to_palette", image_to_palette, -1);
2973
+
2974
+ // Init
2975
+ gdFontCacheSetup();
2976
+ }