rgd 0.4.1a-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+ }