rays 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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