rays 0.1.11 → 0.1.16

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 (168) hide show
  1. checksums.yaml +5 -5
  2. data/.doc/ext/rays/bitmap.cpp +22 -76
  3. data/.doc/ext/rays/bounds.cpp +95 -125
  4. data/.doc/ext/rays/camera.cpp +88 -0
  5. data/.doc/ext/rays/color.cpp +223 -45
  6. data/.doc/ext/rays/color_space.cpp +146 -46
  7. data/.doc/ext/rays/defs.cpp +183 -0
  8. data/.doc/ext/rays/font.cpp +69 -21
  9. data/.doc/ext/rays/image.cpp +26 -37
  10. data/.doc/ext/rays/matrix.cpp +186 -29
  11. data/.doc/ext/rays/native.cpp +14 -8
  12. data/.doc/ext/rays/noise.cpp +53 -0
  13. data/.doc/ext/rays/painter.cpp +187 -292
  14. data/.doc/ext/rays/point.cpp +96 -77
  15. data/.doc/ext/rays/polygon.cpp +313 -0
  16. data/.doc/ext/rays/polygon_line.cpp +96 -0
  17. data/.doc/ext/rays/polyline.cpp +167 -0
  18. data/.doc/ext/rays/rays.cpp +103 -12
  19. data/.doc/ext/rays/shader.cpp +83 -9
  20. data/LICENSE +21 -0
  21. data/README.md +1 -1
  22. data/Rakefile +24 -9
  23. data/VERSION +1 -1
  24. data/ext/rays/bitmap.cpp +22 -80
  25. data/ext/rays/bounds.cpp +100 -128
  26. data/ext/rays/camera.cpp +94 -0
  27. data/ext/rays/color.cpp +231 -51
  28. data/ext/rays/color_space.cpp +149 -47
  29. data/ext/rays/defs.cpp +183 -0
  30. data/ext/rays/defs.h +26 -2
  31. data/ext/rays/extconf.rb +2 -3
  32. data/ext/rays/font.cpp +74 -24
  33. data/ext/rays/image.cpp +28 -40
  34. data/ext/rays/matrix.cpp +198 -30
  35. data/ext/rays/native.cpp +14 -8
  36. data/ext/rays/noise.cpp +55 -0
  37. data/ext/rays/painter.cpp +203 -298
  38. data/ext/rays/point.cpp +105 -81
  39. data/ext/rays/polygon.cpp +329 -0
  40. data/ext/rays/polygon_line.cpp +99 -0
  41. data/ext/rays/polyline.cpp +176 -0
  42. data/ext/rays/rays.cpp +103 -13
  43. data/ext/rays/shader.cpp +84 -9
  44. data/include/rays.h +10 -2
  45. data/include/rays/bitmap.h +14 -26
  46. data/include/rays/bounds.h +21 -4
  47. data/include/rays/camera.h +49 -0
  48. data/include/rays/color.h +25 -14
  49. data/include/rays/color_space.h +15 -10
  50. data/include/rays/coord.h +114 -0
  51. data/include/rays/debug.h +22 -0
  52. data/include/rays/defs.h +36 -0
  53. data/include/rays/exception.h +6 -2
  54. data/include/rays/font.h +4 -4
  55. data/include/rays/image.h +12 -18
  56. data/include/rays/matrix.h +50 -24
  57. data/include/rays/noise.h +42 -0
  58. data/include/rays/opengl.h +2 -50
  59. data/include/rays/painter.h +89 -93
  60. data/include/rays/point.h +44 -51
  61. data/include/rays/polygon.h +198 -0
  62. data/include/rays/polyline.h +71 -0
  63. data/include/rays/rays.h +3 -0
  64. data/include/rays/ruby.h +7 -1
  65. data/include/rays/ruby/bounds.h +1 -1
  66. data/include/rays/ruby/camera.h +41 -0
  67. data/include/rays/ruby/color.h +1 -1
  68. data/include/rays/ruby/color_space.h +1 -1
  69. data/include/rays/ruby/font.h +1 -1
  70. data/include/rays/ruby/matrix.h +1 -1
  71. data/include/rays/ruby/point.h +1 -1
  72. data/include/rays/ruby/polygon.h +52 -0
  73. data/include/rays/ruby/polyline.h +41 -0
  74. data/include/rays/ruby/rays.h +8 -0
  75. data/include/rays/ruby/shader.h +1 -1
  76. data/include/rays/shader.h +36 -8
  77. data/lib/rays.rb +7 -2
  78. data/lib/rays/bitmap.rb +0 -15
  79. data/lib/rays/bounds.rb +17 -23
  80. data/lib/rays/camera.rb +21 -0
  81. data/lib/rays/color.rb +20 -47
  82. data/lib/rays/color_space.rb +13 -13
  83. data/lib/rays/image.rb +3 -7
  84. data/lib/rays/matrix.rb +28 -0
  85. data/lib/rays/module.rb +4 -19
  86. data/lib/rays/painter.rb +78 -93
  87. data/lib/rays/point.rb +13 -21
  88. data/lib/rays/polygon.rb +58 -0
  89. data/lib/rays/polygon_line.rb +36 -0
  90. data/lib/rays/polyline.rb +32 -0
  91. data/lib/rays/shader.rb +20 -1
  92. data/rays.gemspec +5 -7
  93. data/src/bitmap.h +36 -0
  94. data/src/bounds.cpp +74 -11
  95. data/src/color.cpp +58 -23
  96. data/src/color_space.cpp +52 -34
  97. data/src/color_space.h +22 -0
  98. data/src/coord.cpp +170 -0
  99. data/src/coord.h +35 -0
  100. data/src/font.cpp +118 -0
  101. data/src/font.h +64 -0
  102. data/src/frame_buffer.cpp +37 -71
  103. data/src/frame_buffer.h +4 -4
  104. data/src/image.cpp +172 -98
  105. data/src/image.h +25 -0
  106. data/src/ios/bitmap.h +21 -0
  107. data/src/ios/bitmap.mm +129 -110
  108. data/src/ios/camera.mm +236 -0
  109. data/src/ios/font.mm +50 -62
  110. data/src/ios/helper.h +2 -2
  111. data/src/ios/opengl.mm +19 -4
  112. data/src/ios/rays.mm +3 -0
  113. data/src/matrix.cpp +111 -26
  114. data/src/matrix.h +30 -0
  115. data/src/noise.cpp +74 -0
  116. data/src/opengl.cpp +9 -27
  117. data/src/opengl.h +37 -0
  118. data/src/osx/bitmap.h +21 -0
  119. data/src/osx/bitmap.mm +129 -110
  120. data/src/osx/camera.mm +236 -0
  121. data/src/osx/font.mm +49 -62
  122. data/src/osx/helper.h +2 -2
  123. data/src/osx/opengl.mm +19 -83
  124. data/src/osx/rays.mm +3 -0
  125. data/src/painter.cpp +845 -671
  126. data/src/painter.h +24 -0
  127. data/src/point.cpp +140 -119
  128. data/src/polygon.cpp +1266 -0
  129. data/src/polygon.h +32 -0
  130. data/src/polyline.cpp +160 -0
  131. data/src/polyline.h +69 -0
  132. data/src/render_buffer.cpp +11 -4
  133. data/src/render_buffer.h +2 -2
  134. data/src/shader.cpp +163 -106
  135. data/src/shader.h +38 -0
  136. data/src/shader_program.cpp +533 -0
  137. data/src/{program.h → shader_program.h} +28 -16
  138. data/src/shader_source.cpp +140 -0
  139. data/src/shader_source.h +52 -0
  140. data/src/texture.cpp +136 -160
  141. data/src/texture.h +65 -0
  142. data/src/win32/bitmap.cpp +62 -52
  143. data/src/win32/font.cpp +11 -13
  144. data/src/win32/font.h +24 -0
  145. data/src/win32/gdi.h +6 -6
  146. data/test/helper.rb +0 -3
  147. data/test/test_bitmap.rb +31 -7
  148. data/test/test_bounds.rb +36 -0
  149. data/test/test_color.rb +59 -19
  150. data/test/test_color_space.rb +95 -0
  151. data/test/test_font.rb +5 -0
  152. data/test/test_image.rb +24 -20
  153. data/test/test_matrix.rb +106 -0
  154. data/test/test_painter.rb +157 -51
  155. data/test/test_painter_shape.rb +102 -0
  156. data/test/test_point.rb +29 -0
  157. data/test/test_polygon.rb +234 -0
  158. data/test/test_polygon_line.rb +167 -0
  159. data/test/test_polyline.rb +171 -0
  160. data/test/test_shader.rb +9 -9
  161. metadata +102 -70
  162. data/.doc/ext/rays/texture.cpp +0 -138
  163. data/ext/rays/texture.cpp +0 -149
  164. data/include/rays/ruby/texture.h +0 -41
  165. data/include/rays/texture.h +0 -71
  166. data/lib/rays/texture.rb +0 -24
  167. data/src/program.cpp +0 -648
  168. data/test/test_texture.rb +0 -27
@@ -4,6 +4,7 @@
4
4
 
5
5
  #import <Foundation/Foundation.h>
6
6
  #include "rays/exception.h"
7
+ #include "../opengl.h"
7
8
 
8
9
 
9
10
  namespace Rays
@@ -27,6 +28,8 @@ namespace Rays
27
28
  rays_error(__FILE__, __LINE__, "Rays::init(): already initialized.");
28
29
 
29
30
  global::pool = [[NSAutoreleasePool alloc] init];
31
+
32
+ OpenGL_set_context(get_offscreen_context());
30
33
  }
31
34
 
32
35
  void
@@ -1,22 +1,28 @@
1
- #include "rays/painter.h"
1
+ #include "painter.h"
2
2
 
3
3
 
4
4
  #include <math.h>
5
- #include <list>
5
+ #include <assert.h>
6
+ #include <memory>
7
+ #include <vector>
6
8
  #include <algorithm>
7
- #include <boost/scoped_array.hpp>
9
+ #include <glm/gtc/matrix_transform.hpp>
8
10
  #include "rays/exception.h"
9
11
  #include "rays/point.h"
10
12
  #include "rays/bounds.h"
11
13
  #include "rays/color.h"
12
- #include "rays/matrix.h"
13
- #include "rays/font.h"
14
- #include "rays/bitmap.h"
15
- #include "rays/texture.h"
16
- #include "rays/image.h"
17
- #include "rays/shader.h"
14
+ #include "rays/debug.h"
15
+ #include "opengl.h"
16
+ #include "matrix.h"
17
+ #include "polygon.h"
18
+ #include "bitmap.h"
19
+ #include "texture.h"
20
+ #include "image.h"
21
+ #include "font.h"
18
22
  #include "frame_buffer.h"
19
- #include "program.h"
23
+ #include "shader.h"
24
+ #include "shader_program.h"
25
+ #include "shader_source.h"
20
26
 
21
27
 
22
28
  namespace Rays
@@ -35,152 +41,528 @@ namespace Rays
35
41
  };// ColorType
36
42
 
37
43
 
38
- static const float PI = M_PI;
44
+ struct State
45
+ {
39
46
 
40
- static const float PI_2 = PI * 2;
47
+ Color background, colors[2];
41
48
 
49
+ coord stroke_width;
42
50
 
43
- struct Attributes
44
- {
51
+ CapType stroke_cap;
45
52
 
46
- Bounds clip;
53
+ JoinType stroke_join;
47
54
 
48
- Color background, colors[2];
55
+ coord miter_limit;
56
+
57
+ uint nsegment;
58
+
59
+ Bounds clip;
49
60
 
50
61
  Font font;
51
62
 
63
+ Shader shader;
64
+
52
65
  void init ()
53
66
  {
54
- clip .reset(-1);
55
67
  background .reset(0, 0);
56
68
  colors[FILL] .reset(1, 1);
57
69
  colors[STROKE] .reset(1, 0);
70
+ stroke_width = 0;
71
+ stroke_cap = CAP_DEFAULT;
72
+ stroke_join = JOIN_DEFAULT;
73
+ miter_limit = JOIN_DEFAULT_MITER_LIMIT;
74
+ nsegment = 0;
75
+ clip .reset(-1);
58
76
  font = default_font();
77
+ shader = Shader();
78
+ }
79
+
80
+ bool has_color ()
81
+ {
82
+ return colors[FILL] || colors[STROKE];
59
83
  }
60
84
 
61
- };// Attributes
85
+ };// State
62
86
 
63
87
 
64
- struct Painter::Data
88
+ struct TextureInfo
65
89
  {
66
90
 
67
- Bounds viewport;
91
+ const Texture& texture;
68
92
 
69
- Attributes attrs;
93
+ Coord2 texcoord_min, texcoord_max;
70
94
 
71
- Program program;
95
+ TextureInfo (
96
+ const Texture& texture,
97
+ coord x_min, coord y_min,
98
+ coord x_max, coord y_max)
99
+ : texture(texture)
100
+ {
101
+ texcoord_min.reset(x_min, y_min);
102
+ texcoord_max.reset(x_max, y_max);
103
+ }
72
104
 
73
- std::list<Attributes> attrs_stack;
105
+ operator bool () const
106
+ {
107
+ return
108
+ texture &&
109
+ texcoord_min.x < texcoord_max.x &&
110
+ texcoord_min.x < texcoord_max.y;
111
+ }
74
112
 
75
- bool painting;
113
+ bool operator ! () const
114
+ {
115
+ return !operator bool();
116
+ }
76
117
 
77
- GLenum prev_matrix_mode;
118
+ };// TextureInfo
78
119
 
79
- GLuint current_texture;
80
120
 
81
- Image text_image;
121
+ struct OpenGLState
122
+ {
123
+
124
+ GLint viewport[4];
125
+
126
+ GLclampf color_clear[4];
127
+
128
+ GLboolean scissor_test;
129
+ GLint scissor_box[4];
130
+
131
+ GLboolean blend;
132
+ GLint blend_src_factor, blend_dst_factor;
133
+
134
+ GLint framebuffer_binding;
135
+
136
+ void push ()
137
+ {
138
+ glGetIntegerv(GL_VIEWPORT, viewport);
139
+
140
+ glGetFloatv(GL_COLOR_CLEAR_VALUE, color_clear);
141
+
142
+ glGetBooleanv(GL_SCISSOR_TEST, &scissor_test);
143
+ glGetIntegerv(GL_SCISSOR_BOX, scissor_box);
144
+
145
+ glGetBooleanv(GL_BLEND, &blend);
146
+ glGetIntegerv(GL_BLEND_SRC_ALPHA, &blend_src_factor);
147
+ glGetIntegerv(GL_BLEND_DST_ALPHA, &blend_dst_factor);
148
+
149
+ glGetIntegerv(GL_FRAMEBUFFER_BINDING, &framebuffer_binding);
150
+ }
151
+
152
+ void pop ()
153
+ {
154
+ glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
155
+
156
+ glClearColor(
157
+ color_clear[0], color_clear[1], color_clear[2], color_clear[3]);
158
+
159
+ enable(GL_SCISSOR_TEST, scissor_test);
160
+ glScissor(scissor_box[0], scissor_box[1], scissor_box[2], scissor_box[3]);
161
+
162
+ enable(GL_BLEND, blend);
163
+ glBlendFunc(blend_src_factor, blend_dst_factor);
164
+
165
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer_binding);
166
+ }
167
+
168
+ private:
169
+
170
+ void enable(GLenum type, GLboolean value)
171
+ {
172
+ if (value)
173
+ glEnable(type);
174
+ else
175
+ glDisable(type);
176
+ }
177
+
178
+ };// OpenGLState
179
+
180
+
181
+ class DefaultIndices
182
+ {
183
+
184
+ public:
185
+
186
+ void resize (size_t size)
187
+ {
188
+ indices.reserve(size);
189
+ while (indices.size() < size)
190
+ indices.emplace_back(indices.size());
191
+ }
192
+
193
+ void clear ()
194
+ {
195
+ decltype(indices)().swap(indices);
196
+ }
197
+
198
+ const uint* get () const
199
+ {
200
+ return &indices[0];
201
+ }
202
+
203
+ private:
204
+
205
+ std::vector<uint> indices;
206
+
207
+ };// DefaultIndices
208
+
209
+
210
+ template <typename COORD>
211
+ static GLenum get_gl_type ();
212
+
213
+ template <>
214
+ GLenum
215
+ get_gl_type<float> ()
216
+ {
217
+ return GL_FLOAT;
218
+ }
219
+
220
+ static const Shader&
221
+ get_default_shader_for_shape ()
222
+ {
223
+ static const Shader SHADER(
224
+ "varying vec4 " VARYING_COLOR ";"
225
+ "void main ()"
226
+ "{"
227
+ " gl_FragColor = v_Color;"
228
+ "}");
229
+ return SHADER;
230
+ }
231
+
232
+ static const Shader&
233
+ get_default_shader_for_color_texture ()
234
+ {
235
+ static const Shader SHADER(
236
+ "varying vec4 " VARYING_TEXCOORD ";"
237
+ "varying vec4 " VARYING_COLOR ";"
238
+ "vec4 sampleTexture(vec2);"
239
+ "void main ()"
240
+ "{"
241
+ " vec4 color = sampleTexture(" VARYING_TEXCOORD ".xy);"
242
+ " gl_FragColor = v_Color * color;"
243
+ "}");
244
+ return SHADER;
245
+ }
246
+
247
+ static const Shader&
248
+ get_default_shader_for_alpha_texture ()
249
+ {
250
+ static const Shader SHADER(
251
+ "varying vec4 " VARYING_TEXCOORD ";"
252
+ "varying vec4 " VARYING_COLOR ";"
253
+ "vec4 sampleTexture(vec2);"
254
+ "void main ()"
255
+ "{"
256
+ " vec4 color = sampleTexture(" VARYING_TEXCOORD ".xy);"
257
+ " gl_FragColor = vec4(v_Color.rgb, color.a);"
258
+ "}");
259
+ return SHADER;
260
+ }
261
+
262
+
263
+ struct Painter::Data
264
+ {
265
+
266
+ bool painting = false;
267
+
268
+ float pixel_density = 1;
269
+
270
+ Bounds viewport;
271
+
272
+ State state;
273
+
274
+ std::vector<State> state_stack;
275
+
276
+ Matrix position_matrix;
277
+
278
+ std::vector<Matrix> position_matrix_stack;
82
279
 
83
280
  FrameBuffer frame_buffer;
84
281
 
85
- float scale_factor;
282
+ Image text_image;
283
+
284
+ OpenGLState opengl_state;
86
285
 
87
- mutable Matrix matrix_tmp;
286
+ DefaultIndices default_indices;
88
287
 
89
288
  Data ()
90
- : painting(false), prev_matrix_mode(0), current_texture(0),
91
- text_image(1, 1, GRAY, true), scale_factor(1)
92
289
  {
93
- attrs.init();
290
+ state.init();
291
+ }
292
+
293
+ void set_pixel_density (float density)
294
+ {
295
+ if (density <= 0)
296
+ argument_error(__FILE__, __LINE__, "invalid pixel_density.");
297
+
298
+ this->pixel_density = density;
299
+ text_image = Image();
94
300
  }
95
301
 
96
302
  void update_clip ()
97
303
  {
98
- if (attrs.clip)
304
+ const Bounds& clip = state.clip;
305
+ if (clip)
99
306
  {
307
+ coord y = frame_buffer ? clip.y : viewport.h - (clip.y + clip.h);
100
308
  glEnable(GL_SCISSOR_TEST);
101
309
  glScissor(
102
- attrs.clip.x,
103
- viewport.height - attrs.clip.height - attrs.clip.y,
104
- attrs.clip.width,
105
- attrs.clip.height);
310
+ pixel_density * clip.x,
311
+ pixel_density * y,
312
+ pixel_density * clip.width,
313
+ pixel_density * clip.height);
106
314
  }
107
315
  else
108
316
  {
109
317
  glDisable(GL_SCISSOR_TEST);
110
318
  }
111
319
 
112
- check_error(__FILE__, __LINE__);
320
+ OpenGL_check_error(__FILE__, __LINE__);
113
321
  }
114
322
 
115
- bool use_color (ColorType type)
323
+ bool get_color (Color* color, ColorType type)
116
324
  {
117
- const Color& c = attrs.colors[type];
118
- if (c.alpha <= 0) return false;
325
+ const Color& c = state.colors[type];
326
+ if (!c) return false;
119
327
 
120
- glColor4f(c.red, c.green, c.blue, c.alpha);
328
+ *color = c;
121
329
  return true;
122
330
  }
123
331
 
124
- void draw_shape (
125
- GLenum mode,
126
- int nindices, const uint* indices,
127
- int vertex_size, const coord* vertices,
128
- const coord* tex_coords = NULL, const Texture* texture = NULL)
332
+ void draw_polygon (
333
+ GLenum mode, const Color& color,
334
+ const Coord3* points, size_t npoints,
335
+ const uint* indices = NULL, size_t nindices = 0,
336
+ const Coord3* texcoords = NULL,
337
+ const Shader& default_shader = get_default_shader_for_shape(),
338
+ const TextureInfo* texinfo = NULL)
129
339
  {
130
- if (nindices <= 0 || !indices || !vertices)
340
+ if (!points || npoints <= 0)
131
341
  argument_error(__FILE__, __LINE__);
132
342
 
133
343
  if (!painting)
134
344
  invalid_state_error(__FILE__, __LINE__, "'painting' should be true.");
135
345
 
136
- bool use_texture = texture && tex_coords;
346
+ if (!indices || nindices <= 0)
347
+ {
348
+ default_indices.resize(npoints);
349
+ indices = default_indices.get();
350
+ nindices = npoints;
351
+ }
137
352
 
138
- if (use_texture)
353
+ if (!texcoords)
354
+ texcoords = points;
355
+
356
+ const ShaderProgram* program = Shader_get_program(state.shader);
357
+ if (!program || !*program)
139
358
  {
359
+ program = Shader_get_program(default_shader);
360
+ if (!program || !*program) return;
361
+ }
362
+
363
+ ShaderProgram_activate(*program);
364
+ apply_builtin_uniforms(*program, texinfo);
365
+
366
+ GLint a_position = glGetAttribLocation(program->id(), ATTRIB_POSITION);
367
+ GLint a_texcoord = glGetAttribLocation(program->id(), ATTRIB_TEXCOORD);
368
+ GLint a_color = glGetAttribLocation(program->id(), ATTRIB_COLOR);
369
+ if (a_position < 0 || a_texcoord < 0 || a_color < 0)
370
+ opengl_error(__FILE__, __LINE__);
371
+
372
+ setup_vertices(
373
+ points, npoints, texcoords, color, a_position, a_texcoord, a_color);
374
+ //activate_texture(texture);
375
+
376
+ glDrawElements(mode, (GLsizei) nindices, GL_UNSIGNED_INT, indices);
377
+ OpenGL_check_error(__FILE__, __LINE__);
378
+
379
+ //deactivate_texture(texture);
380
+ cleanup_vertices(a_position, a_texcoord);
381
+
382
+ ShaderProgram_deactivate();
383
+ }
384
+
385
+ private:
386
+
387
+ void apply_builtin_uniforms (
388
+ const ShaderProgram& program, const TextureInfo* texinfo)
389
+ {
390
+ GLint pos_matrix_loc =
391
+ glGetUniformLocation(program.id(), UNIFORM_POSITION_MATRIX);
392
+ if (pos_matrix_loc >= 0)
393
+ {
394
+ glUniformMatrix4fv(
395
+ pos_matrix_loc, 1, GL_FALSE, position_matrix.array);
396
+ OpenGL_check_error(__FILE__, __LINE__);
397
+ }
398
+
399
+ GLint texcoord_matrix_loc =
400
+ glGetUniformLocation(program.id(), UNIFORM_TEXCOORD_MATRIX);
401
+ if (texcoord_matrix_loc >= 0)
402
+ {
403
+ static const Matrix TEXCOORD_MATRIX(1);
404
+ glUniformMatrix4fv(
405
+ texcoord_matrix_loc, 1, GL_FALSE, TEXCOORD_MATRIX.array);
406
+ OpenGL_check_error(__FILE__, __LINE__);
407
+ }
408
+
409
+ apply_texture_uniforms(program, texinfo);
410
+ }
411
+
412
+ void apply_texture_uniforms (
413
+ const ShaderProgram& program, const TextureInfo* texinfo)
414
+ {
415
+ if (!texinfo || !*texinfo) return;
416
+
417
+ const Texture& texture = texinfo->texture;
418
+
419
+ GLint texture_loc =
420
+ glGetUniformLocation(program.id(), UNIFORM_TEXTURE);
421
+ if (texture_loc >= 0)
422
+ {
423
+ glActiveTexture(GL_TEXTURE0);
424
+ glBindTexture(GL_TEXTURE_2D, texture.id());
425
+
426
+ glUniform1i(texture_loc, 0);
427
+ OpenGL_check_error(__FILE__, __LINE__);
428
+ }
429
+
430
+ GLint size_loc =
431
+ glGetUniformLocation(program.id(), UNIFORM_TEXTURE_SIZE);
432
+ if (size_loc >= 0)
433
+ {
434
+ glUniform2f(
435
+ size_loc, texture.reserved_width(), texture.reserved_height());
436
+ OpenGL_check_error(__FILE__, __LINE__);
437
+ }
438
+
439
+ GLint min_loc =
440
+ glGetUniformLocation(program.id(), UNIFORM_TEXCOORD_MIN);
441
+ if (min_loc >= 0)
442
+ {
443
+ glUniform2fv(min_loc, 1, texinfo->texcoord_min.array);
444
+ OpenGL_check_error(__FILE__, __LINE__);
445
+ }
446
+
447
+ GLint max_loc =
448
+ glGetUniformLocation(program.id(), UNIFORM_TEXCOORD_MAX);
449
+ if (max_loc >= 0)
450
+ {
451
+ glUniform2fv(max_loc, 1, texinfo->texcoord_max.array);
452
+ OpenGL_check_error(__FILE__, __LINE__);
453
+ }
454
+ }
455
+
456
+ void setup_vertices (
457
+ const Coord3* points, size_t npoints,
458
+ const Coord3* texcoords, const Color& color,
459
+ GLuint a_position, GLuint a_texcoord, GLuint a_color)
460
+ {
461
+ assert(points && npoints >= 0 && texcoords);
462
+
463
+ glEnableVertexAttribArray(a_position);
464
+ glVertexAttribPointer(
465
+ a_position, Coord3::SIZE, get_gl_type<coord>(),
466
+ GL_FALSE, sizeof(Coord3), points);
467
+ OpenGL_check_error(__FILE__, __LINE__);
468
+
469
+ glEnableVertexAttribArray(a_texcoord);
470
+ glVertexAttribPointer(
471
+ a_texcoord, Coord3::SIZE, get_gl_type<coord>(),
472
+ GL_FALSE, sizeof(Coord3), texcoords);
473
+ OpenGL_check_error(__FILE__, __LINE__);
474
+
475
+ glVertexAttrib4fv(a_color, color.array);
476
+ }
477
+
478
+ void cleanup_vertices (GLint a_position, GLint a_texcoord)
479
+ {
480
+ glDisableVertexAttribArray(a_position);
481
+ glDisableVertexAttribArray(a_texcoord);
482
+ OpenGL_check_error(__FILE__, __LINE__);
483
+ }
484
+
485
+ void activate_texture (const Texture* texture)
486
+ {
487
+ if (!texture)
488
+ {
489
+ glDisable(GL_TEXTURE_2D);
490
+ return;
491
+ }
492
+
140
493
  if (!*texture)
141
494
  argument_error(__FILE__, __LINE__, "invalid texture.");
142
495
 
143
496
  GLuint id = texture->id();
144
- if (id != current_texture)
145
- {
497
+ if (id != get_current_texture_id())
146
498
  glBindTexture(GL_TEXTURE_2D, id);
147
- current_texture = id;
148
- }
149
499
 
150
500
  glEnable(GL_TEXTURE_2D);
501
+ }
151
502
 
152
- glEnableClientState(GL_TEXTURE_COORD_ARRAY);
153
- glTexCoordPointer(2, GL_FLOAT, 0, tex_coords);
503
+ GLuint get_current_texture_id ()
504
+ {
505
+ GLint id = 0;
506
+ glGetIntegerv(GL_TEXTURE_BINDING_2D, &id);
507
+ return (GLuint) id;
154
508
  }
155
- else
509
+
510
+ void deactivate_texture (const Texture* texture)
156
511
  {
512
+ if (!texture) return;
513
+
157
514
  glDisable(GL_TEXTURE_2D);
158
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
159
515
  }
160
516
 
161
- glEnableClientState(GL_VERTEX_ARRAY);
162
- glVertexPointer(vertex_size, GL_FLOAT, 0, vertices);
517
+ };// Painter::Data
163
518
 
164
- glDrawElements(mode, nindices, GL_UNSIGNED_INT, indices);
165
519
 
166
- glDisableClientState(GL_VERTEX_ARRAY);
167
- if (use_texture)
168
- {
169
- glDisableClientState(GL_TEXTURE_COORD_ARRAY);
170
- glDisable(GL_TEXTURE_2D);
171
- }
520
+ static void
521
+ draw_polygon (
522
+ Painter* painter,
523
+ const GLenum* modes,
524
+ coord offset_x, coord offset_y,
525
+ bool nofill, bool nostroke,
526
+ const Coord3* points, size_t npoints,
527
+ const uint* indices = NULL, size_t nindices = 0,
528
+ const Coord3* texcoords = NULL,
529
+ const Shader& default_shader = get_default_shader_for_shape(),
530
+ const TextureInfo* texinfo = NULL)
531
+ {
532
+ assert(painter);
533
+
534
+ bool offset = offset_x != 0 || offset_y != 0;
535
+ if (offset)
536
+ {
537
+ painter->push_matrix();
538
+ painter->translate(offset_x, offset_y);
172
539
  }
173
540
 
174
- };// Painter::Data
541
+ Color color;
542
+ for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
543
+ {
544
+ if ((nofill && type == FILL) || (nostroke && type == STROKE))
545
+ continue;
546
+
547
+ if (!painter->self->get_color(&color, (ColorType) type))
548
+ continue;
549
+
550
+ painter->self->draw_polygon(
551
+ modes[type], color, points, npoints, indices, nindices, texcoords,
552
+ default_shader, texinfo);
553
+ }
175
554
 
555
+ if (offset)
556
+ painter->pop_matrix();
557
+ }
176
558
 
177
559
  void
178
- set_painter_scale_factor (Painter* painter, float factor)
560
+ Painter_draw_polygon (
561
+ Painter* painter, GLenum mode, const Color& color,
562
+ const Coord3* points, size_t npoints,
563
+ const uint* indices, size_t nindices)
179
564
  {
180
- if (!painter)
181
- argument_error(__FILE__, __LINE__, "invalid texture.");
182
-
183
- painter->self->scale_factor = factor;
565
+ painter->self->draw_polygon(mode, color, points, npoints, indices, nindices);
184
566
  }
185
567
 
186
568
 
@@ -193,53 +575,57 @@ namespace Rays
193
575
  }
194
576
 
195
577
  void
196
- Painter::canvas (coord x, coord y, coord width, coord height)
578
+ Painter::canvas (
579
+ coord x, coord y, coord width, coord height, float pixel_density)
197
580
  {
198
- canvas(Bounds(x, y, -100, width, height, 200));
581
+ canvas(Bounds(x, y, -100, width, height, 200), pixel_density);
199
582
  }
200
583
 
201
584
  void
202
- Painter::canvas (coord x, coord y, coord z, coord width, coord height, coord depth)
585
+ Painter::canvas (
586
+ coord x, coord y, coord z, coord width, coord height, coord depth,
587
+ float pixel_density)
203
588
  {
204
- canvas(Bounds(x, y, z, width, height, depth));
589
+ canvas(Bounds(x, y, z, width, height, depth), pixel_density);
205
590
  }
206
591
 
207
592
  void
208
- Painter::canvas (const Bounds& bounds)
593
+ Painter::canvas (const Bounds& viewport, float pixel_density)
209
594
  {
210
- if (!bounds)
595
+ if (!viewport)
211
596
  argument_error(__FILE__, __LINE__);
212
597
 
213
598
  if (self->painting)
214
- invalid_state_error(__FILE__, __LINE__, "self->painting should be false.");
599
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
215
600
 
216
- self->viewport = bounds;
601
+ self->viewport = viewport;
602
+ self->set_pixel_density(pixel_density);
217
603
  }
218
604
 
219
605
  void
220
- Painter::bind (const Texture& texture)
606
+ Painter::bind (const Image& image)
221
607
  {
222
- if (!texture)
223
- argument_error(__FILE__, __LINE__, "invalid texture.");
608
+ if (!image)
609
+ argument_error(__FILE__, __LINE__, "invalid image.");
224
610
 
225
611
  if (self->painting)
226
- invalid_state_error(__FILE__, __LINE__, "self->painting should be false.");
612
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
227
613
 
228
- FrameBuffer fb(texture);
614
+ FrameBuffer fb(Image_get_texture(image));
229
615
  if (!fb)
230
616
  rays_error(__FILE__, __LINE__, "invalid frame buffer.");
231
617
 
232
618
  unbind();
233
619
 
234
620
  self->frame_buffer = fb;
235
- canvas(0, 0, fb.width(), fb.height());
621
+ canvas(0, 0, image.width(), image.height(), image.pixel_density());
236
622
  }
237
623
 
238
624
  void
239
625
  Painter::unbind ()
240
626
  {
241
627
  if (self->painting)
242
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
628
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
243
629
 
244
630
  self->frame_buffer = FrameBuffer();
245
631
  }
@@ -250,104 +636,74 @@ namespace Rays
250
636
  return self->viewport;
251
637
  }
252
638
 
639
+ float
640
+ Painter::pixel_density () const
641
+ {
642
+ return self->pixel_density;
643
+ }
253
644
 
254
645
  void
255
646
  Painter::begin ()
256
647
  {
257
648
  if (self->painting)
258
- invalid_state_error(__FILE__, __LINE__, "self->painting should be false.");
649
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be false.");
259
650
 
260
- FrameBuffer& fb = self->frame_buffer;
261
- if (fb) bind_frame_buffer(fb.id());
651
+ self->opengl_state.push();
262
652
 
263
- push_attr();
264
- push_shader();
653
+ //glEnable(GL_CULL_FACE);
654
+ glEnable(GL_BLEND);
655
+ glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
656
+ OpenGL_check_error(__FILE__, __LINE__);
657
+
658
+ FrameBuffer& fb = self->frame_buffer;
659
+ if (fb) FrameBuffer_bind(fb.id());
265
660
 
266
661
  const Bounds& vp = self->viewport;
267
- float scale = self->scale_factor;
662
+ float density = self->pixel_density;
268
663
  glViewport(
269
- (int) vp.x, (int) vp.y,
270
- (int) vp.width * scale, (int) vp.height * scale);
664
+ (int) (vp.x * density), (int) (vp.y * density),
665
+ (int) (vp.width * density), (int) (vp.height * density));
666
+ OpenGL_check_error(__FILE__, __LINE__);
271
667
 
272
668
  coord x1 = vp.x, x2 = vp.x + vp.width;
273
669
  coord y1 = vp.y, y2 = vp.y + vp.height;
274
670
  coord z1 = vp.z, z2 = vp.z + vp.depth;
275
671
  if (z1 == 0 && z2 == 0) {z1 = -100; z2 = 200;}
276
- if (!fb) std::swap(y1, y2);
277
-
278
- glGetIntegerv(GL_MATRIX_MODE, (GLint*) &self->prev_matrix_mode);
279
-
280
- glMatrixMode(GL_PROJECTION);
281
- glPushMatrix();
282
- glLoadIdentity();
283
- glOrtho(x1, x2, y1, y2, z1, z2);
672
+ if (!fb) std::swap(y1, y2);
284
673
 
285
- glMatrixMode(GL_MODELVIEW);
286
- glPushMatrix();
287
- glLoadIdentity();
288
- glTranslatef(0.375f, 0.375f, 0);
674
+ self->position_matrix.reset(1);
675
+ self->position_matrix *= to_rays(glm::ortho(x1, x2, y1, y2));
676
+ //self->position_matrix.translate(0.375f, 0.375f);
289
677
 
290
- glMatrixMode(GL_TEXTURE);
291
- glPushMatrix();
292
- glLoadIdentity();
293
-
294
- #ifndef IOS
295
- glMatrixMode(GL_COLOR);
296
- glPushMatrix();
297
- glLoadIdentity();
298
- #endif
299
-
300
- glMatrixMode(GL_MODELVIEW);
301
-
302
- //glEnable(GL_CULL_FACE);
303
- glEnable(GL_BLEND);
304
- glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
305
-
306
- check_error(__FILE__, __LINE__);
678
+ self->update_clip();
307
679
 
308
680
  self->painting = true;
309
-
310
- no_clip();
311
681
  }
312
682
 
313
683
  void
314
684
  Painter::end ()
315
685
  {
316
686
  if (!self->painting)
317
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
318
-
319
- self->painting = false;
320
-
321
- glDisable(GL_BLEND);
322
- glDisable(GL_CULL_FACE);
323
-
324
- glMatrixMode(GL_PROJECTION);
325
- glPopMatrix();
326
-
327
- glMatrixMode(GL_MODELVIEW);
328
- glPopMatrix();
687
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
329
688
 
330
- glMatrixMode(GL_TEXTURE);
331
- glPopMatrix();
689
+ if (!self->state_stack.empty())
690
+ invalid_state_error(__FILE__, __LINE__, "state stack is not empty.");
332
691
 
333
- #ifndef IOS
334
- glMatrixMode(GL_COLOR);
335
- glPopMatrix();
336
- #endif
692
+ if (!self->position_matrix_stack.empty())
693
+ invalid_state_error(__FILE__, __LINE__, "position matrix stack is not empty.");
337
694
 
338
- glMatrixMode(self->prev_matrix_mode);
339
-
340
- pop_shader();
341
- pop_attr();
695
+ self->painting = false;
696
+ self->opengl_state.pop();
697
+ self->default_indices.clear();
342
698
 
343
- //glFinish();
699
+ glFinish();
344
700
 
345
701
  if (self->frame_buffer)
346
702
  {
347
- unbind_frame_buffer();
703
+ FrameBuffer_unbind();
348
704
 
349
705
  Texture& tex = self->frame_buffer.texture();
350
- if (tex) tex.set_dirty(true);
706
+ if (tex) tex.set_modified();
351
707
  }
352
708
  }
353
709
 
@@ -355,388 +711,243 @@ namespace Rays
355
711
  Painter::clear ()
356
712
  {
357
713
  if (!self->painting)
358
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
714
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
359
715
 
360
- const Color& c = self->attrs.background;
716
+ const Color& c = self->state.background;
361
717
  glClearColor(c.red, c.green, c.blue, c.alpha);
362
718
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
363
-
364
- check_error(__FILE__, __LINE__);
719
+ OpenGL_check_error(__FILE__, __LINE__);
365
720
  }
366
721
 
367
- void
368
- Painter::line (coord x1, coord y1, coord x2, coord y2)
722
+ static inline void
723
+ debug_draw_triangulation (
724
+ Painter* painter, const Polygon& polygon, const Color& color)
369
725
  {
370
- static const uint INDICES[] =
371
- {
372
- 0, 1
373
- };
726
+ #ifdef _DEBUG
727
+ assert(painter);
374
728
 
375
- Data* pself = self.get();
729
+ Color invert_color(
730
+ 1.f - color.red,
731
+ 1.f - color.green,
732
+ 1.f - color.blue);
376
733
 
377
- if (!pself->painting)
378
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
379
-
380
- if (!pself->use_color(STROKE))
381
- return;
382
-
383
- coord vertices[] =
734
+ Polygon::TrianglePointList triangles;
735
+ if (Polygon_triangulate(&triangles, polygon))
384
736
  {
385
- x1, y1,
386
- x2, y2
387
- };
388
-
389
- pself->draw_shape(GL_LINES, 2, INDICES, 2, vertices);
390
- }
391
-
392
- void
393
- Painter::line (const Point& p1, const Point& p2)
394
- {
395
- line(p1.x, p1.y, p2.x, p2.y);
737
+ for (size_t i = 0; i < triangles.size(); i += 3)
738
+ {
739
+ painter->self->draw_polygon(
740
+ GL_LINE_LOOP, invert_color, &triangles[i], 3);
741
+ }
742
+ }
743
+ #endif
396
744
  }
397
745
 
398
746
  void
399
- Painter::lines (const Coord2* points, size_t size)
747
+ Painter::polygon (const Polygon& polygon)
400
748
  {
401
- Data* pself = self.get();
402
-
403
- if (!pself->painting)
404
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
749
+ if (!self->painting)
750
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
405
751
 
406
- if (!pself->use_color(STROKE))
752
+ if (!self->state.has_color())
407
753
  return;
408
754
 
409
- boost::scoped_array<uint> indices(new uint[size]);
410
- for (size_t i = 0; i < size; ++i)
411
- indices[i] = (uint) i;
412
-
413
- pself->draw_shape(GL_LINES, (int) size, indices.get(), 2, (coord*) points);
414
- }
415
-
416
- void
417
- Painter::lines (const Coord3* points, size_t size)
418
- {
419
- Data* pself = self.get();
420
-
421
- if (!pself->painting)
422
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
423
-
424
- if (!pself->use_color(STROKE))
425
- return;
755
+ Color color;
426
756
 
427
- boost::scoped_array<uint> indices(new uint[size]);
428
- boost::scoped_array<Coord2> vertices(new Coord2[size]);
429
- for (size_t i = 0; i < size; ++i)
757
+ if (self->get_color(&color, FILL))
430
758
  {
431
- indices[i] = (uint) i;
432
- vertices[i].reset(points[i].x, points[i].y);
759
+ Polygon_fill(polygon, this, color);
760
+ debug_draw_triangulation(this, polygon, color);
433
761
  }
434
762
 
435
- pself->draw_shape(
436
- GL_LINES, (int) size, indices.get(), 2, (coord*) vertices.get());
763
+ if (self->get_color(&color, STROKE))
764
+ Polygon_stroke(polygon, this, color);
437
765
  }
438
766
 
439
767
  void
440
- Painter::polygon (const Coord2* points, size_t size)
768
+ Painter::line (coord x1, coord y1, coord x2, coord y2)
441
769
  {
442
- Data* pself = self.get();
443
-
444
- if (!pself->painting)
445
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
446
-
447
- GLenum modes[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
448
- boost::scoped_array<uint> indices;
449
-
450
- for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
451
- {
452
- if (!pself->use_color((ColorType) type)) continue;
453
-
454
- if (!indices.get())
455
- {
456
- indices.reset(new uint[size]);
457
- for (size_t i = 0; i < size; ++i)
458
- indices[i] = (uint) i;
459
- }
460
-
461
- pself->draw_shape(
462
- modes[type], (int) size, indices.get(), 2, (coord*) points);
463
- }
770
+ polygon(create_line(x1, y1, x2, y2));
464
771
  }
465
772
 
466
773
  void
467
- Painter::polygon (const Coord3* points, size_t size)
774
+ Painter::line (const Point& p1, const Point& p2)
468
775
  {
469
- Data* pself = self.get();
470
-
471
- if (!pself->painting)
472
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
473
-
474
- GLenum modes[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
475
- boost::scoped_array<uint> indices;
476
- boost::scoped_array<Coord2> vertices;
477
-
478
- for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
479
- {
480
- if (!pself->use_color((ColorType) type)) continue;
481
-
482
- if (!indices.get())
483
- {
484
- indices.reset(new uint[size]);
485
- for (size_t i = 0; i < size; ++i)
486
- indices[i] = (uint) i;
487
- }
776
+ polygon(create_line(p1, p2));
777
+ }
488
778
 
489
- if (!vertices.get())
490
- {
491
- vertices.reset(new Coord2[size]);
492
- for (size_t i = 0; i < size; ++i)
493
- vertices[i].reset(points[i].x, points[i].y);
494
- }
779
+ void
780
+ Painter::line (const Point* points, size_t size, bool loop)
781
+ {
782
+ polygon(create_line(points, size, loop));
783
+ }
495
784
 
496
- pself->draw_shape(
497
- modes[type], (int) size, indices.get(), 2, (coord*) vertices.get());
498
- }
785
+ void
786
+ Painter::line (const Polyline& polyline)
787
+ {
788
+ polygon(create_line(polyline));
499
789
  }
500
790
 
501
791
  void
502
792
  Painter::rect (coord x, coord y, coord width, coord height, coord round)
503
793
  {
504
- rect(x, y, width, height, round, round);
794
+ polygon(create_rect(x, y, width, height, round, nsegment()));
505
795
  }
506
796
 
507
797
  void
508
798
  Painter::rect (
509
799
  coord x, coord y, coord width, coord height,
510
- coord round_width, coord round_height)
800
+ coord round_left_top, coord round_right_top,
801
+ coord round_left_bottom, coord round_right_bottom)
511
802
  {
512
- static const GLenum MODES[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
513
- static const uint INDICES[] =
514
- {
515
- 0, 1, 2, 3
516
- };
517
-
518
- Data* pself = self.get();
519
-
520
- if (!pself->painting)
521
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
522
-
523
- if (width <= 0 || height <= 0) return;
524
-
525
- coord x2 = x + width - 1;
526
- coord y2 = y + height - 1;
527
-
528
- for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
529
- {
530
- if (!pself->use_color((ColorType) type)) continue;
531
-
532
- coord xx = x2 + 1 - type;
533
- coord yy = y2 + 1 - type;
534
- coord vertices[] =
535
- {
536
- x, y,
537
- x, yy,
538
- xx, yy,
539
- xx, y
540
- };
541
-
542
- pself->draw_shape(MODES[type], 4, INDICES, 2, vertices);
543
- }
803
+ polygon(create_rect(
804
+ x, y, width, height,
805
+ round_left_top, round_right_top,
806
+ round_left_bottom, round_right_bottom,
807
+ nsegment()));
544
808
  }
545
809
 
546
810
  void
547
811
  Painter::rect (const Bounds& bounds, coord round)
548
812
  {
549
- rect(
550
- bounds.x, bounds.y, bounds.width, bounds.height,
551
- round);
813
+ polygon(create_rect(bounds, round, nsegment()));
552
814
  }
553
815
 
554
816
  void
555
- Painter::rect (const Bounds& bounds, coord round_width, coord round_height)
817
+ Painter::rect (
818
+ const Bounds& bounds,
819
+ coord round_left_top, coord round_right_top,
820
+ coord round_left_bottom, coord round_right_bottom)
556
821
  {
557
- rect(
558
- bounds.x, bounds.y, bounds.width, bounds.height,
559
- round_width, round_height);
822
+ polygon(create_rect(
823
+ bounds,
824
+ round_left_top, round_right_top,
825
+ round_left_bottom, round_right_bottom,
826
+ nsegment()));
560
827
  }
561
828
 
562
- static void
563
- draw_ellipse (
564
- Painter* painter,
829
+ void
830
+ Painter::ellipse (
565
831
  coord x, coord y, coord width, coord height,
566
- float angle_from, float angle_to, coord radius_min,
567
- uint nsegment)
832
+ const Point& hole_size,
833
+ float angle_from, float angle_to)
568
834
  {
569
- if (!painter)
570
- argument_error(__FILE__, __LINE__);
571
-
572
- Painter::Data* pself = painter->self.get();
573
-
574
- if (!pself->painting)
575
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
576
-
577
- if (height == 0) height = width;
578
- if (nsegment <= 0) nsegment = Painter::ELLIPSE_NSEGMENT;
579
-
580
- coord radius_x = width / 2;
581
- coord radius_y = height / 2;
582
- coord radius_x_min = radius_x * radius_min;
583
- coord radius_y_min = radius_y * radius_min;
584
- float from = angle_from / 360.f;
585
- float to = angle_to / 360.f;
586
- bool hole = radius_min != 0;
587
- int nvertices = hole ? nsegment * 2 : nsegment;
588
- GLenum modes[] =
589
- {
590
- (GLenum) (hole ? GL_TRIANGLE_STRIP : GL_TRIANGLE_FAN),
591
- GL_LINE_LOOP
592
- };
593
- boost::scoped_array<uint> indices;
594
- boost::scoped_array<Coord2> vertices;
595
-
596
- x += radius_x;
597
- y += radius_y;
598
-
599
- for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
600
- {
601
- if (!pself->use_color((ColorType) type)) continue;
602
-
603
- if (!indices.get())
604
- {
605
- indices.reset(new uint[nvertices]);
606
- for (int i = 0; i < nvertices; ++i)
607
- indices[i] = i;
608
- }
609
-
610
- if (!vertices.get())
611
- vertices.reset(new Coord2[nvertices]);
612
-
613
- Coord2* vertex = vertices.get();
614
- assert(vertex);
615
-
616
- for (uint seg = 0; seg < nsegment; ++seg, ++vertex)
617
- {
618
- float pos = (float) seg / (float) nsegment;
619
- float radian = (from + (to - from) * pos) * PI_2;
620
- float xx = cos(radian);
621
- float yy = -sin(radian);
622
-
623
- if (hole)
624
- vertex->reset(x + xx * radius_x_min, y + yy * radius_y_min);
625
- vertex ->reset(x + xx * radius_x, y + yy * radius_y);
626
- }
835
+ polygon(create_ellipse(
836
+ x, y, width, height, hole_size, angle_from, angle_to, nsegment()));
837
+ }
627
838
 
628
- pself->draw_shape(modes[type], nvertices, indices.get(), 2, (coord*) vertices.get());
629
- }
839
+ void
840
+ Painter::ellipse (
841
+ const Bounds& bounds,
842
+ const Point& hole_size,
843
+ float angle_from, float angle_to)
844
+ {
845
+ polygon(create_ellipse(
846
+ bounds, hole_size, angle_from, angle_to, nsegment()));
630
847
  }
631
848
 
632
849
  void
633
850
  Painter::ellipse (
634
- coord x, coord y, coord width, coord height,
635
- coord radius_min, uint nsegment)
851
+ const Point& center, const Point& radius, const Point& hole_radius,
852
+ float angle_from, float angle_to)
636
853
  {
637
- draw_ellipse(this, x, y, width, height, 0, 360, radius_min, nsegment);
854
+ polygon(create_ellipse(
855
+ center, radius, hole_radius, angle_from, angle_to, nsegment()));
638
856
  }
639
857
 
640
858
  void
641
- Painter::ellipse (const Bounds& bounds, coord radius_min, uint nsegment)
859
+ Painter::curve (
860
+ coord x1, coord y1, coord x2, coord y2,
861
+ coord x3, coord y3, coord x4, coord y4,
862
+ bool loop)
642
863
  {
643
- ellipse(
644
- bounds.x, bounds.y, bounds.width, bounds.height, radius_min, nsegment);
864
+ polygon(create_curve(x1, y1, x2, y2, x3, y3, x4, y4, loop));
645
865
  }
646
866
 
647
867
  void
648
- Painter::ellipse (
649
- const Point& center, coord radius, coord radius_min, uint nsegment)
868
+ Painter::curve (
869
+ const Point& p1, const Point& p2, const Point& p3, const Point& p4,
870
+ bool loop)
650
871
  {
651
- ellipse(
652
- center.x - radius, center.y - radius, radius * 2, radius * 2,
653
- radius_min, nsegment);
872
+ polygon(create_curve(p1, p2, p3, p4, loop));
654
873
  }
655
874
 
656
875
  void
657
- Painter::arc (
658
- coord x, coord y, coord width, coord height,
659
- float angle_from, float angle_to, coord radius_min, uint nsegment)
876
+ Painter::curve (const Point* points, size_t size, bool loop)
660
877
  {
661
- draw_ellipse(
662
- this, x, y, width, height, angle_from, angle_to, radius_min, nsegment);
878
+ polygon(create_curve(points, size, loop));
663
879
  }
664
880
 
665
881
  void
666
- Painter::arc (
667
- const Bounds& bounds,
668
- float angle_from, float angle_to, coord radius_min, uint nsegment)
882
+ Painter::bezier (
883
+ coord x1, coord y1, coord x2, coord y2,
884
+ coord x3, coord y3, coord x4, coord y4,
885
+ bool loop)
886
+ {
887
+ polygon(create_bezier(x1, y1, x2, y2, x3, y3, x4, y4, loop));
888
+ }
889
+
890
+ void
891
+ Painter::bezier (
892
+ const Point& p1, const Point& p2, const Point& p3, const Point& p4,
893
+ bool loop)
669
894
  {
670
- arc(
671
- bounds.x, bounds.y, bounds.width, bounds.height,
672
- angle_from, angle_to, radius_min, nsegment);
895
+ polygon(create_bezier(p1, p2, p3, p4, loop));
673
896
  }
674
897
 
675
898
  void
676
- Painter::arc (
677
- const Point& center, coord radius,
678
- float angle_from, float angle_to, coord radius_min, uint nsegment)
899
+ Painter::bezier (const Point* points, size_t size, bool loop)
679
900
  {
680
- arc(
681
- center.x, center.y, radius * 2, radius * 2,
682
- angle_from, angle_to, radius_min, nsegment);
901
+ polygon(create_bezier(points, size, loop));
683
902
  }
684
903
 
685
904
  static void
686
905
  draw_image (
687
- Painter* painter, const Texture& tex,
688
- float s_min, float t_min, float s_max, float t_max,
689
- coord x, coord y, coord width, coord height,
690
- bool nostroke = false)
906
+ Painter* painter, const Image& image,
907
+ coord src_x, coord src_y, coord src_w, coord src_h,
908
+ coord dst_x, coord dst_y, coord dst_w, coord dst_h,
909
+ bool nostroke = false, const Shader* shader = NULL)
691
910
  {
692
911
  static const GLenum MODES[] = {GL_TRIANGLE_FAN, GL_LINE_LOOP};
693
- static const uint INDICES[] =
694
- {
695
- 0, 1, 2, 3
696
- };
697
912
 
698
- assert(tex);
913
+ assert(painter && image);
699
914
 
700
- if (!painter)
701
- argument_error(__FILE__, __LINE__);
915
+ Painter::Data* self = painter->self.get();
702
916
 
703
- Painter::Data* pself = painter->self.get();
917
+ if (!self->painting)
918
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
704
919
 
705
- if (!pself->painting)
706
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
920
+ if (!self->state.has_color())
921
+ return;
707
922
 
708
- coord x2 = x + width - 1;
709
- coord y2 = y + height - 1;
710
- coord vertices[] =
711
- {
712
- x, y,
713
- x, y2,
714
- x2, y2,
715
- x2, y
716
- };
923
+ const Texture& texture = Image_get_texture(image);
924
+ if (!texture)
925
+ invalid_state_error(__FILE__, __LINE__);
717
926
 
718
- for (int type = COLOR_TYPE_BEGIN; type < COLOR_TYPE_END; ++type)
719
- {
720
- if (
721
- (nostroke && type == STROKE) ||
722
- !pself->use_color((ColorType) type))
723
- {
724
- continue;
725
- }
927
+ float density = image.pixel_density();
928
+ src_x *= density;
929
+ src_y *= density;
930
+ src_w *= density;
931
+ src_h *= density;
726
932
 
727
- if (type == FILL)
728
- {
729
- coord tex_coords[] = {
730
- s_min, t_min,
731
- s_min, t_max,
732
- s_max, t_max,
733
- s_max, t_min
734
- };
735
- pself->draw_shape(MODES[type], 4, INDICES, 2, vertices, tex_coords, &tex);
736
- }
737
- else
738
- pself->draw_shape(MODES[type], 4, INDICES, 2, vertices);
739
- }
933
+ Point points[4], texcoords[4];
934
+ points[0] .reset(dst_x, dst_y);
935
+ points[1] .reset(dst_x, dst_y + dst_h);
936
+ points[2] .reset(dst_x + dst_w, dst_y + dst_h);
937
+ points[3] .reset(dst_x + dst_w, dst_y);
938
+ texcoords[0].reset(src_x, src_y);
939
+ texcoords[1].reset(src_x, src_y + src_h);
940
+ texcoords[2].reset(src_x + src_w, src_y + src_h);
941
+ texcoords[3].reset(src_x + src_w, src_y);
942
+
943
+ TextureInfo texinfo(texture, src_x, src_y, src_x + src_w, src_y + src_h);
944
+
945
+ if (!shader)
946
+ shader = &get_default_shader_for_color_texture();
947
+
948
+ draw_polygon(
949
+ painter, MODES, 0, 0, false, nostroke, points, 4, NULL, 0, texcoords,
950
+ *shader, &texinfo);
740
951
  }
741
952
 
742
953
  void
@@ -745,14 +956,10 @@ namespace Rays
745
956
  if (!image_)
746
957
  argument_error(__FILE__, __LINE__);
747
958
 
748
- const Texture& tex = image_.texture();
749
- if (!tex)
750
- argument_error(__FILE__, __LINE__);
751
-
752
959
  draw_image(
753
- this, tex,
754
- 0, 0, tex.s_max(), tex.t_max(),
755
- x, y, tex.width(), tex.height());
960
+ this, image_,
961
+ 0, 0, image_.width(), image_.height(),
962
+ x, y, image_.width(), image_.height());
756
963
  }
757
964
 
758
965
  void
@@ -768,14 +975,10 @@ namespace Rays
768
975
  if (!image_)
769
976
  argument_error(__FILE__, __LINE__);
770
977
 
771
- const Texture& tex = image_.texture();
772
- if (!tex)
773
- argument_error(__FILE__, __LINE__);
774
-
775
978
  draw_image(
776
- this, tex,
777
- 0, 0, tex.s_max(), tex.t_max(),
778
- x, y, width, height);
979
+ this, image_,
980
+ 0, 0, image_.width(), image_.height(),
981
+ x, y, width, height);
779
982
  }
780
983
 
781
984
  void
@@ -788,191 +991,185 @@ namespace Rays
788
991
  void
789
992
  Painter::image (
790
993
  const Image& image_,
791
- coord src_x, coord src_y, coord src_width, coord src_height,
792
- coord dest_x, coord dest_y)
994
+ coord src_x, coord src_y, coord src_width, coord src_height,
995
+ coord dst_x, coord dst_y)
793
996
  {
794
997
  if (!image_)
795
998
  argument_error(__FILE__, __LINE__);
796
999
 
797
- const Texture& tex = image_.texture();
798
- if (!tex)
799
- argument_error(__FILE__, __LINE__);
800
-
801
- coord dest_width = tex.width(), dest_height = tex.height();
802
- float s = tex.s_max() / dest_width, t = tex.t_max() / dest_height;
803
1000
  draw_image(
804
- this, tex,
805
- src_x * s, src_y * t, src_width * s, src_height * t,
806
- dest_x, dest_y, dest_width, dest_height);
1001
+ this, image_,
1002
+ src_x, src_y, src_width, src_height,
1003
+ dst_x, dst_y, image_.width(), image_.height());
807
1004
  }
808
1005
 
809
1006
  void
810
1007
  Painter::image (
811
- const Image& image_, const Bounds& src_bounds, const Point& dest_position)
1008
+ const Image& image_, const Bounds& src_bounds, const Point& dst_position)
812
1009
  {
813
1010
  image(
814
1011
  image_,
815
1012
  src_bounds.x, src_bounds.y, src_bounds.width, src_bounds.height,
816
- dest_position.x, dest_position.y);
1013
+ dst_position.x, dst_position.y);
817
1014
  }
818
1015
 
819
1016
  void
820
1017
  Painter::image (
821
1018
  const Image& image_,
822
- coord src_x, coord src_y, coord src_width, coord src_height,
823
- coord dest_x, coord dest_y, coord dest_width, coord dest_height)
1019
+ coord src_x, coord src_y, coord src_width, coord src_height,
1020
+ coord dst_x, coord dst_y, coord dst_width, coord dst_height)
824
1021
  {
825
1022
  if (!image_)
826
1023
  argument_error(__FILE__, __LINE__);
827
1024
 
828
- const Texture& tex = image_.texture();
829
- if (!tex)
830
- argument_error(__FILE__, __LINE__);
831
-
832
- float s = tex.s_max() / tex.width();
833
- float t = tex.t_max() / tex.height();
834
1025
  draw_image(
835
- this, tex,
836
- src_x * s, src_y * t, src_width * s, src_height * t,
837
- dest_x, dest_y, dest_width, dest_height);
1026
+ this, image_,
1027
+ src_x, src_y, src_width, src_height,
1028
+ dst_x, dst_y, dst_width, dst_height);
838
1029
  }
839
1030
 
840
1031
  void
841
1032
  Painter::image (
842
- const Image& image_, const Bounds& src_bounds, const Bounds& dest_bounds)
1033
+ const Image& image_, const Bounds& src_bounds, const Bounds& dst_bounds)
843
1034
  {
844
1035
  image(
845
1036
  image_,
846
- src_bounds.x, src_bounds.y, src_bounds.width, src_bounds.height,
847
- dest_bounds.x, dest_bounds.y, dest_bounds.width, dest_bounds.height);
1037
+ src_bounds.x, src_bounds.y, src_bounds.width, src_bounds.height,
1038
+ dst_bounds.x, dst_bounds.y, dst_bounds.width, dst_bounds.height);
1039
+ }
1040
+
1041
+ static inline void
1042
+ debug_draw_text (
1043
+ Painter* painter, const Font& font,
1044
+ coord x, coord y, coord str_width, coord str_height)
1045
+ {
1046
+ #if 0
1047
+ save_image(painter->self->text_image, "/tmp/font.png");
1048
+
1049
+ painter->push_state();
1050
+ {
1051
+ coord asc, desc, lead;
1052
+ font.get_height(&asc, &desc, &lead);
1053
+ //printf("%f %f %f %f \n", str_height, asc, desc, lead);
1054
+
1055
+ painter->set_stroke(0.5, 0.5, 1);
1056
+ painter->no_fill();
1057
+ painter->rect(x - 1, y - 1, str_width + 2, str_height + 2);
1058
+
1059
+ coord yy = y;
1060
+ painter->set_stroke(1, 0.5, 0.5, 0.4);
1061
+ painter->rect(x, yy, str_width, asc);//str_height);
1062
+
1063
+ yy += asc;
1064
+ painter->set_stroke(1, 1, 0.5, 0.4);
1065
+ painter->rect(x, yy, str_width, desc);
1066
+
1067
+ yy += desc;
1068
+ painter->set_stroke(1, 0.5, 1, 0.4);
1069
+ painter->rect(x, yy, str_width, lead);
1070
+ }
1071
+ painter->pop_state();
1072
+ #endif
848
1073
  }
849
1074
 
850
1075
  static void
851
1076
  draw_text (
852
- Painter* painter, const char* str, coord str_width, coord str_height,
853
- coord x, coord y, coord width, coord height,
854
- const Font& font)
1077
+ Painter* painter, const Font& font,
1078
+ const char* str, coord x, coord y, coord width = 0, coord height = 0)
855
1079
  {
856
- assert(str && *str != '\0' && font);
1080
+ assert(painter && font && str && *str != '\0');
857
1081
 
858
- if (!painter)
859
- argument_error(__FILE__, __LINE__);
1082
+ Painter::Data* self = painter->self.get();
860
1083
 
861
- if (!painter->self->painting)
862
- invalid_state_error(__FILE__, __LINE__, "self->painting should be true.");
1084
+ if (!self->painting)
1085
+ invalid_state_error(__FILE__, __LINE__, "painting flag should be true.");
863
1086
 
864
- Painter::Data* self = painter->self.get();
865
- int tex_w = ceil(str_width);
866
- int tex_h = ceil(str_height);
1087
+ if (!self->state.has_color())
1088
+ return;
867
1089
 
1090
+ float density = self->pixel_density;
1091
+ coord str_w = Font_get_width(font, density, str);
1092
+ coord str_h = Font_get_height(font, density);
1093
+ int tex_w = ceil(str_w);
1094
+ int tex_h = ceil(str_h);
1095
+ const Texture& texture = Image_get_texture(self->text_image);
868
1096
  if (
869
- self->text_image.width() < tex_w ||
870
- self->text_image.height() < tex_h)
1097
+ texture.width() < tex_w ||
1098
+ texture.height() < tex_h ||
1099
+ self->text_image.pixel_density() != density)
871
1100
  {
872
- self->text_image = Image(
873
- std::max(self->text_image.width(), tex_w),
874
- std::max(self->text_image.height(), tex_h),
875
- self->text_image.color_space(),
876
- self->text_image.alpha_only());
1101
+ int bmp_w = std::max(texture.width(), tex_w);
1102
+ int bmp_h = std::max(texture.height(), tex_h);
1103
+ self->text_image = Image(Bitmap(bmp_w, bmp_h, ALPHA), density);
877
1104
  }
878
1105
 
879
1106
  if (!self->text_image)
880
1107
  invalid_state_error(__FILE__, __LINE__);
881
1108
 
882
- draw_string(&self->text_image.bitmap(), str, 0, 0, font);
1109
+ assert(self->text_image.pixel_density() == density);
883
1110
 
884
- const Texture& tex = self->text_image.texture();
885
- if (!tex)
886
- rays_error(__FILE__, __LINE__, "text_image's texture is invalid.");
1111
+ Bitmap_draw_string(
1112
+ &self->text_image.bitmap(), Font_get_raw(font, density), str, 0, 0);
887
1113
 
888
- #if 0//def DEBUG
889
- save_image(self->text_image, "/Users/snori/font.png");
890
-
891
- painter->push_attr();
892
- {
893
- coord asc, desc, lead;
894
- font.get_height(&asc, &desc, &lead);
895
- //printf("%f %f %f %f \n", str_height, asc, desc, lead);
896
-
897
- painter->set_stroke(0.5, 0.5, 1);
898
- painter->no_fill();
899
- painter->rect(x - 1, y - 1, str_width + 2, str_height + 2);
900
-
901
- coord yy = y;
902
- painter->set_stroke(1, 0.5, 0.5, 0.4);
903
- painter->rect(x, yy, str_width, asc);//str_height);
904
-
905
- yy += asc;
906
- painter->set_stroke(1, 1, 0.5, 0.4);
907
- painter->rect(x, yy, str_width, desc);
908
-
909
- yy += desc;
910
- painter->set_stroke(1, 0.5, 1, 0.4);
911
- painter->rect(x, yy, str_width, lead);
912
- }
913
- painter->pop_attr();
914
- #endif
1114
+ str_w /= density;
1115
+ str_h /= density;
1116
+ if (width == 0) width = str_w;
1117
+ if (height == 0) height = str_h;
915
1118
 
916
1119
  draw_image(
917
- painter, tex,
918
- 0, 0, tex.s(str_width - 1), tex.t(str_height - 1),
919
- x, y, width, height,
920
- true);
1120
+ painter, self->text_image,
1121
+ 0, 0, str_w, str_h,
1122
+ x, y, str_w, str_h,
1123
+ true, &get_default_shader_for_alpha_texture());
1124
+
1125
+ debug_draw_text(painter, font, x, y, str_w / density, str_h / density);
921
1126
  }
922
1127
 
923
1128
  void
924
- Painter::text (const char* str, coord x, coord y, const Font* font)
1129
+ Painter::text (const char* str, coord x, coord y)
925
1130
  {
926
1131
  if (!str)
927
1132
  argument_error(__FILE__, __LINE__);
928
1133
 
929
1134
  if (*str == '\0') return;
930
1135
 
931
- if (!font) font = &self->attrs.font;
932
- if (!*font)
933
- argument_error(__FILE__, __LINE__);
1136
+ const Font& font = self->state.font;
1137
+ if (!font)
1138
+ invalid_state_error(__FILE__, __LINE__);
934
1139
 
935
- coord w = font->get_width(str), h = font->get_height();
936
- w = ceil(w);
937
- h = ceil(h);
938
- draw_text(this, str, w, h, x, y, w, h, *font);
1140
+ draw_text(this, font, str, x, y);
939
1141
  }
940
1142
 
941
1143
  void
942
- Painter::text (const char* str, const Point& position, const Font* font)
1144
+ Painter::text (const char* str, const Point& position)
943
1145
  {
944
- text(str, position.x, position.y, font);
1146
+ text(str, position.x, position.y);
945
1147
  }
946
1148
 
947
1149
  void
948
- Painter::text (
949
- const char* str, coord x, coord y, coord width, coord height,
950
- const Font* font)
1150
+ Painter::text (const char* str, coord x, coord y, coord width, coord height)
951
1151
  {
952
1152
  if (!str)
953
1153
  argument_error(__FILE__, __LINE__);
954
1154
 
955
- if (*str == '\0') return;
1155
+ if (*str == '\0' || width == 0 || height == 0) return;
956
1156
 
957
- if (!font) font = &self->attrs.font;
958
- if (!*font)
959
- argument_error(__FILE__, __LINE__);
1157
+ const Font& font = self->state.font;
1158
+ if (!font)
1159
+ invalid_state_error(__FILE__, __LINE__);
960
1160
 
961
- coord w = font->get_width(str), h = font->get_height();
962
- w = ceil(w);
963
- h = ceil(h);
964
- draw_text(this, str, w, h, x, y, width, height, *font);
1161
+ draw_text(this, font, str, x, y, width, height);
965
1162
  }
966
1163
 
967
1164
  void
968
- Painter::text (const char* str, const Bounds& bounds, const Font* font)
1165
+ Painter::text (const char* str, const Bounds& bounds)
969
1166
  {
970
- text(str, bounds.x, bounds.y, bounds.width, bounds.height, font);
1167
+ text(str, bounds.x, bounds.y, bounds.width, bounds.height);
971
1168
  }
972
1169
 
973
-
974
1170
  void
975
- Painter::set_background (float red, float green, float blue, float alpha, bool clear)
1171
+ Painter::set_background (
1172
+ float red, float green, float blue, float alpha, bool clear)
976
1173
  {
977
1174
  set_background(Color(red, green, blue, alpha), clear);
978
1175
  }
@@ -980,7 +1177,7 @@ namespace Rays
980
1177
  void
981
1178
  Painter::set_background (const Color& color, bool clear)
982
1179
  {
983
- self->attrs.background = color;
1180
+ self->state.background = color;
984
1181
 
985
1182
  if (self->painting && clear) this->clear();
986
1183
  }
@@ -996,7 +1193,7 @@ namespace Rays
996
1193
  const Color&
997
1194
  Painter::background () const
998
1195
  {
999
- return self->attrs.background;
1196
+ return self->state.background;
1000
1197
  }
1001
1198
 
1002
1199
  void
@@ -1008,19 +1205,19 @@ namespace Rays
1008
1205
  void
1009
1206
  Painter::set_fill (const Color& color)
1010
1207
  {
1011
- self->attrs.colors[FILL] = color;
1208
+ self->state.colors[FILL] = color;
1012
1209
  }
1013
1210
 
1014
1211
  void
1015
1212
  Painter::no_fill ()
1016
1213
  {
1017
- self->attrs.colors[FILL].alpha = 0;
1214
+ self->state.colors[FILL].alpha = 0;
1018
1215
  }
1019
1216
 
1020
1217
  const Color&
1021
1218
  Painter::fill () const
1022
1219
  {
1023
- return self->attrs.colors[FILL];
1220
+ return self->state.colors[FILL];
1024
1221
  }
1025
1222
 
1026
1223
  void
@@ -1032,217 +1229,200 @@ namespace Rays
1032
1229
  void
1033
1230
  Painter::set_stroke (const Color& color)
1034
1231
  {
1035
- self->attrs.colors[STROKE] = color;
1232
+ self->state.colors[STROKE] = color;
1036
1233
  }
1037
1234
 
1038
1235
  void
1039
1236
  Painter::no_stroke ()
1040
1237
  {
1041
- self->attrs.colors[STROKE].alpha = 0;
1238
+ self->state.colors[STROKE].alpha = 0;
1042
1239
  }
1043
1240
 
1044
1241
  const Color&
1045
1242
  Painter::stroke () const
1046
1243
  {
1047
- return self->attrs.colors[STROKE];
1244
+ return self->state.colors[STROKE];
1048
1245
  }
1049
1246
 
1050
1247
  void
1051
- Painter::set_clip (coord x, coord y, coord width, coord height)
1248
+ Painter::set_stroke_width (coord width)
1052
1249
  {
1053
- set_clip(Bounds(x, y, width, height));
1250
+ self->state.stroke_width = width;
1054
1251
  }
1055
1252
 
1056
- void
1057
- Painter::set_clip (const Bounds& bounds)
1253
+ coord
1254
+ Painter::stroke_width () const
1058
1255
  {
1059
- self->attrs.clip = bounds;
1060
- self->update_clip();
1256
+ return self->state.stroke_width;
1061
1257
  }
1062
1258
 
1063
1259
  void
1064
- Painter::no_clip ()
1065
- {
1066
- set_clip(0, 0, -1, -1);
1067
- }
1068
-
1069
- const Bounds&
1070
- Painter::clip () const
1260
+ Painter::set_stroke_cap (CapType cap)
1071
1261
  {
1072
- return self->attrs.clip;
1262
+ self->state.stroke_cap = cap;
1073
1263
  }
1074
1264
 
1075
- void
1076
- Painter::set_font (const char* name, coord size)
1265
+ CapType
1266
+ Painter::stroke_cap () const
1077
1267
  {
1078
- set_font(Font(name, size));
1268
+ return self->state.stroke_cap;
1079
1269
  }
1080
1270
 
1081
1271
  void
1082
- Painter::set_font (const Font& font)
1272
+ Painter::set_stroke_join (JoinType join)
1083
1273
  {
1084
- self->attrs.font = font;
1274
+ self->state.stroke_join = join;
1085
1275
  }
1086
1276
 
1087
- const Font&
1088
- Painter::font () const
1277
+ JoinType
1278
+ Painter::stroke_join () const
1089
1279
  {
1090
- return self->attrs.font;
1280
+ return self->state.stroke_join;
1091
1281
  }
1092
1282
 
1093
1283
  void
1094
- Painter::push_attr ()
1284
+ Painter::set_miter_limit (coord limit)
1095
1285
  {
1096
- self->attrs_stack.push_back(self->attrs);
1286
+ self->state.miter_limit = limit;
1097
1287
  }
1098
1288
 
1099
- void
1100
- Painter::pop_attr ()
1289
+ coord
1290
+ Painter::miter_limit () const
1101
1291
  {
1102
- if (self->attrs_stack.empty())
1103
- rays_error(__FILE__, __LINE__, "attrs_stack is empty.");
1104
-
1105
- self->attrs = self->attrs_stack.back();
1106
- self->attrs_stack.pop_back();
1107
- self->update_clip();
1292
+ return self->state.miter_limit;
1108
1293
  }
1109
1294
 
1110
-
1111
1295
  void
1112
- Painter::attach (const Shader& shader)
1296
+ Painter::set_nsegment (int nsegment)
1113
1297
  {
1114
- self->program.attach(shader);
1298
+ if (nsegment < 0) nsegment = 0;
1299
+ self->state.nsegment = nsegment;
1115
1300
  }
1116
1301
 
1117
- void
1118
- Painter::detach (const Shader& shader)
1302
+ uint
1303
+ Painter::nsegment () const
1119
1304
  {
1120
- self->program.detach(shader);
1305
+ return self->state.nsegment;
1121
1306
  }
1122
1307
 
1123
1308
  void
1124
- Painter::set_uniform (const char* name, int arg1)
1309
+ Painter::set_clip (coord x, coord y, coord width, coord height)
1125
1310
  {
1126
- self->program.set_uniform(name, arg1);
1311
+ set_clip(Bounds(x, y, width, height));
1127
1312
  }
1128
1313
 
1129
1314
  void
1130
- Painter::set_uniform (const char* name, int arg1, int arg2)
1315
+ Painter::set_clip (const Bounds& bounds)
1131
1316
  {
1132
- self->program.set_uniform(name, arg1, arg2);
1317
+ self->state.clip = bounds;
1318
+ self->update_clip();
1133
1319
  }
1134
1320
 
1135
1321
  void
1136
- Painter::set_uniform (const char* name, int arg1, int arg2, int arg3)
1322
+ Painter::no_clip ()
1137
1323
  {
1138
- self->program.set_uniform(name, arg1, arg2, arg3);
1324
+ set_clip(0, 0, -1, -1);
1139
1325
  }
1140
1326
 
1141
- void
1142
- Painter::set_uniform (const char* name, int arg1, int arg2, int arg3, int arg4)
1327
+ const Bounds&
1328
+ Painter::clip () const
1143
1329
  {
1144
- self->program.set_uniform(name, arg1, arg2, arg3, arg4);
1330
+ return self->state.clip;
1145
1331
  }
1146
1332
 
1147
1333
  void
1148
- Painter::set_uniform (const char* name, const int* args, size_t size)
1334
+ Painter::set_font (const char* name, coord size)
1149
1335
  {
1150
- self->program.set_uniform(name, args, size);
1336
+ set_font(Font(name, size));
1151
1337
  }
1152
1338
 
1153
1339
  void
1154
- Painter::set_uniform (const char* name, float arg1)
1340
+ Painter::set_font (const Font& font)
1155
1341
  {
1156
- self->program.set_uniform(name, arg1);
1342
+ self->state.font = font;
1157
1343
  }
1158
1344
 
1159
- void
1160
- Painter::set_uniform (const char* name, float arg1, float arg2)
1345
+ const Font&
1346
+ Painter::font () const
1161
1347
  {
1162
- self->program.set_uniform(name, arg1, arg2);
1348
+ return self->state.font;
1163
1349
  }
1164
1350
 
1165
1351
  void
1166
- Painter::set_uniform (const char* name, float arg1, float arg2, float arg3)
1352
+ Painter::set_shader (const Shader& shader)
1167
1353
  {
1168
- self->program.set_uniform(name, arg1, arg2, arg3);
1354
+ self->state.shader = shader;
1169
1355
  }
1170
1356
 
1171
1357
  void
1172
- Painter::set_uniform (const char* name, float arg1, float arg2, float arg3, float arg4)
1358
+ Painter::no_shader ()
1173
1359
  {
1174
- self->program.set_uniform(name, arg1, arg2, arg3, arg4);
1360
+ self->state.shader = Shader();
1175
1361
  }
1176
1362
 
1177
- void
1178
- Painter::set_uniform (const char* name, const float* args, size_t size)
1363
+ const Shader&
1364
+ Painter::shader () const
1179
1365
  {
1180
- self->program.set_uniform(name, args, size);
1366
+ return self->state.shader;
1181
1367
  }
1182
1368
 
1183
1369
  void
1184
- Painter::push_shader ()
1370
+ Painter::push_state ()
1185
1371
  {
1186
- self->program.push();
1372
+ self->state_stack.emplace_back(self->state);
1187
1373
  }
1188
1374
 
1189
1375
  void
1190
- Painter::pop_shader ()
1376
+ Painter::pop_state ()
1191
1377
  {
1192
- self->program.pop();
1193
- }
1378
+ if (self->state_stack.empty())
1379
+ invalid_state_error(__FILE__, __LINE__, "state stack underflow.");
1194
1380
 
1381
+ self->state = self->state_stack.back();
1382
+ self->state_stack.pop_back();
1383
+ self->update_clip();
1384
+ }
1195
1385
 
1196
1386
  void
1197
1387
  Painter::translate (coord x, coord y, coord z)
1198
1388
  {
1199
- glTranslatef(x, y, z);
1389
+ self->position_matrix.translate(x, y, z);
1200
1390
  }
1201
1391
 
1202
1392
  void
1203
1393
  Painter::translate (const Point& value)
1204
1394
  {
1205
- translate(value.x, value.y, value.z);
1395
+ self->position_matrix.translate(value);
1206
1396
  }
1207
1397
 
1208
1398
  void
1209
1399
  Painter::scale (coord x, coord y, coord z)
1210
1400
  {
1211
- glScalef(x, y, z);
1401
+ self->position_matrix.scale(x, y, z);
1212
1402
  }
1213
1403
 
1214
1404
  void
1215
1405
  Painter::scale (const Point& value)
1216
1406
  {
1217
- scale(value.x, value.y, value.z);
1407
+ self->position_matrix.scale(value);
1218
1408
  }
1219
1409
 
1220
1410
  void
1221
- Painter::rotate (float angle, coord x, coord y, coord z)
1411
+ Painter::rotate (float degree, coord x, coord y, coord z)
1222
1412
  {
1223
- glRotatef(angle, x, y, z);
1413
+ self->position_matrix.rotate(degree, x, y, z);
1224
1414
  }
1225
1415
 
1226
1416
  void
1227
- Painter::rotate (float angle, const Point& axis)
1417
+ Painter::rotate (float angle, const Point& normalized_axis)
1228
1418
  {
1229
- rotate(angle, axis.x, axis.y, axis.z);
1419
+ self->position_matrix.rotate(angle, normalized_axis);
1230
1420
  }
1231
1421
 
1232
1422
  void
1233
1423
  Painter::set_matrix (float value)
1234
1424
  {
1235
- if (value == 1)
1236
- {
1237
- glLoadIdentity();
1238
- return;
1239
- }
1240
-
1241
- set_matrix(
1242
- value, 0, 0, 0,
1243
- 0, value, 0, 0,
1244
- 0, 0, value, 0,
1245
- 0, 0, 0, value);
1425
+ self->position_matrix.reset(value);
1246
1426
  }
1247
1427
 
1248
1428
  void
@@ -1252,52 +1432,46 @@ namespace Rays
1252
1432
  float c1, float c2, float c3, float c4,
1253
1433
  float d1, float d2, float d3, float d4)
1254
1434
  {
1255
- float array[] = {
1435
+ self->position_matrix.reset(
1256
1436
  a1, a2, a3, a4,
1257
1437
  b1, b2, b3, b4,
1258
1438
  c1, c2, c3, c4,
1259
- d1, d2, d3, d4
1260
- };
1261
- set_matrix(array);
1439
+ d1, d2, d3, d4);
1262
1440
  }
1263
1441
 
1264
1442
  void
1265
- Painter::set_matrix (const float* elements)
1443
+ Painter::set_matrix (const coord* elements, size_t size)
1266
1444
  {
1267
- if (!elements)
1268
- argument_error(__FILE__, __LINE__);
1269
-
1270
- glLoadMatrixf(elements);
1445
+ self->position_matrix.reset(elements, size);
1271
1446
  }
1272
1447
 
1273
1448
  void
1274
1449
  Painter::set_matrix (const Matrix& matrix)
1275
1450
  {
1276
- set_matrix(matrix.array);
1451
+ self->position_matrix = matrix;
1277
1452
  }
1278
1453
 
1279
1454
  const Matrix&
1280
1455
  Painter::matrix () const
1281
1456
  {
1282
- glGetFloatv(GL_MODELVIEW_MATRIX, self->matrix_tmp.array);
1283
- check_error(__FILE__, __LINE__);
1284
- return self->matrix_tmp;
1457
+ return self->position_matrix;
1285
1458
  }
1286
1459
 
1287
1460
  void
1288
1461
  Painter::push_matrix ()
1289
1462
  {
1290
- glPushMatrix();
1291
- check_error(__FILE__, __LINE__);
1463
+ self->position_matrix_stack.emplace_back(self->position_matrix);
1292
1464
  }
1293
1465
 
1294
1466
  void
1295
1467
  Painter::pop_matrix ()
1296
1468
  {
1297
- glPopMatrix();
1298
- check_error(__FILE__, __LINE__);
1299
- }
1469
+ if (self->position_matrix_stack.empty())
1470
+ invalid_state_error(__FILE__, __LINE__, "matrix stack underflow.");
1300
1471
 
1472
+ self->position_matrix = self->position_matrix_stack.back();
1473
+ self->position_matrix_stack.pop_back();
1474
+ }
1301
1475
 
1302
1476
  Painter::operator bool () const
1303
1477
  {