rays 0.1.1

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 (66) hide show
  1. data/ChangeLog +8 -0
  2. data/README +4 -0
  3. data/Rakefile +72 -0
  4. data/VERSION +1 -0
  5. data/ext/rays/bitmap.cpp +322 -0
  6. data/ext/rays/extconf.rb +61 -0
  7. data/ext/rays/font.cpp +125 -0
  8. data/ext/rays/image.cpp +166 -0
  9. data/ext/rays/native.cpp +24 -0
  10. data/ext/rays/painter.cpp +573 -0
  11. data/ext/rays/rays.cpp +61 -0
  12. data/ext/rays/rays.h +39 -0
  13. data/ext/rays/texture.cpp +130 -0
  14. data/include/rays.h +20 -0
  15. data/include/rays/bitmap.h +80 -0
  16. data/include/rays/colorspace.h +101 -0
  17. data/include/rays/defs.h +33 -0
  18. data/include/rays/font.h +49 -0
  19. data/include/rays/helpers.h +37 -0
  20. data/include/rays/image.h +68 -0
  21. data/include/rays/opengl.h +15 -0
  22. data/include/rays/painter.h +179 -0
  23. data/include/rays/rays.h +19 -0
  24. data/include/rays/ruby.h +15 -0
  25. data/include/rays/ruby/bitmap.h +39 -0
  26. data/include/rays/ruby/font.h +39 -0
  27. data/include/rays/ruby/image.h +39 -0
  28. data/include/rays/ruby/painter.h +39 -0
  29. data/include/rays/ruby/rays.h +21 -0
  30. data/include/rays/ruby/texture.h +39 -0
  31. data/include/rays/texture.h +56 -0
  32. data/include/rays/transform.h +35 -0
  33. data/lib/rays.rb +9 -0
  34. data/lib/rays/autoinit.rb +10 -0
  35. data/lib/rays/bitmap.rb +25 -0
  36. data/lib/rays/image.rb +15 -0
  37. data/lib/rays/module.rb +30 -0
  38. data/lib/rays/painter.rb +99 -0
  39. data/lib/rays/texture.rb +15 -0
  40. data/rays.gemspec +54 -0
  41. data/src/cocoa/bitmap.mm +286 -0
  42. data/src/cocoa/font.mm +193 -0
  43. data/src/cocoa/helpers.h +26 -0
  44. data/src/cocoa/helpers.mm +25 -0
  45. data/src/cocoa/rays.mm +40 -0
  46. data/src/colorspace.cpp +183 -0
  47. data/src/helpers.cpp +22 -0
  48. data/src/image.cpp +133 -0
  49. data/src/painter.cpp +769 -0
  50. data/src/texture.cpp +360 -0
  51. data/src/transform.cpp +88 -0
  52. data/src/win32/bitmap.cpp +212 -0
  53. data/src/win32/font.cpp +99 -0
  54. data/src/win32/gdi.cpp +771 -0
  55. data/src/win32/gdi.h +226 -0
  56. data/src/win32/rays.cpp +36 -0
  57. data/support.rb +58 -0
  58. data/task/ext.rake +41 -0
  59. data/task/gem.rake +33 -0
  60. data/task/git.rake +22 -0
  61. data/task/lib.rake +54 -0
  62. data/test/helpers.rb +15 -0
  63. data/test/test_painter.rb +11 -0
  64. data/test/test_rays.rb +19 -0
  65. data/test/test_texture.rb +11 -0
  66. metadata +153 -0
@@ -0,0 +1,26 @@
1
+ // -*- c++ -*-
2
+ #pragma once
3
+ #ifndef __RAYS_COCOA_HELPERS_H__
4
+ #define __RAYS_COCOA_HELPERS_H__
5
+
6
+
7
+ #include <boost/shared_ptr.hpp>
8
+ #include <CoreFoundation/CoreFoundation.h>
9
+
10
+
11
+ namespace Rays
12
+ {
13
+
14
+
15
+ void safe_cfrelease (CFTypeRef ref);
16
+
17
+
18
+ typedef boost::shared_ptr<const __CFString> CFString;
19
+
20
+ CFString cfstring (const char* str);
21
+
22
+
23
+ }// Rays
24
+
25
+
26
+ #endif//EOH
@@ -0,0 +1,25 @@
1
+ // -*- objc -*-
2
+ #include "helpers.h"
3
+
4
+
5
+ namespace Rays
6
+ {
7
+
8
+
9
+ void
10
+ safe_cfrelease (CFTypeRef ref)
11
+ {
12
+ if (ref) CFRelease(ref);
13
+ }
14
+
15
+
16
+ CFString
17
+ cfstring (const char* str)
18
+ {
19
+ CFStringRef ref = CFStringCreateWithCString(
20
+ kCFAllocatorDefault, str, kCFStringEncodingUTF8);
21
+ return CFString(ref, safe_cfrelease);
22
+ }
23
+
24
+
25
+ }// Rays
data/src/cocoa/rays.mm ADDED
@@ -0,0 +1,40 @@
1
+ // -*- objc -*-
2
+ #include "rays/rays.h"
3
+
4
+
5
+ #import <Cocoa/Cocoa.h>
6
+
7
+
8
+ namespace Rays
9
+ {
10
+
11
+
12
+ namespace global
13
+ {
14
+
15
+
16
+ static NSAutoreleasePool* pool = nil;
17
+
18
+
19
+ }// global
20
+
21
+
22
+ bool
23
+ init ()
24
+ {
25
+ if (global::pool) return false;
26
+ global::pool = [[NSAutoreleasePool alloc] init];
27
+ return true;
28
+ }
29
+
30
+ bool
31
+ fin ()
32
+ {
33
+ if (!global::pool) return false;
34
+ [global::pool release];
35
+ global::pool = nil;
36
+ return true;
37
+ }
38
+
39
+
40
+ }// Rays
@@ -0,0 +1,183 @@
1
+ #include "rays/colorspace.h"
2
+
3
+
4
+ #include <rays/helpers.h>
5
+
6
+
7
+ namespace Rays
8
+ {
9
+
10
+
11
+ enum
12
+ {
13
+
14
+ FIRST = GRAY_8, LAST = ABGR_float,
15
+
16
+ GRAY_FIRST = GRAY_8, GRAY_LAST = GRAY_float,
17
+
18
+ RGB_FIRST = RGB_888, RGB_LAST = ABGR_float,
19
+
20
+ FLOAT_SECOND = RGB_float, FLOAT_LAST = ABGR_float,
21
+
22
+ };
23
+
24
+
25
+ ColorSpace::ColorSpace ()
26
+ : type_(COLORSPACE_UNKNOWN), premult(false)
27
+ {
28
+ }
29
+
30
+ ColorSpace::ColorSpace (ColorSpaceType type, bool premultiplied)
31
+ : type_(type), premult(premultiplied)
32
+ {
33
+ }
34
+
35
+ ColorSpaceType
36
+ ColorSpace::type () const
37
+ {
38
+ return type_;
39
+ }
40
+
41
+ int
42
+ ColorSpace::bpc () const
43
+ {
44
+ static const int BPPS[] =
45
+ {
46
+ 0, // UNKNOWN
47
+ 8, 16, 24, 32, 32, // GRAY
48
+ 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, // RGB(A), BGR(A)
49
+ 32, 32, 32, 32, 32, 32, // RGB(A), BGR(A) float
50
+ };
51
+ if (type_ < 0 || COLORSPACE_LAST <= type_) return BPPS[UNKNOWN];
52
+ return BPPS[type_];
53
+ }
54
+
55
+ int
56
+ ColorSpace::Bpc () const
57
+ {
58
+ return bit2byte(bpc());
59
+ }
60
+
61
+ int
62
+ ColorSpace::bpp () const
63
+ {
64
+ static const int BPPS[] =
65
+ {
66
+ 0, // UNKNOWN
67
+ 8, 16, 24, 32, 32, // GRAY
68
+ 24, 32, 32, 32, 32, // RGB(A)
69
+ 24, 32, 32, 32, 32, // BGR(A)
70
+ 96, 128, 128, // RGB(A) float
71
+ 96, 128, 128, // BGR(A) float
72
+ };
73
+ if (type_ < 0 || COLORSPACE_LAST <= type_) return BPPS[UNKNOWN];
74
+ return BPPS[type_];
75
+ }
76
+
77
+ int
78
+ ColorSpace::Bpp () const
79
+ {
80
+ return bit2byte(bpp());
81
+ }
82
+
83
+ int
84
+ ColorSpace::alpha_pos () const
85
+ {
86
+ return is_alpha_last() ? 3 : 0;
87
+ }
88
+
89
+ bool
90
+ ColorSpace::is_gray () const
91
+ {
92
+ return GRAY_FIRST <= (int) type_ && (int) type_ <= GRAY_LAST;
93
+ }
94
+
95
+ bool
96
+ ColorSpace::is_rgb () const
97
+ {
98
+ return
99
+ (RGB_888 <= type_ && type_ <= XRGB_8888) ||
100
+ (RGB_float <= type_ && type_ <= ARGB_float);
101
+ }
102
+
103
+ bool
104
+ ColorSpace::is_bgr () const
105
+ {
106
+ return
107
+ (BGR_888 <= type_ && type_ <= XBGR_8888) ||
108
+ (BGR_float <= type_ && type_ <= ABGR_float);
109
+ }
110
+
111
+ bool
112
+ ColorSpace::is_float () const
113
+ {
114
+ return
115
+ type_ == GRAY_float ||
116
+ (FLOAT_SECOND <= (int) type_ && (int) type_ <= FLOAT_LAST);
117
+ }
118
+
119
+ bool
120
+ ColorSpace::has_alpha () const
121
+ {
122
+ return
123
+ type_ == RGBA_8888 || type_ == ARGB_8888 ||
124
+ type_ == BGRA_8888 || type_ == ABGR_8888 ||
125
+ type_ == RGBA_float || type_ == ARGB_float ||
126
+ type_ == BGRA_float || type_ == ABGR_float;
127
+ }
128
+
129
+ bool
130
+ ColorSpace::has_skip () const
131
+ {
132
+ return
133
+ type_ == RGBX_8888 || type_ == XRGB_8888 ||
134
+ type_ == BGRX_8888 || type_ == XBGR_8888;
135
+ }
136
+
137
+ bool
138
+ ColorSpace::is_alpha_first () const
139
+ {
140
+ return
141
+ type_ == ARGB_8888 || type_ == ABGR_8888 ||
142
+ type_ == ARGB_float || type_ == ABGR_float;
143
+ }
144
+
145
+ bool
146
+ ColorSpace::is_alpha_last () const
147
+ {
148
+ return
149
+ type_ == RGBA_8888 || type_ == BGRA_8888 ||
150
+ type_ == RGBA_float || type_ == BGRA_float;
151
+ }
152
+
153
+ bool
154
+ ColorSpace::is_skip_first () const
155
+ {
156
+ return type_ == XRGB_8888 || type_ == XBGR_8888;
157
+ }
158
+
159
+ bool
160
+ ColorSpace::is_skip_last () const
161
+ {
162
+ return type_ == RGBX_8888 || type_ == BGRX_8888;
163
+ }
164
+
165
+ bool
166
+ ColorSpace::is_premult () const
167
+ {
168
+ return premult;
169
+ }
170
+
171
+ ColorSpace::operator bool () const
172
+ {
173
+ return FIRST <= (int) type_ && (int) type_ <= LAST;
174
+ }
175
+
176
+ bool
177
+ ColorSpace::operator ! () const
178
+ {
179
+ return !operator bool();
180
+ }
181
+
182
+
183
+ }// Rays
data/src/helpers.cpp ADDED
@@ -0,0 +1,22 @@
1
+ #include "rays/helpers.h"
2
+
3
+
4
+ namespace Rays
5
+ {
6
+
7
+
8
+ int
9
+ bit2byte (int bits)
10
+ {
11
+ if ((bits % 8) != 0) return -1;
12
+ return bits / 8;
13
+ }
14
+
15
+ int
16
+ byte2bit (int bytes)
17
+ {
18
+ return bytes * 8;
19
+ }
20
+
21
+
22
+ }// Rays
data/src/image.cpp ADDED
@@ -0,0 +1,133 @@
1
+ #include "rays/image.h"
2
+
3
+
4
+ #include <rays/bitmap.h>
5
+ #include <rays/texture.h>
6
+
7
+
8
+ namespace Rays
9
+ {
10
+
11
+
12
+ struct Image::Data
13
+ {
14
+
15
+ Bitmap bitmap;
16
+
17
+ bool alphatex;
18
+
19
+ mutable Texture texture;
20
+
21
+ Data ()
22
+ : alphatex(false)
23
+ {
24
+ }
25
+
26
+ };// Image::Data
27
+
28
+
29
+ Image::Image ()
30
+ {
31
+ }
32
+
33
+ Image::Image (
34
+ int width, int height, const ColorSpace& cs,
35
+ bool alphatex)
36
+ {
37
+ self->bitmap = Bitmap(width, height, cs);
38
+ self->alphatex = alphatex;
39
+ }
40
+
41
+ Image::Image (const Bitmap& bitmap, bool alphatex)
42
+ {
43
+ self->bitmap = bitmap;
44
+ self->alphatex = alphatex;
45
+ }
46
+
47
+ Image::~Image ()
48
+ {
49
+ }
50
+
51
+ int
52
+ Image::width () const
53
+ {
54
+ return self->bitmap.width();
55
+ }
56
+
57
+ int
58
+ Image::height () const
59
+ {
60
+ return self->bitmap.height();
61
+ }
62
+
63
+ const ColorSpace&
64
+ Image::color_space () const
65
+ {
66
+ return self->bitmap.color_space();
67
+ }
68
+
69
+ bool
70
+ Image::alpha_texture () const
71
+ {
72
+ return self->alphatex;
73
+ }
74
+
75
+ Bitmap&
76
+ Image::bitmap ()
77
+ {
78
+ return self->bitmap;
79
+ }
80
+
81
+ const Bitmap&
82
+ Image::bitmap () const
83
+ {
84
+ return const_cast<Image*>(this)->bitmap();
85
+ }
86
+
87
+ Texture&
88
+ Image::texture ()
89
+ {
90
+ if (
91
+ self->bitmap &&
92
+ (!self->texture || self->bitmap.dirty()))
93
+ {
94
+ self->texture = Texture(self->bitmap, self->alphatex);
95
+ self->bitmap.set_dirty(false);
96
+ }
97
+
98
+ return self->texture;
99
+ }
100
+
101
+ const Texture&
102
+ Image::texture () const
103
+ {
104
+ return const_cast<Image*>(this)->texture();
105
+ }
106
+
107
+ Image::operator bool () const
108
+ {
109
+ return !!self->bitmap;
110
+ }
111
+
112
+ bool
113
+ Image::operator ! () const
114
+ {
115
+ return !operator bool();
116
+ }
117
+
118
+
119
+ bool
120
+ load_image (Image* image, const char* path, bool alphatex)
121
+ {
122
+ if (!image || !path) return false;
123
+
124
+ Bitmap bitmap;
125
+ if (!load_bitmap(&bitmap, path))
126
+ return false;
127
+
128
+ *image = Image(bitmap, alphatex);
129
+ return *image;
130
+ }
131
+
132
+
133
+ }// Rays
data/src/painter.cpp ADDED
@@ -0,0 +1,769 @@
1
+ #include "rays/painter.h"
2
+
3
+
4
+ #include <math.h>
5
+ #include <algorithm>
6
+ #include <rays/bitmap.h>
7
+ #include <rays/texture.h>
8
+ #include <rays/image.h>
9
+
10
+
11
+ namespace Rays
12
+ {
13
+
14
+
15
+ static const float PI = 3.141592653589793238462643383279f;
16
+
17
+ static const float PI_2 = PI * 2;
18
+
19
+
20
+ static void
21
+ gl_clear_error ()
22
+ {
23
+ glGetError();
24
+ }
25
+
26
+ static bool
27
+ gl_no_error ()
28
+ {
29
+ return glGetError() == GL_NO_ERROR;
30
+ }
31
+
32
+
33
+ struct Rect
34
+ {
35
+
36
+ coord x, y, width, height;
37
+
38
+ Rect ()
39
+ : x(0), y(0), width(0), height(0)
40
+ {
41
+ }
42
+
43
+ coord left () const
44
+ {
45
+ return x;
46
+ }
47
+
48
+ coord top () const
49
+ {
50
+ return y;
51
+ }
52
+
53
+ coord right () const
54
+ {
55
+ return x + width - 1;
56
+ }
57
+
58
+ coord bottom () const
59
+ {
60
+ return y + height - 1;
61
+ }
62
+
63
+ void set (coord x, coord y, coord width, coord height)
64
+ {
65
+ this->x = x;
66
+ this->y = y;
67
+ this->width = width;
68
+ this->height = height;
69
+ }
70
+
71
+ bool get (coord* x, coord* y, coord* width, coord* height)
72
+ {
73
+ if (!x && !y && !width && !height)
74
+ return false;
75
+
76
+ if (x) *x = this->x;
77
+ if (y) *y = this->y;
78
+ if (width) *width = this->width;
79
+ if (height) *height = this->height;
80
+ return true;
81
+ }
82
+
83
+ coord* array () const {return (coord*) this;}
84
+
85
+ operator bool () const
86
+ {
87
+ return width >= 0 && height >= 0;
88
+ }
89
+
90
+ bool operator ! () const
91
+ {
92
+ return !operator bool();
93
+ }
94
+
95
+ };// Rect
96
+
97
+
98
+ struct Color
99
+ {
100
+
101
+ float red, green, blue, alpha;
102
+
103
+ Color ()
104
+ : red(0), green(0), blue(0), alpha(0)
105
+ {
106
+ }
107
+
108
+ void set (float red, float green, float blue, float alpha)
109
+ {
110
+ this->red = red;
111
+ this->green = green;
112
+ this->blue = blue;
113
+ this->alpha = alpha;
114
+ }
115
+
116
+ bool get (float* red, float* green, float* blue, float* alpha) const
117
+ {
118
+ if (!red && !green && !blue && !alpha) return false;
119
+ if (red) *red = this->red;
120
+ if (green) *green = this->green;
121
+ if (blue) *blue = this->blue;
122
+ if (alpha) *alpha = this->alpha;
123
+ return true;
124
+ }
125
+
126
+ float* array () const {return (float*) this;}
127
+
128
+ };// Color
129
+
130
+
131
+ struct Painter::Data
132
+ {
133
+
134
+ Rect viewport, clip;
135
+
136
+ Color clear, colors[2];
137
+
138
+ bool painting, drawing, clipping;
139
+
140
+ Image textimage;
141
+
142
+ Data ()
143
+ : painting(false), drawing(false), clipping(false),
144
+ textimage(1, 1, GRAY, true)
145
+ {
146
+ }
147
+
148
+ bool use_color (size_t i) const
149
+ {
150
+ gl_clear_error();
151
+
152
+ const Color& c = colors[i];
153
+ if (c.alpha <= 0) return false;
154
+
155
+ glColor4fv(c.array());
156
+ return gl_no_error();
157
+ }
158
+
159
+ bool update_clip ()
160
+ {
161
+ gl_clear_error();
162
+
163
+ if (clip)
164
+ {
165
+ if (clipping) return true;
166
+ glEnable(GL_SCISSOR_TEST);
167
+ clipping = true;
168
+ }
169
+ else
170
+ {
171
+ if (!clipping) return true;
172
+ glDisable(GL_SCISSOR_TEST);
173
+ clipping = false;
174
+ }
175
+
176
+ return gl_no_error();
177
+ }
178
+
179
+ };// Painter::Data
180
+
181
+
182
+ enum ColorOrder
183
+ {
184
+
185
+ FILL = 0, STROKE
186
+
187
+ };// ColorOrder
188
+
189
+
190
+ Painter::Painter ()
191
+ {
192
+ }
193
+
194
+ Painter::~Painter ()
195
+ {
196
+ }
197
+
198
+ bool
199
+ Painter::canvas (coord x, coord y, coord width, coord height)
200
+ {
201
+ if (self->painting || width < 0 || height < 0)
202
+ return false;
203
+
204
+ self->viewport.set(x, y, width, height);
205
+
206
+ glViewport(
207
+ (int) self->viewport.x, (int) self->viewport.y,
208
+ (int) self->viewport.width, (int) self->viewport.height);
209
+
210
+ glMatrixMode(GL_PROJECTION);
211
+ glLoadIdentity();
212
+
213
+ glOrtho(
214
+ self->viewport.left(), self->viewport.right(),
215
+ self->viewport.top(), self->viewport.bottom(),
216
+ -100, 100);
217
+ glRotatef(180, 1, 0, 0);
218
+ glTranslatef(0, -self->viewport.height, 0);
219
+
220
+ glMatrixMode(GL_MODELVIEW);
221
+ glLoadIdentity();
222
+
223
+ return true;
224
+ }
225
+
226
+ bool
227
+ Painter::begin ()
228
+ {
229
+ if (self->painting) return false;
230
+
231
+ glEnable(GL_CULL_FACE);
232
+ glEnable(GL_BLEND);
233
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
234
+
235
+ self->painting = true;
236
+
237
+ no_clip();
238
+ clear();
239
+
240
+ return push();
241
+ }
242
+
243
+ bool
244
+ Painter::end ()
245
+ {
246
+ if (!self->painting) return false;
247
+
248
+ pop();
249
+
250
+ self->painting = false;
251
+
252
+ glDisable(GL_BLEND);
253
+ glDisable(GL_CULL_FACE);
254
+
255
+ return true;
256
+ }
257
+
258
+ bool
259
+ Painter::push ()
260
+ {
261
+ glPushMatrix();
262
+ return true;
263
+ }
264
+
265
+ bool
266
+ Painter::pop ()
267
+ {
268
+ glPopMatrix();
269
+ return true;
270
+ }
271
+
272
+
273
+ bool
274
+ Painter::line (coord x1, coord y1, coord x2, coord y2)
275
+ {
276
+ if (!self->painting || !self->use_color(STROKE))
277
+ return true;
278
+
279
+ if (!begin_shape(LINES)) return false;
280
+ bool ret =
281
+ vertex(x1, y1) &&
282
+ vertex(x2, y2);
283
+ if (!end_shape()) return false;
284
+
285
+ return ret;
286
+ }
287
+
288
+ bool
289
+ Painter::rect (coord x, coord y, coord width, coord height)
290
+ {
291
+ static const ShapeType TYPES[] = {QUADS, LINE_LOOP};
292
+
293
+ if (!self->painting) return false;
294
+
295
+ coord x2 = x + width;
296
+ coord y2 = y + height;
297
+
298
+ bool ret = true;
299
+ for (int i = 0; i < 2; ++i)
300
+ {
301
+ if (!self->use_color(i)) continue;
302
+
303
+ if (!begin_shape(TYPES[i])) return false;
304
+ ret &=
305
+ vertex(x, y) &&
306
+ vertex(x, y2) &&
307
+ vertex(x2, y2) &&
308
+ vertex(x2, y);
309
+ if (!end_shape()) return false;
310
+ }
311
+
312
+ return ret;
313
+ }
314
+
315
+ static bool
316
+ draw_ellipse (
317
+ Painter* painter,
318
+ coord x, coord y, coord width, coord height,
319
+ float angle_from, float angle_to, coord radius_min,
320
+ uint nsegment)
321
+ {
322
+ if (!painter || !painter->self->painting)
323
+ return false;
324
+
325
+ if (height == 0) height = width;
326
+
327
+ coord radius_x = width / 2;
328
+ coord radius_y = height / 2;
329
+ coord radius_x_min = radius_x * radius_min;
330
+ coord radius_y_min = radius_y * radius_min;
331
+ float from = angle_from / 360.f;
332
+ float to = angle_to / 360.f;
333
+ bool hole = radius_min != 0;
334
+ ShapeType types[] =
335
+ {
336
+ hole ? TRIANGLE_STRIP : TRIANGLE_FAN,
337
+ LINE_LOOP
338
+ };
339
+
340
+ x += radius_x;
341
+ y += radius_y;
342
+
343
+ bool ret = true;
344
+ for (int i = 0; i < 2; ++i)
345
+ {
346
+ if (!painter->self->use_color(i)) continue;
347
+
348
+ if (!painter->begin_shape(types[i])) return false;
349
+
350
+ if (!hole)
351
+ ret &= painter->vertex(x, y);
352
+
353
+ for (int seg = 0; seg <= (int) nsegment; ++seg)
354
+ {
355
+ float pos = (float) seg / (float) nsegment;
356
+ float radian = (from + (to - from) * pos) * PI_2;
357
+ float xx = cos(radian);
358
+ float yy = -sin(radian);
359
+ if (hole)
360
+ ret &= painter->vertex(x + xx * radius_x_min, y + yy * radius_y_min);
361
+ ret &= painter->vertex(x + xx * radius_x, y + yy * radius_y);
362
+ }
363
+
364
+ if (!painter->end_shape()) return false;
365
+ }
366
+
367
+ return ret;
368
+ }
369
+
370
+ static const uint ELLIPSE_NSEGMENT = 32;
371
+
372
+ bool
373
+ Painter::ellipse (
374
+ coord x, coord y, coord width, coord height, coord radius_min,
375
+ uint nsegment)
376
+ {
377
+ if (nsegment <= 0) nsegment = ELLIPSE_NSEGMENT;
378
+ return draw_ellipse(
379
+ this, x, y, width, height, 0, 360, radius_min, nsegment);
380
+ }
381
+
382
+ bool
383
+ Painter::arc (
384
+ coord x, coord y, coord width, coord height,
385
+ float angle_from, float angle_to, coord radius_min,
386
+ uint nsegment)
387
+ {
388
+ if (nsegment <= 0) nsegment = ELLIPSE_NSEGMENT;
389
+ return draw_ellipse(
390
+ this, x, y, width, height, angle_from, angle_to, radius_min, nsegment);
391
+ }
392
+
393
+ static bool
394
+ draw_image (
395
+ Painter* painter, const Texture& tex,
396
+ float s_min, float t_min, float s_max, float t_max,
397
+ coord x, coord y, coord width, coord height,
398
+ bool nostroke = false)
399
+ {
400
+ static const ShapeType TYPES[] = {QUADS, LINE_LOOP};
401
+
402
+ assert(tex);
403
+
404
+ if (!painter || !painter->self->painting)
405
+ return false;
406
+
407
+ coord x2 = x + width;
408
+ coord y2 = y + height;
409
+
410
+ glEnable(GL_TEXTURE_2D);
411
+ painter->texture(tex);
412
+
413
+ bool ret = true;
414
+ for (int i = 0; i < 2; ++i)
415
+ {
416
+ if (
417
+ (nostroke && TYPES[i] == LINE_LOOP) ||
418
+ !painter->self->use_color(i))
419
+ {
420
+ continue;
421
+ }
422
+
423
+ if (!painter->begin_shape(TYPES[i])) return false;
424
+ ret &=
425
+ painter->vertex(x, y, s_min, t_min) &&
426
+ painter->vertex(x, y2, s_min, t_max) &&
427
+ painter->vertex(x2, y2, s_max, t_max) &&
428
+ painter->vertex(x2, y, s_max, t_min);
429
+ if (!painter->end_shape()) return false;
430
+ }
431
+
432
+ painter->no_texture();
433
+ glDisable(GL_TEXTURE_2D);
434
+
435
+ return ret;
436
+ }
437
+
438
+ bool
439
+ Painter::image (const Image& image_, coord x, coord y)
440
+ {
441
+ if (!image_) return false;
442
+
443
+ const Texture& tex = image_.texture();
444
+ if (!tex) return false;
445
+
446
+ return draw_image(
447
+ this, tex,
448
+ 0, 0, tex.s_max(), tex.t_max(),
449
+ x, y, tex.width(), tex.height());
450
+ }
451
+
452
+ bool
453
+ Painter::image (
454
+ const Image& image_, coord x, coord y, coord width, coord height)
455
+ {
456
+ if (!image_) return false;
457
+
458
+ const Texture& tex = image_.texture();
459
+ if (!tex) return false;
460
+
461
+ return draw_image(
462
+ this, tex,
463
+ 0, 0, tex.s_max(), tex.t_max(),
464
+ x, y, width, height);
465
+ }
466
+
467
+ bool
468
+ Painter::image (
469
+ const Image& image_,
470
+ coord src_x, coord src_y, coord src_width, coord src_height,
471
+ coord dest_x, coord dest_y)
472
+ {
473
+ if (!image_) return false;
474
+
475
+ const Texture& tex = image_.texture();
476
+ if (!tex) return false;
477
+
478
+ coord dest_width = tex.width(), dest_height = tex.height();
479
+ float s = tex.s_max() / dest_width, t = tex.t_max() / dest_height;
480
+ return draw_image(
481
+ this, tex,
482
+ src_x * s, src_y * t, src_width * s, src_height * t,
483
+ dest_x, dest_y, dest_width, dest_height);
484
+ }
485
+
486
+ bool
487
+ Painter::image (
488
+ const Image& image_,
489
+ coord src_x, coord src_y, coord src_width, coord src_height,
490
+ coord dest_x, coord dest_y, coord dest_width, coord dest_height)
491
+ {
492
+ if (!image_) return false;
493
+
494
+ const Texture& tex = image_.texture();
495
+ if (!tex) return false;
496
+
497
+ float s = tex.s_max() / tex.width();
498
+ float t = tex.t_max() / tex.height();
499
+ return draw_image(
500
+ this, tex,
501
+ src_x * s, src_y * t, src_width * s, src_height * t,
502
+ dest_x, dest_y, dest_width, dest_height);
503
+ }
504
+
505
+ static bool
506
+ draw_text (
507
+ Painter* painter, const char* str, coord str_width, coord str_height,
508
+ coord x, coord y, coord width, coord height,
509
+ const Font& font)
510
+ {
511
+ assert(str && *str != '\0' && font);
512
+
513
+ if (!painter || !painter->self->painting)
514
+ return false;
515
+
516
+ Painter::Data* self = painter->self.get();
517
+
518
+ if (
519
+ self->textimage.width() < str_width ||
520
+ self->textimage.height() < str_height)
521
+ {
522
+ coord w = std::max((coord) self->textimage.width(), str_width);
523
+ coord h = std::max((coord) self->textimage.height(), str_height);
524
+ self->textimage = Image(
525
+ w + 1, h + 1, self->textimage.color_space(),
526
+ self->textimage.alpha_texture());
527
+ }
528
+
529
+ if (!self->textimage) return false;
530
+
531
+ if (!draw_string(&self->textimage.bitmap(), str, 0, 0, font))
532
+ return false;
533
+
534
+ const Texture& tex = self->textimage.texture();
535
+ if (!tex) return false;
536
+
537
+ float s = tex.s_max() / tex.width();
538
+ float t = tex.t_max() / tex.height();
539
+ return draw_image(
540
+ painter, tex,
541
+ 0, 0, str_width * s, str_height * t,
542
+ x, y, width, height,
543
+ true);
544
+ }
545
+
546
+ bool
547
+ Painter::text (const char* str, coord x, coord y, const Font& font)
548
+ {
549
+ if (!str || !font) return false;
550
+
551
+ if (*str == '\0') return true;
552
+
553
+ coord w = 0, h = 0;
554
+ if (!font.get_extent(&w, &h, str))
555
+ return false;
556
+
557
+ return draw_text(
558
+ this, str, w, h, x, y, w, h, font);
559
+ }
560
+
561
+ bool
562
+ Painter::text (
563
+ const char* str, coord x, coord y, coord width, coord height,
564
+ const Font& font)
565
+ {
566
+ if (!str || !font) return false;
567
+
568
+ if (*str == '\0') return true;
569
+
570
+ coord w = 0, h = 0;
571
+ if (!font.get_extent(&w, &h, str))
572
+ return false;
573
+
574
+ return draw_text(this, str, w, h, x, y, width, height, font);
575
+ }
576
+
577
+ bool
578
+ Painter::clear ()
579
+ {
580
+ if (!self->painting) return false;
581
+
582
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
583
+ return true;
584
+ }
585
+
586
+ bool
587
+ Painter::get_clear (float* red, float* green, float* blue, float* alpha)
588
+ {
589
+ return self->clear.get(red, green, blue, alpha);
590
+ }
591
+
592
+ bool
593
+ Painter::set_clear (float red, float green, float blue, float alpha)
594
+ {
595
+ self->clear.set(red, green, blue, alpha);
596
+ glClearColor(red, green, blue, alpha);
597
+ return true;
598
+ }
599
+
600
+ bool
601
+ Painter::no_clear ()
602
+ {
603
+ return set_clear(
604
+ self->clear.red, self->clear.green, self->clear.blue, 0);
605
+ }
606
+
607
+ bool
608
+ Painter::get_fill (float* red, float* green, float* blue, float* alpha)
609
+ {
610
+ return self->colors[FILL].get(red, green, blue, alpha);
611
+ }
612
+
613
+ bool
614
+ Painter::set_fill (float red, float green, float blue, float alpha)
615
+ {
616
+ self->colors[FILL].set(red, green, blue, alpha);
617
+ return true;
618
+ }
619
+
620
+ bool
621
+ Painter::no_fill ()
622
+ {
623
+ self->colors[FILL].alpha = 0;
624
+ return true;
625
+ }
626
+
627
+ bool
628
+ Painter::get_stroke (float* red, float* green, float* blue, float* alpha)
629
+ {
630
+ return self->colors[STROKE].get(red, green, blue, alpha);
631
+ }
632
+
633
+ bool
634
+ Painter::set_stroke (float red, float green, float blue, float alpha)
635
+ {
636
+ self->colors[STROKE].set(red, green, blue, alpha);
637
+ return true;
638
+ }
639
+
640
+ bool
641
+ Painter::no_stroke ()
642
+ {
643
+ self->colors[STROKE].alpha = 0;
644
+ return true;
645
+ }
646
+
647
+ bool
648
+ Painter::get_clip (coord* x, coord* y, coord* width, coord* height)
649
+ {
650
+ return self->clip.get(x, y, width, height);
651
+ }
652
+
653
+ bool
654
+ Painter::set_clip (coord x, coord y, coord width, coord height)
655
+ {
656
+ self->clip.set(x, y, width, height);
657
+ if (!self->update_clip())
658
+ return false;
659
+
660
+ if (self->clip)
661
+ {
662
+ glScissor(
663
+ self->clip.x, -self->clip.y, self->clip.width, self->clip.height);
664
+ }
665
+
666
+ return true;
667
+ }
668
+
669
+ bool
670
+ Painter::no_clip ()
671
+ {
672
+ return set_clip(0, 0, -1, -1);
673
+ }
674
+
675
+
676
+ bool
677
+ Painter::begin_shape (ShapeType type)
678
+ {
679
+ if (!self->painting || self->drawing)
680
+ return false;
681
+
682
+ glBegin(type);
683
+
684
+ self->drawing = true;
685
+ return true;
686
+ }
687
+
688
+ bool
689
+ Painter::end_shape ()
690
+ {
691
+ if (!self->painting || !self->drawing)
692
+ return false;
693
+
694
+ glEnd();
695
+
696
+ self->drawing = false;
697
+ return true;
698
+ }
699
+
700
+ bool
701
+ Painter::color (float red, float green, float blue, float alpha)
702
+ {
703
+ if (!self->drawing) return false;
704
+
705
+ glColor4f(red, green, blue, alpha);
706
+ return true;
707
+ }
708
+
709
+ bool
710
+ Painter::texture (const Texture& tex)
711
+ {
712
+ if (!self->drawing) return false;
713
+
714
+ glBindTexture(GL_TEXTURE_2D, tex ? tex.id() : 0);
715
+ return true;
716
+ }
717
+
718
+ bool
719
+ Painter::no_texture ()
720
+ {
721
+ if (!self->drawing) return false;
722
+
723
+ glBindTexture(GL_TEXTURE_2D, 0);
724
+ return true;
725
+ }
726
+
727
+ bool
728
+ Painter::vertex (coord x, coord y)
729
+ {
730
+ return vertex(x, y, 0);
731
+ }
732
+
733
+ bool
734
+ Painter::vertex (coord x, coord y, coord z)
735
+ {
736
+ if (!self->drawing) return false;
737
+
738
+ glVertex3f(x, y, z);
739
+ return true;
740
+ }
741
+
742
+ bool
743
+ Painter::vertex (coord x, coord y, coord texcoord_s, coord texcoord_t)
744
+ {
745
+ return vertex(x, y, 0, texcoord_s, texcoord_t);
746
+ }
747
+
748
+ bool
749
+ Painter::vertex (coord x, coord y, coord z, coord texcoord_s, coord texcoord_t)
750
+ {
751
+ if (!self->drawing) return false;
752
+
753
+ glTexCoord2f(texcoord_s, texcoord_t);
754
+ return vertex(x, y, z);
755
+ }
756
+
757
+ Painter::operator bool () const
758
+ {
759
+ return self->viewport;
760
+ }
761
+
762
+ bool
763
+ Painter::operator ! () const
764
+ {
765
+ return !operator bool();
766
+ }
767
+
768
+
769
+ }// Rays